@acmecloud/core 1.0.2

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 (62) hide show
  1. package/dist/agent/index.d.ts +52 -0
  2. package/dist/agent/index.js +476 -0
  3. package/dist/config/index.d.ts +83 -0
  4. package/dist/config/index.js +318 -0
  5. package/dist/context/index.d.ts +1 -0
  6. package/dist/context/index.js +30 -0
  7. package/dist/llm/provider.d.ts +27 -0
  8. package/dist/llm/provider.js +202 -0
  9. package/dist/llm/vision.d.ts +7 -0
  10. package/dist/llm/vision.js +37 -0
  11. package/dist/mcp/index.d.ts +10 -0
  12. package/dist/mcp/index.js +84 -0
  13. package/dist/prompt/anthropic.d.ts +1 -0
  14. package/dist/prompt/anthropic.js +32 -0
  15. package/dist/prompt/architect.d.ts +1 -0
  16. package/dist/prompt/architect.js +17 -0
  17. package/dist/prompt/autopilot.d.ts +1 -0
  18. package/dist/prompt/autopilot.js +18 -0
  19. package/dist/prompt/beast.d.ts +1 -0
  20. package/dist/prompt/beast.js +83 -0
  21. package/dist/prompt/gemini.d.ts +1 -0
  22. package/dist/prompt/gemini.js +45 -0
  23. package/dist/prompt/index.d.ts +18 -0
  24. package/dist/prompt/index.js +239 -0
  25. package/dist/prompt/zen.d.ts +1 -0
  26. package/dist/prompt/zen.js +13 -0
  27. package/dist/session/index.d.ts +18 -0
  28. package/dist/session/index.js +97 -0
  29. package/dist/skills/index.d.ts +6 -0
  30. package/dist/skills/index.js +72 -0
  31. package/dist/tools/batch.d.ts +2 -0
  32. package/dist/tools/batch.js +65 -0
  33. package/dist/tools/browser.d.ts +7 -0
  34. package/dist/tools/browser.js +86 -0
  35. package/dist/tools/edit.d.ts +11 -0
  36. package/dist/tools/edit.js +312 -0
  37. package/dist/tools/index.d.ts +13 -0
  38. package/dist/tools/index.js +980 -0
  39. package/dist/tools/lsp-client.d.ts +11 -0
  40. package/dist/tools/lsp-client.js +224 -0
  41. package/package.json +42 -0
  42. package/src/agent/index.ts +588 -0
  43. package/src/config/index.ts +383 -0
  44. package/src/context/index.ts +34 -0
  45. package/src/llm/provider.ts +237 -0
  46. package/src/llm/vision.ts +43 -0
  47. package/src/mcp/index.ts +110 -0
  48. package/src/prompt/anthropic.ts +32 -0
  49. package/src/prompt/architect.ts +17 -0
  50. package/src/prompt/autopilot.ts +18 -0
  51. package/src/prompt/beast.ts +83 -0
  52. package/src/prompt/gemini.ts +45 -0
  53. package/src/prompt/index.ts +267 -0
  54. package/src/prompt/zen.ts +13 -0
  55. package/src/session/index.ts +129 -0
  56. package/src/skills/index.ts +86 -0
  57. package/src/tools/batch.ts +73 -0
  58. package/src/tools/browser.ts +95 -0
  59. package/src/tools/edit.ts +317 -0
  60. package/src/tools/index.ts +1112 -0
  61. package/src/tools/lsp-client.ts +303 -0
  62. package/tsconfig.json +19 -0
