cortask 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sebastian Kraus
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.js ADDED
@@ -0,0 +1,724 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { Command as Command4 } from "commander";
5
+ import {
6
+ loadConfig as loadConfig3,
7
+ getDataDir as getDataDir4,
8
+ WorkspaceManager as WorkspaceManager2,
9
+ SessionStore,
10
+ EncryptedCredentialStore,
11
+ getOrCreateSecret,
12
+ createProvider,
13
+ AgentRunner,
14
+ builtinTools,
15
+ createCronTool,
16
+ createArtifactTool,
17
+ loadSkills,
18
+ getEligibleSkills,
19
+ buildSkillTools,
20
+ CronService,
21
+ ArtifactStore,
22
+ installSkillFromGit,
23
+ removeSkill
24
+ } from "@cortask/core";
25
+ import path4 from "path";
26
+ import readline from "readline";
27
+
28
+ // src/terminal/theme.ts
29
+ import chalk, { Chalk } from "chalk";
30
+ var PALETTE = {
31
+ accent: "#6366f1",
32
+ accentBright: "#818cf8",
33
+ accentDim: "#a5b4fc",
34
+ info: "#38bdf8",
35
+ success: "#22c55e",
36
+ warn: "#f59e0b",
37
+ error: "#ef4444",
38
+ muted: "#9ca3af"
39
+ };
40
+ var hasForceColor = typeof process.env.FORCE_COLOR === "string" && process.env.FORCE_COLOR.trim().length > 0 && process.env.FORCE_COLOR.trim() !== "0";
41
+ var baseChalk = process.env.NO_COLOR && !hasForceColor ? new Chalk({ level: 0 }) : chalk;
42
+ var hex = (value) => baseChalk.hex(value);
43
+ var theme = {
44
+ accent: hex(PALETTE.accent),
45
+ accentBright: hex(PALETTE.accentBright),
46
+ accentDim: hex(PALETTE.accentDim),
47
+ info: hex(PALETTE.info),
48
+ success: hex(PALETTE.success),
49
+ warn: hex(PALETTE.warn),
50
+ error: hex(PALETTE.error),
51
+ muted: hex(PALETTE.muted),
52
+ heading: baseChalk.bold.hex(PALETTE.accent),
53
+ command: hex(PALETTE.accentBright),
54
+ option: hex(PALETTE.warn)
55
+ };
56
+ var isRich = () => Boolean(baseChalk.level > 0);
57
+
58
+ // src/terminal/banner.ts
59
+ var bannerEmitted = false;
60
+ var hasFlag = (argv, ...flags) => argv.some((arg) => flags.includes(arg));
61
+ function emitBanner(version, argv) {
62
+ if (bannerEmitted) return;
63
+ const args = argv ?? process.argv;
64
+ if (!process.stdout.isTTY) return;
65
+ if (hasFlag(args, "--json", "--version", "-V")) return;
66
+ const title = "\u26A1 Cortask";
67
+ const tagline = "Local AI agent platform";
68
+ if (isRich()) {
69
+ process.stdout.write(
70
+ `
71
+ ${theme.heading(title)} ${theme.info(version)} ${theme.muted("\u2014")} ${theme.accentDim(tagline)}
72
+
73
+ `
74
+ );
75
+ } else {
76
+ process.stdout.write(`
77
+ ${title} ${version} \u2014 ${tagline}
78
+
79
+ `);
80
+ }
81
+ bannerEmitted = true;
82
+ }
83
+ function hasBannerEmitted() {
84
+ return bannerEmitted;
85
+ }
86
+
87
+ // src/terminal/help.ts
88
+ var EXAMPLES = [
89
+ ["cortask serve", "Start the gateway server"],
90
+ ["cortask chat", "Start interactive chat session"],
91
+ ['cortask run "hello"', "Run a one-shot prompt"],
92
+ ["cortask status", "Show system status"],
93
+ ["cortask dashboard", "Open the web UI"],
94
+ ["cortask setup", "Initialize configuration"],
95
+ ["cortask workspaces list", "List registered workspaces"],
96
+ ["cortask credentials set provider.anthropic.apiKey KEY", "Set API key"]
97
+ ];
98
+ function configureHelp(program2, version) {
99
+ program2.helpOption("-h, --help", "Display help for command");
100
+ program2.helpCommand("help [command]", "Display help for command");
101
+ program2.configureHelp({
102
+ sortSubcommands: true,
103
+ sortOptions: true,
104
+ optionTerm: (option) => theme.option(option.flags),
105
+ subcommandTerm: (cmd) => theme.command(cmd.name())
106
+ });
107
+ const formatHelp = (str) => str.replace(/^Usage:/gm, theme.heading("Usage:")).replace(/^Options:/gm, theme.heading("Options:")).replace(/^Commands:/gm, theme.heading("Commands:")).replace(/^Arguments:/gm, theme.heading("Arguments:"));
108
+ program2.configureOutput({
109
+ writeOut: (str) => process.stdout.write(formatHelp(str)),
110
+ writeErr: (str) => process.stderr.write(formatHelp(str)),
111
+ outputError: (str, write) => write(theme.error(str))
112
+ });
113
+ program2.addHelpText("beforeAll", () => {
114
+ if (hasBannerEmitted()) return "";
115
+ emitBanner(version);
116
+ return "";
117
+ });
118
+ const fmtExamples = EXAMPLES.map(
119
+ ([cmd, desc]) => ` ${theme.command(cmd)}
120
+ ${theme.muted(desc)}`
121
+ ).join("\n");
122
+ program2.addHelpText("afterAll", ({ command }) => {
123
+ if (command !== program2) return "";
124
+ return `
125
+ ${theme.heading("Examples:")}
126
+ ${fmtExamples}
127
+ `;
128
+ });
129
+ }
130
+
131
+ // src/commands/setup.ts
132
+ import { Command } from "commander";
133
+ import fs from "fs";
134
+ import path from "path";
135
+ import { getDataDir } from "@cortask/core";
136
+ var DEFAULT_CONFIG = `# Cortask Configuration
137
+ onboarded: true
138
+
139
+ providers:
140
+ default: anthropic
141
+
142
+ agent:
143
+ maxTurns: 25
144
+ temperature: 0.7
145
+
146
+ server:
147
+ port: 3777
148
+ host: 127.0.0.1
149
+
150
+ skills:
151
+ dirs: []
152
+ `;
153
+ function ensureDir(dir) {
154
+ if (!fs.existsSync(dir)) {
155
+ fs.mkdirSync(dir, { recursive: true });
156
+ }
157
+ }
158
+ var setupCommand = new Command("setup").description("Initialize configuration and data directory").option("--force", "Overwrite existing configuration").action(async (opts) => {
159
+ const dataDir = getDataDir();
160
+ const configPath = path.join(dataDir, "config.yaml");
161
+ console.log(theme.heading("\n\u26A1 Cortask Setup\n"));
162
+ if (fs.existsSync(configPath) && !opts.force) {
163
+ console.log(theme.warn("\u26A0 Configuration already exists:"));
164
+ console.log(theme.info(` ${configPath}`));
165
+ console.log(theme.muted("\n Use --force to overwrite"));
166
+ console.log();
167
+ process.exit(1);
168
+ }
169
+ try {
170
+ ensureDir(dataDir);
171
+ console.log(`${theme.success("\u2713")} Data directory: ${theme.info(dataDir)}`);
172
+ fs.writeFileSync(configPath, DEFAULT_CONFIG, "utf-8");
173
+ console.log(`${theme.success("\u2713")} Config: ${theme.info(configPath)}`);
174
+ const skillsDir = path.join(dataDir, "skills");
175
+ ensureDir(skillsDir);
176
+ console.log(`${theme.success("\u2713")} Skills: ${theme.info(skillsDir)}`);
177
+ console.log(theme.heading("\n\u2713 Setup complete!\n"));
178
+ console.log(theme.muted("Next steps:"));
179
+ console.log(theme.command(" 1. Set your API key:"));
180
+ console.log(theme.info(` cortask credentials set provider.anthropic.apiKey YOUR_KEY`));
181
+ console.log(theme.command("\n 2. Add a workspace:"));
182
+ console.log(theme.info(" cortask workspaces add my-project /path/to/project"));
183
+ console.log(theme.command("\n 3. Start chatting:"));
184
+ console.log(theme.info(" cortask chat -w /path/to/project"));
185
+ console.log();
186
+ } catch (err) {
187
+ console.error(theme.error("\n\u2717 Setup failed"));
188
+ console.error(theme.muted(` ${err.message}`));
189
+ process.exit(1);
190
+ }
191
+ });
192
+
193
+ // src/commands/status.ts
194
+ import { Command as Command2 } from "commander";
195
+ import fs2 from "fs";
196
+ import path2 from "path";
197
+ import { getDataDir as getDataDir2, loadConfig, WorkspaceManager } from "@cortask/core";
198
+ async function fetchHealth(host, port) {
199
+ try {
200
+ const res = await fetch(`http://${host}:${port}/api/health`);
201
+ if (!res.ok) return null;
202
+ return res.json();
203
+ } catch {
204
+ return null;
205
+ }
206
+ }
207
+ var statusCommand = new Command2("status").description("Show system status and configuration").action(async () => {
208
+ const dataDir = getDataDir2();
209
+ const configPath = path2.join(dataDir, "config.yaml");
210
+ if (!fs2.existsSync(configPath)) {
211
+ console.error(theme.error("\n\u2717 No configuration found"));
212
+ console.error(theme.muted(" Run this command to set up:"));
213
+ console.error(theme.command(" cortask setup"));
214
+ console.log();
215
+ process.exit(1);
216
+ }
217
+ try {
218
+ const config = await loadConfig(configPath);
219
+ const host = config.server.host;
220
+ const port = config.server.port;
221
+ console.log(theme.heading("\n Configuration"));
222
+ console.log(` File: ${theme.info(configPath)}`);
223
+ console.log(` Data: ${theme.info(dataDir)}`);
224
+ console.log(theme.heading("\n Gateway"));
225
+ const health = await fetchHealth(host, port);
226
+ if (health) {
227
+ console.log(` Status: ${theme.success("online")}`);
228
+ console.log(` URL: ${theme.info(`http://${host}:${port}`)}`);
229
+ } else {
230
+ console.log(` Status: ${theme.error("offline")}`);
231
+ console.log(` Expected: ${theme.muted(`http://${host}:${port}`)}`);
232
+ }
233
+ console.log(theme.heading("\n Provider"));
234
+ console.log(` Default: ${theme.command(config.providers.default)}`);
235
+ console.log(theme.heading("\n Workspaces"));
236
+ const dbPath = path2.join(dataDir, "cortask.db");
237
+ if (fs2.existsSync(dbPath)) {
238
+ const wm = new WorkspaceManager(dbPath);
239
+ const workspaces = await wm.list();
240
+ if (workspaces.length === 0) {
241
+ console.log(` ${theme.muted("No workspaces registered")}`);
242
+ } else {
243
+ for (const w of workspaces) {
244
+ console.log(` ${theme.success("\u2713")} ${theme.command(w.name)} ${theme.muted(`\u2192 ${w.rootPath}`)}`);
245
+ }
246
+ }
247
+ wm.close();
248
+ } else {
249
+ console.log(` ${theme.muted("Database not initialized")}`);
250
+ }
251
+ console.log(theme.heading("\n Skills"));
252
+ const skillsDir = path2.join(dataDir, "skills");
253
+ if (fs2.existsSync(skillsDir)) {
254
+ const entries = fs2.readdirSync(skillsDir).filter(
255
+ (e) => fs2.statSync(path2.join(skillsDir, e)).isDirectory()
256
+ );
257
+ console.log(` Installed: ${theme.info(entries.length.toString())} skill(s)`);
258
+ } else {
259
+ console.log(` ${theme.muted("No skills directory")}`);
260
+ }
261
+ console.log();
262
+ } catch (err) {
263
+ console.error(theme.error("\n\u2717 Failed to load status"));
264
+ console.error(theme.muted(` ${err.message}`));
265
+ process.exit(1);
266
+ }
267
+ });
268
+
269
+ // src/commands/dashboard.ts
270
+ import { Command as Command3 } from "commander";
271
+ import { exec } from "child_process";
272
+ import path3 from "path";
273
+ import { getDataDir as getDataDir3, loadConfig as loadConfig2 } from "@cortask/core";
274
+ function openBrowser(url) {
275
+ const cmd = process.platform === "win32" ? `start ${url}` : process.platform === "darwin" ? `open ${url}` : `xdg-open ${url}`;
276
+ return new Promise((resolve, reject) => {
277
+ exec(cmd, (err) => err ? reject(err) : resolve());
278
+ });
279
+ }
280
+ async function isGatewayOnline(host, port) {
281
+ try {
282
+ const res = await fetch(`http://${host}:${port}/api/health`);
283
+ return res.ok;
284
+ } catch {
285
+ return false;
286
+ }
287
+ }
288
+ var dashboardCommand = new Command3("dashboard").description("Open the web UI in your browser").option("--no-open", "Print URL without opening browser").action(async (opts) => {
289
+ const dataDir = getDataDir3();
290
+ const configPath = path3.join(dataDir, "config.yaml");
291
+ const config = await loadConfig2(configPath);
292
+ const url = `http://${config.server.host}:${config.server.port}`;
293
+ const online = await isGatewayOnline(config.server.host, config.server.port);
294
+ if (!online) {
295
+ console.log(theme.warn("\n\u26A0 Gateway appears to be offline"));
296
+ console.log(theme.muted(" Start it with:"));
297
+ console.log(theme.command(" cortask serve"));
298
+ console.log();
299
+ }
300
+ if (opts.open) {
301
+ console.log(theme.info(`
302
+ Opening dashboard: ${url}`));
303
+ try {
304
+ await openBrowser(url);
305
+ console.log(theme.success("\u2713 Browser opened"));
306
+ } catch {
307
+ console.log(theme.warn("\n\u26A0 Could not open browser automatically"));
308
+ console.log(theme.info(` Open this URL manually: ${url}`));
309
+ }
310
+ } else {
311
+ console.log(theme.info(`
312
+ Dashboard URL: ${url}`));
313
+ }
314
+ console.log();
315
+ });
316
+
317
+ // src/index.ts
318
+ import { createRequire } from "module";
319
+ var require2 = createRequire(import.meta.url);
320
+ var VERSION = require2("../package.json").version;
321
+ var program = new Command4();
322
+ program.name("cortask").description("Cortask \u2014 Local AI agent with skills, workspaces, and cron").version(VERSION);
323
+ configureHelp(program, VERSION);
324
+ program.command("serve").description("Start the gateway server").option("-p, --port <port>", "Port to listen on", "3777").option("--host <host>", "Host to bind to", "127.0.0.1").action(async (opts) => {
325
+ emitBanner(VERSION);
326
+ const { startServer } = await import("@cortask/gateway");
327
+ console.log(
328
+ `${theme.muted("Starting gateway on")} ${theme.info(`http://${opts.host}:${opts.port}`)}`
329
+ );
330
+ await startServer(parseInt(opts.port, 10), opts.host);
331
+ });
332
+ program.command("chat").description("Interactive chat REPL").option("-w, --workspace <path>", "Workspace directory path", ".").action(async (opts) => {
333
+ emitBanner(VERSION);
334
+ const dataDir = getDataDir4();
335
+ const configPath = path4.join(dataDir, "config.yaml");
336
+ const config = await loadConfig3(configPath);
337
+ const dbPath = path4.join(dataDir, "cortask.db");
338
+ const workspaceManager = new WorkspaceManager2(dbPath);
339
+ const secret = await getOrCreateSecret(dataDir);
340
+ const credentialStore = new EncryptedCredentialStore(
341
+ path4.join(dataDir, "credentials.enc.json"),
342
+ secret
343
+ );
344
+ const cronService = new CronService(dbPath);
345
+ const artifactStore = new ArtifactStore();
346
+ const workspacePath = path4.resolve(opts.workspace);
347
+ const workspaces = await workspaceManager.list();
348
+ let workspace = workspaces.find((w) => w.rootPath === workspacePath);
349
+ if (!workspace) {
350
+ workspace = await workspaceManager.create(
351
+ path4.basename(workspacePath),
352
+ workspacePath
353
+ );
354
+ console.log(
355
+ `${theme.success("\u2713")} Registered workspace: ${theme.command(workspace.name)}`
356
+ );
357
+ }
358
+ const sessionStore = new SessionStore(
359
+ workspaceManager.getSessionDbPath(workspacePath)
360
+ );
361
+ const bundledSkillsDir = path4.resolve("skills");
362
+ const userSkillsDir = path4.join(dataDir, "skills");
363
+ const allSkills = await loadSkills(
364
+ bundledSkillsDir,
365
+ userSkillsDir,
366
+ config.skills.dirs,
367
+ credentialStore
368
+ );
369
+ const eligible = getEligibleSkills(allSkills);
370
+ const skillRegistry = await buildSkillTools(eligible, credentialStore);
371
+ const skillToolHandlers = skillRegistry.toolDefs.map((def) => ({
372
+ definition: def,
373
+ execute: async (args, context) => {
374
+ const handler = skillRegistry.handlers.get(def.name);
375
+ if (!handler) return { toolCallId: "", content: "Tool not found", isError: true };
376
+ return handler(args);
377
+ }
378
+ }));
379
+ const skillPrompts = eligible.map((s) => s.content).filter(Boolean);
380
+ const providerId = config.providers.default || "anthropic";
381
+ const providerConfig = config.providers[providerId];
382
+ const apiKey = await credentialStore.get(`provider.${providerId}.apiKey`);
383
+ if (!apiKey) {
384
+ console.error(theme.error(`
385
+ \u2717 No API key for provider "${providerId}"`));
386
+ console.error(theme.muted(" Set it with:"));
387
+ console.error(
388
+ theme.command(
389
+ ` cortask credentials set provider.${providerId}.apiKey YOUR_KEY`
390
+ )
391
+ );
392
+ console.log();
393
+ process.exit(1);
394
+ }
395
+ const provider = createProvider(providerId, apiKey);
396
+ const model = providerConfig?.model ?? "claude-sonnet-4-5-20250929";
397
+ const sessionId = `cli_${Date.now()}`;
398
+ const runner = new AgentRunner({
399
+ config: {
400
+ provider,
401
+ model,
402
+ maxTurns: config.agent.maxTurns,
403
+ temperature: config.agent.temperature,
404
+ maxTokens: config.agent.maxTokens
405
+ },
406
+ tools: [
407
+ ...builtinTools,
408
+ createCronTool(cronService),
409
+ createArtifactTool(artifactStore),
410
+ ...skillToolHandlers
411
+ ],
412
+ getWorkspacePath: () => workspacePath,
413
+ getDataDir: () => dataDir,
414
+ getMemoryContent: () => workspaceManager.readMemory(workspacePath),
415
+ getGlobalMemoryContent: () => workspaceManager.readGlobalMemory(dataDir),
416
+ getSkillPrompts: () => skillPrompts,
417
+ getSessionMessages: async (sid) => sessionStore.getMessages(sid),
418
+ saveSessionMessages: async (sid, msgs) => sessionStore.saveMessages(sid, msgs)
419
+ });
420
+ console.log(
421
+ `${theme.muted("Workspace:")} ${theme.info(workspacePath)}`
422
+ );
423
+ console.log(
424
+ `${theme.muted("Provider:")} ${theme.command(providerId)} ${theme.muted(`(${model})`)}`
425
+ );
426
+ console.log(
427
+ theme.muted("Type a message, /help for commands, /quit to exit.\n")
428
+ );
429
+ const rl = readline.createInterface({
430
+ input: process.stdin,
431
+ output: process.stdout,
432
+ prompt: `${theme.accent("you>")} `
433
+ });
434
+ rl.prompt();
435
+ rl.on("line", async (line) => {
436
+ const input = line.trim();
437
+ if (!input) {
438
+ rl.prompt();
439
+ return;
440
+ }
441
+ if (input.startsWith("/")) {
442
+ const cmd = input.toLowerCase();
443
+ if (cmd === "/quit" || cmd === "/exit") {
444
+ rl.close();
445
+ return;
446
+ }
447
+ if (cmd === "/help") {
448
+ console.log(theme.heading("\nCommands:"));
449
+ console.log(` ${theme.command("/help")} ${theme.muted("Show this help")}`);
450
+ console.log(` ${theme.command("/quit")} ${theme.muted("Exit the REPL")}`);
451
+ console.log();
452
+ rl.prompt();
453
+ return;
454
+ }
455
+ console.log(theme.warn(`Unknown command: ${input}. Type /help for commands.`));
456
+ rl.prompt();
457
+ return;
458
+ }
459
+ process.stdout.write(`
460
+ ${theme.accentBright("cortask>")} `);
461
+ try {
462
+ for await (const event of runner.runStream({
463
+ prompt: input,
464
+ sessionId
465
+ })) {
466
+ if (event.type === "text_delta" && event.text) {
467
+ process.stdout.write(event.text);
468
+ } else if (event.type === "tool_call_start") {
469
+ process.stdout.write(
470
+ `
471
+ ${theme.muted("[")}${theme.warn("tool")}${theme.muted(":")} ${theme.command(event.toolName)}${theme.muted("]")} `
472
+ );
473
+ } else if (event.type === "tool_result") {
474
+ const preview = event.toolResult?.content?.slice(0, 200) ?? "";
475
+ process.stdout.write(`${theme.muted("\u2192")} ${theme.muted(preview)}
476
+ `);
477
+ }
478
+ }
479
+ } catch (err) {
480
+ console.error(
481
+ theme.error(
482
+ `
483
+ \u2717 ${err instanceof Error ? err.message : String(err)}`
484
+ )
485
+ );
486
+ }
487
+ process.stdout.write("\n\n");
488
+ rl.prompt();
489
+ });
490
+ rl.on("close", () => {
491
+ console.log(theme.muted("\nGoodbye."));
492
+ workspaceManager.close();
493
+ process.exit(0);
494
+ });
495
+ });
496
+ program.command("run").description("Run a one-shot prompt").argument("<prompt>", "The prompt to execute").option("-w, --workspace <path>", "Workspace directory path", ".").action(async (prompt, opts) => {
497
+ const dataDir = getDataDir4();
498
+ const configPath = path4.join(dataDir, "config.yaml");
499
+ const config = await loadConfig3(configPath);
500
+ const dbPath = path4.join(dataDir, "cortask.db");
501
+ const workspaceManager = new WorkspaceManager2(dbPath);
502
+ const secret = await getOrCreateSecret(dataDir);
503
+ const credentialStore = new EncryptedCredentialStore(
504
+ path4.join(dataDir, "credentials.enc.json"),
505
+ secret
506
+ );
507
+ const cronService = new CronService(dbPath);
508
+ const artifactStore = new ArtifactStore();
509
+ const workspacePath = path4.resolve(opts.workspace);
510
+ const workspaces = await workspaceManager.list();
511
+ let workspace = workspaces.find((w) => w.rootPath === workspacePath);
512
+ if (!workspace) {
513
+ workspace = await workspaceManager.create(
514
+ path4.basename(workspacePath),
515
+ workspacePath
516
+ );
517
+ }
518
+ const sessionStore = new SessionStore(
519
+ workspaceManager.getSessionDbPath(workspacePath)
520
+ );
521
+ const providerId = config.providers.default || "anthropic";
522
+ const apiKey = await credentialStore.get(`provider.${providerId}.apiKey`);
523
+ if (!apiKey) {
524
+ console.error(theme.error(`
525
+ \u2717 No API key for provider "${providerId}".`));
526
+ console.error(theme.muted(" Set it with:"));
527
+ console.error(
528
+ theme.command(
529
+ ` cortask credentials set provider.${providerId}.apiKey YOUR_KEY`
530
+ )
531
+ );
532
+ process.exit(1);
533
+ }
534
+ const provider = createProvider(providerId, apiKey);
535
+ const providerConfig = config.providers[providerId];
536
+ const model = providerConfig?.model ?? "claude-sonnet-4-5-20250929";
537
+ const runner = new AgentRunner({
538
+ config: {
539
+ provider,
540
+ model,
541
+ maxTurns: config.agent.maxTurns,
542
+ temperature: config.agent.temperature,
543
+ maxTokens: config.agent.maxTokens
544
+ },
545
+ tools: [
546
+ ...builtinTools,
547
+ createCronTool(cronService),
548
+ createArtifactTool(artifactStore)
549
+ ],
550
+ getWorkspacePath: () => workspacePath,
551
+ getDataDir: () => dataDir,
552
+ getMemoryContent: () => workspaceManager.readMemory(workspacePath),
553
+ getGlobalMemoryContent: () => workspaceManager.readGlobalMemory(dataDir),
554
+ getSkillPrompts: () => [],
555
+ getSessionMessages: async (sid) => sessionStore.getMessages(sid),
556
+ saveSessionMessages: async (sid, msgs) => sessionStore.saveMessages(sid, msgs)
557
+ });
558
+ const result = await runner.run({ prompt });
559
+ console.log(result.response);
560
+ workspaceManager.close();
561
+ });
562
+ program.addCommand(setupCommand);
563
+ program.addCommand(statusCommand);
564
+ program.addCommand(dashboardCommand);
565
+ var ws = program.command("workspaces").description("Manage workspaces");
566
+ ws.command("list").action(async () => {
567
+ const dataDir = getDataDir4();
568
+ const dbPath = path4.join(dataDir, "cortask.db");
569
+ const wm = new WorkspaceManager2(dbPath);
570
+ const list = await wm.list();
571
+ if (list.length === 0) {
572
+ console.log(theme.muted("No workspaces registered."));
573
+ } else {
574
+ for (const w of list) {
575
+ console.log(
576
+ ` ${theme.success("\u2713")} ${theme.command(w.name)} ${theme.muted("\u2192")} ${theme.info(w.rootPath)} ${theme.muted(`(${w.id})`)}`
577
+ );
578
+ }
579
+ }
580
+ wm.close();
581
+ });
582
+ ws.command("add").argument("<name>", "Workspace name").argument("<path>", "Workspace directory path").action(async (name, dirPath) => {
583
+ const dataDir = getDataDir4();
584
+ const dbPath = path4.join(dataDir, "cortask.db");
585
+ const wm = new WorkspaceManager2(dbPath);
586
+ const workspace = await wm.create(name, dirPath);
587
+ console.log(
588
+ `${theme.success("\u2713")} Created workspace ${theme.command(workspace.name)} ${theme.muted(`(${workspace.id})`)}`
589
+ );
590
+ console.log(` ${theme.muted("Path:")} ${theme.info(workspace.rootPath)}`);
591
+ wm.close();
592
+ });
593
+ ws.command("remove").argument("<id>", "Workspace ID").action(async (id) => {
594
+ const dataDir = getDataDir4();
595
+ const dbPath = path4.join(dataDir, "cortask.db");
596
+ const wm = new WorkspaceManager2(dbPath);
597
+ await wm.delete(id);
598
+ console.log(`${theme.success("\u2713")} Removed workspace ${theme.muted(id)}`);
599
+ wm.close();
600
+ });
601
+ var creds = program.command("credentials").description("Manage credentials");
602
+ creds.command("list").action(async () => {
603
+ const dataDir = getDataDir4();
604
+ const secret = await getOrCreateSecret(dataDir);
605
+ const store = new EncryptedCredentialStore(
606
+ path4.join(dataDir, "credentials.enc.json"),
607
+ secret
608
+ );
609
+ const keys = await store.list();
610
+ if (keys.length === 0) {
611
+ console.log(theme.muted("No credentials stored."));
612
+ } else {
613
+ for (const key of keys) {
614
+ console.log(` ${theme.muted("\u2022")} ${theme.command(key)}`);
615
+ }
616
+ }
617
+ });
618
+ creds.command("set").argument("<key>", "Credential key (e.g. provider.anthropic.apiKey)").argument("<value>", "Credential value").action(async (key, value) => {
619
+ const dataDir = getDataDir4();
620
+ const secret = await getOrCreateSecret(dataDir);
621
+ const store = new EncryptedCredentialStore(
622
+ path4.join(dataDir, "credentials.enc.json"),
623
+ secret
624
+ );
625
+ await store.set(key, value);
626
+ console.log(`${theme.success("\u2713")} Credential ${theme.command(key)} saved.`);
627
+ });
628
+ creds.command("remove").argument("<key>", "Credential key").action(async (key) => {
629
+ const dataDir = getDataDir4();
630
+ const secret = await getOrCreateSecret(dataDir);
631
+ const store = new EncryptedCredentialStore(
632
+ path4.join(dataDir, "credentials.enc.json"),
633
+ secret
634
+ );
635
+ await store.delete(key);
636
+ console.log(`${theme.success("\u2713")} Credential ${theme.command(key)} removed.`);
637
+ });
638
+ var sk = program.command("skills").description("Manage skills");
639
+ sk.command("list").action(async () => {
640
+ const dataDir = getDataDir4();
641
+ const secret = await getOrCreateSecret(dataDir);
642
+ const credentialStore = new EncryptedCredentialStore(
643
+ path4.join(dataDir, "credentials.enc.json"),
644
+ secret
645
+ );
646
+ const bundledSkillsDir = path4.resolve("skills");
647
+ const userSkillsDir = path4.join(dataDir, "skills");
648
+ const configPath = path4.join(dataDir, "config.yaml");
649
+ const config = await loadConfig3(configPath);
650
+ const allSkills = await loadSkills(
651
+ bundledSkillsDir,
652
+ userSkillsDir,
653
+ config.skills.dirs,
654
+ credentialStore
655
+ );
656
+ if (allSkills.length === 0) {
657
+ console.log(theme.muted("No skills found."));
658
+ } else {
659
+ for (const skill of allSkills) {
660
+ const icon = skill.eligible ? theme.success("\u2713") : theme.muted("\u25CB");
661
+ const name = theme.command(skill.manifest.name);
662
+ const desc = theme.muted(skill.manifest.description ?? "");
663
+ console.log(` ${icon} ${name} ${desc}`);
664
+ }
665
+ }
666
+ });
667
+ sk.command("install").argument("<git-url>", "Git URL of the skill repository").action(async (gitUrl) => {
668
+ const dataDir = getDataDir4();
669
+ const userSkillsDir = path4.join(dataDir, "skills");
670
+ const result = await installSkillFromGit(gitUrl, userSkillsDir);
671
+ console.log(
672
+ `${theme.success("\u2713")} Installed skill ${theme.command(result.name)}`
673
+ );
674
+ });
675
+ sk.command("remove").argument("<name>", "Skill name").action(async (name) => {
676
+ const dataDir = getDataDir4();
677
+ const userSkillsDir = path4.join(dataDir, "skills");
678
+ await removeSkill(name, userSkillsDir);
679
+ console.log(`${theme.success("\u2713")} Removed skill ${theme.command(name)}`);
680
+ });
681
+ var cr = program.command("cron").description("Manage cron jobs");
682
+ cr.command("list").action(async () => {
683
+ const dataDir = getDataDir4();
684
+ const dbPath = path4.join(dataDir, "cortask.db");
685
+ const cronService = new CronService(dbPath);
686
+ const jobs = cronService.list();
687
+ if (jobs.length === 0) {
688
+ console.log(theme.muted("No cron jobs."));
689
+ } else {
690
+ for (const job of jobs) {
691
+ const icon = job.enabled ? theme.success("\u2713") : theme.muted("\u25CB");
692
+ console.log(` ${icon} ${theme.command(job.name)} ${theme.muted(`(${job.id})`)}`);
693
+ console.log(` ${theme.muted("Schedule:")} ${theme.info(JSON.stringify(job.schedule))}`);
694
+ console.log(` ${theme.muted("Prompt:")} ${job.prompt.slice(0, 80)}...`);
695
+ }
696
+ }
697
+ cronService.stop();
698
+ });
699
+ cr.command("add").requiredOption("-n, --name <name>", "Job name").requiredOption("-s, --schedule <cron>", "Cron expression").requiredOption("-p, --prompt <prompt>", "Prompt to execute").option("-w, --workspace <id>", "Workspace ID").action(async (opts) => {
700
+ const dataDir = getDataDir4();
701
+ const dbPath = path4.join(dataDir, "cortask.db");
702
+ const cronService = new CronService(dbPath);
703
+ const job = cronService.add({
704
+ name: opts.name,
705
+ schedule: { type: "cron", expression: opts.schedule },
706
+ prompt: opts.prompt,
707
+ delivery: {},
708
+ workspaceId: opts.workspace
709
+ });
710
+ console.log(
711
+ `${theme.success("\u2713")} Created cron job ${theme.command(job.name)} ${theme.muted(`(${job.id})`)}`
712
+ );
713
+ cronService.stop();
714
+ });
715
+ cr.command("remove").argument("<id>", "Job ID").action(async (id) => {
716
+ const dataDir = getDataDir4();
717
+ const dbPath = path4.join(dataDir, "cortask.db");
718
+ const cronService = new CronService(dbPath);
719
+ cronService.remove(id);
720
+ console.log(`${theme.success("\u2713")} Deleted cron job ${theme.muted(id)}`);
721
+ cronService.stop();
722
+ });
723
+ program.parse();
724
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/terminal/theme.ts","../src/terminal/banner.ts","../src/terminal/help.ts","../src/commands/setup.ts","../src/commands/status.ts","../src/commands/dashboard.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport {\n loadConfig,\n getDataDir,\n WorkspaceManager,\n SessionStore,\n EncryptedCredentialStore,\n getOrCreateSecret,\n createProvider,\n AgentRunner,\n builtinTools,\n createCronTool,\n createArtifactTool,\n loadSkills,\n getEligibleSkills,\n buildSkillTools,\n CronService,\n ArtifactStore,\n installSkillFromGit,\n removeSkill,\n type ProviderId,\n type ToolHandler,\n} from \"@cortask/core\";\nimport path from \"node:path\";\nimport readline from \"node:readline\";\nimport { theme } from \"./terminal/theme.js\";\nimport { emitBanner } from \"./terminal/banner.js\";\nimport { configureHelp } from \"./terminal/help.js\";\nimport { setupCommand } from \"./commands/setup.js\";\nimport { statusCommand } from \"./commands/status.js\";\nimport { dashboardCommand } from \"./commands/dashboard.js\";\nimport { createRequire } from \"node:module\";\n\nconst require = createRequire(import.meta.url);\nconst VERSION: string = require(\"../package.json\").version;\n\nconst program = new Command();\n\nprogram\n .name(\"cortask\")\n .description(\"Cortask — Local AI agent with skills, workspaces, and cron\")\n .version(VERSION);\n\n// Configure themed help and banner\nconfigureHelp(program, VERSION);\n\n// ── serve ──────────────────────────────────────────────────\n\nprogram\n .command(\"serve\")\n .description(\"Start the gateway server\")\n .option(\"-p, --port <port>\", \"Port to listen on\", \"3777\")\n .option(\"--host <host>\", \"Host to bind to\", \"127.0.0.1\")\n .action(async (opts) => {\n emitBanner(VERSION);\n const { startServer } = await import(\"@cortask/gateway\");\n console.log(\n `${theme.muted(\"Starting gateway on\")} ${theme.info(`http://${opts.host}:${opts.port}`)}`,\n );\n await startServer(parseInt(opts.port, 10), opts.host);\n });\n\n// ── chat ───────────────────────────────────────────────────\n\nprogram\n .command(\"chat\")\n .description(\"Interactive chat REPL\")\n .option(\"-w, --workspace <path>\", \"Workspace directory path\", \".\")\n .action(async (opts) => {\n emitBanner(VERSION);\n const dataDir = getDataDir();\n const configPath = path.join(dataDir, \"config.yaml\");\n const config = await loadConfig(configPath);\n const dbPath = path.join(dataDir, \"cortask.db\");\n const workspaceManager = new WorkspaceManager(dbPath);\n const secret = await getOrCreateSecret(dataDir);\n const credentialStore = new EncryptedCredentialStore(\n path.join(dataDir, \"credentials.enc.json\"),\n secret,\n );\n const cronService = new CronService(dbPath);\n const artifactStore = new ArtifactStore();\n\n // Resolve workspace\n const workspacePath = path.resolve(opts.workspace);\n const workspaces = await workspaceManager.list();\n let workspace = workspaces.find((w) => w.rootPath === workspacePath);\n if (!workspace) {\n workspace = await workspaceManager.create(\n path.basename(workspacePath),\n workspacePath,\n );\n console.log(\n `${theme.success(\"✓\")} Registered workspace: ${theme.command(workspace.name)}`,\n );\n }\n\n const sessionStore = new SessionStore(\n workspaceManager.getSessionDbPath(workspacePath),\n );\n\n // Load skills\n const bundledSkillsDir = path.resolve(\"skills\");\n const userSkillsDir = path.join(dataDir, \"skills\");\n const allSkills = await loadSkills(\n bundledSkillsDir,\n userSkillsDir,\n config.skills.dirs,\n credentialStore,\n );\n const eligible = getEligibleSkills(allSkills);\n const skillRegistry = await buildSkillTools(eligible, credentialStore);\n const skillToolHandlers: ToolHandler[] = skillRegistry.toolDefs.map((def) => ({\n definition: def,\n execute: async (args: Record<string, unknown>, context: Parameters<ToolHandler[\"execute\"]>[1]) => {\n const handler = skillRegistry.handlers.get(def.name);\n if (!handler) return { toolCallId: \"\", content: \"Tool not found\", isError: true };\n return handler(args);\n },\n }));\n const skillPrompts = eligible\n .map((s) => s.content)\n .filter(Boolean);\n\n // Build provider\n const providerId = (config.providers.default || \"anthropic\") as ProviderId;\n const providerConfig = config.providers[providerId];\n const apiKey = await credentialStore.get(`provider.${providerId}.apiKey`);\n if (!apiKey) {\n console.error(theme.error(`\\n✗ No API key for provider \"${providerId}\"`));\n console.error(theme.muted(\" Set it with:\"));\n console.error(\n theme.command(\n ` cortask credentials set provider.${providerId}.apiKey YOUR_KEY`,\n ),\n );\n console.log();\n process.exit(1);\n }\n const provider = createProvider(providerId, apiKey);\n const model =\n ((providerConfig as Record<string, unknown>)?.model as string) ??\n \"claude-sonnet-4-5-20250929\";\n\n const sessionId = `cli_${Date.now()}`;\n\n const runner = new AgentRunner({\n config: {\n provider,\n model,\n maxTurns: config.agent.maxTurns,\n temperature: config.agent.temperature,\n maxTokens: config.agent.maxTokens,\n },\n tools: [\n ...builtinTools,\n createCronTool(cronService),\n createArtifactTool(artifactStore),\n ...skillToolHandlers,\n ],\n getWorkspacePath: () => workspacePath,\n getDataDir: () => dataDir,\n getMemoryContent: () => workspaceManager.readMemory(workspacePath),\n getGlobalMemoryContent: () => workspaceManager.readGlobalMemory(dataDir),\n getSkillPrompts: () => skillPrompts,\n getSessionMessages: async (sid) => sessionStore.getMessages(sid),\n saveSessionMessages: async (sid, msgs) =>\n sessionStore.saveMessages(sid, msgs),\n });\n\n console.log(\n `${theme.muted(\"Workspace:\")} ${theme.info(workspacePath)}`,\n );\n console.log(\n `${theme.muted(\"Provider:\")} ${theme.command(providerId)} ${theme.muted(`(${model})`)}`,\n );\n console.log(\n theme.muted(\"Type a message, /help for commands, /quit to exit.\\n\"),\n );\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n prompt: `${theme.accent(\"you>\")} `,\n });\n\n rl.prompt();\n\n rl.on(\"line\", async (line) => {\n const input = line.trim();\n if (!input) {\n rl.prompt();\n return;\n }\n\n // Slash commands\n if (input.startsWith(\"/\")) {\n const cmd = input.toLowerCase();\n if (cmd === \"/quit\" || cmd === \"/exit\") {\n rl.close();\n return;\n }\n if (cmd === \"/help\") {\n console.log(theme.heading(\"\\nCommands:\"));\n console.log(` ${theme.command(\"/help\")} ${theme.muted(\"Show this help\")}`);\n console.log(` ${theme.command(\"/quit\")} ${theme.muted(\"Exit the REPL\")}`);\n console.log();\n rl.prompt();\n return;\n }\n console.log(theme.warn(`Unknown command: ${input}. Type /help for commands.`));\n rl.prompt();\n return;\n }\n\n process.stdout.write(`\\n${theme.accentBright(\"cortask>\")} `);\n try {\n for await (const event of runner.runStream({\n prompt: input,\n sessionId,\n })) {\n if (event.type === \"text_delta\" && event.text) {\n process.stdout.write(event.text);\n } else if (event.type === \"tool_call_start\") {\n process.stdout.write(\n `\\n${theme.muted(\"[\")}${theme.warn(\"tool\")}${theme.muted(\":\")} ${theme.command(event.toolName)}${theme.muted(\"]\")} `,\n );\n } else if (event.type === \"tool_result\") {\n const preview = event.toolResult?.content?.slice(0, 200) ?? \"\";\n process.stdout.write(`${theme.muted(\"→\")} ${theme.muted(preview)}\\n`);\n }\n }\n } catch (err) {\n console.error(\n theme.error(\n `\\n✗ ${err instanceof Error ? err.message : String(err)}`,\n ),\n );\n }\n process.stdout.write(\"\\n\\n\");\n rl.prompt();\n });\n\n rl.on(\"close\", () => {\n console.log(theme.muted(\"\\nGoodbye.\"));\n workspaceManager.close();\n process.exit(0);\n });\n });\n\n// ── run ────────────────────────────────────────────────────\n\nprogram\n .command(\"run\")\n .description(\"Run a one-shot prompt\")\n .argument(\"<prompt>\", \"The prompt to execute\")\n .option(\"-w, --workspace <path>\", \"Workspace directory path\", \".\")\n .action(async (prompt, opts) => {\n const dataDir = getDataDir();\n const configPath = path.join(dataDir, \"config.yaml\");\n const config = await loadConfig(configPath);\n const dbPath = path.join(dataDir, \"cortask.db\");\n const workspaceManager = new WorkspaceManager(dbPath);\n const secret = await getOrCreateSecret(dataDir);\n const credentialStore = new EncryptedCredentialStore(\n path.join(dataDir, \"credentials.enc.json\"),\n secret,\n );\n const cronService = new CronService(dbPath);\n const artifactStore = new ArtifactStore();\n\n const workspacePath = path.resolve(opts.workspace);\n const workspaces = await workspaceManager.list();\n let workspace = workspaces.find((w) => w.rootPath === workspacePath);\n if (!workspace) {\n workspace = await workspaceManager.create(\n path.basename(workspacePath),\n workspacePath,\n );\n }\n\n const sessionStore = new SessionStore(\n workspaceManager.getSessionDbPath(workspacePath),\n );\n\n const providerId = (config.providers.default || \"anthropic\") as ProviderId;\n const apiKey = await credentialStore.get(`provider.${providerId}.apiKey`);\n if (!apiKey) {\n console.error(theme.error(`\\n✗ No API key for provider \"${providerId}\".`));\n console.error(theme.muted(\" Set it with:\"));\n console.error(\n theme.command(\n ` cortask credentials set provider.${providerId}.apiKey YOUR_KEY`,\n ),\n );\n process.exit(1);\n }\n const provider = createProvider(providerId, apiKey);\n const providerConfig = config.providers[providerId];\n const model =\n ((providerConfig as Record<string, unknown>)?.model as string) ??\n \"claude-sonnet-4-5-20250929\";\n\n const runner = new AgentRunner({\n config: {\n provider,\n model,\n maxTurns: config.agent.maxTurns,\n temperature: config.agent.temperature,\n maxTokens: config.agent.maxTokens,\n },\n tools: [\n ...builtinTools,\n createCronTool(cronService),\n createArtifactTool(artifactStore),\n ],\n getWorkspacePath: () => workspacePath,\n getDataDir: () => dataDir,\n getMemoryContent: () => workspaceManager.readMemory(workspacePath),\n getGlobalMemoryContent: () => workspaceManager.readGlobalMemory(dataDir),\n getSkillPrompts: () => [],\n getSessionMessages: async (sid) => sessionStore.getMessages(sid),\n saveSessionMessages: async (sid, msgs) =>\n sessionStore.saveMessages(sid, msgs),\n });\n\n const result = await runner.run({ prompt });\n console.log(result.response);\n\n workspaceManager.close();\n });\n\n// ── setup, status, dashboard ──────────────────────────────\n\nprogram.addCommand(setupCommand);\nprogram.addCommand(statusCommand);\nprogram.addCommand(dashboardCommand);\n\n// ── workspaces ─────────────────────────────────────────────\n\nconst ws = program.command(\"workspaces\").description(\"Manage workspaces\");\n\nws.command(\"list\").action(async () => {\n const dataDir = getDataDir();\n const dbPath = path.join(dataDir, \"cortask.db\");\n const wm = new WorkspaceManager(dbPath);\n const list = await wm.list();\n if (list.length === 0) {\n console.log(theme.muted(\"No workspaces registered.\"));\n } else {\n for (const w of list) {\n console.log(\n ` ${theme.success(\"✓\")} ${theme.command(w.name)} ${theme.muted(\"→\")} ${theme.info(w.rootPath)} ${theme.muted(`(${w.id})`)}`,\n );\n }\n }\n wm.close();\n});\n\nws.command(\"add\")\n .argument(\"<name>\", \"Workspace name\")\n .argument(\"<path>\", \"Workspace directory path\")\n .action(async (name, dirPath) => {\n const dataDir = getDataDir();\n const dbPath = path.join(dataDir, \"cortask.db\");\n const wm = new WorkspaceManager(dbPath);\n const workspace = await wm.create(name, dirPath);\n console.log(\n `${theme.success(\"✓\")} Created workspace ${theme.command(workspace.name)} ${theme.muted(`(${workspace.id})`)}`,\n );\n console.log(` ${theme.muted(\"Path:\")} ${theme.info(workspace.rootPath)}`);\n wm.close();\n });\n\nws.command(\"remove\")\n .argument(\"<id>\", \"Workspace ID\")\n .action(async (id) => {\n const dataDir = getDataDir();\n const dbPath = path.join(dataDir, \"cortask.db\");\n const wm = new WorkspaceManager(dbPath);\n await wm.delete(id);\n console.log(`${theme.success(\"✓\")} Removed workspace ${theme.muted(id)}`);\n wm.close();\n });\n\n// ── credentials ────────────────────────────────────────────\n\nconst creds = program\n .command(\"credentials\")\n .description(\"Manage credentials\");\n\ncreds.command(\"list\").action(async () => {\n const dataDir = getDataDir();\n const secret = await getOrCreateSecret(dataDir);\n const store = new EncryptedCredentialStore(\n path.join(dataDir, \"credentials.enc.json\"),\n secret,\n );\n const keys = await store.list();\n if (keys.length === 0) {\n console.log(theme.muted(\"No credentials stored.\"));\n } else {\n for (const key of keys) {\n console.log(` ${theme.muted(\"•\")} ${theme.command(key)}`);\n }\n }\n});\n\ncreds\n .command(\"set\")\n .argument(\"<key>\", \"Credential key (e.g. provider.anthropic.apiKey)\")\n .argument(\"<value>\", \"Credential value\")\n .action(async (key, value) => {\n const dataDir = getDataDir();\n const secret = await getOrCreateSecret(dataDir);\n const store = new EncryptedCredentialStore(\n path.join(dataDir, \"credentials.enc.json\"),\n secret,\n );\n await store.set(key, value);\n console.log(`${theme.success(\"✓\")} Credential ${theme.command(key)} saved.`);\n });\n\ncreds\n .command(\"remove\")\n .argument(\"<key>\", \"Credential key\")\n .action(async (key) => {\n const dataDir = getDataDir();\n const secret = await getOrCreateSecret(dataDir);\n const store = new EncryptedCredentialStore(\n path.join(dataDir, \"credentials.enc.json\"),\n secret,\n );\n await store.delete(key);\n console.log(`${theme.success(\"✓\")} Credential ${theme.command(key)} removed.`);\n });\n\n// ── skills ─────────────────────────────────────────────────\n\nconst sk = program.command(\"skills\").description(\"Manage skills\");\n\nsk.command(\"list\").action(async () => {\n const dataDir = getDataDir();\n const secret = await getOrCreateSecret(dataDir);\n const credentialStore = new EncryptedCredentialStore(\n path.join(dataDir, \"credentials.enc.json\"),\n secret,\n );\n const bundledSkillsDir = path.resolve(\"skills\");\n const userSkillsDir = path.join(dataDir, \"skills\");\n const configPath = path.join(dataDir, \"config.yaml\");\n const config = await loadConfig(configPath);\n const allSkills = await loadSkills(\n bundledSkillsDir,\n userSkillsDir,\n config.skills.dirs,\n credentialStore,\n );\n if (allSkills.length === 0) {\n console.log(theme.muted(\"No skills found.\"));\n } else {\n for (const skill of allSkills) {\n const icon = skill.eligible ? theme.success(\"✓\") : theme.muted(\"○\");\n const name = theme.command(skill.manifest.name);\n const desc = theme.muted(skill.manifest.description ?? \"\");\n console.log(` ${icon} ${name} ${desc}`);\n }\n }\n});\n\nsk.command(\"install\")\n .argument(\"<git-url>\", \"Git URL of the skill repository\")\n .action(async (gitUrl) => {\n const dataDir = getDataDir();\n const userSkillsDir = path.join(dataDir, \"skills\");\n const result = await installSkillFromGit(gitUrl, userSkillsDir);\n console.log(\n `${theme.success(\"✓\")} Installed skill ${theme.command(result.name)}`,\n );\n });\n\nsk.command(\"remove\")\n .argument(\"<name>\", \"Skill name\")\n .action(async (name) => {\n const dataDir = getDataDir();\n const userSkillsDir = path.join(dataDir, \"skills\");\n await removeSkill(name, userSkillsDir);\n console.log(`${theme.success(\"✓\")} Removed skill ${theme.command(name)}`);\n });\n\n// ── cron ───────────────────────────────────────────────────\n\nconst cr = program.command(\"cron\").description(\"Manage cron jobs\");\n\ncr.command(\"list\").action(async () => {\n const dataDir = getDataDir();\n const dbPath = path.join(dataDir, \"cortask.db\");\n const cronService = new CronService(dbPath);\n const jobs = cronService.list();\n if (jobs.length === 0) {\n console.log(theme.muted(\"No cron jobs.\"));\n } else {\n for (const job of jobs) {\n const icon = job.enabled ? theme.success(\"✓\") : theme.muted(\"○\");\n console.log(` ${icon} ${theme.command(job.name)} ${theme.muted(`(${job.id})`)}`);\n console.log(` ${theme.muted(\"Schedule:\")} ${theme.info(JSON.stringify(job.schedule))}`);\n console.log(` ${theme.muted(\"Prompt:\")} ${job.prompt.slice(0, 80)}...`);\n }\n }\n cronService.stop();\n});\n\ncr.command(\"add\")\n .requiredOption(\"-n, --name <name>\", \"Job name\")\n .requiredOption(\"-s, --schedule <cron>\", \"Cron expression\")\n .requiredOption(\"-p, --prompt <prompt>\", \"Prompt to execute\")\n .option(\"-w, --workspace <id>\", \"Workspace ID\")\n .action(async (opts) => {\n const dataDir = getDataDir();\n const dbPath = path.join(dataDir, \"cortask.db\");\n const cronService = new CronService(dbPath);\n const job = cronService.add({\n name: opts.name,\n schedule: { type: \"cron\", expression: opts.schedule },\n prompt: opts.prompt,\n delivery: {},\n workspaceId: opts.workspace,\n });\n console.log(\n `${theme.success(\"✓\")} Created cron job ${theme.command(job.name)} ${theme.muted(`(${job.id})`)}`,\n );\n cronService.stop();\n });\n\ncr.command(\"remove\")\n .argument(\"<id>\", \"Job ID\")\n .action(async (id) => {\n const dataDir = getDataDir();\n const dbPath = path.join(dataDir, \"cortask.db\");\n const cronService = new CronService(dbPath);\n cronService.remove(id);\n console.log(`${theme.success(\"✓\")} Deleted cron job ${theme.muted(id)}`);\n cronService.stop();\n });\n\nprogram.parse();\n","import chalk, { Chalk } from \"chalk\";\n\nconst PALETTE = {\n accent: \"#6366f1\",\n accentBright: \"#818cf8\",\n accentDim: \"#a5b4fc\",\n info: \"#38bdf8\",\n success: \"#22c55e\",\n warn: \"#f59e0b\",\n error: \"#ef4444\",\n muted: \"#9ca3af\",\n};\n\nconst hasForceColor =\n typeof process.env.FORCE_COLOR === \"string\" &&\n process.env.FORCE_COLOR.trim().length > 0 &&\n process.env.FORCE_COLOR.trim() !== \"0\";\n\nconst baseChalk =\n process.env.NO_COLOR && !hasForceColor\n ? new Chalk({ level: 0 })\n : chalk;\n\nconst hex = (value: string) => baseChalk.hex(value);\n\nexport const theme = {\n accent: hex(PALETTE.accent),\n accentBright: hex(PALETTE.accentBright),\n accentDim: hex(PALETTE.accentDim),\n info: hex(PALETTE.info),\n success: hex(PALETTE.success),\n warn: hex(PALETTE.warn),\n error: hex(PALETTE.error),\n muted: hex(PALETTE.muted),\n heading: baseChalk.bold.hex(PALETTE.accent),\n command: hex(PALETTE.accentBright),\n option: hex(PALETTE.warn),\n} as const;\n\nexport const isRich = () => Boolean(baseChalk.level > 0);\n","import { isRich, theme } from \"./theme.js\";\n\nlet bannerEmitted = false;\n\nconst hasFlag = (argv: string[], ...flags: string[]) =>\n argv.some((arg) => flags.includes(arg));\n\nexport function emitBanner(version: string, argv?: string[]) {\n if (bannerEmitted) return;\n const args = argv ?? process.argv;\n if (!process.stdout.isTTY) return;\n if (hasFlag(args, \"--json\", \"--version\", \"-V\")) return;\n\n const title = \"⚡ Cortask\";\n const tagline = \"Local AI agent platform\";\n\n if (isRich()) {\n process.stdout.write(\n `\\n${theme.heading(title)} ${theme.info(version)} ${theme.muted(\"—\")} ${theme.accentDim(tagline)}\\n\\n`,\n );\n } else {\n process.stdout.write(`\\n${title} ${version} — ${tagline}\\n\\n`);\n }\n\n bannerEmitted = true;\n}\n\nexport function hasBannerEmitted(): boolean {\n return bannerEmitted;\n}\n","import type { Command } from \"commander\";\nimport { emitBanner, hasBannerEmitted } from \"./banner.js\";\nimport { theme } from \"./theme.js\";\n\nconst EXAMPLES = [\n [\"cortask serve\", \"Start the gateway server\"],\n [\"cortask chat\", \"Start interactive chat session\"],\n [\"cortask run \\\"hello\\\"\", \"Run a one-shot prompt\"],\n [\"cortask status\", \"Show system status\"],\n [\"cortask dashboard\", \"Open the web UI\"],\n [\"cortask setup\", \"Initialize configuration\"],\n [\"cortask workspaces list\", \"List registered workspaces\"],\n [\"cortask credentials set provider.anthropic.apiKey KEY\", \"Set API key\"],\n] as const;\n\nexport function configureHelp(program: Command, version: string) {\n program.helpOption(\"-h, --help\", \"Display help for command\");\n program.helpCommand(\"help [command]\", \"Display help for command\");\n\n program.configureHelp({\n sortSubcommands: true,\n sortOptions: true,\n optionTerm: (option) => theme.option(option.flags),\n subcommandTerm: (cmd) => theme.command(cmd.name()),\n });\n\n const formatHelp = (str: string) =>\n str\n .replace(/^Usage:/gm, theme.heading(\"Usage:\"))\n .replace(/^Options:/gm, theme.heading(\"Options:\"))\n .replace(/^Commands:/gm, theme.heading(\"Commands:\"))\n .replace(/^Arguments:/gm, theme.heading(\"Arguments:\"));\n\n program.configureOutput({\n writeOut: (str) => process.stdout.write(formatHelp(str)),\n writeErr: (str) => process.stderr.write(formatHelp(str)),\n outputError: (str, write) => write(theme.error(str)),\n });\n\n program.addHelpText(\"beforeAll\", () => {\n if (hasBannerEmitted()) return \"\";\n emitBanner(version);\n return \"\";\n });\n\n const fmtExamples = EXAMPLES.map(\n ([cmd, desc]) => ` ${theme.command(cmd)}\\n ${theme.muted(desc)}`,\n ).join(\"\\n\");\n\n program.addHelpText(\"afterAll\", ({ command }) => {\n if (command !== program) return \"\";\n return `\\n${theme.heading(\"Examples:\")}\\n${fmtExamples}\\n`;\n });\n}\n","import { Command } from \"commander\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { getDataDir } from \"@cortask/core\";\nimport { theme } from \"../terminal/theme.js\";\n\nconst DEFAULT_CONFIG = `# Cortask Configuration\nonboarded: true\n\nproviders:\n default: anthropic\n\nagent:\n maxTurns: 25\n temperature: 0.7\n\nserver:\n port: 3777\n host: 127.0.0.1\n\nskills:\n dirs: []\n`;\n\nfunction ensureDir(dir: string) {\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n}\n\nexport const setupCommand = new Command(\"setup\")\n .description(\"Initialize configuration and data directory\")\n .option(\"--force\", \"Overwrite existing configuration\")\n .action(async (opts: { force?: boolean }) => {\n const dataDir = getDataDir();\n const configPath = path.join(dataDir, \"config.yaml\");\n\n console.log(theme.heading(\"\\n⚡ Cortask Setup\\n\"));\n\n if (fs.existsSync(configPath) && !opts.force) {\n console.log(theme.warn(\"⚠ Configuration already exists:\"));\n console.log(theme.info(` ${configPath}`));\n console.log(theme.muted(\"\\n Use --force to overwrite\"));\n console.log();\n process.exit(1);\n }\n\n try {\n ensureDir(dataDir);\n console.log(`${theme.success(\"✓\")} Data directory: ${theme.info(dataDir)}`);\n\n fs.writeFileSync(configPath, DEFAULT_CONFIG, \"utf-8\");\n console.log(`${theme.success(\"✓\")} Config: ${theme.info(configPath)}`);\n\n const skillsDir = path.join(dataDir, \"skills\");\n ensureDir(skillsDir);\n console.log(`${theme.success(\"✓\")} Skills: ${theme.info(skillsDir)}`);\n\n console.log(theme.heading(\"\\n✓ Setup complete!\\n\"));\n\n console.log(theme.muted(\"Next steps:\"));\n console.log(theme.command(\" 1. Set your API key:\"));\n console.log(theme.info(` cortask credentials set provider.anthropic.apiKey YOUR_KEY`));\n console.log(theme.command(\"\\n 2. Add a workspace:\"));\n console.log(theme.info(\" cortask workspaces add my-project /path/to/project\"));\n console.log(theme.command(\"\\n 3. Start chatting:\"));\n console.log(theme.info(\" cortask chat -w /path/to/project\"));\n console.log();\n } catch (err) {\n console.error(theme.error(\"\\n✗ Setup failed\"));\n console.error(theme.muted(` ${(err as Error).message}`));\n process.exit(1);\n }\n });\n","import { Command } from \"commander\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { getDataDir, loadConfig, WorkspaceManager } from \"@cortask/core\";\nimport { theme } from \"../terminal/theme.js\";\n\nasync function fetchHealth(host: string, port: number) {\n try {\n const res = await fetch(`http://${host}:${port}/api/health`);\n if (!res.ok) return null;\n return res.json();\n } catch {\n return null;\n }\n}\n\nexport const statusCommand = new Command(\"status\")\n .description(\"Show system status and configuration\")\n .action(async () => {\n const dataDir = getDataDir();\n const configPath = path.join(dataDir, \"config.yaml\");\n\n if (!fs.existsSync(configPath)) {\n console.error(theme.error(\"\\n✗ No configuration found\"));\n console.error(theme.muted(\" Run this command to set up:\"));\n console.error(theme.command(\" cortask setup\"));\n console.log();\n process.exit(1);\n }\n\n try {\n const config = await loadConfig(configPath);\n const host = config.server.host;\n const port = config.server.port;\n\n console.log(theme.heading(\"\\n Configuration\"));\n console.log(` File: ${theme.info(configPath)}`);\n console.log(` Data: ${theme.info(dataDir)}`);\n\n // Gateway status\n console.log(theme.heading(\"\\n Gateway\"));\n const health = await fetchHealth(host, port);\n if (health) {\n console.log(` Status: ${theme.success(\"online\")}`);\n console.log(` URL: ${theme.info(`http://${host}:${port}`)}`);\n } else {\n console.log(` Status: ${theme.error(\"offline\")}`);\n console.log(` Expected: ${theme.muted(`http://${host}:${port}`)}`);\n }\n\n // Provider\n console.log(theme.heading(\"\\n Provider\"));\n console.log(` Default: ${theme.command(config.providers.default)}`);\n\n // Workspaces\n console.log(theme.heading(\"\\n Workspaces\"));\n const dbPath = path.join(dataDir, \"cortask.db\");\n if (fs.existsSync(dbPath)) {\n const wm = new WorkspaceManager(dbPath);\n const workspaces = await wm.list();\n if (workspaces.length === 0) {\n console.log(` ${theme.muted(\"No workspaces registered\")}`);\n } else {\n for (const w of workspaces) {\n console.log(` ${theme.success(\"✓\")} ${theme.command(w.name)} ${theme.muted(`→ ${w.rootPath}`)}`);\n }\n }\n wm.close();\n } else {\n console.log(` ${theme.muted(\"Database not initialized\")}`);\n }\n\n // Skills\n console.log(theme.heading(\"\\n Skills\"));\n const skillsDir = path.join(dataDir, \"skills\");\n if (fs.existsSync(skillsDir)) {\n const entries = fs.readdirSync(skillsDir).filter((e) =>\n fs.statSync(path.join(skillsDir, e)).isDirectory(),\n );\n console.log(` Installed: ${theme.info(entries.length.toString())} skill(s)`);\n } else {\n console.log(` ${theme.muted(\"No skills directory\")}`);\n }\n\n console.log();\n } catch (err) {\n console.error(theme.error(\"\\n✗ Failed to load status\"));\n console.error(theme.muted(` ${(err as Error).message}`));\n process.exit(1);\n }\n });\n","import { Command } from \"commander\";\nimport { exec } from \"node:child_process\";\nimport path from \"node:path\";\nimport { getDataDir, loadConfig } from \"@cortask/core\";\nimport { theme } from \"../terminal/theme.js\";\n\nfunction openBrowser(url: string): Promise<void> {\n const cmd =\n process.platform === \"win32\"\n ? `start ${url}`\n : process.platform === \"darwin\"\n ? `open ${url}`\n : `xdg-open ${url}`;\n\n return new Promise((resolve, reject) => {\n exec(cmd, (err) => (err ? reject(err) : resolve()));\n });\n}\n\nasync function isGatewayOnline(host: string, port: number): Promise<boolean> {\n try {\n const res = await fetch(`http://${host}:${port}/api/health`);\n return res.ok;\n } catch {\n return false;\n }\n}\n\nexport const dashboardCommand = new Command(\"dashboard\")\n .description(\"Open the web UI in your browser\")\n .option(\"--no-open\", \"Print URL without opening browser\")\n .action(async (opts: { open: boolean }) => {\n const dataDir = getDataDir();\n const configPath = path.join(dataDir, \"config.yaml\");\n const config = await loadConfig(configPath);\n const url = `http://${config.server.host}:${config.server.port}`;\n\n const online = await isGatewayOnline(config.server.host, config.server.port);\n if (!online) {\n console.log(theme.warn(\"\\n⚠ Gateway appears to be offline\"));\n console.log(theme.muted(\" Start it with:\"));\n console.log(theme.command(\" cortask serve\"));\n console.log();\n }\n\n if (opts.open) {\n console.log(theme.info(`\\nOpening dashboard: ${url}`));\n try {\n await openBrowser(url);\n console.log(theme.success(\"✓ Browser opened\"));\n } catch {\n console.log(theme.warn(\"\\n⚠ Could not open browser automatically\"));\n console.log(theme.info(` Open this URL manually: ${url}`));\n }\n } else {\n console.log(theme.info(`\\nDashboard URL: ${url}`));\n }\n console.log();\n });\n"],"mappings":"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","names":["Command","loadConfig","getDataDir","WorkspaceManager","path","program","Command","fs","path","getDataDir","Command","getDataDir","path","fs","Command","path","getDataDir","loadConfig","Command","getDataDir","path","loadConfig","require","Command","getDataDir","path","loadConfig","WorkspaceManager"]}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "cortask",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "license": "MIT",
6
+ "description": "Local AI agent with skills, workspaces, and cron",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/cortask/cortask.git",
10
+ "directory": "packages/cli"
11
+ },
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "bin": {
16
+ "cortask": "dist/index.js"
17
+ },
18
+ "dependencies": {
19
+ "chalk": "^5.6.2",
20
+ "commander": "^12.1.0",
21
+ "@cortask/gateway": "0.1.0",
22
+ "@cortask/core": "0.1.0"
23
+ },
24
+ "devDependencies": {
25
+ "@types/node": "^22.0.0",
26
+ "tsup": "^8.3.0",
27
+ "typescript": "^5.7.0"
28
+ },
29
+ "scripts": {
30
+ "build": "tsup",
31
+ "dev": "tsup --watch",
32
+ "typecheck": "tsc --noEmit",
33
+ "clean": "rm -rf dist"
34
+ }
35
+ }