indusagi-coding-agent 0.1.20 → 0.1.22
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 +33 -0
- package/README.md +48 -0
- package/dist/cli/args.d.ts +1 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +20 -10
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/login-handler.d.ts +6 -1
- package/dist/cli/login-handler.d.ts.map +1 -1
- package/dist/cli/login-handler.js +266 -26
- package/dist/cli/login-handler.js.map +1 -1
- package/dist/core/auth-storage.d.ts +56 -19
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +207 -53
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/model-registry.d.ts +17 -2
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +20 -4
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +0 -2
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/sdk.d.ts +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +12 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/task-session-manager.d.ts.map +1 -1
- package/dist/core/task-session-manager.js +7 -1
- package/dist/core/task-session-manager.js.map +1 -1
- package/dist/core/tools/index.d.ts +18 -0
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +23 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/webfetch.d.ts +59 -0
- package/dist/core/tools/webfetch.d.ts.map +1 -0
- package/dist/core/tools/webfetch.js +265 -0
- package/dist/core/tools/webfetch.js.map +1 -0
- package/dist/core/tools/websearch.d.ts +63 -0
- package/dist/core/tools/websearch.d.ts.map +1 -0
- package/dist/core/tools/websearch.js +140 -0
- package/dist/core/tools/websearch.js.map +1 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +5 -1
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts +28 -0
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +159 -27
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +20 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +265 -1
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/docs/README.md +79 -0
- package/docs/extensions.md +1 -1
- package/docs/hooks.md +378 -0
- package/docs/sdk.md +12 -0
- package/docs/subagents.md +225 -0
- package/docs/web-tools.md +304 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.1.22]
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- **Web Search Tool**: Real-time web search using Exa AI API
|
|
7
|
+
- Search for current events and information beyond knowledge cutoff
|
|
8
|
+
- Configurable result counts, live crawling modes, and search types
|
|
9
|
+
- Access via `websearch` tool (now included in default tools)
|
|
10
|
+
- **Web Fetch Tool**: Fetch content from URLs with format conversion
|
|
11
|
+
- Fetch webpages and convert to markdown, text, or HTML
|
|
12
|
+
- Image support (returns as base64 attachment)
|
|
13
|
+
- Configurable timeout (max 120 seconds) and 5MB size limit
|
|
14
|
+
- Access via `webfetch` tool (now included in default tools)
|
|
15
|
+
- Both tools are now available in default tool set alongside read, bash, edit, write, task, todoread, and todowrite
|
|
16
|
+
|
|
17
|
+
## [0.1.21]
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
- **Multi-account support**: Login with multiple accounts per provider
|
|
21
|
+
- Use `indusagi login --provider <provider> --account <name>` to add named accounts
|
|
22
|
+
- Use `indusagi login --list` to view all saved accounts
|
|
23
|
+
- Use `indusagi --account <name>` to select which account to use
|
|
24
|
+
- Interactive mode: Select existing accounts or add new ones via `/login`
|
|
25
|
+
- **Claude Sonnet 4.6**: New model added (`claude-sonnet-4-6`) with 200K context, 128K max output, $3/$15 pricing
|
|
26
|
+
- **GLM-5 model**: Fixed endpoint for Z.AI coding subscription (`api.z.ai/api/coding/paas/v4`)
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
- **GPT-5.3 Codex Spark**: Context window updated from 32K to 128K tokens
|
|
30
|
+
- Updated `indusagi` dependency to `0.12.6`
|
|
31
|
+
|
|
32
|
+
### Removed
|
|
33
|
+
- **Google Cloud Code Assist (Gemini CLI)**: OAuth provider removed
|
|
34
|
+
- **Google Antigravity**: OAuth provider and all models removed
|
|
35
|
+
|
|
3
36
|
## [0.1.20]
|
|
4
37
|
|
|
5
38
|
### Fixed
|
package/README.md
CHANGED
|
@@ -30,6 +30,42 @@ Example (file-aware prompt):
|
|
|
30
30
|
indusagi @src/index.ts "Summarize this file"
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
+
## Web Search & Web Fetch
|
|
34
|
+
|
|
35
|
+
The agent includes built-in tools for web operations:
|
|
36
|
+
|
|
37
|
+
### Web Search Tool
|
|
38
|
+
Search the web for real-time information using Exa AI:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
indusagi "Search for latest AI developments 2026"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Features:
|
|
45
|
+
- Real-time web search beyond knowledge cutoff
|
|
46
|
+
- Configurable result counts (1-10)
|
|
47
|
+
- Live crawling modes (fallback/preferred)
|
|
48
|
+
- Search types: auto, fast, deep
|
|
49
|
+
|
|
50
|
+
### Web Fetch Tool
|
|
51
|
+
Fetch content from URLs with format conversion:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
indusagi "Fetch https://example.com and show me the content"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Features:
|
|
58
|
+
- Fetch webpages and convert to markdown, text, or HTML
|
|
59
|
+
- Image support (returns as base64 attachment)
|
|
60
|
+
- Configurable timeout (up to 120 seconds)
|
|
61
|
+
- 5MB response size limit
|
|
62
|
+
|
|
63
|
+
Both tools are included in the default tool set and work automatically without any additional flags.
|
|
64
|
+
|
|
65
|
+
## Documentation
|
|
66
|
+
|
|
67
|
+
For complete documentation, visit: https://www.indusagi.com
|
|
68
|
+
|
|
33
69
|
## Modes
|
|
34
70
|
|
|
35
71
|
- Interactive mode (default)
|
|
@@ -40,15 +76,27 @@ indusagi @src/index.ts "Summarize this file"
|
|
|
40
76
|
## Customization
|
|
41
77
|
|
|
42
78
|
- Extensions: `docs/extensions.md`
|
|
79
|
+
- Hooks: `docs/hooks.md`
|
|
43
80
|
- Skills: `docs/skills.md`
|
|
81
|
+
- Subagents: `docs/subagents.md`
|
|
44
82
|
- Prompt templates: `docs/prompt-templates.md`
|
|
45
83
|
- Themes: `docs/themes.md`
|
|
46
84
|
- Packages: `docs/packages.md`
|
|
47
85
|
|
|
86
|
+
## Session Management
|
|
87
|
+
|
|
88
|
+
- Session format: `docs/session.md`
|
|
89
|
+
- Tree navigation: `docs/tree.md`
|
|
90
|
+
- Compaction: `docs/compaction.md`
|
|
91
|
+
|
|
48
92
|
## Configuration
|
|
49
93
|
|
|
50
94
|
Settings can be global or project-specific. See `docs/settings.md`.
|
|
51
95
|
|
|
96
|
+
- Keybindings: `docs/keybindings.md`
|
|
97
|
+
- Custom models: `docs/models.md`
|
|
98
|
+
- Custom providers: `docs/custom-provider.md`
|
|
99
|
+
|
|
52
100
|
## License
|
|
53
101
|
|
|
54
102
|
MIT
|
package/dist/cli/args.d.ts
CHANGED
package/dist/cli/args.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGpD,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEjE,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAE3C,MAAM,WAAW,IAAI;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,8EAA8E;IAC9E,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC;CAC5C;AAID,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,aAAa,CAE1E;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,SAAS,GAAG,QAAQ,CAAA;CAAE,CAAC,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGpD,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEjE,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAE3C,MAAM,WAAW,IAAI;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,8EAA8E;IAC9E,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC;CAC5C;AAID,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,aAAa,CAE1E;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,SAAS,GAAG,QAAQ,CAAA;CAAE,CAAC,GAAG,IAAI,CA+H5G;AAED,wBAAgB,SAAS,IAAI,IAAI,CAgJhC"}
|
package/dist/cli/args.js
CHANGED
|
@@ -37,6 +37,9 @@ export function parseArgs(args, extensionFlags) {
|
|
|
37
37
|
else if (arg === "--provider" && i + 1 < args.length) {
|
|
38
38
|
result.provider = args[++i];
|
|
39
39
|
}
|
|
40
|
+
else if (arg === "--account" && i + 1 < args.length) {
|
|
41
|
+
result.account = args[++i];
|
|
42
|
+
}
|
|
40
43
|
else if (arg === "--model" && i + 1 < args.length) {
|
|
41
44
|
result.model = args[++i];
|
|
42
45
|
}
|
|
@@ -179,6 +182,7 @@ ${chalk.bold("Commands:")}
|
|
|
179
182
|
|
|
180
183
|
${chalk.bold("Options:")}
|
|
181
184
|
--provider <name> Provider name (default: google)
|
|
185
|
+
--account <name> Account name for multi-account providers (default: default)
|
|
182
186
|
--model <id> Model ID (default: gemini-2.5-flash)
|
|
183
187
|
--api-key <key> API key (defaults to env vars)
|
|
184
188
|
--system-prompt <text> System prompt (default: coding assistant prompt)
|
|
@@ -193,8 +197,8 @@ ${chalk.bold("Options:")}
|
|
|
193
197
|
--models <patterns> Comma-separated model patterns for Ctrl+P cycling
|
|
194
198
|
Supports globs (anthropic/*, *sonnet*) and fuzzy matching
|
|
195
199
|
--no-tools Disable all built-in tools
|
|
196
|
-
--tools <tools> Comma-separated list of tools to enable (default: read,bash,edit,write,task,todoread,todowrite)
|
|
197
|
-
Available: read, bash, edit, write, task, grep, find, ls, todoread, todowrite
|
|
200
|
+
--tools <tools> Comma-separated list of tools to enable (default: read,bash,edit,write,task,todoread,todowrite,websearch,webfetch)
|
|
201
|
+
Available: read, bash, edit, write, task, grep, find, ls, todoread, todowrite, websearch, webfetch
|
|
198
202
|
--thinking <level> Set thinking level: off, minimal, low, medium, high, xhigh
|
|
199
203
|
--extension, -e <path> Load an extension file (can be used multiple times)
|
|
200
204
|
--no-extensions Disable extension discovery (explicit -e paths still work)
|
|
@@ -261,6 +265,10 @@ ${chalk.bold("Examples:")}
|
|
|
261
265
|
${APP_NAME} login --provider kimi-coding # Login to Kimi Code with API key
|
|
262
266
|
${APP_NAME} login --provider anthropic # Login to Anthropic with OAuth
|
|
263
267
|
${APP_NAME} login --provider openai # Login to OpenAI with API key
|
|
268
|
+
${APP_NAME} login --provider minimax --account prod # Login to MiniMax (prod account)
|
|
269
|
+
${APP_NAME} login --provider minimax --account dev # Login to MiniMax (dev account)
|
|
270
|
+
${APP_NAME} login --list # List all saved accounts
|
|
271
|
+
${APP_NAME} logout --provider minimax --account dev # Logout specific account
|
|
264
272
|
|
|
265
273
|
${chalk.bold("Environment Variables:")}
|
|
266
274
|
ANTHROPIC_AINDUSAGI_KEY - Anthropic Claude API key
|
|
@@ -290,14 +298,16 @@ ${chalk.bold("Environment Variables:")}
|
|
|
290
298
|
${ENV_AGENT_DIR.padEnd(32)} - Session storage directory (default: ~/${CONFIG_DIR_NAME}/agent)
|
|
291
299
|
INDUSAGI_SHARE_VIEWER_URL - Base URL for /share command (default: https://buildwithindusagi.ai/session/)
|
|
292
300
|
|
|
293
|
-
${chalk.bold("Available Tools (default: read, bash, edit, write):")}
|
|
294
|
-
read
|
|
295
|
-
bash
|
|
296
|
-
edit
|
|
297
|
-
write
|
|
298
|
-
grep
|
|
299
|
-
find
|
|
300
|
-
ls
|
|
301
|
+
${chalk.bold("Available Tools (default: read, bash, edit, write, websearch, webfetch):")}
|
|
302
|
+
read - Read file contents
|
|
303
|
+
bash - Execute bash commands
|
|
304
|
+
edit - Edit files with find/replace
|
|
305
|
+
write - Write files (creates/overwrites)
|
|
306
|
+
grep - Search file contents (read-only, off by default)
|
|
307
|
+
find - Find files by glob pattern (read-only, off by default)
|
|
308
|
+
ls - List directory contents (read-only, off by default)
|
|
309
|
+
websearch - Search the web using Exa AI for real-time information
|
|
310
|
+
webfetch - Fetch content from URLs with format conversion (markdown/text/html)
|
|
301
311
|
`);
|
|
302
312
|
}
|
|
303
313
|
//# sourceMappingURL=args.js.map
|
package/dist/cli/args.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EAAE,QAAQ,EAAiB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,14 +2,19 @@
|
|
|
2
2
|
* Login command handler for AI provider authentication
|
|
3
3
|
* Supports OAuth and API key-based authentication
|
|
4
4
|
*
|
|
5
|
+
* MULTI-ACCOUNT SUPPORT: Each provider can have multiple named accounts.
|
|
6
|
+
*
|
|
5
7
|
* Pattern matched with openclaw implementation:
|
|
6
8
|
* - Check for environment variables (KIMI_API_KEY, MOONSHOT_API_KEY, etc.)
|
|
7
9
|
* - Show info/help URL
|
|
8
10
|
* - Prompt for API key input
|
|
9
|
-
* - Store in auth storage
|
|
11
|
+
* - Store in auth storage with account name
|
|
10
12
|
*/
|
|
11
13
|
export interface LoginOptions {
|
|
12
14
|
provider?: string;
|
|
15
|
+
account?: string;
|
|
16
|
+
list?: boolean;
|
|
17
|
+
all?: boolean;
|
|
13
18
|
}
|
|
14
19
|
export declare function handleLoginCommand(args: string[]): Promise<boolean>;
|
|
15
20
|
//# sourceMappingURL=login-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login-handler.d.ts","sourceRoot":"","sources":["../../src/cli/login-handler.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"login-handler.d.ts","sourceRoot":"","sources":["../../src/cli/login-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAQH,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;CACd;AA2BD,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CA8BzE"}
|
|
@@ -2,28 +2,40 @@
|
|
|
2
2
|
* Login command handler for AI provider authentication
|
|
3
3
|
* Supports OAuth and API key-based authentication
|
|
4
4
|
*
|
|
5
|
+
* MULTI-ACCOUNT SUPPORT: Each provider can have multiple named accounts.
|
|
6
|
+
*
|
|
5
7
|
* Pattern matched with openclaw implementation:
|
|
6
8
|
* - Check for environment variables (KIMI_API_KEY, MOONSHOT_API_KEY, etc.)
|
|
7
9
|
* - Show info/help URL
|
|
8
10
|
* - Prompt for API key input
|
|
9
|
-
* - Store in auth storage
|
|
11
|
+
* - Store in auth storage with account name
|
|
10
12
|
*/
|
|
11
|
-
import { getEnvApiKey } from "indusagi/ai";
|
|
13
|
+
import { getEnvApiKey, getOAuthProviders } from "indusagi/ai";
|
|
12
14
|
import chalk from "chalk";
|
|
13
15
|
import { createInterface } from "readline";
|
|
14
16
|
import { AuthStorage } from "../core/auth-storage.js";
|
|
15
17
|
import { getAgentDir } from "../config.js";
|
|
16
18
|
function parseLoginCommand(args) {
|
|
17
19
|
const [command, ...rest] = args;
|
|
18
|
-
if (command !== "login") {
|
|
20
|
+
if (command !== "login" && command !== "logout") {
|
|
19
21
|
return undefined;
|
|
20
22
|
}
|
|
21
23
|
const options = {};
|
|
24
|
+
const isLogout = command === "logout";
|
|
22
25
|
for (let i = 0; i < rest.length; i++) {
|
|
23
26
|
const arg = rest[i];
|
|
24
27
|
if (arg === "--provider" && i + 1 < rest.length) {
|
|
25
28
|
options.provider = rest[++i];
|
|
26
29
|
}
|
|
30
|
+
else if (arg === "--account" && i + 1 < rest.length) {
|
|
31
|
+
options.account = rest[++i];
|
|
32
|
+
}
|
|
33
|
+
else if (arg === "--list") {
|
|
34
|
+
options.list = true;
|
|
35
|
+
}
|
|
36
|
+
else if (arg === "--all" && isLogout) {
|
|
37
|
+
options.all = true;
|
|
38
|
+
}
|
|
27
39
|
}
|
|
28
40
|
return options;
|
|
29
41
|
}
|
|
@@ -34,39 +46,169 @@ export async function handleLoginCommand(args) {
|
|
|
34
46
|
}
|
|
35
47
|
const agentDir = getAgentDir();
|
|
36
48
|
const authStorage = new AuthStorage(agentDir);
|
|
49
|
+
// Handle --list flag
|
|
50
|
+
if (options.list) {
|
|
51
|
+
await listAccounts(authStorage);
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
37
54
|
// If provider not specified, show list
|
|
38
55
|
if (!options.provider) {
|
|
39
|
-
await showProviderSelection();
|
|
56
|
+
await showProviderSelection(authStorage);
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
// Handle logout
|
|
60
|
+
if (args[0] === "logout") {
|
|
61
|
+
await logoutFromProvider(authStorage, options.provider, options.account, options.all);
|
|
40
62
|
return true;
|
|
41
63
|
}
|
|
42
64
|
// Login to specific provider
|
|
43
|
-
await loginToProvider(authStorage, options.provider);
|
|
65
|
+
await loginToProvider(authStorage, options.provider, options.account);
|
|
44
66
|
return true;
|
|
45
67
|
}
|
|
46
|
-
async function
|
|
47
|
-
|
|
68
|
+
async function listAccounts(authStorage) {
|
|
69
|
+
console.log(chalk.bold("\n🔐 Saved Accounts:\n"));
|
|
70
|
+
const providers = authStorage.list();
|
|
71
|
+
if (providers.length === 0) {
|
|
72
|
+
console.log(chalk.dim("No saved accounts. Use 'indusagi login --provider <provider>' to add accounts.\n"));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
for (const provider of providers) {
|
|
76
|
+
const accounts = authStorage.getAccounts(provider);
|
|
77
|
+
const defaultAccount = authStorage.getDefaultAccount(provider);
|
|
78
|
+
console.log(chalk.cyan(`${provider} (${accounts.length} account${accounts.length !== 1 ? 's' : ''}):`));
|
|
79
|
+
for (const { accountId, credential } of accounts) {
|
|
80
|
+
const isDefault = accountId === defaultAccount;
|
|
81
|
+
const defaultMarker = isDefault ? chalk.green(" [default]") : "";
|
|
82
|
+
const type = credential.type === "oauth" ? "OAuth" : "API key";
|
|
83
|
+
const name = credential.accountName || accountId;
|
|
84
|
+
let status = "✓";
|
|
85
|
+
if (credential.type === "oauth") {
|
|
86
|
+
const expired = Date.now() >= credential.expires;
|
|
87
|
+
status = expired ? chalk.yellow("⚠ expired") : chalk.green("✓");
|
|
88
|
+
}
|
|
89
|
+
console.log(` ${status} ${name}${defaultMarker} (${type})`);
|
|
90
|
+
}
|
|
91
|
+
console.log();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async function showProviderSelection(authStorage) {
|
|
95
|
+
// Get OAuth providers
|
|
96
|
+
const oauthProviders = getOAuthProviders().map(p => ({
|
|
97
|
+
id: p.id,
|
|
98
|
+
name: p.name,
|
|
99
|
+
auth: "OAuth",
|
|
100
|
+
}));
|
|
101
|
+
// API key providers
|
|
102
|
+
const apiKeyProviders = [
|
|
48
103
|
{ id: "kimi", name: "Kimi (Moonshot AI)", auth: "API key" },
|
|
49
104
|
{ id: "kimi-coding", name: "Kimi Code (Moonshot - Subscription)", auth: "API key" },
|
|
50
|
-
{ id: "anthropic", name: "Anthropic (Claude)", auth: "
|
|
105
|
+
{ id: "anthropic", name: "Anthropic (Claude)", auth: "API key" },
|
|
51
106
|
{ id: "openai", name: "OpenAI", auth: "API key" },
|
|
52
107
|
{ id: "google", name: "Google (Gemini)", auth: "API key" },
|
|
53
|
-
{ id: "
|
|
108
|
+
{ id: "groq", name: "Groq", auth: "API key" },
|
|
109
|
+
{ id: "cerebras", name: "Cerebras", auth: "API key" },
|
|
110
|
+
{ id: "xai", name: "xAI (Grok)", auth: "API key" },
|
|
111
|
+
{ id: "openrouter", name: "OpenRouter", auth: "API key" },
|
|
112
|
+
{ id: "vercel-ai-gateway", name: "Vercel AI Gateway", auth: "API key" },
|
|
113
|
+
{ id: "zai", name: "Z.AI (GLM)", auth: "API key" },
|
|
114
|
+
{ id: "mistral", name: "Mistral", auth: "API key" },
|
|
115
|
+
{ id: "minimax", name: "MiniMax", auth: "API key" },
|
|
116
|
+
{ id: "minimax-cn", name: "MiniMax (China)", auth: "API key" },
|
|
117
|
+
{ id: "opencode", name: "OpenCode Zen", auth: "API key" },
|
|
54
118
|
];
|
|
55
119
|
console.log(chalk.bold("\n🔐 Available Providers for Authentication\n"));
|
|
56
|
-
|
|
57
|
-
|
|
120
|
+
console.log(chalk.dim("OAuth Providers:"));
|
|
121
|
+
oauthProviders.forEach((p, idx) => {
|
|
122
|
+
const accountCount = authStorage.getAccounts(p.id).length;
|
|
123
|
+
const accountInfo = accountCount > 0 ? chalk.green(` (${accountCount} saved)`) : "";
|
|
124
|
+
console.log(` ${idx + 1}. ${p.name} ${chalk.dim(`(${p.auth})`)}${accountInfo}`);
|
|
125
|
+
});
|
|
126
|
+
console.log(chalk.dim("\nAPI Key Providers:"));
|
|
127
|
+
apiKeyProviders.forEach((p, idx) => {
|
|
128
|
+
const accountCount = authStorage.getAccounts(p.id).length;
|
|
129
|
+
const accountInfo = accountCount > 0 ? chalk.green(` (${accountCount} saved)`) : "";
|
|
130
|
+
console.log(` ${oauthProviders.length + idx + 1}. ${p.name} ${chalk.dim(`(${p.auth})`)}${accountInfo}`);
|
|
58
131
|
});
|
|
59
|
-
console.log("\n" + chalk.dim("Run: indusagi login --provider <provider-id>"));
|
|
60
|
-
console.log(chalk.dim("Example: indusagi login --provider
|
|
132
|
+
console.log("\n" + chalk.dim("Run: indusagi login --provider <provider-id> [--account <name>]"));
|
|
133
|
+
console.log(chalk.dim("Example: indusagi login --provider minimax --account production\n"));
|
|
61
134
|
// Show examples
|
|
62
135
|
console.log(chalk.bold("Examples:"));
|
|
63
|
-
console.log(` ${chalk.cyan("indusagi login --provider
|
|
64
|
-
console.log(` ${chalk.cyan("indusagi login --provider
|
|
65
|
-
console.log(` ${chalk.cyan("indusagi login --provider
|
|
66
|
-
console.log(` ${chalk.cyan("indusagi login --provider
|
|
136
|
+
console.log(` ${chalk.cyan("indusagi login --provider openai-codex --account personal")} ${chalk.dim("# Login to ChatGPT (personal)")}`);
|
|
137
|
+
console.log(` ${chalk.cyan("indusagi login --provider openai-codex --account work")} ${chalk.dim("# Login to ChatGPT (work)")}`);
|
|
138
|
+
console.log(` ${chalk.cyan("indusagi login --provider minimax --account prod")} ${chalk.dim("# Add MiniMax API key (prod)")}`);
|
|
139
|
+
console.log(` ${chalk.cyan("indusagi login --provider minimax --account dev")} ${chalk.dim("# Add MiniMax API key (dev)")}`);
|
|
140
|
+
console.log(` ${chalk.cyan("indusagi login --list")} ${chalk.dim("# List all saved accounts")}`);
|
|
141
|
+
console.log(` ${chalk.cyan("indusagi logout --provider openai-codex --account work")} ${chalk.dim("# Logout specific account")}\n`);
|
|
67
142
|
}
|
|
68
|
-
async function loginToProvider(authStorage, provider) {
|
|
69
|
-
|
|
143
|
+
async function loginToProvider(authStorage, provider, accountId) {
|
|
144
|
+
// Check if this is an OAuth provider
|
|
145
|
+
const oauthProviders = getOAuthProviders();
|
|
146
|
+
const oauthProvider = oauthProviders.find(p => p.id === provider);
|
|
147
|
+
// Generate account name if not provided
|
|
148
|
+
const targetAccountId = accountId || "default";
|
|
149
|
+
const existingAccounts = authStorage.getAccounts(provider);
|
|
150
|
+
// If no account specified and accounts exist, ask if user wants to add new or use existing
|
|
151
|
+
if (!accountId && existingAccounts.length > 0) {
|
|
152
|
+
console.log(chalk.yellow(`\n⚠️ Provider '${provider}' already has ${existingAccounts.length} saved account(s):`));
|
|
153
|
+
for (const { accountId, credential } of existingAccounts) {
|
|
154
|
+
const name = credential.accountName || accountId;
|
|
155
|
+
const isDefault = accountId === authStorage.getDefaultAccount(provider);
|
|
156
|
+
console.log(` - ${name}${isDefault ? " [default]" : ""}`);
|
|
157
|
+
}
|
|
158
|
+
const choice = await promptChoice("What would you like to do?", ["Use existing account", "Add new account"]);
|
|
159
|
+
if (choice === "Use existing account") {
|
|
160
|
+
const selected = await promptChoice("Select account:", existingAccounts.map(a => a.credential.accountName || a.accountId));
|
|
161
|
+
const selectedAccount = existingAccounts.find(a => (a.credential.accountName || a.accountId) === selected);
|
|
162
|
+
if (selectedAccount) {
|
|
163
|
+
authStorage.setDefaultAccount(provider, selectedAccount.accountId);
|
|
164
|
+
console.log(chalk.green.bold(`\n✅ Switched to account: ${selected}\n`));
|
|
165
|
+
}
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
// User wants to add new account - prompt for name
|
|
169
|
+
const newName = await promptInput("Enter new account name (e.g., 'work', 'personal')");
|
|
170
|
+
if (!newName || newName.trim() === "") {
|
|
171
|
+
console.error(chalk.red("\n❌ Account name is required\n"));
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
// Check if name already exists
|
|
175
|
+
const nameExists = existingAccounts.some(a => (a.credential.accountName || a.accountId) === newName.trim());
|
|
176
|
+
if (nameExists) {
|
|
177
|
+
console.error(chalk.red(`\n❌ Account '${newName}' already exists for ${provider}\n`));
|
|
178
|
+
process.exit(1);
|
|
179
|
+
}
|
|
180
|
+
accountId = newName.trim();
|
|
181
|
+
}
|
|
182
|
+
console.log(chalk.bold(`\n🔐 Logging in to ${provider}${accountId ? ` [${accountId}]` : ""}...\n`));
|
|
183
|
+
// Handle OAuth login
|
|
184
|
+
if (oauthProvider) {
|
|
185
|
+
console.log(chalk.dim(`Starting OAuth flow for ${oauthProvider.name}...`));
|
|
186
|
+
console.log(chalk.dim("A browser window should open. Complete login to finish.\n"));
|
|
187
|
+
try {
|
|
188
|
+
await authStorage.login(provider, {
|
|
189
|
+
onAuth: (info) => {
|
|
190
|
+
console.log(chalk.dim(`Opening: ${info.url}`));
|
|
191
|
+
if (info.instructions) {
|
|
192
|
+
console.log(chalk.dim(info.instructions));
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
onPrompt: async (prompt) => {
|
|
196
|
+
return promptInput(prompt.message);
|
|
197
|
+
},
|
|
198
|
+
onProgress: (msg) => {
|
|
199
|
+
console.log(chalk.dim(msg));
|
|
200
|
+
},
|
|
201
|
+
}, targetAccountId, accountId);
|
|
202
|
+
console.log(chalk.green.bold(`\n✅ Login successful! Account: ${accountId || "default"}\n`));
|
|
203
|
+
console.log(chalk.dim(`Use: indusagi --provider ${provider} --account ${accountId || "default"} [options]\n`));
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
console.error(chalk.red(`\n❌ Login failed: ${error instanceof Error ? error.message : error}\n`));
|
|
207
|
+
process.exit(1);
|
|
208
|
+
}
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
// Handle API key login
|
|
70
212
|
const envKey = getEnvApiKey(provider);
|
|
71
213
|
// Get provider info
|
|
72
214
|
const providerInfo = getProviderInfo(provider);
|
|
@@ -82,10 +224,15 @@ async function loginToProvider(authStorage, provider) {
|
|
|
82
224
|
if (envKey) {
|
|
83
225
|
const useExisting = await promptChoice(`Use existing ${providerInfo.envVar} (from environment)?`, ["Yes", "No, enter a new key"]);
|
|
84
226
|
if (useExisting === "Yes") {
|
|
85
|
-
authStorage.
|
|
86
|
-
|
|
227
|
+
authStorage.set(provider, targetAccountId, {
|
|
228
|
+
type: "api_key",
|
|
229
|
+
key: envKey,
|
|
230
|
+
accountId: targetAccountId,
|
|
231
|
+
accountName: accountId || "Default",
|
|
232
|
+
});
|
|
233
|
+
console.log(chalk.green.bold(`\n✅ Login successful! Account: ${accountId || "default"}\n`));
|
|
87
234
|
console.log(chalk.dim(`Using ${providerInfo.envVar} from environment`));
|
|
88
|
-
console.log(chalk.dim(`Use: indusagi --provider ${provider} [options]\n`));
|
|
235
|
+
console.log(chalk.dim(`Use: indusagi --provider ${provider} --account ${accountId || "default"} [options]\n`));
|
|
89
236
|
return;
|
|
90
237
|
}
|
|
91
238
|
}
|
|
@@ -95,10 +242,53 @@ async function loginToProvider(authStorage, provider) {
|
|
|
95
242
|
console.error(chalk.red("\n❌ API key is required\n"));
|
|
96
243
|
process.exit(1);
|
|
97
244
|
}
|
|
98
|
-
authStorage.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
245
|
+
authStorage.set(provider, targetAccountId, {
|
|
246
|
+
type: "api_key",
|
|
247
|
+
key: apiKey.trim(),
|
|
248
|
+
accountId: targetAccountId,
|
|
249
|
+
accountName: accountId || "Default",
|
|
250
|
+
});
|
|
251
|
+
console.log(chalk.green.bold(`\n✅ Login successful! Account: ${accountId || "default"}\n`));
|
|
252
|
+
console.log(chalk.dim(`API key saved for ${provider}/${accountId || "default"}`));
|
|
253
|
+
console.log(chalk.dim(`Use: indusagi --provider ${provider} --account ${accountId || "default"} [options]\n`));
|
|
254
|
+
}
|
|
255
|
+
async function logoutFromProvider(authStorage, provider, accountId, all) {
|
|
256
|
+
if (all) {
|
|
257
|
+
authStorage.logout(provider);
|
|
258
|
+
console.log(chalk.green.bold(`\n✅ Logged out all accounts for: ${provider}\n`));
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
const accounts = authStorage.getAccounts(provider);
|
|
262
|
+
if (accounts.length === 0) {
|
|
263
|
+
console.log(chalk.yellow(`\n⚠️ No accounts found for: ${provider}\n`));
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
// If specific account provided
|
|
267
|
+
if (accountId) {
|
|
268
|
+
authStorage.logout(provider, accountId);
|
|
269
|
+
console.log(chalk.green.bold(`\n✅ Logged out: ${provider}/${accountId}\n`));
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
// If multiple accounts, ask which one
|
|
273
|
+
if (accounts.length > 1) {
|
|
274
|
+
const selected = await promptChoice("Select account to logout:", [...accounts.map(a => a.credential.accountName || a.accountId), "All accounts"]);
|
|
275
|
+
if (selected === "All accounts") {
|
|
276
|
+
authStorage.logout(provider);
|
|
277
|
+
console.log(chalk.green.bold(`\n✅ Logged out all accounts for: ${provider}\n`));
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
const selectedAccount = accounts.find(a => (a.credential.accountName || a.accountId) === selected);
|
|
281
|
+
if (selectedAccount) {
|
|
282
|
+
authStorage.logout(provider, selectedAccount.accountId);
|
|
283
|
+
console.log(chalk.green.bold(`\n✅ Logged out: ${provider}/${selected}\n`));
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
// Single account - logout it
|
|
289
|
+
const singleAccount = accounts[0];
|
|
290
|
+
authStorage.logout(provider, singleAccount.accountId);
|
|
291
|
+
console.log(chalk.green.bold(`\n✅ Logged out: ${provider}/${singleAccount.credential.accountName || singleAccount.accountId}\n`));
|
|
102
292
|
}
|
|
103
293
|
function getProviderInfo(provider) {
|
|
104
294
|
const providers = {
|
|
@@ -132,6 +322,56 @@ function getProviderInfo(provider) {
|
|
|
132
322
|
envVar: "GEMINI_API_KEY",
|
|
133
323
|
helpUrl: "https://aistudio.google.com/app/apikey",
|
|
134
324
|
},
|
|
325
|
+
groq: {
|
|
326
|
+
name: "Groq",
|
|
327
|
+
envVar: "GROQ_API_KEY",
|
|
328
|
+
helpUrl: "https://console.groq.com/keys",
|
|
329
|
+
},
|
|
330
|
+
cerebras: {
|
|
331
|
+
name: "Cerebras",
|
|
332
|
+
envVar: "CEREBRAS_API_KEY",
|
|
333
|
+
helpUrl: "https://cloud.cerebras.ai/",
|
|
334
|
+
},
|
|
335
|
+
xai: {
|
|
336
|
+
name: "xAI (Grok)",
|
|
337
|
+
envVar: "XAI_API_KEY",
|
|
338
|
+
helpUrl: "https://x.ai/api",
|
|
339
|
+
},
|
|
340
|
+
openrouter: {
|
|
341
|
+
name: "OpenRouter",
|
|
342
|
+
envVar: "OPENROUTER_API_KEY",
|
|
343
|
+
helpUrl: "https://openrouter.ai/keys",
|
|
344
|
+
},
|
|
345
|
+
"vercel-ai-gateway": {
|
|
346
|
+
name: "Vercel AI Gateway",
|
|
347
|
+
envVar: "AI_GATEWAY_API_KEY",
|
|
348
|
+
helpUrl: "https://vercel.com/docs/ai-gateway",
|
|
349
|
+
},
|
|
350
|
+
zai: {
|
|
351
|
+
name: "Z.AI (GLM)",
|
|
352
|
+
envVar: "ZAI_API_KEY",
|
|
353
|
+
helpUrl: "https://api.z.ai/",
|
|
354
|
+
},
|
|
355
|
+
mistral: {
|
|
356
|
+
name: "Mistral",
|
|
357
|
+
envVar: "MISTRAL_API_KEY",
|
|
358
|
+
helpUrl: "https://console.mistral.ai/",
|
|
359
|
+
},
|
|
360
|
+
minimax: {
|
|
361
|
+
name: "MiniMax",
|
|
362
|
+
envVar: "MINIMAX_API_KEY",
|
|
363
|
+
helpUrl: "https://www.minimaxi.com/",
|
|
364
|
+
},
|
|
365
|
+
"minimax-cn": {
|
|
366
|
+
name: "MiniMax (China)",
|
|
367
|
+
envVar: "MINIMAX_CN_API_KEY",
|
|
368
|
+
helpUrl: "https://www.minimaxi.com/",
|
|
369
|
+
},
|
|
370
|
+
opencode: {
|
|
371
|
+
name: "OpenCode Zen",
|
|
372
|
+
envVar: "OPENCODE_API_KEY",
|
|
373
|
+
helpUrl: "https://opencode.ai/",
|
|
374
|
+
},
|
|
135
375
|
};
|
|
136
376
|
return providers[provider];
|
|
137
377
|
}
|