@ottocode/sdk 0.1.293 → 0.1.295

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.293",
3
+ "version": "0.1.295",
4
4
  "description": "AI agent SDK for building intelligent assistants - tree-shakable and comprehensive",
5
5
  "author": "nitishxyz",
6
6
  "license": "MIT",
@@ -42,10 +42,30 @@ function killProcessTree(pid: number) {
42
42
  }
43
43
  }
44
44
 
45
+ export type ShellOutputMode = 'full' | 'tail';
46
+
47
+ const DEFAULT_TAIL_LINES = 100;
48
+
49
+ export function appendTailLines(
50
+ current: string,
51
+ text: string,
52
+ tailLines: number,
53
+ ): string {
54
+ if (!text) return current;
55
+ const linesToKeep = Math.max(1, Math.floor(tailLines));
56
+ const combined = `${current}${text}`;
57
+ const lines = combined.split('\n');
58
+ const entriesToKeep = combined.endsWith('\n') ? linesToKeep + 1 : linesToKeep;
59
+ if (lines.length <= entriesToKeep) return combined;
60
+ return lines.slice(-entriesToKeep).join('\n');
61
+ }
62
+
45
63
  type ShellResult = ToolResponse<{
46
64
  exitCode: number;
47
65
  stdout: string;
48
66
  stderr: string;
67
+ outputMode?: ShellOutputMode;
68
+ tailLines?: number;
49
69
  }>;
50
70
 
51
71
  type ShellStreamChunk =
@@ -89,6 +109,23 @@ const shellInputSchema = z
89
109
  .optional()
90
110
  .default(300000)
91
111
  .describe('Timeout in milliseconds (default: 300000 = 5 minutes)'),
112
+ outputMode: z
113
+ .enum(['full', 'tail'])
114
+ .optional()
115
+ .default('full')
116
+ .describe(
117
+ 'Output capture mode. Use "full" for complete stdout/stderr, or "tail" to keep only the last tailLines lines and avoid huge tool results.',
118
+ ),
119
+ tailLines: z
120
+ .number()
121
+ .int()
122
+ .min(1)
123
+ .max(5000)
124
+ .optional()
125
+ .default(DEFAULT_TAIL_LINES)
126
+ .describe(
127
+ 'Number of trailing stdout/stderr lines to keep when outputMode is "tail"',
128
+ ),
92
129
  })
93
130
  .strict();
94
131
 
@@ -112,7 +149,14 @@ export function buildShellTool(projectRoot: string): {
112
149
  description: DESCRIPTION,
113
150
  inputSchema: shellInputSchema,
114
151
  execute(
115
- { cmd, cwd, allowNonZeroExit, timeout = 300000 }: ShellInput,
152
+ {
153
+ cmd,
154
+ cwd,
155
+ allowNonZeroExit,
156
+ timeout = 300000,
157
+ outputMode = 'full',
158
+ tailLines = DEFAULT_TAIL_LINES,
159
+ }: ShellInput,
116
160
  options?: { abortSignal?: AbortSignal },
117
161
  ): AsyncIterable<ShellStreamChunk> | ShellResult {
118
162
  const abortSignal = options?.abortSignal;
@@ -128,7 +172,14 @@ export function buildShellTool(projectRoot: string): {
128
172
  const shellExecutor = shellExecutorContext.getStore();
129
173
  if (shellExecutor) {
130
174
  return shellExecutor(
131
- { cmd: finalCmd, cwd: absCwd, allowNonZeroExit, timeout },
175
+ {
176
+ cmd: finalCmd,
177
+ cwd: absCwd,
178
+ allowNonZeroExit,
179
+ timeout,
180
+ outputMode,
181
+ tailLines,
182
+ },
132
183
  options,
133
184
  ) as AsyncIterable<ShellStreamChunk> | ShellResult;
134
185
  }
@@ -196,13 +247,19 @@ export function buildShellTool(projectRoot: string): {
196
247
 
197
248
  proc.stdout?.on('data', (chunk) => {
198
249
  const text = chunk.toString();
199
- stdout += text;
250
+ stdout =
251
+ outputMode === 'tail'
252
+ ? appendTailLines(stdout, text, tailLines)
253
+ : `${stdout}${text}`;
200
254
  pushDelta(text);
201
255
  });
202
256
 
203
257
  proc.stderr?.on('data', (chunk) => {
204
258
  const text = chunk.toString();
205
- stderr += text;
259
+ stderr =
260
+ outputMode === 'tail'
261
+ ? appendTailLines(stderr, text, tailLines)
262
+ : `${stderr}${text}`;
206
263
  pushDelta(text);
207
264
  });
208
265
 
@@ -213,6 +270,7 @@ export function buildShellTool(projectRoot: string): {
213
270
  cmd,
214
271
  stdout,
215
272
  stderr,
273
+ ...(outputMode === 'tail' ? { outputMode, tailLines } : {}),
216
274
  }),
217
275
  );
218
276
  return;
@@ -228,6 +286,7 @@ export function buildShellTool(projectRoot: string): {
228
286
  value: timeout,
229
287
  stdout,
230
288
  stderr,
289
+ ...(outputMode === 'tail' ? { outputMode, tailLines } : {}),
231
290
  suggestion: 'Increase timeout or optimize the command',
232
291
  },
233
292
  ),
@@ -244,6 +303,7 @@ export function buildShellTool(projectRoot: string): {
244
303
  stdout,
245
304
  stderr,
246
305
  cmd,
306
+ ...(outputMode === 'tail' ? { outputMode, tailLines } : {}),
247
307
  suggestion: 'Check command syntax or use allowNonZeroExit: true',
248
308
  }),
249
309
  );
@@ -255,6 +315,7 @@ export function buildShellTool(projectRoot: string): {
255
315
  exitCode: exitCode ?? 0,
256
316
  stdout,
257
317
  stderr,
318
+ ...(outputMode === 'tail' ? { outputMode, tailLines } : {}),
258
319
  });
259
320
  });
260
321
 
@@ -8,6 +8,7 @@
8
8
 
9
9
  - Chain commands with `&&` to fail-fast.
10
10
  - For long outputs, redirect to a file and `read` it back.
11
+ - For verbose commands like builds or tests, set `outputMode: "tail"` and optionally `tailLines` to return only the last N stdout/stderr lines in the final tool result while still streaming full output to the UI. Use `outputMode: "full"` when you need complete output in the result.
11
12
  - For long-running non-interactive commands, set an appropriate `timeout` and ensure the command exits on its own.
12
13
  - Batch independent checks (e.g. `git status && git diff`) in parallel tool calls rather than sequential shell chains when you need results separately.
13
14
  - Never use `shell` with `sed`/`awk` for programmatic file editing — use the dedicated file-editing tools instead.