@gagik.co/snippet-agent 0.1.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/.eslintrc.js +13 -0
- package/.prettierrc.json +1 -0
- package/README.md +23 -0
- package/dist/agent-class.d.ts +47 -0
- package/dist/agent-class.js +314 -0
- package/dist/agent.d.ts +1 -0
- package/dist/agent.js +392 -0
- package/dist/banner.d.ts +1 -0
- package/dist/banner.js +23 -0
- package/dist/confirmation-extension.d.ts +10 -0
- package/dist/confirmation-extension.js +213 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +141 -0
- package/dist/mongosh-interactive-mode.d.ts +33 -0
- package/dist/mongosh-interactive-mode.js +244 -0
- package/dist/project-agent.d.ts +1 -0
- package/dist/project-agent.js +36 -0
- package/dist/shell-context.d.ts +17 -0
- package/dist/shell-context.js +75 -0
- package/dist/skills-loader.d.ts +2 -0
- package/dist/skills-loader.js +69 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +8 -0
- package/dist/src/project-agent.d.ts +1 -0
- package/dist/src/project-agent.js +36 -0
- package/dist/stdout-patcher.d.ts +5 -0
- package/dist/stdout-patcher.js +41 -0
- package/dist/tools/index.d.ts +4 -0
- package/dist/tools/index.js +7 -0
- package/dist/tools/mongosh-eval.d.ts +7 -0
- package/dist/tools/mongosh-eval.js +84 -0
- package/dist/tools/search-docs.d.ts +2 -0
- package/dist/tools/search-docs.js +106 -0
- package/dist/tools/types.d.ts +12 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools.d.ts +7 -0
- package/dist/tools.js +189 -0
- package/dist/types.d.ts +21 -0
- package/dist/types.js +2 -0
- package/package.json +38 -0
- package/skills/mongodb-connection.md +208 -0
- package/skills/mongodb-natural-language-querying.md +202 -0
- package/skills/mongodb-query-optimizer.md +265 -0
- package/skills/mongodb-schema-design.md +455 -0
- package/skills/mongodb-search-and-ai.md +357 -0
- package/skills/mongosh-shell.md +227 -0
- package/src/agent-class.ts +393 -0
- package/src/banner.ts +36 -0
- package/src/confirmation-extension.ts +297 -0
- package/src/index.ts +137 -0
- package/src/mongosh-interactive-mode.ts +420 -0
- package/src/shell-context.ts +97 -0
- package/src/skills-loader.ts +37 -0
- package/src/stdout-patcher.ts +48 -0
- package/src/tools/index.ts +4 -0
- package/src/tools/mongosh-eval.ts +115 -0
- package/src/tools/search-docs.ts +115 -0
- package/src/tools/types.ts +15 -0
- package/src/types.ts +23 -0
- package/tsconfig-lint.json +4 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { inspect } from 'util';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { highlight } from 'cli-highlight';
|
|
4
|
+
|
|
5
|
+
type ConfirmationExtensionOptions = {
|
|
6
|
+
skipConfirmation?: boolean;
|
|
7
|
+
allowedTools?: string[];
|
|
8
|
+
blockedTools?: string[];
|
|
9
|
+
skipConfirmTools?: string[];
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
let globalOptions: ConfirmationExtensionOptions = {};
|
|
13
|
+
|
|
14
|
+
export function setConfirmationOptions(
|
|
15
|
+
options: ConfirmationExtensionOptions,
|
|
16
|
+
): void {
|
|
17
|
+
globalOptions = options;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function getConfirmationOptions(): ConfirmationExtensionOptions {
|
|
21
|
+
return globalOptions;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function formatToolName(toolName: string): string {
|
|
25
|
+
const displayName = toolName.replace(/_/g, ' ');
|
|
26
|
+
return chalk.white.bold(displayName);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function formatToolParams(
|
|
30
|
+
toolName: string,
|
|
31
|
+
input: Record<string, unknown>,
|
|
32
|
+
): string {
|
|
33
|
+
const lines: string[] = [];
|
|
34
|
+
for (const [key, value] of Object.entries(input)) {
|
|
35
|
+
const formatted =
|
|
36
|
+
typeof value === 'string'
|
|
37
|
+
? value
|
|
38
|
+
: inspect(value, { depth: 3, breakLength: 80 });
|
|
39
|
+
lines.push(` ${chalk.gray(key)}: ${formatted}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return lines.length > 0 ? '\n\n' + lines.join('\n') : '';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function stripAnsiCodes(str: string): string {
|
|
46
|
+
// eslint-disable-next-line no-control-regex
|
|
47
|
+
return str.replace(/\u001b\[[0-9;]*m/g, '');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function formatWithBackground(content: string): string {
|
|
51
|
+
// ANSI color codes - darker gray background (48;5;236) and reset
|
|
52
|
+
const BG_DARK_GRAY = '\u001b[48;5;236m';
|
|
53
|
+
const RESET = '\u001b[0m';
|
|
54
|
+
const PADDING = ' ';
|
|
55
|
+
|
|
56
|
+
// Always use maximum available terminal width (minus small margin)
|
|
57
|
+
const terminalWidth = process.stdout.columns || 80;
|
|
58
|
+
const boxWidth = Math.max(40, terminalWidth - 2);
|
|
59
|
+
const contentWidth = boxWidth - 4; // minus padding on both sides
|
|
60
|
+
|
|
61
|
+
// Split content and wrap long lines to fit the full width
|
|
62
|
+
const rawLines = content.split('\n');
|
|
63
|
+
|
|
64
|
+
const processedLines: string[] = [];
|
|
65
|
+
for (const line of rawLines) {
|
|
66
|
+
const visibleLen = stripAnsiCodes(line).length;
|
|
67
|
+
if (visibleLen > contentWidth) {
|
|
68
|
+
// Hard wrap: keep ANSI codes, split at visible character boundary
|
|
69
|
+
let currentLine = line;
|
|
70
|
+
let currentVisibleLen = visibleLen;
|
|
71
|
+
|
|
72
|
+
while (currentVisibleLen > contentWidth) {
|
|
73
|
+
// Map visible character position to actual string position (preserving ANSI codes)
|
|
74
|
+
let visibleCount = 0;
|
|
75
|
+
let actualIndex = 0;
|
|
76
|
+
for (
|
|
77
|
+
let i = 0;
|
|
78
|
+
i < currentLine.length && visibleCount < contentWidth;
|
|
79
|
+
i++
|
|
80
|
+
) {
|
|
81
|
+
if (currentLine[i] === '\u001b') {
|
|
82
|
+
// Skip ANSI sequence
|
|
83
|
+
while (i < currentLine.length && currentLine[i] !== 'm') {
|
|
84
|
+
i++;
|
|
85
|
+
}
|
|
86
|
+
} else {
|
|
87
|
+
visibleCount++;
|
|
88
|
+
}
|
|
89
|
+
actualIndex = i + 1;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
processedLines.push(currentLine.slice(0, actualIndex));
|
|
93
|
+
currentLine = currentLine.slice(actualIndex);
|
|
94
|
+
currentVisibleLen = stripAnsiCodes(currentLine).length;
|
|
95
|
+
}
|
|
96
|
+
if (currentLine.length > 0) {
|
|
97
|
+
processedLines.push(currentLine);
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
processedLines.push(line);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Build lines with dark gray background extending to full box width
|
|
105
|
+
const formattedLines = processedLines.map((line) => {
|
|
106
|
+
const visibleLen = stripAnsiCodes(line).length;
|
|
107
|
+
const pad = ' '.repeat(Math.max(0, contentWidth - visibleLen));
|
|
108
|
+
return `${BG_DARK_GRAY}${PADDING}${line}${pad}${PADDING}${RESET}`;
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// Add empty padding lines with same full-width background
|
|
112
|
+
const emptyLine = `${BG_DARK_GRAY}${' '.repeat(boxWidth)}${RESET}`;
|
|
113
|
+
|
|
114
|
+
return [emptyLine, ...formattedLines, emptyLine].join('\n');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function formatConfirmationMessage(
|
|
118
|
+
toolName: string,
|
|
119
|
+
input: Record<string, unknown>,
|
|
120
|
+
): { title: string; message: string } {
|
|
121
|
+
if (toolName === 'mongosh_eval') {
|
|
122
|
+
const expression = input.expression as string | undefined;
|
|
123
|
+
if (expression) {
|
|
124
|
+
const highlighted = highlight(expression, {
|
|
125
|
+
language: 'javascript',
|
|
126
|
+
theme: {
|
|
127
|
+
keyword: chalk.magenta,
|
|
128
|
+
function: chalk.cyan,
|
|
129
|
+
string: chalk.green,
|
|
130
|
+
number: chalk.yellow,
|
|
131
|
+
comment: chalk.gray,
|
|
132
|
+
operator: chalk.white,
|
|
133
|
+
punctuation: chalk.white,
|
|
134
|
+
literal: chalk.yellow,
|
|
135
|
+
params: chalk.white,
|
|
136
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
137
|
+
} as any,
|
|
138
|
+
});
|
|
139
|
+
return {
|
|
140
|
+
title: `Run this mongosh script? ${chalk.gray('(please review the code above)')}`,
|
|
141
|
+
message: '\n' + formatWithBackground(highlighted),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const nameLine = formatToolName(toolName);
|
|
147
|
+
const paramsSection = formatToolParams(toolName, input);
|
|
148
|
+
return {
|
|
149
|
+
title: 'Tool Call Confirmation',
|
|
150
|
+
message: nameLine + paramsSection,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
155
|
+
export default function createConfirmationExtension(pi: any): void {
|
|
156
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
157
|
+
pi.on(
|
|
158
|
+
'tool_call',
|
|
159
|
+
async (
|
|
160
|
+
event: {
|
|
161
|
+
type: 'tool_call';
|
|
162
|
+
toolCallId: string;
|
|
163
|
+
toolName: string;
|
|
164
|
+
input: Record<string, unknown>;
|
|
165
|
+
},
|
|
166
|
+
ctx: {
|
|
167
|
+
ui: {
|
|
168
|
+
confirm: (title: string, message: string) => Promise<boolean>;
|
|
169
|
+
notify: (message: string, type: 'info' | 'warning' | 'error') => void;
|
|
170
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
171
|
+
custom: <T>(
|
|
172
|
+
factory: (
|
|
173
|
+
tui: any,
|
|
174
|
+
theme: any,
|
|
175
|
+
keybindings: any,
|
|
176
|
+
done: (result: T) => void,
|
|
177
|
+
) => {
|
|
178
|
+
render: () => string[];
|
|
179
|
+
invalidate: () => void;
|
|
180
|
+
handleInput?: (keyData: string) => void;
|
|
181
|
+
},
|
|
182
|
+
options?: {
|
|
183
|
+
overlay?: boolean;
|
|
184
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
185
|
+
overlayOptions?: any;
|
|
186
|
+
},
|
|
187
|
+
) => Promise<T>;
|
|
188
|
+
setWidget: (
|
|
189
|
+
key: string,
|
|
190
|
+
content:
|
|
191
|
+
| string[]
|
|
192
|
+
| ((
|
|
193
|
+
tui: unknown,
|
|
194
|
+
theme: unknown,
|
|
195
|
+
) => {
|
|
196
|
+
render: (width: number) => string[];
|
|
197
|
+
invalidate: () => void;
|
|
198
|
+
})
|
|
199
|
+
| undefined,
|
|
200
|
+
options?: { position?: 'above' | 'below' },
|
|
201
|
+
) => void;
|
|
202
|
+
};
|
|
203
|
+
},
|
|
204
|
+
) => {
|
|
205
|
+
const { toolName, input } = event;
|
|
206
|
+
const options = getConfirmationOptions();
|
|
207
|
+
|
|
208
|
+
if (options.skipConfirmation) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (options.allowedTools && !options.allowedTools.includes(toolName)) {
|
|
213
|
+
return {
|
|
214
|
+
block: true,
|
|
215
|
+
reason: `Tool "${toolName}" is not in the allowed tools list.`,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (options.blockedTools?.includes(toolName)) {
|
|
220
|
+
return {
|
|
221
|
+
block: true,
|
|
222
|
+
reason: `Tool "${toolName}" is blocked by policy.`,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Skip confirmation for whitelisted tools
|
|
227
|
+
if (options.skipConfirmTools?.includes(toolName)) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const { title, message } = formatConfirmationMessage(toolName, input);
|
|
232
|
+
|
|
233
|
+
// Show code in chat history (static, scrollable)
|
|
234
|
+
ctx.ui.notify(message, 'info');
|
|
235
|
+
|
|
236
|
+
// Custom minimal confirm dialog using Pi SDK's custom() API with done callback
|
|
237
|
+
const confirmed = await ctx.ui.custom(
|
|
238
|
+
(_tui, _theme, _keybindings, done) => {
|
|
239
|
+
let selectedIndex = 0;
|
|
240
|
+
const opts = ['Yes', 'No'];
|
|
241
|
+
|
|
242
|
+
return {
|
|
243
|
+
render: () => {
|
|
244
|
+
const lines: string[] = [];
|
|
245
|
+
// Title at the top of the dialog
|
|
246
|
+
lines.push(chalk.white.bold(title));
|
|
247
|
+
// Yes/No options
|
|
248
|
+
for (let i = 0; i < opts.length; i++) {
|
|
249
|
+
const isSelected = i === selectedIndex;
|
|
250
|
+
const line = isSelected
|
|
251
|
+
? `${chalk.cyan('→')} ${chalk.cyan.bold(opts[i])}`
|
|
252
|
+
: ` ${chalk.gray(opts[i])}`;
|
|
253
|
+
lines.push(line);
|
|
254
|
+
}
|
|
255
|
+
return lines;
|
|
256
|
+
},
|
|
257
|
+
invalidate: () => {},
|
|
258
|
+
handleInput: (keyData: string) => {
|
|
259
|
+
// Up/Down to navigate
|
|
260
|
+
if (keyData === '\u001b[A') {
|
|
261
|
+
// Up arrow
|
|
262
|
+
selectedIndex = Math.max(0, selectedIndex - 1);
|
|
263
|
+
} else if (keyData === '\u001b[B') {
|
|
264
|
+
// Down arrow
|
|
265
|
+
selectedIndex = Math.min(opts.length - 1, selectedIndex + 1);
|
|
266
|
+
} else if (keyData === '\r' || keyData === '\n') {
|
|
267
|
+
// Enter to confirm
|
|
268
|
+
done(selectedIndex === 0); // Yes = index 0
|
|
269
|
+
} else if (keyData === '\x03' || keyData === '\u001b') {
|
|
270
|
+
// Ctrl+C or Escape to cancel
|
|
271
|
+
done(false);
|
|
272
|
+
} else if (keyData.toLowerCase() === 'y') {
|
|
273
|
+
done(true);
|
|
274
|
+
} else if (keyData.toLowerCase() === 'n') {
|
|
275
|
+
done(false);
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
};
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
overlay: true,
|
|
282
|
+
overlayOptions: {
|
|
283
|
+
anchor: 'bottom-center',
|
|
284
|
+
offsetY: -4, // Move up above the input field
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
if (!confirmed) {
|
|
290
|
+
return {
|
|
291
|
+
block: true,
|
|
292
|
+
reason: `Tool "${toolName}" was cancelled by user.`,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
},
|
|
296
|
+
);
|
|
297
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import * as path from 'path';
|
|
2
|
+
import type { CliContext } from './types';
|
|
3
|
+
import { loadSkillsFromDir } from './skills-loader';
|
|
4
|
+
import { createShellContext } from './shell-context';
|
|
5
|
+
import { createMongoshEvalTool, createSearchDocsTool } from './tools';
|
|
6
|
+
import { createStdoutPatcher } from './stdout-patcher';
|
|
7
|
+
import { setConfirmationOptions } from './confirmation-extension';
|
|
8
|
+
import { Agent } from './agent-class';
|
|
9
|
+
|
|
10
|
+
function setupDebugLogging(): boolean {
|
|
11
|
+
// Ensure telemetry is disabled from pi-coding-agent
|
|
12
|
+
// This is a safeguard in addition to the settings manager configuration
|
|
13
|
+
process.env.PI_TELEMETRY = 'false';
|
|
14
|
+
|
|
15
|
+
const debugLogging = process.env.DEBUG_AGENT === '1';
|
|
16
|
+
const logRequests = process.env.DEBUG_AGENT_REQUESTS === '1';
|
|
17
|
+
|
|
18
|
+
if (debugLogging) {
|
|
19
|
+
process.stderr.write(`[agent] DEBUG_AGENT_REQUESTS=${process.env.DEBUG_AGENT_REQUESTS ?? 'undefined'}\n`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (logRequests) {
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
24
|
+
const originalFetch = (globalThis as any).fetch;
|
|
25
|
+
if (originalFetch) {
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
|
+
(globalThis as any).fetch = async (input: any, init?: any) => {
|
|
28
|
+
const url = typeof input === 'string' ? input : input.toString();
|
|
29
|
+
const method = init?.method || 'GET';
|
|
30
|
+
process.stderr.write(`[agent:fetch] ${String(method)} ${String(url)}\n`);
|
|
31
|
+
const start = Date.now();
|
|
32
|
+
try {
|
|
33
|
+
const response = await originalFetch(input, init);
|
|
34
|
+
process.stderr.write(`[agent:fetch] Response: ${String(response.status)} (${String(Date.now() - start)}ms)\n`);
|
|
35
|
+
return response;
|
|
36
|
+
} catch (err) {
|
|
37
|
+
process.stderr.write(`[agent:fetch] Error: ${String(err)}\n`);
|
|
38
|
+
throw err;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return debugLogging;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function loadServices() {
|
|
48
|
+
const {
|
|
49
|
+
createAgentSessionRuntime,
|
|
50
|
+
createAgentSessionServices,
|
|
51
|
+
createAgentSessionFromServices,
|
|
52
|
+
SessionManager,
|
|
53
|
+
InteractiveMode,
|
|
54
|
+
SettingsManager,
|
|
55
|
+
getAgentDir,
|
|
56
|
+
initTheme,
|
|
57
|
+
AuthStorage,
|
|
58
|
+
ModelRegistry,
|
|
59
|
+
} = await import('@earendil-works/pi-coding-agent');
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
createAgentSessionRuntime,
|
|
63
|
+
createAgentSessionServices,
|
|
64
|
+
createAgentSessionFromServices,
|
|
65
|
+
SessionManager,
|
|
66
|
+
InteractiveMode,
|
|
67
|
+
SettingsManager,
|
|
68
|
+
getAgentDir,
|
|
69
|
+
initTheme,
|
|
70
|
+
AuthStorage,
|
|
71
|
+
ModelRegistry,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export = async (mongoshContext: CliContext) => {
|
|
76
|
+
const debugLogging = setupDebugLogging();
|
|
77
|
+
|
|
78
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
79
|
+
const shellContext = mongoshContext as any;
|
|
80
|
+
|
|
81
|
+
const skillsDir = path.join(__dirname, '..', 'skills');
|
|
82
|
+
const loadedSkills = loadSkillsFromDir(skillsDir);
|
|
83
|
+
|
|
84
|
+
const shellCtx = createShellContext({ shellContext });
|
|
85
|
+
const mongoshEvalTool = await createMongoshEvalTool({ shellContext: shellCtx, debugLogging });
|
|
86
|
+
const searchDocsTool = await createSearchDocsTool();
|
|
87
|
+
const stdoutPatcher = createStdoutPatcher();
|
|
88
|
+
|
|
89
|
+
const services = await loadServices();
|
|
90
|
+
|
|
91
|
+
// Initialize theme after loading services
|
|
92
|
+
services.initTheme('dark', false);
|
|
93
|
+
|
|
94
|
+
// Whitelist search_docs tool to run without confirmation
|
|
95
|
+
setConfirmationOptions({
|
|
96
|
+
skipConfirmTools: ['search_docs'],
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const agent = new Agent({
|
|
100
|
+
services,
|
|
101
|
+
mongoshEvalTool,
|
|
102
|
+
searchDocsTool,
|
|
103
|
+
loadedSkills,
|
|
104
|
+
skillsDir,
|
|
105
|
+
debugLogging,
|
|
106
|
+
stdoutPatcher,
|
|
107
|
+
shellContext: shellCtx,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const agentFn = async () => {
|
|
111
|
+
await agent.run();
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
115
|
+
(agentFn as any).isDirectShellCommand = true;
|
|
116
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
117
|
+
(agentFn as any).returnsPromise = true;
|
|
118
|
+
|
|
119
|
+
// Add resume method - callable as agent.resume <sessionId>
|
|
120
|
+
const resumeFn = async (sessionId: string) => {
|
|
121
|
+
if (!sessionId) {
|
|
122
|
+
process.stderr.write('Usage: agent.resume <session-id>\n');
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
await agent.resume(sessionId);
|
|
126
|
+
};
|
|
127
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
128
|
+
(resumeFn as any).isDirectShellCommand = true;
|
|
129
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
130
|
+
(resumeFn as any).returnsPromise = true;
|
|
131
|
+
|
|
132
|
+
// Register agent and agent.resume
|
|
133
|
+
shellCtx.instanceState.shellApi['agent'] = agentFn;
|
|
134
|
+
shellCtx.instanceState.context['agent'] = agentFn;
|
|
135
|
+
shellCtx.instanceState.shellApi['agent.resume'] = resumeFn;
|
|
136
|
+
shellCtx.instanceState.context['agent.resume'] = resumeFn;
|
|
137
|
+
};
|