@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
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,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
|
+
};
|