@delega-dev/cli 1.0.5 → 1.0.6

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.
@@ -1,66 +0,0 @@
1
- name: Publish to npm
2
-
3
- on:
4
- push:
5
- tags:
6
- - 'v*'
7
-
8
- permissions:
9
- contents: write
10
-
11
- jobs:
12
- publish:
13
- runs-on: ubuntu-latest
14
- steps:
15
- - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
16
- with:
17
- fetch-depth: 0
18
-
19
- - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
20
- with:
21
- node-version: 22
22
- cache: npm
23
- registry-url: https://registry.npmjs.org
24
-
25
- - run: npm ci
26
-
27
- - name: Type check
28
- run: npx tsc --noEmit
29
-
30
- - name: Build
31
- run: npm run build
32
-
33
- - name: Verify package version matches tag
34
- run: |
35
- PKG_VERSION=$(node -p "require('./package.json').version")
36
- TAG_VERSION="${GITHUB_REF_NAME#v}"
37
- if [ "$PKG_VERSION" != "$TAG_VERSION" ]; then
38
- echo "❌ package.json version ($PKG_VERSION) doesn't match tag ($TAG_VERSION)"
39
- exit 1
40
- fi
41
-
42
- - name: Publish to npm
43
- run: npm publish --access public
44
- env:
45
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
46
-
47
- - name: Generate changelog
48
- run: |
49
- PREV_TAG=$(git tag --sort=-v:refname | sed -n '2p')
50
- if [ -n "$PREV_TAG" ]; then
51
- echo "## Changes since $PREV_TAG" > /tmp/changelog.md
52
- echo "" >> /tmp/changelog.md
53
- git log "$PREV_TAG"..HEAD --pretty=format:"- %s (%h)" --no-merges >> /tmp/changelog.md
54
- else
55
- echo "## Initial release" > /tmp/changelog.md
56
- echo "" >> /tmp/changelog.md
57
- git log --pretty=format:"- %s (%h)" --no-merges >> /tmp/changelog.md
58
- fi
59
-
60
- - name: Create GitHub Release
61
- env:
62
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
63
- run: |
64
- gh release create "${{ github.ref_name }}" \
65
- --title "${{ github.ref_name }}" \
66
- --notes-file /tmp/changelog.md
package/src/api.ts DELETED
@@ -1,70 +0,0 @@
1
- import { getApiKey, getApiUrl } from "./config.js";
2
-
3
- export interface ApiError {
4
- error?: string;
5
- message?: string;
6
- }
7
-
8
- export async function apiCall<T = unknown>(
9
- method: string,
10
- path: string,
11
- body?: unknown,
12
- ): Promise<T> {
13
- const apiKey = getApiKey();
14
- if (!apiKey) {
15
- console.error("Not authenticated. Run: delega login");
16
- process.exit(1);
17
- }
18
-
19
- let apiBase: string;
20
- try {
21
- apiBase = getApiUrl();
22
- } catch (err) {
23
- const msg = err instanceof Error ? err.message : String(err);
24
- console.error(`Configuration error: ${msg}`);
25
- process.exit(1);
26
- }
27
-
28
- const url = apiBase + path;
29
-
30
- const headers: Record<string, string> = {
31
- "X-Agent-Key": apiKey,
32
- "Content-Type": "application/json",
33
- };
34
-
35
- const options: RequestInit = { method, headers };
36
- if (body !== undefined) {
37
- options.body = JSON.stringify(body);
38
- }
39
-
40
- let res: Response;
41
- try {
42
- res = await fetch(url, options);
43
- } catch (err) {
44
- const msg = err instanceof Error ? err.message : String(err);
45
- console.error(`Connection error: ${msg}`);
46
- process.exit(1);
47
- }
48
-
49
- if (res.status === 401) {
50
- console.error("Authentication failed. Run: delega login");
51
- process.exit(1);
52
- }
53
-
54
- let data: unknown;
55
- const text = await res.text();
56
- try {
57
- data = text ? JSON.parse(text) : {};
58
- } catch {
59
- data = { message: text };
60
- }
61
-
62
- if (!res.ok) {
63
- const errData = data as ApiError;
64
- const msg = errData.error || errData.message || `Request failed (${res.status})`;
65
- console.error(`Error: ${msg}`);
66
- process.exit(1);
67
- }
68
-
69
- return data as T;
70
- }
@@ -1,115 +0,0 @@
1
- import { Command } from "commander";
2
- import node_readline from "node:readline";
3
- import chalk from "chalk";
4
- import { apiCall } from "../api.js";
5
- import { printTable, formatDate, label } from "../ui.js";
6
-
7
- interface Agent {
8
- id: string;
9
- name: string;
10
- display_name?: string;
11
- active?: boolean;
12
- created_at?: string;
13
- api_key?: string;
14
- }
15
-
16
- function confirm(question: string): Promise<boolean> {
17
- const rl = node_readline.createInterface({
18
- input: process.stdin,
19
- output: process.stdout,
20
- });
21
- return new Promise((resolve) => {
22
- rl.question(question, (answer) => {
23
- rl.close();
24
- resolve(answer.trim().toLowerCase() === "y");
25
- });
26
- });
27
- }
28
-
29
- const agentsList = new Command("list")
30
- .description("List agents")
31
- .option("--json", "Output raw JSON")
32
- .action(async (opts) => {
33
- const data = await apiCall<Agent[]>("GET", "/v1/agents");
34
-
35
- if (opts.json) {
36
- console.log(JSON.stringify(data, null, 2));
37
- return;
38
- }
39
-
40
- const agents = Array.isArray(data) ? data : [data];
41
-
42
- if (agents.length === 0) {
43
- console.log("No agents found.");
44
- return;
45
- }
46
-
47
- const headers = ["Name", "Display Name", "Active", "Created"];
48
- const rows = agents.map((a) => [
49
- a.name,
50
- a.display_name || "—",
51
- a.active !== false ? "yes" : "no",
52
- formatDate(a.created_at || ""),
53
- ]);
54
-
55
- printTable(headers, rows);
56
- });
57
-
58
- const agentsCreate = new Command("create")
59
- .description("Create a new agent")
60
- .argument("<name>", "Agent name")
61
- .option("--display-name <name>", "Friendly display name")
62
- .option("--json", "Output raw JSON")
63
- .action(async (name: string, opts) => {
64
- const body: Record<string, unknown> = { name };
65
- if (opts.displayName) body.display_name = opts.displayName;
66
-
67
- const agent = await apiCall<Agent>("POST", "/v1/agents", body);
68
-
69
- if (opts.json) {
70
- console.log(JSON.stringify(agent, null, 2));
71
- return;
72
- }
73
-
74
- console.log();
75
- label("Agent Created", agent.name);
76
- if (agent.display_name) label("Display Name", agent.display_name);
77
- label("ID", agent.id);
78
- if (agent.api_key) {
79
- console.log();
80
- console.log(` API Key: ${chalk.cyan.bold(agent.api_key)}`);
81
- console.log(
82
- chalk.yellow(" Save this key — it will not be shown again."),
83
- );
84
- }
85
- console.log();
86
- });
87
-
88
- const agentsRotate = new Command("rotate")
89
- .description("Rotate an agent's API key")
90
- .argument("<id>", "Agent ID")
91
- .action(async (id: string) => {
92
- const yes = await confirm(
93
- `Rotate key for agent ${id}? Old key will stop working immediately. (y/N) `,
94
- );
95
- if (!yes) {
96
- console.log("Cancelled.");
97
- return;
98
- }
99
-
100
- const result = await apiCall<{ api_key: string }>(
101
- "POST",
102
- `/v1/agents/${id}/rotate-key`,
103
- );
104
-
105
- console.log();
106
- console.log(` New API Key: ${chalk.cyan.bold(result.api_key)}`);
107
- console.log(chalk.yellow(" Save this key — it will not be shown again."));
108
- console.log();
109
- });
110
-
111
- export const agentsCommand = new Command("agents")
112
- .description("Manage agents")
113
- .addCommand(agentsList)
114
- .addCommand(agentsCreate)
115
- .addCommand(agentsRotate);
@@ -1,100 +0,0 @@
1
- import { Command } from "commander";
2
- import node_readline from "node:readline";
3
- import { saveConfig, loadConfig, normalizeApiUrl } from "../config.js";
4
- import { printBanner } from "../ui.js";
5
-
6
- interface Agent {
7
- id: string;
8
- name: string;
9
- display_name?: string;
10
- }
11
-
12
- async function promptSecret(question: string): Promise<string> {
13
- const mutedOutput = {
14
- muted: false,
15
- write(chunk: string) {
16
- if (!this.muted || chunk.includes(question)) {
17
- process.stdout.write(chunk);
18
- }
19
- },
20
- };
21
-
22
- const rl = node_readline.createInterface({
23
- input: process.stdin,
24
- output: mutedOutput as unknown as NodeJS.WritableStream,
25
- terminal: true,
26
- });
27
-
28
- mutedOutput.muted = true;
29
-
30
- return new Promise((resolve) => {
31
- rl.question(question, (answer) => {
32
- rl.close();
33
- process.stdout.write("\n");
34
- resolve(answer.trim());
35
- });
36
- });
37
- }
38
-
39
- export const loginCommand = new Command("login")
40
- .description("Authenticate with the Delega API")
41
- .action(async () => {
42
- printBanner();
43
-
44
- const key = await promptSecret("Enter your API key (starts with dlg_): ");
45
-
46
- if (!key) {
47
- console.error("No key provided.");
48
- process.exit(1);
49
- }
50
-
51
- if (!key.startsWith("dlg_")) {
52
- console.error("Invalid key format. Keys start with dlg_");
53
- process.exit(1);
54
- }
55
-
56
- // Validate by calling the API
57
- const config = loadConfig();
58
- let apiUrl: string;
59
- try {
60
- apiUrl = normalizeApiUrl(
61
- config.api_url || process.env.DELEGA_API_URL || "https://api.delega.dev",
62
- );
63
- } catch (err) {
64
- const msg = err instanceof Error ? err.message : String(err);
65
- console.error(`Configuration error: ${msg}`);
66
- process.exit(1);
67
- }
68
-
69
- let res: Response;
70
- try {
71
- res = await fetch(`${apiUrl}/v1/agent/me`, {
72
- headers: {
73
- "X-Agent-Key": key,
74
- "Content-Type": "application/json",
75
- },
76
- });
77
- } catch (err) {
78
- const msg = err instanceof Error ? err.message : String(err);
79
- console.error(`Connection error: ${msg}`);
80
- process.exit(1);
81
- }
82
-
83
- if (!res.ok) {
84
- console.error("Invalid API key. Authentication failed.");
85
- process.exit(1);
86
- }
87
-
88
- let agentName = "agent";
89
- try {
90
- const data = (await res.json()) as { agent?: Agent };
91
- if (data.agent?.name) {
92
- agentName = data.agent.display_name || data.agent.name;
93
- }
94
- } catch {
95
- // Proceed with default name
96
- }
97
-
98
- saveConfig({ ...config, api_key: key });
99
- console.log(`\nLogged in as ${agentName}. Key saved to ~/.delega/config.json`);
100
- });
@@ -1,48 +0,0 @@
1
- import { Command } from "commander";
2
- import { apiCall } from "../api.js";
3
- import { label } from "../ui.js";
4
-
5
- interface Stats {
6
- total_tasks?: number;
7
- completed_tasks?: number;
8
- pending_tasks?: number;
9
- total_agents?: number;
10
- active_agents?: number;
11
- [key: string]: unknown;
12
- }
13
-
14
- export const statsCommand = new Command("stats")
15
- .description("Show usage statistics")
16
- .option("--json", "Output raw JSON")
17
- .action(async (opts) => {
18
- const data = await apiCall<Stats>("GET", "/v1/stats");
19
-
20
- if (opts.json) {
21
- console.log(JSON.stringify(data, null, 2));
22
- return;
23
- }
24
-
25
- console.log();
26
- if (data.total_tasks !== undefined) label("Total Tasks", String(data.total_tasks));
27
- if (data.completed_tasks !== undefined) label("Completed", String(data.completed_tasks));
28
- if (data.pending_tasks !== undefined) label("Pending", String(data.pending_tasks));
29
- if (data.total_agents !== undefined) label("Total Agents", String(data.total_agents));
30
- if (data.active_agents !== undefined) label("Active Agents", String(data.active_agents));
31
-
32
- // Print any additional stats fields
33
- const knownKeys = new Set([
34
- "total_tasks",
35
- "completed_tasks",
36
- "pending_tasks",
37
- "total_agents",
38
- "active_agents",
39
- ]);
40
- for (const [key, value] of Object.entries(data)) {
41
- if (!knownKeys.has(key) && value !== undefined) {
42
- const displayKey = key.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
43
- const displayVal = typeof value === "object" ? JSON.stringify(value) : String(value);
44
- label(displayKey, displayVal);
45
- }
46
- }
47
- console.log();
48
- });
@@ -1,189 +0,0 @@
1
- import { Command } from "commander";
2
- import node_readline from "node:readline";
3
- import { apiCall } from "../api.js";
4
- import {
5
- printTable,
6
- formatDate,
7
- formatId,
8
- priorityBadge,
9
- statusBadge,
10
- label,
11
- } from "../ui.js";
12
-
13
- interface Task {
14
- id: string;
15
- content: string;
16
- status: string;
17
- priority: number;
18
- labels?: string[];
19
- due_date?: string;
20
- created_at?: string;
21
- updated_at?: string;
22
- completed_at?: string;
23
- assigned_to_agent_id?: string;
24
- comments?: Comment[];
25
- }
26
-
27
- interface Comment {
28
- id: string;
29
- content: string;
30
- created_at?: string;
31
- }
32
-
33
- function confirm(question: string): Promise<boolean> {
34
- const rl = node_readline.createInterface({
35
- input: process.stdin,
36
- output: process.stdout,
37
- });
38
- return new Promise((resolve) => {
39
- rl.question(question, (answer) => {
40
- rl.close();
41
- resolve(answer.trim().toLowerCase() === "y");
42
- });
43
- });
44
- }
45
-
46
- const tasksList = new Command("list")
47
- .description("List tasks")
48
- .option("--completed", "Include completed tasks")
49
- .option("--limit <n>", "Limit results", parseInt)
50
- .option("--json", "Output raw JSON")
51
- .action(async (opts) => {
52
- let path = "/v1/tasks";
53
- const params: string[] = [];
54
- if (opts.completed) params.push("completed=true");
55
- if (opts.limit) params.push(`limit=${opts.limit}`);
56
- if (params.length > 0) path += "?" + params.join("&");
57
-
58
- const data = await apiCall<Task[]>("GET", path);
59
-
60
- if (opts.json) {
61
- console.log(JSON.stringify(data, null, 2));
62
- return;
63
- }
64
-
65
- const tasks = Array.isArray(data) ? data : [];
66
-
67
- if (tasks.length === 0) {
68
- console.log("No tasks found.");
69
- return;
70
- }
71
-
72
- const headers = ["ID", "Priority", "Status", "Content"];
73
- const rows = tasks.map((t) => [
74
- formatId(t.id),
75
- priorityBadge(t.priority),
76
- statusBadge(t.status),
77
- t.content.length > 50 ? t.content.slice(0, 47) + "..." : t.content,
78
- ]);
79
-
80
- printTable(headers, rows);
81
- });
82
-
83
- const tasksCreate = new Command("create")
84
- .description("Create a new task")
85
- .argument("<content>", "Task content")
86
- .option("--priority <n>", "Priority 1-4 (default: 1)", (v: string) => parseInt(v, 10), 1)
87
- .option("--labels <labels>", "Comma-separated labels")
88
- .option("--due <date>", "Due date (YYYY-MM-DD)")
89
- .option("--json", "Output raw JSON")
90
- .action(async (content: string, opts) => {
91
- const body: Record<string, unknown> = { content };
92
- if (opts.priority) body.priority = opts.priority;
93
- if (opts.labels) body.labels = opts.labels.split(",").map((l: string) => l.trim());
94
- if (opts.due) body.due_date = opts.due;
95
-
96
- const task = await apiCall<Task>("POST", "/v1/tasks", body);
97
-
98
- if (opts.json) {
99
- console.log(JSON.stringify(task, null, 2));
100
- return;
101
- }
102
-
103
- console.log(`Task created: ${task.id}`);
104
- console.log();
105
- label("Content", task.content);
106
- label("Priority", priorityBadge(task.priority));
107
- label("Status", statusBadge(task.status));
108
- if (task.due_date) label("Due", formatDate(task.due_date));
109
- });
110
-
111
- const tasksShow = new Command("show")
112
- .description("Show task details")
113
- .argument("<id>", "Task ID")
114
- .option("--json", "Output raw JSON")
115
- .action(async (id: string, opts) => {
116
- const task = await apiCall<Task>("GET", `/v1/tasks/${id}`);
117
-
118
- if (opts.json) {
119
- console.log(JSON.stringify(task, null, 2));
120
- return;
121
- }
122
-
123
- console.log();
124
- label("ID", task.id);
125
- label("Content", task.content);
126
- label("Status", statusBadge(task.status));
127
- label("Priority", priorityBadge(task.priority));
128
- const labels = typeof task.labels === "string" ? JSON.parse(task.labels) : task.labels;
129
- if (labels && labels.length > 0) {
130
- label("Labels", labels.join(", "));
131
- }
132
- if (task.due_date) label("Due", formatDate(task.due_date));
133
- if (task.assigned_to_agent_id) label("Assigned To", task.assigned_to_agent_id);
134
- label("Created", formatDate(task.created_at || ""));
135
- if (task.updated_at) label("Updated", formatDate(task.updated_at));
136
- if (task.completed_at) label("Completed", formatDate(task.completed_at));
137
-
138
- if (task.comments && task.comments.length > 0) {
139
- console.log();
140
- console.log("Comments:");
141
- for (const c of task.comments) {
142
- console.log(` [${formatDate(c.created_at || "")}] ${c.content}`);
143
- }
144
- }
145
- console.log();
146
- });
147
-
148
- const tasksComplete = new Command("complete")
149
- .description("Mark a task as completed")
150
- .argument("<id>", "Task ID")
151
- .action(async (id: string) => {
152
- await apiCall("POST", `/v1/tasks/${id}/complete`);
153
- console.log(`Task ${id} completed.`);
154
- });
155
-
156
- const tasksDelete = new Command("delete")
157
- .description("Delete a task")
158
- .argument("<id>", "Task ID")
159
- .action(async (id: string) => {
160
- const yes = await confirm(`Delete task ${id}? (y/N) `);
161
- if (!yes) {
162
- console.log("Cancelled.");
163
- return;
164
- }
165
- await apiCall("DELETE", `/v1/tasks/${id}`);
166
- console.log(`Task ${id} deleted.`);
167
- });
168
-
169
- const tasksDelegate = new Command("delegate")
170
- .description("Delegate a task to another agent")
171
- .argument("<task_id>", "Task ID")
172
- .argument("<agent_id>", "Agent ID to delegate to")
173
- .requiredOption("--content <content>", "Subtask description (required)")
174
- .action(async (taskId: string, agentId: string, opts) => {
175
- const body: Record<string, unknown> = { assigned_to_agent_id: agentId };
176
- if (opts.content) body.content = opts.content;
177
-
178
- await apiCall("POST", `/v1/tasks/${taskId}/delegate`, body);
179
- console.log(`Task delegated to ${agentId}.`);
180
- });
181
-
182
- export const tasksCommand = new Command("tasks")
183
- .description("Manage tasks")
184
- .addCommand(tasksList)
185
- .addCommand(tasksCreate)
186
- .addCommand(tasksShow)
187
- .addCommand(tasksComplete)
188
- .addCommand(tasksDelete)
189
- .addCommand(tasksDelegate);
@@ -1,47 +0,0 @@
1
- import { Command } from "commander";
2
- import { apiCall } from "../api.js";
3
- import { label } from "../ui.js";
4
-
5
- interface Agent {
6
- id: string;
7
- name: string;
8
- display_name?: string;
9
- email?: string;
10
- plan?: string;
11
- active?: boolean;
12
- user?: {
13
- email?: string;
14
- plan?: string;
15
- };
16
- }
17
-
18
- export const whoamiCommand = new Command("whoami")
19
- .description("Show current authenticated agent")
20
- .action(async () => {
21
- const data = await apiCall<Agent | Agent[]>("GET", "/v1/agents");
22
-
23
- let agent: Agent;
24
- if (Array.isArray(data)) {
25
- if (data.length === 0) {
26
- console.error("No agent found.");
27
- process.exit(1);
28
- }
29
- agent = data[0];
30
- } else {
31
- agent = data;
32
- }
33
-
34
- console.log();
35
- label("Agent", agent.name);
36
- if (agent.display_name) {
37
- label("Display Name", agent.display_name);
38
- }
39
- if (agent.user?.email || agent.email) {
40
- label("Email", agent.user?.email || agent.email || "");
41
- }
42
- if (agent.user?.plan || agent.plan) {
43
- label("Plan", agent.user?.plan || agent.plan || "");
44
- }
45
- label("Active", agent.active !== false ? "yes" : "no");
46
- console.log();
47
- });