@mastra/core 1.16.1-alpha.0 → 1.17.0-alpha.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/CHANGELOG.md +128 -0
- package/dist/agent/index.cjs +8 -8
- package/dist/agent/index.js +1 -1
- package/dist/{chunk-XKOCRXCP.js → chunk-4UTQD6B5.js} +3 -3
- package/dist/{chunk-XKOCRXCP.js.map → chunk-4UTQD6B5.js.map} +1 -1
- package/dist/{chunk-WJEUD4JG.js → chunk-5TKRQNGW.js} +4 -4
- package/dist/{chunk-WJEUD4JG.js.map → chunk-5TKRQNGW.js.map} +1 -1
- package/dist/{chunk-BEDQJNIR.cjs → chunk-6HSR64XA.cjs} +15 -5
- package/dist/chunk-6HSR64XA.cjs.map +1 -0
- package/dist/{chunk-LFZXBZR5.cjs → chunk-76NWBCBU.cjs} +9 -9
- package/dist/{chunk-LFZXBZR5.cjs.map → chunk-76NWBCBU.cjs.map} +1 -1
- package/dist/{chunk-J3NJXIJ4.js → chunk-ABA3KD3X.js} +524 -246
- package/dist/chunk-ABA3KD3X.js.map +1 -0
- package/dist/{chunk-SNASZNHI.js → chunk-AGEYVARR.js} +2 -2
- package/dist/{chunk-SNASZNHI.js.map → chunk-AGEYVARR.js.map} +1 -1
- package/dist/{chunk-RQBBPR64.cjs → chunk-AH2ZNH4Y.cjs} +30 -28
- package/dist/chunk-AH2ZNH4Y.cjs.map +1 -0
- package/dist/{chunk-EXIQD6L3.cjs → chunk-AX5EPGND.cjs} +51 -51
- package/dist/{chunk-EXIQD6L3.cjs.map → chunk-AX5EPGND.cjs.map} +1 -1
- package/dist/{chunk-BSMSIRKQ.js → chunk-E7L2JB4A.js} +8 -8
- package/dist/{chunk-BSMSIRKQ.js.map → chunk-E7L2JB4A.js.map} +1 -1
- package/dist/{chunk-RLAMKAFZ.js → chunk-FLW4344C.js} +3 -3
- package/dist/{chunk-RLAMKAFZ.js.map → chunk-FLW4344C.js.map} +1 -1
- package/dist/{chunk-DKQA3ER2.cjs → chunk-I2Z4GKQ6.cjs} +15 -15
- package/dist/{chunk-DKQA3ER2.cjs.map → chunk-I2Z4GKQ6.cjs.map} +1 -1
- package/dist/{chunk-LO7V2FG6.cjs → chunk-ID5X55KA.cjs} +7 -7
- package/dist/{chunk-LO7V2FG6.cjs.map → chunk-ID5X55KA.cjs.map} +1 -1
- package/dist/{chunk-53YOAG3E.js → chunk-JMYTEYXJ.js} +5 -5
- package/dist/{chunk-53YOAG3E.js.map → chunk-JMYTEYXJ.js.map} +1 -1
- package/dist/{chunk-5TZP6NN4.js → chunk-K76OKOAK.js} +3 -3
- package/dist/{chunk-5TZP6NN4.js.map → chunk-K76OKOAK.js.map} +1 -1
- package/dist/{chunk-ZJMETLCP.js → chunk-LOGX3EQD.js} +30 -28
- package/dist/chunk-LOGX3EQD.js.map +1 -0
- package/dist/{chunk-BLBX5SP3.js → chunk-MNIWCQYZ.js} +4 -4
- package/dist/{chunk-BLBX5SP3.js.map → chunk-MNIWCQYZ.js.map} +1 -1
- package/dist/{chunk-DSFXGE5Y.cjs → chunk-O54IMECL.cjs} +185 -185
- package/dist/{chunk-DSFXGE5Y.cjs.map → chunk-O54IMECL.cjs.map} +1 -1
- package/dist/{chunk-OC5SNZ6R.cjs → chunk-OBHOUEDZ.cjs} +83 -83
- package/dist/{chunk-OC5SNZ6R.cjs.map → chunk-OBHOUEDZ.cjs.map} +1 -1
- package/dist/{chunk-OTQY4UJ4.js → chunk-OIZT4TON.js} +476 -27
- package/dist/chunk-OIZT4TON.js.map +1 -0
- package/dist/{chunk-LIVMJB3N.cjs → chunk-P54SNCAD.cjs} +3 -3
- package/dist/{chunk-LIVMJB3N.cjs.map → chunk-P54SNCAD.cjs.map} +1 -1
- package/dist/{chunk-DXRM6H35.js → chunk-PICHLY3C.js} +4 -4
- package/dist/{chunk-DXRM6H35.js.map → chunk-PICHLY3C.js.map} +1 -1
- package/dist/{chunk-7L2ICIDI.cjs → chunk-PQ4CVQXD.cjs} +6 -6
- package/dist/{chunk-7L2ICIDI.cjs.map → chunk-PQ4CVQXD.cjs.map} +1 -1
- package/dist/{chunk-O7JQYUXP.cjs → chunk-PTRJHO2K.cjs} +7 -7
- package/dist/{chunk-O7JQYUXP.cjs.map → chunk-PTRJHO2K.cjs.map} +1 -1
- package/dist/{chunk-SQACXTWK.cjs → chunk-QVQ3PGG2.cjs} +2 -2
- package/dist/{chunk-SQACXTWK.cjs.map → chunk-QVQ3PGG2.cjs.map} +1 -1
- package/dist/{chunk-XW4B2RAG.cjs → chunk-QVVWKMFM.cjs} +525 -248
- package/dist/chunk-QVVWKMFM.cjs.map +1 -0
- package/dist/{chunk-5S7MQ37C.cjs → chunk-R47HLGU7.cjs} +512 -61
- package/dist/chunk-R47HLGU7.cjs.map +1 -0
- package/dist/{chunk-R67VVUDR.cjs → chunk-SDSIVJMT.cjs} +16 -16
- package/dist/{chunk-R67VVUDR.cjs.map → chunk-SDSIVJMT.cjs.map} +1 -1
- package/dist/{chunk-UGXRRSSU.js → chunk-UOCBF4IP.js} +3 -3
- package/dist/{chunk-UGXRRSSU.js.map → chunk-UOCBF4IP.js.map} +1 -1
- package/dist/{chunk-GVHOPNRI.js → chunk-X234OVG3.js} +14 -4
- package/dist/chunk-X234OVG3.js.map +1 -0
- package/dist/{chunk-XVP3C4KW.cjs → chunk-XTN63GKI.cjs} +7 -7
- package/dist/{chunk-XVP3C4KW.cjs.map → chunk-XTN63GKI.cjs.map} +1 -1
- package/dist/{chunk-NJONWVEJ.js → chunk-YBNI2A6Y.js} +8 -8
- package/dist/{chunk-NJONWVEJ.js.map → chunk-YBNI2A6Y.js.map} +1 -1
- package/dist/{chunk-UXFQJJQG.js → chunk-ZT26XXEB.js} +5 -5
- package/dist/{chunk-UXFQJJQG.js.map → chunk-ZT26XXEB.js.map} +1 -1
- package/dist/datasets/index.cjs +17 -17
- package/dist/datasets/index.js +2 -2
- package/dist/docs/SKILL.md +4 -1
- package/dist/docs/assets/SOURCE_MAP.json +364 -354
- package/dist/docs/references/docs-memory-observational-memory.md +7 -5
- package/dist/docs/references/docs-observability-tracing-bridges-otel.md +3 -3
- package/dist/docs/references/docs-workspace-lsp.md +116 -0
- package/dist/docs/references/docs-workspace-overview.md +15 -1
- package/dist/docs/references/guides-agent-frameworks-ai-sdk.md +3 -3
- package/dist/docs/references/reference-ai-sdk-with-mastra.md +2 -2
- package/dist/docs/references/reference-auth-okta.md +162 -0
- package/dist/docs/references/reference-client-js-agents.md +2 -2
- package/dist/docs/references/reference-harness-harness-class.md +2 -0
- package/dist/docs/references/reference-memory-observational-memory.md +2 -2
- package/dist/docs/references/reference-observability-tracing-interfaces.md +1 -1
- package/dist/docs/references/reference-processors-message-history-processor.md +1 -1
- package/dist/docs/references/reference-processors-processor-interface.md +3 -3
- package/dist/docs/references/reference-processors-semantic-recall-processor.md +1 -1
- package/dist/docs/references/reference-processors-skill-search-processor.md +93 -0
- package/dist/docs/references/reference-processors-tool-call-filter.md +2 -2
- package/dist/docs/references/reference-processors-working-memory-processor.md +1 -1
- package/dist/docs/references/reference-tools-mcp-client.md +1 -1
- package/dist/docs/references/reference.md +2 -0
- package/dist/evals/index.cjs +20 -20
- package/dist/evals/index.js +3 -3
- package/dist/evals/scoreTraces/index.cjs +5 -5
- package/dist/evals/scoreTraces/index.js +2 -2
- package/dist/harness/harness.d.ts +4 -5
- package/dist/harness/harness.d.ts.map +1 -1
- package/dist/harness/index.cjs +44 -12
- package/dist/harness/index.cjs.map +1 -1
- package/dist/harness/index.d.ts +1 -1
- package/dist/harness/index.d.ts.map +1 -1
- package/dist/harness/index.js +39 -7
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/types.d.ts +18 -4
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.js +1 -1
- package/dist/llm/index.cjs +16 -16
- package/dist/llm/index.js +5 -5
- package/dist/llm/model/provider-types.generated.d.ts +5 -0
- package/dist/loop/index.cjs +14 -14
- package/dist/loop/index.js +1 -1
- package/dist/mastra/index.cjs +2 -2
- package/dist/mastra/index.js +1 -1
- package/dist/memory/index.cjs +14 -14
- package/dist/memory/index.js +1 -1
- package/dist/memory/types.d.ts +4 -0
- package/dist/memory/types.d.ts.map +1 -1
- package/dist/models-dev-DYILKQKY.js +3 -0
- package/dist/{models-dev-DMH6Y26P.js.map → models-dev-DYILKQKY.js.map} +1 -1
- package/dist/models-dev-EX67IAAF.cjs +12 -0
- package/dist/{models-dev-YEVVUBSG.cjs.map → models-dev-EX67IAAF.cjs.map} +1 -1
- package/dist/netlify-EDK4WKCW.cjs +12 -0
- package/dist/{netlify-CQVRCF2F.cjs.map → netlify-EDK4WKCW.cjs.map} +1 -1
- package/dist/netlify-RQLBHLLX.js +3 -0
- package/dist/{netlify-IAN7GQOF.js.map → netlify-RQLBHLLX.js.map} +1 -1
- package/dist/processor-provider/index.cjs +10 -10
- package/dist/processor-provider/index.js +1 -1
- package/dist/processors/index.cjs +50 -42
- package/dist/processors/index.js +1 -1
- package/dist/processors/processors/index.d.ts +2 -0
- package/dist/processors/processors/index.d.ts.map +1 -1
- package/dist/processors/processors/skill-search.d.ts +111 -0
- package/dist/processors/processors/skill-search.d.ts.map +1 -0
- package/dist/processors/tool-result-reminder.d.ts +32 -0
- package/dist/processors/tool-result-reminder.d.ts.map +1 -0
- package/dist/provider-registry-3RCP7DTQ.js +3 -0
- package/dist/{provider-registry-PBDYA2JQ.js.map → provider-registry-3RCP7DTQ.js.map} +1 -1
- package/dist/provider-registry-MBXOBTD4.cjs +40 -0
- package/dist/{provider-registry-CCLGCN3B.cjs.map → provider-registry-MBXOBTD4.cjs.map} +1 -1
- package/dist/provider-registry.json +10 -0
- package/dist/relevance/index.cjs +3 -3
- package/dist/relevance/index.js +1 -1
- package/dist/storage/constants.cjs +56 -56
- package/dist/storage/constants.js +1 -1
- package/dist/storage/index.cjs +160 -160
- package/dist/storage/index.js +2 -2
- package/dist/storage/types.d.ts +2 -0
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/stream/index.cjs +8 -8
- package/dist/stream/index.js +1 -1
- package/dist/test-utils/llm-mock.cjs +4 -4
- package/dist/test-utils/llm-mock.js +1 -1
- package/dist/tool-loop-agent/index.cjs +4 -4
- package/dist/tool-loop-agent/index.js +1 -1
- package/dist/tools/tool-builder/builder.d.ts.map +1 -1
- package/dist/utils.cjs +23 -23
- package/dist/utils.js +1 -1
- package/dist/vector/index.cjs +7 -7
- package/dist/vector/index.js +1 -1
- package/dist/workflows/evented/index.cjs +10 -10
- package/dist/workflows/evented/index.js +1 -1
- package/dist/workflows/index.cjs +24 -24
- package/dist/workflows/index.js +1 -1
- package/dist/workspace/constants/index.d.ts +4 -1
- package/dist/workspace/constants/index.d.ts.map +1 -1
- package/dist/workspace/index.cjs +68 -68
- package/dist/workspace/index.js +1 -1
- package/dist/workspace/lsp/client.d.ts +30 -0
- package/dist/workspace/lsp/client.d.ts.map +1 -1
- package/dist/workspace/lsp/manager.d.ts +11 -0
- package/dist/workspace/lsp/manager.d.ts.map +1 -1
- package/dist/workspace/tools/index.d.ts +1 -0
- package/dist/workspace/tools/index.d.ts.map +1 -1
- package/dist/workspace/tools/lsp-inspect.d.ts +13 -0
- package/dist/workspace/tools/lsp-inspect.d.ts.map +1 -0
- package/dist/workspace/tools/tools.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/llm/model/provider-types.generated.d.ts +5 -0
- package/dist/chunk-5S7MQ37C.cjs.map +0 -1
- package/dist/chunk-BEDQJNIR.cjs.map +0 -1
- package/dist/chunk-GVHOPNRI.js.map +0 -1
- package/dist/chunk-J3NJXIJ4.js.map +0 -1
- package/dist/chunk-OTQY4UJ4.js.map +0 -1
- package/dist/chunk-RQBBPR64.cjs.map +0 -1
- package/dist/chunk-XW4B2RAG.cjs.map +0 -1
- package/dist/chunk-ZJMETLCP.js.map +0 -1
- package/dist/models-dev-DMH6Y26P.js +0 -3
- package/dist/models-dev-YEVVUBSG.cjs +0 -12
- package/dist/netlify-CQVRCF2F.cjs +0 -12
- package/dist/netlify-IAN7GQOF.js +0 -3
- package/dist/provider-registry-CCLGCN3B.cjs +0 -40
- package/dist/provider-registry-PBDYA2JQ.js +0 -3
|
@@ -100,68 +100,68 @@ var WorkspaceReadOnlyError = class extends WorkspaceError {
|
|
|
100
100
|
}
|
|
101
101
|
};
|
|
102
102
|
var FilesystemError = class extends Error {
|
|
103
|
-
constructor(message, code,
|
|
103
|
+
constructor(message, code, path8) {
|
|
104
104
|
super(message);
|
|
105
105
|
this.code = code;
|
|
106
|
-
this.path =
|
|
106
|
+
this.path = path8;
|
|
107
107
|
this.name = "FilesystemError";
|
|
108
108
|
}
|
|
109
109
|
};
|
|
110
110
|
var FileNotFoundError = class extends FilesystemError {
|
|
111
|
-
constructor(
|
|
112
|
-
super(`File not found: ${
|
|
111
|
+
constructor(path8) {
|
|
112
|
+
super(`File not found: ${path8}`, "ENOENT", path8);
|
|
113
113
|
this.name = "FileNotFoundError";
|
|
114
114
|
}
|
|
115
115
|
};
|
|
116
116
|
var DirectoryNotFoundError = class extends FilesystemError {
|
|
117
|
-
constructor(
|
|
118
|
-
super(`Directory not found: ${
|
|
117
|
+
constructor(path8) {
|
|
118
|
+
super(`Directory not found: ${path8}`, "ENOENT", path8);
|
|
119
119
|
this.name = "DirectoryNotFoundError";
|
|
120
120
|
}
|
|
121
121
|
};
|
|
122
122
|
var FileExistsError = class extends FilesystemError {
|
|
123
|
-
constructor(
|
|
124
|
-
super(`File already exists: ${
|
|
123
|
+
constructor(path8) {
|
|
124
|
+
super(`File already exists: ${path8}`, "EEXIST", path8);
|
|
125
125
|
this.name = "FileExistsError";
|
|
126
126
|
}
|
|
127
127
|
};
|
|
128
128
|
var IsDirectoryError = class extends FilesystemError {
|
|
129
|
-
constructor(
|
|
130
|
-
super(`Path is a directory: ${
|
|
129
|
+
constructor(path8) {
|
|
130
|
+
super(`Path is a directory: ${path8}`, "EISDIR", path8);
|
|
131
131
|
this.name = "IsDirectoryError";
|
|
132
132
|
}
|
|
133
133
|
};
|
|
134
134
|
var NotDirectoryError = class extends FilesystemError {
|
|
135
|
-
constructor(
|
|
136
|
-
super(`Path is not a directory: ${
|
|
135
|
+
constructor(path8) {
|
|
136
|
+
super(`Path is not a directory: ${path8}`, "ENOTDIR", path8);
|
|
137
137
|
this.name = "NotDirectoryError";
|
|
138
138
|
}
|
|
139
139
|
};
|
|
140
140
|
var DirectoryNotEmptyError = class extends FilesystemError {
|
|
141
|
-
constructor(
|
|
142
|
-
super(`Directory not empty: ${
|
|
141
|
+
constructor(path8) {
|
|
142
|
+
super(`Directory not empty: ${path8}`, "ENOTEMPTY", path8);
|
|
143
143
|
this.name = "DirectoryNotEmptyError";
|
|
144
144
|
}
|
|
145
145
|
};
|
|
146
146
|
var PermissionError = class extends FilesystemError {
|
|
147
|
-
constructor(
|
|
148
|
-
super(`Permission denied: ${operation} on ${
|
|
147
|
+
constructor(path8, operation) {
|
|
148
|
+
super(`Permission denied: ${operation} on ${path8}`, "EACCES", path8);
|
|
149
149
|
this.operation = operation;
|
|
150
150
|
this.name = "PermissionError";
|
|
151
151
|
}
|
|
152
152
|
};
|
|
153
153
|
var FileReadRequiredError = class extends FilesystemError {
|
|
154
|
-
constructor(
|
|
155
|
-
super(reason, "EREAD_REQUIRED",
|
|
154
|
+
constructor(path8, reason) {
|
|
155
|
+
super(reason, "EREAD_REQUIRED", path8);
|
|
156
156
|
this.name = "FileReadRequiredError";
|
|
157
157
|
}
|
|
158
158
|
};
|
|
159
159
|
var StaleFileError = class extends FilesystemError {
|
|
160
|
-
constructor(
|
|
160
|
+
constructor(path8, expectedMtime, actualMtime) {
|
|
161
161
|
super(
|
|
162
|
-
`File was modified externally: ${
|
|
162
|
+
`File was modified externally: ${path8} (expected mtime ${expectedMtime.toISOString()}, actual ${actualMtime.toISOString()})`,
|
|
163
163
|
"ESTALE",
|
|
164
|
-
|
|
164
|
+
path8
|
|
165
165
|
);
|
|
166
166
|
this.expectedMtime = expectedMtime;
|
|
167
167
|
this.actualMtime = actualMtime;
|
|
@@ -200,14 +200,14 @@ var CompositeFilesystem = class {
|
|
|
200
200
|
constructor(config) {
|
|
201
201
|
this.id = `cfs-${Date.now().toString(36)}`;
|
|
202
202
|
this._mounts = /* @__PURE__ */ new Map();
|
|
203
|
-
for (const [
|
|
204
|
-
const normalized = this.normalizePath(
|
|
205
|
-
this._mounts.set(normalized,
|
|
203
|
+
for (const [path8, fs6] of Object.entries(config.mounts)) {
|
|
204
|
+
const normalized = this.normalizePath(path8);
|
|
205
|
+
this._mounts.set(normalized, fs6);
|
|
206
206
|
}
|
|
207
207
|
if (this._mounts.size === 0) {
|
|
208
208
|
throw new Error("CompositeFilesystem requires at least one mount");
|
|
209
209
|
}
|
|
210
|
-
this.readOnly = [...this._mounts.values()].every((
|
|
210
|
+
this.readOnly = [...this._mounts.values()].every((fs6) => fs6.readOnly) || void 0;
|
|
211
211
|
const mountPaths = [...this._mounts.keys()];
|
|
212
212
|
for (const a of mountPaths) {
|
|
213
213
|
for (const b of mountPaths) {
|
|
@@ -236,8 +236,8 @@ var CompositeFilesystem = class {
|
|
|
236
236
|
*/
|
|
237
237
|
async getInfo() {
|
|
238
238
|
const mounts = {};
|
|
239
|
-
for (const [mountPath,
|
|
240
|
-
mounts[mountPath] = await
|
|
239
|
+
for (const [mountPath, fs6] of this._mounts) {
|
|
240
|
+
mounts[mountPath] = await fs6.getInfo?.() ?? null;
|
|
241
241
|
}
|
|
242
242
|
return {
|
|
243
243
|
id: this.id,
|
|
@@ -252,42 +252,42 @@ var CompositeFilesystem = class {
|
|
|
252
252
|
* Get the underlying filesystem for a given path.
|
|
253
253
|
* Returns undefined if the path doesn't resolve to any mount.
|
|
254
254
|
*/
|
|
255
|
-
getFilesystemForPath(
|
|
256
|
-
const resolved = this.resolveMount(
|
|
255
|
+
getFilesystemForPath(path8) {
|
|
256
|
+
const resolved = this.resolveMount(path8);
|
|
257
257
|
return resolved?.fs;
|
|
258
258
|
}
|
|
259
259
|
/**
|
|
260
260
|
* Get the mount path for a given path.
|
|
261
261
|
* Returns undefined if the path doesn't resolve to any mount.
|
|
262
262
|
*/
|
|
263
|
-
getMountPathForPath(
|
|
264
|
-
const resolved = this.resolveMount(
|
|
263
|
+
getMountPathForPath(path8) {
|
|
264
|
+
const resolved = this.resolveMount(path8);
|
|
265
265
|
return resolved?.mountPath;
|
|
266
266
|
}
|
|
267
267
|
/**
|
|
268
268
|
* Resolve a workspace-relative path to an absolute disk path.
|
|
269
269
|
* Strips the mount prefix and delegates to the underlying filesystem.
|
|
270
270
|
*/
|
|
271
|
-
resolveAbsolutePath(
|
|
272
|
-
const r = this.resolveMount(
|
|
271
|
+
resolveAbsolutePath(path8) {
|
|
272
|
+
const r = this.resolveMount(path8);
|
|
273
273
|
if (!r) return void 0;
|
|
274
274
|
return r.fs.resolveAbsolutePath?.(r.fsPath);
|
|
275
275
|
}
|
|
276
|
-
normalizePath(
|
|
277
|
-
if (!
|
|
278
|
-
let n = posixPath__default.default.normalize(
|
|
276
|
+
normalizePath(path8) {
|
|
277
|
+
if (!path8 || path8 === "/" || path8 === ".") return "/";
|
|
278
|
+
let n = posixPath__default.default.normalize(path8);
|
|
279
279
|
if (n === ".") return "/";
|
|
280
280
|
if (!n.startsWith("/")) n = `/${n}`;
|
|
281
281
|
if (n.length > 1 && n.endsWith("/")) n = n.slice(0, -1);
|
|
282
282
|
return n;
|
|
283
283
|
}
|
|
284
|
-
resolveMount(
|
|
285
|
-
const normalized = this.normalizePath(
|
|
284
|
+
resolveMount(path8) {
|
|
285
|
+
const normalized = this.normalizePath(path8);
|
|
286
286
|
let best = null;
|
|
287
|
-
for (const [mountPath,
|
|
287
|
+
for (const [mountPath, fs6] of this._mounts) {
|
|
288
288
|
if (normalized === mountPath || normalized.startsWith(mountPath + "/")) {
|
|
289
289
|
if (!best || mountPath.length > best.mountPath.length) {
|
|
290
|
-
best = { mountPath, fs:
|
|
290
|
+
best = { mountPath, fs: fs6 };
|
|
291
291
|
}
|
|
292
292
|
}
|
|
293
293
|
}
|
|
@@ -297,11 +297,11 @@ var CompositeFilesystem = class {
|
|
|
297
297
|
else if (fsPath.startsWith("/")) fsPath = fsPath.slice(1);
|
|
298
298
|
return { fs: best.fs, fsPath, mountPath: best.mountPath };
|
|
299
299
|
}
|
|
300
|
-
getVirtualEntries(
|
|
301
|
-
const normalized = this.normalizePath(
|
|
300
|
+
getVirtualEntries(path8) {
|
|
301
|
+
const normalized = this.normalizePath(path8);
|
|
302
302
|
if (this.resolveMount(normalized)) return null;
|
|
303
303
|
const entriesMap = /* @__PURE__ */ new Map();
|
|
304
|
-
for (const [mountPath,
|
|
304
|
+
for (const [mountPath, fs6] of this._mounts.entries()) {
|
|
305
305
|
const isUnder = normalized === "/" ? mountPath.startsWith("/") : mountPath.startsWith(normalized + "/");
|
|
306
306
|
if (isUnder) {
|
|
307
307
|
const remaining = normalized === "/" ? mountPath.slice(1) : mountPath.slice(normalized.length + 1);
|
|
@@ -311,12 +311,12 @@ var CompositeFilesystem = class {
|
|
|
311
311
|
const entry = { name: next, type: "directory" };
|
|
312
312
|
if (isDirectMount) {
|
|
313
313
|
entry.mount = {
|
|
314
|
-
provider:
|
|
315
|
-
icon:
|
|
316
|
-
displayName:
|
|
317
|
-
description:
|
|
318
|
-
status:
|
|
319
|
-
error:
|
|
314
|
+
provider: fs6.provider,
|
|
315
|
+
icon: fs6.icon,
|
|
316
|
+
displayName: fs6.displayName,
|
|
317
|
+
description: fs6.description,
|
|
318
|
+
status: fs6.status,
|
|
319
|
+
error: fs6.error
|
|
320
320
|
};
|
|
321
321
|
}
|
|
322
322
|
entriesMap.set(next, entry);
|
|
@@ -325,8 +325,8 @@ var CompositeFilesystem = class {
|
|
|
325
325
|
}
|
|
326
326
|
return entriesMap.size > 0 ? Array.from(entriesMap.values()) : null;
|
|
327
327
|
}
|
|
328
|
-
isVirtualPath(
|
|
329
|
-
const normalized = this.normalizePath(
|
|
328
|
+
isVirtualPath(path8) {
|
|
329
|
+
const normalized = this.normalizePath(path8);
|
|
330
330
|
if (normalized === "/" && !this._mounts.has("/")) return true;
|
|
331
331
|
for (const mountPath of this._mounts.keys()) {
|
|
332
332
|
if (mountPath.startsWith(normalized + "/")) return true;
|
|
@@ -337,9 +337,9 @@ var CompositeFilesystem = class {
|
|
|
337
337
|
* Assert that a filesystem is writable (not read-only).
|
|
338
338
|
* @throws {PermissionError} if the filesystem is read-only
|
|
339
339
|
*/
|
|
340
|
-
assertWritable(
|
|
341
|
-
if (
|
|
342
|
-
throw new PermissionError(
|
|
340
|
+
assertWritable(fs6, path8, operation) {
|
|
341
|
+
if (fs6.readOnly) {
|
|
342
|
+
throw new PermissionError(path8, `${operation} (filesystem is read-only)`);
|
|
343
343
|
}
|
|
344
344
|
}
|
|
345
345
|
// ===========================================================================
|
|
@@ -347,9 +347,9 @@ var CompositeFilesystem = class {
|
|
|
347
347
|
// ===========================================================================
|
|
348
348
|
async init() {
|
|
349
349
|
this.status = "initializing";
|
|
350
|
-
for (const [mountPath,
|
|
350
|
+
for (const [mountPath, fs6] of this._mounts.entries()) {
|
|
351
351
|
try {
|
|
352
|
-
await callLifecycle(
|
|
352
|
+
await callLifecycle(fs6, "init");
|
|
353
353
|
} catch (e) {
|
|
354
354
|
const message = e instanceof Error ? e.message : String(e);
|
|
355
355
|
console.warn(`[CompositeFilesystem] Mount "${mountPath}" failed to initialize: ${message}`);
|
|
@@ -360,9 +360,9 @@ var CompositeFilesystem = class {
|
|
|
360
360
|
async destroy() {
|
|
361
361
|
this.status = "destroying";
|
|
362
362
|
const errors = [];
|
|
363
|
-
for (const
|
|
363
|
+
for (const fs6 of this._mounts.values()) {
|
|
364
364
|
try {
|
|
365
|
-
await callLifecycle(
|
|
365
|
+
await callLifecycle(fs6, "destroy");
|
|
366
366
|
} catch (e) {
|
|
367
367
|
errors.push(e instanceof Error ? e : new Error(String(e)));
|
|
368
368
|
}
|
|
@@ -373,27 +373,27 @@ var CompositeFilesystem = class {
|
|
|
373
373
|
}
|
|
374
374
|
this.status = "destroyed";
|
|
375
375
|
}
|
|
376
|
-
async readFile(
|
|
377
|
-
const r = this.resolveMount(
|
|
378
|
-
if (!r) throw new Error(`No mount for path: ${
|
|
376
|
+
async readFile(path8, options) {
|
|
377
|
+
const r = this.resolveMount(path8);
|
|
378
|
+
if (!r) throw new Error(`No mount for path: ${path8}`);
|
|
379
379
|
return r.fs.readFile(r.fsPath, options);
|
|
380
380
|
}
|
|
381
|
-
async writeFile(
|
|
382
|
-
const r = this.resolveMount(
|
|
383
|
-
if (!r) throw new Error(`No mount for path: ${
|
|
384
|
-
this.assertWritable(r.fs,
|
|
381
|
+
async writeFile(path8, content, options) {
|
|
382
|
+
const r = this.resolveMount(path8);
|
|
383
|
+
if (!r) throw new Error(`No mount for path: ${path8}`);
|
|
384
|
+
this.assertWritable(r.fs, path8, "writeFile");
|
|
385
385
|
return r.fs.writeFile(r.fsPath, content, options);
|
|
386
386
|
}
|
|
387
|
-
async appendFile(
|
|
388
|
-
const r = this.resolveMount(
|
|
389
|
-
if (!r) throw new Error(`No mount for path: ${
|
|
390
|
-
this.assertWritable(r.fs,
|
|
387
|
+
async appendFile(path8, content) {
|
|
388
|
+
const r = this.resolveMount(path8);
|
|
389
|
+
if (!r) throw new Error(`No mount for path: ${path8}`);
|
|
390
|
+
this.assertWritable(r.fs, path8, "appendFile");
|
|
391
391
|
return r.fs.appendFile(r.fsPath, content);
|
|
392
392
|
}
|
|
393
|
-
async deleteFile(
|
|
394
|
-
const r = this.resolveMount(
|
|
395
|
-
if (!r) throw new Error(`No mount for path: ${
|
|
396
|
-
this.assertWritable(r.fs,
|
|
393
|
+
async deleteFile(path8, options) {
|
|
394
|
+
const r = this.resolveMount(path8);
|
|
395
|
+
if (!r) throw new Error(`No mount for path: ${path8}`);
|
|
396
|
+
this.assertWritable(r.fs, path8, "deleteFile");
|
|
397
397
|
return r.fs.deleteFile(r.fsPath, options);
|
|
398
398
|
}
|
|
399
399
|
async copyFile(src, dest, options) {
|
|
@@ -421,35 +421,35 @@ var CompositeFilesystem = class {
|
|
|
421
421
|
await this.copyFile(src, dest, options);
|
|
422
422
|
await srcR.fs.deleteFile(srcR.fsPath);
|
|
423
423
|
}
|
|
424
|
-
async readdir(
|
|
425
|
-
const virtual = this.getVirtualEntries(
|
|
424
|
+
async readdir(path8, options) {
|
|
425
|
+
const virtual = this.getVirtualEntries(path8);
|
|
426
426
|
if (virtual) return virtual;
|
|
427
|
-
const r = this.resolveMount(
|
|
428
|
-
if (!r) throw new Error(`No mount for path: ${
|
|
427
|
+
const r = this.resolveMount(path8);
|
|
428
|
+
if (!r) throw new Error(`No mount for path: ${path8}`);
|
|
429
429
|
return r.fs.readdir(r.fsPath, options);
|
|
430
430
|
}
|
|
431
|
-
async mkdir(
|
|
432
|
-
const r = this.resolveMount(
|
|
433
|
-
if (!r) throw new Error(`No mount for path: ${
|
|
434
|
-
this.assertWritable(r.fs,
|
|
431
|
+
async mkdir(path8, options) {
|
|
432
|
+
const r = this.resolveMount(path8);
|
|
433
|
+
if (!r) throw new Error(`No mount for path: ${path8}`);
|
|
434
|
+
this.assertWritable(r.fs, path8, "mkdir");
|
|
435
435
|
return r.fs.mkdir(r.fsPath, options);
|
|
436
436
|
}
|
|
437
|
-
async rmdir(
|
|
438
|
-
const r = this.resolveMount(
|
|
439
|
-
if (!r) throw new Error(`No mount for path: ${
|
|
440
|
-
this.assertWritable(r.fs,
|
|
437
|
+
async rmdir(path8, options) {
|
|
438
|
+
const r = this.resolveMount(path8);
|
|
439
|
+
if (!r) throw new Error(`No mount for path: ${path8}`);
|
|
440
|
+
this.assertWritable(r.fs, path8, "rmdir");
|
|
441
441
|
return r.fs.rmdir(r.fsPath, options);
|
|
442
442
|
}
|
|
443
|
-
async exists(
|
|
444
|
-
if (this.isVirtualPath(
|
|
445
|
-
const r = this.resolveMount(
|
|
443
|
+
async exists(path8) {
|
|
444
|
+
if (this.isVirtualPath(path8)) return true;
|
|
445
|
+
const r = this.resolveMount(path8);
|
|
446
446
|
if (!r) return false;
|
|
447
447
|
if (r.fsPath === "") return true;
|
|
448
448
|
return r.fs.exists(r.fsPath);
|
|
449
449
|
}
|
|
450
|
-
async stat(
|
|
451
|
-
const normalized = this.normalizePath(
|
|
452
|
-
if (this.isVirtualPath(
|
|
450
|
+
async stat(path8) {
|
|
451
|
+
const normalized = this.normalizePath(path8);
|
|
452
|
+
if (this.isVirtualPath(path8)) {
|
|
453
453
|
const parts = normalized.split("/").filter(Boolean);
|
|
454
454
|
const now = /* @__PURE__ */ new Date();
|
|
455
455
|
return {
|
|
@@ -461,8 +461,8 @@ var CompositeFilesystem = class {
|
|
|
461
461
|
modifiedAt: now
|
|
462
462
|
};
|
|
463
463
|
}
|
|
464
|
-
const r = this.resolveMount(
|
|
465
|
-
if (!r) throw new Error(`No mount for path: ${
|
|
464
|
+
const r = this.resolveMount(path8);
|
|
465
|
+
if (!r) throw new Error(`No mount for path: ${path8}`);
|
|
466
466
|
if (r.fsPath === "") {
|
|
467
467
|
const parts = normalized.split("/").filter(Boolean);
|
|
468
468
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -477,9 +477,9 @@ var CompositeFilesystem = class {
|
|
|
477
477
|
}
|
|
478
478
|
return r.fs.stat(r.fsPath);
|
|
479
479
|
}
|
|
480
|
-
async isFile(
|
|
481
|
-
if (this.isVirtualPath(
|
|
482
|
-
const r = this.resolveMount(
|
|
480
|
+
async isFile(path8) {
|
|
481
|
+
if (this.isVirtualPath(path8)) return false;
|
|
482
|
+
const r = this.resolveMount(path8);
|
|
483
483
|
if (!r) return false;
|
|
484
484
|
try {
|
|
485
485
|
const stat3 = await r.fs.stat(r.fsPath);
|
|
@@ -488,9 +488,9 @@ var CompositeFilesystem = class {
|
|
|
488
488
|
return false;
|
|
489
489
|
}
|
|
490
490
|
}
|
|
491
|
-
async isDirectory(
|
|
492
|
-
if (this.isVirtualPath(
|
|
493
|
-
const r = this.resolveMount(
|
|
491
|
+
async isDirectory(path8) {
|
|
492
|
+
if (this.isVirtualPath(path8)) return true;
|
|
493
|
+
const r = this.resolveMount(path8);
|
|
494
494
|
if (!r) return false;
|
|
495
495
|
if (r.fsPath === "") return true;
|
|
496
496
|
try {
|
|
@@ -505,9 +505,9 @@ var CompositeFilesystem = class {
|
|
|
505
505
|
* Used by agents to understand available storage locations.
|
|
506
506
|
*/
|
|
507
507
|
getInstructions(_opts) {
|
|
508
|
-
const mountDescriptions = Array.from(this._mounts.entries()).map(([mountPath,
|
|
509
|
-
const name =
|
|
510
|
-
const access3 =
|
|
508
|
+
const mountDescriptions = Array.from(this._mounts.entries()).map(([mountPath, fs6]) => {
|
|
509
|
+
const name = fs6.displayName || fs6.provider;
|
|
510
|
+
const access3 = fs6.readOnly ? "(read-only)" : "(read-write)";
|
|
511
511
|
return `- ${mountPath}: ${name} ${access3}`;
|
|
512
512
|
}).join("\n");
|
|
513
513
|
return `Filesystem mount points:
|
|
@@ -1375,35 +1375,35 @@ var LocalFilesystem = class extends MastraFilesystem {
|
|
|
1375
1375
|
};
|
|
1376
1376
|
var InMemoryFileReadTracker = class {
|
|
1377
1377
|
records = /* @__PURE__ */ new Map();
|
|
1378
|
-
recordRead(
|
|
1379
|
-
const normalizedPath = this.normalizePath(
|
|
1378
|
+
recordRead(path8, modifiedAt) {
|
|
1379
|
+
const normalizedPath = this.normalizePath(path8);
|
|
1380
1380
|
this.records.set(normalizedPath, {
|
|
1381
1381
|
path: normalizedPath,
|
|
1382
1382
|
readAt: /* @__PURE__ */ new Date(),
|
|
1383
1383
|
modifiedAtRead: modifiedAt
|
|
1384
1384
|
});
|
|
1385
1385
|
}
|
|
1386
|
-
getReadRecord(
|
|
1387
|
-
return this.records.get(this.normalizePath(
|
|
1386
|
+
getReadRecord(path8) {
|
|
1387
|
+
return this.records.get(this.normalizePath(path8));
|
|
1388
1388
|
}
|
|
1389
|
-
needsReRead(
|
|
1390
|
-
const record = this.getReadRecord(
|
|
1389
|
+
needsReRead(path8, currentModifiedAt) {
|
|
1390
|
+
const record = this.getReadRecord(path8);
|
|
1391
1391
|
if (!record) {
|
|
1392
1392
|
return {
|
|
1393
1393
|
needsReRead: true,
|
|
1394
|
-
reason: `File "${
|
|
1394
|
+
reason: `File "${path8}" has not been read. You must read a file before writing to it.`
|
|
1395
1395
|
};
|
|
1396
1396
|
}
|
|
1397
1397
|
if (currentModifiedAt.getTime() > record.modifiedAtRead.getTime()) {
|
|
1398
1398
|
return {
|
|
1399
1399
|
needsReRead: true,
|
|
1400
|
-
reason: `File "${
|
|
1400
|
+
reason: `File "${path8}" was modified since last read (read at: ${record.modifiedAtRead.toISOString()}, current: ${currentModifiedAt.toISOString()}). Please re-read the file to get the latest contents.`
|
|
1401
1401
|
};
|
|
1402
1402
|
}
|
|
1403
1403
|
return { needsReRead: false };
|
|
1404
1404
|
}
|
|
1405
|
-
clearReadRecord(
|
|
1406
|
-
this.records.delete(this.normalizePath(
|
|
1405
|
+
clearReadRecord(path8) {
|
|
1406
|
+
this.records.delete(this.normalizePath(path8));
|
|
1407
1407
|
}
|
|
1408
1408
|
clear() {
|
|
1409
1409
|
this.records.clear();
|
|
@@ -1491,10 +1491,10 @@ function createGlobMatcher(patterns, options) {
|
|
|
1491
1491
|
posix: true,
|
|
1492
1492
|
dot: options?.dot ?? false
|
|
1493
1493
|
});
|
|
1494
|
-
return (
|
|
1494
|
+
return (path8) => matcher(normalizeForMatch(path8));
|
|
1495
1495
|
}
|
|
1496
|
-
function matchGlob(
|
|
1497
|
-
return createGlobMatcher(pattern, options)(
|
|
1496
|
+
function matchGlob(path8, pattern, options) {
|
|
1497
|
+
return createGlobMatcher(pattern, options)(path8);
|
|
1498
1498
|
}
|
|
1499
1499
|
async function walkAll(readdir4, dir, depth, maxDepth) {
|
|
1500
1500
|
if (depth >= maxDepth) return [];
|
|
@@ -1584,7 +1584,7 @@ function isLSPAvailable() {
|
|
|
1584
1584
|
return jsonrpcModule !== null;
|
|
1585
1585
|
}
|
|
1586
1586
|
try {
|
|
1587
|
-
const req = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-
|
|
1587
|
+
const req = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-QVVWKMFM.cjs', document.baseURI).href)));
|
|
1588
1588
|
req.resolve("vscode-jsonrpc/node");
|
|
1589
1589
|
req.resolve("vscode-languageserver-protocol");
|
|
1590
1590
|
return true;
|
|
@@ -1598,7 +1598,7 @@ async function loadLSPDeps() {
|
|
|
1598
1598
|
return { ...jsonrpcModule, ...lspProtocolModule };
|
|
1599
1599
|
}
|
|
1600
1600
|
try {
|
|
1601
|
-
const req = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-
|
|
1601
|
+
const req = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-QVVWKMFM.cjs', document.baseURI).href)));
|
|
1602
1602
|
const jsonrpc = req("vscode-jsonrpc/node");
|
|
1603
1603
|
const protocol = req("vscode-languageserver-protocol");
|
|
1604
1604
|
jsonrpcModule = {
|
|
@@ -1620,6 +1620,15 @@ async function loadLSPDeps() {
|
|
|
1620
1620
|
function toFileUri(fsPath) {
|
|
1621
1621
|
return url.pathToFileURL(fsPath).toString();
|
|
1622
1622
|
}
|
|
1623
|
+
async function withTimeout(promise, ms, errorMessage) {
|
|
1624
|
+
let timer;
|
|
1625
|
+
return Promise.race([
|
|
1626
|
+
promise,
|
|
1627
|
+
new Promise((_, reject) => {
|
|
1628
|
+
timer = setTimeout(() => reject(new Error(errorMessage)), ms);
|
|
1629
|
+
})
|
|
1630
|
+
]).finally(() => clearTimeout(timer));
|
|
1631
|
+
}
|
|
1623
1632
|
var LSPClient = class {
|
|
1624
1633
|
connection = null;
|
|
1625
1634
|
handle = null;
|
|
@@ -1637,6 +1646,10 @@ var LSPClient = class {
|
|
|
1637
1646
|
get isAlive() {
|
|
1638
1647
|
return this.handle !== null && this.handle.exitCode === void 0;
|
|
1639
1648
|
}
|
|
1649
|
+
/** Name of the LSP server. */
|
|
1650
|
+
get serverName() {
|
|
1651
|
+
return this.serverDef.name;
|
|
1652
|
+
}
|
|
1640
1653
|
/**
|
|
1641
1654
|
* Initialize the LSP connection — spawns the server and performs the handshake.
|
|
1642
1655
|
*/
|
|
@@ -1808,6 +1821,56 @@ var LSPClient = class {
|
|
|
1808
1821
|
textDocument: { uri }
|
|
1809
1822
|
});
|
|
1810
1823
|
}
|
|
1824
|
+
/**
|
|
1825
|
+
* Query hover information at a position.
|
|
1826
|
+
*/
|
|
1827
|
+
async queryHover(uri, position, timeoutMs = 5e3) {
|
|
1828
|
+
if (!this.connection) return null;
|
|
1829
|
+
return withTimeout(
|
|
1830
|
+
this.connection.sendRequest("textDocument/hover", { textDocument: { uri }, position }),
|
|
1831
|
+
timeoutMs,
|
|
1832
|
+
"Hover request timed out"
|
|
1833
|
+
);
|
|
1834
|
+
}
|
|
1835
|
+
/**
|
|
1836
|
+
* Query definition(s) at a position.
|
|
1837
|
+
*/
|
|
1838
|
+
async queryDefinition(uri, position, timeoutMs = 5e3) {
|
|
1839
|
+
if (!this.connection) return [];
|
|
1840
|
+
const result = await withTimeout(
|
|
1841
|
+
this.connection.sendRequest("textDocument/definition", { textDocument: { uri }, position }),
|
|
1842
|
+
timeoutMs,
|
|
1843
|
+
"Definition request timed out"
|
|
1844
|
+
);
|
|
1845
|
+
if (!result) return [];
|
|
1846
|
+
return Array.isArray(result) ? result : result.uri ? [result] : [];
|
|
1847
|
+
}
|
|
1848
|
+
/**
|
|
1849
|
+
* Query type definition(s) at a position.
|
|
1850
|
+
*/
|
|
1851
|
+
async queryTypeDefinition(uri, position, timeoutMs = 5e3) {
|
|
1852
|
+
if (!this.connection) return [];
|
|
1853
|
+
const result = await withTimeout(
|
|
1854
|
+
this.connection.sendRequest("textDocument/typeDefinition", { textDocument: { uri }, position }),
|
|
1855
|
+
timeoutMs,
|
|
1856
|
+
"Type definition request timed out"
|
|
1857
|
+
);
|
|
1858
|
+
if (!result) return [];
|
|
1859
|
+
return Array.isArray(result) ? result : result.uri ? [result] : [];
|
|
1860
|
+
}
|
|
1861
|
+
/**
|
|
1862
|
+
* Query implementation(s) at a position.
|
|
1863
|
+
*/
|
|
1864
|
+
async queryImplementation(uri, position, timeoutMs = 5e3) {
|
|
1865
|
+
if (!this.connection) return [];
|
|
1866
|
+
const result = await withTimeout(
|
|
1867
|
+
this.connection.sendRequest("textDocument/implementation", { textDocument: { uri }, position }),
|
|
1868
|
+
timeoutMs,
|
|
1869
|
+
"Implementation request timed out"
|
|
1870
|
+
);
|
|
1871
|
+
if (!result) return [];
|
|
1872
|
+
return Array.isArray(result) ? result : result.uri ? [result] : [];
|
|
1873
|
+
}
|
|
1811
1874
|
/**
|
|
1812
1875
|
* Shutdown the connection and kill the process.
|
|
1813
1876
|
*/
|
|
@@ -1903,12 +1966,12 @@ function walkUp(startDir, markers) {
|
|
|
1903
1966
|
}
|
|
1904
1967
|
return null;
|
|
1905
1968
|
}
|
|
1906
|
-
async function walkUpAsync(startDir, markers,
|
|
1969
|
+
async function walkUpAsync(startDir, markers, fs6) {
|
|
1907
1970
|
let current = startDir;
|
|
1908
1971
|
const fsRoot = nodePath.parse(current).root;
|
|
1909
1972
|
while (true) {
|
|
1910
1973
|
for (const marker of markers) {
|
|
1911
|
-
if (await
|
|
1974
|
+
if (await fs6.exists(nodePath.join(current, marker))) {
|
|
1912
1975
|
return current;
|
|
1913
1976
|
}
|
|
1914
1977
|
}
|
|
@@ -2155,6 +2218,28 @@ var LSPManager = class {
|
|
|
2155
2218
|
}
|
|
2156
2219
|
return this.initClient(serverDef, projectRoot, key);
|
|
2157
2220
|
}
|
|
2221
|
+
/**
|
|
2222
|
+
* Get LSP client ready to query a file.
|
|
2223
|
+
* Opens the file in the client so queries can be made.
|
|
2224
|
+
* Returns null when no LSP client is available.
|
|
2225
|
+
*/
|
|
2226
|
+
async prepareQuery(filePath) {
|
|
2227
|
+
const client = await this.getClient(filePath);
|
|
2228
|
+
if (!client) return null;
|
|
2229
|
+
const languageId = getLanguageId(filePath);
|
|
2230
|
+
if (!languageId) return null;
|
|
2231
|
+
const fs6 = await import('fs/promises');
|
|
2232
|
+
let content = "";
|
|
2233
|
+
try {
|
|
2234
|
+
content = await fs6.readFile(filePath, "utf-8");
|
|
2235
|
+
} catch {
|
|
2236
|
+
content = "";
|
|
2237
|
+
}
|
|
2238
|
+
client.notifyOpen(filePath, content, languageId);
|
|
2239
|
+
const { pathToFileURL: pathToFileURL3 } = await import('url');
|
|
2240
|
+
const uri = pathToFileURL3(filePath).toString();
|
|
2241
|
+
return { client, uri, languageId, serverName: client.serverName };
|
|
2242
|
+
}
|
|
2158
2243
|
/**
|
|
2159
2244
|
* Convenience method: open file, send content, wait for diagnostics, return normalized results.
|
|
2160
2245
|
* Returns null when no LSP client is available; otherwise returns diagnostics
|
|
@@ -2738,14 +2823,14 @@ var MountManager = class {
|
|
|
2738
2823
|
/**
|
|
2739
2824
|
* Get a mount entry by path.
|
|
2740
2825
|
*/
|
|
2741
|
-
get(
|
|
2742
|
-
return this._entries.get(
|
|
2826
|
+
get(path8) {
|
|
2827
|
+
return this._entries.get(path8);
|
|
2743
2828
|
}
|
|
2744
2829
|
/**
|
|
2745
2830
|
* Check if a mount exists at the given path.
|
|
2746
2831
|
*/
|
|
2747
|
-
has(
|
|
2748
|
-
return this._entries.has(
|
|
2832
|
+
has(path8) {
|
|
2833
|
+
return this._entries.has(path8);
|
|
2749
2834
|
}
|
|
2750
2835
|
// ---------------------------------------------------------------------------
|
|
2751
2836
|
// Entry Modification
|
|
@@ -2757,8 +2842,8 @@ var MountManager = class {
|
|
|
2757
2842
|
add(mounts) {
|
|
2758
2843
|
const paths = Object.keys(mounts);
|
|
2759
2844
|
this.logger.debug(`Adding ${paths.length} pending mount(s)`, { paths });
|
|
2760
|
-
for (const [
|
|
2761
|
-
this._entries.set(
|
|
2845
|
+
for (const [path8, filesystem] of Object.entries(mounts)) {
|
|
2846
|
+
this._entries.set(path8, {
|
|
2762
2847
|
filesystem,
|
|
2763
2848
|
state: "pending"
|
|
2764
2849
|
});
|
|
@@ -2768,8 +2853,8 @@ var MountManager = class {
|
|
|
2768
2853
|
* Update a mount entry's state.
|
|
2769
2854
|
* Creates the entry if it doesn't exist.
|
|
2770
2855
|
*/
|
|
2771
|
-
set(
|
|
2772
|
-
const existing = this._entries.get(
|
|
2856
|
+
set(path8, updates) {
|
|
2857
|
+
const existing = this._entries.get(path8);
|
|
2773
2858
|
if (existing) {
|
|
2774
2859
|
existing.state = updates.state;
|
|
2775
2860
|
if (updates.config) {
|
|
@@ -2780,7 +2865,7 @@ var MountManager = class {
|
|
|
2780
2865
|
existing.error = updates.error;
|
|
2781
2866
|
}
|
|
2782
2867
|
} else if (updates.filesystem) {
|
|
2783
|
-
this._entries.set(
|
|
2868
|
+
this._entries.set(path8, {
|
|
2784
2869
|
filesystem: updates.filesystem,
|
|
2785
2870
|
state: updates.state,
|
|
2786
2871
|
config: updates.config,
|
|
@@ -2788,14 +2873,14 @@ var MountManager = class {
|
|
|
2788
2873
|
error: updates.error
|
|
2789
2874
|
});
|
|
2790
2875
|
} else {
|
|
2791
|
-
this.logger.debug(`set() called for unknown path "${
|
|
2876
|
+
this.logger.debug(`set() called for unknown path "${path8}" without filesystem \u2014 no entry created`);
|
|
2792
2877
|
}
|
|
2793
2878
|
}
|
|
2794
2879
|
/**
|
|
2795
2880
|
* Delete a mount entry.
|
|
2796
2881
|
*/
|
|
2797
|
-
delete(
|
|
2798
|
-
return this._entries.delete(
|
|
2882
|
+
delete(path8) {
|
|
2883
|
+
return this._entries.delete(path8);
|
|
2799
2884
|
}
|
|
2800
2885
|
/**
|
|
2801
2886
|
* Clear all mount entries.
|
|
@@ -2816,7 +2901,7 @@ var MountManager = class {
|
|
|
2816
2901
|
return;
|
|
2817
2902
|
}
|
|
2818
2903
|
this.logger.debug(`Processing ${pendingCount} pending mount(s)`);
|
|
2819
|
-
for (const [
|
|
2904
|
+
for (const [path8, entry] of this._entries) {
|
|
2820
2905
|
if (entry.state !== "pending") {
|
|
2821
2906
|
continue;
|
|
2822
2907
|
}
|
|
@@ -2826,7 +2911,7 @@ var MountManager = class {
|
|
|
2826
2911
|
try {
|
|
2827
2912
|
const hookResult = await this._onMount({
|
|
2828
2913
|
filesystem: entry.filesystem,
|
|
2829
|
-
mountPath:
|
|
2914
|
+
mountPath: path8,
|
|
2830
2915
|
config,
|
|
2831
2916
|
sandbox: this._sandbox,
|
|
2832
2917
|
workspace: this._workspace
|
|
@@ -2834,7 +2919,7 @@ var MountManager = class {
|
|
|
2834
2919
|
if (hookResult === false) {
|
|
2835
2920
|
entry.state = "unsupported";
|
|
2836
2921
|
entry.error = "Skipped by onMount hook";
|
|
2837
|
-
this.logger.debug(`Mount skipped by onMount hook`, { path:
|
|
2922
|
+
this.logger.debug(`Mount skipped by onMount hook`, { path: path8, provider: fsProvider });
|
|
2838
2923
|
continue;
|
|
2839
2924
|
}
|
|
2840
2925
|
if (hookResult && typeof hookResult === "object") {
|
|
@@ -2842,54 +2927,54 @@ var MountManager = class {
|
|
|
2842
2927
|
entry.state = "mounted";
|
|
2843
2928
|
entry.config = config;
|
|
2844
2929
|
entry.configHash = config ? this.hashConfig(config) : void 0;
|
|
2845
|
-
this.logger.info(`Mount handled by onMount hook`, { path:
|
|
2930
|
+
this.logger.info(`Mount handled by onMount hook`, { path: path8, provider: fsProvider });
|
|
2846
2931
|
} else {
|
|
2847
2932
|
entry.state = "error";
|
|
2848
2933
|
entry.error = hookResult.error ?? "Mount hook failed";
|
|
2849
|
-
this.logger.error(`Mount hook failed`, { path:
|
|
2934
|
+
this.logger.error(`Mount hook failed`, { path: path8, provider: fsProvider, error: entry.error });
|
|
2850
2935
|
}
|
|
2851
2936
|
continue;
|
|
2852
2937
|
}
|
|
2853
2938
|
} catch (err) {
|
|
2854
2939
|
entry.state = "error";
|
|
2855
2940
|
entry.error = `Mount hook error: ${String(err)}`;
|
|
2856
|
-
this.logger.error(`Mount hook threw error`, { path:
|
|
2941
|
+
this.logger.error(`Mount hook threw error`, { path: path8, provider: fsProvider, error: entry.error });
|
|
2857
2942
|
continue;
|
|
2858
2943
|
}
|
|
2859
2944
|
}
|
|
2860
2945
|
if (!config) {
|
|
2861
2946
|
entry.state = "unsupported";
|
|
2862
2947
|
entry.error = "Filesystem does not support mounting";
|
|
2863
|
-
this.logger.debug(`Filesystem does not support mounting`, { path:
|
|
2948
|
+
this.logger.debug(`Filesystem does not support mounting`, { path: path8, provider: fsProvider });
|
|
2864
2949
|
continue;
|
|
2865
2950
|
}
|
|
2866
2951
|
entry.config = config;
|
|
2867
2952
|
entry.configHash = this.hashConfig(config);
|
|
2868
2953
|
entry.state = "mounting";
|
|
2869
|
-
this.logger.debug(`Mounting filesystem`, { path:
|
|
2954
|
+
this.logger.debug(`Mounting filesystem`, { path: path8, provider: fsProvider, type: config.type });
|
|
2870
2955
|
try {
|
|
2871
|
-
const result = await this._mountFn(entry.filesystem,
|
|
2956
|
+
const result = await this._mountFn(entry.filesystem, path8);
|
|
2872
2957
|
if (result.success) {
|
|
2873
2958
|
entry.state = "mounted";
|
|
2874
|
-
this.logger.info(`Mount successful`, { path:
|
|
2959
|
+
this.logger.info(`Mount successful`, { path: path8, provider: fsProvider });
|
|
2875
2960
|
} else if (result.unavailable) {
|
|
2876
2961
|
entry.state = "unavailable";
|
|
2877
2962
|
entry.error = result.error ?? "FUSE tool not installed";
|
|
2878
|
-
this.logger.warn(`FUSE mount unavailable`, { path:
|
|
2963
|
+
this.logger.warn(`FUSE mount unavailable`, { path: path8, provider: fsProvider, error: entry.error });
|
|
2879
2964
|
} else {
|
|
2880
2965
|
entry.state = "error";
|
|
2881
2966
|
entry.error = result.error ?? "Mount failed";
|
|
2882
|
-
this.logger.error(`Mount failed`, { path:
|
|
2967
|
+
this.logger.error(`Mount failed`, { path: path8, provider: fsProvider, error: entry.error });
|
|
2883
2968
|
}
|
|
2884
2969
|
} catch (err) {
|
|
2885
2970
|
if (err instanceof MountToolNotFoundError) {
|
|
2886
2971
|
entry.state = "unavailable";
|
|
2887
2972
|
entry.error = String(err);
|
|
2888
|
-
this.logger.warn(`FUSE mount unavailable`, { path:
|
|
2973
|
+
this.logger.warn(`FUSE mount unavailable`, { path: path8, provider: fsProvider, error: entry.error });
|
|
2889
2974
|
} else {
|
|
2890
2975
|
entry.state = "error";
|
|
2891
2976
|
entry.error = String(err);
|
|
2892
|
-
this.logger.error(`Mount threw error`, { path:
|
|
2977
|
+
this.logger.error(`Mount threw error`, { path: path8, provider: fsProvider, error: entry.error });
|
|
2893
2978
|
}
|
|
2894
2979
|
}
|
|
2895
2980
|
}
|
|
@@ -2938,10 +3023,10 @@ var MountManager = class {
|
|
|
2938
3023
|
if (separatorIndex <= 0) {
|
|
2939
3024
|
return null;
|
|
2940
3025
|
}
|
|
2941
|
-
const
|
|
3026
|
+
const path8 = content.slice(0, separatorIndex);
|
|
2942
3027
|
const configHash = content.slice(separatorIndex + 1);
|
|
2943
|
-
if (!
|
|
2944
|
-
return { path:
|
|
3028
|
+
if (!path8 || !configHash) return null;
|
|
3029
|
+
return { path: path8, configHash };
|
|
2945
3030
|
}
|
|
2946
3031
|
/**
|
|
2947
3032
|
* Check if a config hash matches the expected hash for a mount path.
|
|
@@ -3427,11 +3512,11 @@ function buildBwrapCommand(command, workspacePath, config) {
|
|
|
3427
3512
|
}
|
|
3428
3513
|
bwrapArgs.push("--proc", "/proc");
|
|
3429
3514
|
bwrapArgs.push("--tmpfs", "/tmp");
|
|
3430
|
-
for (const
|
|
3431
|
-
bwrapArgs.push("--ro-bind-try",
|
|
3515
|
+
for (const path8 of DEFAULT_READONLY_BINDS) {
|
|
3516
|
+
bwrapArgs.push("--ro-bind-try", path8, path8);
|
|
3432
3517
|
}
|
|
3433
|
-
for (const
|
|
3434
|
-
bwrapArgs.push("--ro-bind",
|
|
3518
|
+
for (const path8 of config.readOnlyPaths ?? []) {
|
|
3519
|
+
bwrapArgs.push("--ro-bind", path8, path8);
|
|
3435
3520
|
}
|
|
3436
3521
|
if (config.allowSystemBinaries !== false) {
|
|
3437
3522
|
const nodePath4 = process.execPath;
|
|
@@ -3443,8 +3528,8 @@ function buildBwrapCommand(command, workspacePath, config) {
|
|
|
3443
3528
|
bwrapArgs.push("--ro-bind-try", "/snap", "/snap");
|
|
3444
3529
|
}
|
|
3445
3530
|
bwrapArgs.push("--bind", workspacePath, workspacePath);
|
|
3446
|
-
for (const
|
|
3447
|
-
bwrapArgs.push("--bind",
|
|
3531
|
+
for (const path8 of config.readWritePaths ?? []) {
|
|
3532
|
+
bwrapArgs.push("--bind", path8, path8);
|
|
3448
3533
|
}
|
|
3449
3534
|
bwrapArgs.push("--chdir", workspacePath);
|
|
3450
3535
|
bwrapArgs.push("--die-with-parent");
|
|
@@ -4852,18 +4937,18 @@ var VersionedSkillSource = class {
|
|
|
4852
4937
|
/**
|
|
4853
4938
|
* Normalize a path by stripping leading/trailing slashes and dots.
|
|
4854
4939
|
*/
|
|
4855
|
-
#normalizePath(
|
|
4856
|
-
let normalized =
|
|
4940
|
+
#normalizePath(path8) {
|
|
4941
|
+
let normalized = path8.replace(/^[./\\]+|[/\\]+$/g, "");
|
|
4857
4942
|
if (normalized === "") return "";
|
|
4858
4943
|
return normalized;
|
|
4859
4944
|
}
|
|
4860
|
-
async exists(
|
|
4861
|
-
const normalized = this.#normalizePath(
|
|
4945
|
+
async exists(path8) {
|
|
4946
|
+
const normalized = this.#normalizePath(path8);
|
|
4862
4947
|
if (this.#tree.entries[normalized]) return true;
|
|
4863
4948
|
return this.#directories.has(normalized);
|
|
4864
4949
|
}
|
|
4865
|
-
async stat(
|
|
4866
|
-
const normalized = this.#normalizePath(
|
|
4950
|
+
async stat(path8) {
|
|
4951
|
+
const normalized = this.#normalizePath(path8);
|
|
4867
4952
|
const name = normalized.split("/").pop() || normalized || ".";
|
|
4868
4953
|
const entry = this.#tree.entries[normalized];
|
|
4869
4954
|
if (entry) {
|
|
@@ -4885,27 +4970,27 @@ var VersionedSkillSource = class {
|
|
|
4885
4970
|
modifiedAt: this.#versionCreatedAt
|
|
4886
4971
|
};
|
|
4887
4972
|
}
|
|
4888
|
-
throw new Error(`Path not found in skill version tree: ${
|
|
4973
|
+
throw new Error(`Path not found in skill version tree: ${path8}`);
|
|
4889
4974
|
}
|
|
4890
|
-
async readFile(
|
|
4891
|
-
const normalized = this.#normalizePath(
|
|
4975
|
+
async readFile(path8) {
|
|
4976
|
+
const normalized = this.#normalizePath(path8);
|
|
4892
4977
|
const entry = this.#tree.entries[normalized];
|
|
4893
4978
|
if (!entry) {
|
|
4894
|
-
throw new Error(`File not found in skill version tree: ${
|
|
4979
|
+
throw new Error(`File not found in skill version tree: ${path8}`);
|
|
4895
4980
|
}
|
|
4896
4981
|
const blob = await this.#blobStore.get(entry.blobHash);
|
|
4897
4982
|
if (!blob) {
|
|
4898
|
-
throw new Error(`Blob not found for hash ${entry.blobHash} (file: ${
|
|
4983
|
+
throw new Error(`Blob not found for hash ${entry.blobHash} (file: ${path8})`);
|
|
4899
4984
|
}
|
|
4900
4985
|
if (entry.encoding === "base64") {
|
|
4901
4986
|
return Buffer.from(blob.content, "base64");
|
|
4902
4987
|
}
|
|
4903
4988
|
return blob.content;
|
|
4904
4989
|
}
|
|
4905
|
-
async readdir(
|
|
4906
|
-
const normalized = this.#normalizePath(
|
|
4990
|
+
async readdir(path8) {
|
|
4991
|
+
const normalized = this.#normalizePath(path8);
|
|
4907
4992
|
if (!this.#directories.has(normalized)) {
|
|
4908
|
-
throw new Error(`Directory not found in skill version tree: ${
|
|
4993
|
+
throw new Error(`Directory not found in skill version tree: ${path8}`);
|
|
4909
4994
|
}
|
|
4910
4995
|
const prefix = normalized === "" ? "" : normalized + "/";
|
|
4911
4996
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -4938,15 +5023,15 @@ var CompositeVersionedSkillSource = class {
|
|
|
4938
5023
|
this.#fallback = options?.fallback;
|
|
4939
5024
|
this.#fallbackSkills = new Set(options?.fallbackSkills ?? []);
|
|
4940
5025
|
}
|
|
4941
|
-
#normalizePath(
|
|
4942
|
-
return
|
|
5026
|
+
#normalizePath(path8) {
|
|
5027
|
+
return path8.replace(/^[./\\]+|[/\\]+$/g, "");
|
|
4943
5028
|
}
|
|
4944
5029
|
/**
|
|
4945
5030
|
* Route a path to the correct source.
|
|
4946
5031
|
* Returns the source and the remaining path within that source.
|
|
4947
5032
|
*/
|
|
4948
|
-
#routePath(
|
|
4949
|
-
const normalized = this.#normalizePath(
|
|
5033
|
+
#routePath(path8) {
|
|
5034
|
+
const normalized = this.#normalizePath(path8);
|
|
4950
5035
|
if (normalized === "") return null;
|
|
4951
5036
|
const segments = normalized.split("/");
|
|
4952
5037
|
const skillDir = segments[0];
|
|
@@ -4963,15 +5048,15 @@ var CompositeVersionedSkillSource = class {
|
|
|
4963
5048
|
}
|
|
4964
5049
|
return null;
|
|
4965
5050
|
}
|
|
4966
|
-
async exists(
|
|
4967
|
-
const normalized = this.#normalizePath(
|
|
5051
|
+
async exists(path8) {
|
|
5052
|
+
const normalized = this.#normalizePath(path8);
|
|
4968
5053
|
if (normalized === "") return true;
|
|
4969
|
-
const route = this.#routePath(
|
|
5054
|
+
const route = this.#routePath(path8);
|
|
4970
5055
|
if (!route) return false;
|
|
4971
5056
|
return route.source.exists(route.subPath);
|
|
4972
5057
|
}
|
|
4973
|
-
async stat(
|
|
4974
|
-
const normalized = this.#normalizePath(
|
|
5058
|
+
async stat(path8) {
|
|
5059
|
+
const normalized = this.#normalizePath(path8);
|
|
4975
5060
|
if (normalized === "") {
|
|
4976
5061
|
return {
|
|
4977
5062
|
name: ".",
|
|
@@ -4981,21 +5066,21 @@ var CompositeVersionedSkillSource = class {
|
|
|
4981
5066
|
modifiedAt: /* @__PURE__ */ new Date()
|
|
4982
5067
|
};
|
|
4983
5068
|
}
|
|
4984
|
-
const route = this.#routePath(
|
|
5069
|
+
const route = this.#routePath(path8);
|
|
4985
5070
|
if (!route) {
|
|
4986
|
-
throw new Error(`Path not found in composite skill source: ${
|
|
5071
|
+
throw new Error(`Path not found in composite skill source: ${path8}`);
|
|
4987
5072
|
}
|
|
4988
5073
|
return route.source.stat(route.subPath);
|
|
4989
5074
|
}
|
|
4990
|
-
async readFile(
|
|
4991
|
-
const route = this.#routePath(
|
|
5075
|
+
async readFile(path8) {
|
|
5076
|
+
const route = this.#routePath(path8);
|
|
4992
5077
|
if (!route) {
|
|
4993
|
-
throw new Error(`File not found in composite skill source: ${
|
|
5078
|
+
throw new Error(`File not found in composite skill source: ${path8}`);
|
|
4994
5079
|
}
|
|
4995
5080
|
return route.source.readFile(route.subPath);
|
|
4996
5081
|
}
|
|
4997
|
-
async readdir(
|
|
4998
|
-
const normalized = this.#normalizePath(
|
|
5082
|
+
async readdir(path8) {
|
|
5083
|
+
const normalized = this.#normalizePath(path8);
|
|
4999
5084
|
if (normalized === "") {
|
|
5000
5085
|
const entries = [];
|
|
5001
5086
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -5011,9 +5096,9 @@ var CompositeVersionedSkillSource = class {
|
|
|
5011
5096
|
}
|
|
5012
5097
|
return entries;
|
|
5013
5098
|
}
|
|
5014
|
-
const route = this.#routePath(
|
|
5099
|
+
const route = this.#routePath(path8);
|
|
5015
5100
|
if (!route) {
|
|
5016
|
-
throw new Error(`Directory not found in composite skill source: ${
|
|
5101
|
+
throw new Error(`Directory not found in composite skill source: ${path8}`);
|
|
5017
5102
|
}
|
|
5018
5103
|
return route.source.readdir(route.subPath);
|
|
5019
5104
|
}
|
|
@@ -5213,7 +5298,7 @@ var WorkspaceSkillsImpl = class _WorkspaceSkillsImpl {
|
|
|
5213
5298
|
if (a.length !== b.length) return false;
|
|
5214
5299
|
const sortedA = [...a].sort();
|
|
5215
5300
|
const sortedB = [...b].sort();
|
|
5216
|
-
return sortedA.every((
|
|
5301
|
+
return sortedA.every((path8, i) => path8 === sortedB[i]);
|
|
5217
5302
|
}
|
|
5218
5303
|
// ===========================================================================
|
|
5219
5304
|
// Search
|
|
@@ -5819,9 +5904,9 @@ ${validation.errors.join("\n")}`);
|
|
|
5819
5904
|
/**
|
|
5820
5905
|
* Get parent path
|
|
5821
5906
|
*/
|
|
5822
|
-
#getParentPath(
|
|
5823
|
-
const lastSlash =
|
|
5824
|
-
return lastSlash > 0 ?
|
|
5907
|
+
#getParentPath(path8) {
|
|
5908
|
+
const lastSlash = path8.lastIndexOf("/");
|
|
5909
|
+
return lastSlash > 0 ? path8.substring(0, lastSlash) : "/";
|
|
5825
5910
|
}
|
|
5826
5911
|
};
|
|
5827
5912
|
function hashContent(content) {
|
|
@@ -6052,14 +6137,14 @@ function createSkillReadTool(skills) {
|
|
|
6052
6137
|
startLine: v4.z.number().optional().describe("Starting line number (1-indexed). If omitted, starts from the beginning."),
|
|
6053
6138
|
endLine: v4.z.number().optional().describe("Ending line number (1-indexed, inclusive). If omitted, reads to the end.")
|
|
6054
6139
|
}),
|
|
6055
|
-
execute: async ({ skillName, path:
|
|
6140
|
+
execute: async ({ skillName, path: path8, startLine, endLine }) => {
|
|
6056
6141
|
const resolved = await resolveSkill(skills, skillName);
|
|
6057
6142
|
if ("notFound" in resolved) return resolved.notFound;
|
|
6058
6143
|
const resolvedPath = resolved.skill.path;
|
|
6059
6144
|
let content = null;
|
|
6060
|
-
content = await skills.getReference(resolvedPath,
|
|
6061
|
-
if (content === null) content = await skills.getScript(resolvedPath,
|
|
6062
|
-
if (content === null) content = await skills.getAsset(resolvedPath,
|
|
6145
|
+
content = await skills.getReference(resolvedPath, path8);
|
|
6146
|
+
if (content === null) content = await skills.getScript(resolvedPath, path8);
|
|
6147
|
+
if (content === null) content = await skills.getAsset(resolvedPath, path8);
|
|
6063
6148
|
if (content === null) {
|
|
6064
6149
|
const refs = (await skills.listReferences(resolvedPath)).map((f) => `references/${f}`);
|
|
6065
6150
|
const scriptsList = (await skills.listScripts(resolvedPath)).map((f) => `scripts/${f}`);
|
|
@@ -6067,11 +6152,11 @@ function createSkillReadTool(skills) {
|
|
|
6067
6152
|
const allFiles = [...refs, ...scriptsList, ...assets];
|
|
6068
6153
|
const fileList = allFiles.length > 0 ? `
|
|
6069
6154
|
Available files: ${allFiles.join(", ")}` : "";
|
|
6070
|
-
return `File "${
|
|
6155
|
+
return `File "${path8}" not found in skill "${skillName}".${fileList}`;
|
|
6071
6156
|
}
|
|
6072
6157
|
const textContent = typeof content === "string" ? content : content.toString("utf-8");
|
|
6073
6158
|
if (textContent.slice(0, 1e3).includes("\0")) {
|
|
6074
|
-
const fullPath = `${resolved.skill.path}/${
|
|
6159
|
+
const fullPath = `${resolved.skill.path}/${path8}`;
|
|
6075
6160
|
const size = typeof content === "string" ? Buffer.byteLength(content) : content.length;
|
|
6076
6161
|
return `Binary file: ${fullPath} (${size} bytes)`;
|
|
6077
6162
|
}
|
|
@@ -6107,8 +6192,8 @@ var Workspace = class {
|
|
|
6107
6192
|
if (config.filesystem) {
|
|
6108
6193
|
throw new WorkspaceError('Cannot use both "filesystem" and "mounts"', "INVALID_CONFIG");
|
|
6109
6194
|
}
|
|
6110
|
-
for (const [mountPath,
|
|
6111
|
-
if (
|
|
6195
|
+
for (const [mountPath, fs6] of Object.entries(config.mounts)) {
|
|
6196
|
+
if (fs6 instanceof LocalFilesystem && !fs6.contained) {
|
|
6112
6197
|
console.warn(
|
|
6113
6198
|
`[Workspace] LocalFilesystem at mount "${mountPath}" has contained: false, which is incompatible with mounts. CompositeFilesystem strips mount prefixes and produces absolute paths (e.g. "/file.txt"), which a non-contained LocalFilesystem interprets as real host paths instead of paths relative to basePath. Use contained: true (default) or allowedPaths for specific exceptions.`
|
|
6114
6199
|
);
|
|
@@ -6304,13 +6389,13 @@ var Workspace = class {
|
|
|
6304
6389
|
* @param options - Index options (metadata, type hints)
|
|
6305
6390
|
* @throws {SearchNotAvailableError} if search is not configured
|
|
6306
6391
|
*/
|
|
6307
|
-
async index(
|
|
6392
|
+
async index(path8, content, options) {
|
|
6308
6393
|
if (!this._searchEngine) {
|
|
6309
6394
|
throw new SearchNotAvailableError();
|
|
6310
6395
|
}
|
|
6311
6396
|
this.lastAccessedAt = /* @__PURE__ */ new Date();
|
|
6312
6397
|
const doc = {
|
|
6313
|
-
id:
|
|
6398
|
+
id: path8,
|
|
6314
6399
|
content,
|
|
6315
6400
|
metadata: {
|
|
6316
6401
|
type: options?.type,
|
|
@@ -6619,6 +6704,9 @@ var WORKSPACE_TOOLS = {
|
|
|
6619
6704
|
SEARCH: {
|
|
6620
6705
|
SEARCH: `${WORKSPACE_TOOLS_PREFIX}_search`,
|
|
6621
6706
|
INDEX: `${WORKSPACE_TOOLS_PREFIX}_index`
|
|
6707
|
+
},
|
|
6708
|
+
LSP: {
|
|
6709
|
+
LSP_INSPECT: `${WORKSPACE_TOOLS_PREFIX}_lsp_inspect`
|
|
6622
6710
|
}
|
|
6623
6711
|
};
|
|
6624
6712
|
function requireWorkspace(context) {
|
|
@@ -6740,7 +6828,7 @@ function isAstGrepAvailable() {
|
|
|
6740
6828
|
return astGrepModule !== null;
|
|
6741
6829
|
}
|
|
6742
6830
|
try {
|
|
6743
|
-
const req = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-
|
|
6831
|
+
const req = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-QVVWKMFM.cjs', document.baseURI).href)));
|
|
6744
6832
|
req.resolve("@ast-grep/napi");
|
|
6745
6833
|
return true;
|
|
6746
6834
|
} catch {
|
|
@@ -6941,7 +7029,7 @@ Pattern replace (for everything else):
|
|
|
6941
7029
|
isDefault: v4.z.boolean().optional().describe("Whether the first name is a default import")
|
|
6942
7030
|
}).optional().describe("Required for add-import transform. Specifies the module and names to import.")
|
|
6943
7031
|
}),
|
|
6944
|
-
execute: async ({ path:
|
|
7032
|
+
execute: async ({ path: path8, pattern, replacement, transform, targetName, newName, importSpec }, context) => {
|
|
6945
7033
|
const { workspace, filesystem } = requireFilesystem(context);
|
|
6946
7034
|
await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.AST_EDIT);
|
|
6947
7035
|
if (filesystem.readOnly) {
|
|
@@ -6954,19 +7042,19 @@ Pattern replace (for everything else):
|
|
|
6954
7042
|
const { parse: parse2, Lang } = astGrep;
|
|
6955
7043
|
let content;
|
|
6956
7044
|
try {
|
|
6957
|
-
content = await filesystem.readFile(
|
|
7045
|
+
content = await filesystem.readFile(path8, { encoding: "utf-8" });
|
|
6958
7046
|
} catch (error) {
|
|
6959
7047
|
if (error instanceof FileNotFoundError) {
|
|
6960
|
-
return `File not found: ${
|
|
7048
|
+
return `File not found: ${path8}. Use the write file tool to create it first.`;
|
|
6961
7049
|
}
|
|
6962
7050
|
throw error;
|
|
6963
7051
|
}
|
|
6964
7052
|
if (typeof content !== "string") {
|
|
6965
7053
|
return `Cannot perform AST edits on binary files. Use the write file tool instead.`;
|
|
6966
7054
|
}
|
|
6967
|
-
const lang = getLanguageFromPath(
|
|
7055
|
+
const lang = getLanguageFromPath(path8, Lang);
|
|
6968
7056
|
if (!lang) {
|
|
6969
|
-
return `Unsupported file type for AST editing: ${
|
|
7057
|
+
return `Unsupported file type for AST editing: ${path8}`;
|
|
6970
7058
|
}
|
|
6971
7059
|
const ast = parse2(lang, content);
|
|
6972
7060
|
const root = ast.root();
|
|
@@ -7016,16 +7104,16 @@ Pattern replace (for everything else):
|
|
|
7016
7104
|
}
|
|
7017
7105
|
const wasModified = modifiedContent !== content;
|
|
7018
7106
|
if (wasModified) {
|
|
7019
|
-
await filesystem.writeFile(
|
|
7107
|
+
await filesystem.writeFile(path8, modifiedContent, {
|
|
7020
7108
|
overwrite: true,
|
|
7021
7109
|
expectedMtime: context?.__expectedMtime
|
|
7022
7110
|
});
|
|
7023
7111
|
}
|
|
7024
7112
|
if (!wasModified) {
|
|
7025
|
-
return `No changes made to ${
|
|
7113
|
+
return `No changes made to ${path8} (${changes.join("; ")})`;
|
|
7026
7114
|
}
|
|
7027
|
-
let output = `${
|
|
7028
|
-
output += await getEditDiagnosticsText(workspace,
|
|
7115
|
+
let output = `${path8}: ${changes.join("; ")}`;
|
|
7116
|
+
output += await getEditDiagnosticsText(workspace, path8, modifiedContent);
|
|
7029
7117
|
return output;
|
|
7030
7118
|
}
|
|
7031
7119
|
});
|
|
@@ -7036,19 +7124,19 @@ var deleteFileTool = chunkK4NN2KQQ_cjs.createTool({
|
|
|
7036
7124
|
path: v4.z.string().describe("The path to the file or directory to delete"),
|
|
7037
7125
|
recursive: v4.z.boolean().optional().default(false).describe("If true, delete directories and their contents recursively. Required for non-empty directories.")
|
|
7038
7126
|
}),
|
|
7039
|
-
execute: async ({ path:
|
|
7127
|
+
execute: async ({ path: path8, recursive }, context) => {
|
|
7040
7128
|
const { filesystem } = requireFilesystem(context);
|
|
7041
7129
|
await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.DELETE);
|
|
7042
7130
|
if (filesystem.readOnly) {
|
|
7043
7131
|
throw new WorkspaceReadOnlyError("delete");
|
|
7044
7132
|
}
|
|
7045
|
-
const stat3 = await filesystem.stat(
|
|
7133
|
+
const stat3 = await filesystem.stat(path8);
|
|
7046
7134
|
if (stat3.type === "directory") {
|
|
7047
|
-
await filesystem.rmdir(
|
|
7135
|
+
await filesystem.rmdir(path8, { recursive, force: recursive });
|
|
7048
7136
|
} else {
|
|
7049
|
-
await filesystem.deleteFile(
|
|
7137
|
+
await filesystem.deleteFile(path8);
|
|
7050
7138
|
}
|
|
7051
|
-
return `Deleted ${
|
|
7139
|
+
return `Deleted ${path8}`;
|
|
7052
7140
|
}
|
|
7053
7141
|
});
|
|
7054
7142
|
var editFileTool = chunkK4NN2KQQ_cjs.createTool({
|
|
@@ -7066,24 +7154,24 @@ Usage:
|
|
|
7066
7154
|
new_string: v4.z.string().describe("The text to replace old_string with"),
|
|
7067
7155
|
replace_all: v4.z.boolean().optional().default(false).describe("If true, replace all occurrences. If false (default), old_string must be unique.")
|
|
7068
7156
|
}),
|
|
7069
|
-
execute: async ({ path:
|
|
7157
|
+
execute: async ({ path: path8, old_string, new_string, replace_all }, context) => {
|
|
7070
7158
|
const { workspace, filesystem } = requireFilesystem(context);
|
|
7071
7159
|
await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.EDIT_FILE);
|
|
7072
7160
|
if (filesystem.readOnly) {
|
|
7073
7161
|
throw new WorkspaceReadOnlyError("edit_file");
|
|
7074
7162
|
}
|
|
7075
7163
|
try {
|
|
7076
|
-
const content = await filesystem.readFile(
|
|
7164
|
+
const content = await filesystem.readFile(path8, { encoding: "utf-8" });
|
|
7077
7165
|
if (typeof content !== "string") {
|
|
7078
7166
|
return `Cannot edit binary files. Use the write file tool instead.`;
|
|
7079
7167
|
}
|
|
7080
7168
|
const result = replaceString(content, old_string, new_string, replace_all);
|
|
7081
|
-
await filesystem.writeFile(
|
|
7169
|
+
await filesystem.writeFile(path8, result.content, {
|
|
7082
7170
|
overwrite: true,
|
|
7083
7171
|
expectedMtime: context?.__expectedMtime
|
|
7084
7172
|
});
|
|
7085
|
-
let output = `Replaced ${result.replacements} occurrence${result.replacements !== 1 ? "s" : ""} in ${
|
|
7086
|
-
output += await getEditDiagnosticsText(workspace,
|
|
7173
|
+
let output = `Replaced ${result.replacements} occurrence${result.replacements !== 1 ? "s" : ""} in ${path8}`;
|
|
7174
|
+
output += await getEditDiagnosticsText(workspace, path8, result.content);
|
|
7087
7175
|
return output;
|
|
7088
7176
|
} catch (error) {
|
|
7089
7177
|
if (error instanceof StringNotFoundError) {
|
|
@@ -7335,19 +7423,19 @@ var fileStatTool = chunkK4NN2KQQ_cjs.createTool({
|
|
|
7335
7423
|
inputSchema: v4.z.object({
|
|
7336
7424
|
path: v4.z.string().describe("The path to check")
|
|
7337
7425
|
}),
|
|
7338
|
-
execute: async ({ path:
|
|
7426
|
+
execute: async ({ path: path8 }, context) => {
|
|
7339
7427
|
const { filesystem } = requireFilesystem(context);
|
|
7340
7428
|
await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.FILE_STAT);
|
|
7341
7429
|
try {
|
|
7342
|
-
const stat3 = await filesystem.stat(
|
|
7430
|
+
const stat3 = await filesystem.stat(path8);
|
|
7343
7431
|
const modifiedAt = stat3.modifiedAt.toISOString();
|
|
7344
|
-
const parts = [`${
|
|
7432
|
+
const parts = [`${path8}`, `Type: ${stat3.type}`];
|
|
7345
7433
|
if (stat3.size !== void 0) parts.push(`Size: ${stat3.size} bytes`);
|
|
7346
7434
|
parts.push(`Modified: ${modifiedAt}`);
|
|
7347
7435
|
return parts.join(" ");
|
|
7348
7436
|
} catch (error) {
|
|
7349
7437
|
if (error instanceof FileNotFoundError) {
|
|
7350
|
-
return `${
|
|
7438
|
+
return `${path8}: not found`;
|
|
7351
7439
|
}
|
|
7352
7440
|
throw error;
|
|
7353
7441
|
}
|
|
@@ -7613,11 +7701,11 @@ var indexContentTool = chunkK4NN2KQQ_cjs.createTool({
|
|
|
7613
7701
|
content: v4.z.string().describe("The text content to index"),
|
|
7614
7702
|
metadata: v4.z.record(v4.z.string(), v4.z.unknown()).optional().describe("Optional metadata to store with the document")
|
|
7615
7703
|
}),
|
|
7616
|
-
execute: async ({ path:
|
|
7704
|
+
execute: async ({ path: path8, content, metadata }, context) => {
|
|
7617
7705
|
const workspace = requireWorkspace(context);
|
|
7618
7706
|
await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.SEARCH.INDEX);
|
|
7619
|
-
await workspace.index(
|
|
7620
|
-
return `Indexed ${
|
|
7707
|
+
await workspace.index(path8, content, { metadata });
|
|
7708
|
+
return `Indexed ${path8}`;
|
|
7621
7709
|
}
|
|
7622
7710
|
});
|
|
7623
7711
|
var KILL_TAIL_LINES = 50;
|
|
@@ -7673,7 +7761,7 @@ Use this to stop a long-running background process that was started with execute
|
|
|
7673
7761
|
});
|
|
7674
7762
|
|
|
7675
7763
|
// src/workspace/tools/tree-formatter.ts
|
|
7676
|
-
async function formatAsTree(
|
|
7764
|
+
async function formatAsTree(fs6, path8, options) {
|
|
7677
7765
|
const maxDepth = options?.maxDepth ?? Infinity;
|
|
7678
7766
|
const showHidden = options?.showHidden ?? false;
|
|
7679
7767
|
const dirsOnly = options?.dirsOnly ?? false;
|
|
@@ -7683,9 +7771,9 @@ async function formatAsTree(fs5, path7, options) {
|
|
|
7683
7771
|
const respectGitignore = options?.respectGitignore ?? true;
|
|
7684
7772
|
let ignoreFilter = options?.ignoreFilter;
|
|
7685
7773
|
if (!ignoreFilter && respectGitignore) {
|
|
7686
|
-
const rawFilter = await loadGitignore(
|
|
7774
|
+
const rawFilter = await loadGitignore(fs6);
|
|
7687
7775
|
if (rawFilter) {
|
|
7688
|
-
const normalizedPath =
|
|
7776
|
+
const normalizedPath = path8.replace(/^\.\//, "").replace(/^\//, "").replace(/\/$/, "");
|
|
7689
7777
|
const targetIsIgnored = normalizedPath && rawFilter(normalizedPath + "/");
|
|
7690
7778
|
ignoreFilter = targetIsIgnored ? void 0 : rawFilter;
|
|
7691
7779
|
}
|
|
@@ -7707,7 +7795,7 @@ async function formatAsTree(fs5, path7, options) {
|
|
|
7707
7795
|
}
|
|
7708
7796
|
let entries;
|
|
7709
7797
|
try {
|
|
7710
|
-
entries = await
|
|
7798
|
+
entries = await fs6.readdir(currentPath);
|
|
7711
7799
|
} catch (error) {
|
|
7712
7800
|
if (depth === 0) {
|
|
7713
7801
|
throw error;
|
|
@@ -7747,7 +7835,7 @@ async function formatAsTree(fs5, path7, options) {
|
|
|
7747
7835
|
if (globMatcher && !dirsOnly) {
|
|
7748
7836
|
filtered = filtered.filter((e) => {
|
|
7749
7837
|
if (e.type === "directory") return true;
|
|
7750
|
-
const relativePath = getRelativePath(
|
|
7838
|
+
const relativePath = getRelativePath(path8, currentPath, e.name);
|
|
7751
7839
|
return globMatcher(relativePath);
|
|
7752
7840
|
});
|
|
7753
7841
|
}
|
|
@@ -7761,7 +7849,7 @@ async function formatAsTree(fs5, path7, options) {
|
|
|
7761
7849
|
const entry = filtered[i];
|
|
7762
7850
|
const displayName = entry.isSymlink && entry.symlinkTarget ? `${entry.name} -> ${entry.symlinkTarget}` : entry.name;
|
|
7763
7851
|
lines.push(`${indent}${displayName}`);
|
|
7764
|
-
paths.push(getRelativePath(
|
|
7852
|
+
paths.push(getRelativePath(path8, currentPath, entry.name));
|
|
7765
7853
|
if (entry.type === "directory") {
|
|
7766
7854
|
dirCount++;
|
|
7767
7855
|
if (!entry.isSymlink) {
|
|
@@ -7773,7 +7861,7 @@ async function formatAsTree(fs5, path7, options) {
|
|
|
7773
7861
|
}
|
|
7774
7862
|
}
|
|
7775
7863
|
}
|
|
7776
|
-
await buildTree(
|
|
7864
|
+
await buildTree(path8, 0);
|
|
7777
7865
|
const dirPart = dirCount === 1 ? "1 directory" : `${dirCount} directories`;
|
|
7778
7866
|
const filePart = fileCount === 1 ? "1 file" : `${fileCount} files`;
|
|
7779
7867
|
let summary = `${dirPart}, ${filePart}`;
|
|
@@ -7836,10 +7924,10 @@ Examples:
|
|
|
7836
7924
|
),
|
|
7837
7925
|
respectGitignore: v4.z.boolean().optional().default(true).describe("Respect .gitignore in the listed directory (default: true).")
|
|
7838
7926
|
}),
|
|
7839
|
-
execute: async ({ path:
|
|
7927
|
+
execute: async ({ path: path8 = ".", maxDepth = 2, showHidden, dirsOnly, exclude, extension, pattern, respectGitignore }, context) => {
|
|
7840
7928
|
const { workspace, filesystem } = requireFilesystem(context);
|
|
7841
7929
|
await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.LIST_FILES);
|
|
7842
|
-
const result = await formatAsTree(filesystem,
|
|
7930
|
+
const result = await formatAsTree(filesystem, path8, {
|
|
7843
7931
|
maxDepth,
|
|
7844
7932
|
showHidden,
|
|
7845
7933
|
dirsOnly,
|
|
@@ -7857,6 +7945,194 @@ ${result.summary}`,
|
|
|
7857
7945
|
);
|
|
7858
7946
|
}
|
|
7859
7947
|
});
|
|
7948
|
+
var CURSOR_MARKER = "<<<";
|
|
7949
|
+
async function getLinePreview(filePath, lineNumber) {
|
|
7950
|
+
try {
|
|
7951
|
+
const content = await fs2__namespace.default.readFile(filePath, "utf-8");
|
|
7952
|
+
const lines = content.split("\n");
|
|
7953
|
+
const line = lines[lineNumber - 1];
|
|
7954
|
+
return line?.trim() ?? null;
|
|
7955
|
+
} catch {
|
|
7956
|
+
return null;
|
|
7957
|
+
}
|
|
7958
|
+
}
|
|
7959
|
+
function getAbsolutePath(workspacePath, lspRoot, resolveAbsolutePath) {
|
|
7960
|
+
const resolvedPath = resolveAbsolutePath?.(workspacePath);
|
|
7961
|
+
if (resolvedPath) {
|
|
7962
|
+
return resolvedPath;
|
|
7963
|
+
}
|
|
7964
|
+
if (nodePath__namespace.default.isAbsolute(workspacePath)) {
|
|
7965
|
+
return workspacePath;
|
|
7966
|
+
}
|
|
7967
|
+
return nodePath__namespace.default.resolve(lspRoot, workspacePath);
|
|
7968
|
+
}
|
|
7969
|
+
function locationUriToPath(uri) {
|
|
7970
|
+
if (!uri.startsWith("file://")) {
|
|
7971
|
+
return null;
|
|
7972
|
+
}
|
|
7973
|
+
try {
|
|
7974
|
+
return url.fileURLToPath(uri);
|
|
7975
|
+
} catch {
|
|
7976
|
+
return null;
|
|
7977
|
+
}
|
|
7978
|
+
}
|
|
7979
|
+
function locationKey(location) {
|
|
7980
|
+
return `${location.path}:L${location.line}`;
|
|
7981
|
+
}
|
|
7982
|
+
function compressPath(filePath) {
|
|
7983
|
+
const cwd = process.cwd();
|
|
7984
|
+
if (filePath.startsWith(cwd)) {
|
|
7985
|
+
return "$cwd" + filePath.slice(cwd.length);
|
|
7986
|
+
}
|
|
7987
|
+
return filePath;
|
|
7988
|
+
}
|
|
7989
|
+
var lspInspectTool = chunkK4NN2KQQ_cjs.createTool({
|
|
7990
|
+
id: WORKSPACE_TOOLS.LSP.LSP_INSPECT,
|
|
7991
|
+
description: "Inspect code at a specific symbol position using the Language Server Protocol. Provide an absolute file path, a 1-indexed line number, and the exact line content with <<< marking the cursor position. Exactly one <<< marker is required. Returns hover information, any diagnostics reported on that line, plus definition and implementation locations when available. Use this for type information, symbol navigation, and go-to-definition; use view to read the surrounding implementation.",
|
|
7992
|
+
inputSchema: v4.z.object({
|
|
7993
|
+
path: v4.z.string().describe("Absolute path to the file"),
|
|
7994
|
+
line: v4.z.number().int().positive().describe("Line number (1-indexed)"),
|
|
7995
|
+
match: v4.z.string().describe(
|
|
7996
|
+
'Line content with <<< marking the cursor position. Exactly one <<< marker is required. Example: "const foo = <<<bar()" means cursor is at bar'
|
|
7997
|
+
)
|
|
7998
|
+
}),
|
|
7999
|
+
execute: async ({ path: filePath, line, match }, context) => {
|
|
8000
|
+
const workspace = requireWorkspace(context);
|
|
8001
|
+
await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.LSP.LSP_INSPECT);
|
|
8002
|
+
const cursorPositions = [];
|
|
8003
|
+
let searchStart = 0;
|
|
8004
|
+
while (true) {
|
|
8005
|
+
const pos = match.indexOf(CURSOR_MARKER, searchStart);
|
|
8006
|
+
if (pos === -1) break;
|
|
8007
|
+
cursorPositions.push(pos);
|
|
8008
|
+
searchStart = pos + CURSOR_MARKER.length;
|
|
8009
|
+
}
|
|
8010
|
+
if (cursorPositions.length === 0) {
|
|
8011
|
+
return {
|
|
8012
|
+
error: `No <<< cursor marker found in match`
|
|
8013
|
+
};
|
|
8014
|
+
}
|
|
8015
|
+
if (cursorPositions.length > 1) {
|
|
8016
|
+
return {
|
|
8017
|
+
error: `Multiple <<< markers found (found ${cursorPositions.length}, expected 1)`
|
|
8018
|
+
};
|
|
8019
|
+
}
|
|
8020
|
+
const character = cursorPositions[0] + 1;
|
|
8021
|
+
const lspManager = workspace.lsp;
|
|
8022
|
+
if (!lspManager) {
|
|
8023
|
+
return {
|
|
8024
|
+
error: "LSP is not configured for this workspace. Enable LSP in workspace config to use this tool."
|
|
8025
|
+
};
|
|
8026
|
+
}
|
|
8027
|
+
const absolutePath = getAbsolutePath(
|
|
8028
|
+
filePath,
|
|
8029
|
+
lspManager.root,
|
|
8030
|
+
workspace.filesystem?.resolveAbsolutePath?.bind(workspace.filesystem)
|
|
8031
|
+
);
|
|
8032
|
+
let fileContent = "";
|
|
8033
|
+
try {
|
|
8034
|
+
fileContent = await fs2__namespace.default.readFile(absolutePath, "utf-8");
|
|
8035
|
+
} catch {
|
|
8036
|
+
fileContent = "";
|
|
8037
|
+
}
|
|
8038
|
+
let queryResult;
|
|
8039
|
+
try {
|
|
8040
|
+
queryResult = await lspManager.prepareQuery(absolutePath);
|
|
8041
|
+
} catch (err) {
|
|
8042
|
+
return {
|
|
8043
|
+
error: `Failed to initialize LSP client: ${err instanceof Error ? err.message : String(err)}`
|
|
8044
|
+
};
|
|
8045
|
+
}
|
|
8046
|
+
if (!queryResult) {
|
|
8047
|
+
return {
|
|
8048
|
+
error: `No language server available for files of this type: ${filePath}`
|
|
8049
|
+
};
|
|
8050
|
+
}
|
|
8051
|
+
const { client, uri } = queryResult;
|
|
8052
|
+
const position = { line: line - 1, character: character - 1 };
|
|
8053
|
+
const result = {};
|
|
8054
|
+
try {
|
|
8055
|
+
const hoverResult = await client.queryHover(uri, position).catch(() => null);
|
|
8056
|
+
if (hoverResult) {
|
|
8057
|
+
const contents = hoverResult.contents;
|
|
8058
|
+
if (contents) {
|
|
8059
|
+
if (typeof contents === "string") {
|
|
8060
|
+
result.hover = { value: contents, kind: "plaintext" };
|
|
8061
|
+
} else if (Array.isArray(contents)) {
|
|
8062
|
+
const first = contents[0];
|
|
8063
|
+
if (typeof first === "string") {
|
|
8064
|
+
result.hover = { value: first, kind: "plaintext" };
|
|
8065
|
+
} else if (first?.value) {
|
|
8066
|
+
result.hover = { value: first.value, kind: first.kind ?? "markdown" };
|
|
8067
|
+
}
|
|
8068
|
+
} else if (contents.value) {
|
|
8069
|
+
result.hover = { value: contents.value, kind: contents.kind ?? "markdown" };
|
|
8070
|
+
}
|
|
8071
|
+
}
|
|
8072
|
+
}
|
|
8073
|
+
const diagnosticsPromise = fileContent ? Promise.resolve().then(() => {
|
|
8074
|
+
client.notifyChange(absolutePath, fileContent, 1);
|
|
8075
|
+
return client.waitForDiagnostics(absolutePath, 5e3, true);
|
|
8076
|
+
}).catch(() => []) : Promise.resolve([]);
|
|
8077
|
+
const [diagnosticsResult, definitionResult, implResult] = await Promise.all([
|
|
8078
|
+
diagnosticsPromise,
|
|
8079
|
+
client.queryDefinition(uri, position).catch(() => []),
|
|
8080
|
+
client.queryImplementation(uri, position).catch(() => [])
|
|
8081
|
+
]);
|
|
8082
|
+
if (diagnosticsResult && diagnosticsResult.length > 0) {
|
|
8083
|
+
const lineDiagnostics = diagnosticsResult.map((diagnostic) => ({
|
|
8084
|
+
line: typeof diagnostic.line === "number" ? diagnostic.line : (diagnostic.range?.start?.line ?? -1) + 1,
|
|
8085
|
+
severity: typeof diagnostic.severity === "number" ? diagnostic.severity === 1 ? "error" : diagnostic.severity === 2 ? "warning" : diagnostic.severity === 3 ? "info" : "hint" : diagnostic.severity,
|
|
8086
|
+
message: diagnostic.message,
|
|
8087
|
+
source: diagnostic.source ?? null
|
|
8088
|
+
})).filter((diagnostic) => diagnostic.line === line).map(({ severity, message, source }) => ({ severity, message, source }));
|
|
8089
|
+
if (lineDiagnostics.length > 0) {
|
|
8090
|
+
result.diagnostics = lineDiagnostics;
|
|
8091
|
+
}
|
|
8092
|
+
}
|
|
8093
|
+
const definitionLocations = definitionResult.map((loc) => ({
|
|
8094
|
+
uri: loc.uri ?? loc.targetUri,
|
|
8095
|
+
range: loc.range ?? loc.targetRange
|
|
8096
|
+
})).map((loc) => {
|
|
8097
|
+
const resolvedPath = loc.uri ? locationUriToPath(String(loc.uri)) : null;
|
|
8098
|
+
return resolvedPath ? {
|
|
8099
|
+
path: resolvedPath,
|
|
8100
|
+
line: (loc.range?.start?.line ?? 0) + 1,
|
|
8101
|
+
character: (loc.range?.start?.character ?? 0) + 1
|
|
8102
|
+
} : null;
|
|
8103
|
+
}).filter((loc) => Boolean(loc)).filter((loc) => !(loc.path === absolutePath && loc.line === line));
|
|
8104
|
+
if (definitionLocations.length > 0) {
|
|
8105
|
+
const previews = await Promise.all(definitionLocations.map((loc) => getLinePreview(loc.path, loc.line)));
|
|
8106
|
+
result.definition = definitionLocations.map((loc, i) => ({
|
|
8107
|
+
location: `${compressPath(loc.path)}:L${loc.line}:C${loc.character}`,
|
|
8108
|
+
preview: previews[i]
|
|
8109
|
+
}));
|
|
8110
|
+
}
|
|
8111
|
+
const definitionKeys = new Set(definitionLocations.map(locationKey));
|
|
8112
|
+
const implementationLocations = implResult.map((loc) => ({
|
|
8113
|
+
uri: loc.uri ?? loc.targetUri,
|
|
8114
|
+
range: loc.range ?? loc.targetRange
|
|
8115
|
+
})).map((loc) => {
|
|
8116
|
+
const resolvedPath = loc.uri ? locationUriToPath(String(loc.uri)) : null;
|
|
8117
|
+
return resolvedPath ? {
|
|
8118
|
+
path: resolvedPath,
|
|
8119
|
+
line: (loc.range?.start?.line ?? 0) + 1,
|
|
8120
|
+
character: (loc.range?.start?.character ?? 0) + 1
|
|
8121
|
+
} : null;
|
|
8122
|
+
}).filter((loc) => Boolean(loc)).filter((loc) => !definitionKeys.has(locationKey(loc)) && !(loc.path === absolutePath && loc.line === line));
|
|
8123
|
+
if (implementationLocations.length > 0) {
|
|
8124
|
+
result.implementation = implementationLocations.map(
|
|
8125
|
+
(loc) => `${compressPath(loc.path)}:L${loc.line}:C${loc.character}`
|
|
8126
|
+
);
|
|
8127
|
+
}
|
|
8128
|
+
} catch (err) {
|
|
8129
|
+
result.error = `LSP query failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
8130
|
+
} finally {
|
|
8131
|
+
client.notifyClose(absolutePath);
|
|
8132
|
+
}
|
|
8133
|
+
return result;
|
|
8134
|
+
}
|
|
8135
|
+
});
|
|
7860
8136
|
var mkdirTool = chunkK4NN2KQQ_cjs.createTool({
|
|
7861
8137
|
id: WORKSPACE_TOOLS.FILESYSTEM.MKDIR,
|
|
7862
8138
|
description: "Create a directory in the workspace filesystem",
|
|
@@ -7864,14 +8140,14 @@ var mkdirTool = chunkK4NN2KQQ_cjs.createTool({
|
|
|
7864
8140
|
path: v4.z.string().describe("The path of the directory to create"),
|
|
7865
8141
|
recursive: v4.z.boolean().optional().default(true).describe("Whether to create parent directories if they do not exist")
|
|
7866
8142
|
}),
|
|
7867
|
-
execute: async ({ path:
|
|
8143
|
+
execute: async ({ path: path8, recursive }, context) => {
|
|
7868
8144
|
const { filesystem } = requireFilesystem(context);
|
|
7869
8145
|
await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.MKDIR);
|
|
7870
8146
|
if (filesystem.readOnly) {
|
|
7871
8147
|
throw new WorkspaceReadOnlyError("mkdir");
|
|
7872
8148
|
}
|
|
7873
|
-
await filesystem.mkdir(
|
|
7874
|
-
return `Created directory ${
|
|
8149
|
+
await filesystem.mkdir(path8, { recursive });
|
|
8150
|
+
return `Created directory ${path8}`;
|
|
7875
8151
|
}
|
|
7876
8152
|
});
|
|
7877
8153
|
var readFileTool = chunkK4NN2KQQ_cjs.createTool({
|
|
@@ -7884,12 +8160,12 @@ var readFileTool = chunkK4NN2KQQ_cjs.createTool({
|
|
|
7884
8160
|
limit: v4.z.number().optional().describe("Maximum number of lines to read. If omitted, reads to the end of the file."),
|
|
7885
8161
|
showLineNumbers: v4.z.boolean().optional().default(true).describe("Whether to prefix each line with its line number (default: true)")
|
|
7886
8162
|
}),
|
|
7887
|
-
execute: async ({ path:
|
|
8163
|
+
execute: async ({ path: path8, encoding, offset, limit, showLineNumbers }, context) => {
|
|
7888
8164
|
const { workspace, filesystem } = requireFilesystem(context);
|
|
7889
8165
|
await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.READ_FILE);
|
|
7890
8166
|
const effectiveEncoding = encoding ?? "utf-8";
|
|
7891
|
-
const fullContent = await filesystem.readFile(
|
|
7892
|
-
const stat3 = await filesystem.stat(
|
|
8167
|
+
const fullContent = await filesystem.readFile(path8, { encoding: effectiveEncoding });
|
|
8168
|
+
const stat3 = await filesystem.stat(path8);
|
|
7893
8169
|
const isTextEncoding = !encoding || encoding === "utf-8" || encoding === "utf8";
|
|
7894
8170
|
const tokenLimit = workspace.getToolsConfig()?.[WORKSPACE_TOOLS.FILESYSTEM.READ_FILE]?.maxOutputTokens;
|
|
7895
8171
|
if (!isTextEncoding) {
|
|
@@ -7957,19 +8233,19 @@ var writeFileTool = chunkK4NN2KQQ_cjs.createTool({
|
|
|
7957
8233
|
content: v4.z.string().describe("The content to write to the file"),
|
|
7958
8234
|
overwrite: v4.z.boolean().optional().default(true).describe("Whether to overwrite the file if it already exists")
|
|
7959
8235
|
}),
|
|
7960
|
-
execute: async ({ path:
|
|
8236
|
+
execute: async ({ path: path8, content, overwrite }, context) => {
|
|
7961
8237
|
const { workspace, filesystem } = requireFilesystem(context);
|
|
7962
8238
|
await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE);
|
|
7963
8239
|
if (filesystem.readOnly) {
|
|
7964
8240
|
throw new WorkspaceReadOnlyError("write_file");
|
|
7965
8241
|
}
|
|
7966
|
-
await filesystem.writeFile(
|
|
8242
|
+
await filesystem.writeFile(path8, content, {
|
|
7967
8243
|
overwrite,
|
|
7968
8244
|
expectedMtime: context?.__expectedMtime
|
|
7969
8245
|
});
|
|
7970
8246
|
const size = Buffer.byteLength(content, "utf-8");
|
|
7971
|
-
let output = `Wrote ${size} bytes to ${
|
|
7972
|
-
output += await getEditDiagnosticsText(workspace,
|
|
8247
|
+
let output = `Wrote ${size} bytes to ${path8}`;
|
|
8248
|
+
output += await getEditDiagnosticsText(workspace, path8, content);
|
|
7973
8249
|
return output;
|
|
7974
8250
|
}
|
|
7975
8251
|
});
|
|
@@ -8124,6 +8400,7 @@ function createWorkspaceTools(workspace) {
|
|
|
8124
8400
|
addTool(WORKSPACE_TOOLS.SANDBOX.KILL_PROCESS, killProcessTool);
|
|
8125
8401
|
}
|
|
8126
8402
|
}
|
|
8403
|
+
addTool(WORKSPACE_TOOLS.LSP.LSP_INSPECT, lspInspectTool);
|
|
8127
8404
|
return tools;
|
|
8128
8405
|
}
|
|
8129
8406
|
|
|
@@ -8196,5 +8473,5 @@ exports.requireWorkspace = requireWorkspace;
|
|
|
8196
8473
|
exports.resolveToolConfig = resolveToolConfig;
|
|
8197
8474
|
exports.searchTool = searchTool;
|
|
8198
8475
|
exports.writeFileTool = writeFileTool;
|
|
8199
|
-
//# sourceMappingURL=chunk-
|
|
8200
|
-
//# sourceMappingURL=chunk-
|
|
8476
|
+
//# sourceMappingURL=chunk-QVVWKMFM.cjs.map
|
|
8477
|
+
//# sourceMappingURL=chunk-QVVWKMFM.cjs.map
|