swarmlancer-cli 0.5.3 → 0.6.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/app.js +13 -10
- package/dist/config.d.ts +1 -0
- package/dist/screens/agent-config.d.ts +1 -1
- package/dist/screens/agent-config.js +9 -19
- package/dist/screens/agent-editor.d.ts +1 -0
- package/dist/screens/agent-editor.js +13 -19
- package/dist/screens/name-editor.d.ts +2 -3
- package/dist/screens/name-editor.js +12 -21
- package/package.json +1 -1
package/dist/app.js
CHANGED
|
@@ -19,7 +19,7 @@ import { MessageScreen } from "./screens/message.js";
|
|
|
19
19
|
import { screenProfiles } from "./screening.js";
|
|
20
20
|
let terminal;
|
|
21
21
|
let tui;
|
|
22
|
-
|
|
22
|
+
// Runtime state for currently running agent
|
|
23
23
|
function setScreen(component) {
|
|
24
24
|
tui.clear();
|
|
25
25
|
tui.addChild(component);
|
|
@@ -57,9 +57,9 @@ async function silentSetup() {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
// ── Sub-screens ───────────────────────────────────────────
|
|
60
|
-
function askName(title,
|
|
60
|
+
function askName(title, current = "") {
|
|
61
61
|
return new Promise((resolve) => {
|
|
62
|
-
const screen = new NameEditorScreen(tui, current, title
|
|
62
|
+
const screen = new NameEditorScreen(tui, current, title);
|
|
63
63
|
screen.onSave = (name) => resolve(name);
|
|
64
64
|
screen.onCancel = () => resolve(null);
|
|
65
65
|
setScreen(screen);
|
|
@@ -134,8 +134,13 @@ async function runAgentConfig(agentId) {
|
|
|
134
134
|
});
|
|
135
135
|
idx = action.index >= 0 ? action.index : idx;
|
|
136
136
|
switch (action.action) {
|
|
137
|
+
case "toggle-active": {
|
|
138
|
+
agent.active = !agent.active;
|
|
139
|
+
saveAgent(agent);
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
137
142
|
case "edit-name": {
|
|
138
|
-
const n = await askName("Rename
|
|
143
|
+
const n = await askName("Rename", agent.name);
|
|
139
144
|
if (n) {
|
|
140
145
|
agent.name = n;
|
|
141
146
|
saveAgent(agent);
|
|
@@ -175,8 +180,7 @@ async function runSwarm() {
|
|
|
175
180
|
{ value: "__create__", label: "+ Create", description: "" },
|
|
176
181
|
];
|
|
177
182
|
for (const agent of agents) {
|
|
178
|
-
const
|
|
179
|
-
const suffix = isRunning ? " [⚡]" : "";
|
|
183
|
+
const suffix = agent.active ? " (ON)" : "";
|
|
180
184
|
items.push({ value: agent.id, label: `${agent.name}${suffix}`, description: "" });
|
|
181
185
|
}
|
|
182
186
|
const result = await new Promise((resolve) => {
|
|
@@ -189,7 +193,7 @@ async function runSwarm() {
|
|
|
189
193
|
return;
|
|
190
194
|
idx = result.index;
|
|
191
195
|
if (result.value === "__create__") {
|
|
192
|
-
const name = await askName("
|
|
196
|
+
const name = await askName("+ Create");
|
|
193
197
|
if (name) {
|
|
194
198
|
const a = createAgent(name);
|
|
195
199
|
await runAgentConfig(a.id);
|
|
@@ -226,7 +230,7 @@ async function runProviders() {
|
|
|
226
230
|
await showMessage("Coming soon", [`${provider.label} is not yet supported.`], "info");
|
|
227
231
|
continue;
|
|
228
232
|
}
|
|
229
|
-
const key = await askName(provider.label
|
|
233
|
+
const key = await askName(provider.label);
|
|
230
234
|
if (key) {
|
|
231
235
|
saveProviderKey(provider.id, key);
|
|
232
236
|
await showMessage("Saved", [`${provider.label} API key saved.`], "success");
|
|
@@ -297,12 +301,11 @@ async function goOnline() {
|
|
|
297
301
|
}
|
|
298
302
|
setActiveModel(resolved.provider, resolved.model);
|
|
299
303
|
setAgentInstructions(agent.instructions);
|
|
300
|
-
runningAgentId = agent.id;
|
|
301
304
|
const modelInfo = { provider: resolved.provider, id: resolved.model, name: resolved.model };
|
|
302
305
|
const config = getConfig();
|
|
303
306
|
const screen = new AgentRunningScreen(tui, modelInfo, config.serverUrl, agent.name);
|
|
304
307
|
const done = new Promise((resolve) => {
|
|
305
|
-
screen.onStop = () => { stopAgent();
|
|
308
|
+
screen.onStop = () => { stopAgent(); resolve(); };
|
|
306
309
|
});
|
|
307
310
|
setScreen(screen);
|
|
308
311
|
const log = (line) => screen.addLog(line);
|
package/dist/config.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type Component } from "@mariozechner/pi-tui";
|
|
2
2
|
import type { TUI } from "@mariozechner/pi-tui";
|
|
3
3
|
import type { AgentProfile } from "../config.js";
|
|
4
|
-
export type AgentConfigAction = "edit-name" | "edit-instructions" | "edit-discovery" | "edit-limits" | "edit-model" | "delete" | "back";
|
|
4
|
+
export type AgentConfigAction = "toggle-active" | "edit-name" | "edit-instructions" | "edit-discovery" | "edit-limits" | "edit-model" | "delete" | "back";
|
|
5
5
|
export declare class AgentConfigScreen implements Component {
|
|
6
6
|
private container;
|
|
7
7
|
private selectList;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Container,
|
|
1
|
+
import { Container, Spacer, SelectList, Text, matchesKey, Key, } from "@mariozechner/pi-tui";
|
|
2
2
|
import { colors, theme } from "../theme.js";
|
|
3
3
|
import { BannerComponent } from "./banner.js";
|
|
4
4
|
export class AgentConfigScreen {
|
|
@@ -9,25 +9,15 @@ export class AgentConfigScreen {
|
|
|
9
9
|
constructor(tui, agent, initialIndex = 0) {
|
|
10
10
|
this.tui = tui;
|
|
11
11
|
this.container = new Container();
|
|
12
|
-
this.container.addChild(new BannerComponent(
|
|
13
|
-
|
|
14
|
-
const modelStr = agent.modelPattern || "(auto — cheapest)";
|
|
15
|
-
const instrStr = agent.instructions.length > 0
|
|
16
|
-
? `${agent.instructions.split("\n").length} lines`
|
|
17
|
-
: "empty";
|
|
18
|
-
const discoveryStr = `threshold ${agent.discovery.matchThreshold}/10, ${agent.discovery.maxScreenPerSession} max`;
|
|
19
|
-
const limitsStr = `${agent.limits.maxConcurrentConversations} concurrent, ${agent.limits.maxMessagesPerConversation} msgs`;
|
|
20
|
-
this.container.addChild(new Text(` ${colors.gray("Model:")} ${modelStr}`, 0, 0));
|
|
21
|
-
this.container.addChild(new Text(` ${colors.gray("Instructions:")} ${instrStr}`, 0, 0));
|
|
22
|
-
this.container.addChild(new Text(` ${colors.gray("Discovery:")} ${discoveryStr}`, 0, 0));
|
|
23
|
-
this.container.addChild(new Text(` ${colors.gray("Limits:")} ${limitsStr}`, 0, 0));
|
|
24
|
-
this.container.addChild(new Spacer(1));
|
|
12
|
+
this.container.addChild(new BannerComponent(agent.name));
|
|
13
|
+
const activeLabel = agent.active ? "ON" : "OFF";
|
|
25
14
|
const items = [
|
|
26
|
-
{ value: "
|
|
27
|
-
{ value: "edit-
|
|
28
|
-
{ value: "edit-
|
|
29
|
-
{ value: "edit-
|
|
30
|
-
{ value: "edit-
|
|
15
|
+
{ value: "toggle-active", label: `Active: ${activeLabel}`, description: "" },
|
|
16
|
+
{ value: "edit-name", label: "Rename", description: "" },
|
|
17
|
+
{ value: "edit-instructions", label: "Instructions", description: "" },
|
|
18
|
+
{ value: "edit-discovery", label: "Discovery", description: "" },
|
|
19
|
+
{ value: "edit-limits", label: "Limits", description: "" },
|
|
20
|
+
{ value: "edit-model", label: "Model", description: "" },
|
|
31
21
|
{ value: "delete", label: "Delete", description: "" },
|
|
32
22
|
];
|
|
33
23
|
this.selectList = new SelectList(items, items.length, {
|
|
@@ -2,6 +2,7 @@ import { type Component } from "@mariozechner/pi-tui";
|
|
|
2
2
|
import type { TUI } from "@mariozechner/pi-tui";
|
|
3
3
|
export declare class AgentEditorScreen implements Component {
|
|
4
4
|
private tui;
|
|
5
|
+
private banner;
|
|
5
6
|
private editor;
|
|
6
7
|
private cachedLines?;
|
|
7
8
|
onSave?: (content: string) => void;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Editor, matchesKey, Key,
|
|
2
|
-
import { colors
|
|
1
|
+
import { Editor, matchesKey, Key, } from "@mariozechner/pi-tui";
|
|
2
|
+
import { colors } from "../theme.js";
|
|
3
|
+
import { BannerComponent } from "./banner.js";
|
|
3
4
|
const EDITOR_THEME = {
|
|
4
5
|
borderColor: (s) => colors.lime(s),
|
|
5
6
|
selectList: {
|
|
@@ -12,28 +13,27 @@ const EDITOR_THEME = {
|
|
|
12
13
|
};
|
|
13
14
|
export class AgentEditorScreen {
|
|
14
15
|
tui;
|
|
16
|
+
banner;
|
|
15
17
|
editor;
|
|
16
18
|
cachedLines;
|
|
17
19
|
onSave;
|
|
18
20
|
onCancel;
|
|
19
21
|
constructor(tui, content) {
|
|
20
22
|
this.tui = tui;
|
|
23
|
+
this.banner = new BannerComponent("Instructions");
|
|
21
24
|
this.editor = new Editor(tui, EDITOR_THEME, { paddingX: 1 });
|
|
22
25
|
this.editor.setText(content);
|
|
23
|
-
this.editor.disableSubmit = true;
|
|
26
|
+
this.editor.disableSubmit = true;
|
|
24
27
|
}
|
|
25
28
|
handleInput(data) {
|
|
26
|
-
// Ctrl+S to save
|
|
27
29
|
if (matchesKey(data, Key.ctrl("s"))) {
|
|
28
30
|
this.onSave?.(this.editor.getText());
|
|
29
31
|
return;
|
|
30
32
|
}
|
|
31
|
-
// Escape to cancel
|
|
32
33
|
if (matchesKey(data, Key.escape)) {
|
|
33
34
|
this.onCancel?.();
|
|
34
35
|
return;
|
|
35
36
|
}
|
|
36
|
-
// Everything else goes to the editor
|
|
37
37
|
this.editor.handleInput(data);
|
|
38
38
|
this.cachedLines = undefined;
|
|
39
39
|
this.tui.requestRender();
|
|
@@ -41,24 +41,18 @@ export class AgentEditorScreen {
|
|
|
41
41
|
render(width) {
|
|
42
42
|
if (this.cachedLines)
|
|
43
43
|
return this.cachedLines;
|
|
44
|
-
const lines =
|
|
45
|
-
|
|
46
|
-
lines.push(truncateToWidth(` ${theme.title("Instructions")}`, width));
|
|
47
|
-
lines.push(truncateToWidth(theme.border("─".repeat(width)), width));
|
|
48
|
-
// Editor takes most of the space — pad with empty lines to double the height
|
|
44
|
+
const lines = this.banner.render(width);
|
|
45
|
+
// Editor content
|
|
49
46
|
const editorLines = this.editor.render(width);
|
|
50
|
-
for (const line of editorLines)
|
|
47
|
+
for (const line of editorLines)
|
|
51
48
|
lines.push(line);
|
|
52
|
-
|
|
53
|
-
// Add padding lines to give the editor more vertical space
|
|
49
|
+
// Fill remaining terminal height to give editor 2x visual space
|
|
54
50
|
const termHeight = this.tui.terminal?.rows ?? 40;
|
|
55
|
-
const usedLines = lines.length +
|
|
51
|
+
const usedLines = lines.length + 2;
|
|
56
52
|
const remaining = Math.max(0, termHeight - usedLines);
|
|
57
|
-
for (let i = 0; i < remaining; i++)
|
|
53
|
+
for (let i = 0; i < remaining; i++)
|
|
58
54
|
lines.push("");
|
|
59
|
-
|
|
60
|
-
lines.push(truncateToWidth(theme.border("─".repeat(width)), width));
|
|
61
|
-
lines.push(truncateToWidth(colors.gray(" ctrl+s save • esc cancel"), width));
|
|
55
|
+
lines.push(colors.gray(" ctrl+s save • esc cancel"));
|
|
62
56
|
this.cachedLines = lines;
|
|
63
57
|
return lines;
|
|
64
58
|
}
|
|
@@ -2,13 +2,12 @@ import { type Component } from "@mariozechner/pi-tui";
|
|
|
2
2
|
import type { TUI } from "@mariozechner/pi-tui";
|
|
3
3
|
export declare class NameEditorScreen implements Component {
|
|
4
4
|
private tui;
|
|
5
|
+
private container;
|
|
5
6
|
private editor;
|
|
6
7
|
private cachedLines?;
|
|
7
|
-
private title;
|
|
8
|
-
private subtitle;
|
|
9
8
|
onSave?: (name: string) => void;
|
|
10
9
|
onCancel?: () => void;
|
|
11
|
-
constructor(tui: TUI, currentName: string, title?: string
|
|
10
|
+
constructor(tui: TUI, currentName: string, title?: string);
|
|
12
11
|
handleInput(data: string): void;
|
|
13
12
|
render(width: number): string[];
|
|
14
13
|
invalidate(): void;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Editor, matchesKey, Key,
|
|
2
|
-
import { colors
|
|
1
|
+
import { Container, Editor, matchesKey, Key, } from "@mariozechner/pi-tui";
|
|
2
|
+
import { colors } from "../theme.js";
|
|
3
|
+
import { BannerComponent } from "./banner.js";
|
|
3
4
|
const EDITOR_THEME = {
|
|
4
5
|
borderColor: (s) => colors.lime(s),
|
|
5
6
|
selectList: {
|
|
@@ -12,24 +13,22 @@ const EDITOR_THEME = {
|
|
|
12
13
|
};
|
|
13
14
|
export class NameEditorScreen {
|
|
14
15
|
tui;
|
|
16
|
+
container;
|
|
15
17
|
editor;
|
|
16
18
|
cachedLines;
|
|
17
|
-
title;
|
|
18
|
-
subtitle;
|
|
19
19
|
onSave;
|
|
20
20
|
onCancel;
|
|
21
|
-
constructor(tui, currentName, title = "
|
|
21
|
+
constructor(tui, currentName, title = "Rename") {
|
|
22
22
|
this.tui = tui;
|
|
23
|
-
this.
|
|
24
|
-
this.
|
|
23
|
+
this.container = new Container();
|
|
24
|
+
this.container.addChild(new BannerComponent(title));
|
|
25
25
|
this.editor = new Editor(tui, EDITOR_THEME, { paddingX: 1 });
|
|
26
26
|
this.editor.setText(currentName);
|
|
27
|
-
this.editor.disableSubmit = false;
|
|
27
|
+
this.editor.disableSubmit = false;
|
|
28
28
|
this.editor.onSubmit = (text) => {
|
|
29
29
|
const trimmed = text.trim();
|
|
30
|
-
if (trimmed.length > 0)
|
|
30
|
+
if (trimmed.length > 0)
|
|
31
31
|
this.onSave?.(trimmed);
|
|
32
|
-
}
|
|
33
32
|
};
|
|
34
33
|
}
|
|
35
34
|
handleInput(data) {
|
|
@@ -44,19 +43,11 @@ export class NameEditorScreen {
|
|
|
44
43
|
render(width) {
|
|
45
44
|
if (this.cachedLines)
|
|
46
45
|
return this.cachedLines;
|
|
47
|
-
const lines =
|
|
48
|
-
|
|
49
|
-
lines.push(truncateToWidth(theme.border("─".repeat(width)), width));
|
|
50
|
-
lines.push(truncateToWidth(theme.title(` ${this.title}`), width));
|
|
51
|
-
lines.push(truncateToWidth(colors.gray(` ${this.subtitle}`), width));
|
|
52
|
-
lines.push(truncateToWidth(theme.border("─".repeat(width)), width));
|
|
53
|
-
lines.push("");
|
|
54
|
-
for (const line of this.editor.render(width)) {
|
|
46
|
+
const lines = this.container.render(width);
|
|
47
|
+
for (const line of this.editor.render(width))
|
|
55
48
|
lines.push(line);
|
|
56
|
-
}
|
|
57
49
|
lines.push("");
|
|
58
|
-
lines.push(
|
|
59
|
-
lines.push(truncateToWidth(colors.gray(" enter save • esc cancel"), width));
|
|
50
|
+
lines.push(colors.gray(" enter save • esc cancel"));
|
|
60
51
|
this.cachedLines = lines;
|
|
61
52
|
return lines;
|
|
62
53
|
}
|