@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.
Files changed (61) hide show
  1. package/.eslintrc.js +13 -0
  2. package/.prettierrc.json +1 -0
  3. package/README.md +23 -0
  4. package/dist/agent-class.d.ts +47 -0
  5. package/dist/agent-class.js +314 -0
  6. package/dist/agent.d.ts +1 -0
  7. package/dist/agent.js +392 -0
  8. package/dist/banner.d.ts +1 -0
  9. package/dist/banner.js +23 -0
  10. package/dist/confirmation-extension.d.ts +10 -0
  11. package/dist/confirmation-extension.js +213 -0
  12. package/dist/index.d.ts +3 -0
  13. package/dist/index.js +141 -0
  14. package/dist/mongosh-interactive-mode.d.ts +33 -0
  15. package/dist/mongosh-interactive-mode.js +244 -0
  16. package/dist/project-agent.d.ts +1 -0
  17. package/dist/project-agent.js +36 -0
  18. package/dist/shell-context.d.ts +17 -0
  19. package/dist/shell-context.js +75 -0
  20. package/dist/skills-loader.d.ts +2 -0
  21. package/dist/skills-loader.js +69 -0
  22. package/dist/src/index.d.ts +1 -0
  23. package/dist/src/index.js +8 -0
  24. package/dist/src/project-agent.d.ts +1 -0
  25. package/dist/src/project-agent.js +36 -0
  26. package/dist/stdout-patcher.d.ts +5 -0
  27. package/dist/stdout-patcher.js +41 -0
  28. package/dist/tools/index.d.ts +4 -0
  29. package/dist/tools/index.js +7 -0
  30. package/dist/tools/mongosh-eval.d.ts +7 -0
  31. package/dist/tools/mongosh-eval.js +84 -0
  32. package/dist/tools/search-docs.d.ts +2 -0
  33. package/dist/tools/search-docs.js +106 -0
  34. package/dist/tools/types.d.ts +12 -0
  35. package/dist/tools/types.js +2 -0
  36. package/dist/tools.d.ts +7 -0
  37. package/dist/tools.js +189 -0
  38. package/dist/types.d.ts +21 -0
  39. package/dist/types.js +2 -0
  40. package/package.json +38 -0
  41. package/skills/mongodb-connection.md +208 -0
  42. package/skills/mongodb-natural-language-querying.md +202 -0
  43. package/skills/mongodb-query-optimizer.md +265 -0
  44. package/skills/mongodb-schema-design.md +455 -0
  45. package/skills/mongodb-search-and-ai.md +357 -0
  46. package/skills/mongosh-shell.md +227 -0
  47. package/src/agent-class.ts +393 -0
  48. package/src/banner.ts +36 -0
  49. package/src/confirmation-extension.ts +297 -0
  50. package/src/index.ts +137 -0
  51. package/src/mongosh-interactive-mode.ts +420 -0
  52. package/src/shell-context.ts +97 -0
  53. package/src/skills-loader.ts +37 -0
  54. package/src/stdout-patcher.ts +48 -0
  55. package/src/tools/index.ts +4 -0
  56. package/src/tools/mongosh-eval.ts +115 -0
  57. package/src/tools/search-docs.ts +115 -0
  58. package/src/tools/types.ts +15 -0
  59. package/src/types.ts +23 -0
  60. package/tsconfig-lint.json +4 -0
  61. package/tsconfig.json +20 -0
