swarmlancer-cli 0.2.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.
Files changed (48) hide show
  1. package/README.md +15 -0
  2. package/dist/agent.d.ts +13 -0
  3. package/dist/agent.js +202 -0
  4. package/dist/app.d.ts +4 -0
  5. package/dist/app.js +496 -0
  6. package/dist/config.d.ts +49 -0
  7. package/dist/config.js +175 -0
  8. package/dist/index.d.ts +2 -0
  9. package/dist/index.js +129 -0
  10. package/dist/inference.d.ts +13 -0
  11. package/dist/inference.js +105 -0
  12. package/dist/login.d.ts +1 -0
  13. package/dist/login.js +57 -0
  14. package/dist/screening.d.ts +22 -0
  15. package/dist/screening.js +101 -0
  16. package/dist/screens/agent-config.d.ts +14 -0
  17. package/dist/screens/agent-config.js +64 -0
  18. package/dist/screens/agent-editor.d.ts +13 -0
  19. package/dist/screens/agent-editor.js +64 -0
  20. package/dist/screens/agent-list.d.ts +22 -0
  21. package/dist/screens/agent-list.js +73 -0
  22. package/dist/screens/agent-picker.d.ts +15 -0
  23. package/dist/screens/agent-picker.js +51 -0
  24. package/dist/screens/agent-running.d.ts +20 -0
  25. package/dist/screens/agent-running.js +68 -0
  26. package/dist/screens/banner.d.ts +6 -0
  27. package/dist/screens/banner.js +27 -0
  28. package/dist/screens/dashboard.d.ts +16 -0
  29. package/dist/screens/dashboard.js +59 -0
  30. package/dist/screens/discovery-settings.d.ts +17 -0
  31. package/dist/screens/discovery-settings.js +189 -0
  32. package/dist/screens/message.d.ts +15 -0
  33. package/dist/screens/message.js +39 -0
  34. package/dist/screens/model-picker.d.ts +14 -0
  35. package/dist/screens/model-picker.js +49 -0
  36. package/dist/screens/name-editor.d.ts +15 -0
  37. package/dist/screens/name-editor.js +67 -0
  38. package/dist/screens/session-goal.d.ts +13 -0
  39. package/dist/screens/session-goal.js +61 -0
  40. package/dist/screens/settings.d.ts +15 -0
  41. package/dist/screens/settings.js +126 -0
  42. package/dist/screens/setup-wizard.d.ts +20 -0
  43. package/dist/screens/setup-wizard.js +120 -0
  44. package/dist/screens/status-panel.d.ts +15 -0
  45. package/dist/screens/status-panel.js +37 -0
  46. package/dist/theme.d.ts +42 -0
  47. package/dist/theme.js +56 -0
  48. package/package.json +49 -0
