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
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if a command exists in the system PATH.
|
|
3
|
+
* Uses `which` (Unix) or `where` (Windows).
|
|
4
|
+
*/
|
|
5
|
+
export declare function isInPath(cmd: string): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Mask an API key for safe display.
|
|
8
|
+
* Shows first 6 + last 4 characters: `sk-ant-...7x9z`
|
|
9
|
+
*/
|
|
10
|
+
export declare function maskKey(key: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Whether stdin/stdout support interactive terminal features.
|
|
13
|
+
*/
|
|
14
|
+
export declare function isTTY(): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Resolve the user's home directory, or throw if unresolvable.
|
|
17
|
+
* Prefers $HOME (Unix), falls back to $USERPROFILE (Windows).
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveHome(): string;
|
|
20
|
+
/**
|
|
21
|
+
* Basic email format check. Not exhaustive — just catches obvious typos.
|
|
22
|
+
*/
|
|
23
|
+
export declare function isValidEmail(email: string): boolean;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Shared CLI utilities.
|
|
2
|
+
// Single source of truth for helpers used across multiple CLI modules.
|
|
3
|
+
import { execSync } from "child_process";
|
|
4
|
+
/**
|
|
5
|
+
* Check if a command exists in the system PATH.
|
|
6
|
+
* Uses `which` (Unix) or `where` (Windows).
|
|
7
|
+
*/
|
|
8
|
+
export function isInPath(cmd) {
|
|
9
|
+
try {
|
|
10
|
+
// Only allow simple command names (no spaces, slashes, or shell metacharacters)
|
|
11
|
+
if (!/^[a-zA-Z0-9._-]+$/.test(cmd))
|
|
12
|
+
return false;
|
|
13
|
+
const which = process.platform === "win32" ? "where" : "which";
|
|
14
|
+
execSync(`${which} ${cmd}`, { stdio: "ignore" });
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Mask an API key for safe display.
|
|
23
|
+
* Shows first 6 + last 4 characters: `sk-ant-...7x9z`
|
|
24
|
+
*/
|
|
25
|
+
export function maskKey(key) {
|
|
26
|
+
if (key.length <= 10)
|
|
27
|
+
return "****";
|
|
28
|
+
return key.slice(0, 6) + "..." + key.slice(-4);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Whether stdin/stdout support interactive terminal features.
|
|
32
|
+
*/
|
|
33
|
+
export function isTTY() {
|
|
34
|
+
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Resolve the user's home directory, or throw if unresolvable.
|
|
38
|
+
* Prefers $HOME (Unix), falls back to $USERPROFILE (Windows).
|
|
39
|
+
*/
|
|
40
|
+
export function resolveHome() {
|
|
41
|
+
const home = process.env.HOME ?? process.env.USERPROFILE;
|
|
42
|
+
if (!home) {
|
|
43
|
+
throw new Error("Cannot determine home directory. Set the HOME environment variable.");
|
|
44
|
+
}
|
|
45
|
+
return home;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Basic email format check. Not exhaustive — just catches obvious typos.
|
|
49
|
+
*/
|
|
50
|
+
export function isValidEmail(email) {
|
|
51
|
+
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
|
|
52
|
+
}
|
package/dist/server/src/index.js
CHANGED
|
@@ -150,7 +150,7 @@ function createHttpServer() {
|
|
|
150
150
|
// Read current architecture file
|
|
151
151
|
const content = await readFile(config.diagramPath, "utf-8");
|
|
152
152
|
const arch = JSON.parse(content);
|
|
153
|
-
// Apply position/dimension updates
|
|
153
|
+
// Apply position/dimension updates only to moved nodes
|
|
154
154
|
for (const update of updates) {
|
|
155
155
|
const node = arch.nodes.find((n) => n.id === update.id);
|
|
156
156
|
if (node) {
|
|
@@ -158,10 +158,9 @@ function createHttpServer() {
|
|
|
158
158
|
node.y = update.y;
|
|
159
159
|
node.width = update.width;
|
|
160
160
|
node.height = update.height;
|
|
161
|
+
node.userPositioned = true;
|
|
161
162
|
}
|
|
162
163
|
}
|
|
163
|
-
// Mark layout as user-saved so UI uses these positions
|
|
164
|
-
arch.layoutSaved = true;
|
|
165
164
|
// Write back
|
|
166
165
|
await writeFile(config.diagramPath, JSON.stringify(arch, null, 2), "utf-8");
|
|
167
166
|
currentArchitecture = arch;
|
|
@@ -380,12 +379,21 @@ function createHttpServer() {
|
|
|
380
379
|
}
|
|
381
380
|
const params = new URL(url, `http://localhost:${config.port}`).searchParams;
|
|
382
381
|
const format = params.get("format") || "mermaid";
|
|
383
|
-
const supported = ["mermaid", "markdown", "json", "plantuml", "dot"];
|
|
382
|
+
const supported = ["mermaid", "markdown", "json", "plantuml", "dot", "html"];
|
|
384
383
|
if (!supported.includes(format)) {
|
|
385
384
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
386
385
|
res.end(JSON.stringify({ error: `Unknown format: ${format}. Supported: ${supported.join(", ")}` }));
|
|
387
386
|
return;
|
|
388
387
|
}
|
|
388
|
+
// HTML export requires Pro tier
|
|
389
|
+
if (format === "html") {
|
|
390
|
+
const license = loadLicenseInfo();
|
|
391
|
+
if (license.tier !== "premium") {
|
|
392
|
+
res.writeHead(403, { "Content-Type": "application/json" });
|
|
393
|
+
res.end(JSON.stringify({ error: "HTML export requires a Pro subscription." }));
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
389
397
|
const realNodes = arch.nodes;
|
|
390
398
|
const nodeMap = new Map();
|
|
391
399
|
for (const nd of realNodes)
|
|
@@ -516,6 +524,43 @@ function createHttpServer() {
|
|
|
516
524
|
ext = "json";
|
|
517
525
|
break;
|
|
518
526
|
}
|
|
527
|
+
case "html": {
|
|
528
|
+
// Build self-contained interactive HTML file
|
|
529
|
+
const uiAssetsDir = path.join(UI_DIST, "assets");
|
|
530
|
+
if (!existsSync(uiAssetsDir)) {
|
|
531
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
532
|
+
res.end(JSON.stringify({ error: "UI build not found. Run: npm run build:ui" }));
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
const { readdirSync } = await import("fs");
|
|
536
|
+
const uiAssetFiles = readdirSync(uiAssetsDir);
|
|
537
|
+
let cssInline = "";
|
|
538
|
+
for (const f of uiAssetFiles.filter((f) => f.endsWith(".css"))) {
|
|
539
|
+
cssInline += readFileSync(path.join(uiAssetsDir, f), "utf-8") + "\n";
|
|
540
|
+
}
|
|
541
|
+
let jsInline = "";
|
|
542
|
+
for (const f of uiAssetFiles.filter((f) => f.endsWith(".js"))) {
|
|
543
|
+
jsInline += readFileSync(path.join(uiAssetsDir, f), "utf-8") + "\n";
|
|
544
|
+
}
|
|
545
|
+
content = `<!DOCTYPE html>
|
|
546
|
+
<html lang="en" data-theme="dark">
|
|
547
|
+
<head>
|
|
548
|
+
<meta charset="UTF-8">
|
|
549
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
550
|
+
<title>${config.name} - ArchByte Architecture</title>
|
|
551
|
+
<style>${cssInline}</style>
|
|
552
|
+
</head>
|
|
553
|
+
<body>
|
|
554
|
+
<script>try{if(localStorage.getItem('archbyte-theme')==='light')document.documentElement.setAttribute('data-theme','light')}catch(e){}</script>
|
|
555
|
+
<div id="root"></div>
|
|
556
|
+
<script>window.__ARCHBYTE_DATA__ = ${JSON.stringify(arch)};</script>
|
|
557
|
+
<script type="module">${jsInline}</script>
|
|
558
|
+
</body>
|
|
559
|
+
</html>`;
|
|
560
|
+
contentType = "text/html";
|
|
561
|
+
ext = "html";
|
|
562
|
+
break;
|
|
563
|
+
}
|
|
519
564
|
default: { // markdown
|
|
520
565
|
const lines = [`# Architecture — ${config.name}`, "", `> Generated by ArchByte on ${new Date().toISOString().slice(0, 10)}`, ""];
|
|
521
566
|
lines.push("## Summary", "");
|
|
@@ -726,6 +771,7 @@ function createHttpServer() {
|
|
|
726
771
|
node.width = update.width;
|
|
727
772
|
if (update.height)
|
|
728
773
|
node.height = update.height;
|
|
774
|
+
node.userPositioned = true;
|
|
729
775
|
}
|
|
730
776
|
}
|
|
731
777
|
// Update timestamp
|
|
@@ -1343,7 +1389,15 @@ function loadLicenseInfo() {
|
|
|
1343
1389
|
const credPath = path.join(home, ".archbyte", "credentials.json");
|
|
1344
1390
|
if (!existsSync(credPath))
|
|
1345
1391
|
return defaults;
|
|
1346
|
-
const
|
|
1392
|
+
const raw = JSON.parse(readFileSync(credPath, "utf-8"));
|
|
1393
|
+
// Multi-account format (version 2): extract active account
|
|
1394
|
+
let creds;
|
|
1395
|
+
if (raw?.version === 2 && raw.accounts && typeof raw.active === "string") {
|
|
1396
|
+
creds = raw.accounts[raw.active] ?? {};
|
|
1397
|
+
}
|
|
1398
|
+
else {
|
|
1399
|
+
creds = raw;
|
|
1400
|
+
}
|
|
1347
1401
|
if (!creds.token)
|
|
1348
1402
|
return defaults;
|
|
1349
1403
|
// Check expiry
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "archbyte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "ArchByte - See what agents build. As they build it.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -45,6 +45,9 @@
|
|
|
45
45
|
"openai": "^6.19.0",
|
|
46
46
|
"zod": "^4.3.6"
|
|
47
47
|
},
|
|
48
|
+
"optionalDependencies": {
|
|
49
|
+
"@anthropic-ai/claude-agent-sdk": "^0.1.77"
|
|
50
|
+
},
|
|
48
51
|
"devDependencies": {
|
|
49
52
|
"@types/js-yaml": "^4.0.9",
|
|
50
53
|
"@types/node": "^20.0.0",
|