@struktoai/mirage-agents 0.0.3-alpha.0 → 0.0.4
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/README.md +3 -3
- package/dist/chunk-IMI7BLEG.js +142 -0
- package/dist/chunk-IMI7BLEG.js.map +1 -0
- package/dist/{chunk-KAHWIK63.js → chunk-ODKR5YZI.js} +3 -5
- package/dist/chunk-ODKR5YZI.js.map +1 -0
- package/dist/chunk-OLFSAPC6.js +139 -0
- package/dist/chunk-OLFSAPC6.js.map +1 -0
- package/dist/chunk-XEQB7N3F.js +79 -0
- package/dist/chunk-XEQB7N3F.js.map +1 -0
- package/dist/claude-agent-sdk/index.d.ts +15 -0
- package/dist/claude-agent-sdk/index.js +91 -0
- package/dist/claude-agent-sdk/index.js.map +1 -0
- package/dist/file-version-Clij-pms.d.ts +22 -0
- package/dist/langchain/index.d.ts +1 -1
- package/dist/langchain/index.js +1 -1
- package/dist/mcp/index.d.ts +14 -0
- package/dist/mcp/index.js +100 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/openai/index.d.ts +14 -3
- package/dist/openai/index.js +82 -2
- package/dist/openai/index.js.map +1 -1
- package/dist/opencode/index.d.ts +8 -18
- package/dist/opencode/index.js +66 -67
- package/dist/opencode/index.js.map +1 -1
- package/dist/pi/index.d.ts +13 -8
- package/dist/pi/index.js +66 -37
- package/dist/pi/index.js.map +1 -1
- package/dist/prompt-Ca4hc1Ul.d.ts +11 -0
- package/dist/tool-descriptions-7CgIovZc.d.ts +33 -0
- package/dist/vercel/index.d.ts +3 -67
- package/dist/vercel/index.js +28 -102
- package/dist/vercel/index.js.map +1 -1
- package/package.json +56 -17
- package/dist/chunk-KAHWIK63.js.map +0 -1
- package/dist/prompt-CbBVJuUY.d.ts +0 -11
package/dist/pi/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MIRAGE_SYSTEM_PROMPT,
|
|
3
3
|
buildSystemPrompt
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-ODKR5YZI.js";
|
|
5
|
+
import {
|
|
6
|
+
FileVersionTracker,
|
|
7
|
+
StaleMirageFileError
|
|
8
|
+
} from "../chunk-XEQB7N3F.js";
|
|
5
9
|
|
|
6
10
|
// src/pi/extension.ts
|
|
7
11
|
import {
|
|
@@ -12,11 +16,11 @@ import {
|
|
|
12
16
|
createLsToolDefinition,
|
|
13
17
|
createReadToolDefinition,
|
|
14
18
|
createWriteToolDefinition
|
|
15
|
-
} from "@
|
|
19
|
+
} from "@earendil-works/pi-coding-agent";
|
|
16
20
|
|
|
17
21
|
// src/pi/operations.ts
|
|
18
|
-
import picomatch from "picomatch";
|
|
19
22
|
import { rstripSlash } from "@struktoai/mirage-core";
|
|
23
|
+
import picomatch from "picomatch";
|
|
20
24
|
async function ensureParent(ws, dir) {
|
|
21
25
|
const norm = rstripSlash(dir) || "/";
|
|
22
26
|
if (norm === "/" || await ws.fs.exists(norm)) return;
|
|
@@ -31,12 +35,7 @@ async function ensureParent(ws, dir) {
|
|
|
31
35
|
}
|
|
32
36
|
async function walkDirectory(ws, dir, cwdPrefix, matcher, opts, results) {
|
|
33
37
|
if (results.length >= opts.limit) return;
|
|
34
|
-
|
|
35
|
-
try {
|
|
36
|
-
entries = await ws.fs.readdir(dir);
|
|
37
|
-
} catch {
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
38
|
+
const entries = await ws.fs.readdir(dir);
|
|
40
39
|
for (const full of entries) {
|
|
41
40
|
if (results.length >= opts.limit) return;
|
|
42
41
|
const rel = full.startsWith(cwdPrefix) ? full.slice(cwdPrefix.length) : full;
|
|
@@ -46,20 +45,16 @@ async function walkDirectory(ws, dir, cwdPrefix, matcher, opts, results) {
|
|
|
46
45
|
if (isDir) await walkDirectory(ws, full, cwdPrefix, matcher, opts, results);
|
|
47
46
|
}
|
|
48
47
|
}
|
|
49
|
-
function mirageOperations(ws) {
|
|
48
|
+
function mirageOperations(ws, options = {}) {
|
|
49
|
+
const versions = new FileVersionTracker(ws, options.staleWriteProtection ?? true);
|
|
50
50
|
const read = {
|
|
51
|
-
readFile:
|
|
52
|
-
const bytes = await ws.fs.readFile(absolutePath, { raw: true });
|
|
53
|
-
return Buffer.from(bytes);
|
|
54
|
-
},
|
|
51
|
+
readFile: (absolutePath) => versions.read(absolutePath),
|
|
55
52
|
access: async (absolutePath) => {
|
|
56
53
|
await ws.fs.stat(absolutePath);
|
|
57
54
|
}
|
|
58
55
|
};
|
|
59
56
|
const write = {
|
|
60
|
-
writeFile:
|
|
61
|
-
await ws.fs.writeFile(absolutePath, content);
|
|
62
|
-
},
|
|
57
|
+
writeFile: (absolutePath, content) => versions.write(absolutePath, content),
|
|
63
58
|
mkdir: async (dir) => {
|
|
64
59
|
await ensureParent(ws, dir);
|
|
65
60
|
if (!await ws.fs.exists(dir)) {
|
|
@@ -68,29 +63,44 @@ function mirageOperations(ws) {
|
|
|
68
63
|
}
|
|
69
64
|
};
|
|
70
65
|
const edit = {
|
|
71
|
-
readFile:
|
|
72
|
-
writeFile:
|
|
66
|
+
readFile: (absolutePath) => versions.readForEdit(absolutePath),
|
|
67
|
+
writeFile: (absolutePath, content) => versions.writeEdit(absolutePath, content),
|
|
73
68
|
access: read.access
|
|
74
69
|
};
|
|
75
70
|
const bash = {
|
|
76
|
-
exec: async (command,
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
71
|
+
exec: async (command, cwd, options2) => {
|
|
72
|
+
const timeoutSignal = options2.timeout !== void 0 && options2.timeout > 0 ? AbortSignal.timeout(options2.timeout * 1e3) : void 0;
|
|
73
|
+
const signal = options2.signal !== void 0 && timeoutSignal !== void 0 ? AbortSignal.any([options2.signal, timeoutSignal]) : options2.signal ?? timeoutSignal;
|
|
74
|
+
let result;
|
|
75
|
+
try {
|
|
76
|
+
result = signal === void 0 ? await ws.execute(command, { cwd }) : await ws.execute(command, { cwd, signal });
|
|
77
|
+
} catch (error) {
|
|
78
|
+
if (options2.signal?.aborted === true) {
|
|
79
|
+
throw new Error("aborted");
|
|
80
|
+
}
|
|
81
|
+
if (timeoutSignal?.aborted === true) {
|
|
82
|
+
throw new Error("timeout:" + String(options2.timeout));
|
|
83
|
+
}
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
if (result.stdout.length > 0) {
|
|
87
|
+
options2.onData(Buffer.from(result.stdout));
|
|
88
|
+
}
|
|
89
|
+
if (result.stderr.length > 0) {
|
|
90
|
+
options2.onData(Buffer.from(result.stderr));
|
|
81
91
|
}
|
|
82
92
|
return { exitCode: result.exitCode };
|
|
83
93
|
}
|
|
84
94
|
};
|
|
85
95
|
const grep = {
|
|
86
96
|
isDirectory: async (absolutePath) => ws.fs.isDir(absolutePath),
|
|
87
|
-
readFile: async (absolutePath) =>
|
|
97
|
+
readFile: async (absolutePath) => (await versions.read(absolutePath)).toString("utf-8")
|
|
88
98
|
};
|
|
89
99
|
const find = {
|
|
90
100
|
exists: async (absolutePath) => ws.fs.exists(absolutePath),
|
|
91
|
-
glob: async (pattern, cwd,
|
|
101
|
+
glob: async (pattern, cwd, options2) => {
|
|
92
102
|
const matcher = picomatch(pattern, { dot: false });
|
|
93
|
-
const ignoreMatchers =
|
|
103
|
+
const ignoreMatchers = options2.ignore.map((p) => picomatch(p, { dot: false }));
|
|
94
104
|
const root = rstripSlash(cwd) || "/";
|
|
95
105
|
const cwdPrefix = root === "/" ? "/" : `${root}/`;
|
|
96
106
|
const results = [];
|
|
@@ -99,7 +109,7 @@ function mirageOperations(ws) {
|
|
|
99
109
|
root,
|
|
100
110
|
cwdPrefix,
|
|
101
111
|
matcher,
|
|
102
|
-
{ ignoreMatchers, limit:
|
|
112
|
+
{ ignoreMatchers, limit: options2.limit },
|
|
103
113
|
results
|
|
104
114
|
);
|
|
105
115
|
return results;
|
|
@@ -121,21 +131,40 @@ function mirageOperations(ws) {
|
|
|
121
131
|
}
|
|
122
132
|
|
|
123
133
|
// src/pi/extension.ts
|
|
134
|
+
function bashAtCwd(operations, cwd) {
|
|
135
|
+
return {
|
|
136
|
+
exec: (command, _hostCwd, options) => operations.exec(command, cwd, options)
|
|
137
|
+
};
|
|
138
|
+
}
|
|
124
139
|
function mirageExtension(ws, opts = {}) {
|
|
125
140
|
const cwd = opts.cwd ?? "/";
|
|
126
|
-
const ops = mirageOperations(ws);
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
pi
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
141
|
+
const ops = mirageOperations(ws, opts);
|
|
142
|
+
const userBash = bashAtCwd(ops.bash, cwd);
|
|
143
|
+
const systemPrompt = opts.systemPrompt === false ? void 0 : opts.systemPrompt ?? buildSystemPrompt({ workspace: ws });
|
|
144
|
+
return {
|
|
145
|
+
name: "mirage",
|
|
146
|
+
factory: (pi) => {
|
|
147
|
+
pi.registerTool(createReadToolDefinition(cwd, { operations: ops.read }));
|
|
148
|
+
pi.registerTool(createWriteToolDefinition(cwd, { operations: ops.write }));
|
|
149
|
+
pi.registerTool(createEditToolDefinition(cwd, { operations: ops.edit }));
|
|
150
|
+
pi.registerTool(createBashToolDefinition(cwd, { operations: ops.bash }));
|
|
151
|
+
pi.registerTool(createGrepToolDefinition(cwd, { operations: ops.grep }));
|
|
152
|
+
pi.registerTool(createFindToolDefinition(cwd, { operations: ops.find }));
|
|
153
|
+
pi.registerTool(createLsToolDefinition(cwd, { operations: ops.ls }));
|
|
154
|
+
pi.on("user_bash", () => ({ operations: userBash }));
|
|
155
|
+
if (systemPrompt !== void 0) {
|
|
156
|
+
pi.on("before_agent_start", (event) => ({
|
|
157
|
+
systemPrompt: `${event.systemPrompt}
|
|
158
|
+
|
|
159
|
+
${systemPrompt}`
|
|
160
|
+
}));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
135
163
|
};
|
|
136
164
|
}
|
|
137
165
|
export {
|
|
138
166
|
MIRAGE_SYSTEM_PROMPT,
|
|
167
|
+
StaleMirageFileError,
|
|
139
168
|
buildSystemPrompt,
|
|
140
169
|
mirageExtension,
|
|
141
170
|
mirageOperations
|
package/dist/pi/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/pi/extension.ts","../../src/pi/operations.ts"],"sourcesContent":["// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n\nimport type { Workspace } from '@struktoai/mirage-core'\nimport {\n createBashToolDefinition,\n createEditToolDefinition,\n createFindToolDefinition,\n createGrepToolDefinition,\n createLsToolDefinition,\n createReadToolDefinition,\n createWriteToolDefinition,\n type ExtensionFactory,\n} from '@mariozechner/pi-coding-agent'\nimport { mirageOperations } from './operations.ts'\n\nexport interface MirageExtensionOptions {\n cwd?: string\n}\n\nexport function mirageExtension(\n ws: Workspace,\n opts: MirageExtensionOptions = {},\n): ExtensionFactory {\n const cwd = opts.cwd ?? '/'\n const ops = mirageOperations(ws)\n return (pi) => {\n pi.registerTool(createReadToolDefinition(cwd, { operations: ops.read }))\n pi.registerTool(createWriteToolDefinition(cwd, { operations: ops.write }))\n pi.registerTool(createEditToolDefinition(cwd, { operations: ops.edit }))\n pi.registerTool(createBashToolDefinition(cwd, { operations: ops.bash }))\n pi.registerTool(createGrepToolDefinition(cwd, { operations: ops.grep }))\n pi.registerTool(createFindToolDefinition(cwd, { operations: ops.find }))\n pi.registerTool(createLsToolDefinition(cwd, { operations: ops.ls }))\n }\n}\n","// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n\nimport type { Workspace } from '@struktoai/mirage-core'\nimport type {\n BashOperations,\n EditOperations,\n FindOperations,\n GrepOperations,\n LsOperations,\n ReadOperations,\n WriteOperations,\n} from '@mariozechner/pi-coding-agent'\nimport picomatch from 'picomatch'\nimport { rstripSlash } from '@struktoai/mirage-core'\n\nexport interface MirageOperationsBundle {\n read: ReadOperations\n write: WriteOperations\n edit: EditOperations\n bash: BashOperations\n grep: GrepOperations\n find: FindOperations\n ls: LsOperations\n}\n\nasync function ensureParent(ws: Workspace, dir: string): Promise<void> {\n const norm = rstripSlash(dir) || '/'\n if (norm === '/' || (await ws.fs.exists(norm))) return\n const parent = norm.substring(0, norm.lastIndexOf('/')) || '/'\n await ensureParent(ws, parent)\n try {\n await ws.fs.mkdir(norm)\n } catch (err) {\n if (await ws.fs.isDir(norm)) return\n throw err\n }\n}\n\ninterface WalkOptions {\n ignoreMatchers: ((path: string) => boolean)[]\n limit: number\n}\n\nasync function walkDirectory(\n ws: Workspace,\n dir: string,\n cwdPrefix: string,\n matcher: (relativePath: string) => boolean,\n opts: WalkOptions,\n results: string[],\n): Promise<void> {\n if (results.length >= opts.limit) return\n let entries: string[]\n try {\n entries = await ws.fs.readdir(dir)\n } catch {\n return\n }\n for (const full of entries) {\n if (results.length >= opts.limit) return\n const rel = full.startsWith(cwdPrefix) ? full.slice(cwdPrefix.length) : full\n if (opts.ignoreMatchers.some((m) => m(rel))) continue\n const isDir = await ws.fs.isDir(full)\n if (matcher(rel)) results.push(full)\n if (isDir) await walkDirectory(ws, full, cwdPrefix, matcher, opts, results)\n }\n}\n\nexport function mirageOperations(ws: Workspace): MirageOperationsBundle {\n const read: ReadOperations = {\n readFile: async (absolutePath: string) => {\n const bytes = await ws.fs.readFile(absolutePath, { raw: true })\n return Buffer.from(bytes)\n },\n access: async (absolutePath: string) => {\n await ws.fs.stat(absolutePath)\n },\n }\n\n const write: WriteOperations = {\n writeFile: async (absolutePath: string, content: string) => {\n await ws.fs.writeFile(absolutePath, content)\n },\n mkdir: async (dir: string) => {\n await ensureParent(ws, dir)\n if (!(await ws.fs.exists(dir))) {\n await ws.fs.mkdir(dir)\n }\n },\n }\n\n const edit: EditOperations = {\n readFile: read.readFile,\n writeFile: write.writeFile,\n access: read.access,\n }\n\n const bash: BashOperations = {\n exec: async (command, _cwd, options) => {\n const result = await ws.execute(command)\n const combined = result.stdoutText + result.stderrText\n if (combined.length > 0) {\n options.onData(Buffer.from(combined))\n }\n return { exitCode: result.exitCode }\n },\n }\n\n const grep: GrepOperations = {\n isDirectory: async (absolutePath: string) => ws.fs.isDir(absolutePath),\n readFile: async (absolutePath: string) => ws.fs.readFileText(absolutePath),\n }\n\n const find: FindOperations = {\n exists: async (absolutePath: string) => ws.fs.exists(absolutePath),\n glob: async (pattern, cwd, options) => {\n const matcher = picomatch(pattern, { dot: false })\n const ignoreMatchers = options.ignore.map((p) => picomatch(p, { dot: false }))\n const root = rstripSlash(cwd) || '/'\n const cwdPrefix = root === '/' ? '/' : `${root}/`\n const results: string[] = []\n await walkDirectory(\n ws,\n root,\n cwdPrefix,\n matcher,\n { ignoreMatchers, limit: options.limit },\n results,\n )\n return results\n },\n }\n\n const ls: LsOperations = {\n exists: async (absolutePath: string) => ws.fs.exists(absolutePath),\n stat: async (absolutePath: string) => {\n const isDir = await ws.fs.isDir(absolutePath)\n return { isDirectory: () => isDir }\n },\n readdir: async (absolutePath: string) => {\n const entries = await ws.fs.readdir(absolutePath)\n const prefix = absolutePath === '/' ? '/' : `${rstripSlash(absolutePath)}/`\n return entries.map((e) => (e.startsWith(prefix) ? e.slice(prefix.length) : e))\n },\n }\n\n return { read, write, edit, bash, grep, find, ls }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/pi/extension.ts","../../src/pi/operations.ts"],"sourcesContent":["// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n\nimport type { Workspace } from '@struktoai/mirage-core'\nimport {\n createBashToolDefinition,\n createEditToolDefinition,\n createFindToolDefinition,\n createGrepToolDefinition,\n createLsToolDefinition,\n createReadToolDefinition,\n createWriteToolDefinition,\n type BashOperations,\n type InlineExtension,\n} from '@earendil-works/pi-coding-agent'\nimport { buildSystemPrompt } from '../prompt.ts'\nimport { mirageOperations, type MirageOperationsOptions } from './operations.ts'\n\nexport interface MirageExtensionOptions extends MirageOperationsOptions {\n cwd?: string\n systemPrompt?: string | false\n}\n\nfunction bashAtCwd(operations: BashOperations, cwd: string): BashOperations {\n return {\n exec: (command, _hostCwd, options) => operations.exec(command, cwd, options),\n }\n}\n\nexport function mirageExtension(ws: Workspace, opts: MirageExtensionOptions = {}): InlineExtension {\n const cwd = opts.cwd ?? '/'\n const ops = mirageOperations(ws, opts)\n const userBash = bashAtCwd(ops.bash, cwd)\n const systemPrompt =\n opts.systemPrompt === false\n ? undefined\n : (opts.systemPrompt ?? buildSystemPrompt({ workspace: ws }))\n return {\n name: 'mirage',\n factory: (pi) => {\n pi.registerTool(createReadToolDefinition(cwd, { operations: ops.read }))\n pi.registerTool(createWriteToolDefinition(cwd, { operations: ops.write }))\n pi.registerTool(createEditToolDefinition(cwd, { operations: ops.edit }))\n pi.registerTool(createBashToolDefinition(cwd, { operations: ops.bash }))\n pi.registerTool(createGrepToolDefinition(cwd, { operations: ops.grep }))\n pi.registerTool(createFindToolDefinition(cwd, { operations: ops.find }))\n pi.registerTool(createLsToolDefinition(cwd, { operations: ops.ls }))\n pi.on('user_bash', () => ({ operations: userBash }))\n if (systemPrompt !== undefined) {\n pi.on('before_agent_start', (event) => ({\n systemPrompt: `${event.systemPrompt}\\n\\n${systemPrompt}`,\n }))\n }\n },\n }\n}\n","// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n\nimport { rstripSlash, type ExecuteResult, type Workspace } from '@struktoai/mirage-core'\nimport type {\n BashOperations,\n EditOperations,\n FindOperations,\n GrepOperations,\n LsOperations,\n ReadOperations,\n WriteOperations,\n} from '@earendil-works/pi-coding-agent'\nimport picomatch from 'picomatch'\nimport { FileVersionTracker } from '../file-version.ts'\n\nexport { StaleMirageFileError } from '../file-version.ts'\n\nexport interface MirageOperationsOptions {\n staleWriteProtection?: boolean\n}\n\nexport interface MirageOperationsBundle {\n read: ReadOperations\n write: WriteOperations\n edit: EditOperations\n bash: BashOperations\n grep: GrepOperations\n find: FindOperations\n ls: LsOperations\n}\n\nasync function ensureParent(ws: Workspace, dir: string): Promise<void> {\n const norm = rstripSlash(dir) || '/'\n if (norm === '/' || (await ws.fs.exists(norm))) return\n const parent = norm.substring(0, norm.lastIndexOf('/')) || '/'\n await ensureParent(ws, parent)\n try {\n await ws.fs.mkdir(norm)\n } catch (err) {\n if (await ws.fs.isDir(norm)) return\n throw err\n }\n}\n\ninterface WalkOptions {\n ignoreMatchers: ((path: string) => boolean)[]\n limit: number\n}\n\nasync function walkDirectory(\n ws: Workspace,\n dir: string,\n cwdPrefix: string,\n matcher: (relativePath: string) => boolean,\n opts: WalkOptions,\n results: string[],\n): Promise<void> {\n if (results.length >= opts.limit) return\n const entries = await ws.fs.readdir(dir)\n for (const full of entries) {\n if (results.length >= opts.limit) return\n const rel = full.startsWith(cwdPrefix) ? full.slice(cwdPrefix.length) : full\n if (opts.ignoreMatchers.some((m) => m(rel))) continue\n const isDir = await ws.fs.isDir(full)\n if (matcher(rel)) results.push(full)\n if (isDir) await walkDirectory(ws, full, cwdPrefix, matcher, opts, results)\n }\n}\n\nexport function mirageOperations(\n ws: Workspace,\n options: MirageOperationsOptions = {},\n): MirageOperationsBundle {\n const versions = new FileVersionTracker(ws, options.staleWriteProtection ?? true)\n const read: ReadOperations = {\n readFile: (absolutePath: string) => versions.read(absolutePath),\n access: async (absolutePath: string) => {\n await ws.fs.stat(absolutePath)\n },\n }\n\n const write: WriteOperations = {\n writeFile: (absolutePath: string, content: string) => versions.write(absolutePath, content),\n mkdir: async (dir: string) => {\n await ensureParent(ws, dir)\n if (!(await ws.fs.exists(dir))) {\n await ws.fs.mkdir(dir)\n }\n },\n }\n\n const edit: EditOperations = {\n readFile: (absolutePath: string) => versions.readForEdit(absolutePath),\n writeFile: (absolutePath: string, content: string) => versions.writeEdit(absolutePath, content),\n access: read.access,\n }\n\n const bash: BashOperations = {\n exec: async (command, cwd, options) => {\n const timeoutSignal =\n options.timeout !== undefined && options.timeout > 0\n ? AbortSignal.timeout(options.timeout * 1000)\n : undefined\n const signal =\n options.signal !== undefined && timeoutSignal !== undefined\n ? AbortSignal.any([options.signal, timeoutSignal])\n : (options.signal ?? timeoutSignal)\n let result: ExecuteResult\n try {\n result =\n signal === undefined\n ? await ws.execute(command, { cwd })\n : await ws.execute(command, { cwd, signal })\n } catch (error) {\n if (options.signal?.aborted === true) {\n throw new Error('aborted')\n }\n if (timeoutSignal?.aborted === true) {\n throw new Error('timeout:' + String(options.timeout))\n }\n throw error\n }\n if (result.stdout.length > 0) {\n options.onData(Buffer.from(result.stdout))\n }\n if (result.stderr.length > 0) {\n options.onData(Buffer.from(result.stderr))\n }\n return { exitCode: result.exitCode }\n },\n }\n\n const grep: GrepOperations = {\n isDirectory: async (absolutePath: string) => ws.fs.isDir(absolutePath),\n readFile: async (absolutePath: string) => (await versions.read(absolutePath)).toString('utf-8'),\n }\n\n const find: FindOperations = {\n exists: async (absolutePath: string) => ws.fs.exists(absolutePath),\n glob: async (pattern, cwd, options) => {\n const matcher = picomatch(pattern, { dot: false })\n const ignoreMatchers = options.ignore.map((p) => picomatch(p, { dot: false }))\n const root = rstripSlash(cwd) || '/'\n const cwdPrefix = root === '/' ? '/' : `${root}/`\n const results: string[] = []\n await walkDirectory(\n ws,\n root,\n cwdPrefix,\n matcher,\n { ignoreMatchers, limit: options.limit },\n results,\n )\n return results\n },\n }\n\n const ls: LsOperations = {\n exists: async (absolutePath: string) => ws.fs.exists(absolutePath),\n stat: async (absolutePath: string) => {\n const isDir = await ws.fs.isDir(absolutePath)\n return { isDirectory: () => isDir }\n },\n readdir: async (absolutePath: string) => {\n const entries = await ws.fs.readdir(absolutePath)\n const prefix = absolutePath === '/' ? '/' : `${rstripSlash(absolutePath)}/`\n return entries.map((e) => (e.startsWith(prefix) ? e.slice(prefix.length) : e))\n },\n }\n\n return { read, write, edit, bash, grep, find, ls }\n}\n"],"mappings":"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","names":["options"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Workspace } from '@struktoai/mirage-core';
|
|
2
|
+
|
|
3
|
+
declare const MIRAGE_SYSTEM_PROMPT = "Your filesystem is powered by Mirage \u2014 a virtual filesystem that mounts cloud storage, local files, and in-memory data as a unified file tree.\n\nCapabilities beyond standard filesystem:\n- cat on .parquet, .orc, .feather files returns a formatted table\n- head -n 5 on data files returns the first 5 rows\n- grep works natively on CSV, JSON, Parquet \u2014 not just text\n- Pipes work: cat data.parquet | grep error | sort | uniq | wc -l\n- head, tail, cut, wc, sort, uniq, tee, xargs are all available\n\nYou can write Python code and execute it. The workspace is pre-configured with your data sources mounted at their respective paths.\n\nUse the execute tool for complex operations. Use read/write/edit for simple file operations.\n";
|
|
4
|
+
interface BuildSystemPromptOptions {
|
|
5
|
+
workspace?: Workspace;
|
|
6
|
+
mountInfo?: Record<string, string>;
|
|
7
|
+
extraInstructions?: string;
|
|
8
|
+
}
|
|
9
|
+
declare function buildSystemPrompt(opts?: BuildSystemPromptOptions): string;
|
|
10
|
+
|
|
11
|
+
export { type BuildSystemPromptOptions as B, MIRAGE_SYSTEM_PROMPT as M, buildSystemPrompt as b };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Workspace } from '@struktoai/mirage-core';
|
|
2
|
+
|
|
3
|
+
interface ToolResult {
|
|
4
|
+
[key: string]: unknown;
|
|
5
|
+
content: {
|
|
6
|
+
type: 'text';
|
|
7
|
+
text: string;
|
|
8
|
+
}[];
|
|
9
|
+
isError?: boolean;
|
|
10
|
+
}
|
|
11
|
+
interface MirageToolOperationsOptions {
|
|
12
|
+
staleWriteProtection?: boolean;
|
|
13
|
+
}
|
|
14
|
+
declare class MirageToolOperations {
|
|
15
|
+
private readonly ws;
|
|
16
|
+
private readonly versions;
|
|
17
|
+
constructor(ws: Workspace, options?: MirageToolOperationsOptions);
|
|
18
|
+
execute(command: string): Promise<ToolResult>;
|
|
19
|
+
read(path: string, offset?: number, limit?: number): Promise<ToolResult>;
|
|
20
|
+
write(path: string, content: string): Promise<ToolResult>;
|
|
21
|
+
edit(path: string, oldString: string, newString: string, replaceAll?: boolean): Promise<ToolResult>;
|
|
22
|
+
ls(path: string): Promise<ToolResult>;
|
|
23
|
+
grep(pattern: string, path: string): Promise<ToolResult>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
declare const EXECUTE_DESCRIPTION: string;
|
|
27
|
+
declare const READ_DESCRIPTION: string;
|
|
28
|
+
declare const WRITE_DESCRIPTION: string;
|
|
29
|
+
declare const EDIT_DESCRIPTION: string;
|
|
30
|
+
declare const LS_DESCRIPTION = "List files and directories at the given path on the Mirage virtual filesystem.";
|
|
31
|
+
declare const GREP_DESCRIPTION: string;
|
|
32
|
+
|
|
33
|
+
export { EDIT_DESCRIPTION as E, GREP_DESCRIPTION as G, LS_DESCRIPTION as L, type MirageToolOperationsOptions as M, READ_DESCRIPTION as R, type ToolResult as T, WRITE_DESCRIPTION as W, EXECUTE_DESCRIPTION as a, MirageToolOperations as b };
|
package/dist/vercel/index.d.ts
CHANGED
|
@@ -1,70 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { Workspace } from '@struktoai/mirage-core';
|
|
2
|
+
import { ToolSet } from 'ai';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
kind: 'text';
|
|
6
|
-
path: string;
|
|
7
|
-
mimeType: string;
|
|
8
|
-
content: string;
|
|
9
|
-
bytes: number;
|
|
10
|
-
} | {
|
|
11
|
-
kind: 'media';
|
|
12
|
-
path: string;
|
|
13
|
-
mimeType: string;
|
|
14
|
-
base64: string;
|
|
15
|
-
bytes: number;
|
|
16
|
-
} | {
|
|
17
|
-
kind: 'binary';
|
|
18
|
-
path: string;
|
|
19
|
-
mimeType: string;
|
|
20
|
-
bytes: number;
|
|
21
|
-
note: string;
|
|
22
|
-
} | {
|
|
23
|
-
error: string;
|
|
24
|
-
};
|
|
25
|
-
declare function mirageTools(ws: Workspace): {
|
|
26
|
-
execute: ai.Tool<{
|
|
27
|
-
command: string;
|
|
28
|
-
}, {
|
|
29
|
-
stdout: string;
|
|
30
|
-
stderr: string;
|
|
31
|
-
exitCode: number;
|
|
32
|
-
}>;
|
|
33
|
-
readFile: ai.Tool<{
|
|
34
|
-
path: string;
|
|
35
|
-
}, ReadFileResult>;
|
|
36
|
-
writeFile: ai.Tool<{
|
|
37
|
-
path: string;
|
|
38
|
-
content: string;
|
|
39
|
-
}, {
|
|
40
|
-
path: string;
|
|
41
|
-
}>;
|
|
42
|
-
editFile: ai.Tool<{
|
|
43
|
-
path: string;
|
|
44
|
-
oldString: string;
|
|
45
|
-
newString: string;
|
|
46
|
-
replaceAll?: boolean | undefined;
|
|
47
|
-
}, {
|
|
48
|
-
error: string;
|
|
49
|
-
path?: never;
|
|
50
|
-
occurrences?: never;
|
|
51
|
-
} | {
|
|
52
|
-
path: string;
|
|
53
|
-
occurrences: number;
|
|
54
|
-
error?: never;
|
|
55
|
-
}>;
|
|
56
|
-
ls: ai.Tool<{
|
|
57
|
-
path: string;
|
|
58
|
-
}, {
|
|
59
|
-
error: string;
|
|
60
|
-
files?: never;
|
|
61
|
-
} | {
|
|
62
|
-
files: {
|
|
63
|
-
path: string;
|
|
64
|
-
is_dir: boolean;
|
|
65
|
-
}[];
|
|
66
|
-
error?: never;
|
|
67
|
-
}>;
|
|
68
|
-
};
|
|
4
|
+
declare function mirageTools(ws: Workspace): ToolSet;
|
|
69
5
|
|
|
70
6
|
export { mirageTools };
|
package/dist/vercel/index.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
readWorkspaceFile
|
|
3
|
+
} from "../chunk-IMI7BLEG.js";
|
|
4
|
+
|
|
1
5
|
// src/vercel/index.ts
|
|
2
6
|
import { encodeBase64, gnuDirname } from "@struktoai/mirage-core";
|
|
3
7
|
import { tool } from "ai";
|
|
@@ -13,79 +17,30 @@ async function ensureParent(ws, path) {
|
|
|
13
17
|
if (!await ws.fs.exists(parent)) throw err;
|
|
14
18
|
}
|
|
15
19
|
}
|
|
16
|
-
var TEXT_EXTS = /* @__PURE__ */ new Set([
|
|
17
|
-
"txt",
|
|
18
|
-
"md",
|
|
19
|
-
"json",
|
|
20
|
-
"jsonl",
|
|
21
|
-
"yaml",
|
|
22
|
-
"yml",
|
|
23
|
-
"csv",
|
|
24
|
-
"tsv",
|
|
25
|
-
"xml",
|
|
26
|
-
"html",
|
|
27
|
-
"htm",
|
|
28
|
-
"js",
|
|
29
|
-
"mjs",
|
|
30
|
-
"cjs",
|
|
31
|
-
"ts",
|
|
32
|
-
"tsx",
|
|
33
|
-
"jsx",
|
|
34
|
-
"py",
|
|
35
|
-
"rb",
|
|
36
|
-
"rs",
|
|
37
|
-
"go",
|
|
38
|
-
"java",
|
|
39
|
-
"c",
|
|
40
|
-
"cpp",
|
|
41
|
-
"h",
|
|
42
|
-
"hpp",
|
|
43
|
-
"sh",
|
|
44
|
-
"bash",
|
|
45
|
-
"zsh",
|
|
46
|
-
"sql",
|
|
47
|
-
"log",
|
|
48
|
-
"env",
|
|
49
|
-
"ini",
|
|
50
|
-
"toml",
|
|
51
|
-
"conf",
|
|
52
|
-
"cfg"
|
|
53
|
-
]);
|
|
54
|
-
var PRESENTABLE_BINARY = /* @__PURE__ */ new Set([
|
|
55
|
-
"application/pdf",
|
|
56
|
-
"image/jpeg",
|
|
57
|
-
"image/png",
|
|
58
|
-
"image/gif",
|
|
59
|
-
"image/webp"
|
|
60
|
-
]);
|
|
61
|
-
function extOf(path) {
|
|
62
|
-
const dot = path.lastIndexOf(".");
|
|
63
|
-
if (dot < 0) return "";
|
|
64
|
-
return path.slice(dot + 1).toLowerCase();
|
|
65
|
-
}
|
|
66
|
-
function mimeFor(path) {
|
|
67
|
-
const ext = extOf(path);
|
|
68
|
-
if (ext === "json" || ext === "jsonl") return "application/json";
|
|
69
|
-
if (ext === "csv") return "text/csv";
|
|
70
|
-
if (ext === "html" || ext === "htm") return "text/html";
|
|
71
|
-
if (ext === "md") return "text/markdown";
|
|
72
|
-
if (TEXT_EXTS.has(ext)) return "text/plain";
|
|
73
|
-
if (ext === "png") return "image/png";
|
|
74
|
-
if (ext === "jpg" || ext === "jpeg") return "image/jpeg";
|
|
75
|
-
if (ext === "gif") return "image/gif";
|
|
76
|
-
if (ext === "webp") return "image/webp";
|
|
77
|
-
if (ext === "pdf") return "application/pdf";
|
|
78
|
-
return "application/octet-stream";
|
|
79
|
-
}
|
|
80
|
-
function isTextMime(mime) {
|
|
81
|
-
return mime.startsWith("text/") || mime === "application/json";
|
|
82
|
-
}
|
|
83
20
|
function bytesToBase64(bytes) {
|
|
84
21
|
return encodeBase64(bytes);
|
|
85
22
|
}
|
|
86
23
|
function isError(r) {
|
|
87
24
|
return "error" in r;
|
|
88
25
|
}
|
|
26
|
+
async function readFileResult(ws, path) {
|
|
27
|
+
try {
|
|
28
|
+
const result = await readWorkspaceFile(ws, path);
|
|
29
|
+
if (result.kind === "text") return result;
|
|
30
|
+
if (result.kind === "image" || result.kind === "file") {
|
|
31
|
+
return {
|
|
32
|
+
kind: "media",
|
|
33
|
+
path: result.path,
|
|
34
|
+
mimeType: result.mimeType,
|
|
35
|
+
base64: bytesToBase64(result.data),
|
|
36
|
+
bytes: result.bytes
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
} catch (error) {
|
|
41
|
+
return { error: error instanceof Error ? error.message : String(error) };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
89
44
|
function mirageTools(ws) {
|
|
90
45
|
return {
|
|
91
46
|
execute: tool({
|
|
@@ -107,40 +62,7 @@ function mirageTools(ws) {
|
|
|
107
62
|
inputSchema: z.object({
|
|
108
63
|
path: z.string().describe("Absolute path inside the workspace.")
|
|
109
64
|
}),
|
|
110
|
-
execute: async ({ path }) =>
|
|
111
|
-
let bytes;
|
|
112
|
-
try {
|
|
113
|
-
bytes = await ws.fs.readFile(path);
|
|
114
|
-
} catch (err) {
|
|
115
|
-
return { error: err instanceof Error ? err.message : String(err) };
|
|
116
|
-
}
|
|
117
|
-
const mimeType = mimeFor(path);
|
|
118
|
-
if (isTextMime(mimeType)) {
|
|
119
|
-
return {
|
|
120
|
-
kind: "text",
|
|
121
|
-
path,
|
|
122
|
-
mimeType,
|
|
123
|
-
content: new TextDecoder("utf-8", { fatal: false }).decode(bytes),
|
|
124
|
-
bytes: bytes.length
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
if (PRESENTABLE_BINARY.has(mimeType)) {
|
|
128
|
-
return {
|
|
129
|
-
kind: "media",
|
|
130
|
-
path,
|
|
131
|
-
mimeType,
|
|
132
|
-
base64: bytesToBase64(bytes),
|
|
133
|
-
bytes: bytes.length
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
return {
|
|
137
|
-
kind: "binary",
|
|
138
|
-
path,
|
|
139
|
-
mimeType,
|
|
140
|
-
bytes: bytes.length,
|
|
141
|
-
note: `Binary file ${path} (${mimeType}, ${String(bytes.length)} bytes). Use the execute tool with shell commands (head, file, wc, od) to inspect.`
|
|
142
|
-
};
|
|
143
|
-
},
|
|
65
|
+
execute: async ({ path }) => readFileResult(ws, path),
|
|
144
66
|
toModelOutput: ({ output }) => {
|
|
145
67
|
const out = output;
|
|
146
68
|
if (isError(out)) return { type: "error-text", value: out.error };
|
|
@@ -153,7 +75,11 @@ function mirageTools(ws) {
|
|
|
153
75
|
type: "text",
|
|
154
76
|
text: `[${out.path}] ${out.mimeType} (${String(out.bytes)} bytes)`
|
|
155
77
|
},
|
|
156
|
-
{
|
|
78
|
+
{
|
|
79
|
+
type: "file",
|
|
80
|
+
data: { type: "data", data: out.base64 },
|
|
81
|
+
mediaType: out.mimeType
|
|
82
|
+
}
|
|
157
83
|
]
|
|
158
84
|
};
|
|
159
85
|
}
|
package/dist/vercel/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/vercel/index.ts"],"sourcesContent":["// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n\nimport { encodeBase64, gnuDirname } from '@struktoai/mirage-core'\nimport type { Workspace } from '@struktoai/mirage-node'\nimport { tool } from 'ai'\nimport { z } from 'zod'\n\nasync function ensureParent(ws: Workspace, path: string): Promise<void> {\n const parent = gnuDirname(path)\n if (parent === '/' || parent === '' || parent === '.') return\n if (await ws.fs.exists(parent)) return\n await ensureParent(ws, parent)\n try {\n await ws.fs.mkdir(parent)\n } catch (err) {\n if (!(await ws.fs.exists(parent))) throw err\n }\n}\n\nconst TEXT_EXTS = new Set([\n 'txt',\n 'md',\n 'json',\n 'jsonl',\n 'yaml',\n 'yml',\n 'csv',\n 'tsv',\n 'xml',\n 'html',\n 'htm',\n 'js',\n 'mjs',\n 'cjs',\n 'ts',\n 'tsx',\n 'jsx',\n 'py',\n 'rb',\n 'rs',\n 'go',\n 'java',\n 'c',\n 'cpp',\n 'h',\n 'hpp',\n 'sh',\n 'bash',\n 'zsh',\n 'sql',\n 'log',\n 'env',\n 'ini',\n 'toml',\n 'conf',\n 'cfg',\n])\n\nconst PRESENTABLE_BINARY = new Set([\n 'application/pdf',\n 'image/jpeg',\n 'image/png',\n 'image/gif',\n 'image/webp',\n])\n\nfunction extOf(path: string): string {\n const dot = path.lastIndexOf('.')\n if (dot < 0) return ''\n return path.slice(dot + 1).toLowerCase()\n}\n\nfunction mimeFor(path: string): string {\n const ext = extOf(path)\n if (ext === 'json' || ext === 'jsonl') return 'application/json'\n if (ext === 'csv') return 'text/csv'\n if (ext === 'html' || ext === 'htm') return 'text/html'\n if (ext === 'md') return 'text/markdown'\n if (TEXT_EXTS.has(ext)) return 'text/plain'\n if (ext === 'png') return 'image/png'\n if (ext === 'jpg' || ext === 'jpeg') return 'image/jpeg'\n if (ext === 'gif') return 'image/gif'\n if (ext === 'webp') return 'image/webp'\n if (ext === 'pdf') return 'application/pdf'\n return 'application/octet-stream'\n}\n\nfunction isTextMime(mime: string): boolean {\n return mime.startsWith('text/') || mime === 'application/json'\n}\n\nfunction bytesToBase64(bytes: Uint8Array): string {\n return encodeBase64(bytes)\n}\n\ntype ReadFileResult =\n | { kind: 'text'; path: string; mimeType: string; content: string; bytes: number }\n | { kind: 'media'; path: string; mimeType: string; base64: string; bytes: number }\n | { kind: 'binary'; path: string; mimeType: string; bytes: number; note: string }\n | { error: string }\n\nfunction isError(r: ReadFileResult): r is { error: string } {\n return 'error' in r\n}\n\nexport function mirageTools(ws: Workspace) {\n return {\n execute: tool({\n description:\n 'Execute a shell command in the Mirage workspace and return stdout, stderr, and exitCode.',\n inputSchema: z.object({\n command: z.string().describe('The shell command to execute.'),\n }),\n execute: async ({ command }) => {\n const io = await ws.execute(command)\n return {\n stdout: io.stdoutText,\n stderr: io.stderrText,\n exitCode: io.exitCode,\n }\n },\n }),\n\n readFile: tool({\n description:\n 'Read a file from the Mirage workspace. Text files (utf-8 source/data) come back as text; PDFs and images (png/jpeg/gif/webp) come back as base64 media that is forwarded to the model as a multimodal attachment; other binaries return a metadata stub.',\n inputSchema: z.object({\n path: z.string().describe('Absolute path inside the workspace.'),\n }),\n execute: async ({ path }): Promise<ReadFileResult> => {\n let bytes: Uint8Array\n try {\n bytes = await ws.fs.readFile(path)\n } catch (err) {\n return { error: err instanceof Error ? err.message : String(err) }\n }\n const mimeType = mimeFor(path)\n if (isTextMime(mimeType)) {\n return {\n kind: 'text',\n path,\n mimeType,\n content: new TextDecoder('utf-8', { fatal: false }).decode(bytes),\n bytes: bytes.length,\n }\n }\n if (PRESENTABLE_BINARY.has(mimeType)) {\n return {\n kind: 'media',\n path,\n mimeType,\n base64: bytesToBase64(bytes),\n bytes: bytes.length,\n }\n }\n return {\n kind: 'binary',\n path,\n mimeType,\n bytes: bytes.length,\n note: `Binary file ${path} (${mimeType}, ${String(bytes.length)} bytes). Use the execute tool with shell commands (head, file, wc, od) to inspect.`,\n }\n },\n toModelOutput: ({ output }) => {\n const out: ReadFileResult = output\n if (isError(out)) return { type: 'error-text', value: out.error }\n if (out.kind === 'text') return { type: 'text', value: out.content }\n if (out.kind === 'media') {\n return {\n type: 'content',\n value: [\n {\n type: 'text',\n text: `[${out.path}] ${out.mimeType} (${String(out.bytes)} bytes)`,\n },\n { type: 'media', data: out.base64, mediaType: out.mimeType },\n ],\n }\n }\n return { type: 'text', value: out.note }\n },\n }),\n\n writeFile: tool({\n description:\n 'Write content to a file in the Mirage workspace. Creates missing parent directories.',\n inputSchema: z.object({\n path: z.string().describe('Absolute path inside the workspace.'),\n content: z.string().describe('UTF-8 text content to write.'),\n }),\n execute: async ({ path, content }) => {\n await ensureParent(ws, path)\n await ws.fs.writeFile(path, content)\n return { path }\n },\n }),\n\n editFile: tool({\n description:\n 'Replace a string inside an existing file. Errors if the string appears more than once unless replaceAll is true.',\n inputSchema: z.object({\n path: z.string().describe('Absolute path of the file to edit.'),\n oldString: z.string().describe('The exact string to replace.'),\n newString: z.string().describe('The replacement string.'),\n replaceAll: z\n .boolean()\n .optional()\n .describe('Replace every occurrence rather than requiring a unique match.'),\n }),\n execute: async ({ path, oldString, newString, replaceAll }) => {\n let current: string\n try {\n current = await ws.fs.readFileText(path)\n } catch {\n return { error: `Error: file '${path}' not found` }\n }\n const count = current.split(oldString).length - 1\n if (count === 0) {\n return { error: `Error: string not found in file: '${oldString}'` }\n }\n if (count > 1 && replaceAll !== true) {\n return {\n error: `Error: string '${oldString}' appears ${String(count)} times. Use replaceAll=true`,\n }\n }\n const next =\n replaceAll === true\n ? current.split(oldString).join(newString)\n : current.replace(oldString, newString)\n await ws.fs.writeFile(path, next)\n return { path, occurrences: replaceAll === true ? count : 1 }\n },\n }),\n\n ls: tool({\n description: 'List entries of a directory in the Mirage workspace.',\n inputSchema: z.object({\n path: z.string().describe('Absolute directory path inside the workspace.'),\n }),\n execute: async ({ path }) => {\n let entries: string[]\n try {\n entries = await ws.fs.readdir(path)\n } catch (err) {\n return { error: err instanceof Error ? err.message : String(err) }\n }\n const files: { path: string; is_dir: boolean }[] = []\n for (const entry of entries) {\n const isDir = await ws.fs.isDir(entry)\n files.push({ path: entry, is_dir: isDir })\n }\n return { files }\n },\n }),\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/vercel/index.ts"],"sourcesContent":["// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========\n\nimport { encodeBase64, gnuDirname, type Workspace } from '@struktoai/mirage-core'\nimport { tool, type ToolSet } from 'ai'\nimport { z } from 'zod'\nimport { readWorkspaceFile } from '../read-file.ts'\n\nasync function ensureParent(ws: Workspace, path: string): Promise<void> {\n const parent = gnuDirname(path)\n if (parent === '/' || parent === '' || parent === '.') return\n if (await ws.fs.exists(parent)) return\n await ensureParent(ws, parent)\n try {\n await ws.fs.mkdir(parent)\n } catch (err) {\n if (!(await ws.fs.exists(parent))) throw err\n }\n}\n\nfunction bytesToBase64(bytes: Uint8Array): string {\n return encodeBase64(bytes)\n}\n\ntype ReadFileResult =\n | { kind: 'text'; path: string; mimeType: string; content: string; bytes: number }\n | { kind: 'media'; path: string; mimeType: string; base64: string; bytes: number }\n | { kind: 'binary'; path: string; mimeType: string; bytes: number; note: string }\n | { error: string }\n\nfunction isError(r: ReadFileResult): r is { error: string } {\n return 'error' in r\n}\n\nasync function readFileResult(ws: Workspace, path: string): Promise<ReadFileResult> {\n try {\n const result = await readWorkspaceFile(ws, path)\n if (result.kind === 'text') return result\n if (result.kind === 'image' || result.kind === 'file') {\n return {\n kind: 'media',\n path: result.path,\n mimeType: result.mimeType,\n base64: bytesToBase64(result.data),\n bytes: result.bytes,\n }\n }\n return result\n } catch (error) {\n return { error: error instanceof Error ? error.message : String(error) }\n }\n}\n\nexport function mirageTools(ws: Workspace): ToolSet {\n return {\n execute: tool({\n description:\n 'Execute a shell command in the Mirage workspace and return stdout, stderr, and exitCode.',\n inputSchema: z.object({\n command: z.string().describe('The shell command to execute.'),\n }),\n execute: async ({ command }) => {\n const io = await ws.execute(command)\n return {\n stdout: io.stdoutText,\n stderr: io.stderrText,\n exitCode: io.exitCode,\n }\n },\n }),\n\n readFile: tool({\n description:\n 'Read a file from the Mirage workspace. Text files (utf-8 source/data) come back as text; PDFs and images (png/jpeg/gif/webp) come back as base64 media that is forwarded to the model as a multimodal attachment; other binaries return a metadata stub.',\n inputSchema: z.object({\n path: z.string().describe('Absolute path inside the workspace.'),\n }),\n execute: async ({ path }): Promise<ReadFileResult> => readFileResult(ws, path),\n toModelOutput: ({ output }) => {\n const out: ReadFileResult = output\n if (isError(out)) return { type: 'error-text', value: out.error }\n if (out.kind === 'text') return { type: 'text', value: out.content }\n if (out.kind === 'media') {\n return {\n type: 'content',\n value: [\n {\n type: 'text',\n text: `[${out.path}] ${out.mimeType} (${String(out.bytes)} bytes)`,\n },\n {\n type: 'file',\n data: { type: 'data', data: out.base64 },\n mediaType: out.mimeType,\n },\n ],\n }\n }\n return { type: 'text', value: out.note }\n },\n }),\n\n writeFile: tool({\n description:\n 'Write content to a file in the Mirage workspace. Creates missing parent directories.',\n inputSchema: z.object({\n path: z.string().describe('Absolute path inside the workspace.'),\n content: z.string().describe('UTF-8 text content to write.'),\n }),\n execute: async ({ path, content }) => {\n await ensureParent(ws, path)\n await ws.fs.writeFile(path, content)\n return { path }\n },\n }),\n\n editFile: tool({\n description:\n 'Replace a string inside an existing file. Errors if the string appears more than once unless replaceAll is true.',\n inputSchema: z.object({\n path: z.string().describe('Absolute path of the file to edit.'),\n oldString: z.string().describe('The exact string to replace.'),\n newString: z.string().describe('The replacement string.'),\n replaceAll: z\n .boolean()\n .optional()\n .describe('Replace every occurrence rather than requiring a unique match.'),\n }),\n execute: async ({ path, oldString, newString, replaceAll }) => {\n let current: string\n try {\n current = await ws.fs.readFileText(path)\n } catch {\n return { error: `Error: file '${path}' not found` }\n }\n const count = current.split(oldString).length - 1\n if (count === 0) {\n return { error: `Error: string not found in file: '${oldString}'` }\n }\n if (count > 1 && replaceAll !== true) {\n return {\n error: `Error: string '${oldString}' appears ${String(count)} times. Use replaceAll=true`,\n }\n }\n const next =\n replaceAll === true\n ? current.split(oldString).join(newString)\n : current.replace(oldString, newString)\n await ws.fs.writeFile(path, next)\n return { path, occurrences: replaceAll === true ? count : 1 }\n },\n }),\n\n ls: tool({\n description: 'List entries of a directory in the Mirage workspace.',\n inputSchema: z.object({\n path: z.string().describe('Absolute directory path inside the workspace.'),\n }),\n execute: async ({ path }) => {\n let entries: string[]\n try {\n entries = await ws.fs.readdir(path)\n } catch (err) {\n return { error: err instanceof Error ? err.message : String(err) }\n }\n const files: { path: string; is_dir: boolean }[] = []\n for (const entry of entries) {\n const isDir = await ws.fs.isDir(entry)\n files.push({ path: entry, is_dir: isDir })\n }\n return { files }\n },\n }),\n }\n}\n"],"mappings":"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","names":[]}
|