@@ -0,0 +1,120 @@
1
+ import { SelectList, truncateToWidth, } from "@mariozechner/pi-tui";
2
+ import { colors, theme } from "../theme.js";
3
+ export class SetupWizardScreen {
4
+ tui;
5
+ steps;
6
+ cachedRender;
7
+ // For confirmation prompts
8
+ promptActive = false;
9
+ promptText = "";
10
+ promptList;
11
+ promptResolve;
12
+ constructor(tui) {
13
+ this.tui = tui;
14
+ this.steps = [
15
+ { label: "Authentication", status: "pending" },
16
+ { label: "Model detection", status: "pending" },
17
+ { label: "Agents", status: "pending" },
18
+ ];
19
+ }
20
+ setStep(index, status, detail) {
21
+ this.steps[index].status = status;
22
+ if (detail !== undefined)
23
+ this.steps[index].detail = detail;
24
+ this.cachedRender = undefined;
25
+ this.tui.requestRender();
26
+ }
27
+ /** Show a yes/no prompt and return the user's choice */
28
+ askConfirm(question) {
29
+ return new Promise((resolve) => {
30
+ this.promptActive = true;
31
+ this.promptText = question;
32
+ this.promptResolve = resolve;
33
+ const items = [
34
+ { value: "yes", label: "Yes" },
35
+ { value: "no", label: "Later" },
36
+ ];
37
+ this.promptList = new SelectList(items, 2, {
38
+ selectedPrefix: (t) => theme.accent(t),
39
+ selectedText: (t) => theme.accent(t),
40
+ description: (t) => colors.gray(t),
41
+ scrollInfo: (t) => colors.gray(t),
42
+ noMatch: (t) => colors.yellow(t),
43
+ });
44
+ this.promptList.onSelect = (item) => {
45
+ this.promptActive = false;
46
+ this.promptList = undefined;
47
+ this.cachedRender = undefined;
48
+ this.tui.requestRender();
49
+ resolve(item.value === "yes");
50
+ };
51
+ this.promptList.onCancel = () => {
52
+ this.promptActive = false;
53
+ this.promptList = undefined;
54
+ this.cachedRender = undefined;
55
+ this.tui.requestRender();
56
+ resolve(false);
57
+ };
58
+ this.cachedRender = undefined;
59
+ this.tui.requestRender();
60
+ });
61
+ }
62
+ handleInput(data) {
63
+ if (this.promptActive && this.promptList) {
64
+ this.promptList.handleInput(data);
65
+ this.cachedRender = undefined;
66
+ this.tui.requestRender();
67
+ }
68
+ }
69
+ render(width) {
70
+ if (this.cachedRender)
71
+ return this.cachedRender;
72
+ const lines = [];
73
+ // Steps
74
+ for (let si = 0; si < this.steps.length; si++) {
75
+ const step = this.steps[si];
76
+ let icon;
77
+ let line;
78
+ switch (step.status) {
79
+ case "pending":
80
+ icon = colors.gray("○");
81
+ line = colors.gray(step.label);
82
+ break;
83
+ case "running":
84
+ icon = colors.cyan("◉");
85
+ line = colors.cyan(step.label + "...");
86
+ break;
87
+ case "done":
88
+ icon = colors.green("✓");
89
+ line = colors.green(step.label);
90
+ break;
91
+ case "failed":
92
+ icon = colors.red("✗");
93
+ line = colors.red(step.label);
94
+ break;
95
+ case "skipped":
96
+ icon = colors.yellow("⊘");
97
+ line = colors.yellow(step.label);
98
+ break;
99
+ }
100
+ lines.push(truncateToWidth(` ${icon} ${line}`, width));
101
+ if (step.detail) {
102
+ lines.push(truncateToWidth(` ${colors.gray(step.detail)}`, width));
103
+ }
104
+ }
105
+ // Prompt
106
+ if (this.promptActive && this.promptList) {
107
+ lines.push("");
108
+ lines.push(truncateToWidth(` ${colors.bold(this.promptText)}`, width));
109
+ lines.push("");
110
+ for (const pLine of this.promptList.render(width - 2)) {
111
+ lines.push(truncateToWidth(` ${pLine}`, width));
112
+ }
113
+ }
114
+ this.cachedRender = lines;
115
+ return lines;
116
+ }
117
+ invalidate() {
118
+ this.cachedRender = undefined;
119
+ }
120
+ }
@@ -0,0 +1,15 @@
1
+ import { Container } from "@mariozechner/pi-tui";
2
+ import type { Model, Api } from "@mariozechner/pi-ai";
3
+ export interface StatusInfo {
4
+ loggedIn: boolean;
5
+ model: Model<Api> | undefined;
6
+ agentCount: number;
7
+ serverUrl: string;
8
+ }
9
+ export declare class StatusPanel extends Container {
10
+ private info;
11
+ constructor(info: StatusInfo);
12
+ update(info: Partial<StatusInfo>): void;
13
+ private rebuild;
14
+ invalidate(): void;
15
+ }
@@ -0,0 +1,37 @@
1
+ import { Container, Text } from "@mariozechner/pi-tui";
2
+ import { colors, theme } from "../theme.js";
3
+ export class StatusPanel extends Container {
4
+ info;
5
+ constructor(info) {
6
+ super();
7
+ this.info = info;
8
+ this.rebuild();
9
+ }
10
+ update(info) {
11
+ Object.assign(this.info, info);
12
+ this.rebuild();
13
+ }
14
+ rebuild() {
15
+ this.clear();
16
+ const line = (label, value, ok) => {
17
+ const icon = ok ? colors.green("✓") : colors.red("✗");
18
+ const labelStr = colors.gray(label.padEnd(10));
19
+ return ` ${icon} ${labelStr} ${value}`;
20
+ };
21
+ this.addChild(new Text(theme.border("─".repeat(50)), 0, 0));
22
+ this.addChild(new Text(line("Auth", this.info.loggedIn ? "logged in" : "not logged in", this.info.loggedIn), 0, 0));
23
+ this.addChild(new Text(line("Model", this.info.model
24
+ ? `${this.info.model.provider}/${this.info.model.id}`
25
+ : "(not detected)", !!this.info.model), 0, 0));
26
+ const agentStr = this.info.agentCount === 0
27
+ ? "none — create one in Manage agents"
28
+ : `${this.info.agentCount} agent${this.info.agentCount === 1 ? "" : "s"}`;
29
+ this.addChild(new Text(line("Agents", agentStr, this.info.agentCount > 0), 0, 0));
30
+ this.addChild(new Text(line("Server", this.info.serverUrl, true), 0, 0));
31
+ this.addChild(new Text(theme.border("─".repeat(50)), 0, 0));
32
+ }
33
+ invalidate() {
34
+ super.invalidate();
35
+ this.rebuild();
36
+ }
37
+ }
@@ -0,0 +1,42 @@
1
+ export declare const colors: {
2
+ reset: string;
3
+ bold: (s: string) => string;
4
+ dim: (s: string) => string;
5
+ italic: (s: string) => string;
6
+ cyan: (s: string) => string;
7
+ green: (s: string) => string;
8
+ red: (s: string) => string;
9
+ yellow: (s: string) => string;
10
+ magenta: (s: string) => string;
11
+ blue: (s: string) => string;
12
+ white: (s: string) => string;
13
+ gray: (s: string) => string;
14
+ brightCyan: (s: string) => string;
15
+ brightGreen: (s: string) => string;
16
+ brightYellow: (s: string) => string;
17
+ brightWhite: (s: string) => string;
18
+ lime: (s: string) => string;
19
+ limeBold: (s: string) => string;
20
+ bgLime: (s: string) => string;
21
+ bgGray: (s: string) => string;
22
+ bgCyan: (s: string) => string;
23
+ bgBlue: (s: string) => string;
24
+ inverse: (s: string) => string;
25
+ };
26
+ export declare const theme: {
27
+ accent: (s: string) => string;
28
+ success: (s: string) => string;
29
+ error: (s: string) => string;
30
+ warning: (s: string) => string;
31
+ muted: (s: string) => string;
32
+ highlight: (s: string) => string;
33
+ border: (s: string) => string;
34
+ title: (s: string) => string;
35
+ subtitle: (s: string) => string;
36
+ status: {
37
+ ok: (s: string) => string;
38
+ fail: (s: string) => string;
39
+ warn: (s: string) => string;
40
+ info: (s: string) => string;
41
+ };
42
+ };
package/dist/theme.js ADDED
@@ -0,0 +1,56 @@
1
+ // ANSI color helpers for standalone TUI (no pi theme system)
2
+ const ESC = "\x1b[";
3
+ // Logo color: #C8F135 (RGB 200, 241, 53) — lime green from the Swarmlancer logo
4
+ const LIME_FG = `${ESC}38;2;200;241;53m`;
5
+ const LIME_BG = `${ESC}48;2;200;241;53m`;
6
+ const DARK_FG = `${ESC}38;2;26;26;26m`;
7
+ const RESET = `${ESC}0m`;
8
+ export const colors = {
9
+ reset: `${ESC}0m`,
10
+ // Foreground
11
+ bold: (s) => `${ESC}1m${s}${ESC}22m`,
12
+ dim: (s) => `${ESC}2m${s}${ESC}22m`,
13
+ italic: (s) => `${ESC}3m${s}${ESC}23m`,
14
+ // Named colors
15
+ cyan: (s) => `${ESC}36m${s}${ESC}39m`,
16
+ green: (s) => `${ESC}32m${s}${ESC}39m`,
17
+ red: (s) => `${ESC}31m${s}${ESC}39m`,
18
+ yellow: (s) => `${ESC}33m${s}${ESC}39m`,
19
+ magenta: (s) => `${ESC}35m${s}${ESC}39m`,
20
+ blue: (s) => `${ESC}34m${s}${ESC}39m`,
21
+ white: (s) => `${ESC}37m${s}${ESC}39m`,
22
+ gray: (s) => `${ESC}90m${s}${ESC}39m`,
23
+ // Bright
24
+ brightCyan: (s) => `${ESC}96m${s}${ESC}39m`,
25
+ brightGreen: (s) => `${ESC}92m${s}${ESC}39m`,
26
+ brightYellow: (s) => `${ESC}93m${s}${ESC}39m`,
27
+ brightWhite: (s) => `${ESC}97m${s}${ESC}39m`,
28
+ // Logo lime green — #C8F135
29
+ lime: (s) => `${LIME_FG}${s}${ESC}39m`,
30
+ limeBold: (s) => `${LIME_FG}${ESC}1m${s}${ESC}22m${ESC}39m`,
31
+ bgLime: (s) => `${LIME_BG}${DARK_FG}${s}${RESET}`,
32
+ // Background
33
+ bgGray: (s) => `${ESC}48;5;236m${s}${ESC}49m`,
34
+ bgCyan: (s) => `${ESC}46m${s}${ESC}49m`,
35
+ bgBlue: (s) => `${ESC}44m${s}${ESC}49m`,
36
+ // Inverse
37
+ inverse: (s) => `${ESC}7m${s}${ESC}27m`,
38
+ };
39
+ // Semantic aliases — accent is now the logo lime green
40
+ export const theme = {
41
+ accent: colors.lime,
42
+ success: colors.green,
43
+ error: colors.red,
44
+ warning: colors.yellow,
45
+ muted: colors.gray,
46
+ highlight: colors.limeBold,
47
+ border: colors.lime,
48
+ title: (s) => colors.bold(colors.lime(s)),
49
+ subtitle: (s) => colors.bold(colors.white(s)),
50
+ status: {
51
+ ok: (s) => colors.green(`✓ ${s}`),
52
+ fail: (s) => colors.red(`✗ ${s}`),
53
+ warn: (s) => colors.yellow(`⚠ ${s}`),
54
+ info: (s) => colors.lime(`▸ ${s}`),
55
+ },
56
+ };
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "swarmlancer-cli",
3
+ "version": "0.2.0",
4
+ "description": "Swarmlancer CLI — let the swarm begin. Connect your AI agent to a network of other agents.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "swarmlancer": "dist/index.js"
10
+ },
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc -p tsconfig.build.json",
16
+ "prepublishOnly": "rm -rf dist && npm run build",
17
+ "start": "bun run src/index.ts start",
18
+ "dev": "bun run src/index.ts"
19
+ },
20
+ "keywords": [
21
+ "ai",
22
+ "agent",
23
+ "networking",
24
+ "cli",
25
+ "llm",
26
+ "autonomous"
27
+ ],
28
+ "author": "nevertypeit",
29
+ "license": "MIT",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/nevertypeit/swarmlancer-cli"
33
+ },
34
+ "homepage": "https://swarmlancer.com",
35
+ "engines": {
36
+ "node": ">=18"
37
+ },
38
+ "devDependencies": {
39
+ "@types/node": "^25.5.0",
40
+ "@types/ws": "^8.18.1",
41
+ "typescript": "^5.8.0"
42
+ },
43
+ "dependencies": {
44
+ "@mariozechner/pi-coding-agent": "^0.58.4",
45
+ "@mariozechner/pi-tui": "^0.58.4",
46
+ "open": "^11.0.0",
47
+ "ws": "^8.19.0"
48
+ }
49
+ }