indusagi-coding-agent 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/CHANGELOG.md +2249 -0
- package/README.md +546 -0
- package/dist/cli/args.js +282 -0
- package/dist/cli/config-selector.js +30 -0
- package/dist/cli/file-processor.js +78 -0
- package/dist/cli/list-models.js +91 -0
- package/dist/cli/session-picker.js +31 -0
- package/dist/cli.js +10 -0
- package/dist/config.js +158 -0
- package/dist/core/agent-session.js +2097 -0
- package/dist/core/auth-storage.js +278 -0
- package/dist/core/bash-executor.js +211 -0
- package/dist/core/compaction/branch-summarization.js +241 -0
- package/dist/core/compaction/compaction.js +606 -0
- package/dist/core/compaction/index.js +6 -0
- package/dist/core/compaction/utils.js +137 -0
- package/dist/core/diagnostics.js +1 -0
- package/dist/core/event-bus.js +24 -0
- package/dist/core/exec.js +70 -0
- package/dist/core/export-html/ansi-to-html.js +248 -0
- package/dist/core/export-html/index.js +221 -0
- package/dist/core/export-html/template.css +905 -0
- package/dist/core/export-html/template.html +54 -0
- package/dist/core/export-html/template.js +1549 -0
- package/dist/core/export-html/tool-renderer.js +56 -0
- package/dist/core/export-html/vendor/highlight.min.js +1213 -0
- package/dist/core/export-html/vendor/marked.min.js +6 -0
- package/dist/core/extensions/index.js +8 -0
- package/dist/core/extensions/loader.js +395 -0
- package/dist/core/extensions/runner.js +499 -0
- package/dist/core/extensions/types.js +31 -0
- package/dist/core/extensions/wrapper.js +101 -0
- package/dist/core/footer-data-provider.js +133 -0
- package/dist/core/index.js +8 -0
- package/dist/core/keybindings.js +140 -0
- package/dist/core/messages.js +122 -0
- package/dist/core/model-registry.js +454 -0
- package/dist/core/model-resolver.js +309 -0
- package/dist/core/package-manager.js +1142 -0
- package/dist/core/prompt-templates.js +250 -0
- package/dist/core/resource-loader.js +569 -0
- package/dist/core/sdk.js +225 -0
- package/dist/core/session-manager.js +1078 -0
- package/dist/core/settings-manager.js +430 -0
- package/dist/core/skills.js +339 -0
- package/dist/core/system-prompt.js +136 -0
- package/dist/core/timings.js +24 -0
- package/dist/core/tools/bash.js +226 -0
- package/dist/core/tools/edit-diff.js +242 -0
- package/dist/core/tools/edit.js +145 -0
- package/dist/core/tools/find.js +205 -0
- package/dist/core/tools/grep.js +238 -0
- package/dist/core/tools/index.js +60 -0
- package/dist/core/tools/ls.js +117 -0
- package/dist/core/tools/path-utils.js +52 -0
- package/dist/core/tools/read.js +165 -0
- package/dist/core/tools/truncate.js +204 -0
- package/dist/core/tools/write.js +77 -0
- package/dist/index.js +41 -0
- package/dist/main.js +565 -0
- package/dist/migrations.js +260 -0
- package/dist/modes/index.js +7 -0
- package/dist/modes/interactive/components/armin.js +328 -0
- package/dist/modes/interactive/components/assistant-message.js +86 -0
- package/dist/modes/interactive/components/bash-execution.js +155 -0
- package/dist/modes/interactive/components/bordered-loader.js +47 -0
- package/dist/modes/interactive/components/branch-summary-message.js +41 -0
- package/dist/modes/interactive/components/compaction-summary-message.js +42 -0
- package/dist/modes/interactive/components/config-selector.js +458 -0
- package/dist/modes/interactive/components/countdown-timer.js +27 -0
- package/dist/modes/interactive/components/custom-editor.js +61 -0
- package/dist/modes/interactive/components/custom-message.js +80 -0
- package/dist/modes/interactive/components/diff.js +132 -0
- package/dist/modes/interactive/components/dynamic-border.js +19 -0
- package/dist/modes/interactive/components/extension-editor.js +96 -0
- package/dist/modes/interactive/components/extension-input.js +54 -0
- package/dist/modes/interactive/components/extension-selector.js +70 -0
- package/dist/modes/interactive/components/footer.js +213 -0
- package/dist/modes/interactive/components/index.js +31 -0
- package/dist/modes/interactive/components/keybinding-hints.js +60 -0
- package/dist/modes/interactive/components/login-dialog.js +138 -0
- package/dist/modes/interactive/components/model-selector.js +253 -0
- package/dist/modes/interactive/components/oauth-selector.js +91 -0
- package/dist/modes/interactive/components/scoped-models-selector.js +262 -0
- package/dist/modes/interactive/components/session-selector-search.js +145 -0
- package/dist/modes/interactive/components/session-selector.js +698 -0
- package/dist/modes/interactive/components/settings-selector.js +250 -0
- package/dist/modes/interactive/components/show-images-selector.js +33 -0
- package/dist/modes/interactive/components/skill-invocation-message.js +44 -0
- package/dist/modes/interactive/components/theme-selector.js +43 -0
- package/dist/modes/interactive/components/thinking-selector.js +45 -0
- package/dist/modes/interactive/components/tool-execution.js +608 -0
- package/dist/modes/interactive/components/tree-selector.js +892 -0
- package/dist/modes/interactive/components/user-message-selector.js +109 -0
- package/dist/modes/interactive/components/user-message.js +15 -0
- package/dist/modes/interactive/components/visual-truncate.js +32 -0
- package/dist/modes/interactive/interactive-mode.js +3576 -0
- package/dist/modes/interactive/theme/dark.json +85 -0
- package/dist/modes/interactive/theme/light.json +84 -0
- package/dist/modes/interactive/theme/theme-schema.json +335 -0
- package/dist/modes/interactive/theme/theme.js +938 -0
- package/dist/modes/print-mode.js +96 -0
- package/dist/modes/rpc/rpc-client.js +390 -0
- package/dist/modes/rpc/rpc-mode.js +448 -0
- package/dist/modes/rpc/rpc-types.js +7 -0
- package/dist/utils/changelog.js +86 -0
- package/dist/utils/clipboard-image.js +116 -0
- package/dist/utils/clipboard.js +58 -0
- package/dist/utils/frontmatter.js +25 -0
- package/dist/utils/git.js +5 -0
- package/dist/utils/image-convert.js +34 -0
- package/dist/utils/image-resize.js +180 -0
- package/dist/utils/mime.js +25 -0
- package/dist/utils/photon.js +120 -0
- package/dist/utils/shell.js +164 -0
- package/dist/utils/sleep.js +16 -0
- package/dist/utils/tools-manager.js +186 -0
- package/docs/compaction.md +390 -0
- package/docs/custom-provider.md +538 -0
- package/docs/development.md +69 -0
- package/docs/extensions.md +1733 -0
- package/docs/images/doom-extension.png +0 -0
- package/docs/images/interactive-mode.png +0 -0
- package/docs/images/tree-view.png +0 -0
- package/docs/json.md +79 -0
- package/docs/keybindings.md +162 -0
- package/docs/models.md +193 -0
- package/docs/packages.md +163 -0
- package/docs/prompt-templates.md +67 -0
- package/docs/providers.md +147 -0
- package/docs/rpc.md +1048 -0
- package/docs/sdk.md +957 -0
- package/docs/session.md +412 -0
- package/docs/settings.md +216 -0
- package/docs/shell-aliases.md +13 -0
- package/docs/skills.md +226 -0
- package/docs/terminal-setup.md +65 -0
- package/docs/themes.md +295 -0
- package/docs/tree.md +219 -0
- package/docs/tui.md +887 -0
- package/docs/windows.md +17 -0
- package/examples/README.md +25 -0
- package/examples/extensions/README.md +192 -0
- package/examples/extensions/antigravity-image-gen.ts +414 -0
- package/examples/extensions/auto-commit-on-exit.ts +49 -0
- package/examples/extensions/bookmark.ts +50 -0
- package/examples/extensions/claude-rules.ts +86 -0
- package/examples/extensions/confirm-destructive.ts +59 -0
- package/examples/extensions/custom-compaction.ts +115 -0
- package/examples/extensions/custom-footer.ts +65 -0
- package/examples/extensions/custom-header.ts +73 -0
- package/examples/extensions/custom-provider-anthropic/index.ts +605 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
- package/examples/extensions/custom-provider-anthropic/package.json +19 -0
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +350 -0
- package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +83 -0
- package/examples/extensions/dirty-repo-guard.ts +56 -0
- package/examples/extensions/doom-overlay/README.md +46 -0
- package/examples/extensions/doom-overlay/doom/build/doom.js +21 -0
- package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
- package/examples/extensions/doom-overlay/doom/build.sh +152 -0
- package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -0
- package/examples/extensions/doom-overlay/doom-component.ts +133 -0
- package/examples/extensions/doom-overlay/doom-engine.ts +173 -0
- package/examples/extensions/doom-overlay/doom-keys.ts +105 -0
- package/examples/extensions/doom-overlay/index.ts +74 -0
- package/examples/extensions/doom-overlay/wad-finder.ts +51 -0
- package/examples/extensions/event-bus.ts +43 -0
- package/examples/extensions/file-trigger.ts +41 -0
- package/examples/extensions/git-checkpoint.ts +53 -0
- package/examples/extensions/handoff.ts +151 -0
- package/examples/extensions/hello.ts +25 -0
- package/examples/extensions/inline-bash.ts +94 -0
- package/examples/extensions/input-transform.ts +43 -0
- package/examples/extensions/interactive-shell.ts +196 -0
- package/examples/extensions/mac-system-theme.ts +47 -0
- package/examples/extensions/message-renderer.ts +60 -0
- package/examples/extensions/modal-editor.ts +86 -0
- package/examples/extensions/model-status.ts +31 -0
- package/examples/extensions/notify.ts +25 -0
- package/examples/extensions/overlay-qa-tests.ts +882 -0
- package/examples/extensions/overlay-test.ts +151 -0
- package/examples/extensions/permission-gate.ts +34 -0
- package/examples/extensions/pirate.ts +47 -0
- package/examples/extensions/plan-mode/README.md +65 -0
- package/examples/extensions/plan-mode/index.ts +341 -0
- package/examples/extensions/plan-mode/utils.ts +168 -0
- package/examples/extensions/preset.ts +399 -0
- package/examples/extensions/protected-paths.ts +30 -0
- package/examples/extensions/qna.ts +120 -0
- package/examples/extensions/question.ts +265 -0
- package/examples/extensions/questionnaire.ts +428 -0
- package/examples/extensions/rainbow-editor.ts +88 -0
- package/examples/extensions/sandbox/index.ts +318 -0
- package/examples/extensions/sandbox/package-lock.json +92 -0
- package/examples/extensions/sandbox/package.json +19 -0
- package/examples/extensions/send-user-message.ts +97 -0
- package/examples/extensions/session-name.ts +27 -0
- package/examples/extensions/shutdown-command.ts +63 -0
- package/examples/extensions/snake.ts +344 -0
- package/examples/extensions/space-invaders.ts +561 -0
- package/examples/extensions/ssh.ts +220 -0
- package/examples/extensions/status-line.ts +40 -0
- package/examples/extensions/subagent/README.md +172 -0
- package/examples/extensions/subagent/agents/planner.md +37 -0
- package/examples/extensions/subagent/agents/reviewer.md +35 -0
- package/examples/extensions/subagent/agents/scout.md +50 -0
- package/examples/extensions/subagent/agents/worker.md +24 -0
- package/examples/extensions/subagent/agents.ts +127 -0
- package/examples/extensions/subagent/index.ts +964 -0
- package/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
- package/examples/extensions/subagent/prompts/implement.md +10 -0
- package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
- package/examples/extensions/summarize.ts +196 -0
- package/examples/extensions/timed-confirm.ts +70 -0
- package/examples/extensions/todo.ts +300 -0
- package/examples/extensions/tool-override.ts +144 -0
- package/examples/extensions/tools.ts +147 -0
- package/examples/extensions/trigger-compact.ts +40 -0
- package/examples/extensions/truncated-tool.ts +193 -0
- package/examples/extensions/widget-placement.ts +17 -0
- package/examples/extensions/with-deps/index.ts +36 -0
- package/examples/extensions/with-deps/package-lock.json +31 -0
- package/examples/extensions/with-deps/package.json +22 -0
- package/examples/sdk/01-minimal.ts +22 -0
- package/examples/sdk/02-custom-model.ts +50 -0
- package/examples/sdk/03-custom-prompt.ts +55 -0
- package/examples/sdk/04-skills.ts +46 -0
- package/examples/sdk/05-tools.ts +56 -0
- package/examples/sdk/06-extensions.ts +88 -0
- package/examples/sdk/07-context-files.ts +40 -0
- package/examples/sdk/08-prompt-templates.ts +47 -0
- package/examples/sdk/09-api-keys-and-oauth.ts +48 -0
- package/examples/sdk/10-settings.ts +38 -0
- package/examples/sdk/11-sessions.ts +48 -0
- package/examples/sdk/12-full-control.ts +82 -0
- package/examples/sdk/13-codex-oauth.ts +37 -0
- package/examples/sdk/README.md +144 -0
- package/package.json +85 -0
package/dist/cli/args.js
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI argument parsing and help display
|
|
3
|
+
*/
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import { APP_NAME, CONFIG_DIR_NAME, ENV_AGENT_DIR } from "../config.js";
|
|
6
|
+
import { allTools } from "../core/tools/index.js";
|
|
7
|
+
const VALID_THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh"];
|
|
8
|
+
export function isValidThinkingLevel(level) {
|
|
9
|
+
return VALID_THINKING_LEVELS.includes(level);
|
|
10
|
+
}
|
|
11
|
+
export function parseArgs(args, extensionFlags) {
|
|
12
|
+
const result = {
|
|
13
|
+
messages: [],
|
|
14
|
+
fileArgs: [],
|
|
15
|
+
unknownFlags: new Map(),
|
|
16
|
+
};
|
|
17
|
+
for (let i = 0; i < args.length; i++) {
|
|
18
|
+
const arg = args[i];
|
|
19
|
+
if (arg === "--help" || arg === "-h") {
|
|
20
|
+
result.help = true;
|
|
21
|
+
}
|
|
22
|
+
else if (arg === "--version" || arg === "-v") {
|
|
23
|
+
result.version = true;
|
|
24
|
+
}
|
|
25
|
+
else if (arg === "--mode" && i + 1 < args.length) {
|
|
26
|
+
const mode = args[++i];
|
|
27
|
+
if (mode === "text" || mode === "json" || mode === "rpc") {
|
|
28
|
+
result.mode = mode;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
else if (arg === "--continue" || arg === "-c") {
|
|
32
|
+
result.continue = true;
|
|
33
|
+
}
|
|
34
|
+
else if (arg === "--resume" || arg === "-r") {
|
|
35
|
+
result.resume = true;
|
|
36
|
+
}
|
|
37
|
+
else if (arg === "--provider" && i + 1 < args.length) {
|
|
38
|
+
result.provider = args[++i];
|
|
39
|
+
}
|
|
40
|
+
else if (arg === "--model" && i + 1 < args.length) {
|
|
41
|
+
result.model = args[++i];
|
|
42
|
+
}
|
|
43
|
+
else if (arg === "--api-key" && i + 1 < args.length) {
|
|
44
|
+
result.apiKey = args[++i];
|
|
45
|
+
}
|
|
46
|
+
else if (arg === "--system-prompt" && i + 1 < args.length) {
|
|
47
|
+
result.systemPrompt = args[++i];
|
|
48
|
+
}
|
|
49
|
+
else if (arg === "--append-system-prompt" && i + 1 < args.length) {
|
|
50
|
+
result.appendSystemPrompt = args[++i];
|
|
51
|
+
}
|
|
52
|
+
else if (arg === "--no-session") {
|
|
53
|
+
result.noSession = true;
|
|
54
|
+
}
|
|
55
|
+
else if (arg === "--session" && i + 1 < args.length) {
|
|
56
|
+
result.session = args[++i];
|
|
57
|
+
}
|
|
58
|
+
else if (arg === "--session-dir" && i + 1 < args.length) {
|
|
59
|
+
result.sessionDir = args[++i];
|
|
60
|
+
}
|
|
61
|
+
else if (arg === "--models" && i + 1 < args.length) {
|
|
62
|
+
result.models = args[++i].split(",").map((s) => s.trim());
|
|
63
|
+
}
|
|
64
|
+
else if (arg === "--no-tools") {
|
|
65
|
+
result.noTools = true;
|
|
66
|
+
}
|
|
67
|
+
else if (arg === "--tools" && i + 1 < args.length) {
|
|
68
|
+
const toolNames = args[++i].split(",").map((s) => s.trim());
|
|
69
|
+
const validTools = [];
|
|
70
|
+
for (const name of toolNames) {
|
|
71
|
+
if (name in allTools) {
|
|
72
|
+
validTools.push(name);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
console.error(chalk.yellow(`Warning: Unknown tool "${name}". Valid tools: ${Object.keys(allTools).join(", ")}`));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
result.tools = validTools;
|
|
79
|
+
}
|
|
80
|
+
else if (arg === "--thinking" && i + 1 < args.length) {
|
|
81
|
+
const level = args[++i];
|
|
82
|
+
if (isValidThinkingLevel(level)) {
|
|
83
|
+
result.thinking = level;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
console.error(chalk.yellow(`Warning: Invalid thinking level "${level}". Valid values: ${VALID_THINKING_LEVELS.join(", ")}`));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
else if (arg === "--print" || arg === "-p") {
|
|
90
|
+
result.print = true;
|
|
91
|
+
}
|
|
92
|
+
else if (arg === "--export" && i + 1 < args.length) {
|
|
93
|
+
result.export = args[++i];
|
|
94
|
+
}
|
|
95
|
+
else if ((arg === "--extension" || arg === "-e") && i + 1 < args.length) {
|
|
96
|
+
result.extensions = result.extensions ?? [];
|
|
97
|
+
result.extensions.push(args[++i]);
|
|
98
|
+
}
|
|
99
|
+
else if (arg === "--no-extensions") {
|
|
100
|
+
result.noExtensions = true;
|
|
101
|
+
}
|
|
102
|
+
else if (arg === "--skill" && i + 1 < args.length) {
|
|
103
|
+
result.skills = result.skills ?? [];
|
|
104
|
+
result.skills.push(args[++i]);
|
|
105
|
+
}
|
|
106
|
+
else if (arg === "--prompt-template" && i + 1 < args.length) {
|
|
107
|
+
result.promptTemplates = result.promptTemplates ?? [];
|
|
108
|
+
result.promptTemplates.push(args[++i]);
|
|
109
|
+
}
|
|
110
|
+
else if (arg === "--theme" && i + 1 < args.length) {
|
|
111
|
+
result.themes = result.themes ?? [];
|
|
112
|
+
result.themes.push(args[++i]);
|
|
113
|
+
}
|
|
114
|
+
else if (arg === "--no-skills") {
|
|
115
|
+
result.noSkills = true;
|
|
116
|
+
}
|
|
117
|
+
else if (arg === "--no-prompt-templates") {
|
|
118
|
+
result.noPromptTemplates = true;
|
|
119
|
+
}
|
|
120
|
+
else if (arg === "--no-themes") {
|
|
121
|
+
result.noThemes = true;
|
|
122
|
+
}
|
|
123
|
+
else if (arg === "--list-models") {
|
|
124
|
+
// Check if next arg is a search pattern (not a flag or file arg)
|
|
125
|
+
if (i + 1 < args.length && !args[i + 1].startsWith("-") && !args[i + 1].startsWith("@")) {
|
|
126
|
+
result.listModels = args[++i];
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
result.listModels = true;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else if (arg === "--verbose") {
|
|
133
|
+
result.verbose = true;
|
|
134
|
+
}
|
|
135
|
+
else if (arg.startsWith("@")) {
|
|
136
|
+
result.fileArgs.push(arg.slice(1)); // Remove @ prefix
|
|
137
|
+
}
|
|
138
|
+
else if (arg.startsWith("--") && extensionFlags) {
|
|
139
|
+
// Check if it's an extension-registered flag
|
|
140
|
+
const flagName = arg.slice(2);
|
|
141
|
+
const extFlag = extensionFlags.get(flagName);
|
|
142
|
+
if (extFlag) {
|
|
143
|
+
if (extFlag.type === "boolean") {
|
|
144
|
+
result.unknownFlags.set(flagName, true);
|
|
145
|
+
}
|
|
146
|
+
else if (extFlag.type === "string" && i + 1 < args.length) {
|
|
147
|
+
result.unknownFlags.set(flagName, args[++i]);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// Unknown flags without extensionFlags are silently ignored (first pass)
|
|
151
|
+
}
|
|
152
|
+
else if (!arg.startsWith("-")) {
|
|
153
|
+
result.messages.push(arg);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return result;
|
|
157
|
+
}
|
|
158
|
+
export function printHelp() {
|
|
159
|
+
console.log(`${chalk.bold(APP_NAME)} - AI coding assistant with read, bash, edit, write tools
|
|
160
|
+
|
|
161
|
+
${chalk.bold("Usage:")}
|
|
162
|
+
${APP_NAME} [options] [@files...] [messages...]
|
|
163
|
+
|
|
164
|
+
${chalk.bold("Commands:")}
|
|
165
|
+
${APP_NAME} install <source> [-l] Install extension source and add to settings
|
|
166
|
+
${APP_NAME} remove <source> [-l] Remove extension source from settings
|
|
167
|
+
${APP_NAME} update [source] Update installed extensions (skips pinned sources)
|
|
168
|
+
${APP_NAME} list List installed extensions from settings
|
|
169
|
+
${APP_NAME} config Open TUI to enable/disable package resources
|
|
170
|
+
|
|
171
|
+
${chalk.bold("Options:")}
|
|
172
|
+
--provider <name> Provider name (default: google)
|
|
173
|
+
--model <id> Model ID (default: gemini-2.5-flash)
|
|
174
|
+
--api-key <key> API key (defaults to env vars)
|
|
175
|
+
--system-prompt <text> System prompt (default: coding assistant prompt)
|
|
176
|
+
--append-system-prompt <text> Append text or file contents to the system prompt
|
|
177
|
+
--mode <mode> Output mode: text (default), json, or rpc
|
|
178
|
+
--print, -p Non-interactive mode: process prompt and exit
|
|
179
|
+
--continue, -c Continue previous session
|
|
180
|
+
--resume, -r Select a session to resume
|
|
181
|
+
--session <path> Use specific session file
|
|
182
|
+
--session-dir <dir> Directory for session storage and lookup
|
|
183
|
+
--no-session Don't save session (ephemeral)
|
|
184
|
+
--models <patterns> Comma-separated model patterns for Ctrl+P cycling
|
|
185
|
+
Supports globs (anthropic/*, *sonnet*) and fuzzy matching
|
|
186
|
+
--no-tools Disable all built-in tools
|
|
187
|
+
--tools <tools> Comma-separated list of tools to enable (default: read,bash,edit,write)
|
|
188
|
+
Available: read, bash, edit, write, grep, find, ls
|
|
189
|
+
--thinking <level> Set thinking level: off, minimal, low, medium, high, xhigh
|
|
190
|
+
--extension, -e <path> Load an extension file (can be used multiple times)
|
|
191
|
+
--no-extensions Disable extension discovery (explicit -e paths still work)
|
|
192
|
+
--skill <path> Load a skill file or directory (can be used multiple times)
|
|
193
|
+
--no-skills Disable skills discovery and loading
|
|
194
|
+
--prompt-template <path> Load a prompt template file or directory (can be used multiple times)
|
|
195
|
+
--no-prompt-templates Disable prompt template discovery and loading
|
|
196
|
+
--theme <path> Load a theme file or directory (can be used multiple times)
|
|
197
|
+
--no-themes Disable theme discovery and loading
|
|
198
|
+
--export <file> Export session file to HTML and exit
|
|
199
|
+
--list-models [search] List available models (with optional fuzzy search)
|
|
200
|
+
--verbose Force verbose startup (overrides quietStartup setting)
|
|
201
|
+
--help, -h Show this help
|
|
202
|
+
--version, -v Show version number
|
|
203
|
+
|
|
204
|
+
Extensions can register additional flags (e.g., --plan from plan-mode extension).
|
|
205
|
+
|
|
206
|
+
${chalk.bold("Examples:")}
|
|
207
|
+
# Interactive mode
|
|
208
|
+
${APP_NAME}
|
|
209
|
+
|
|
210
|
+
# Interactive mode with initial prompt
|
|
211
|
+
${APP_NAME} "List all .ts files in src/"
|
|
212
|
+
|
|
213
|
+
# Include files in initial message
|
|
214
|
+
${APP_NAME} @prompt.md @image.png "What color is the sky?"
|
|
215
|
+
|
|
216
|
+
# Non-interactive mode (process and exit)
|
|
217
|
+
${APP_NAME} -p "List all .ts files in src/"
|
|
218
|
+
|
|
219
|
+
# Multiple messages (interactive)
|
|
220
|
+
${APP_NAME} "Read package.json" "What dependencies do we have?"
|
|
221
|
+
|
|
222
|
+
# Continue previous session
|
|
223
|
+
${APP_NAME} --continue "What did we discuss?"
|
|
224
|
+
|
|
225
|
+
# Use different model
|
|
226
|
+
${APP_NAME} --provider openai --model gpt-4o-mini "Help me refactor this code"
|
|
227
|
+
|
|
228
|
+
# Limit model cycling to specific models
|
|
229
|
+
${APP_NAME} --models claude-sonnet,claude-haiku,gpt-4o
|
|
230
|
+
|
|
231
|
+
# Limit to a specific provider with glob pattern
|
|
232
|
+
${APP_NAME} --models "github-copilot/*"
|
|
233
|
+
|
|
234
|
+
# Cycle models with fixed thinking levels
|
|
235
|
+
${APP_NAME} --models sonnet:high,haiku:low
|
|
236
|
+
|
|
237
|
+
# Start with a specific thinking level
|
|
238
|
+
${APP_NAME} --thinking high "Solve this complex problem"
|
|
239
|
+
|
|
240
|
+
# Read-only mode (no file modifications possible)
|
|
241
|
+
${APP_NAME} --tools read,grep,find,ls -p "Review the code in src/"
|
|
242
|
+
|
|
243
|
+
# Export a session file to HTML
|
|
244
|
+
${APP_NAME} --export ~/${CONFIG_DIR_NAME}/agent/sessions/--path--/session.jsonl
|
|
245
|
+
${APP_NAME} --export session.jsonl output.html
|
|
246
|
+
|
|
247
|
+
${chalk.bold("Environment Variables:")}
|
|
248
|
+
ANTHROPIC_AINDUSAGI_KEY - Anthropic Claude API key
|
|
249
|
+
ANTHROPIC_OAUTH_TOKEN - Anthropic OAuth token (alternative to API key)
|
|
250
|
+
OPENAI_AINDUSAGI_KEY - OpenAI GPT API key
|
|
251
|
+
AZURE_OPENAI_AINDUSAGI_KEY - Azure OpenAI API key
|
|
252
|
+
AZURE_OPENAI_BASE_URL - Azure OpenAI base URL (https://{resource}.openai.azure.com/openai/v1)
|
|
253
|
+
AZURE_OPENAI_RESOURCE_NAME - Azure OpenAI resource name (alternative to base URL)
|
|
254
|
+
AZURE_OPENAI_AINDUSAGI_VERSION - Azure OpenAI API version (default: v1)
|
|
255
|
+
AZURE_OPENAI_DEPLOYMENT_NAME_MAP - Azure OpenAI model=deployment map (comma-separated)
|
|
256
|
+
GEMINI_AINDUSAGI_KEY - Google Gemini API key
|
|
257
|
+
GROQ_AINDUSAGI_KEY - Groq API key
|
|
258
|
+
CEREBRAS_AINDUSAGI_KEY - Cerebras API key
|
|
259
|
+
XAI_AINDUSAGI_KEY - xAI Grok API key
|
|
260
|
+
OPENROUTER_AINDUSAGI_KEY - OpenRouter API key
|
|
261
|
+
AI_GATEWAY_AINDUSAGI_KEY - Vercel AI Gateway API key
|
|
262
|
+
ZAI_AINDUSAGI_KEY - ZAI API key
|
|
263
|
+
MISTRAL_AINDUSAGI_KEY - Mistral API key
|
|
264
|
+
MINIMAX_AINDUSAGI_KEY - MiniMax API key
|
|
265
|
+
AWS_PROFILE - AWS profile for Amazon Bedrock
|
|
266
|
+
AWS_ACCESS_KEY_ID - AWS access key for Amazon Bedrock
|
|
267
|
+
AWS_SECRET_ACCESS_KEY - AWS secret key for Amazon Bedrock
|
|
268
|
+
AWS_BEARER_TOKEN_BEDROCK - Bedrock API key (bearer token)
|
|
269
|
+
AWS_REGION - AWS region for Amazon Bedrock (e.g., us-east-1)
|
|
270
|
+
${ENV_AGENT_DIR.padEnd(32)} - Session storage directory (default: ~/${CONFIG_DIR_NAME}/agent)
|
|
271
|
+
INDUSAGI_SHARE_VIEWER_URL - Base URL for /share command (default: https://buildwithindusagi.ai/session/)
|
|
272
|
+
|
|
273
|
+
${chalk.bold("Available Tools (default: read, bash, edit, write):")}
|
|
274
|
+
read - Read file contents
|
|
275
|
+
bash - Execute bash commands
|
|
276
|
+
edit - Edit files with find/replace
|
|
277
|
+
write - Write files (creates/overwrites)
|
|
278
|
+
grep - Search file contents (read-only, off by default)
|
|
279
|
+
find - Find files by glob pattern (read-only, off by default)
|
|
280
|
+
ls - List directory contents (read-only, off by default)
|
|
281
|
+
`);
|
|
282
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TUI config selector for `indusagi config` command
|
|
3
|
+
*/
|
|
4
|
+
import { ProcessTerminal, TUI } from "indusagi/tui";
|
|
5
|
+
import { ConfigSelectorComponent } from "../modes/interactive/components/config-selector.js";
|
|
6
|
+
import { initTheme, stopThemeWatcher } from "../modes/interactive/theme/theme.js";
|
|
7
|
+
/** Show TUI config selector and return when closed */
|
|
8
|
+
export async function selectConfig(options) {
|
|
9
|
+
// Initialize theme before showing TUI
|
|
10
|
+
initTheme(options.settingsManager.getTheme(), true);
|
|
11
|
+
return new Promise((resolve) => {
|
|
12
|
+
const ui = new TUI(new ProcessTerminal());
|
|
13
|
+
let resolved = false;
|
|
14
|
+
const selector = new ConfigSelectorComponent(options.resolvedPaths, options.settingsManager, options.cwd, options.agentDir, () => {
|
|
15
|
+
if (!resolved) {
|
|
16
|
+
resolved = true;
|
|
17
|
+
ui.stop();
|
|
18
|
+
stopThemeWatcher();
|
|
19
|
+
resolve();
|
|
20
|
+
}
|
|
21
|
+
}, () => {
|
|
22
|
+
ui.stop();
|
|
23
|
+
stopThemeWatcher();
|
|
24
|
+
process.exit(0);
|
|
25
|
+
}, () => ui.requestRender());
|
|
26
|
+
ui.addChild(selector);
|
|
27
|
+
ui.setFocus(selector.getResourceList());
|
|
28
|
+
ui.start();
|
|
29
|
+
});
|
|
30
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process @file CLI arguments into text content and image attachments
|
|
3
|
+
*/
|
|
4
|
+
import { access, readFile, stat } from "node:fs/promises";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import { resolve } from "path";
|
|
7
|
+
import { resolveReadPath } from "../core/tools/path-utils.js";
|
|
8
|
+
import { formatDimensionNote, resizeImage } from "../utils/image-resize.js";
|
|
9
|
+
import { detectSupportedImageMimeTypeFromFile } from "../utils/mime.js";
|
|
10
|
+
/** Process @file arguments into text content and image attachments */
|
|
11
|
+
export async function processFileArguments(fileArgs, options) {
|
|
12
|
+
const autoResizeImages = options?.autoResizeImages ?? true;
|
|
13
|
+
let text = "";
|
|
14
|
+
const images = [];
|
|
15
|
+
for (const fileArg of fileArgs) {
|
|
16
|
+
// Expand and resolve path (handles ~ expansion and macOS screenshot Unicode spaces)
|
|
17
|
+
const absolutePath = resolve(resolveReadPath(fileArg, process.cwd()));
|
|
18
|
+
// Check if file exists
|
|
19
|
+
try {
|
|
20
|
+
await access(absolutePath);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
console.error(chalk.red(`Error: File not found: ${absolutePath}`));
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
// Check if file is empty
|
|
27
|
+
const stats = await stat(absolutePath);
|
|
28
|
+
if (stats.size === 0) {
|
|
29
|
+
// Skip empty files
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
const mimeType = await detectSupportedImageMimeTypeFromFile(absolutePath);
|
|
33
|
+
if (mimeType) {
|
|
34
|
+
// Handle image file
|
|
35
|
+
const content = await readFile(absolutePath);
|
|
36
|
+
const base64Content = content.toString("base64");
|
|
37
|
+
let attachment;
|
|
38
|
+
let dimensionNote;
|
|
39
|
+
if (autoResizeImages) {
|
|
40
|
+
const resized = await resizeImage({ type: "image", data: base64Content, mimeType });
|
|
41
|
+
dimensionNote = formatDimensionNote(resized);
|
|
42
|
+
attachment = {
|
|
43
|
+
type: "image",
|
|
44
|
+
mimeType: resized.mimeType,
|
|
45
|
+
data: resized.data,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
attachment = {
|
|
50
|
+
type: "image",
|
|
51
|
+
mimeType,
|
|
52
|
+
data: base64Content,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
images.push(attachment);
|
|
56
|
+
// Add text reference to image with optional dimension note
|
|
57
|
+
if (dimensionNote) {
|
|
58
|
+
text += `<file name="${absolutePath}">${dimensionNote}</file>\n`;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
text += `<file name="${absolutePath}"></file>\n`;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
// Handle text file
|
|
66
|
+
try {
|
|
67
|
+
const content = await readFile(absolutePath, "utf-8");
|
|
68
|
+
text += `<file name="${absolutePath}">\n${content}\n</file>\n`;
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
72
|
+
console.error(chalk.red(`Error: Could not read file ${absolutePath}: ${message}`));
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return { text, images };
|
|
78
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* List available models with optional fuzzy search
|
|
3
|
+
*/
|
|
4
|
+
import { fuzzyFilter } from "indusagi/tui";
|
|
5
|
+
/**
|
|
6
|
+
* Format a number as human-readable (e.g., 200000 -> "200K", 1000000 -> "1M")
|
|
7
|
+
*/
|
|
8
|
+
function formatTokenCount(count) {
|
|
9
|
+
if (count >= 1_000_000) {
|
|
10
|
+
const millions = count / 1_000_000;
|
|
11
|
+
return millions % 1 === 0 ? `${millions}M` : `${millions.toFixed(1)}M`;
|
|
12
|
+
}
|
|
13
|
+
if (count >= 1_000) {
|
|
14
|
+
const thousands = count / 1_000;
|
|
15
|
+
return thousands % 1 === 0 ? `${thousands}K` : `${thousands.toFixed(1)}K`;
|
|
16
|
+
}
|
|
17
|
+
return count.toString();
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* List available models, optionally filtered by search pattern
|
|
21
|
+
*/
|
|
22
|
+
export async function listModels(modelRegistry, searchPattern) {
|
|
23
|
+
const models = modelRegistry.getAvailable();
|
|
24
|
+
if (models.length === 0) {
|
|
25
|
+
console.log("No models available. Set API keys in environment variables.");
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
// Apply fuzzy filter if search pattern provided
|
|
29
|
+
let filteredModels = models;
|
|
30
|
+
if (searchPattern) {
|
|
31
|
+
filteredModels = fuzzyFilter(models, searchPattern, (m) => `${m.provider} ${m.id}`);
|
|
32
|
+
}
|
|
33
|
+
if (filteredModels.length === 0) {
|
|
34
|
+
console.log(`No models matching "${searchPattern}"`);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
// Sort by provider, then by model id
|
|
38
|
+
filteredModels.sort((a, b) => {
|
|
39
|
+
const providerCmp = a.provider.localeCompare(b.provider);
|
|
40
|
+
if (providerCmp !== 0)
|
|
41
|
+
return providerCmp;
|
|
42
|
+
return a.id.localeCompare(b.id);
|
|
43
|
+
});
|
|
44
|
+
// Calculate column widths
|
|
45
|
+
const rows = filteredModels.map((m) => ({
|
|
46
|
+
provider: m.provider,
|
|
47
|
+
model: m.id,
|
|
48
|
+
context: formatTokenCount(m.contextWindow),
|
|
49
|
+
maxOut: formatTokenCount(m.maxTokens),
|
|
50
|
+
thinking: m.reasoning ? "yes" : "no",
|
|
51
|
+
images: m.input.includes("image") ? "yes" : "no",
|
|
52
|
+
}));
|
|
53
|
+
const headers = {
|
|
54
|
+
provider: "provider",
|
|
55
|
+
model: "model",
|
|
56
|
+
context: "context",
|
|
57
|
+
maxOut: "max-out",
|
|
58
|
+
thinking: "thinking",
|
|
59
|
+
images: "images",
|
|
60
|
+
};
|
|
61
|
+
const widths = {
|
|
62
|
+
provider: Math.max(headers.provider.length, ...rows.map((r) => r.provider.length)),
|
|
63
|
+
model: Math.max(headers.model.length, ...rows.map((r) => r.model.length)),
|
|
64
|
+
context: Math.max(headers.context.length, ...rows.map((r) => r.context.length)),
|
|
65
|
+
maxOut: Math.max(headers.maxOut.length, ...rows.map((r) => r.maxOut.length)),
|
|
66
|
+
thinking: Math.max(headers.thinking.length, ...rows.map((r) => r.thinking.length)),
|
|
67
|
+
images: Math.max(headers.images.length, ...rows.map((r) => r.images.length)),
|
|
68
|
+
};
|
|
69
|
+
// Print header
|
|
70
|
+
const headerLine = [
|
|
71
|
+
headers.provider.padEnd(widths.provider),
|
|
72
|
+
headers.model.padEnd(widths.model),
|
|
73
|
+
headers.context.padEnd(widths.context),
|
|
74
|
+
headers.maxOut.padEnd(widths.maxOut),
|
|
75
|
+
headers.thinking.padEnd(widths.thinking),
|
|
76
|
+
headers.images.padEnd(widths.images),
|
|
77
|
+
].join(" ");
|
|
78
|
+
console.log(headerLine);
|
|
79
|
+
// Print rows
|
|
80
|
+
for (const row of rows) {
|
|
81
|
+
const line = [
|
|
82
|
+
row.provider.padEnd(widths.provider),
|
|
83
|
+
row.model.padEnd(widths.model),
|
|
84
|
+
row.context.padEnd(widths.context),
|
|
85
|
+
row.maxOut.padEnd(widths.maxOut),
|
|
86
|
+
row.thinking.padEnd(widths.thinking),
|
|
87
|
+
row.images.padEnd(widths.images),
|
|
88
|
+
].join(" ");
|
|
89
|
+
console.log(line);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TUI session selector for --resume flag
|
|
3
|
+
*/
|
|
4
|
+
import { ProcessTerminal, TUI } from "indusagi/tui";
|
|
5
|
+
import { SessionSelectorComponent } from "../modes/interactive/components/session-selector.js";
|
|
6
|
+
/** Show TUI session selector and return selected session path or null if cancelled */
|
|
7
|
+
export async function selectSession(currentSessionsLoader, allSessionsLoader) {
|
|
8
|
+
return new Promise((resolve) => {
|
|
9
|
+
const ui = new TUI(new ProcessTerminal());
|
|
10
|
+
let resolved = false;
|
|
11
|
+
const selector = new SessionSelectorComponent(currentSessionsLoader, allSessionsLoader, (path) => {
|
|
12
|
+
if (!resolved) {
|
|
13
|
+
resolved = true;
|
|
14
|
+
ui.stop();
|
|
15
|
+
resolve(path);
|
|
16
|
+
}
|
|
17
|
+
}, () => {
|
|
18
|
+
if (!resolved) {
|
|
19
|
+
resolved = true;
|
|
20
|
+
ui.stop();
|
|
21
|
+
resolve(null);
|
|
22
|
+
}
|
|
23
|
+
}, () => {
|
|
24
|
+
ui.stop();
|
|
25
|
+
process.exit(0);
|
|
26
|
+
}, () => ui.requestRender(), { showRenameHint: false });
|
|
27
|
+
ui.addChild(selector);
|
|
28
|
+
ui.setFocus(selector.getSessionList());
|
|
29
|
+
ui.start();
|
|
30
|
+
});
|
|
31
|
+
}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI entry point for the refactored coding agent.
|
|
4
|
+
* Uses main.ts with AgentSession and new mode modules.
|
|
5
|
+
*
|
|
6
|
+
* Test with: npx tsx src/cli-new.ts [args...]
|
|
7
|
+
*/
|
|
8
|
+
process.title = "indusagi";
|
|
9
|
+
import { main } from "./main.js";
|
|
10
|
+
main(process.argv.slice(2));
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "fs";
|
|
2
|
+
import { homedir } from "os";
|
|
3
|
+
import { dirname, join, resolve } from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
// =============================================================================
|
|
6
|
+
// Package Detection
|
|
7
|
+
// =============================================================================
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = dirname(__filename);
|
|
10
|
+
/**
|
|
11
|
+
* Detect if we're running as a Bun compiled binary.
|
|
12
|
+
* Bun binaries have import.meta.url containing "$bunfs", "~BUN", or "%7EBUN" (Bun's virtual filesystem path)
|
|
13
|
+
*/
|
|
14
|
+
export const isBunBinary = import.meta.url.includes("$bunfs") || import.meta.url.includes("~BUN") || import.meta.url.includes("%7EBUN");
|
|
15
|
+
/** Detect if Bun is the runtime (compiled binary or bun run) */
|
|
16
|
+
export const isBunRuntime = !!process.versions.bun;
|
|
17
|
+
// =============================================================================
|
|
18
|
+
// Package Asset Paths (shipped with executable)
|
|
19
|
+
// =============================================================================
|
|
20
|
+
/**
|
|
21
|
+
* Get the base directory for resolving package assets (themes, package.json, README.md, CHANGELOG.md).
|
|
22
|
+
* - For Bun binary: returns the directory containing the executable
|
|
23
|
+
* - For Node.js (dist/): returns __dirname (the dist/ directory)
|
|
24
|
+
* - For tsx (src/): returns parent directory (the package root)
|
|
25
|
+
*/
|
|
26
|
+
export function getPackageDir() {
|
|
27
|
+
if (isBunBinary) {
|
|
28
|
+
// Bun binary: process.execPath points to the compiled executable
|
|
29
|
+
return dirname(process.execPath);
|
|
30
|
+
}
|
|
31
|
+
// Node.js: walk up from __dirname until we find package.json
|
|
32
|
+
let dir = __dirname;
|
|
33
|
+
while (dir !== dirname(dir)) {
|
|
34
|
+
if (existsSync(join(dir, "package.json"))) {
|
|
35
|
+
return dir;
|
|
36
|
+
}
|
|
37
|
+
dir = dirname(dir);
|
|
38
|
+
}
|
|
39
|
+
// Fallback (shouldn't happen)
|
|
40
|
+
return __dirname;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Get path to built-in themes directory (shipped with package)
|
|
44
|
+
* - For Bun binary: theme/ next to executable
|
|
45
|
+
* - For Node.js (dist/): dist/modes/interactive/theme/
|
|
46
|
+
* - For tsx (src/): src/modes/interactive/theme/
|
|
47
|
+
*/
|
|
48
|
+
export function getThemesDir() {
|
|
49
|
+
if (isBunBinary) {
|
|
50
|
+
return join(dirname(process.execPath), "theme");
|
|
51
|
+
}
|
|
52
|
+
// Theme is in modes/interactive/theme/ relative to src/ or dist/
|
|
53
|
+
const packageDir = getPackageDir();
|
|
54
|
+
const srcOrDist = existsSync(join(packageDir, "src")) ? "src" : "dist";
|
|
55
|
+
return join(packageDir, srcOrDist, "modes", "interactive", "theme");
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Get path to HTML export template directory (shipped with package)
|
|
59
|
+
* - For Bun binary: export-html/ next to executable
|
|
60
|
+
* - For Node.js (dist/): dist/core/export-html/
|
|
61
|
+
* - For tsx (src/): src/core/export-html/
|
|
62
|
+
*/
|
|
63
|
+
export function getExportTemplateDir() {
|
|
64
|
+
if (isBunBinary) {
|
|
65
|
+
return join(dirname(process.execPath), "export-html");
|
|
66
|
+
}
|
|
67
|
+
const packageDir = getPackageDir();
|
|
68
|
+
const srcOrDist = existsSync(join(packageDir, "src")) ? "src" : "dist";
|
|
69
|
+
return join(packageDir, srcOrDist, "core", "export-html");
|
|
70
|
+
}
|
|
71
|
+
/** Get path to package.json */
|
|
72
|
+
export function getPackageJsonPath() {
|
|
73
|
+
return join(getPackageDir(), "package.json");
|
|
74
|
+
}
|
|
75
|
+
/** Get path to README.md */
|
|
76
|
+
export function getReadmePath() {
|
|
77
|
+
return resolve(join(getPackageDir(), "README.md"));
|
|
78
|
+
}
|
|
79
|
+
/** Get path to docs directory */
|
|
80
|
+
export function getDocsPath() {
|
|
81
|
+
return resolve(join(getPackageDir(), "docs"));
|
|
82
|
+
}
|
|
83
|
+
/** Get path to examples directory */
|
|
84
|
+
export function getExamplesPath() {
|
|
85
|
+
return resolve(join(getPackageDir(), "examples"));
|
|
86
|
+
}
|
|
87
|
+
/** Get path to CHANGELOG.md */
|
|
88
|
+
export function getChangelogPath() {
|
|
89
|
+
return resolve(join(getPackageDir(), "CHANGELOG.md"));
|
|
90
|
+
}
|
|
91
|
+
// =============================================================================
|
|
92
|
+
// App Config (from package.json indusagiConfig)
|
|
93
|
+
// =============================================================================
|
|
94
|
+
const pkg = JSON.parse(readFileSync(getPackageJsonPath(), "utf-8"));
|
|
95
|
+
export const APP_NAME = pkg.indusagiConfig?.name || "indusagi";
|
|
96
|
+
export const CONFIG_DIR_NAME = pkg.indusagiConfig?.configDir || ".indusagi";
|
|
97
|
+
export const VERSION = pkg.version;
|
|
98
|
+
// e.g., INDUSAGI_CODING_AGENT_DIR or TAU_CODING_AGENT_DIR
|
|
99
|
+
export const ENV_AGENT_DIR = `${APP_NAME.toUpperCase()}_CODING_AGENT_DIR`;
|
|
100
|
+
export const ENV_SHARE_VIEWER_URL = `${APP_NAME.toUpperCase()}_SHARE_VIEWER_URL`;
|
|
101
|
+
const DEFAULT_SHARE_VIEWER_URL = "https://buildwithindusagi.ai/session/";
|
|
102
|
+
/** Get the share viewer URL for a gist ID */
|
|
103
|
+
export function getShareViewerUrl(gistId) {
|
|
104
|
+
const baseUrl = process.env[ENV_SHARE_VIEWER_URL] || DEFAULT_SHARE_VIEWER_URL;
|
|
105
|
+
return `${baseUrl}#${gistId}`;
|
|
106
|
+
}
|
|
107
|
+
// =============================================================================
|
|
108
|
+
// User Config Paths (~/.indusagi/agent/*)
|
|
109
|
+
// =============================================================================
|
|
110
|
+
/** Get the agent config directory (e.g., ~/.indusagi/agent/) */
|
|
111
|
+
export function getAgentDir() {
|
|
112
|
+
const envDir = process.env[ENV_AGENT_DIR];
|
|
113
|
+
if (envDir) {
|
|
114
|
+
// Expand tilde to home directory
|
|
115
|
+
if (envDir === "~")
|
|
116
|
+
return homedir();
|
|
117
|
+
if (envDir.startsWith("~/"))
|
|
118
|
+
return homedir() + envDir.slice(1);
|
|
119
|
+
return envDir;
|
|
120
|
+
}
|
|
121
|
+
return join(homedir(), CONFIG_DIR_NAME, "agent");
|
|
122
|
+
}
|
|
123
|
+
/** Get path to user's custom themes directory */
|
|
124
|
+
export function getCustomThemesDir() {
|
|
125
|
+
return join(getAgentDir(), "themes");
|
|
126
|
+
}
|
|
127
|
+
/** Get path to models.json */
|
|
128
|
+
export function getModelsPath() {
|
|
129
|
+
return join(getAgentDir(), "models.json");
|
|
130
|
+
}
|
|
131
|
+
/** Get path to auth.json */
|
|
132
|
+
export function getAuthPath() {
|
|
133
|
+
return join(getAgentDir(), "auth.json");
|
|
134
|
+
}
|
|
135
|
+
/** Get path to settings.json */
|
|
136
|
+
export function getSettingsPath() {
|
|
137
|
+
return join(getAgentDir(), "settings.json");
|
|
138
|
+
}
|
|
139
|
+
/** Get path to tools directory */
|
|
140
|
+
export function getToolsDir() {
|
|
141
|
+
return join(getAgentDir(), "tools");
|
|
142
|
+
}
|
|
143
|
+
/** Get path to managed binaries directory (fd, rg) */
|
|
144
|
+
export function getBinDir() {
|
|
145
|
+
return join(getAgentDir(), "bin");
|
|
146
|
+
}
|
|
147
|
+
/** Get path to prompt templates directory */
|
|
148
|
+
export function getPromptsDir() {
|
|
149
|
+
return join(getAgentDir(), "prompts");
|
|
150
|
+
}
|
|
151
|
+
/** Get path to sessions directory */
|
|
152
|
+
export function getSessionsDir() {
|
|
153
|
+
return join(getAgentDir(), "sessions");
|
|
154
|
+
}
|
|
155
|
+
/** Get path to debug log file */
|
|
156
|
+
export function getDebugLogPath() {
|
|
157
|
+
return join(getAgentDir(), `${APP_NAME}-debug.log`);
|
|
158
|
+
}
|