swarmlancer 0.1.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 +15 -0
- package/dist/agent.d.ts +4 -0
- package/dist/agent.js +95 -0
- package/dist/app.d.ts +4 -0
- package/dist/app.js +303 -0
- package/dist/config.d.ts +12 -0
- package/dist/config.js +61 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +110 -0
- package/dist/inference.d.ts +9 -0
- package/dist/inference.js +100 -0
- package/dist/login.d.ts +1 -0
- package/dist/login.js +57 -0
- package/dist/profile.d.ts +3 -0
- package/dist/profile.js +32 -0
- package/dist/screens/agent-editor.d.ts +13 -0
- package/dist/screens/agent-editor.js +64 -0
- package/dist/screens/agent-running.d.ts +17 -0
- package/dist/screens/agent-running.js +62 -0
- package/dist/screens/banner.d.ts +6 -0
- package/dist/screens/banner.js +28 -0
- package/dist/screens/dashboard.d.ts +16 -0
- package/dist/screens/dashboard.js +62 -0
- package/dist/screens/message.d.ts +15 -0
- package/dist/screens/message.js +39 -0
- package/dist/screens/model-picker.d.ts +14 -0
- package/dist/screens/model-picker.js +49 -0
- package/dist/screens/profile-editor.d.ts +16 -0
- package/dist/screens/profile-editor.js +129 -0
- package/dist/screens/profile-view.d.ts +11 -0
- package/dist/screens/profile-view.js +38 -0
- package/dist/screens/setup-wizard.d.ts +20 -0
- package/dist/screens/setup-wizard.js +120 -0
- package/dist/screens/status-panel.d.ts +15 -0
- package/dist/screens/status-panel.js +34 -0
- package/dist/theme.d.ts +39 -0
- package/dist/theme.js +47 -0
- package/package.json +49 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { Editor, matchesKey, Key, truncateToWidth, } from "@mariozechner/pi-tui";
|
|
2
|
+
import { colors, theme } from "../theme.js";
|
|
3
|
+
const EDITOR_THEME = {
|
|
4
|
+
borderColor: (s) => colors.cyan(s),
|
|
5
|
+
selectList: {
|
|
6
|
+
selectedPrefix: (t) => colors.cyan(t),
|
|
7
|
+
selectedText: (t) => colors.cyan(t),
|
|
8
|
+
description: (t) => colors.gray(t),
|
|
9
|
+
scrollInfo: (t) => colors.gray(t),
|
|
10
|
+
noMatch: (t) => colors.yellow(t),
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
export class ProfileEditorScreen {
|
|
14
|
+
tui;
|
|
15
|
+
fields;
|
|
16
|
+
editors;
|
|
17
|
+
currentField = 0;
|
|
18
|
+
cachedLines;
|
|
19
|
+
onSave;
|
|
20
|
+
onCancel;
|
|
21
|
+
constructor(tui, profile) {
|
|
22
|
+
this.tui = tui;
|
|
23
|
+
this.fields = [
|
|
24
|
+
{ key: "displayName", label: "Display name", value: profile.displayName || "" },
|
|
25
|
+
{ key: "bio", label: "Bio", value: profile.bio || "" },
|
|
26
|
+
{ key: "skills", label: "Skills", value: profile.skills || "" },
|
|
27
|
+
{ key: "projects", label: "Projects", value: profile.projects || "" },
|
|
28
|
+
{ key: "lookingFor", label: "Looking for", value: profile.lookingFor || "" },
|
|
29
|
+
];
|
|
30
|
+
this.editors = this.fields.map((f) => {
|
|
31
|
+
const editor = new Editor(tui, EDITOR_THEME, { paddingX: 1 });
|
|
32
|
+
editor.setText(f.value);
|
|
33
|
+
// Enter moves to next field (via onSubmit), Shift+Enter = new line
|
|
34
|
+
editor.disableSubmit = false;
|
|
35
|
+
return editor;
|
|
36
|
+
});
|
|
37
|
+
// Wire up Enter on each field → advance to next / save
|
|
38
|
+
this.editors.forEach((ed, i) => {
|
|
39
|
+
ed.onSubmit = () => {
|
|
40
|
+
if (i < this.fields.length - 1) {
|
|
41
|
+
this.currentField = i + 1;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
this.onSave?.(this.getResult());
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
this.cachedLines = undefined;
|
|
48
|
+
this.tui.requestRender();
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
getResult() {
|
|
53
|
+
const result = {};
|
|
54
|
+
for (let i = 0; i < this.fields.length; i++) {
|
|
55
|
+
result[this.fields[i].key] = this.editors[i].getText();
|
|
56
|
+
}
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
handleInput(data) {
|
|
60
|
+
if (matchesKey(data, Key.escape)) {
|
|
61
|
+
this.onCancel?.();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// Ctrl+S to save from anywhere
|
|
65
|
+
if (matchesKey(data, Key.ctrl("s"))) {
|
|
66
|
+
this.onSave?.(this.getResult());
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
// Tab → next field, Shift+Tab → prev field
|
|
70
|
+
if (matchesKey(data, Key.tab)) {
|
|
71
|
+
if (this.currentField < this.fields.length - 1) {
|
|
72
|
+
this.currentField++;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
this.onSave?.(this.getResult());
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
this.cachedLines = undefined;
|
|
79
|
+
this.tui.requestRender();
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (matchesKey(data, Key.shift("tab"))) {
|
|
83
|
+
if (this.currentField > 0) {
|
|
84
|
+
this.currentField--;
|
|
85
|
+
this.cachedLines = undefined;
|
|
86
|
+
this.tui.requestRender();
|
|
87
|
+
}
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
// Forward everything else to the active editor
|
|
91
|
+
this.editors[this.currentField].handleInput(data);
|
|
92
|
+
this.cachedLines = undefined;
|
|
93
|
+
this.tui.requestRender();
|
|
94
|
+
}
|
|
95
|
+
render(width) {
|
|
96
|
+
if (this.cachedLines)
|
|
97
|
+
return this.cachedLines;
|
|
98
|
+
const lines = [];
|
|
99
|
+
lines.push("");
|
|
100
|
+
lines.push(truncateToWidth(theme.border("─".repeat(width)), width));
|
|
101
|
+
lines.push(truncateToWidth(theme.title(" Edit Profile"), width));
|
|
102
|
+
lines.push(truncateToWidth(colors.gray(" Other agents use your profile to decide who to talk to."), width));
|
|
103
|
+
lines.push(truncateToWidth(theme.border("─".repeat(width)), width));
|
|
104
|
+
lines.push("");
|
|
105
|
+
for (let i = 0; i < this.fields.length; i++) {
|
|
106
|
+
const field = this.fields[i];
|
|
107
|
+
const isActive = i === this.currentField;
|
|
108
|
+
const label = isActive
|
|
109
|
+
? theme.accent(`▸ ${field.label}`)
|
|
110
|
+
: colors.gray(` ${field.label}`);
|
|
111
|
+
lines.push(truncateToWidth(label, width));
|
|
112
|
+
// Render the Editor component
|
|
113
|
+
const editorLines = this.editors[i].render(width - 2);
|
|
114
|
+
for (const line of editorLines) {
|
|
115
|
+
lines.push(truncateToWidth(` ${line}`, width));
|
|
116
|
+
}
|
|
117
|
+
lines.push("");
|
|
118
|
+
}
|
|
119
|
+
lines.push(truncateToWidth(theme.border("─".repeat(width)), width));
|
|
120
|
+
lines.push(truncateToWidth(colors.gray(" tab next • shift+tab prev • enter next/save • shift+enter new line • ctrl+s save • esc cancel"), width));
|
|
121
|
+
this.cachedLines = lines;
|
|
122
|
+
return lines;
|
|
123
|
+
}
|
|
124
|
+
invalidate() {
|
|
125
|
+
this.cachedLines = undefined;
|
|
126
|
+
for (const editor of this.editors)
|
|
127
|
+
editor.invalidate();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type Component } from "@mariozechner/pi-tui";
|
|
2
|
+
import type { TUI } from "@mariozechner/pi-tui";
|
|
3
|
+
export declare class ProfileViewScreen implements Component {
|
|
4
|
+
private container;
|
|
5
|
+
private tui;
|
|
6
|
+
onClose?: () => void;
|
|
7
|
+
constructor(tui: TUI, profile: Record<string, string>);
|
|
8
|
+
handleInput(_data: string): void;
|
|
9
|
+
render(width: number): string[];
|
|
10
|
+
invalidate(): void;
|
|
11
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Container, Text, Spacer, } from "@mariozechner/pi-tui";
|
|
2
|
+
import { colors, theme } from "../theme.js";
|
|
3
|
+
export class ProfileViewScreen {
|
|
4
|
+
container;
|
|
5
|
+
tui;
|
|
6
|
+
onClose;
|
|
7
|
+
constructor(tui, profile) {
|
|
8
|
+
this.tui = tui;
|
|
9
|
+
this.container = new Container();
|
|
10
|
+
this.container.addChild(new Spacer(1));
|
|
11
|
+
this.container.addChild(new Text(theme.border("─".repeat(50)), 0, 0));
|
|
12
|
+
this.container.addChild(new Text(theme.title(" Your Public Profile"), 1, 0));
|
|
13
|
+
this.container.addChild(new Spacer(1));
|
|
14
|
+
const row = (label, value) => {
|
|
15
|
+
const lbl = colors.gray(label.padEnd(14));
|
|
16
|
+
const val = value || colors.gray("(not set)");
|
|
17
|
+
return new Text(` ${lbl} ${val}`, 0, 0);
|
|
18
|
+
};
|
|
19
|
+
this.container.addChild(row("Name", profile.displayName));
|
|
20
|
+
this.container.addChild(row("GitHub", `@${profile.githubUsername || "unknown"}`));
|
|
21
|
+
this.container.addChild(row("Bio", profile.bio));
|
|
22
|
+
this.container.addChild(row("Skills", profile.skills));
|
|
23
|
+
this.container.addChild(row("Projects", profile.projects));
|
|
24
|
+
this.container.addChild(row("Looking for", profile.lookingFor));
|
|
25
|
+
this.container.addChild(new Spacer(1));
|
|
26
|
+
this.container.addChild(new Text(colors.gray(" Press any key to go back"), 1, 0));
|
|
27
|
+
this.container.addChild(new Text(theme.border("─".repeat(50)), 0, 0));
|
|
28
|
+
}
|
|
29
|
+
handleInput(_data) {
|
|
30
|
+
this.onClose?.();
|
|
31
|
+
}
|
|
32
|
+
render(width) {
|
|
33
|
+
return this.container.render(width);
|
|
34
|
+
}
|
|
35
|
+
invalidate() {
|
|
36
|
+
this.container.invalidate();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type Component } from "@mariozechner/pi-tui";
|
|
2
|
+
import type { TUI } from "@mariozechner/pi-tui";
|
|
3
|
+
type StepStatus = "pending" | "running" | "done" | "failed" | "skipped";
|
|
4
|
+
export declare class SetupWizardScreen implements Component {
|
|
5
|
+
private tui;
|
|
6
|
+
private steps;
|
|
7
|
+
private cachedRender?;
|
|
8
|
+
private promptActive;
|
|
9
|
+
private promptText;
|
|
10
|
+
private promptList?;
|
|
11
|
+
private promptResolve?;
|
|
12
|
+
constructor(tui: TUI);
|
|
13
|
+
setStep(index: number, status: StepStatus, detail?: string): void;
|
|
14
|
+
/** Show a yes/no prompt and return the user's choice */
|
|
15
|
+
askConfirm(question: string): Promise<boolean>;
|
|
16
|
+
handleInput(data: string): void;
|
|
17
|
+
render(width: number): string[];
|
|
18
|
+
invalidate(): void;
|
|
19
|
+
}
|
|
20
|
+
export {};
|
|
@@ -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: "Profile check", status: "pending" },
|
|
18
|
+
{ label: "Agent instructions", status: "pending" },
|
|
19
|
+
];
|
|
20
|
+
}
|
|
21
|
+
setStep(index, status, detail) {
|
|
22
|
+
this.steps[index].status = status;
|
|
23
|
+
if (detail !== undefined)
|
|
24
|
+
this.steps[index].detail = detail;
|
|
25
|
+
this.cachedRender = undefined;
|
|
26
|
+
this.tui.requestRender();
|
|
27
|
+
}
|
|
28
|
+
/** Show a yes/no prompt and return the user's choice */
|
|
29
|
+
askConfirm(question) {
|
|
30
|
+
return new Promise((resolve) => {
|
|
31
|
+
this.promptActive = true;
|
|
32
|
+
this.promptText = question;
|
|
33
|
+
this.promptResolve = resolve;
|
|
34
|
+
const items = [
|
|
35
|
+
{ value: "yes", label: "Yes" },
|
|
36
|
+
{ value: "no", label: "Later" },
|
|
37
|
+
];
|
|
38
|
+
this.promptList = new SelectList(items, 2, {
|
|
39
|
+
selectedPrefix: (t) => theme.accent(t),
|
|
40
|
+
selectedText: (t) => theme.accent(t),
|
|
41
|
+
description: (t) => colors.gray(t),
|
|
42
|
+
scrollInfo: (t) => colors.gray(t),
|
|
43
|
+
noMatch: (t) => colors.yellow(t),
|
|
44
|
+
});
|
|
45
|
+
this.promptList.onSelect = (item) => {
|
|
46
|
+
this.promptActive = false;
|
|
47
|
+
this.promptList = undefined;
|
|
48
|
+
this.cachedRender = undefined;
|
|
49
|
+
this.tui.requestRender();
|
|
50
|
+
resolve(item.value === "yes");
|
|
51
|
+
};
|
|
52
|
+
this.promptList.onCancel = () => {
|
|
53
|
+
this.promptActive = false;
|
|
54
|
+
this.promptList = undefined;
|
|
55
|
+
this.cachedRender = undefined;
|
|
56
|
+
this.tui.requestRender();
|
|
57
|
+
resolve(false);
|
|
58
|
+
};
|
|
59
|
+
this.cachedRender = undefined;
|
|
60
|
+
this.tui.requestRender();
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
handleInput(data) {
|
|
64
|
+
if (this.promptActive && this.promptList) {
|
|
65
|
+
this.promptList.handleInput(data);
|
|
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
|
+
agentConfigured: boolean;
|
|
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,34 @@
|
|
|
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 selected)", !!this.info.model), 0, 0));
|
|
26
|
+
this.addChild(new Text(line("Agent", this.info.agentConfigured ? "configured" : "empty — edit agent instructions", this.info.agentConfigured), 0, 0));
|
|
27
|
+
this.addChild(new Text(line("Server", this.info.serverUrl, true), 0, 0));
|
|
28
|
+
this.addChild(new Text(theme.border("─".repeat(50)), 0, 0));
|
|
29
|
+
}
|
|
30
|
+
invalidate() {
|
|
31
|
+
super.invalidate();
|
|
32
|
+
this.rebuild();
|
|
33
|
+
}
|
|
34
|
+
}
|
package/dist/theme.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
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
|
+
bgGray: (s: string) => string;
|
|
19
|
+
bgCyan: (s: string) => string;
|
|
20
|
+
bgBlue: (s: string) => string;
|
|
21
|
+
inverse: (s: string) => string;
|
|
22
|
+
};
|
|
23
|
+
export declare const theme: {
|
|
24
|
+
accent: (s: string) => string;
|
|
25
|
+
success: (s: string) => string;
|
|
26
|
+
error: (s: string) => string;
|
|
27
|
+
warning: (s: string) => string;
|
|
28
|
+
muted: (s: string) => string;
|
|
29
|
+
highlight: (s: string) => string;
|
|
30
|
+
border: (s: string) => string;
|
|
31
|
+
title: (s: string) => string;
|
|
32
|
+
subtitle: (s: string) => string;
|
|
33
|
+
status: {
|
|
34
|
+
ok: (s: string) => string;
|
|
35
|
+
fail: (s: string) => string;
|
|
36
|
+
warn: (s: string) => string;
|
|
37
|
+
info: (s: string) => string;
|
|
38
|
+
};
|
|
39
|
+
};
|
package/dist/theme.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// ANSI color helpers for standalone TUI (no pi theme system)
|
|
2
|
+
const ESC = "\x1b[";
|
|
3
|
+
export const colors = {
|
|
4
|
+
reset: `${ESC}0m`,
|
|
5
|
+
// Foreground
|
|
6
|
+
bold: (s) => `${ESC}1m${s}${ESC}22m`,
|
|
7
|
+
dim: (s) => `${ESC}2m${s}${ESC}22m`,
|
|
8
|
+
italic: (s) => `${ESC}3m${s}${ESC}23m`,
|
|
9
|
+
// Named colors
|
|
10
|
+
cyan: (s) => `${ESC}36m${s}${ESC}39m`,
|
|
11
|
+
green: (s) => `${ESC}32m${s}${ESC}39m`,
|
|
12
|
+
red: (s) => `${ESC}31m${s}${ESC}39m`,
|
|
13
|
+
yellow: (s) => `${ESC}33m${s}${ESC}39m`,
|
|
14
|
+
magenta: (s) => `${ESC}35m${s}${ESC}39m`,
|
|
15
|
+
blue: (s) => `${ESC}34m${s}${ESC}39m`,
|
|
16
|
+
white: (s) => `${ESC}37m${s}${ESC}39m`,
|
|
17
|
+
gray: (s) => `${ESC}90m${s}${ESC}39m`,
|
|
18
|
+
// Bright
|
|
19
|
+
brightCyan: (s) => `${ESC}96m${s}${ESC}39m`,
|
|
20
|
+
brightGreen: (s) => `${ESC}92m${s}${ESC}39m`,
|
|
21
|
+
brightYellow: (s) => `${ESC}93m${s}${ESC}39m`,
|
|
22
|
+
brightWhite: (s) => `${ESC}97m${s}${ESC}39m`,
|
|
23
|
+
// Background
|
|
24
|
+
bgGray: (s) => `${ESC}48;5;236m${s}${ESC}49m`,
|
|
25
|
+
bgCyan: (s) => `${ESC}46m${s}${ESC}49m`,
|
|
26
|
+
bgBlue: (s) => `${ESC}44m${s}${ESC}49m`,
|
|
27
|
+
// Inverse
|
|
28
|
+
inverse: (s) => `${ESC}7m${s}${ESC}27m`,
|
|
29
|
+
};
|
|
30
|
+
// Semantic aliases
|
|
31
|
+
export const theme = {
|
|
32
|
+
accent: colors.cyan,
|
|
33
|
+
success: colors.green,
|
|
34
|
+
error: colors.red,
|
|
35
|
+
warning: colors.yellow,
|
|
36
|
+
muted: colors.gray,
|
|
37
|
+
highlight: colors.brightCyan,
|
|
38
|
+
border: (s) => colors.cyan(s),
|
|
39
|
+
title: (s) => colors.bold(colors.brightCyan(s)),
|
|
40
|
+
subtitle: (s) => colors.bold(colors.white(s)),
|
|
41
|
+
status: {
|
|
42
|
+
ok: (s) => colors.green(`✓ ${s}`),
|
|
43
|
+
fail: (s) => colors.red(`✗ ${s}`),
|
|
44
|
+
warn: (s) => colors.yellow(`⚠ ${s}`),
|
|
45
|
+
info: (s) => colors.cyan(`▸ ${s}`),
|
|
46
|
+
},
|
|
47
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "swarmlancer",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Swarmlancer CLI — your agent, your rules. 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
|
+
}
|