@grackle-ai/runtime-sdk 0.82.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.
- package/dist/async-queue.d.ts +13 -0
- package/dist/async-queue.d.ts.map +1 -0
- package/dist/async-queue.js +48 -0
- package/dist/async-queue.js.map +1 -0
- package/dist/base-runtime.d.ts +30 -0
- package/dist/base-runtime.d.ts.map +1 -0
- package/dist/base-runtime.js +23 -0
- package/dist/base-runtime.js.map +1 -0
- package/dist/base-session.d.ts +104 -0
- package/dist/base-session.d.ts.map +1 -0
- package/dist/base-session.js +198 -0
- package/dist/base-session.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +4 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +10 -0
- package/dist/logger.js.map +1 -0
- package/dist/runtime-installer.d.ts +43 -0
- package/dist/runtime-installer.d.ts.map +1 -0
- package/dist/runtime-installer.js +275 -0
- package/dist/runtime-installer.js.map +1 -0
- package/dist/runtime-utils.d.ts +97 -0
- package/dist/runtime-utils.d.ts.map +1 -0
- package/dist/runtime-utils.js +291 -0
- package/dist/runtime-utils.js.map +1 -0
- package/dist/runtime.d.ts +63 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +2 -0
- package/dist/runtime.js.map +1 -0
- package/dist/tsdoc-metadata.json +11 -0
- package/dist/worktree.d.ts +30 -0
- package/dist/worktree.d.ts.map +1 -0
- package/dist/worktree.js +115 -0
- package/dist/worktree.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { execFile } from "node:child_process";
|
|
5
|
+
import { createRequire, register } from "node:module";
|
|
6
|
+
import { pathToFileURL } from "node:url";
|
|
7
|
+
import { RUNTIME_MANIFESTS } from "@grackle-ai/common";
|
|
8
|
+
import { logger } from "./logger.js";
|
|
9
|
+
// ─── Constants ──────────────────────────────────────────────
|
|
10
|
+
/** Base directory for isolated per-runtime installs. */
|
|
11
|
+
const RUNTIMES_BASE_DIR = join(homedir(), ".grackle", "runtimes");
|
|
12
|
+
/** Filename for the version/staleness marker in each runtime directory. */
|
|
13
|
+
const MANIFEST_FILENAME = "manifest.json";
|
|
14
|
+
// ─── Dev Mode Detection ─────────────────────────────────────
|
|
15
|
+
/**
|
|
16
|
+
* Check if PowerLine is running from a monorepo source checkout.
|
|
17
|
+
* Looks for `rush.json` relative to PowerLine's compiled location
|
|
18
|
+
* (packages/powerline/dist → 3 levels up).
|
|
19
|
+
*/
|
|
20
|
+
export function isDevMode() {
|
|
21
|
+
const repoRoot = resolve(import.meta.dirname, "../../../");
|
|
22
|
+
return existsSync(join(repoRoot, "rush.json"));
|
|
23
|
+
}
|
|
24
|
+
// ─── PowerLine Version ──────────────────────────────────────
|
|
25
|
+
/** Cached PowerLine version string, read once from package.json. */
|
|
26
|
+
let cachedVersion;
|
|
27
|
+
/** Read the PowerLine package version for manifest staleness checks. */
|
|
28
|
+
function getPowerLineVersion() {
|
|
29
|
+
if (!cachedVersion) {
|
|
30
|
+
try {
|
|
31
|
+
const esmRequire = createRequire(import.meta.url);
|
|
32
|
+
const pkg = esmRequire("../package.json");
|
|
33
|
+
cachedVersion = pkg.version;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
cachedVersion = "unknown";
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return cachedVersion;
|
|
40
|
+
}
|
|
41
|
+
// ─── Single-Flight Guard ────────────────────────────────────
|
|
42
|
+
/** Prevents concurrent installs of the same runtime. */
|
|
43
|
+
const inflight = new Map();
|
|
44
|
+
// ─── vscode-jsonrpc Hook ────────────────────────────────────
|
|
45
|
+
/** Whether the vscode-jsonrpc module resolve hook has been registered. */
|
|
46
|
+
let jsonRpcHookRegistered = false;
|
|
47
|
+
/**
|
|
48
|
+
* Register a module resolve hook that rewrites `vscode-jsonrpc/node`
|
|
49
|
+
* to `vscode-jsonrpc/node.js` for Node 22 strict ESM compatibility.
|
|
50
|
+
* Only needed for the copilot runtime.
|
|
51
|
+
*/
|
|
52
|
+
function registerJsonRpcHook() {
|
|
53
|
+
if (jsonRpcHookRegistered) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
register("data:text/javascript," +
|
|
57
|
+
encodeURIComponent(`export async function resolve(s,c,n){return s==="vscode-jsonrpc/node"?n("vscode-jsonrpc/node.js",c):n(s,c);}`));
|
|
58
|
+
jsonRpcHookRegistered = true;
|
|
59
|
+
}
|
|
60
|
+
// ─── Core API ───────────────────────────────────────────────
|
|
61
|
+
/**
|
|
62
|
+
* Ensure that the npm packages for a runtime are installed in an isolated
|
|
63
|
+
* directory under `~/.grackle/runtimes/<name>/`.
|
|
64
|
+
*
|
|
65
|
+
* **Fast path**: if the persisted manifest matches the current PowerLine
|
|
66
|
+
* version and package specs, returns immediately (one `readFileSync`).
|
|
67
|
+
*
|
|
68
|
+
* **Dev mode**: returns empty string immediately — Rush already resolves
|
|
69
|
+
* all packages via the monorepo's node_modules.
|
|
70
|
+
*
|
|
71
|
+
* @returns The absolute path to the runtime's install directory.
|
|
72
|
+
*/
|
|
73
|
+
export function ensureRuntimeInstalled(runtimeName, options = {}) {
|
|
74
|
+
// Register module hooks regardless of install path — the hook must be
|
|
75
|
+
// active before the first SDK import, even when packages are already
|
|
76
|
+
// installed or resolved via Rush in dev mode.
|
|
77
|
+
if (runtimeName in RUNTIME_MANIFESTS && RUNTIME_MANIFESTS[runtimeName].needsJsonRpcHook) {
|
|
78
|
+
registerJsonRpcHook();
|
|
79
|
+
}
|
|
80
|
+
// Dev mode: skip the install guard — importFromRuntime() will try a
|
|
81
|
+
// standard import first, falling back to the isolated runtime directory
|
|
82
|
+
// (and running doInstall on demand) if the package isn't in the monorepo.
|
|
83
|
+
if (isDevMode()) {
|
|
84
|
+
return Promise.resolve("");
|
|
85
|
+
}
|
|
86
|
+
if (!(runtimeName in RUNTIME_MANIFESTS)) {
|
|
87
|
+
return Promise.reject(new Error(`Unknown runtime: ${runtimeName}. No manifest entry found.`));
|
|
88
|
+
}
|
|
89
|
+
const manifest = RUNTIME_MANIFESTS[runtimeName];
|
|
90
|
+
const runtimeDir = join(RUNTIMES_BASE_DIR, runtimeName);
|
|
91
|
+
// Fast path: check if already installed and up-to-date
|
|
92
|
+
if (isManifestCurrent(runtimeDir, manifest)) {
|
|
93
|
+
return Promise.resolve(runtimeDir);
|
|
94
|
+
}
|
|
95
|
+
// Single-flight: if another call is already installing this runtime, reuse its promise
|
|
96
|
+
const existing = inflight.get(runtimeName);
|
|
97
|
+
if (existing) {
|
|
98
|
+
return existing;
|
|
99
|
+
}
|
|
100
|
+
const installPromise = doInstall(runtimeName, runtimeDir, manifest, options)
|
|
101
|
+
.then(() => {
|
|
102
|
+
inflight.delete(runtimeName);
|
|
103
|
+
return runtimeDir;
|
|
104
|
+
})
|
|
105
|
+
.catch((err) => {
|
|
106
|
+
inflight.delete(runtimeName);
|
|
107
|
+
throw err;
|
|
108
|
+
});
|
|
109
|
+
inflight.set(runtimeName, installPromise);
|
|
110
|
+
return installPromise;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Dynamically import a module from an isolated runtime directory.
|
|
114
|
+
*
|
|
115
|
+
* In dev mode, falls back to standard `import()` since Rush handles resolution.
|
|
116
|
+
*
|
|
117
|
+
* @param runtimeName - Runtime identifier (e.g. "claude-code")
|
|
118
|
+
* @param packageName - npm package name to import (e.g. `\@anthropic-ai/claude-agent-sdk`)
|
|
119
|
+
* @returns The imported module
|
|
120
|
+
*/
|
|
121
|
+
export async function importFromRuntime(runtimeName, packageName) {
|
|
122
|
+
if (isDevMode()) {
|
|
123
|
+
try {
|
|
124
|
+
return await import(packageName);
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
// Only fall back to runtime directory for module-not-found errors.
|
|
128
|
+
// Rethrow real runtime errors (init failures, syntax errors, etc.)
|
|
129
|
+
const code = err.code;
|
|
130
|
+
if (code !== "ERR_MODULE_NOT_FOUND" && code !== "MODULE_NOT_FOUND") {
|
|
131
|
+
throw err;
|
|
132
|
+
}
|
|
133
|
+
// Package not in monorepo devDependencies — install on demand and
|
|
134
|
+
// resolve from the isolated runtime directory below.
|
|
135
|
+
if (!(runtimeName in RUNTIME_MANIFESTS)) {
|
|
136
|
+
throw err;
|
|
137
|
+
}
|
|
138
|
+
const manifest = RUNTIME_MANIFESTS[runtimeName];
|
|
139
|
+
const runtimeDir = join(RUNTIMES_BASE_DIR, runtimeName);
|
|
140
|
+
if (!isManifestCurrent(runtimeDir, manifest)) {
|
|
141
|
+
logger.info({ runtimeName, packageName }, "Package not found in monorepo — installing via lazy runtime installer");
|
|
142
|
+
await doInstall(runtimeName, runtimeDir, manifest, {});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const runtimeDir = join(RUNTIMES_BASE_DIR, runtimeName);
|
|
147
|
+
try {
|
|
148
|
+
const esmRequire = createRequire(join(runtimeDir, "package.json"));
|
|
149
|
+
let resolved;
|
|
150
|
+
try {
|
|
151
|
+
resolved = esmRequire.resolve(packageName);
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
// CJS resolve fails for ESM-only packages (exports map without "require" condition).
|
|
155
|
+
// Fall back to reading the package's main/exports field directly.
|
|
156
|
+
const pkgJsonPath = join(runtimeDir, "node_modules", ...packageName.split("/"), "package.json");
|
|
157
|
+
const pkg = JSON.parse(readFileSync(pkgJsonPath, "utf8"));
|
|
158
|
+
const exportsRoot = pkg.exports?.["."];
|
|
159
|
+
let entryPoint;
|
|
160
|
+
if (typeof exportsRoot === "string") {
|
|
161
|
+
entryPoint = exportsRoot;
|
|
162
|
+
}
|
|
163
|
+
else if (typeof exportsRoot === "object") {
|
|
164
|
+
entryPoint = exportsRoot.import || exportsRoot.default || pkg.main || "index.js";
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
entryPoint = pkg.main || "index.js";
|
|
168
|
+
}
|
|
169
|
+
resolved = join(runtimeDir, "node_modules", ...packageName.split("/"), entryPoint);
|
|
170
|
+
}
|
|
171
|
+
return import(pathToFileURL(resolved).href);
|
|
172
|
+
}
|
|
173
|
+
catch (resolveErr) {
|
|
174
|
+
throw new Error(`Failed to resolve "${packageName}" from runtime directory ${runtimeDir}. `
|
|
175
|
+
+ `The lazy installer may have failed — check the logs above for details. `
|
|
176
|
+
+ `Manual fix: cd ${runtimeDir} && npm install`, { cause: resolveErr });
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Get the path to the `.bin` directory inside a runtime's node_modules.
|
|
181
|
+
* Used to add runtime-specific CLI binaries to PATH when spawning agent subprocesses.
|
|
182
|
+
*
|
|
183
|
+
* @param runtimeName - Runtime identifier (e.g. "codex-acp")
|
|
184
|
+
* @returns Absolute path to `~/.grackle/runtimes/<name>/node_modules/.bin`
|
|
185
|
+
*/
|
|
186
|
+
export function getRuntimeBinDirectory(runtimeName) {
|
|
187
|
+
if (isDevMode()) {
|
|
188
|
+
// In dev mode, prefer the isolated runtime directory if it exists (packages
|
|
189
|
+
// removed from devDependencies); fall back to the monorepo's bin.
|
|
190
|
+
const monoBin = resolve(import.meta.dirname, "../node_modules/.bin");
|
|
191
|
+
const runtimeBin = join(RUNTIMES_BASE_DIR, runtimeName, "node_modules", ".bin");
|
|
192
|
+
return existsSync(runtimeBin) ? runtimeBin : monoBin;
|
|
193
|
+
}
|
|
194
|
+
return join(RUNTIMES_BASE_DIR, runtimeName, "node_modules", ".bin");
|
|
195
|
+
}
|
|
196
|
+
// ─── Internal Helpers ───────────────────────────────────────
|
|
197
|
+
/** Check if the persisted manifest matches the current state. */
|
|
198
|
+
function isManifestCurrent(runtimeDir, manifest) {
|
|
199
|
+
const manifestPath = join(runtimeDir, MANIFEST_FILENAME);
|
|
200
|
+
try {
|
|
201
|
+
const raw = readFileSync(manifestPath, "utf8");
|
|
202
|
+
const persisted = JSON.parse(raw);
|
|
203
|
+
if (persisted.powerlineVersion !== getPowerLineVersion()) {
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
// Compare package specs
|
|
207
|
+
const currentKeys = Object.keys(manifest.packages).sort();
|
|
208
|
+
const persistedKeys = Object.keys(persisted.packages).sort();
|
|
209
|
+
if (currentKeys.length !== persistedKeys.length) {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
for (let i = 0; i < currentKeys.length; i++) {
|
|
213
|
+
if (currentKeys[i] !== persistedKeys[i]) {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
if (manifest.packages[currentKeys[i]] !== persisted.packages[currentKeys[i]]) {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/** Perform the actual npm install and write the manifest. */
|
|
227
|
+
async function doInstall(runtimeName, runtimeDir, manifest, options) {
|
|
228
|
+
const { eventCallback } = options;
|
|
229
|
+
const packageNames = Object.entries(manifest.packages)
|
|
230
|
+
.map(([name, version]) => `${name}@${version}`)
|
|
231
|
+
.join(", ");
|
|
232
|
+
logger.info({ runtimeName, packages: packageNames }, "Installing runtime packages");
|
|
233
|
+
if (eventCallback) {
|
|
234
|
+
eventCallback(`Installing ${runtimeName} runtime (${packageNames})...`);
|
|
235
|
+
}
|
|
236
|
+
// Ensure directory exists
|
|
237
|
+
mkdirSync(runtimeDir, { recursive: true });
|
|
238
|
+
// Write package.json
|
|
239
|
+
const packageJson = {
|
|
240
|
+
name: `grackle-runtime-${runtimeName}`,
|
|
241
|
+
version: "1.0.0",
|
|
242
|
+
private: true,
|
|
243
|
+
dependencies: { ...manifest.packages },
|
|
244
|
+
};
|
|
245
|
+
writeFileSync(join(runtimeDir, "package.json"), JSON.stringify(packageJson, null, 2));
|
|
246
|
+
// Run npm install asynchronously to avoid blocking the event loop.
|
|
247
|
+
// shell:true is needed on Windows where npm is a .cmd batch file.
|
|
248
|
+
await new Promise((resolve, reject) => {
|
|
249
|
+
execFile("npm", ["install", "--omit=dev", "--registry=https://registry.npmjs.org"], { cwd: runtimeDir, timeout: 120_000, shell: true, maxBuffer: 10 * 1024 * 1024 }, (err, _stdout, stderr) => {
|
|
250
|
+
if (err) {
|
|
251
|
+
const detail = err.message || String(err);
|
|
252
|
+
const stderrSnippet = stderr ? stderr.slice(0, 500) : "";
|
|
253
|
+
logger.error({ runtimeName, runtimeDir, err, stderrSnippet }, "npm install failed for runtime packages");
|
|
254
|
+
reject(new Error(`Failed to install ${runtimeName} runtime packages. Run manually:\n`
|
|
255
|
+
+ ` cd ${runtimeDir} && npm install\n`
|
|
256
|
+
+ `Cause: ${detail}`
|
|
257
|
+
+ (stderrSnippet ? `\nStderr: ${stderrSnippet}` : "")));
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
resolve();
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
// Write manifest for staleness checking
|
|
265
|
+
const persistedManifest = {
|
|
266
|
+
powerlineVersion: getPowerLineVersion(),
|
|
267
|
+
packages: { ...manifest.packages },
|
|
268
|
+
};
|
|
269
|
+
writeFileSync(join(runtimeDir, MANIFEST_FILENAME), JSON.stringify(persistedManifest, null, 2));
|
|
270
|
+
logger.info({ runtimeName, runtimeDir }, "Runtime packages installed successfully");
|
|
271
|
+
if (eventCallback) {
|
|
272
|
+
eventCallback(`${runtimeName} runtime installed successfully`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
//# sourceMappingURL=runtime-installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-installer.js","sourceRoot":"","sources":["../src/runtime-installer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { AgentEvent } from "./runtime.js";
|
|
2
|
+
import type { AsyncQueue } from "./async-queue.js";
|
|
3
|
+
/**
|
|
4
|
+
* Higher-level git repository abstraction for workspace resolution.
|
|
5
|
+
*
|
|
6
|
+
* Unlike the raw `GitExecutor` in worktree.ts (which wraps a single `exec(args)` call),
|
|
7
|
+
* this interface provides domain-specific methods for repository discovery and branch checkout.
|
|
8
|
+
*/
|
|
9
|
+
export interface GitRepository {
|
|
10
|
+
/** Check if a directory is inside a git repository. */
|
|
11
|
+
isRepo(dir: string): Promise<boolean>;
|
|
12
|
+
/** Return the git toplevel for a directory, or undefined if not a repo. */
|
|
13
|
+
toplevel(dir: string): Promise<string | undefined>;
|
|
14
|
+
/** Check out (or create) a branch in the main working tree. */
|
|
15
|
+
checkoutBranch(repoPath: string, branch: string): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
/** Default implementation that shells out to the real git binary. */
|
|
18
|
+
export declare const NODE_GIT_REPOSITORY: GitRepository;
|
|
19
|
+
/** Filesystem operations for workspace discovery. */
|
|
20
|
+
export interface WorkspaceLocator {
|
|
21
|
+
/** Check if a path exists. */
|
|
22
|
+
exists(path: string): boolean;
|
|
23
|
+
/** List entries in a directory. Returns empty array on failure. */
|
|
24
|
+
readDirectory(path: string): string[];
|
|
25
|
+
}
|
|
26
|
+
/** Default implementation using real Node.js fs. */
|
|
27
|
+
export declare const NODE_WORKSPACE_LOCATOR: WorkspaceLocator;
|
|
28
|
+
/** Options for resolving the working directory. */
|
|
29
|
+
export interface ResolveWorkingDirectoryOptions {
|
|
30
|
+
/** Git branch to check out in a worktree. */
|
|
31
|
+
branch?: string;
|
|
32
|
+
/** Base path for worktree creation or working directory override. */
|
|
33
|
+
workingDirectory?: string;
|
|
34
|
+
/** When true, create git worktrees for branch isolation. When false, checkout in place. Defaults to true when undefined. */
|
|
35
|
+
useWorktrees?: boolean;
|
|
36
|
+
/** Event queue to push system messages to. */
|
|
37
|
+
eventQueue: AsyncQueue<AgentEvent>;
|
|
38
|
+
/**
|
|
39
|
+
* When true, the `/workspace` fallback requires the directory to be non-empty.
|
|
40
|
+
* Only claude-code sets this — codex and copilot accept empty workspaces.
|
|
41
|
+
*/
|
|
42
|
+
requireNonEmpty?: boolean;
|
|
43
|
+
/** @internal Git repository abstraction for testing. */
|
|
44
|
+
git?: GitRepository;
|
|
45
|
+
/** @internal Workspace locator abstraction for testing. */
|
|
46
|
+
locator?: WorkspaceLocator;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Find the git repository root from a set of well-known workspace paths.
|
|
50
|
+
*
|
|
51
|
+
* Checks (in order):
|
|
52
|
+
* 1. The provided basePath (if given)
|
|
53
|
+
* 2. /workspace (Docker convention)
|
|
54
|
+
* 3. /workspaces/* (GitHub Codespaces convention — picks the first git repo found)
|
|
55
|
+
*
|
|
56
|
+
* Returns the first path that exists and is a git repository, or undefined.
|
|
57
|
+
*/
|
|
58
|
+
export declare function findGitRepoPath(basePath?: string, git?: GitRepository, locator?: WorkspaceLocator): Promise<string | undefined>;
|
|
59
|
+
/**
|
|
60
|
+
* Resolve the working directory for an agent session.
|
|
61
|
+
*
|
|
62
|
+
* Tries worktree creation first (when branch + basePath are provided and
|
|
63
|
+
* useWorktrees is not false), auto-detecting the git repo if the provided
|
|
64
|
+
* basePath is not a git repo. Falls back to workspace directories on failure.
|
|
65
|
+
*
|
|
66
|
+
* When useWorktrees is explicitly false, checks out the branch directly in the
|
|
67
|
+
* main working tree instead of creating a worktree. When useWorktrees is
|
|
68
|
+
* undefined (proto3 unset), it defaults to true.
|
|
69
|
+
*/
|
|
70
|
+
export declare function resolveWorkingDirectory(options: ResolveWorkingDirectoryOptions): Promise<string | undefined>;
|
|
71
|
+
/**
|
|
72
|
+
* Convert Grackle MCP server configs (keyed object) to ACP format (named array).
|
|
73
|
+
*
|
|
74
|
+
* Grackle format: `{ "name": { command, args, env, ... } }`
|
|
75
|
+
* ACP format: `[{ name, type: "stdio"|"http", command, args, env, ... }]`
|
|
76
|
+
*/
|
|
77
|
+
export declare function convertMcpServers(servers: Record<string, unknown> | undefined): Record<string, unknown>[];
|
|
78
|
+
/** Resolved MCP configuration returned by resolveMcpServers. */
|
|
79
|
+
export interface ResolvedMcpConfig {
|
|
80
|
+
servers: Record<string, unknown> | undefined;
|
|
81
|
+
disallowedTools: string[];
|
|
82
|
+
}
|
|
83
|
+
/** Broker configuration for injecting the HTTP MCP server entry. Matches SpawnOptions.mcpBroker. */
|
|
84
|
+
export interface BrokerConfig {
|
|
85
|
+
/** Full URL of the broker's /mcp endpoint. */
|
|
86
|
+
url: string;
|
|
87
|
+
/** Scoped Bearer token for this session. */
|
|
88
|
+
token: string;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Load MCP server configurations from the shared GRACKLE_MCP_CONFIG file and spawn options.
|
|
92
|
+
*
|
|
93
|
+
* Also reads `disallowedTools` and filters matching tools from MCP server configs.
|
|
94
|
+
* When `brokerConfig` is provided, injects an HTTP-based Grackle MCP server entry.
|
|
95
|
+
*/
|
|
96
|
+
export declare function resolveMcpServers(spawnMcpServers?: Record<string, unknown>, brokerConfig?: BrokerConfig): ResolvedMcpConfig;
|
|
97
|
+
//# sourceMappingURL=runtime-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-utils.d.ts","sourceRoot":"","sources":["../src/runtime-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AASnD;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtC,2EAA2E;IAC3E,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACnD,+DAA+D;IAC/D,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjE;AAED,qEAAqE;AACrE,eAAO,MAAM,mBAAmB,EAAE,aA6B9B,CAAC;AAEL,qDAAqD;AACrD,MAAM,WAAW,gBAAgB;IAC/B,8BAA8B;IAC9B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9B,mEAAmE;IACnE,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CACvC;AAED,oDAAoD;AACpD,eAAO,MAAM,sBAAsB,EAAE,gBASpC,CAAC;AAIF,mDAAmD;AACnD,MAAM,WAAW,8BAA8B;IAC7C,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,4HAA4H;IAC5H,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,8CAA8C;IAC9C,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;IACnC;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,wDAAwD;IACxD,GAAG,CAAC,EAAE,aAAa,CAAC;IACpB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,QAAQ,CAAC,EAAE,MAAM,EACjB,GAAG,GAAE,aAAmC,EACxC,OAAO,GAAE,gBAAyC,GACjD,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAuB7B;AAiCD;;;;;;;;;;GAUG;AACH,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,8BAA8B,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAkElH;AAID;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAyCzG;AAID,gEAAgE;AAChE,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAC7C,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,oGAAoG;AACpG,MAAM,WAAW,YAAY;IAC3B,8CAA8C;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;CACf;AAGD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzC,YAAY,CAAC,EAAE,YAAY,GAC1B,iBAAiB,CAkEnB"}
|