@@ -0,0 +1,11 @@
1
+ import { type ChildProcessWithoutNullStreams } from "child_process";
2
+ import { MessageConnection } from "vscode-jsonrpc/lib/node/main.js";
3
+ import type { Diagnostic } from "vscode-languageserver-types";
4
+ export interface LspClient {
5
+ connection: MessageConnection;
6
+ process: ChildProcessWithoutNullStreams;
7
+ diagnostics: Map<string, Diagnostic[]>;
8
+ openFile: (filePath: string, timeoutMs?: number) => Promise<void>;
9
+ shutdown: () => Promise<void>;
10
+ }
11
+ export declare function getLspClientForFile(workspaceRoot: string, filePath: string): Promise<LspClient>;
@@ -0,0 +1,224 @@
1
+ import { spawn } from "child_process";
2
+ import path from "path";
3
+ import { pathToFileURL } from "url";
4
+ import { createMessageConnection, StreamMessageReader, StreamMessageWriter, } from "vscode-jsonrpc/lib/node/main.js";
5
+ import * as fs from "fs/promises";
6
+ const SERVER_CONFIGS = {
7
+ typescript: {
8
+ command: process.platform === "win32" ? "npx.cmd" : "npx",
9
+ args: ["--no-install", "typescript-language-server", "--stdio"],
10
+ languageIdResolver: (filePath) => filePath.endsWith(".tsx")
11
+ ? "typescriptreact"
12
+ : filePath.endsWith(".jsx")
13
+ ? "javascriptreact"
14
+ : filePath.endsWith(".js")
15
+ ? "javascript"
16
+ : "typescript",
17
+ },
18
+ python: {
19
+ command: process.platform === "win32" ? "npx.cmd" : "npx",
20
+ // npx pyright-langserver will use standard pyright if available
21
+ args: ["--no-install", "pyright-langserver", "--stdio"],
22
+ languageIdResolver: () => "python",
23
+ },
24
+ go: {
25
+ command: "gopls",
26
+ args: [], // gopls runs in stdio mode by default
27
+ languageIdResolver: () => "go",
28
+ },
29
+ rust: {
30
+ command: "rust-analyzer",
31
+ args: [],
32
+ languageIdResolver: () => "rust",
33
+ },
34
+ };
35
+ const clients = new Map();
36
+ const clientInitializationPromises = new Map();
37
+ // Track file versions globally across all servers
38
+ const fileVersions = new Map();
39
+ function getLanguageIdForExtension(filePath) {
40
+ const ext = path.extname(filePath).toLowerCase();
41
+ if ([".ts", ".tsx", ".js", ".jsx", ".cjs", ".mjs"].includes(ext))
42
+ return "typescript";
43
+ if ([".py", ".pyi"].includes(ext))
44
+ return "python";
45
+ if ([".go"].includes(ext))
46
+ return "go";
47
+ if ([".rs"].includes(ext))
48
+ return "rust";
49
+ return null;
50
+ }
51
+ async function getTsServerPath(workspaceRoot) {
52
+ const localTsServer = path.join(workspaceRoot, "node_modules", "typescript", "lib", "tsserver.js");
53
+ try {
54
+ await fs.stat(localTsServer);
55
+ return localTsServer;
56
+ }
57
+ catch { }
58
+ return null;
59
+ }
60
+ async function resolveTsLsCommand(workspaceRoot) {
61
+ // Walk up from workspaceRoot looking for node_modules/.bin/typescript-language-server
62
+ const bin = process.platform === "win32"
63
+ ? "typescript-language-server.cmd"
64
+ : "typescript-language-server";
65
+ let dir = workspaceRoot;
66
+ for (let i = 0; i < 5; i++) {
67
+ const candidate = path.join(dir, "node_modules", ".bin", bin);
68
+ try {
69
+ await fs.access(candidate);
70
+ return { command: candidate, args: ["--stdio"] };
71
+ }
72
+ catch { }
73
+ const parent = path.dirname(dir);
74
+ if (parent === dir)
75
+ break;
76
+ dir = parent;
77
+ }
78
+ // Fallback: try global install via npx (with --no-install to avoid slow download)
79
+ return {
80
+ command: process.platform === "win32" ? "npx.cmd" : "npx",
81
+ args: ["--no-install", "typescript-language-server", "--stdio"],
82
+ };
83
+ }
84
+ export async function getLspClientForFile(workspaceRoot, filePath) {
85
+ const langId = getLanguageIdForExtension(filePath);
86
+ if (!langId) {
87
+ throw new Error(`Unsupported file extension for LSP: ${filePath}`);
88
+ }
89
+ if (clients.has(langId)) {
90
+ return clients.get(langId);
91
+ }
92
+ if (!clientInitializationPromises.has(langId)) {
93
+ const promise = initializeLspClient(workspaceRoot, langId).catch((err) => {
94
+ clientInitializationPromises.delete(langId);
95
+ throw err;
96
+ });
97
+ clientInitializationPromises.set(langId, promise);
98
+ }
99
+ return clientInitializationPromises.get(langId);
100
+ }
101
+ async function initializeLspClient(workspaceRoot, langId) {
102
+ let config = SERVER_CONFIGS[langId];
103
+ // For TypeScript, prefer the local node_modules binary over npx
104
+ if (langId === "typescript") {
105
+ const resolved = await resolveTsLsCommand(workspaceRoot);
106
+ config = { ...config, ...resolved };
107
+ }
108
+ console.log(`[LSP] Starting ${langId} language server (${config.command} ${config.args.join(" ")})...`);
109
+ const proc = spawn(config.command, config.args, {
110
+ cwd: workspaceRoot,
111
+ env: { ...process.env },
112
+ shell: false, // direct binary, no shell needed
113
+ });
114
+ // Fast-fail: if the process exits immediately, it's not installed
115
+ await new Promise((resolve, reject) => {
116
+ const onExit = (code) => {
117
+ reject(new Error(`[LSP] ${langId} server exited immediately (code ${code}). Is it installed?`));
118
+ };
119
+ proc.once("exit", onExit);
120
+ // Give it 500ms to either crash or start successfully
121
+ setTimeout(() => {
122
+ proc.removeListener("exit", onExit);
123
+ resolve();
124
+ }, 500);
125
+ });
126
+ // Capture stderr for debug logging
127
+ proc.stderr.on("data", (data) => {
128
+ // console.error(`[LSP ${langId}] ${data.toString()}`);
129
+ });
130
+ const connection = createMessageConnection(new StreamMessageReader(proc.stdout), new StreamMessageWriter(proc.stdin));
131
+ const diagnosticsMap = new Map();
132
+ // Listeners waiting for diagnostics on a specific URI
133
+ const diagnosticsListeners = new Map();
134
+ connection.onNotification("textDocument/publishDiagnostics", (params) => {
135
+ diagnosticsMap.set(params.uri, params.diagnostics);
136
+ // Notify any waiters for this URI
137
+ const listeners = diagnosticsListeners.get(params.uri);
138
+ if (listeners) {
139
+ diagnosticsListeners.delete(params.uri);
140
+ for (const cb of listeners)
141
+ cb();
142
+ }
143
+ });
144
+ connection.onRequest("window/workDoneProgress/create", () => null);
145
+ connection.onRequest("workspace/configuration", () => [{}]);
146
+ connection.listen();
147
+ let initializationOptions = {};
148
+ if (langId === "typescript") {
149
+ const tsserverPath = await getTsServerPath(workspaceRoot);
150
+ if (tsserverPath) {
151
+ initializationOptions = { tsserver: { path: tsserverPath } };
152
+ }
153
+ }
154
+ // 1. Initialize (with timeout to avoid hanging on slow server startup)
155
+ const INIT_TIMEOUT_MS = 15000;
156
+ await Promise.race([
157
+ connection.sendRequest("initialize", {
158
+ processId: process.pid,
159
+ rootUri: pathToFileURL(workspaceRoot).href,
160
+ capabilities: {
161
+ textDocument: {
162
+ synchronization: { didOpen: true, didChange: true },
163
+ publishDiagnostics: { relatedInformation: true },
164
+ },
165
+ },
166
+ initializationOptions,
167
+ }),
168
+ new Promise((_, reject) => setTimeout(() => reject(new Error(`[LSP] initialize timed out after ${INIT_TIMEOUT_MS}ms`)), INIT_TIMEOUT_MS)),
169
+ ]);
170
+ // 2. Initialized
171
+ await connection.sendNotification("initialized", {});
172
+ const client = {
173
+ connection,
174
+ process: proc,
175
+ diagnostics: diagnosticsMap,
176
+ openFile: async (filePath, timeoutMs = 3000) => {
177
+ const uri = pathToFileURL(filePath).href;
178
+ const content = await fs.readFile(filePath, "utf8");
179
+ const version = fileVersions.get(uri);
180
+ const resolvedLangId = config.languageIdResolver(filePath);
181
+ // Set up a promise that resolves when publishDiagnostics fires for this URI
182
+ const diagReady = new Promise((resolve) => {
183
+ const existing = diagnosticsListeners.get(uri) ?? [];
184
+ existing.push(resolve);
185
+ diagnosticsListeners.set(uri, existing);
186
+ });
187
+ if (version !== undefined) {
188
+ const nextVersion = version + 1;
189
+ fileVersions.set(uri, nextVersion);
190
+ await connection.sendNotification("textDocument/didChange", {
191
+ textDocument: { uri, version: nextVersion },
192
+ contentChanges: [{ text: content }],
193
+ });
194
+ }
195
+ else {
196
+ fileVersions.set(uri, 0);
197
+ await connection.sendNotification("textDocument/didOpen", {
198
+ textDocument: {
199
+ uri,
200
+ languageId: resolvedLangId,
201
+ version: 0,
202
+ text: content,
203
+ },
204
+ });
205
+ }
206
+ // Wait for diagnostics or timeout — whichever comes first
207
+ await Promise.race([
208
+ diagReady,
209
+ new Promise((resolve) => setTimeout(resolve, timeoutMs)),
210
+ ]);
211
+ },
212
+ shutdown: async () => {
213
+ await connection.sendRequest("shutdown");
214
+ await connection.sendNotification("exit");
215
+ connection.dispose();
216
+ proc.kill();
217
+ clients.delete(langId);
218
+ clientInitializationPromises.delete(langId);
219
+ // Note: fileVersions is global, we don't clear it here so documents stay "open" if another server needs them
220
+ },
221
+ };
222
+ clients.set(langId, client);
223
+ return client;
224
+ }
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@acmecloud/core",
3
+ "version": "1.0.2",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "exports": {
7
+ "./*": "./dist/*"
8
+ },
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "postinstall": "npx playwright install chromium"
15
+ },
16
+ "dependencies": {
17
+ "@ai-sdk/anthropic": "^3.0.46",
18
+ "@ai-sdk/deepinfra": "^2.0.34",
19
+ "@ai-sdk/google": "^3.0.30",
20
+ "@ai-sdk/groq": "^3.0.24",
21
+ "@ai-sdk/mistral": "^3.0.20",
22
+ "@ai-sdk/openai": "^3.0.30",
23
+ "@ai-sdk/xai": "^3.0.57",
24
+ "@modelcontextprotocol/sdk": "^1.26.0",
25
+ "@openrouter/ai-sdk-provider": "^2.2.3",
26
+ "@playwright/test": "^1.58.2",
27
+ "ai": "^6.0.97",
28
+ "better-sqlite3": "^12.6.2",
29
+ "diff": "^7.0.0",
30
+ "dotenv": "^17.3.1",
31
+ "iconv-lite": "^0.7.2",
32
+ "playwright": "^1.58.2",
33
+ "turndown": "^7.2.0",
34
+ "vscode-jsonrpc": "^8.2.1",
35
+ "vscode-languageserver-types": "^3.17.5",
36
+ "zod": "^4.3.6"
37
+ },
38
+ "devDependencies": {
39
+ "@types/diff": "^7.0.2",
40
+ "@types/turndown": "^5.0.6"
41
+ }
42
+ }