archbyte 0.3.4 → 0.4.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/README.md +42 -0
- package/bin/archbyte.js +32 -14
- package/dist/agents/pipeline/merger.js +16 -11
- package/dist/agents/providers/claude-sdk.d.ts +7 -0
- package/dist/agents/providers/claude-sdk.js +59 -0
- package/dist/agents/providers/router.d.ts +5 -0
- package/dist/agents/providers/router.js +23 -1
- package/dist/agents/runtime/types.d.ts +2 -2
- package/dist/agents/runtime/types.js +5 -0
- package/dist/cli/analyze.js +8 -4
- package/dist/cli/auth.d.ts +11 -2
- package/dist/cli/auth.js +312 -73
- package/dist/cli/config.d.ts +1 -0
- package/dist/cli/config.js +51 -15
- package/dist/cli/constants.js +4 -1
- package/dist/cli/export.js +64 -2
- package/dist/cli/license-gate.d.ts +1 -1
- package/dist/cli/license-gate.js +3 -2
- package/dist/cli/mcp.js +8 -12
- package/dist/cli/setup.js +166 -35
- package/dist/cli/ui.d.ts +14 -0
- package/dist/cli/ui.js +98 -14
- package/dist/cli/utils.d.ts +23 -0
- package/dist/cli/utils.js +52 -0
- package/dist/server/src/index.js +59 -5
- package/package.json +4 -1
- package/ui/dist/assets/index-DmO1qYan.js +70 -0
- package/ui/dist/index.html +1 -1
- package/ui/dist/assets/index-Bdr9FnaA.js +0 -70
package/README.md
CHANGED
|
@@ -76,6 +76,48 @@ Run `/archbyte-help` in Claude Code to see all commands.
|
|
|
76
76
|
|
|
77
77
|
## CLI Commands
|
|
78
78
|
|
|
79
|
+
### `archbyte login`
|
|
80
|
+
|
|
81
|
+
Sign in or create a free account. Shows an interactive provider picker (GitHub, Google, Email & Password).
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
archbyte login # interactive provider picker
|
|
85
|
+
archbyte login --github # sign in with GitHub
|
|
86
|
+
archbyte login --google # sign in with Google
|
|
87
|
+
archbyte login --email # sign in with email and password
|
|
88
|
+
archbyte login --token JWT # login with a pre-existing JWT token
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Multiple accounts are supported. If already logged in, you'll be prompted to add a different account.
|
|
92
|
+
|
|
93
|
+
### `archbyte logout`
|
|
94
|
+
|
|
95
|
+
Sign out of ArchByte.
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
archbyte logout # logout active account
|
|
99
|
+
archbyte logout user@co.com # logout specific account
|
|
100
|
+
archbyte logout --all # logout all accounts
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### `archbyte accounts`
|
|
104
|
+
|
|
105
|
+
List and manage logged-in accounts.
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
archbyte accounts # list all accounts
|
|
109
|
+
archbyte accounts switch # interactive account switcher
|
|
110
|
+
archbyte accounts switch user@co.com # switch to specific account
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### `archbyte status`
|
|
114
|
+
|
|
115
|
+
Show account status, tier, and usage.
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
archbyte status
|
|
119
|
+
```
|
|
120
|
+
|
|
79
121
|
### `archbyte init`
|
|
80
122
|
|
|
81
123
|
Scaffold an `archbyte.yaml` config and `.archbyte/` directory.
|
package/bin/archbyte.js
CHANGED
|
@@ -18,7 +18,7 @@ import { handlePatrol } from '../dist/cli/patrol.js';
|
|
|
18
18
|
import { handleWorkflow } from '../dist/cli/workflow.js';
|
|
19
19
|
import { handleAnalyze } from '../dist/cli/analyze.js';
|
|
20
20
|
import { handleConfig } from '../dist/cli/config.js';
|
|
21
|
-
import { handleLogin, handleLoginWithToken, handleLogout, handleStatus } from '../dist/cli/auth.js';
|
|
21
|
+
import { handleLogin, handleLoginWithToken, handleLogout, handleStatus, handleAccounts, handleAccountSwitch } from '../dist/cli/auth.js';
|
|
22
22
|
import { handleRun } from '../dist/cli/run.js';
|
|
23
23
|
import { handleSetup } from '../dist/cli/setup.js';
|
|
24
24
|
import { handleVersion, handleUpdate } from '../dist/cli/version.js';
|
|
@@ -32,17 +32,15 @@ const program = new Command();
|
|
|
32
32
|
|
|
33
33
|
program
|
|
34
34
|
.name('archbyte')
|
|
35
|
-
.description('ArchByte -
|
|
36
|
-
.version(PKG_VERSION)
|
|
35
|
+
.description('ArchByte - AI architecture analysis with an interactive diagram UI')
|
|
36
|
+
.version(PKG_VERSION, '-v, --version', 'Show version number')
|
|
37
37
|
.addHelpText('after', `
|
|
38
38
|
Quick start:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
4. $ archbyte run Analyze → generate → serve
|
|
39
|
+
$ archbyte login Sign in or create a free account
|
|
40
|
+
$ archbyte init Configure your model provider
|
|
41
|
+
$ archbyte run Analyze + open interactive diagram UI
|
|
43
42
|
|
|
44
43
|
https://archbyte.heartbyte.io
|
|
45
|
-
Support: archbyte@heartbyte.io
|
|
46
44
|
`);
|
|
47
45
|
|
|
48
46
|
// — Getting started —
|
|
@@ -53,11 +51,13 @@ program
|
|
|
53
51
|
.option('--token <jwt>', 'Login with a pre-existing JWT token')
|
|
54
52
|
.option('--github', 'Sign in with GitHub')
|
|
55
53
|
.option('--google', 'Sign in with Google')
|
|
54
|
+
.option('--email', 'Sign in with email and password')
|
|
56
55
|
.action(async (options) => {
|
|
57
56
|
if (options.token) {
|
|
58
57
|
await handleLoginWithToken(options.token);
|
|
59
58
|
} else {
|
|
60
|
-
|
|
59
|
+
// Explicit provider flag, or null for interactive picker
|
|
60
|
+
const provider = options.github ? 'github' : options.google ? 'google' : options.email ? 'email' : undefined;
|
|
61
61
|
await handleLogin(provider);
|
|
62
62
|
}
|
|
63
63
|
});
|
|
@@ -65,8 +65,10 @@ program
|
|
|
65
65
|
program
|
|
66
66
|
.command('logout')
|
|
67
67
|
.description('Sign out of ArchByte')
|
|
68
|
-
.
|
|
69
|
-
|
|
68
|
+
.argument('[email]', 'Logout a specific account by email')
|
|
69
|
+
.option('--all', 'Logout all accounts')
|
|
70
|
+
.action(async (email, options) => {
|
|
71
|
+
await handleLogout({ email, all: options.all });
|
|
70
72
|
});
|
|
71
73
|
|
|
72
74
|
program
|
|
@@ -169,7 +171,7 @@ program
|
|
|
169
171
|
.command('export')
|
|
170
172
|
.description('Export architecture to various formats')
|
|
171
173
|
.option('-d, --diagram <path>', 'Path to architecture JSON (default: .archbyte/architecture.json)')
|
|
172
|
-
.option('-f, --format <format>', 'Output format: mermaid, markdown, json, plantuml, dot (default: mermaid)')
|
|
174
|
+
.option('-f, --format <format>', 'Output format: mermaid, markdown, json, plantuml, dot, html [Pro] (default: mermaid)')
|
|
173
175
|
.option('-o, --output <path>', 'Write to file instead of stdout')
|
|
174
176
|
.action(async (options) => {
|
|
175
177
|
await handleExport(options);
|
|
@@ -214,14 +216,30 @@ program
|
|
|
214
216
|
await handleStatus();
|
|
215
217
|
});
|
|
216
218
|
|
|
219
|
+
const accountsCmd = program
|
|
220
|
+
.command('accounts')
|
|
221
|
+
.description('List and manage logged-in accounts')
|
|
222
|
+
.action(async () => {
|
|
223
|
+
await handleAccounts();
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
accountsCmd
|
|
227
|
+
.command('switch')
|
|
228
|
+
.description('Switch the active account')
|
|
229
|
+
.argument('[email]', 'Switch to a specific account by email')
|
|
230
|
+
.action(async (email) => {
|
|
231
|
+
await handleAccountSwitch(email);
|
|
232
|
+
});
|
|
233
|
+
|
|
217
234
|
program
|
|
218
235
|
.command('config')
|
|
219
236
|
.description('Manage ArchByte configuration (provider, API key)')
|
|
220
237
|
.argument('[action]', 'show, set, get, or path')
|
|
221
238
|
.argument('[key]', 'config key (provider, api-key, model)')
|
|
222
239
|
.argument('[value]', 'config value')
|
|
223
|
-
.
|
|
224
|
-
|
|
240
|
+
.option('--raw', 'Show unmasked values (for scripting)')
|
|
241
|
+
.action(async (action, key, value, options) => {
|
|
242
|
+
await handleConfig({ args: [action, key, value].filter(Boolean), raw: options.raw });
|
|
225
243
|
});
|
|
226
244
|
|
|
227
245
|
program
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
// Pipeline — Merger
|
|
2
2
|
// Assembles all agent outputs into a StaticAnalysisResult
|
|
3
|
+
function sanitize(s) {
|
|
4
|
+
if (!s)
|
|
5
|
+
return s;
|
|
6
|
+
return s.replace(/\u2014/g, "-").replace(/\u2013/g, "-").replace(/\u2018|\u2019/g, "'").replace(/\u201C|\u201D/g, '"');
|
|
7
|
+
}
|
|
3
8
|
/**
|
|
4
9
|
* Merge all pipeline agent outputs into a StaticAnalysisResult
|
|
5
10
|
* compatible with the existing buildAnalysisFromStatic() in cli/analyze.ts.
|
|
@@ -11,11 +16,11 @@ export function mergeAgentOutputs(ctx, componentId, serviceDesc, flowDet, connMa
|
|
|
11
16
|
for (const c of componentId.components) {
|
|
12
17
|
components.push({
|
|
13
18
|
id: c.id,
|
|
14
|
-
name: c.name,
|
|
19
|
+
name: sanitize(c.name) ?? c.name,
|
|
15
20
|
type: c.type,
|
|
16
21
|
layer: c.layer,
|
|
17
22
|
path: c.path,
|
|
18
|
-
description: c.description,
|
|
23
|
+
description: sanitize(c.description),
|
|
19
24
|
technologies: c.technologies,
|
|
20
25
|
});
|
|
21
26
|
}
|
|
@@ -46,7 +51,7 @@ export function mergeAgentOutputs(ctx, componentId, serviceDesc, flowDet, connMa
|
|
|
46
51
|
type: "database",
|
|
47
52
|
layer: "data",
|
|
48
53
|
path: "",
|
|
49
|
-
description: db.description,
|
|
54
|
+
description: sanitize(db.description),
|
|
50
55
|
technologies: [db.type],
|
|
51
56
|
});
|
|
52
57
|
componentIds.add(db.id);
|
|
@@ -59,11 +64,11 @@ export function mergeAgentOutputs(ctx, componentId, serviceDesc, flowDet, connMa
|
|
|
59
64
|
if (!componentIds.has(svc.id)) {
|
|
60
65
|
components.push({
|
|
61
66
|
id: svc.id,
|
|
62
|
-
name: svc.name,
|
|
67
|
+
name: sanitize(svc.name) ?? svc.name,
|
|
63
68
|
type: "service",
|
|
64
69
|
layer: "external",
|
|
65
70
|
path: "",
|
|
66
|
-
description: svc.description,
|
|
71
|
+
description: sanitize(svc.description),
|
|
67
72
|
technologies: [svc.type],
|
|
68
73
|
});
|
|
69
74
|
componentIds.add(svc.id);
|
|
@@ -96,7 +101,7 @@ export function mergeAgentOutputs(ctx, componentId, serviceDesc, flowDet, connMa
|
|
|
96
101
|
// Apply validator description improvements
|
|
97
102
|
if (validatorOut?.componentDescriptions) {
|
|
98
103
|
for (const comp of components) {
|
|
99
|
-
const better = validatorOut.componentDescriptions[comp.id];
|
|
104
|
+
const better = sanitize(validatorOut.componentDescriptions[comp.id]);
|
|
100
105
|
if (better && better.length > (comp.description?.length ?? 0)) {
|
|
101
106
|
comp.description = better;
|
|
102
107
|
}
|
|
@@ -118,7 +123,7 @@ export function mergeAgentOutputs(ctx, componentId, serviceDesc, flowDet, connMa
|
|
|
118
123
|
from: c.from,
|
|
119
124
|
to: c.to,
|
|
120
125
|
type: c.type,
|
|
121
|
-
description: c.description,
|
|
126
|
+
description: sanitize(c.description),
|
|
122
127
|
confidence: 80,
|
|
123
128
|
async: c.async,
|
|
124
129
|
});
|
|
@@ -198,7 +203,7 @@ export function mergeAgentOutputs(ctx, componentId, serviceDesc, flowDet, connMa
|
|
|
198
203
|
from: c.from,
|
|
199
204
|
to: c.to,
|
|
200
205
|
type: c.type,
|
|
201
|
-
description: c.description,
|
|
206
|
+
description: sanitize(c.description),
|
|
202
207
|
confidence: 65,
|
|
203
208
|
async: c.async,
|
|
204
209
|
});
|
|
@@ -247,7 +252,7 @@ export function mergeAgentOutputs(ctx, componentId, serviceDesc, flowDet, connMa
|
|
|
247
252
|
// Override docs from service-describer
|
|
248
253
|
const docs = { ...ctx.docs };
|
|
249
254
|
if (serviceDesc?.projectDescription && serviceDesc.projectDescription.length > (docs.projectDescription?.length ?? 0)) {
|
|
250
|
-
docs.projectDescription = serviceDesc.projectDescription;
|
|
255
|
+
docs.projectDescription = sanitize(serviceDesc.projectDescription);
|
|
251
256
|
}
|
|
252
257
|
return {
|
|
253
258
|
structure,
|
|
@@ -259,8 +264,8 @@ export function mergeAgentOutputs(ctx, componentId, serviceDesc, flowDet, connMa
|
|
|
259
264
|
connections: {
|
|
260
265
|
connections: filteredConnections,
|
|
261
266
|
flows: flows.map((f) => ({
|
|
262
|
-
name: f.name,
|
|
263
|
-
description: f.description,
|
|
267
|
+
name: sanitize(f.name) ?? f.name,
|
|
268
|
+
description: sanitize(f.description),
|
|
264
269
|
category: f.category,
|
|
265
270
|
steps: f.steps,
|
|
266
271
|
})),
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { LLMProvider, ChatParams, LLMResponse, LLMChunk } from "../runtime/types.js";
|
|
2
|
+
export declare class ClaudeSdkProvider implements LLMProvider {
|
|
3
|
+
name: "claude-sdk";
|
|
4
|
+
chat(params: ChatParams): Promise<LLMResponse>;
|
|
5
|
+
stream(params: ChatParams): AsyncIterable<LLMChunk>;
|
|
6
|
+
private extractPrompt;
|
|
7
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export class ClaudeSdkProvider {
|
|
2
|
+
name = "claude-sdk";
|
|
3
|
+
async chat(params) {
|
|
4
|
+
const { query } = await import("@anthropic-ai/claude-agent-sdk");
|
|
5
|
+
const prompt = this.extractPrompt(params.messages);
|
|
6
|
+
const result = query({
|
|
7
|
+
prompt,
|
|
8
|
+
options: {
|
|
9
|
+
systemPrompt: params.system,
|
|
10
|
+
allowedTools: [],
|
|
11
|
+
maxTurns: 1,
|
|
12
|
+
...(params.model ? { model: params.model } : {}),
|
|
13
|
+
permissionMode: "bypassPermissions",
|
|
14
|
+
allowDangerouslySkipPermissions: true,
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
let resultText = "";
|
|
18
|
+
let usage = { inputTokens: 0, outputTokens: 0 };
|
|
19
|
+
for await (const message of result) {
|
|
20
|
+
if (message.type === "result") {
|
|
21
|
+
if (message.subtype === "success") {
|
|
22
|
+
resultText = message.result;
|
|
23
|
+
}
|
|
24
|
+
usage = {
|
|
25
|
+
inputTokens: message.usage.input_tokens ?? 0,
|
|
26
|
+
outputTokens: message.usage.output_tokens ?? 0,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
content: [{ type: "text", text: resultText }],
|
|
32
|
+
stopReason: "end_turn",
|
|
33
|
+
usage,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
async *stream(params) {
|
|
37
|
+
// Pipeline agents don't use streaming — delegate to chat()
|
|
38
|
+
const response = await this.chat(params);
|
|
39
|
+
const text = response.content.find((b) => b.type === "text")?.text ?? "";
|
|
40
|
+
if (text) {
|
|
41
|
+
yield { type: "text", text };
|
|
42
|
+
}
|
|
43
|
+
yield { type: "done" };
|
|
44
|
+
}
|
|
45
|
+
extractPrompt(messages) {
|
|
46
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
47
|
+
if (messages[i].role === "user") {
|
|
48
|
+
const content = messages[i].content;
|
|
49
|
+
if (typeof content === "string")
|
|
50
|
+
return content;
|
|
51
|
+
return content
|
|
52
|
+
.filter((b) => b.type === "text")
|
|
53
|
+
.map((b) => b.text ?? "")
|
|
54
|
+
.join("\n");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return "";
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import type { LLMProvider, ArchByteConfig } from "../runtime/types.js";
|
|
2
2
|
export declare function createProvider(config: ArchByteConfig): LLMProvider;
|
|
3
|
+
/**
|
|
4
|
+
* Check if Claude Code CLI is available on PATH.
|
|
5
|
+
*/
|
|
6
|
+
export declare function isClaudeCodeAvailable(): boolean;
|
|
3
7
|
/**
|
|
4
8
|
* Auto-detect provider from environment variables.
|
|
5
9
|
* Checks in order: ARCHBYTE_PROVIDER, then falls back to whichever API key is set.
|
|
10
|
+
* Last resort: Claude Code on PATH → claude-sdk (zero config).
|
|
6
11
|
*/
|
|
7
12
|
export declare function detectConfig(): ArchByteConfig | null;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
1
2
|
import { AnthropicProvider } from "./anthropic.js";
|
|
2
3
|
import { OpenAIProvider } from "./openai.js";
|
|
3
4
|
import { GoogleProvider } from "./google.js";
|
|
5
|
+
import { ClaudeSdkProvider } from "./claude-sdk.js";
|
|
4
6
|
export function createProvider(config) {
|
|
5
7
|
switch (config.provider) {
|
|
6
8
|
case "anthropic":
|
|
@@ -9,13 +11,29 @@ export function createProvider(config) {
|
|
|
9
11
|
return new OpenAIProvider(config.apiKey);
|
|
10
12
|
case "google":
|
|
11
13
|
return new GoogleProvider(config.apiKey);
|
|
14
|
+
case "claude-sdk":
|
|
15
|
+
return new ClaudeSdkProvider();
|
|
12
16
|
default:
|
|
13
17
|
throw new Error(`Unknown provider: ${config.provider}`);
|
|
14
18
|
}
|
|
15
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Check if Claude Code CLI is available on PATH.
|
|
22
|
+
*/
|
|
23
|
+
export function isClaudeCodeAvailable() {
|
|
24
|
+
try {
|
|
25
|
+
const cmd = process.platform === "win32" ? "where claude" : "which claude";
|
|
26
|
+
execSync(cmd, { stdio: "pipe" });
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
16
33
|
/**
|
|
17
34
|
* Auto-detect provider from environment variables.
|
|
18
35
|
* Checks in order: ARCHBYTE_PROVIDER, then falls back to whichever API key is set.
|
|
36
|
+
* Last resort: Claude Code on PATH → claude-sdk (zero config).
|
|
19
37
|
*/
|
|
20
38
|
export function detectConfig() {
|
|
21
39
|
const explicit = process.env.ARCHBYTE_PROVIDER;
|
|
@@ -23,7 +41,11 @@ export function detectConfig() {
|
|
|
23
41
|
if (explicit && apiKey) {
|
|
24
42
|
return { provider: explicit, apiKey };
|
|
25
43
|
}
|
|
26
|
-
//
|
|
44
|
+
// Claude Code on PATH → zero-config, preferred
|
|
45
|
+
if (isClaudeCodeAvailable()) {
|
|
46
|
+
return { provider: "claude-sdk" };
|
|
47
|
+
}
|
|
48
|
+
// Fall back to API key env vars
|
|
27
49
|
if (process.env.ANTHROPIC_API_KEY) {
|
|
28
50
|
return { provider: "anthropic", apiKey: process.env.ANTHROPIC_API_KEY };
|
|
29
51
|
}
|
|
@@ -97,14 +97,14 @@ export interface License {
|
|
|
97
97
|
expiresAt: string;
|
|
98
98
|
isValid: boolean;
|
|
99
99
|
}
|
|
100
|
-
export type ProviderName = "anthropic" | "openai" | "google";
|
|
100
|
+
export type ProviderName = "anthropic" | "openai" | "google" | "claude-sdk";
|
|
101
101
|
export interface ProviderProfile {
|
|
102
102
|
apiKey?: string;
|
|
103
103
|
model?: string;
|
|
104
104
|
}
|
|
105
105
|
export interface ArchByteConfig {
|
|
106
106
|
provider: ProviderName;
|
|
107
|
-
apiKey
|
|
107
|
+
apiKey?: string;
|
|
108
108
|
model?: string;
|
|
109
109
|
modelOverrides?: Partial<Record<ModelTier, string>>;
|
|
110
110
|
profiles?: Record<string, ProviderProfile>;
|
package/dist/cli/analyze.js
CHANGED
|
@@ -72,7 +72,7 @@ export async function handleAnalyze(options) {
|
|
|
72
72
|
if (options.provider) {
|
|
73
73
|
config = {
|
|
74
74
|
provider: options.provider,
|
|
75
|
-
apiKey: options.apiKey ?? config?.apiKey ?? "",
|
|
75
|
+
...(options.provider !== "claude-sdk" ? { apiKey: options.apiKey ?? config?.apiKey ?? "" } : {}),
|
|
76
76
|
};
|
|
77
77
|
}
|
|
78
78
|
if (options.apiKey && config) {
|
|
@@ -81,7 +81,10 @@ export async function handleAnalyze(options) {
|
|
|
81
81
|
if (!config) {
|
|
82
82
|
console.error(chalk.red("No model provider configured."));
|
|
83
83
|
console.error();
|
|
84
|
-
console.error(chalk.bold("
|
|
84
|
+
console.error(chalk.bold("Zero-config (Claude Code users):"));
|
|
85
|
+
console.error(chalk.gray(" Install Claude Code → archbyte analyze just works"));
|
|
86
|
+
console.error();
|
|
87
|
+
console.error(chalk.bold("Or set up with:"));
|
|
85
88
|
console.error(chalk.gray(" archbyte config set provider anthropic"));
|
|
86
89
|
console.error(chalk.gray(" archbyte config set api-key sk-ant-..."));
|
|
87
90
|
console.error();
|
|
@@ -93,10 +96,11 @@ export async function handleAnalyze(options) {
|
|
|
93
96
|
console.error(chalk.gray(" archbyte analyze --static"));
|
|
94
97
|
console.error();
|
|
95
98
|
console.error(chalk.bold("Supported providers:"));
|
|
96
|
-
console.error(chalk.gray(" anthropic, openai, google"));
|
|
99
|
+
console.error(chalk.gray(" anthropic, openai, google, claude-sdk"));
|
|
97
100
|
process.exit(1);
|
|
98
101
|
}
|
|
99
|
-
|
|
102
|
+
const providerLabel = config.provider === "claude-sdk" ? "Claude Code (SDK)" : config.provider;
|
|
103
|
+
console.log(chalk.gray(`Provider: ${chalk.white(providerLabel)}`));
|
|
100
104
|
console.log(chalk.gray(`Project: ${chalk.white(path.basename(rootDir))}`));
|
|
101
105
|
console.log();
|
|
102
106
|
// 2. Create provider
|
package/dist/cli/auth.d.ts
CHANGED
|
@@ -5,10 +5,16 @@ interface Credentials {
|
|
|
5
5
|
expiresAt: string;
|
|
6
6
|
}
|
|
7
7
|
export type OAuthProvider = "github" | "google";
|
|
8
|
-
export
|
|
8
|
+
export type LoginProvider = OAuthProvider | "email";
|
|
9
|
+
export declare function handleLogin(provider?: LoginProvider): Promise<void>;
|
|
9
10
|
export declare function handleLoginWithToken(token: string): Promise<void>;
|
|
10
|
-
export declare function handleLogout(
|
|
11
|
+
export declare function handleLogout(options?: {
|
|
12
|
+
all?: boolean;
|
|
13
|
+
email?: string;
|
|
14
|
+
}): Promise<void>;
|
|
11
15
|
export declare function handleStatus(): Promise<void>;
|
|
16
|
+
export declare function handleAccounts(): Promise<void>;
|
|
17
|
+
export declare function handleAccountSwitch(email?: string): Promise<void>;
|
|
12
18
|
export declare function loadCredentials(): Credentials | null;
|
|
13
19
|
/**
|
|
14
20
|
* Get the tier from the JWT token payload. NEVER falls back to the
|
|
@@ -34,6 +40,9 @@ export declare function getVerifiedTier(): "free" | "premium";
|
|
|
34
40
|
/**
|
|
35
41
|
* Check if an offline action is allowed. Returns true if within limits.
|
|
36
42
|
* Increments the counter when allowed.
|
|
43
|
+
*
|
|
44
|
+
* Uses atomic write-to-temp-then-rename to prevent race conditions
|
|
45
|
+
* between concurrent CLI invocations.
|
|
37
46
|
*/
|
|
38
47
|
export declare function checkOfflineAction(): {
|
|
39
48
|
allowed: boolean;
|