@ottocode/sdk 0.1.304 → 0.1.305
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ottocode/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.305",
|
|
4
4
|
"description": "AI agent SDK for building intelligent assistants - tree-shakable and comprehensive",
|
|
5
5
|
"author": "nitishxyz",
|
|
6
6
|
"license": "MIT",
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
"@ai-sdk/provider": "3.0.10",
|
|
106
106
|
"@ai-sdk/provider-utils": "4.0.27",
|
|
107
107
|
"@ai-sdk/xai": "3.0.93",
|
|
108
|
-
"@ff-labs/fff-bun": "0.9.
|
|
108
|
+
"@ff-labs/fff-bun": "0.9.4",
|
|
109
109
|
"@modelcontextprotocol/sdk": "1.27.1",
|
|
110
110
|
"@openauthjs/openauth": "0.4.3",
|
|
111
111
|
"@openrouter/ai-sdk-provider": "1.5.4",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { join } from 'node:path';
|
|
2
|
-
import { spawn,
|
|
2
|
+
import { spawn, execFileSync } from 'node:child_process';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import {
|
|
5
5
|
clearCachedBinaries,
|
|
@@ -10,7 +10,10 @@ import { fileExists, isExecutable } from './bin-manager/filesystem.ts';
|
|
|
10
10
|
import { getAgiBinDir, getBinaryFileName } from './bin-manager/paths.ts';
|
|
11
11
|
import { extractFromVendor } from './bin-manager/vendor.ts';
|
|
12
12
|
|
|
13
|
-
let cachedLoginPath:
|
|
13
|
+
let cachedLoginPath: {
|
|
14
|
+
key: string;
|
|
15
|
+
path: string | null;
|
|
16
|
+
} | null = null;
|
|
14
17
|
|
|
15
18
|
export { getAgiBinDir } from './bin-manager/paths.ts';
|
|
16
19
|
|
|
@@ -64,15 +67,61 @@ export function clearBinaryCache(): void {
|
|
|
64
67
|
clearCachedBinaries();
|
|
65
68
|
}
|
|
66
69
|
|
|
67
|
-
function
|
|
68
|
-
if (
|
|
70
|
+
export function getUserShell(): string {
|
|
71
|
+
if (process.platform === 'win32') return process.env.COMSPEC || 'cmd.exe';
|
|
72
|
+
return process.env.SHELL || '/bin/bash';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function getShellRcBootstrap(shell: string): string {
|
|
76
|
+
const shellName = shell.split('/').pop() || '';
|
|
77
|
+
if (shellName.includes('zsh')) {
|
|
78
|
+
return 'if [ -f "$HOME/.zshrc" ]; then . "$HOME/.zshrc"; fi';
|
|
79
|
+
}
|
|
80
|
+
if (shellName.includes('bash')) {
|
|
81
|
+
return 'if [ -f "$HOME/.bashrc" ]; then . "$HOME/.bashrc"; fi';
|
|
82
|
+
}
|
|
83
|
+
return '';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function getInteractiveShellFlag(shell: string): string {
|
|
87
|
+
const shellName = shell.split('/').pop() || '';
|
|
88
|
+
if (shellName.includes('bash')) return '-ic';
|
|
89
|
+
return '-ilc';
|
|
90
|
+
}
|
|
69
91
|
|
|
92
|
+
export function getShellExecutionConfig(cmd: string): {
|
|
93
|
+
command: string;
|
|
94
|
+
args: string[];
|
|
95
|
+
env: NodeJS.ProcessEnv;
|
|
96
|
+
} {
|
|
97
|
+
const env = { ...process.env, PATH: getAugmentedPath() };
|
|
70
98
|
if (process.platform === 'win32') {
|
|
71
|
-
|
|
72
|
-
|
|
99
|
+
return {
|
|
100
|
+
command: getUserShell(),
|
|
101
|
+
args: ['/d', '/s', '/c', cmd],
|
|
102
|
+
env,
|
|
103
|
+
};
|
|
73
104
|
}
|
|
74
105
|
|
|
106
|
+
const command = getUserShell();
|
|
107
|
+
return {
|
|
108
|
+
command,
|
|
109
|
+
args: [getInteractiveShellFlag(command), 'eval "$OTTO_SHELL_COMMAND"'],
|
|
110
|
+
env: { ...env, OTTO_SHELL_COMMAND: cmd },
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function getLoginShellPath(): string | null {
|
|
75
115
|
const home = process.env.HOME || homedir();
|
|
116
|
+
const userShell = getUserShell();
|
|
117
|
+
const cacheKey = [home, userShell, process.env.PATH || ''].join('\0');
|
|
118
|
+
if (cachedLoginPath?.key === cacheKey) return cachedLoginPath.path;
|
|
119
|
+
|
|
120
|
+
if (process.platform === 'win32') {
|
|
121
|
+
cachedLoginPath = { key: cacheKey, path: process.env.PATH || '' };
|
|
122
|
+
return cachedLoginPath.path;
|
|
123
|
+
}
|
|
124
|
+
|
|
76
125
|
const shellCandidates = [
|
|
77
126
|
process.env.SHELL,
|
|
78
127
|
'/bin/zsh',
|
|
@@ -82,21 +131,28 @@ function getLoginShellPath(): string | null {
|
|
|
82
131
|
|
|
83
132
|
for (const shell of shellCandidates) {
|
|
84
133
|
try {
|
|
85
|
-
const
|
|
134
|
+
const rcBootstrap = getShellRcBootstrap(shell);
|
|
135
|
+
const pathCommand = `${rcBootstrap ? `${rcBootstrap}\n` : ''}echo "___PATH___:$PATH"`;
|
|
136
|
+
const result = execFileSync(shell, ['-ilc', pathCommand], {
|
|
86
137
|
timeout: 5000,
|
|
87
138
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
88
|
-
env: {
|
|
139
|
+
env: {
|
|
140
|
+
...process.env,
|
|
141
|
+
HOME: home,
|
|
142
|
+
USER: process.env.USER || '',
|
|
143
|
+
SHELL: shell,
|
|
144
|
+
},
|
|
89
145
|
});
|
|
90
146
|
const output = result.toString();
|
|
91
147
|
const match = output.match(/___PATH___:(.*)/);
|
|
92
148
|
if (match?.[1]?.trim()) {
|
|
93
|
-
cachedLoginPath = match[1].trim();
|
|
94
|
-
return cachedLoginPath;
|
|
149
|
+
cachedLoginPath = { key: cacheKey, path: match[1].trim() };
|
|
150
|
+
return cachedLoginPath.path;
|
|
95
151
|
}
|
|
96
152
|
} catch {}
|
|
97
153
|
}
|
|
98
154
|
|
|
99
|
-
cachedLoginPath = null;
|
|
155
|
+
cachedLoginPath = { key: cacheKey, path: null };
|
|
100
156
|
return null;
|
|
101
157
|
}
|
|
102
158
|
|
|
@@ -3,7 +3,7 @@ import { AsyncLocalStorage } from 'node:async_hooks';
|
|
|
3
3
|
import { spawn } from 'node:child_process';
|
|
4
4
|
import { z } from 'zod/v3';
|
|
5
5
|
import DESCRIPTION from './shell.txt' with { type: 'text' };
|
|
6
|
-
import {
|
|
6
|
+
import { getShellExecutionConfig } from '../bin-manager.ts';
|
|
7
7
|
import { createToolError, type ToolResponse } from '../error.ts';
|
|
8
8
|
import { injectCoAuthorIntoGitCommit } from './git-identity.ts';
|
|
9
9
|
|
|
@@ -47,17 +47,6 @@ export type ShellOutputMode = 'auto' | 'full' | 'tail';
|
|
|
47
47
|
const DEFAULT_TAIL_LINES = 100;
|
|
48
48
|
const DEFAULT_MAX_OUTPUT_BYTES = 128_000;
|
|
49
49
|
|
|
50
|
-
function looksLikeRepositorySearchCommand(cmd: string): boolean {
|
|
51
|
-
const normalized = cmd.replace(/\s+/g, ' ').trim();
|
|
52
|
-
return (
|
|
53
|
-
/(^|[;&|()]\s*)(rg|ripgrep)(\s|$)/.test(normalized) ||
|
|
54
|
-
/(^|[;&|()]\s*)grep\s+.*\s(-R|-r|--recursive)(\s|$)/.test(normalized) ||
|
|
55
|
-
/(^|[;&|()]\s*)find\s+(\.|\.\/|\$PWD|\S*\/).*(-name|-iname|-path|-type)/.test(
|
|
56
|
-
normalized,
|
|
57
|
-
)
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
50
|
type CompactTextResult = {
|
|
62
51
|
text: string;
|
|
63
52
|
truncated: boolean;
|
|
@@ -147,7 +136,9 @@ const shellInputSchema = z
|
|
|
147
136
|
.object({
|
|
148
137
|
cmd: z
|
|
149
138
|
.string()
|
|
150
|
-
.describe(
|
|
139
|
+
.describe(
|
|
140
|
+
'Non-interactive shell command to run using the user shell with login/interactive startup loaded',
|
|
141
|
+
),
|
|
151
142
|
cwd: z
|
|
152
143
|
.string()
|
|
153
144
|
.default('.')
|
|
@@ -231,18 +222,6 @@ export function buildShellTool(projectRoot: string): {
|
|
|
231
222
|
});
|
|
232
223
|
}
|
|
233
224
|
|
|
234
|
-
if (looksLikeRepositorySearchCommand(cmd)) {
|
|
235
|
-
return createToolError(
|
|
236
|
-
'This looks like repository discovery. Use the search tool for content/code search or glob for filename/path discovery.',
|
|
237
|
-
'validation',
|
|
238
|
-
{
|
|
239
|
-
cmd,
|
|
240
|
-
suggestion:
|
|
241
|
-
'Use search for file contents, or glob for file and path discovery.',
|
|
242
|
-
},
|
|
243
|
-
);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
225
|
const absCwd = resolveSafePath(projectRoot, cwd || '.');
|
|
247
226
|
const finalCmd = injectCoAuthorIntoGitCommit(cmd);
|
|
248
227
|
const shellExecutor = shellExecutorContext.getStore();
|
|
@@ -261,11 +240,11 @@ export function buildShellTool(projectRoot: string): {
|
|
|
261
240
|
) as AsyncIterable<ShellStreamChunk> | ShellResult;
|
|
262
241
|
}
|
|
263
242
|
|
|
264
|
-
const
|
|
243
|
+
const shellConfig = getShellExecutionConfig(finalCmd);
|
|
244
|
+
const proc = spawn(shellConfig.command, shellConfig.args, {
|
|
265
245
|
cwd: absCwd,
|
|
266
|
-
shell: true,
|
|
267
246
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
268
|
-
env:
|
|
247
|
+
env: shellConfig.env,
|
|
269
248
|
detached: true,
|
|
270
249
|
});
|
|
271
250
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
- Execute a non-interactive shell command using
|
|
1
|
+
- Execute a non-interactive shell command using the user's shell with login/interactive startup loaded
|
|
2
2
|
- Returns `stdout`, `stderr`, and `exitCode`
|
|
3
3
|
- `cwd` is relative to the project root and sandboxed within it
|
|
4
4
|
|