@ezlkg/shn 1.0.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/commands/logs.d.ts +5 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +53 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/start.d.ts +14 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +146 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/status.d.ts +5 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +23 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/stop.d.ts +5 -0
- package/dist/commands/stop.d.ts.map +1 -0
- package/dist/commands/stop.js +9 -0
- package/dist/commands/stop.js.map +1 -0
- package/dist/commands/update.d.ts +5 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +9 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/workspaces.d.ts +5 -0
- package/dist/commands/workspaces.d.ts.map +1 -0
- package/dist/commands/workspaces.js +19 -0
- package/dist/commands/workspaces.js.map +1 -0
- package/dist/docker.d.ts +58 -0
- package/dist/docker.d.ts.map +1 -0
- package/dist/docker.js +159 -0
- package/dist/docker.js.map +1 -0
- package/dist/env.d.ts +26 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +119 -0
- package/dist/env.js.map +1 -0
- package/dist/home.d.ts +16 -0
- package/dist/home.d.ts.map +1 -0
- package/dist/home.js +52 -0
- package/dist/home.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +167 -0
- package/dist/index.js.map +1 -0
- package/dist/paths.d.ts +25 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +57 -0
- package/dist/paths.js.map +1 -0
- package/dist/splash.d.ts +5 -0
- package/dist/splash.d.ts.map +1 -0
- package/dist/splash.js +38 -0
- package/dist/splash.js.map +1 -0
- package/infra/compose.yml +50 -0
- package/infra/router-config.json +33 -0
- package/package.json +42 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,wBAAgB,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAkD9C"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `shannon logs` command — tail a workspace's workflow log.
|
|
3
|
+
*/
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { spawn } from 'node:child_process';
|
|
7
|
+
import { getWorkspacesDir } from '../home.js';
|
|
8
|
+
export function logs(workspaceId) {
|
|
9
|
+
const workspacesDir = getWorkspacesDir();
|
|
10
|
+
let logFile = '';
|
|
11
|
+
// 1. Direct match
|
|
12
|
+
const directPath = path.join(workspacesDir, workspaceId, 'workflow.log');
|
|
13
|
+
if (fs.existsSync(directPath)) {
|
|
14
|
+
logFile = directPath;
|
|
15
|
+
}
|
|
16
|
+
// 2. Resume workflow ID (e.g. workspace_resume_123)
|
|
17
|
+
if (!logFile) {
|
|
18
|
+
const base = workspaceId.replace(/_resume_\d+$/, '');
|
|
19
|
+
if (base !== workspaceId) {
|
|
20
|
+
const resumePath = path.join(workspacesDir, base, 'workflow.log');
|
|
21
|
+
if (fs.existsSync(resumePath)) {
|
|
22
|
+
logFile = resumePath;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// 3. Named workspace ID (e.g. workspace_shannon-123)
|
|
27
|
+
if (!logFile) {
|
|
28
|
+
const base = workspaceId.replace(/_shannon-\d+$/, '');
|
|
29
|
+
if (base !== workspaceId) {
|
|
30
|
+
const namedPath = path.join(workspacesDir, base, 'workflow.log');
|
|
31
|
+
if (fs.existsSync(namedPath)) {
|
|
32
|
+
logFile = namedPath;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (!logFile) {
|
|
37
|
+
console.error(`ERROR: Workflow log not found for: ${workspaceId}`);
|
|
38
|
+
console.error('');
|
|
39
|
+
console.error('Possible causes:');
|
|
40
|
+
console.error(' - Workflow hasn\'t started yet');
|
|
41
|
+
console.error(' - Workspace ID is incorrect');
|
|
42
|
+
console.error('');
|
|
43
|
+
console.error('Check the Temporal Web UI at http://localhost:8233 for workflow details');
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
console.log(`Tailing workflow log: ${logFile}`);
|
|
47
|
+
const tail = spawn('tail', ['-f', logFile], { stdio: 'inherit' });
|
|
48
|
+
process.on('SIGINT', () => {
|
|
49
|
+
tail.kill();
|
|
50
|
+
process.exit(0);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=logs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.js","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,UAAU,IAAI,CAAC,WAAmB;IACtC,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAC;IACzC,IAAI,OAAO,GAAG,EAAE,CAAC;IAEjB,kBAAkB;IAClB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC;IACzE,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,OAAO,GAAG,UAAU,CAAC;IACvB,CAAC;IAED,oDAAoD;IACpD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;QACrD,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;YACzB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;YAClE,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC9B,OAAO,GAAG,UAAU,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;IAED,qDAAqD;IACrD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;QACtD,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;YACzB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;YACjE,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC7B,OAAO,GAAG,SAAS,CAAC;YACtB,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,sCAAsC,WAAW,EAAE,CAAC,CAAC;QACnE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;QAClD,OAAO,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAC/C,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,yEAAyE,CAAC,CAAC;QACzF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,yBAAyB,OAAO,EAAE,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IAElE,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;QACxB,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `shannon start` command — launch a pentest scan.
|
|
3
|
+
*/
|
|
4
|
+
export interface StartArgs {
|
|
5
|
+
url: string;
|
|
6
|
+
repo: string;
|
|
7
|
+
config?: string;
|
|
8
|
+
workspace?: string;
|
|
9
|
+
pipelineTesting: boolean;
|
|
10
|
+
router: boolean;
|
|
11
|
+
version: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function start(args: StartArgs): void;
|
|
14
|
+
//# sourceMappingURL=start.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AAAA;;GAEG;AAWH,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,OAAO,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,KAAK,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,CAyH3C"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `shannon start` command — launch a pentest scan.
|
|
3
|
+
*/
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { execSync } from 'node:child_process';
|
|
7
|
+
import { initHome, getWorkspacesDir, getCredentialsPath } from '../home.js';
|
|
8
|
+
import { loadEnv, buildEnvFlags, validateCredentials } from '../env.js';
|
|
9
|
+
import { resolveRepo, resolveConfig, ensureDeliverables } from '../paths.js';
|
|
10
|
+
import { ensureInfra, pullImage, spawnWorker, randomSuffix } from '../docker.js';
|
|
11
|
+
import { displaySplash } from '../splash.js';
|
|
12
|
+
export function start(args) {
|
|
13
|
+
// 1. Initialize ~/.shannon and load env
|
|
14
|
+
initHome();
|
|
15
|
+
loadEnv();
|
|
16
|
+
// 2. Validate credentials
|
|
17
|
+
const creds = validateCredentials(args.router);
|
|
18
|
+
if (!creds.valid) {
|
|
19
|
+
console.error(`ERROR: ${creds.error}`);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
// 3. Resolve paths
|
|
23
|
+
const repo = resolveRepo(args.repo);
|
|
24
|
+
const config = args.config ? resolveConfig(args.config) : undefined;
|
|
25
|
+
ensureDeliverables(repo.hostPath);
|
|
26
|
+
// 4. Ensure workspaces dir is writable by container user (UID 1001)
|
|
27
|
+
const workspacesDir = getWorkspacesDir();
|
|
28
|
+
fs.mkdirSync(workspacesDir, { recursive: true });
|
|
29
|
+
fs.chmodSync(workspacesDir, 0o777);
|
|
30
|
+
// 5. Handle router env
|
|
31
|
+
if (args.router) {
|
|
32
|
+
process.env.ANTHROPIC_BASE_URL = 'http://shannon-router:3456';
|
|
33
|
+
process.env.ANTHROPIC_AUTH_TOKEN = 'shannon-router-key';
|
|
34
|
+
}
|
|
35
|
+
// 6. Pull image and start infra
|
|
36
|
+
pullImage();
|
|
37
|
+
ensureInfra(args.router);
|
|
38
|
+
// 7. Generate unique task queue and container name
|
|
39
|
+
const suffix = randomSuffix();
|
|
40
|
+
const taskQueue = `shannon-${suffix}`;
|
|
41
|
+
const containerName = `shannon-worker-${suffix}`;
|
|
42
|
+
// 8. Generate workspace name if not provided
|
|
43
|
+
let workspace = args.workspace;
|
|
44
|
+
if (!workspace) {
|
|
45
|
+
const hostname = new URL(args.url).hostname.replace(/[^a-zA-Z0-9-]/g, '-');
|
|
46
|
+
workspace = `${hostname}_shannon-${Date.now()}`;
|
|
47
|
+
}
|
|
48
|
+
// 9. Check for GCP credentials
|
|
49
|
+
const credentialsPath = getCredentialsPath();
|
|
50
|
+
const hasCredentials = fs.existsSync(credentialsPath);
|
|
51
|
+
// 10. Display splash screen
|
|
52
|
+
displaySplash(args.version);
|
|
53
|
+
// 11. Spawn worker container
|
|
54
|
+
const proc = spawnWorker({
|
|
55
|
+
url: args.url,
|
|
56
|
+
repo,
|
|
57
|
+
workspacesDir,
|
|
58
|
+
taskQueue,
|
|
59
|
+
containerName,
|
|
60
|
+
envFlags: buildEnvFlags(),
|
|
61
|
+
...(config && { config }),
|
|
62
|
+
...(hasCredentials && { credentials: credentialsPath }),
|
|
63
|
+
...(workspace && { workspace }),
|
|
64
|
+
...(args.pipelineTesting && { pipelineTesting: true }),
|
|
65
|
+
});
|
|
66
|
+
// 12. Wait for workflow.log to appear, then display info
|
|
67
|
+
const workflowLog = path.join(workspacesDir, workspace, 'workflow.log');
|
|
68
|
+
proc.on('error', (err) => {
|
|
69
|
+
console.error(`Failed to start worker: ${err.message}`);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
});
|
|
72
|
+
// Poll for workflow.log header
|
|
73
|
+
process.stdout.write('Waiting for workflow to start...');
|
|
74
|
+
let workflowId = '';
|
|
75
|
+
let attempts = 0;
|
|
76
|
+
const pollInterval = setInterval(() => {
|
|
77
|
+
attempts++;
|
|
78
|
+
if (attempts > 60) {
|
|
79
|
+
clearInterval(pollInterval);
|
|
80
|
+
process.stdout.write('\n');
|
|
81
|
+
console.error('Timeout waiting for workflow to start');
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
const content = fs.readFileSync(workflowLog, 'utf-8');
|
|
86
|
+
if (content.includes('====')) {
|
|
87
|
+
clearInterval(pollInterval);
|
|
88
|
+
// Extract workflow ID
|
|
89
|
+
const match = /^Workflow ID: (.+)$/m.exec(content);
|
|
90
|
+
if (match?.[1]) {
|
|
91
|
+
workflowId = match[1];
|
|
92
|
+
}
|
|
93
|
+
// Clear waiting line and show info
|
|
94
|
+
process.stdout.write('\r\x1b[K');
|
|
95
|
+
printInfo(args, workspace, workflowId, repo.hostPath);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// File doesn't exist yet
|
|
101
|
+
}
|
|
102
|
+
process.stdout.write('.');
|
|
103
|
+
}, 2000);
|
|
104
|
+
// Handle SIGINT — stop the worker container
|
|
105
|
+
const cleanup = () => {
|
|
106
|
+
clearInterval(pollInterval);
|
|
107
|
+
console.log(`\nStopping worker ${containerName}...`);
|
|
108
|
+
try {
|
|
109
|
+
execSync(`docker stop ${containerName}`, { stdio: 'pipe' });
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// Container may have already exited
|
|
113
|
+
}
|
|
114
|
+
process.exit(0);
|
|
115
|
+
};
|
|
116
|
+
process.on('SIGINT', cleanup);
|
|
117
|
+
process.on('SIGTERM', cleanup);
|
|
118
|
+
}
|
|
119
|
+
function printInfo(args, workspace, workflowId, repoPath) {
|
|
120
|
+
console.log(` Target: ${args.url}`);
|
|
121
|
+
console.log(` Repository: ${repoPath}`);
|
|
122
|
+
console.log(` Workspace: ${workspace}`);
|
|
123
|
+
if (args.config) {
|
|
124
|
+
console.log(` Config: ${path.resolve(args.config)}`);
|
|
125
|
+
}
|
|
126
|
+
if (args.pipelineTesting) {
|
|
127
|
+
console.log(' Mode: Pipeline Testing');
|
|
128
|
+
}
|
|
129
|
+
if (args.router) {
|
|
130
|
+
console.log(' Router: Enabled');
|
|
131
|
+
}
|
|
132
|
+
console.log('');
|
|
133
|
+
console.log(' Monitor:');
|
|
134
|
+
if (workflowId) {
|
|
135
|
+
console.log(` Web UI: http://localhost:8233/namespaces/default/workflows/${workflowId}`);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
console.log(' Web UI: http://localhost:8233');
|
|
139
|
+
}
|
|
140
|
+
console.log(` Logs: npx @ezlkg/shn logs ${workspace}`);
|
|
141
|
+
console.log('');
|
|
142
|
+
console.log(' Output:');
|
|
143
|
+
console.log(` Reports: ~/.shannon/workspaces/${workspace}/`);
|
|
144
|
+
console.log('');
|
|
145
|
+
}
|
|
146
|
+
//# 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 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,wBAAgB,MAAM,IAAI,IAAI,CAiB7B"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `shannon status` command — show running workers and Temporal health.
|
|
3
|
+
*/
|
|
4
|
+
import { isTemporalReady, listRunningWorkers } from '../docker.js';
|
|
5
|
+
export function status() {
|
|
6
|
+
// 1. Temporal health
|
|
7
|
+
const temporalUp = isTemporalReady();
|
|
8
|
+
console.log(`Temporal: ${temporalUp ? 'running' : 'not running'}`);
|
|
9
|
+
if (temporalUp) {
|
|
10
|
+
console.log(' Web UI: http://localhost:8233');
|
|
11
|
+
}
|
|
12
|
+
console.log('');
|
|
13
|
+
// 2. Running workers
|
|
14
|
+
const workers = listRunningWorkers();
|
|
15
|
+
if (workers) {
|
|
16
|
+
console.log('Workers:');
|
|
17
|
+
console.log(workers);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
console.log('Workers: none running');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEnE,MAAM,UAAU,MAAM;IACpB,qBAAqB;IACrB,MAAM,UAAU,GAAG,eAAe,EAAE,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,aAAa,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC;IACnE,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,qBAAqB;IACrB,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;IACrC,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACvC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop.d.ts","sourceRoot":"","sources":["../../src/commands/stop.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,wBAAgB,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAGzC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop.js","sourceRoot":"","sources":["../../src/commands/stop.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEtD,MAAM,UAAU,IAAI,CAAC,KAAc;IACjC,WAAW,EAAE,CAAC;IACd,SAAS,CAAC,KAAK,CAAC,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,wBAAgB,MAAM,IAAI,IAAI,CAG7B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,UAAU,MAAM;IACpB,UAAU,EAAE,CAAC;IACb,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../../src/commands/workspaces.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,wBAAgB,UAAU,IAAI,IAAI,CAcjC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `shannon workspaces` command — list all workspaces.
|
|
3
|
+
*/
|
|
4
|
+
import { execSync } from 'node:child_process';
|
|
5
|
+
import { getWorkspacesDir } from '../home.js';
|
|
6
|
+
import { getWorkerImage } from '../docker.js';
|
|
7
|
+
export function workspaces() {
|
|
8
|
+
const workspacesDir = getWorkspacesDir();
|
|
9
|
+
const image = getWorkerImage();
|
|
10
|
+
try {
|
|
11
|
+
execSync(`docker run --rm -v "${workspacesDir}:/app/workspaces" -e "WORKSPACES_DIR=/app/workspaces" "${image}" node dist/temporal/workspaces.js`, { stdio: 'inherit' });
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
console.error('ERROR: Failed to list workspaces. Is the Docker image available?');
|
|
15
|
+
console.error(` Run: docker pull ${image}`);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=workspaces.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspaces.js","sourceRoot":"","sources":["../../src/commands/workspaces.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,MAAM,UAAU,UAAU;IACxB,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,cAAc,EAAE,CAAC;IAE/B,IAAI,CAAC;QACH,QAAQ,CACN,uBAAuB,aAAa,0DAA0D,KAAK,oCAAoC,EACvI,EAAE,KAAK,EAAE,SAAS,EAAE,CACrB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAClF,OAAO,CAAC,KAAK,CAAC,sBAAsB,KAAK,EAAE,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
package/dist/docker.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Docker orchestration — compose lifecycle, network, image pull, worker spawning.
|
|
3
|
+
*/
|
|
4
|
+
import { type ChildProcess } from 'node:child_process';
|
|
5
|
+
export declare function getWorkerImage(): string;
|
|
6
|
+
/** Generate an 8-char random hex suffix for container/queue names. */
|
|
7
|
+
export declare function randomSuffix(): string;
|
|
8
|
+
/**
|
|
9
|
+
* Check if Temporal is running and healthy.
|
|
10
|
+
*/
|
|
11
|
+
export declare function isTemporalReady(): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Ensure Temporal (and optionally router) are running via compose.
|
|
14
|
+
*/
|
|
15
|
+
export declare function ensureInfra(useRouter: boolean): void;
|
|
16
|
+
/**
|
|
17
|
+
* Pull the worker image if not already present.
|
|
18
|
+
*/
|
|
19
|
+
export declare function pullImage(): void;
|
|
20
|
+
export interface WorkerOptions {
|
|
21
|
+
url: string;
|
|
22
|
+
repo: {
|
|
23
|
+
hostPath: string;
|
|
24
|
+
containerPath: string;
|
|
25
|
+
};
|
|
26
|
+
workspacesDir: string;
|
|
27
|
+
taskQueue: string;
|
|
28
|
+
containerName: string;
|
|
29
|
+
envFlags: string[];
|
|
30
|
+
config?: {
|
|
31
|
+
hostPath: string;
|
|
32
|
+
containerPath: string;
|
|
33
|
+
};
|
|
34
|
+
credentials?: string;
|
|
35
|
+
workspace?: string;
|
|
36
|
+
pipelineTesting?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Spawn the worker container in detached mode and return the process.
|
|
40
|
+
*/
|
|
41
|
+
export declare function spawnWorker(opts: WorkerOptions): ChildProcess;
|
|
42
|
+
/**
|
|
43
|
+
* Stop all running shannon-worker-* containers.
|
|
44
|
+
*/
|
|
45
|
+
export declare function stopWorkers(): void;
|
|
46
|
+
/**
|
|
47
|
+
* Tear down the compose stack.
|
|
48
|
+
*/
|
|
49
|
+
export declare function stopInfra(clean: boolean): void;
|
|
50
|
+
/**
|
|
51
|
+
* Pull the latest worker image (for `update` command).
|
|
52
|
+
*/
|
|
53
|
+
export declare function pullLatest(): void;
|
|
54
|
+
/**
|
|
55
|
+
* List running worker containers.
|
|
56
|
+
*/
|
|
57
|
+
export declare function listRunningWorkers(): string;
|
|
58
|
+
//# sourceMappingURL=docker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["../src/docker.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAWxE,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,sEAAsE;AACtE,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAqBD;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAIzC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAqBpD;AAED;;GAEG;AACH,wBAAgB,SAAS,IAAI,IAAI,CAQhC;AAgBD,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,aAAa,GAAG,YAAY,CAwC7D;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAMlC;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAK9C;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAGjC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C"}
|
package/dist/docker.js
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Docker orchestration — compose lifecycle, network, image pull, worker spawning.
|
|
3
|
+
*/
|
|
4
|
+
import { execSync, spawn } from 'node:child_process';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import os from 'node:os';
|
|
7
|
+
import crypto from 'node:crypto';
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
9
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const WORKER_IMAGE = 'ezlkgp/shn:latest';
|
|
11
|
+
const COMPOSE_FILE = path.resolve(__dirname, '..', 'infra', 'compose.yml');
|
|
12
|
+
export function getWorkerImage() {
|
|
13
|
+
return WORKER_IMAGE;
|
|
14
|
+
}
|
|
15
|
+
/** Generate an 8-char random hex suffix for container/queue names. */
|
|
16
|
+
export function randomSuffix() {
|
|
17
|
+
return crypto.randomBytes(4).toString('hex');
|
|
18
|
+
}
|
|
19
|
+
/** Run a command silently, return true if it succeeds. */
|
|
20
|
+
function execQuiet(cmd) {
|
|
21
|
+
try {
|
|
22
|
+
execSync(cmd, { stdio: 'pipe' });
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/** Run a command and return stdout, or empty string on failure. */
|
|
30
|
+
function execOutput(cmd) {
|
|
31
|
+
try {
|
|
32
|
+
return execSync(cmd, { stdio: 'pipe', encoding: 'utf-8' }).trim();
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return '';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Check if Temporal is running and healthy.
|
|
40
|
+
*/
|
|
41
|
+
export function isTemporalReady() {
|
|
42
|
+
return execQuiet('docker exec shannon-temporal temporal operator cluster health --address localhost:7233 2>/dev/null | grep -q SERVING');
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Ensure Temporal (and optionally router) are running via compose.
|
|
46
|
+
*/
|
|
47
|
+
export function ensureInfra(useRouter) {
|
|
48
|
+
if (isTemporalReady()) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
console.log('Starting Shannon infrastructure...');
|
|
52
|
+
const profiles = useRouter ? '--profile router' : '';
|
|
53
|
+
execSync(`docker compose -f "${COMPOSE_FILE}" ${profiles} up -d`, {
|
|
54
|
+
stdio: 'inherit',
|
|
55
|
+
});
|
|
56
|
+
console.log('Waiting for Temporal to be ready...');
|
|
57
|
+
for (let i = 0; i < 30; i++) {
|
|
58
|
+
if (isTemporalReady()) {
|
|
59
|
+
console.log('Temporal is ready!');
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
execSync('sleep 2');
|
|
63
|
+
}
|
|
64
|
+
console.error('Timeout waiting for Temporal');
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Pull the worker image if not already present.
|
|
69
|
+
*/
|
|
70
|
+
export function pullImage() {
|
|
71
|
+
const exists = execQuiet(`docker image inspect "${WORKER_IMAGE}" 2>/dev/null`);
|
|
72
|
+
if (exists) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
console.log(`Pulling ${WORKER_IMAGE}...`);
|
|
76
|
+
execSync(`docker pull "${WORKER_IMAGE}"`, { stdio: 'inherit' });
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Detect if --add-host is needed (Linux without Podman).
|
|
80
|
+
* macOS has host.docker.internal built in.
|
|
81
|
+
*/
|
|
82
|
+
function addHostFlag() {
|
|
83
|
+
if (os.platform() === 'linux') {
|
|
84
|
+
const hasPodman = execQuiet('command -v podman');
|
|
85
|
+
if (!hasPodman) {
|
|
86
|
+
return ['--add-host', 'host.docker.internal:host-gateway'];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Spawn the worker container in detached mode and return the process.
|
|
93
|
+
*/
|
|
94
|
+
export function spawnWorker(opts) {
|
|
95
|
+
const args = ['run', '-d', '--rm', '--name', opts.containerName, '--network', 'shannon-net'];
|
|
96
|
+
// Add host flag for Linux
|
|
97
|
+
args.push(...addHostFlag());
|
|
98
|
+
// Volume mounts
|
|
99
|
+
args.push('-v', `${opts.workspacesDir}:/app/workspaces`);
|
|
100
|
+
args.push('-v', `${opts.repo.hostPath}:${opts.repo.containerPath}`);
|
|
101
|
+
if (opts.config) {
|
|
102
|
+
args.push('-v', `${opts.config.hostPath}:${opts.config.containerPath}:ro`);
|
|
103
|
+
}
|
|
104
|
+
if (opts.credentials) {
|
|
105
|
+
args.push('-v', `${opts.credentials}:/app/credentials/google-sa-vertex-key.json:ro`);
|
|
106
|
+
}
|
|
107
|
+
// Environment
|
|
108
|
+
args.push(...opts.envFlags);
|
|
109
|
+
// Container settings
|
|
110
|
+
args.push('--shm-size', '2gb', '--ipc', 'host', '--security-opt', 'seccomp=unconfined');
|
|
111
|
+
// Image
|
|
112
|
+
args.push(WORKER_IMAGE);
|
|
113
|
+
// Worker command
|
|
114
|
+
args.push('node', 'dist/temporal/worker.js', opts.url, opts.repo.containerPath);
|
|
115
|
+
args.push('--task-queue', opts.taskQueue);
|
|
116
|
+
if (opts.config) {
|
|
117
|
+
args.push('--config', opts.config.containerPath);
|
|
118
|
+
}
|
|
119
|
+
if (opts.workspace) {
|
|
120
|
+
args.push('--workspace', opts.workspace);
|
|
121
|
+
}
|
|
122
|
+
if (opts.pipelineTesting) {
|
|
123
|
+
args.push('--pipeline-testing');
|
|
124
|
+
}
|
|
125
|
+
return spawn('docker', args, { stdio: 'pipe' });
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Stop all running shannon-worker-* containers.
|
|
129
|
+
*/
|
|
130
|
+
export function stopWorkers() {
|
|
131
|
+
const workers = execOutput('docker ps -q --filter "name=shannon-worker-"');
|
|
132
|
+
if (workers) {
|
|
133
|
+
console.log('Stopping worker containers...');
|
|
134
|
+
execSync(`echo "${workers}" | xargs docker stop`, { stdio: 'inherit' });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Tear down the compose stack.
|
|
139
|
+
*/
|
|
140
|
+
export function stopInfra(clean) {
|
|
141
|
+
const cleanFlag = clean ? '-v' : '';
|
|
142
|
+
execSync(`docker compose -f "${COMPOSE_FILE}" --profile router down ${cleanFlag}`, {
|
|
143
|
+
stdio: 'inherit',
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Pull the latest worker image (for `update` command).
|
|
148
|
+
*/
|
|
149
|
+
export function pullLatest() {
|
|
150
|
+
console.log(`Pulling ${WORKER_IMAGE}...`);
|
|
151
|
+
execSync(`docker pull "${WORKER_IMAGE}"`, { stdio: 'inherit' });
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* List running worker containers.
|
|
155
|
+
*/
|
|
156
|
+
export function listRunningWorkers() {
|
|
157
|
+
return execOutput('docker ps --filter "name=shannon-worker-" --format "table {{.Names}}\t{{.Status}}\t{{.RunningFor}}"');
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=docker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker.js","sourceRoot":"","sources":["../src/docker.ts"],"names":[],"mappings":"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"}
|
package/dist/env.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment variable loading and credential validation.
|
|
3
|
+
*
|
|
4
|
+
* Loads ~/.shannon/.env and validates that at least one authentication
|
|
5
|
+
* method is configured (API key, OAuth, Bedrock, Vertex, or router).
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Load ~/.shannon/.env into process.env.
|
|
9
|
+
* Existing env vars take precedence (standard dotenv behavior).
|
|
10
|
+
*/
|
|
11
|
+
export declare function loadEnv(): void;
|
|
12
|
+
/**
|
|
13
|
+
* Build `-e KEY=VALUE` flags for docker run, only for set variables.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildEnvFlags(): string[];
|
|
16
|
+
interface CredentialValidation {
|
|
17
|
+
valid: boolean;
|
|
18
|
+
error?: string;
|
|
19
|
+
mode: 'api-key' | 'oauth' | 'bedrock' | 'vertex' | 'router';
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Validate that at least one authentication method is configured.
|
|
23
|
+
*/
|
|
24
|
+
export declare function validateCredentials(useRouter: boolean): CredentialValidation;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAyBH;;;GAGG;AACH,wBAAgB,OAAO,IAAI,IAAI,CAE9B;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAWxC;AAED,UAAU,oBAAoB;IAC5B,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;CAC7D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,OAAO,GAAG,oBAAoB,CA2D5E"}
|