octo-dev 0.4.1 → 0.4.3
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/package.json +3 -2
- package/src/cli/index.ts +1 -1
- package/src/shared/ollama.ts +19 -0
- package/src/shared/process-runner.ts +27 -35
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "octo-dev",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"description": "CLI for monorepo build orchestration, semantic versioning, and local infrastructure management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"commander": "^13.1.0",
|
|
47
|
+
"execa": "^9.6.1",
|
|
47
48
|
"ollama": "^0.5.16",
|
|
48
49
|
"semver": "^7.7.2",
|
|
49
50
|
"tsx": "^4.19.4",
|
|
@@ -55,7 +56,7 @@
|
|
|
55
56
|
"@types/semver": "^7.7.0",
|
|
56
57
|
"fast-check": "^4.1.1",
|
|
57
58
|
"typescript": "^5.8.3",
|
|
58
|
-
"vitest": "^
|
|
59
|
+
"vitest": "^4.1.8"
|
|
59
60
|
},
|
|
60
61
|
"engines": {
|
|
61
62
|
"node": ">=25.0.0"
|
package/src/cli/index.ts
CHANGED
package/src/shared/ollama.ts
CHANGED
|
@@ -19,10 +19,29 @@ async function hasModel(model: string): Promise<boolean> {
|
|
|
19
19
|
return result.stdout.includes(model);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Ensures a system dependency is available, installing it if the user agrees.
|
|
24
|
+
*/
|
|
25
|
+
async function ensureDependency(command: string, installCmd: string, name: string): Promise<boolean> {
|
|
26
|
+
const check = await run('which', [command], { timeout: 5_000 });
|
|
27
|
+
if (check.exitCode === 0) return true;
|
|
28
|
+
|
|
29
|
+
const shouldInstall = await confirm(`${name} não encontrado (necessário para Ollama). Instalar? (s/n) `);
|
|
30
|
+
if (!shouldInstall) return false;
|
|
31
|
+
|
|
32
|
+
const result = await run('sudo', installCmd.split(' '), { timeout: 60_000, interactive: true });
|
|
33
|
+
return result.exitCode === 0;
|
|
34
|
+
}
|
|
35
|
+
|
|
22
36
|
/**
|
|
23
37
|
* Installs Ollama via the official install script.
|
|
24
38
|
*/
|
|
25
39
|
async function install(): Promise<boolean> {
|
|
40
|
+
// Ollama requires zstd for extraction
|
|
41
|
+
if (!await ensureDependency('zstd', 'apt-get install -y zstd', 'zstd')) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
|
|
26
45
|
logger.info('Instalando Ollama...');
|
|
27
46
|
const result = await run('curl -fsSL https://ollama.com/install.sh | sh', [], {
|
|
28
47
|
timeout: 120_000,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { execaCommand, execa } from 'execa';
|
|
2
2
|
|
|
3
3
|
export interface RunOptions {
|
|
4
4
|
cwd?: string;
|
|
@@ -6,7 +6,7 @@ export interface RunOptions {
|
|
|
6
6
|
env?: Record<string, string>;
|
|
7
7
|
/** When true, inherits stdio so the user can interact (e.g. git password prompts) */
|
|
8
8
|
interactive?: boolean;
|
|
9
|
-
/** When true, runs command through the system shell. Use only for piped commands. */
|
|
9
|
+
/** When true, runs command through the system shell. Use only for piped/complex commands. */
|
|
10
10
|
shell?: boolean;
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -16,39 +16,31 @@ export interface RunResult {
|
|
|
16
16
|
exitCode: number;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
/**
|
|
20
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Executes a command with args. Powered by execa.
|
|
21
|
+
* Returns stdout, stderr, and exitCode without throwing on non-zero exit.
|
|
22
|
+
*/
|
|
23
|
+
export async function run(command: string, args: string[] = [], options: RunOptions = {}): Promise<RunResult> {
|
|
21
24
|
const { cwd, timeout = 60_000, env, interactive = false, shell = false } = options;
|
|
22
25
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
child.on('close', (code) => {
|
|
45
|
-
clearTimeout(timer);
|
|
46
|
-
resolve({ stdout, stderr, exitCode: code ?? 1 });
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
child.on('error', (err) => {
|
|
50
|
-
clearTimeout(timer);
|
|
51
|
-
reject(err);
|
|
52
|
-
});
|
|
53
|
-
});
|
|
26
|
+
const execOptions = {
|
|
27
|
+
cwd,
|
|
28
|
+
env: env ? { ...process.env, ...env } : undefined,
|
|
29
|
+
timeout,
|
|
30
|
+
shell,
|
|
31
|
+
reject: false,
|
|
32
|
+
stdin: interactive ? 'inherit' as const : undefined,
|
|
33
|
+
stdout: interactive ? 'inherit' as const : 'pipe' as const,
|
|
34
|
+
stderr: interactive ? 'inherit' as const : 'pipe' as const,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const result = shell && args.length === 0
|
|
38
|
+
? await execaCommand(command, execOptions)
|
|
39
|
+
: await execa(command, args, execOptions);
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
stdout: result.stdout ?? '',
|
|
43
|
+
stderr: result.stderr ?? '',
|
|
44
|
+
exitCode: result.exitCode ?? 1,
|
|
45
|
+
};
|
|
54
46
|
}
|