package/dist/index.js ADDED
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ const path = __importStar(require("path"));
36
+ const skills_loader_1 = require("./skills-loader");
37
+ const shell_context_1 = require("./shell-context");
38
+ const tools_1 = require("./tools");
39
+ const stdout_patcher_1 = require("./stdout-patcher");
40
+ const confirmation_extension_1 = require("./confirmation-extension");
41
+ const agent_class_1 = require("./agent-class");
42
+ function setupDebugLogging() {
43
+ // Ensure telemetry is disabled from pi-coding-agent
44
+ // This is a safeguard in addition to the settings manager configuration
45
+ process.env.PI_TELEMETRY = 'false';
46
+ const debugLogging = process.env.DEBUG_AGENT === '1';
47
+ const logRequests = process.env.DEBUG_AGENT_REQUESTS === '1';
48
+ if (debugLogging) {
49
+ process.stderr.write(`[agent] DEBUG_AGENT_REQUESTS=${process.env.DEBUG_AGENT_REQUESTS ?? 'undefined'}\n`);
50
+ }
51
+ if (logRequests) {
52
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
53
+ const originalFetch = globalThis.fetch;
54
+ if (originalFetch) {
55
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
56
+ globalThis.fetch = async (input, init) => {
57
+ const url = typeof input === 'string' ? input : input.toString();
58
+ const method = init?.method || 'GET';
59
+ process.stderr.write(`[agent:fetch] ${String(method)} ${String(url)}\n`);
60
+ const start = Date.now();
61
+ try {
62
+ const response = await originalFetch(input, init);
63
+ process.stderr.write(`[agent:fetch] Response: ${String(response.status)} (${String(Date.now() - start)}ms)\n`);
64
+ return response;
65
+ }
66
+ catch (err) {
67
+ process.stderr.write(`[agent:fetch] Error: ${String(err)}\n`);
68
+ throw err;
69
+ }
70
+ };
71
+ }
72
+ }
73
+ return debugLogging;
74
+ }
75
+ async function loadServices() {
76
+ const { createAgentSessionRuntime, createAgentSessionServices, createAgentSessionFromServices, SessionManager, InteractiveMode, SettingsManager, getAgentDir, initTheme, AuthStorage, ModelRegistry, } = await import('@earendil-works/pi-coding-agent');
77
+ return {
78
+ createAgentSessionRuntime,
79
+ createAgentSessionServices,
80
+ createAgentSessionFromServices,
81
+ SessionManager,
82
+ InteractiveMode,
83
+ SettingsManager,
84
+ getAgentDir,
85
+ initTheme,
86
+ AuthStorage,
87
+ ModelRegistry,
88
+ };
89
+ }
90
+ module.exports = async (mongoshContext) => {
91
+ const debugLogging = setupDebugLogging();
92
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
93
+ const shellContext = mongoshContext;
94
+ const skillsDir = path.join(__dirname, '..', 'skills');
95
+ const loadedSkills = (0, skills_loader_1.loadSkillsFromDir)(skillsDir);
96
+ const shellCtx = (0, shell_context_1.createShellContext)({ shellContext });
97
+ const mongoshEvalTool = await (0, tools_1.createMongoshEvalTool)({ shellContext: shellCtx, debugLogging });
98
+ const searchDocsTool = await (0, tools_1.createSearchDocsTool)();
99
+ const stdoutPatcher = (0, stdout_patcher_1.createStdoutPatcher)();
100
+ const services = await loadServices();
101
+ // Initialize theme after loading services
102
+ services.initTheme('dark', false);
103
+ // Whitelist search_docs tool to run without confirmation
104
+ (0, confirmation_extension_1.setConfirmationOptions)({
105
+ skipConfirmTools: ['search_docs'],
106
+ });
107
+ const agent = new agent_class_1.Agent({
108
+ services,
109
+ mongoshEvalTool,
110
+ searchDocsTool,
111
+ loadedSkills,
112
+ skillsDir,
113
+ debugLogging,
114
+ stdoutPatcher,
115
+ shellContext: shellCtx,
116
+ });
117
+ const agentFn = async () => {
118
+ await agent.run();
119
+ };
120
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
121
+ agentFn.isDirectShellCommand = true;
122
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
123
+ agentFn.returnsPromise = true;
124
+ // Add resume method - callable as agent.resume <sessionId>
125
+ const resumeFn = async (sessionId) => {
126
+ if (!sessionId) {
127
+ process.stderr.write('Usage: agent.resume <session-id>\n');
128
+ return;
129
+ }
130
+ await agent.resume(sessionId);
131
+ };
132
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
133
+ resumeFn.isDirectShellCommand = true;
134
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
135
+ resumeFn.returnsPromise = true;
136
+ // Register agent and agent.resume
137
+ shellCtx.instanceState.shellApi['agent'] = agentFn;
138
+ shellCtx.instanceState.context['agent'] = agentFn;
139
+ shellCtx.instanceState.shellApi['agent.resume'] = resumeFn;
140
+ shellCtx.instanceState.context['agent.resume'] = resumeFn;
141
+ };
@@ -0,0 +1,33 @@
1
+ import type { ShellContext } from './shell-context';
2
+ import type { InteractiveModeOptions } from '@earendil-works/pi-coding-agent';
3
+ import type { AgentSessionRuntime } from '@earendil-works/pi-coding-agent';
4
+ type MongoshEvalFunction = (expression: string) => Promise<{
5
+ output: string;
6
+ error?: string;
7
+ }>;
8
+ type MongoshInteractiveModeOptions = InteractiveModeOptions & {
9
+ shellContext: ShellContext;
10
+ mongoshEval: MongoshEvalFunction;
11
+ debugLogging?: boolean;
12
+ InteractiveMode: any;
13
+ };
14
+ export declare class MongoshInteractiveMode {
15
+ private baseMode;
16
+ private shellContext;
17
+ private mongoshEval;
18
+ private debugLogging;
19
+ private mongoshComponent?;
20
+ private pendingMongoshComponents;
21
+ private originalOnSubmit?;
22
+ private originalBorderColor?;
23
+ constructor(runtimeHost: AgentSessionRuntime, options: MongoshInteractiveModeOptions);
24
+ init(): Promise<void>;
25
+ private overrideOnSubmit;
26
+ private updateMongoshModeIndicator;
27
+ private handleMongoshCommand;
28
+ run(): Promise<void>;
29
+ stop(): void;
30
+ showError(message: string): void;
31
+ showWarning(message: string): void;
32
+ }
33
+ export {};
@@ -0,0 +1,244 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MongoshInteractiveMode = void 0;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const pi_tui_1 = require("@earendil-works/pi-tui");
9
+ // Mongosh execution component for UI rendering
10
+ class MongoshExecutionComponent {
11
+ constructor(command, ui, excludeFromContext) {
12
+ this.output = [];
13
+ this.isComplete = false;
14
+ this.cancelled = false;
15
+ this.command = command;
16
+ this.ui = ui;
17
+ this.excludeFromContext = excludeFromContext;
18
+ }
19
+ appendOutput(chunk) {
20
+ this.output.push(chunk);
21
+ this.ui.requestRender();
22
+ }
23
+ setComplete(exitCode, cancelled = false) {
24
+ this.isComplete = true;
25
+ this.exitCode = exitCode;
26
+ this.cancelled = cancelled;
27
+ this.ui.requestRender();
28
+ }
29
+ render(width) {
30
+ const lines = [];
31
+ const prefix = this.excludeFromContext ? '$$' : '$';
32
+ // Simple syntax highlighting with chalk - just show the command
33
+ // Full highlighting is done via the confirmation extension for tool calls
34
+ const header = `${chalk_1.default.gray(prefix)} ${chalk_1.default.cyan(this.command)}`;
35
+ lines.push((0, pi_tui_1.truncateToWidth)(header, width));
36
+ if (this.output.length > 0) {
37
+ const outputText = this.output.join('');
38
+ const outputLines = outputText.split('\n');
39
+ const prefixStr = chalk_1.default.gray('│ ');
40
+ const prefixWidth = 2; // '│ ' is 2 visible characters
41
+ for (const line of outputLines.slice(0, 100)) {
42
+ const availableWidth = Math.max(0, width - prefixWidth);
43
+ lines.push(prefixStr + (0, pi_tui_1.truncateToWidth)(line, availableWidth));
44
+ }
45
+ if (outputLines.length > 100) {
46
+ lines.push(chalk_1.default.gray(`... ${outputLines.length - 100} more lines`));
47
+ }
48
+ }
49
+ if (this.isComplete) {
50
+ if (this.cancelled) {
51
+ lines.push(chalk_1.default.yellow('◼ cancelled'));
52
+ }
53
+ else if (this.exitCode !== undefined && this.exitCode !== 0) {
54
+ lines.push(chalk_1.default.red(`✗ exit ${this.exitCode}`));
55
+ }
56
+ else {
57
+ lines.push(chalk_1.default.green('✓ done'));
58
+ }
59
+ }
60
+ else {
61
+ lines.push(chalk_1.default.cyan('◌ running...'));
62
+ }
63
+ return lines;
64
+ }
65
+ invalidate() {
66
+ this.ui.requestRender();
67
+ }
68
+ }
69
+ // Wrapper class that adds mongosh mode to InteractiveMode
70
+ class MongoshInteractiveMode {
71
+ constructor(runtimeHost, options) {
72
+ this.pendingMongoshComponents = [];
73
+ // Store our custom options
74
+ this.shellContext = options.shellContext;
75
+ this.mongoshEval = options.mongoshEval;
76
+ this.debugLogging = options.debugLogging ?? false;
77
+ // Create the base InteractiveMode using the passed class
78
+ const baseOptions = {
79
+ migratedProviders: options.migratedProviders,
80
+ modelFallbackMessage: options.modelFallbackMessage,
81
+ initialMessage: options.initialMessage,
82
+ initialImages: options.initialImages,
83
+ initialMessages: options.initialMessages,
84
+ verbose: options.verbose,
85
+ };
86
+ this.baseMode = new options.InteractiveMode(runtimeHost, baseOptions);
87
+ }
88
+ async init() {
89
+ await this.baseMode.init();
90
+ // Now that init is done, we can override the onSubmit handler
91
+ this.overrideOnSubmit();
92
+ }
93
+ overrideOnSubmit() {
94
+ // Store the original onSubmit from the default editor
95
+ this.originalOnSubmit = this.baseMode.defaultEditor.onSubmit;
96
+ // Store the original onChange if it exists
97
+ const originalOnChange = this.baseMode.defaultEditor.onChange;
98
+ if (this.debugLogging) {
99
+ process.stderr.write('[mongosh mode] overrideOnSubmit called\n');
100
+ }
101
+ // Create our wrapper onChange that detects $ prefix for visual feedback
102
+ const wrappedOnChange = (text) => {
103
+ // Check if we're in mongosh mode (starts with $)
104
+ const wasMongoshMode = this.baseMode.isMongoshMode;
105
+ const isMongoshMode = text.startsWith('$');
106
+ // Update the mode flag
107
+ this.baseMode.isMongoshMode = isMongoshMode;
108
+ // Update indicator if mode changed
109
+ if (wasMongoshMode !== isMongoshMode) {
110
+ this.updateMongoshModeIndicator();
111
+ }
112
+ // Call original onChange if it exists
113
+ if (originalOnChange) {
114
+ originalOnChange(text);
115
+ }
116
+ };
117
+ // Create our wrapper onSubmit that checks for $ prefix
118
+ const wrappedOnSubmit = async (text) => {
119
+ if (this.debugLogging) {
120
+ process.stderr.write(`[mongosh mode] wrappedOnSubmit called with: "${text.substring(0, 50)}..."\n`);
121
+ }
122
+ // Reset mongosh mode flag
123
+ this.baseMode.isMongoshMode = false;
124
+ this.updateMongoshModeIndicator();
125
+ // Handle mongosh command ($ for normal, $$ for excluded from context)
126
+ if (text.startsWith('$')) {
127
+ if (this.debugLogging) {
128
+ process.stderr.write('[mongosh mode] Detected $ prefix\n');
129
+ }
130
+ const isExcluded = text.startsWith('$$');
131
+ const command = isExcluded
132
+ ? text.slice(2).trim()
133
+ : text.slice(1).trim();
134
+ if (command) {
135
+ // Add to history
136
+ this.baseMode.editor.addToHistory?.(text);
137
+ // Handle the mongosh command
138
+ await this.handleMongoshCommand(command, isExcluded);
139
+ return;
140
+ }
141
+ }
142
+ // Not a mongosh command - call the original handler
143
+ // We need to call the original onSubmit which handles ! for bash and normal messages
144
+ if (this.originalOnSubmit) {
145
+ await this.originalOnSubmit(text);
146
+ }
147
+ };
148
+ // Apply the wrapped handlers to both editors
149
+ this.baseMode.defaultEditor.onSubmit = wrappedOnSubmit;
150
+ this.baseMode.editor.onSubmit = wrappedOnSubmit;
151
+ this.baseMode.defaultEditor.onChange = wrappedOnChange;
152
+ this.baseMode.editor.onChange = wrappedOnChange;
153
+ if (this.debugLogging) {
154
+ process.stderr.write('[mongosh mode] wrappedOnSubmit assigned to editors\n');
155
+ }
156
+ }
157
+ updateMongoshModeIndicator() {
158
+ // Store original border color on first call
159
+ if (!this.originalBorderColor) {
160
+ this.originalBorderColor = this.baseMode.editor.borderColor;
161
+ }
162
+ // Use green border for mongosh mode (distinct from bash mode which uses yellow/orange)
163
+ // When not in mongosh mode, restore the original color
164
+ this.baseMode.editor.borderColor = this.baseMode.isMongoshMode
165
+ ? chalk_1.default.green
166
+ : (this.originalBorderColor ?? chalk_1.default.gray);
167
+ // Show/hide the mongosh mode text widget
168
+ if (this.baseMode.setExtensionWidget) {
169
+ if (this.baseMode.isMongoshMode) {
170
+ this.baseMode.setExtensionWidget('mongosh-mode-indicator', [chalk_1.default.green('mongosh mode')], { position: 'above' });
171
+ }
172
+ else {
173
+ this.baseMode.setExtensionWidget('mongosh-mode-indicator', undefined);
174
+ }
175
+ }
176
+ this.baseMode.ui.requestRender();
177
+ }
178
+ async handleMongoshCommand(command, excludeFromContext = false) {
179
+ // Clear the editor
180
+ this.baseMode.editor.setText('');
181
+ // Create UI component for display
182
+ this.mongoshComponent = new MongoshExecutionComponent(command, this.baseMode.ui, excludeFromContext);
183
+ const isDeferred = this.baseMode.session.isStreaming;
184
+ if (isDeferred) {
185
+ // Show in pending area when agent is streaming
186
+ this.baseMode.pendingMessagesContainer.addChild(this.mongoshComponent);
187
+ this.pendingMongoshComponents.push(this.mongoshComponent);
188
+ }
189
+ else {
190
+ // Show in chat immediately when agent is idle
191
+ this.baseMode.chatContainer.addChild(this.mongoshComponent);
192
+ }
193
+ this.baseMode.ui.requestRender();
194
+ try {
195
+ // Execute the mongosh command
196
+ const result = await this.mongoshEval(command);
197
+ if (this.mongoshComponent) {
198
+ if (result.error) {
199
+ this.mongoshComponent.appendOutput(`Error: ${result.error}`);
200
+ this.mongoshComponent.setComplete(1, false);
201
+ }
202
+ else {
203
+ this.mongoshComponent.appendOutput(result.output);
204
+ this.mongoshComponent.setComplete(0, false);
205
+ }
206
+ }
207
+ // Record result in session for context (unless excluded)
208
+ if (!excludeFromContext && this.baseMode.session.recordBashResult) {
209
+ this.baseMode.session.recordBashResult(command, {
210
+ exitCode: result.error ? 1 : 0,
211
+ output: result.output,
212
+ }, { excludeFromContext: false });
213
+ }
214
+ }
215
+ catch (error) {
216
+ if (this.mongoshComponent) {
217
+ const errorMsg = error instanceof Error ? error.message : 'Unknown error';
218
+ this.mongoshComponent.appendOutput(`Error: ${errorMsg}`);
219
+ this.mongoshComponent.setComplete(1, false);
220
+ }
221
+ if (this.debugLogging) {
222
+ process.stderr.write(`[mongosh mode] Error executing command: ${error instanceof Error ? error.message : String(error)}\n`);
223
+ }
224
+ }
225
+ this.mongoshComponent = undefined;
226
+ this.baseMode.ui.requestRender();
227
+ }
228
+ async run() {
229
+ // The base mode's run() method handles the main loop
230
+ // Our onSubmit override will intercept $ commands
231
+ await this.baseMode.run();
232
+ }
233
+ stop() {
234
+ this.baseMode.stop();
235
+ }
236
+ // Delegate other methods to base mode
237
+ showError(message) {
238
+ this.baseMode.showError(message);
239
+ }
240
+ showWarning(message) {
241
+ this.baseMode.showWarning(message);
242
+ }
243
+ }
244
+ exports.MongoshInteractiveMode = MongoshInteractiveMode;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const pi_coding_agent_1 = require("@earendil-works/pi-coding-agent");
4
+ module.exports = async (globalThis) => {
5
+ class ProjectAgent {
6
+ constructor({ agent }) {
7
+ this.agent = agent;
8
+ }
9
+ static async create(cliContext) {
10
+ const agent = new pi_coding_agent_1.PiCodingAgent({
11
+ workspace: process.cwd(),
12
+ });
13
+ const projectAgent = new ProjectAgent({
14
+ agent,
15
+ });
16
+ return projectAgent;
17
+ }
18
+ async chat(message) {
19
+ const response = await this.agent.chat(message);
20
+ console.log(response);
21
+ return response;
22
+ }
23
+ help() {
24
+ console.log('Pi Coding Agent for Mongosh');
25
+ console.log('');
26
+ console.log('Commands:');
27
+ console.log(' projectAgent.chat(message) - Send a message to the Pi agent');
28
+ }
29
+ [Symbol.for('nodejs.util.inspect.custom')]() {
30
+ this.help();
31
+ return '';
32
+ }
33
+ }
34
+ globalThis.projectAgent =
35
+ await ProjectAgent.create(globalThis);
36
+ };
@@ -0,0 +1,17 @@
1
+ import type { ShellInstanceState } from './types';
2
+ export type ShellContext = {
3
+ shellEvaluator: any;
4
+ originalEval: (input: string, context: object, filename: string) => unknown;
5
+ formatResultValue: (value: unknown) => Promise<string>;
6
+ instanceState: ShellInstanceState;
7
+ capturedPrintOutput: string[];
8
+ };
9
+ export declare function createShellContext(options: {
10
+ shellContext: {
11
+ db: {
12
+ _mongo: {
13
+ _instanceState: ShellInstanceState;
14
+ };
15
+ };
16
+ };
17
+ }): ShellContext;
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createShellContext = createShellContext;
4
+ const vm_1 = require("vm");
5
+ function createShellContext(options) {
6
+ const { shellContext } = options;
7
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
8
+ const { ShellEvaluator } = require('@mongosh/shell-evaluator');
9
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
10
+ const { toShellResult } = require('@mongosh/shell-api');
11
+ const instanceState = shellContext.db._mongo._instanceState;
12
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
+ const shellEvaluator = new ShellEvaluator(instanceState, (value) => value);
14
+ const originalEval = (input, context, filename) => {
15
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
16
+ return new vm_1.Script(input, { filename }).runInContext(context);
17
+ };
18
+ const capturedPrintOutput = [];
19
+ // Patch the context's print function to capture output
20
+ if (instanceState.context) {
21
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
+ const originalPrint = instanceState.context.print;
23
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
+ instanceState.context.print = function (...args) {
25
+ const output = args.map((arg) => typeof arg === 'string' ? arg : JSON.stringify(arg)).join(' ');
26
+ capturedPrintOutput.push(output);
27
+ // Also call original print if it exists
28
+ if (originalPrint) {
29
+ return originalPrint.apply(this, args);
30
+ }
31
+ return undefined;
32
+ };
33
+ // Also patch printjson
34
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
+ const originalPrintJson = instanceState.context.printjson;
36
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
37
+ instanceState.context.printjson = function (value) {
38
+ const output = typeof value === 'string'
39
+ ? value
40
+ : JSON.stringify(value, null, 2);
41
+ capturedPrintOutput.push(output);
42
+ if (originalPrintJson) {
43
+ return originalPrintJson.call(this, value);
44
+ }
45
+ return undefined;
46
+ };
47
+ }
48
+ const formatResultValue = async (value) => {
49
+ if (value === undefined)
50
+ return '';
51
+ const shellResult = await toShellResult(value);
52
+ const printable = shellResult.printable;
53
+ if (printable === undefined || printable === null) {
54
+ return String(printable);
55
+ }
56
+ if (typeof printable === 'string')
57
+ return printable;
58
+ try {
59
+ if (typeof printable.toJSON === 'function') {
60
+ return JSON.stringify(printable.toJSON(), null, 2);
61
+ }
62
+ return JSON.stringify(printable, null, 2);
63
+ }
64
+ catch {
65
+ return String(printable);
66
+ }
67
+ };
68
+ return {
69
+ shellEvaluator,
70
+ originalEval,
71
+ formatResultValue,
72
+ instanceState,
73
+ capturedPrintOutput,
74
+ };
75
+ }
@@ -0,0 +1,2 @@
1
+ import type { Skill } from './types';
2
+ export declare function loadSkillsFromDir(skillsDir: string): Skill[];
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.loadSkillsFromDir = loadSkillsFromDir;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ function loadSkillsFromDir(skillsDir) {
40
+ const skills = [];
41
+ if (!fs.existsSync(skillsDir))
42
+ return skills;
43
+ const files = fs.readdirSync(skillsDir).filter(f => f.endsWith('.md'));
44
+ for (const file of files) {
45
+ const filePath = path.join(skillsDir, file);
46
+ const content = fs.readFileSync(filePath, 'utf-8');
47
+ const frontmatterMatch = content.match(/^---\s*\n([\s\S]*?)\n---\s*\n/);
48
+ let name = file.replace('.md', '');
49
+ let description = '';
50
+ let skillContent = content;
51
+ if (frontmatterMatch) {
52
+ const frontmatter = frontmatterMatch[1];
53
+ skillContent = content.slice(frontmatterMatch[0].length);
54
+ const nameMatch = frontmatter.match(/name:\s*(.+)/);
55
+ const descMatch = frontmatter.match(/description:\s*(.+)/);
56
+ if (nameMatch)
57
+ name = nameMatch[1].trim();
58
+ if (descMatch)
59
+ description = descMatch[1].trim();
60
+ }
61
+ skills.push({
62
+ name,
63
+ description,
64
+ content: skillContent.trim(),
65
+ source: filePath,
66
+ });
67
+ }
68
+ return skills;
69
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ // tsc assigns to a global exports variable for TypeScript files which doesn't pair well
3
+ // with mongosh scripts so we have this wrapper to load the module and minimize rewriting.
4
+ (() => {
5
+ const localRequire = require('module').createRequire(__filename);
6
+ // eslint-disable-next-line no-undef
7
+ localRequire('./project-agent.js')(globalThis);
8
+ })();
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const pi_coding_agent_1 = require("@earendil-works/pi-coding-agent");
4
+ module.exports = async (globalThis) => {
5
+ class ProjectAgent {
6
+ constructor({ agent }) {
7
+ this.agent = agent;
8
+ }
9
+ static async create(cliContext) {
10
+ const agent = new pi_coding_agent_1.PiCodingAgent({
11
+ workspace: process.cwd(),
12
+ });
13
+ const projectAgent = new ProjectAgent({
14
+ agent,
15
+ });
16
+ return projectAgent;
17
+ }
18
+ async chat(message) {
19
+ const response = await this.agent.chat(message);
20
+ console.log(response);
21
+ return response;
22
+ }
23
+ help() {
24
+ console.log('Pi Coding Agent for Mongosh');
25
+ console.log('');
26
+ console.log('Commands:');
27
+ console.log(' projectAgent.chat(message) - Send a message to the Pi agent');
28
+ }
29
+ [Symbol.for('nodejs.util.inspect.custom')]() {
30
+ this.help();
31
+ return '';
32
+ }
33
+ }
34
+ globalThis.projectAgent =
35
+ await ProjectAgent.create(globalThis);
36
+ };