archbyte 0.2.8 → 0.3.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/dist/agents/pipeline/agents/component-identifier.js +67 -8
- package/dist/agents/pipeline/agents/connection-mapper.js +33 -8
- package/dist/agents/pipeline/agents/flow-detector.js +61 -8
- package/dist/agents/pipeline/agents/service-describer.js +36 -8
- package/dist/agents/pipeline/agents/validator.js +38 -9
- package/dist/agents/pipeline/index.d.ts +1 -0
- package/dist/agents/pipeline/index.js +123 -7
- package/dist/agents/pipeline/types.d.ts +11 -0
- package/dist/agents/providers/openai.js +6 -6
- package/dist/agents/runtime/types.js +2 -2
- package/dist/cli/analyze.js +68 -23
- package/dist/cli/auth.js +2 -2
- package/dist/cli/incremental.d.ts +21 -0
- package/dist/cli/incremental.js +117 -1
- package/dist/cli/serve.js +89 -13
- package/dist/cli/setup.js +119 -28
- package/dist/cli/yaml-io.d.ts +2 -0
- package/package.json +1 -1
package/dist/cli/setup.js
CHANGED
|
@@ -11,21 +11,20 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
11
11
|
const __dirname = path.dirname(__filename);
|
|
12
12
|
const PROVIDERS = [
|
|
13
13
|
{ name: "anthropic", label: "Anthropic", hint: "Claude Sonnet / Opus" },
|
|
14
|
-
{ name: "openai", label: "OpenAI", hint: "
|
|
14
|
+
{ name: "openai", label: "OpenAI", hint: "GPT-5.2 / o4-mini" },
|
|
15
15
|
{ name: "google", label: "Google", hint: "Gemini Flash / Pro" },
|
|
16
16
|
];
|
|
17
17
|
const PROVIDER_MODELS = {
|
|
18
18
|
anthropic: [
|
|
19
|
-
{ id: "", label: "Default (recommended)", hint: "
|
|
19
|
+
{ id: "", label: "Default (recommended)", hint: "Opus for all agents" },
|
|
20
20
|
{ id: "claude-haiku-4-5-20251001", label: "Claude Haiku 4.5", hint: "Fastest, cheapest" },
|
|
21
21
|
{ id: "claude-sonnet-4-5-20250929", label: "Claude Sonnet 4.5", hint: "Balanced, great quality" },
|
|
22
22
|
{ id: "claude-opus-4-6", label: "Claude Opus 4.6", hint: "Most capable" },
|
|
23
23
|
],
|
|
24
24
|
openai: [
|
|
25
|
-
{ id: "", label: "Default (recommended)", hint: "
|
|
26
|
-
{ id: "gpt-5.2
|
|
27
|
-
{ id: "
|
|
28
|
-
{ id: "o3", label: "o3", hint: "Reasoning model" },
|
|
25
|
+
{ id: "", label: "Default (recommended)", hint: "GPT-5.2 for all agents" },
|
|
26
|
+
{ id: "gpt-5.2", label: "GPT-5.2", hint: "Latest flagship model" },
|
|
27
|
+
{ id: "o4-mini", label: "o4-mini", hint: "Fast reasoning model" },
|
|
29
28
|
],
|
|
30
29
|
google: [
|
|
31
30
|
{ id: "", label: "Default (recommended)", hint: "Flash for fast agents, Pro for connections" },
|
|
@@ -93,10 +92,47 @@ function askHidden(prompt) {
|
|
|
93
92
|
stdin.on("data", onData);
|
|
94
93
|
});
|
|
95
94
|
}
|
|
96
|
-
|
|
95
|
+
function askText(prompt) {
|
|
96
|
+
return new Promise((resolve) => {
|
|
97
|
+
process.stdout.write(prompt);
|
|
98
|
+
const stdin = process.stdin;
|
|
99
|
+
const wasRaw = stdin.isRaw;
|
|
100
|
+
stdin.setRawMode(true);
|
|
101
|
+
stdin.resume();
|
|
102
|
+
stdin.setEncoding("utf8");
|
|
103
|
+
let input = "";
|
|
104
|
+
const onData = (data) => {
|
|
105
|
+
for (const ch of data) {
|
|
106
|
+
if (ch === "\n" || ch === "\r" || ch === "\u0004") {
|
|
107
|
+
stdin.setRawMode(wasRaw ?? false);
|
|
108
|
+
stdin.pause();
|
|
109
|
+
stdin.removeListener("data", onData);
|
|
110
|
+
process.stdout.write("\n");
|
|
111
|
+
resolve(input);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
else if (ch === "\u0003") {
|
|
115
|
+
process.stdout.write("\n");
|
|
116
|
+
process.exit(0);
|
|
117
|
+
}
|
|
118
|
+
else if (ch === "\u007F" || ch === "\b") {
|
|
119
|
+
if (input.length > 0) {
|
|
120
|
+
input = input.slice(0, -1);
|
|
121
|
+
process.stdout.write("\b \b");
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
input += ch;
|
|
126
|
+
process.stdout.write(ch);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
stdin.on("data", onData);
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
async function validateProviderSilent(providerName, apiKey, model) {
|
|
97
134
|
try {
|
|
98
135
|
const provider = createProvider({ provider: providerName, apiKey });
|
|
99
|
-
const model = resolveModel(providerName, "fast");
|
|
100
136
|
await provider.chat({
|
|
101
137
|
model,
|
|
102
138
|
system: "Reply with 'ok'.",
|
|
@@ -105,7 +141,11 @@ async function validateProviderSilent(providerName, apiKey) {
|
|
|
105
141
|
});
|
|
106
142
|
return true;
|
|
107
143
|
}
|
|
108
|
-
catch {
|
|
144
|
+
catch (err) {
|
|
145
|
+
if (process.env.ARCHBYTE_DEBUG) {
|
|
146
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
147
|
+
console.log(chalk.red(`\n Validation error: ${msg}`));
|
|
148
|
+
}
|
|
109
149
|
return false;
|
|
110
150
|
}
|
|
111
151
|
}
|
|
@@ -163,7 +203,8 @@ export async function handleSetup() {
|
|
|
163
203
|
for (const p of configured) {
|
|
164
204
|
const active = p === config.provider ? chalk.green(" (active)") : "";
|
|
165
205
|
const model = profiles[p].model ? chalk.gray(` model: ${profiles[p].model}`) : "";
|
|
166
|
-
|
|
206
|
+
const email = profiles[p].email ? chalk.gray(` (${profiles[p].email})`) : "";
|
|
207
|
+
console.log(chalk.gray(` ${p}: ${maskKey(profiles[p].apiKey)}${email}${model}${active}`));
|
|
167
208
|
}
|
|
168
209
|
console.log();
|
|
169
210
|
}
|
|
@@ -213,6 +254,30 @@ export async function handleSetup() {
|
|
|
213
254
|
if (!profiles[provider])
|
|
214
255
|
profiles[provider] = { apiKey: "" };
|
|
215
256
|
profiles[provider].apiKey = apiKey;
|
|
257
|
+
// Step 2b: Email for this provider account (optional)
|
|
258
|
+
const existingEmail = profiles[provider].email;
|
|
259
|
+
if (existingEmail) {
|
|
260
|
+
console.log(chalk.gray(`\n Account email: ${existingEmail}`));
|
|
261
|
+
const emailIdx = await select(" Update email?", [
|
|
262
|
+
`Keep existing ${chalk.gray("(" + existingEmail + ")")}`,
|
|
263
|
+
"Enter new email",
|
|
264
|
+
"Skip",
|
|
265
|
+
]);
|
|
266
|
+
if (emailIdx === 1) {
|
|
267
|
+
const newEmail = await askText(chalk.bold(" Email: "));
|
|
268
|
+
if (newEmail) {
|
|
269
|
+
profiles[provider].email = newEmail;
|
|
270
|
+
console.log(chalk.green(` ✓ Email: ${newEmail}`));
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
const email = await askText(chalk.bold(` ${selected.label} account email ${chalk.gray("(optional, Enter to skip)")}: `));
|
|
276
|
+
if (email) {
|
|
277
|
+
profiles[provider].email = email;
|
|
278
|
+
console.log(chalk.green(` ✓ Email: ${email}`));
|
|
279
|
+
}
|
|
280
|
+
}
|
|
216
281
|
// Step 3: Model selection
|
|
217
282
|
const models = PROVIDER_MODELS[provider];
|
|
218
283
|
if (models) {
|
|
@@ -227,14 +292,24 @@ export async function handleSetup() {
|
|
|
227
292
|
console.log(chalk.green(` ✓ Model: ${chosen.label}`));
|
|
228
293
|
}
|
|
229
294
|
else {
|
|
230
|
-
|
|
231
|
-
|
|
295
|
+
// Save the actual default model so config is explicit
|
|
296
|
+
const defaultModels = {
|
|
297
|
+
anthropic: "claude-opus-4-6",
|
|
298
|
+
openai: "gpt-5.2",
|
|
299
|
+
google: "gemini-2.5-pro",
|
|
300
|
+
ollama: "qwen2.5-coder",
|
|
301
|
+
};
|
|
302
|
+
const defaultModel = defaultModels[provider] ?? resolveModel(provider, "standard");
|
|
303
|
+
profiles[provider].model = defaultModel;
|
|
304
|
+
console.log(chalk.green(` ✓ Model: ${defaultModel} (default)`));
|
|
232
305
|
}
|
|
233
306
|
}
|
|
234
307
|
config.profiles = profiles;
|
|
308
|
+
// Validate with the model the user actually chose
|
|
309
|
+
const validationModel = profiles[provider].model ?? resolveModel(provider, "fast");
|
|
235
310
|
// Validate provider with spinner
|
|
236
|
-
const s = spinner(
|
|
237
|
-
let isValid = await validateProviderSilent(provider, apiKey);
|
|
311
|
+
const s = spinner(`Validating credentials with ${validationModel}`);
|
|
312
|
+
let isValid = await validateProviderSilent(provider, apiKey, validationModel);
|
|
238
313
|
s.stop(isValid ? "valid" : "invalid", isValid ? "green" : "red");
|
|
239
314
|
// Retry loop on failure
|
|
240
315
|
if (!isValid) {
|
|
@@ -248,8 +323,8 @@ export async function handleSetup() {
|
|
|
248
323
|
profiles[provider].apiKey = newKey;
|
|
249
324
|
console.log(chalk.green(` ✓ API key: ${maskKey(newKey)}`));
|
|
250
325
|
}
|
|
251
|
-
const s2 = spinner(
|
|
252
|
-
isValid = await validateProviderSilent(provider, profiles[provider].apiKey);
|
|
326
|
+
const s2 = spinner(`Validating credentials with ${validationModel}`);
|
|
327
|
+
isValid = await validateProviderSilent(provider, profiles[provider].apiKey, validationModel);
|
|
253
328
|
s2.stop(isValid ? "valid" : "invalid", isValid ? "green" : "red");
|
|
254
329
|
}
|
|
255
330
|
if (!isValid) {
|
|
@@ -262,13 +337,11 @@ export async function handleSetup() {
|
|
|
262
337
|
delete config.ollamaBaseUrl;
|
|
263
338
|
// Save config
|
|
264
339
|
saveConfig(config);
|
|
265
|
-
console.log(chalk.gray(`\n Config saved to ${CONFIG_PATH}`));
|
|
266
|
-
console.log(chalk.gray(" Your API key is stored locally on this machine and never sent to ArchByte."));
|
|
267
|
-
console.log(chalk.gray(" All model calls go directly from your machine to your provider."));
|
|
268
340
|
// Generate archbyte.yaml in .archbyte/ if it doesn't exist
|
|
269
341
|
const projectDir = process.cwd();
|
|
270
342
|
const archbyteDir = path.join(projectDir, ".archbyte");
|
|
271
343
|
const yamlPath = path.join(archbyteDir, "archbyte.yaml");
|
|
344
|
+
let yamlCreated = false;
|
|
272
345
|
if (!fs.existsSync(yamlPath)) {
|
|
273
346
|
if (!fs.existsSync(archbyteDir)) {
|
|
274
347
|
fs.mkdirSync(archbyteDir, { recursive: true });
|
|
@@ -288,21 +361,39 @@ export async function handleSetup() {
|
|
|
288
361
|
let template = fs.readFileSync(templatePath, "utf-8");
|
|
289
362
|
template = template.replace("name: my-project", `name: ${projectName}`);
|
|
290
363
|
fs.writeFileSync(yamlPath, template, "utf-8");
|
|
291
|
-
|
|
292
|
-
}
|
|
293
|
-
else {
|
|
294
|
-
console.log(chalk.gray(` .archbyte/archbyte.yaml already exists`));
|
|
364
|
+
yamlCreated = true;
|
|
295
365
|
}
|
|
296
366
|
// Generate README.md in .archbyte/
|
|
297
367
|
writeArchbyteReadme(archbyteDir);
|
|
368
|
+
// ─── Summary ───
|
|
369
|
+
const dim = chalk.gray;
|
|
370
|
+
const sep = dim(" ───");
|
|
371
|
+
console.log();
|
|
372
|
+
console.log(chalk.bold.green(" ✓ Setup complete"));
|
|
373
|
+
console.log();
|
|
374
|
+
console.log(sep);
|
|
375
|
+
console.log();
|
|
376
|
+
console.log(dim(" ~/.archbyte/") + " API keys, login, config " + dim("(global)"));
|
|
377
|
+
console.log(dim(" .archbyte/") + " Analysis, diagrams " + dim("(per project)"));
|
|
298
378
|
console.log();
|
|
299
|
-
console.log(
|
|
379
|
+
console.log(dim(" Your keys never leave this machine."));
|
|
380
|
+
console.log(dim(" All model calls go directly to your provider."));
|
|
300
381
|
console.log();
|
|
301
|
-
console.log(
|
|
302
|
-
console.log(
|
|
382
|
+
console.log(sep);
|
|
383
|
+
console.log();
|
|
384
|
+
if (yamlCreated) {
|
|
385
|
+
console.log(chalk.green(" + ") + "Created " + chalk.cyan(".archbyte/archbyte.yaml"));
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
console.log(dim(" .archbyte/archbyte.yaml already exists"));
|
|
389
|
+
}
|
|
390
|
+
console.log();
|
|
391
|
+
console.log(sep);
|
|
392
|
+
console.log();
|
|
393
|
+
console.log(" " + chalk.bold("Next"));
|
|
394
|
+
console.log(" " + chalk.cyan("archbyte run") + " Analyze your codebase");
|
|
303
395
|
if (hasClaude || hasCodex) {
|
|
304
|
-
console.log();
|
|
305
|
-
console.log(chalk.bold(" MCP: ") + chalk.cyan("archbyte mcp install") + chalk.bold(" to use ArchByte from your AI tool."));
|
|
396
|
+
console.log(" " + chalk.cyan("archbyte mcp install") + " Use from your AI tool");
|
|
306
397
|
}
|
|
307
398
|
console.log();
|
|
308
399
|
}
|
package/dist/cli/yaml-io.d.ts
CHANGED
|
@@ -71,6 +71,8 @@ export interface ScanMetadata {
|
|
|
71
71
|
};
|
|
72
72
|
validation?: unknown;
|
|
73
73
|
gaps?: unknown;
|
|
74
|
+
incrementalMode?: boolean;
|
|
75
|
+
skippedAgents?: string[];
|
|
74
76
|
}
|
|
75
77
|
export declare function loadSpec(rootDir: string): ArchbyteSpec | null;
|
|
76
78
|
export declare function writeSpec(rootDir: string, spec: ArchbyteSpec): void;
|