@taskcast/cli 1.2.0 → 1.3.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/client.d.ts +15 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +47 -0
- package/dist/client.js.map +1 -0
- package/dist/commands/doctor.d.ts +23 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +95 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/logs.d.ts +11 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +171 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/migrate.d.ts +3 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +84 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/node.d.ts +5 -0
- package/dist/commands/node.d.ts.map +1 -0
- package/dist/commands/node.js +57 -0
- package/dist/commands/node.js.map +1 -0
- package/dist/commands/ping.d.ts +9 -0
- package/dist/commands/ping.d.ts.map +1 -0
- package/dist/commands/ping.js +43 -0
- package/dist/commands/ping.js.map +1 -0
- package/dist/commands/playground.d.ts +3 -0
- package/dist/commands/playground.d.ts.map +1 -0
- package/dist/commands/playground.js +37 -0
- package/dist/commands/playground.js.map +1 -0
- package/dist/commands/service.d.ts +8 -0
- package/dist/commands/service.d.ts.map +1 -0
- package/dist/commands/service.js +237 -0
- package/dist/commands/service.js.map +1 -0
- package/dist/commands/start.d.ts +3 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +145 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/tasks.d.ts +11 -0
- package/dist/commands/tasks.d.ts.map +1 -0
- package/dist/commands/tasks.js +129 -0
- package/dist/commands/tasks.js.map +1 -0
- package/dist/commands/ui.d.ts +3 -0
- package/dist/commands/ui.d.ts.map +1 -0
- package/dist/commands/ui.js +103 -0
- package/dist/commands/ui.js.map +1 -0
- package/dist/index.js +41 -413
- package/dist/index.js.map +1 -1
- package/dist/node-config.d.ts +22 -0
- package/dist/node-config.d.ts.map +1 -0
- package/dist/node-config.js +71 -0
- package/dist/node-config.js.map +1 -0
- package/dist/service/interface.d.ts +26 -0
- package/dist/service/interface.d.ts.map +1 -0
- package/dist/service/interface.js +3 -0
- package/dist/service/interface.js.map +1 -0
- package/dist/service/launchd.d.ts +11 -0
- package/dist/service/launchd.d.ts.map +1 -0
- package/dist/service/launchd.js +97 -0
- package/dist/service/launchd.js.map +1 -0
- package/dist/service/paths.d.ts +12 -0
- package/dist/service/paths.d.ts.map +1 -0
- package/dist/service/paths.js +35 -0
- package/dist/service/paths.js.map +1 -0
- package/dist/service/resolve.d.ts +3 -0
- package/dist/service/resolve.d.ts.map +1 -0
- package/dist/service/resolve.js +10 -0
- package/dist/service/resolve.js.map +1 -0
- package/dist/service/systemd.d.ts +11 -0
- package/dist/service/systemd.d.ts.map +1 -0
- package/dist/service/systemd.js +86 -0
- package/dist/service/systemd.js.map +1 -0
- package/dist/utils.d.ts +5 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +65 -0
- package/dist/utils.js.map +1 -0
- package/package.json +9 -8
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ping.js","sourceRoot":"","sources":["../../src/commands/ping.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAQrD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW,EAAE,UAAwB,KAAK;IACzE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IACxB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,GAAG,SAAS,CAAC,CAAA;QAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAA;QACpC,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,GAAG,CAAC,MAAM,EAAE,EAAE,CAAA;QAC9D,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAA;IAChC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAG,GAAa,CAAC,OAAO,EAAE,CAAA;IACrD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,yCAAyC,CAAC;SACtD,MAAM,CAAC,eAAe,EAAE,oBAAoB,CAAC;SAC7C,MAAM,CAAC,KAAK,EAAE,IAAuB,EAAE,EAAE;QACxC,MAAM,GAAG,GAAG,IAAI,iBAAiB,EAAE,CAAA;QACnC,IAAI,IAAI,CAAA;QACR,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACzB,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,IAAI,aAAa,CAAC,CAAA;gBAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,GAAG,GAAG,CAAC,UAAU,EAAE,CAAA;QACzB,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACzC,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,CAAC,GAAG,KAAK,MAAM,CAAC,SAAS,KAAK,CAAC,CAAA;QACrE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,uBAAuB,IAAI,CAAC,GAAG,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC,CAAA;YACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;IACH,CAAC,CAAC,CAAA;AACN,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playground.d.ts","sourceRoot":"","sources":["../../src/commands/playground.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAKnC,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+BhE"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { existsSync } from 'fs';
|
|
2
|
+
import { join, dirname } from 'path';
|
|
3
|
+
import { createRequire } from 'module';
|
|
4
|
+
export function registerPlaygroundCommand(program) {
|
|
5
|
+
program
|
|
6
|
+
.command('playground')
|
|
7
|
+
.description('Serve only the playground UI (no engine)')
|
|
8
|
+
.option('-p, --port <port>', 'port to listen on', '5173')
|
|
9
|
+
.action(async (options) => {
|
|
10
|
+
const port = Number(options.port);
|
|
11
|
+
try {
|
|
12
|
+
const require = createRequire(import.meta.url);
|
|
13
|
+
const pkgPath = require.resolve('@taskcast/playground/package.json');
|
|
14
|
+
const distDir = join(dirname(pkgPath), 'dist');
|
|
15
|
+
if (!existsSync(distDir)) {
|
|
16
|
+
console.error('[taskcast] Playground dist not found. Run `pnpm --filter @taskcast/playground build` first.');
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
const { OpenAPIHono } = await import('@hono/zod-openapi');
|
|
20
|
+
const app = new OpenAPIHono();
|
|
21
|
+
const { serveStatic } = await import('@hono/node-server/serve-static');
|
|
22
|
+
app.use('/_playground/*', serveStatic({ root: distDir, rewriteRequestPath: (p) => p.replace(/^\/_playground/, '') }));
|
|
23
|
+
app.get('/_playground/*', serveStatic({ root: distDir, rewriteRequestPath: () => '/index.html' }));
|
|
24
|
+
app.get('/', (c) => c.redirect('/_playground/'));
|
|
25
|
+
const { serve } = await import('@hono/node-server');
|
|
26
|
+
serve({ fetch: app.fetch, port }, () => {
|
|
27
|
+
console.log(`[taskcast] Playground UI at http://localhost:${port}/_playground/`);
|
|
28
|
+
console.log('[taskcast] Use "External" mode in the UI to connect to a remote server.');
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
console.error('[taskcast] @taskcast/playground not available.');
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=playground.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playground.js","sourceRoot":"","sources":["../../src/commands/playground.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAA;AAC/B,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAA;AAEtC,MAAM,UAAU,yBAAyB,CAAC,OAAgB;IACxD,OAAO;SACJ,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,CAAC,0CAA0C,CAAC;SACvD,MAAM,CAAC,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,CAAC;SACxD,MAAM,CAAC,KAAK,EAAE,OAAyB,EAAE,EAAE;QAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QACjC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YAC9C,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,mCAAmC,CAAC,CAAA;YACpE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAA;YAC9C,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBACzB,OAAO,CAAC,KAAK,CAAC,6FAA6F,CAAC,CAAA;gBAC5G,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC;YACD,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAA;YACzD,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAA;YAC7B,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,gCAAgC,CAAC,CAAA;YACtE,GAAG,CAAC,GAAG,CAAC,gBAAgB,EAAE,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;YAC7H,GAAG,CAAC,GAAG,CAAC,gBAAgB,EAAE,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC,CAAC,CAAA;YAClG,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAA0C,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAA;YACzF,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAA;YACnD,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE;gBACrC,OAAO,CAAC,GAAG,CAAC,gDAAgD,IAAI,eAAe,CAAC,CAAA;gBAChF,OAAO,CAAC,GAAG,CAAC,yEAAyE,CAAC,CAAA;YACxF,CAAC,CAAC,CAAA;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAA;YAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;IACH,CAAC,CAAC,CAAA;AACN,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
export declare function runServiceStart(_healthTimeoutMs?: number): Promise<void>;
|
|
3
|
+
export declare function runServiceStop(): Promise<void>;
|
|
4
|
+
export declare function runServiceStatus(): Promise<void>;
|
|
5
|
+
export declare function runServiceRestart(_healthTimeoutMs?: number): Promise<void>;
|
|
6
|
+
export declare function registerServiceCommand(program: Command): void;
|
|
7
|
+
export declare function pollHealth(port: number, timeoutMs?: number): Promise<boolean>;
|
|
8
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/commands/service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAkDnC,wBAAsB,eAAe,CAAC,gBAAgB,SAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB5E;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CASpD;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CA6BtD;AAGD,wBAAsB,iBAAiB,CAAC,gBAAgB,SAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB9E;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAmF7D;AAqBD,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,SAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAcjF"}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import { dirname } from 'path';
|
|
3
|
+
import { createServiceManager } from '../service/resolve.js';
|
|
4
|
+
import { getServicePaths } from '../service/paths.js';
|
|
5
|
+
function resolveNodePath() {
|
|
6
|
+
return process.execPath;
|
|
7
|
+
}
|
|
8
|
+
// Note: resolveEntryPoint uses import.meta.url which cannot be mocked in Vitest ESM tests.
|
|
9
|
+
// The entryPoint value is verified structurally (mockInstall called) but not by exact path.
|
|
10
|
+
/* v8 ignore next 3 */
|
|
11
|
+
function resolveEntryPoint() {
|
|
12
|
+
return new URL('../index.js', import.meta.url).pathname;
|
|
13
|
+
}
|
|
14
|
+
function ensureConfigFile(paths, configOpt) {
|
|
15
|
+
if (configOpt)
|
|
16
|
+
return configOpt;
|
|
17
|
+
// Check if any config already exists
|
|
18
|
+
if (existsSync(paths.defaultConfigPath)) {
|
|
19
|
+
return paths.defaultConfigPath;
|
|
20
|
+
}
|
|
21
|
+
// Create default config with SQLite
|
|
22
|
+
const dir = dirname(paths.defaultConfigPath);
|
|
23
|
+
mkdirSync(dir, { recursive: true });
|
|
24
|
+
const dbPath = paths.defaultDbPath;
|
|
25
|
+
const content = `# Taskcast service configuration
|
|
26
|
+
port: 3721
|
|
27
|
+
|
|
28
|
+
adapters:
|
|
29
|
+
shortTermStore:
|
|
30
|
+
provider: sqlite
|
|
31
|
+
path: ${dbPath}
|
|
32
|
+
longTermStore:
|
|
33
|
+
provider: sqlite
|
|
34
|
+
path: ${dbPath}
|
|
35
|
+
`;
|
|
36
|
+
writeFileSync(paths.defaultConfigPath, content);
|
|
37
|
+
console.log(`[taskcast] Created default config at ${paths.defaultConfigPath}`);
|
|
38
|
+
return paths.defaultConfigPath;
|
|
39
|
+
}
|
|
40
|
+
// Exported action functions — used directly by alias commands in index.ts
|
|
41
|
+
// _healthTimeoutMs is injectable for testing (default 5000ms)
|
|
42
|
+
export async function runServiceStart(_healthTimeoutMs = 5000) {
|
|
43
|
+
const mgr = createServiceManager();
|
|
44
|
+
const st = await mgr.status();
|
|
45
|
+
if (st.state === 'running') {
|
|
46
|
+
console.log('[taskcast] Service is already running.');
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
await mgr.start();
|
|
50
|
+
const paths = getServicePaths();
|
|
51
|
+
const port = await getPortFromConfig();
|
|
52
|
+
const started = await pollHealth(port, _healthTimeoutMs);
|
|
53
|
+
if (started) {
|
|
54
|
+
console.log(`[taskcast] Service started on http://localhost:${port}`);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
console.error('[taskcast] Service may have failed to start. Check logs:');
|
|
58
|
+
if (paths.stdoutLog) {
|
|
59
|
+
console.error(` ${paths.stdoutLog}`);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
console.error(' journalctl --user -u taskcast');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export async function runServiceStop() {
|
|
67
|
+
const mgr = createServiceManager();
|
|
68
|
+
const st = await mgr.status();
|
|
69
|
+
if (st.state !== 'running') {
|
|
70
|
+
console.log('[taskcast] Service is not running.');
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
await mgr.stop();
|
|
74
|
+
console.log('[taskcast] Service stopped.');
|
|
75
|
+
}
|
|
76
|
+
export async function runServiceStatus() {
|
|
77
|
+
const mgr = createServiceManager();
|
|
78
|
+
const st = await mgr.status();
|
|
79
|
+
if (st.state === 'not-installed') {
|
|
80
|
+
console.log('Service: not installed');
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (st.state === 'stopped') {
|
|
84
|
+
console.log('Service: stopped');
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
console.log(`Service: running (pid ${st.pid})`);
|
|
88
|
+
try {
|
|
89
|
+
const port = await getPortFromConfig();
|
|
90
|
+
const res = await fetch(`http://localhost:${port}/health/detail`);
|
|
91
|
+
if (res.ok) {
|
|
92
|
+
const body = await res.json();
|
|
93
|
+
if (body.uptime != null) {
|
|
94
|
+
const h = Math.floor(body.uptime / 3600);
|
|
95
|
+
const m = Math.floor((body.uptime % 3600) / 60);
|
|
96
|
+
console.log(`Uptime: ${h}h ${m}m`);
|
|
97
|
+
}
|
|
98
|
+
if (body.adapters?.shortTermStore) {
|
|
99
|
+
console.log(`Storage: ${body.adapters.shortTermStore.provider}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// Health endpoint not reachable — just show basic status
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// _healthTimeoutMs is injectable for testing (default 5000ms)
|
|
108
|
+
export async function runServiceRestart(_healthTimeoutMs = 5000) {
|
|
109
|
+
const mgr = createServiceManager();
|
|
110
|
+
await mgr.restart();
|
|
111
|
+
const paths = getServicePaths();
|
|
112
|
+
const port = await getPortFromConfig();
|
|
113
|
+
const started = await pollHealth(port, _healthTimeoutMs);
|
|
114
|
+
if (started) {
|
|
115
|
+
console.log(`[taskcast] Service restarted on http://localhost:${port}`);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
console.error('[taskcast] Service may have failed to restart. Check logs:');
|
|
119
|
+
if (paths.stdoutLog) {
|
|
120
|
+
console.error(` ${paths.stdoutLog}`);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
console.error(' journalctl --user -u taskcast');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
export function registerServiceCommand(program) {
|
|
128
|
+
const service = program
|
|
129
|
+
.command('service')
|
|
130
|
+
.description('Manage Taskcast as a system service');
|
|
131
|
+
service
|
|
132
|
+
.command('install')
|
|
133
|
+
.description('Register Taskcast as a system service with auto-start on boot')
|
|
134
|
+
.option('-c, --config <path>', 'config file path')
|
|
135
|
+
.option('-p, --port <port>', 'port to listen on', '3721')
|
|
136
|
+
.option('-s, --storage <type>', 'storage backend: memory | redis | sqlite')
|
|
137
|
+
.option('--db-path <path>', 'SQLite database file path')
|
|
138
|
+
.action(async (opts) => {
|
|
139
|
+
const port = Number(opts.port);
|
|
140
|
+
if (!Number.isFinite(port) || port < 1 || port > 65535 || port !== Math.floor(port)) {
|
|
141
|
+
console.error(`[taskcast] Invalid port: ${opts.port}`);
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
144
|
+
const mgr = createServiceManager();
|
|
145
|
+
const paths = getServicePaths();
|
|
146
|
+
const configPath = ensureConfigFile(paths, opts.config);
|
|
147
|
+
// When using auto-generated config (SQLite default) and user didn't
|
|
148
|
+
// explicitly set --storage, ensure the service starts with sqlite.
|
|
149
|
+
const autoSqlite = !opts.config && !opts.storage;
|
|
150
|
+
const storage = opts.storage ?? (autoSqlite ? 'sqlite' : undefined);
|
|
151
|
+
const dbPath = opts.dbPath ?? (autoSqlite ? paths.defaultDbPath : undefined);
|
|
152
|
+
const installOpts = {
|
|
153
|
+
port,
|
|
154
|
+
config: configPath,
|
|
155
|
+
nodePath: resolveNodePath(),
|
|
156
|
+
entryPoint: resolveEntryPoint(),
|
|
157
|
+
...(storage !== undefined ? { storage } : {}),
|
|
158
|
+
...(dbPath !== undefined ? { dbPath } : {}),
|
|
159
|
+
};
|
|
160
|
+
await mgr.install(installOpts);
|
|
161
|
+
// Write state file with the installed port so start/restart poll the right port
|
|
162
|
+
const statePath = paths.serviceStatePath;
|
|
163
|
+
mkdirSync(dirname(statePath), { recursive: true });
|
|
164
|
+
writeFileSync(statePath, JSON.stringify({ port }));
|
|
165
|
+
console.log('[taskcast] Service installed successfully.');
|
|
166
|
+
console.log('[taskcast] Run `taskcast service start` to start the service.');
|
|
167
|
+
});
|
|
168
|
+
service
|
|
169
|
+
.command('uninstall')
|
|
170
|
+
.description('Remove Taskcast system service registration')
|
|
171
|
+
.action(async () => {
|
|
172
|
+
const mgr = createServiceManager();
|
|
173
|
+
await mgr.uninstall();
|
|
174
|
+
console.log('[taskcast] Service uninstalled successfully.');
|
|
175
|
+
});
|
|
176
|
+
service
|
|
177
|
+
.command('start')
|
|
178
|
+
.description('Start Taskcast via system service manager')
|
|
179
|
+
.action(() => runServiceStart());
|
|
180
|
+
service
|
|
181
|
+
.command('stop')
|
|
182
|
+
.description('Stop Taskcast system service')
|
|
183
|
+
.action(() => runServiceStop());
|
|
184
|
+
service
|
|
185
|
+
.command('restart')
|
|
186
|
+
.description('Restart Taskcast system service')
|
|
187
|
+
.action(() => runServiceRestart());
|
|
188
|
+
service
|
|
189
|
+
.command('reload')
|
|
190
|
+
.description('Restart Taskcast system service (alias for restart)')
|
|
191
|
+
.action(() => runServiceRestart());
|
|
192
|
+
service
|
|
193
|
+
.command('status')
|
|
194
|
+
.description('Show Taskcast service status')
|
|
195
|
+
.action(runServiceStatus);
|
|
196
|
+
}
|
|
197
|
+
async function getPortFromConfig() {
|
|
198
|
+
try {
|
|
199
|
+
const paths = getServicePaths();
|
|
200
|
+
// Try state file first (written by install, has the exact installed port)
|
|
201
|
+
try {
|
|
202
|
+
const state = JSON.parse(readFileSync(paths.serviceStatePath, 'utf8'));
|
|
203
|
+
if (typeof state.port === 'number')
|
|
204
|
+
return state.port;
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
// State file not present — fall through to config file
|
|
208
|
+
}
|
|
209
|
+
const text = readFileSync(paths.defaultConfigPath, 'utf8');
|
|
210
|
+
const match = text.match(/^port:\s*(\d+)/m);
|
|
211
|
+
if (match)
|
|
212
|
+
return Number(match[1]);
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
// Config not readable — use default
|
|
216
|
+
}
|
|
217
|
+
return 3721;
|
|
218
|
+
}
|
|
219
|
+
export async function pollHealth(port, timeoutMs = 5000) {
|
|
220
|
+
const start = Date.now();
|
|
221
|
+
while (Date.now() - start < timeoutMs) {
|
|
222
|
+
try {
|
|
223
|
+
const res = await fetch(`http://localhost:${port}/health`);
|
|
224
|
+
if (res.ok)
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
// Not ready yet
|
|
229
|
+
}
|
|
230
|
+
const remaining = timeoutMs - (Date.now() - start);
|
|
231
|
+
if (remaining <= 0)
|
|
232
|
+
break;
|
|
233
|
+
await new Promise(r => setTimeout(r, Math.min(500, remaining)));
|
|
234
|
+
}
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/commands/service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAqBnC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA4I3D"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { Redis } from 'ioredis';
|
|
2
|
+
import postgres from 'postgres';
|
|
3
|
+
import { existsSync } from 'fs';
|
|
4
|
+
import { join, dirname } from 'path';
|
|
5
|
+
import { createRequire } from 'module';
|
|
6
|
+
import { TaskEngine, WorkerManager, loadConfigFile, resolveAdminToken, MemoryBroadcastProvider, MemoryShortTermStore, } from '@taskcast/core';
|
|
7
|
+
import { createTaskcastApp } from '@taskcast/server';
|
|
8
|
+
import { createRedisAdapters } from '@taskcast/redis';
|
|
9
|
+
import { PostgresLongTermStore } from '@taskcast/postgres';
|
|
10
|
+
import { createSqliteAdapters } from '@taskcast/sqlite';
|
|
11
|
+
import { promptCreateGlobalConfig, createDefaultGlobalConfig } from '../utils.js';
|
|
12
|
+
export function registerStartCommand(program) {
|
|
13
|
+
program
|
|
14
|
+
.command('start', { isDefault: true })
|
|
15
|
+
.description('Start the taskcast server in foreground (default)')
|
|
16
|
+
.option('-c, --config <path>', 'config file path')
|
|
17
|
+
.option('-p, --port <port>', 'port to listen on', '3721')
|
|
18
|
+
.option('-s, --storage <type>', 'storage backend: memory | redis | sqlite', 'memory')
|
|
19
|
+
.option('--db-path <path>', 'SQLite database file path (default: ./taskcast.db)')
|
|
20
|
+
.option('--playground', 'serve the interactive playground UI at /_playground/')
|
|
21
|
+
.option('-v, --verbose', 'enable verbose logging')
|
|
22
|
+
.action(async (options) => {
|
|
23
|
+
let { config: fileConfig, source, path: configPath } = await loadConfigFile(options.config);
|
|
24
|
+
if (source === 'none') {
|
|
25
|
+
const shouldCreate = await promptCreateGlobalConfig();
|
|
26
|
+
if (shouldCreate) {
|
|
27
|
+
const createdPath = createDefaultGlobalConfig();
|
|
28
|
+
if (createdPath) {
|
|
29
|
+
const created = await loadConfigFile(createdPath);
|
|
30
|
+
fileConfig = created.config;
|
|
31
|
+
source = created.source;
|
|
32
|
+
configPath = created.path;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const port = Number(options.port ?? fileConfig.port ?? 3721);
|
|
37
|
+
const redisUrl = process.env['TASKCAST_REDIS_URL'] ?? fileConfig.adapters?.broadcast?.url;
|
|
38
|
+
const postgresUrl = process.env['TASKCAST_POSTGRES_URL'] ?? fileConfig.adapters?.longTermStore?.url;
|
|
39
|
+
let shortTermStore;
|
|
40
|
+
let broadcast;
|
|
41
|
+
let longTermStore;
|
|
42
|
+
const storage = options.storage ?? process.env['TASKCAST_STORAGE'] ?? (redisUrl ? 'redis' : 'memory');
|
|
43
|
+
let shortTermLabel;
|
|
44
|
+
let longTermLabel;
|
|
45
|
+
if (storage === 'sqlite') {
|
|
46
|
+
const dbPath = options.dbPath ?? './taskcast.db';
|
|
47
|
+
const sqliteOpts = options.dbPath ? { path: options.dbPath } : {};
|
|
48
|
+
const adapters = createSqliteAdapters(sqliteOpts);
|
|
49
|
+
broadcast = new MemoryBroadcastProvider();
|
|
50
|
+
shortTermStore = adapters.shortTermStore;
|
|
51
|
+
longTermStore = adapters.longTermStore;
|
|
52
|
+
shortTermLabel = `sqlite @ ${dbPath}`;
|
|
53
|
+
longTermLabel = `sqlite @ ${dbPath}`;
|
|
54
|
+
}
|
|
55
|
+
else if (storage === 'redis' || redisUrl) {
|
|
56
|
+
const pubClient = new Redis(redisUrl);
|
|
57
|
+
const subClient = new Redis(redisUrl);
|
|
58
|
+
const storeClient = new Redis(redisUrl);
|
|
59
|
+
const adapters = createRedisAdapters(pubClient, subClient, storeClient);
|
|
60
|
+
broadcast = adapters.broadcast;
|
|
61
|
+
shortTermStore = adapters.shortTermStore;
|
|
62
|
+
shortTermLabel = `redis @ ${redisUrl}`;
|
|
63
|
+
longTermLabel = '(none)';
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
broadcast = new MemoryBroadcastProvider();
|
|
67
|
+
shortTermStore = new MemoryShortTermStore();
|
|
68
|
+
shortTermLabel = 'memory';
|
|
69
|
+
longTermLabel = '(none)';
|
|
70
|
+
}
|
|
71
|
+
if (storage !== 'sqlite' && postgresUrl) {
|
|
72
|
+
const sql = postgres(postgresUrl);
|
|
73
|
+
longTermStore = new PostgresLongTermStore(sql);
|
|
74
|
+
longTermLabel = `postgres @ ${postgresUrl}`;
|
|
75
|
+
}
|
|
76
|
+
// Print startup configuration summary
|
|
77
|
+
console.log(`[taskcast] Config: ${configPath ?? '(none)'}`);
|
|
78
|
+
console.log(`[taskcast] Short-term store: ${shortTermLabel}`);
|
|
79
|
+
console.log(`[taskcast] Long-term store: ${longTermLabel}`);
|
|
80
|
+
const engineOpts = { shortTermStore, broadcast };
|
|
81
|
+
if (longTermStore !== undefined)
|
|
82
|
+
engineOpts.longTermStore = longTermStore;
|
|
83
|
+
const engine = new TaskEngine(engineOpts);
|
|
84
|
+
const authMode = (process.env['TASKCAST_AUTH_MODE'] ?? fileConfig.auth?.mode ?? 'none');
|
|
85
|
+
// Worker assignment system
|
|
86
|
+
const workersEnabled = fileConfig.workers?.enabled ?? false;
|
|
87
|
+
let workerManager;
|
|
88
|
+
if (workersEnabled) {
|
|
89
|
+
console.log('[taskcast] Worker assignment system enabled');
|
|
90
|
+
const wmOpts = {
|
|
91
|
+
engine,
|
|
92
|
+
shortTermStore,
|
|
93
|
+
broadcast,
|
|
94
|
+
};
|
|
95
|
+
if (longTermStore !== undefined)
|
|
96
|
+
wmOpts.longTermStore = longTermStore;
|
|
97
|
+
if (fileConfig.workers?.defaults)
|
|
98
|
+
wmOpts.defaults = fileConfig.workers.defaults;
|
|
99
|
+
workerManager = new WorkerManager(wmOpts);
|
|
100
|
+
}
|
|
101
|
+
// Resolve admin token (auto-generate + print if adminApi is enabled)
|
|
102
|
+
resolveAdminToken(fileConfig);
|
|
103
|
+
const serverOpts = {
|
|
104
|
+
engine,
|
|
105
|
+
shortTermStore,
|
|
106
|
+
auth: { mode: authMode },
|
|
107
|
+
config: fileConfig,
|
|
108
|
+
verbose: options.verbose ?? false,
|
|
109
|
+
};
|
|
110
|
+
if (workerManager !== undefined)
|
|
111
|
+
serverOpts.workerManager = workerManager;
|
|
112
|
+
const { app, stop } = createTaskcastApp(serverOpts);
|
|
113
|
+
// Serve playground static files if --playground and dist exists
|
|
114
|
+
if (options.playground) {
|
|
115
|
+
try {
|
|
116
|
+
const require = createRequire(import.meta.url);
|
|
117
|
+
const pkgPath = require.resolve('@taskcast/playground/package.json');
|
|
118
|
+
const distDir = join(dirname(pkgPath), 'dist');
|
|
119
|
+
if (existsSync(distDir)) {
|
|
120
|
+
const { serveStatic } = await import('@hono/node-server/serve-static');
|
|
121
|
+
app.use('/_playground/*', serveStatic({ root: distDir, rewriteRequestPath: (p) => p.replace(/^\/_playground/, '') }));
|
|
122
|
+
// SPA fallback: serve index.html for non-asset paths
|
|
123
|
+
app.get('/_playground/*', serveStatic({ root: distDir, rewriteRequestPath: () => '/index.html' }));
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
console.warn('[taskcast] Playground dist not found. Run `pnpm --filter @taskcast/playground build` first.');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
console.warn('[taskcast] @taskcast/playground not available, skipping playground UI.');
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
const { serve } = await import('@hono/node-server');
|
|
134
|
+
const server = serve({ fetch: app.fetch, port }, () => {
|
|
135
|
+
console.log(`[taskcast] Server started on http://localhost:${port}`);
|
|
136
|
+
if (options.playground) {
|
|
137
|
+
console.log(`[taskcast] Playground UI at http://localhost:${port}/_playground/`);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
// Clean up scheduler/heartbeat on shutdown
|
|
141
|
+
process.on('SIGTERM', () => { stop(); server.close?.(); });
|
|
142
|
+
process.on('SIGINT', () => { stop(); server.close?.(); });
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
export interface TaskListItem {
|
|
3
|
+
id: string;
|
|
4
|
+
type?: string;
|
|
5
|
+
status: string;
|
|
6
|
+
createdAt: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function formatTaskList(tasks: TaskListItem[]): string;
|
|
9
|
+
export declare function formatTaskInspect(task: any, events: any[]): string;
|
|
10
|
+
export declare function registerTasksCommand(program: Command): void;
|
|
11
|
+
//# sourceMappingURL=tasks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../src/commands/tasks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAKnC,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,MAAM,CAa5D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,CAyBlE;AAmBD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAwE3D"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { NodeConfigManager } from '../node-config.js';
|
|
2
|
+
import { createClientFromNodeAsync } from '../client.js';
|
|
3
|
+
export function formatTaskList(tasks) {
|
|
4
|
+
if (tasks.length === 0)
|
|
5
|
+
return 'No tasks found.';
|
|
6
|
+
const header = `${'ID'.padEnd(28)}${'TYPE'.padEnd(13)}${'STATUS'.padEnd(11)}CREATED`;
|
|
7
|
+
const rows = tasks.map((t) => {
|
|
8
|
+
const id = (t.id ?? '').padEnd(28);
|
|
9
|
+
const type = (t.type ?? '').padEnd(13);
|
|
10
|
+
const status = (t.status ?? '').padEnd(11);
|
|
11
|
+
const created = formatTimestamp(t.createdAt);
|
|
12
|
+
return `${id}${type}${status}${created}`;
|
|
13
|
+
});
|
|
14
|
+
return [header, ...rows].join('\n');
|
|
15
|
+
}
|
|
16
|
+
export function formatTaskInspect(task, events) {
|
|
17
|
+
const lines = [];
|
|
18
|
+
lines.push(`Task: ${task.id}`);
|
|
19
|
+
lines.push(` Type: ${task.type ?? ''}`);
|
|
20
|
+
lines.push(` Status: ${task.status}`);
|
|
21
|
+
lines.push(` Params: ${task.params != null ? JSON.stringify(task.params) : ''}`);
|
|
22
|
+
lines.push(` Created: ${formatTimestamp(task.createdAt)}`);
|
|
23
|
+
if (events.length > 0) {
|
|
24
|
+
const last5 = events.slice(-5);
|
|
25
|
+
lines.push('');
|
|
26
|
+
lines.push(`Recent Events (last ${last5.length}):`);
|
|
27
|
+
for (let i = 0; i < last5.length; i++) {
|
|
28
|
+
const e = last5[i];
|
|
29
|
+
const series = e.seriesId ? `series:${e.seriesId}` : '';
|
|
30
|
+
const ts = formatTimestamp(e.timestamp);
|
|
31
|
+
lines.push(` #${i} ${(e.type ?? '').padEnd(13)}${(e.level ?? '').padEnd(7)}${series.padEnd(17)}${ts}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
lines.push('');
|
|
36
|
+
lines.push('No events.');
|
|
37
|
+
}
|
|
38
|
+
return lines.join('\n');
|
|
39
|
+
}
|
|
40
|
+
function formatTimestamp(ts) {
|
|
41
|
+
if (!ts)
|
|
42
|
+
return '';
|
|
43
|
+
const d = new Date(ts);
|
|
44
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
45
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Call _request on the server-sdk client.
|
|
49
|
+
* The SDK doesn't expose a listTasks method, so we use the internal _request
|
|
50
|
+
* to leverage the already-configured auth token and fetch function.
|
|
51
|
+
*/
|
|
52
|
+
async function clientRequest(client, method, path) {
|
|
53
|
+
// Access the private _request method via bracket notation
|
|
54
|
+
return client._request(method, path);
|
|
55
|
+
}
|
|
56
|
+
export function registerTasksCommand(program) {
|
|
57
|
+
const tasks = program
|
|
58
|
+
.command('tasks')
|
|
59
|
+
.description('Manage tasks on a Taskcast server');
|
|
60
|
+
tasks
|
|
61
|
+
.command('list')
|
|
62
|
+
.description('List tasks')
|
|
63
|
+
.option('--status <status>', 'Filter by status (e.g. running)')
|
|
64
|
+
.option('--type <type>', 'Filter by task type (e.g. llm.*)')
|
|
65
|
+
.option('--limit <limit>', 'Maximum number of tasks to show', '20')
|
|
66
|
+
.option('--node <name>', 'Named node to query')
|
|
67
|
+
.action(async (opts) => {
|
|
68
|
+
const mgr = new NodeConfigManager();
|
|
69
|
+
let node;
|
|
70
|
+
if (opts.node) {
|
|
71
|
+
node = mgr.get(opts.node);
|
|
72
|
+
if (!node) {
|
|
73
|
+
console.error(`Node "${opts.node}" not found`);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
node = mgr.getCurrent();
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
const client = await createClientFromNodeAsync(node);
|
|
82
|
+
const params = new URLSearchParams();
|
|
83
|
+
if (opts.status)
|
|
84
|
+
params.set('status', opts.status);
|
|
85
|
+
if (opts.type)
|
|
86
|
+
params.set('type', opts.type);
|
|
87
|
+
const qs = params.toString();
|
|
88
|
+
const path = `/tasks${qs ? `?${qs}` : ''}`;
|
|
89
|
+
const body = await clientRequest(client, 'GET', path);
|
|
90
|
+
const limit = parseInt(opts.limit ?? '20', 10);
|
|
91
|
+
const tasks = body.tasks.slice(0, limit);
|
|
92
|
+
console.log(formatTaskList(tasks));
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
console.error(`Error: ${err.message}`);
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
tasks
|
|
100
|
+
.command('inspect')
|
|
101
|
+
.description('Inspect a task and its recent events')
|
|
102
|
+
.argument('<taskId>', 'Task ID to inspect')
|
|
103
|
+
.option('--node <name>', 'Named node to query')
|
|
104
|
+
.action(async (taskId, opts) => {
|
|
105
|
+
const mgr = new NodeConfigManager();
|
|
106
|
+
let node;
|
|
107
|
+
if (opts.node) {
|
|
108
|
+
node = mgr.get(opts.node);
|
|
109
|
+
if (!node) {
|
|
110
|
+
console.error(`Node "${opts.node}" not found`);
|
|
111
|
+
process.exit(1);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
node = mgr.getCurrent();
|
|
116
|
+
}
|
|
117
|
+
try {
|
|
118
|
+
const client = await createClientFromNodeAsync(node);
|
|
119
|
+
const task = await client.getTask(taskId);
|
|
120
|
+
const events = await client.getHistory(taskId);
|
|
121
|
+
console.log(formatTaskInspect(task, events));
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
console.error(`Error: ${err.message}`);
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=tasks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/commands/tasks.ts"],"names":[],"mappings":"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"}
|