@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
|
@@ -6,11 +6,12 @@ import nodePath__default, { parse, join, dirname } from 'path';
|
|
|
6
6
|
import posixPath from 'path/posix';
|
|
7
7
|
import { constants, existsSync } from 'fs';
|
|
8
8
|
import * as fs2 from 'fs/promises';
|
|
9
|
+
import fs2__default from 'fs/promises';
|
|
9
10
|
import * as os3 from 'os';
|
|
10
11
|
import os3__default from 'os';
|
|
11
12
|
import picomatch from 'picomatch';
|
|
12
13
|
import { createRequire } from 'module';
|
|
13
|
-
import { pathToFileURL } from 'url';
|
|
14
|
+
import { fileURLToPath, pathToFileURL } from 'url';
|
|
14
15
|
import { execFileSync } from 'child_process';
|
|
15
16
|
import * as crypto from 'crypto';
|
|
16
17
|
import { createHash } from 'crypto';
|
|
@@ -71,68 +72,68 @@ var WorkspaceReadOnlyError = class extends WorkspaceError {
|
|
|
71
72
|
}
|
|
72
73
|
};
|
|
73
74
|
var FilesystemError = class extends Error {
|
|
74
|
-
constructor(message, code,
|
|
75
|
+
constructor(message, code, path8) {
|
|
75
76
|
super(message);
|
|
76
77
|
this.code = code;
|
|
77
|
-
this.path =
|
|
78
|
+
this.path = path8;
|
|
78
79
|
this.name = "FilesystemError";
|
|
79
80
|
}
|
|
80
81
|
};
|
|
81
82
|
var FileNotFoundError = class extends FilesystemError {
|
|
82
|
-
constructor(
|
|
83
|
-
super(`File not found: ${
|
|
83
|
+
constructor(path8) {
|
|
84
|
+
super(`File not found: ${path8}`, "ENOENT", path8);
|
|
84
85
|
this.name = "FileNotFoundError";
|
|
85
86
|
}
|
|
86
87
|
};
|
|
87
88
|
var DirectoryNotFoundError = class extends FilesystemError {
|
|
88
|
-
constructor(
|
|
89
|
-
super(`Directory not found: ${
|
|
89
|
+
constructor(path8) {
|
|
90
|
+
super(`Directory not found: ${path8}`, "ENOENT", path8);
|
|
90
91
|
this.name = "DirectoryNotFoundError";
|
|
91
92
|
}
|
|
92
93
|
};
|
|
93
94
|
var FileExistsError = class extends FilesystemError {
|
|
94
|
-
constructor(
|
|
95
|
-
super(`File already exists: ${
|
|
95
|
+
constructor(path8) {
|
|
96
|
+
super(`File already exists: ${path8}`, "EEXIST", path8);
|
|
96
97
|
this.name = "FileExistsError";
|
|
97
98
|
}
|
|
98
99
|
};
|
|
99
100
|
var IsDirectoryError = class extends FilesystemError {
|
|
100
|
-
constructor(
|
|
101
|
-
super(`Path is a directory: ${
|
|
101
|
+
constructor(path8) {
|
|
102
|
+
super(`Path is a directory: ${path8}`, "EISDIR", path8);
|
|
102
103
|
this.name = "IsDirectoryError";
|
|
103
104
|
}
|
|
104
105
|
};
|
|
105
106
|
var NotDirectoryError = class extends FilesystemError {
|
|
106
|
-
constructor(
|
|
107
|
-
super(`Path is not a directory: ${
|
|
107
|
+
constructor(path8) {
|
|
108
|
+
super(`Path is not a directory: ${path8}`, "ENOTDIR", path8);
|
|
108
109
|
this.name = "NotDirectoryError";
|
|
109
110
|
}
|
|
110
111
|
};
|
|
111
112
|
var DirectoryNotEmptyError = class extends FilesystemError {
|
|
112
|
-
constructor(
|
|
113
|
-
super(`Directory not empty: ${
|
|
113
|
+
constructor(path8) {
|
|
114
|
+
super(`Directory not empty: ${path8}`, "ENOTEMPTY", path8);
|
|
114
115
|
this.name = "DirectoryNotEmptyError";
|
|
115
116
|
}
|
|
116
117
|
};
|
|
117
118
|
var PermissionError = class extends FilesystemError {
|
|
118
|
-
constructor(
|
|
119
|
-
super(`Permission denied: ${operation} on ${
|
|
119
|
+
constructor(path8, operation) {
|
|
120
|
+
super(`Permission denied: ${operation} on ${path8}`, "EACCES", path8);
|
|
120
121
|
this.operation = operation;
|
|
121
122
|
this.name = "PermissionError";
|
|
122
123
|
}
|
|
123
124
|
};
|
|
124
125
|
var FileReadRequiredError = class extends FilesystemError {
|
|
125
|
-
constructor(
|
|
126
|
-
super(reason, "EREAD_REQUIRED",
|
|
126
|
+
constructor(path8, reason) {
|
|
127
|
+
super(reason, "EREAD_REQUIRED", path8);
|
|
127
128
|
this.name = "FileReadRequiredError";
|
|
128
129
|
}
|
|
129
130
|
};
|
|
130
131
|
var StaleFileError = class extends FilesystemError {
|
|
131
|
-
constructor(
|
|
132
|
+
constructor(path8, expectedMtime, actualMtime) {
|
|
132
133
|
super(
|
|
133
|
-
`File was modified externally: ${
|
|
134
|
+
`File was modified externally: ${path8} (expected mtime ${expectedMtime.toISOString()}, actual ${actualMtime.toISOString()})`,
|
|
134
135
|
"ESTALE",
|
|
135
|
-
|
|
136
|
+
path8
|
|
136
137
|
);
|
|
137
138
|
this.expectedMtime = expectedMtime;
|
|
138
139
|
this.actualMtime = actualMtime;
|
|
@@ -171,14 +172,14 @@ var CompositeFilesystem = class {
|
|
|
171
172
|
constructor(config) {
|
|
172
173
|
this.id = `cfs-${Date.now().toString(36)}`;
|
|
173
174
|
this._mounts = /* @__PURE__ */ new Map();
|
|
174
|
-
for (const [
|
|
175
|
-
const normalized = this.normalizePath(
|
|
176
|
-
this._mounts.set(normalized,
|
|
175
|
+
for (const [path8, fs6] of Object.entries(config.mounts)) {
|
|
176
|
+
const normalized = this.normalizePath(path8);
|
|
177
|
+
this._mounts.set(normalized, fs6);
|
|
177
178
|
}
|
|
178
179
|
if (this._mounts.size === 0) {
|
|
179
180
|
throw new Error("CompositeFilesystem requires at least one mount");
|
|
180
181
|
}
|
|
181
|
-
this.readOnly = [...this._mounts.values()].every((
|
|
182
|
+
this.readOnly = [...this._mounts.values()].every((fs6) => fs6.readOnly) || void 0;
|
|
182
183
|
const mountPaths = [...this._mounts.keys()];
|
|
183
184
|
for (const a of mountPaths) {
|
|
184
185
|
for (const b of mountPaths) {
|
|
@@ -207,8 +208,8 @@ var CompositeFilesystem = class {
|
|
|
207
208
|
*/
|
|
208
209
|
async getInfo() {
|
|
209
210
|
const mounts = {};
|
|
210
|
-
for (const [mountPath,
|
|
211
|
-
mounts[mountPath] = await
|
|
211
|
+
for (const [mountPath, fs6] of this._mounts) {
|
|
212
|
+
mounts[mountPath] = await fs6.getInfo?.() ?? null;
|
|
212
213
|
}
|
|
213
214
|
return {
|
|
214
215
|
id: this.id,
|
|
@@ -223,42 +224,42 @@ var CompositeFilesystem = class {
|
|
|
223
224
|
* Get the underlying filesystem for a given path.
|
|
224
225
|
* Returns undefined if the path doesn't resolve to any mount.
|
|
225
226
|
*/
|
|
226
|
-
getFilesystemForPath(
|
|
227
|
-
const resolved = this.resolveMount(
|
|
227
|
+
getFilesystemForPath(path8) {
|
|
228
|
+
const resolved = this.resolveMount(path8);
|
|
228
229
|
return resolved?.fs;
|
|
229
230
|
}
|
|
230
231
|
/**
|
|
231
232
|
* Get the mount path for a given path.
|
|
232
233
|
* Returns undefined if the path doesn't resolve to any mount.
|
|
233
234
|
*/
|
|
234
|
-
getMountPathForPath(
|
|
235
|
-
const resolved = this.resolveMount(
|
|
235
|
+
getMountPathForPath(path8) {
|
|
236
|
+
const resolved = this.resolveMount(path8);
|
|
236
237
|
return resolved?.mountPath;
|
|
237
238
|
}
|
|
238
239
|
/**
|
|
239
240
|
* Resolve a workspace-relative path to an absolute disk path.
|
|
240
241
|
* Strips the mount prefix and delegates to the underlying filesystem.
|
|
241
242
|
*/
|
|
242
|
-
resolveAbsolutePath(
|
|
243
|
-
const r = this.resolveMount(
|
|
243
|
+
resolveAbsolutePath(path8) {
|
|
244
|
+
const r = this.resolveMount(path8);
|
|
244
245
|
if (!r) return void 0;
|
|
245
246
|
return r.fs.resolveAbsolutePath?.(r.fsPath);
|
|
246
247
|
}
|
|
247
|
-
normalizePath(
|
|
248
|
-
if (!
|
|
249
|
-
let n = posixPath.normalize(
|
|
248
|
+
normalizePath(path8) {
|
|
249
|
+
if (!path8 || path8 === "/" || path8 === ".") return "/";
|
|
250
|
+
let n = posixPath.normalize(path8);
|
|
250
251
|
if (n === ".") return "/";
|
|
251
252
|
if (!n.startsWith("/")) n = `/${n}`;
|
|
252
253
|
if (n.length > 1 && n.endsWith("/")) n = n.slice(0, -1);
|
|
253
254
|
return n;
|
|
254
255
|
}
|
|
255
|
-
resolveMount(
|
|
256
|
-
const normalized = this.normalizePath(
|
|
256
|
+
resolveMount(path8) {
|
|
257
|
+
const normalized = this.normalizePath(path8);
|
|
257
258
|
let best = null;
|
|
258
|
-
for (const [mountPath,
|
|
259
|
+
for (const [mountPath, fs6] of this._mounts) {
|
|
259
260
|
if (normalized === mountPath || normalized.startsWith(mountPath + "/")) {
|
|
260
261
|
if (!best || mountPath.length > best.mountPath.length) {
|
|
261
|
-
best = { mountPath, fs:
|
|
262
|
+
best = { mountPath, fs: fs6 };
|
|
262
263
|
}
|
|
263
264
|
}
|
|
264
265
|
}
|
|
@@ -268,11 +269,11 @@ var CompositeFilesystem = class {
|
|
|
268
269
|
else if (fsPath.startsWith("/")) fsPath = fsPath.slice(1);
|
|
269
270
|
return { fs: best.fs, fsPath, mountPath: best.mountPath };
|
|
270
271
|
}
|
|
271
|
-
getVirtualEntries(
|
|
272
|
-
const normalized = this.normalizePath(
|
|
272
|
+
getVirtualEntries(path8) {
|
|
273
|
+
const normalized = this.normalizePath(path8);
|
|
273
274
|
if (this.resolveMount(normalized)) return null;
|
|
274
275
|
const entriesMap = /* @__PURE__ */ new Map();
|
|
275
|
-
for (const [mountPath,
|
|
276
|
+
for (const [mountPath, fs6] of this._mounts.entries()) {
|
|
276
277
|
const isUnder = normalized === "/" ? mountPath.startsWith("/") : mountPath.startsWith(normalized + "/");
|
|
277
278
|
if (isUnder) {
|
|
278
279
|
const remaining = normalized === "/" ? mountPath.slice(1) : mountPath.slice(normalized.length + 1);
|
|
@@ -282,12 +283,12 @@ var CompositeFilesystem = class {
|
|
|
282
283
|
const entry = { name: next, type: "directory" };
|
|
283
284
|
if (isDirectMount) {
|
|
284
285
|
entry.mount = {
|
|
285
|
-
provider:
|
|
286
|
-
icon:
|
|
287
|
-
displayName:
|
|
288
|
-
description:
|
|
289
|
-
status:
|
|
290
|
-
error:
|
|
286
|
+
provider: fs6.provider,
|
|
287
|
+
icon: fs6.icon,
|
|
288
|
+
displayName: fs6.displayName,
|
|
289
|
+
description: fs6.description,
|
|
290
|
+
status: fs6.status,
|
|
291
|
+
error: fs6.error
|
|
291
292
|
};
|
|
292
293
|
}
|
|
293
294
|
entriesMap.set(next, entry);
|
|
@@ -296,8 +297,8 @@ var CompositeFilesystem = class {
|
|
|
296
297
|
}
|
|
297
298
|
return entriesMap.size > 0 ? Array.from(entriesMap.values()) : null;
|
|
298
299
|
}
|
|
299
|
-
isVirtualPath(
|
|
300
|
-
const normalized = this.normalizePath(
|
|
300
|
+
isVirtualPath(path8) {
|
|
301
|
+
const normalized = this.normalizePath(path8);
|
|
301
302
|
if (normalized === "/" && !this._mounts.has("/")) return true;
|
|
302
303
|
for (const mountPath of this._mounts.keys()) {
|
|
303
304
|
if (mountPath.startsWith(normalized + "/")) return true;
|
|
@@ -308,9 +309,9 @@ var CompositeFilesystem = class {
|
|
|
308
309
|
* Assert that a filesystem is writable (not read-only).
|
|
309
310
|
* @throws {PermissionError} if the filesystem is read-only
|
|
310
311
|
*/
|
|
311
|
-
assertWritable(
|
|
312
|
-
if (
|
|
313
|
-
throw new PermissionError(
|
|
312
|
+
assertWritable(fs6, path8, operation) {
|
|
313
|
+
if (fs6.readOnly) {
|
|
314
|
+
throw new PermissionError(path8, `${operation} (filesystem is read-only)`);
|
|
314
315
|
}
|
|
315
316
|
}
|
|
316
317
|
// ===========================================================================
|
|
@@ -318,9 +319,9 @@ var CompositeFilesystem = class {
|
|
|
318
319
|
// ===========================================================================
|
|
319
320
|
async init() {
|
|
320
321
|
this.status = "initializing";
|
|
321
|
-
for (const [mountPath,
|
|
322
|
+
for (const [mountPath, fs6] of this._mounts.entries()) {
|
|
322
323
|
try {
|
|
323
|
-
await callLifecycle(
|
|
324
|
+
await callLifecycle(fs6, "init");
|
|
324
325
|
} catch (e) {
|
|
325
326
|
const message = e instanceof Error ? e.message : String(e);
|
|
326
327
|
console.warn(`[CompositeFilesystem] Mount "${mountPath}" failed to initialize: ${message}`);
|
|
@@ -331,9 +332,9 @@ var CompositeFilesystem = class {
|
|
|
331
332
|
async destroy() {
|
|
332
333
|
this.status = "destroying";
|
|
333
334
|
const errors = [];
|
|
334
|
-
for (const
|
|
335
|
+
for (const fs6 of this._mounts.values()) {
|
|
335
336
|
try {
|
|
336
|
-
await callLifecycle(
|
|
337
|
+
await callLifecycle(fs6, "destroy");
|
|
337
338
|
} catch (e) {
|
|
338
339
|
errors.push(e instanceof Error ? e : new Error(String(e)));
|
|
339
340
|
}
|
|
@@ -344,27 +345,27 @@ var CompositeFilesystem = class {
|
|
|
344
345
|
}
|
|
345
346
|
this.status = "destroyed";
|
|
346
347
|
}
|
|
347
|
-
async readFile(
|
|
348
|
-
const r = this.resolveMount(
|
|
349
|
-
if (!r) throw new Error(`No mount for path: ${
|
|
348
|
+
async readFile(path8, options) {
|
|
349
|
+
const r = this.resolveMount(path8);
|
|
350
|
+
if (!r) throw new Error(`No mount for path: ${path8}`);
|
|
350
351
|
return r.fs.readFile(r.fsPath, options);
|
|
351
352
|
}
|
|
352
|
-
async writeFile(
|
|
353
|
-
const r = this.resolveMount(
|
|
354
|
-
if (!r) throw new Error(`No mount for path: ${
|
|
355
|
-
this.assertWritable(r.fs,
|
|
353
|
+
async writeFile(path8, content, options) {
|
|
354
|
+
const r = this.resolveMount(path8);
|
|
355
|
+
if (!r) throw new Error(`No mount for path: ${path8}`);
|
|
356
|
+
this.assertWritable(r.fs, path8, "writeFile");
|
|
356
357
|
return r.fs.writeFile(r.fsPath, content, options);
|
|
357
358
|
}
|
|
358
|
-
async appendFile(
|
|
359
|
-
const r = this.resolveMount(
|
|
360
|
-
if (!r) throw new Error(`No mount for path: ${
|
|
361
|
-
this.assertWritable(r.fs,
|
|
359
|
+
async appendFile(path8, content) {
|
|
360
|
+
const r = this.resolveMount(path8);
|
|
361
|
+
if (!r) throw new Error(`No mount for path: ${path8}`);
|
|
362
|
+
this.assertWritable(r.fs, path8, "appendFile");
|
|
362
363
|
return r.fs.appendFile(r.fsPath, content);
|
|
363
364
|
}
|
|
364
|
-
async deleteFile(
|
|
365
|
-
const r = this.resolveMount(
|
|
366
|
-
if (!r) throw new Error(`No mount for path: ${
|
|
367
|
-
this.assertWritable(r.fs,
|
|
365
|
+
async deleteFile(path8, options) {
|
|
366
|
+
const r = this.resolveMount(path8);
|
|
367
|
+
if (!r) throw new Error(`No mount for path: ${path8}`);
|
|
368
|
+
this.assertWritable(r.fs, path8, "deleteFile");
|
|
368
369
|
return r.fs.deleteFile(r.fsPath, options);
|
|
369
370
|
}
|
|
370
371
|
async copyFile(src, dest, options) {
|
|
@@ -392,35 +393,35 @@ var CompositeFilesystem = class {
|
|
|
392
393
|
await this.copyFile(src, dest, options);
|
|
393
394
|
await srcR.fs.deleteFile(srcR.fsPath);
|
|
394
395
|
}
|
|
395
|
-
async readdir(
|
|
396
|
-
const virtual = this.getVirtualEntries(
|
|
396
|
+
async readdir(path8, options) {
|
|
397
|
+
const virtual = this.getVirtualEntries(path8);
|
|
397
398
|
if (virtual) return virtual;
|
|
398
|
-
const r = this.resolveMount(
|
|
399
|
-
if (!r) throw new Error(`No mount for path: ${
|
|
399
|
+
const r = this.resolveMount(path8);
|
|
400
|
+
if (!r) throw new Error(`No mount for path: ${path8}`);
|
|
400
401
|
return r.fs.readdir(r.fsPath, options);
|
|
401
402
|
}
|
|
402
|
-
async mkdir(
|
|
403
|
-
const r = this.resolveMount(
|
|
404
|
-
if (!r) throw new Error(`No mount for path: ${
|
|
405
|
-
this.assertWritable(r.fs,
|
|
403
|
+
async mkdir(path8, options) {
|
|
404
|
+
const r = this.resolveMount(path8);
|
|
405
|
+
if (!r) throw new Error(`No mount for path: ${path8}`);
|
|
406
|
+
this.assertWritable(r.fs, path8, "mkdir");
|
|
406
407
|
return r.fs.mkdir(r.fsPath, options);
|
|
407
408
|
}
|
|
408
|
-
async rmdir(
|
|
409
|
-
const r = this.resolveMount(
|
|
410
|
-
if (!r) throw new Error(`No mount for path: ${
|
|
411
|
-
this.assertWritable(r.fs,
|
|
409
|
+
async rmdir(path8, options) {
|
|
410
|
+
const r = this.resolveMount(path8);
|
|
411
|
+
if (!r) throw new Error(`No mount for path: ${path8}`);
|
|
412
|
+
this.assertWritable(r.fs, path8, "rmdir");
|
|
412
413
|
return r.fs.rmdir(r.fsPath, options);
|
|
413
414
|
}
|
|
414
|
-
async exists(
|
|
415
|
-
if (this.isVirtualPath(
|
|
416
|
-
const r = this.resolveMount(
|
|
415
|
+
async exists(path8) {
|
|
416
|
+
if (this.isVirtualPath(path8)) return true;
|
|
417
|
+
const r = this.resolveMount(path8);
|
|
417
418
|
if (!r) return false;
|
|
418
419
|
if (r.fsPath === "") return true;
|
|
419
420
|
return r.fs.exists(r.fsPath);
|
|
420
421
|
}
|
|
421
|
-
async stat(
|
|
422
|
-
const normalized = this.normalizePath(
|
|
423
|
-
if (this.isVirtualPath(
|
|
422
|
+
async stat(path8) {
|
|
423
|
+
const normalized = this.normalizePath(path8);
|
|
424
|
+
if (this.isVirtualPath(path8)) {
|
|
424
425
|
const parts = normalized.split("/").filter(Boolean);
|
|
425
426
|
const now = /* @__PURE__ */ new Date();
|
|
426
427
|
return {
|
|
@@ -432,8 +433,8 @@ var CompositeFilesystem = class {
|
|
|
432
433
|
modifiedAt: now
|
|
433
434
|
};
|
|
434
435
|
}
|
|
435
|
-
const r = this.resolveMount(
|
|
436
|
-
if (!r) throw new Error(`No mount for path: ${
|
|
436
|
+
const r = this.resolveMount(path8);
|
|
437
|
+
if (!r) throw new Error(`No mount for path: ${path8}`);
|
|
437
438
|
if (r.fsPath === "") {
|
|
438
439
|
const parts = normalized.split("/").filter(Boolean);
|
|
439
440
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -448,9 +449,9 @@ var CompositeFilesystem = class {
|
|
|
448
449
|
}
|
|
449
450
|
return r.fs.stat(r.fsPath);
|
|
450
451
|
}
|
|
451
|
-
async isFile(
|
|
452
|
-
if (this.isVirtualPath(
|
|
453
|
-
const r = this.resolveMount(
|
|
452
|
+
async isFile(path8) {
|
|
453
|
+
if (this.isVirtualPath(path8)) return false;
|
|
454
|
+
const r = this.resolveMount(path8);
|
|
454
455
|
if (!r) return false;
|
|
455
456
|
try {
|
|
456
457
|
const stat3 = await r.fs.stat(r.fsPath);
|
|
@@ -459,9 +460,9 @@ var CompositeFilesystem = class {
|
|
|
459
460
|
return false;
|
|
460
461
|
}
|
|
461
462
|
}
|
|
462
|
-
async isDirectory(
|
|
463
|
-
if (this.isVirtualPath(
|
|
464
|
-
const r = this.resolveMount(
|
|
463
|
+
async isDirectory(path8) {
|
|
464
|
+
if (this.isVirtualPath(path8)) return true;
|
|
465
|
+
const r = this.resolveMount(path8);
|
|
465
466
|
if (!r) return false;
|
|
466
467
|
if (r.fsPath === "") return true;
|
|
467
468
|
try {
|
|
@@ -476,9 +477,9 @@ var CompositeFilesystem = class {
|
|
|
476
477
|
* Used by agents to understand available storage locations.
|
|
477
478
|
*/
|
|
478
479
|
getInstructions(_opts) {
|
|
479
|
-
const mountDescriptions = Array.from(this._mounts.entries()).map(([mountPath,
|
|
480
|
-
const name =
|
|
481
|
-
const access3 =
|
|
480
|
+
const mountDescriptions = Array.from(this._mounts.entries()).map(([mountPath, fs6]) => {
|
|
481
|
+
const name = fs6.displayName || fs6.provider;
|
|
482
|
+
const access3 = fs6.readOnly ? "(read-only)" : "(read-write)";
|
|
482
483
|
return `- ${mountPath}: ${name} ${access3}`;
|
|
483
484
|
}).join("\n");
|
|
484
485
|
return `Filesystem mount points:
|
|
@@ -1346,35 +1347,35 @@ var LocalFilesystem = class extends MastraFilesystem {
|
|
|
1346
1347
|
};
|
|
1347
1348
|
var InMemoryFileReadTracker = class {
|
|
1348
1349
|
records = /* @__PURE__ */ new Map();
|
|
1349
|
-
recordRead(
|
|
1350
|
-
const normalizedPath = this.normalizePath(
|
|
1350
|
+
recordRead(path8, modifiedAt) {
|
|
1351
|
+
const normalizedPath = this.normalizePath(path8);
|
|
1351
1352
|
this.records.set(normalizedPath, {
|
|
1352
1353
|
path: normalizedPath,
|
|
1353
1354
|
readAt: /* @__PURE__ */ new Date(),
|
|
1354
1355
|
modifiedAtRead: modifiedAt
|
|
1355
1356
|
});
|
|
1356
1357
|
}
|
|
1357
|
-
getReadRecord(
|
|
1358
|
-
return this.records.get(this.normalizePath(
|
|
1358
|
+
getReadRecord(path8) {
|
|
1359
|
+
return this.records.get(this.normalizePath(path8));
|
|
1359
1360
|
}
|
|
1360
|
-
needsReRead(
|
|
1361
|
-
const record = this.getReadRecord(
|
|
1361
|
+
needsReRead(path8, currentModifiedAt) {
|
|
1362
|
+
const record = this.getReadRecord(path8);
|
|
1362
1363
|
if (!record) {
|
|
1363
1364
|
return {
|
|
1364
1365
|
needsReRead: true,
|
|
1365
|
-
reason: `File "${
|
|
1366
|
+
reason: `File "${path8}" has not been read. You must read a file before writing to it.`
|
|
1366
1367
|
};
|
|
1367
1368
|
}
|
|
1368
1369
|
if (currentModifiedAt.getTime() > record.modifiedAtRead.getTime()) {
|
|
1369
1370
|
return {
|
|
1370
1371
|
needsReRead: true,
|
|
1371
|
-
reason: `File "${
|
|
1372
|
+
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.`
|
|
1372
1373
|
};
|
|
1373
1374
|
}
|
|
1374
1375
|
return { needsReRead: false };
|
|
1375
1376
|
}
|
|
1376
|
-
clearReadRecord(
|
|
1377
|
-
this.records.delete(this.normalizePath(
|
|
1377
|
+
clearReadRecord(path8) {
|
|
1378
|
+
this.records.delete(this.normalizePath(path8));
|
|
1378
1379
|
}
|
|
1379
1380
|
clear() {
|
|
1380
1381
|
this.records.clear();
|
|
@@ -1462,10 +1463,10 @@ function createGlobMatcher(patterns, options) {
|
|
|
1462
1463
|
posix: true,
|
|
1463
1464
|
dot: options?.dot ?? false
|
|
1464
1465
|
});
|
|
1465
|
-
return (
|
|
1466
|
+
return (path8) => matcher(normalizeForMatch(path8));
|
|
1466
1467
|
}
|
|
1467
|
-
function matchGlob(
|
|
1468
|
-
return createGlobMatcher(pattern, options)(
|
|
1468
|
+
function matchGlob(path8, pattern, options) {
|
|
1469
|
+
return createGlobMatcher(pattern, options)(path8);
|
|
1469
1470
|
}
|
|
1470
1471
|
async function walkAll(readdir4, dir, depth, maxDepth) {
|
|
1471
1472
|
if (depth >= maxDepth) return [];
|
|
@@ -1591,6 +1592,15 @@ async function loadLSPDeps() {
|
|
|
1591
1592
|
function toFileUri(fsPath) {
|
|
1592
1593
|
return pathToFileURL(fsPath).toString();
|
|
1593
1594
|
}
|
|
1595
|
+
async function withTimeout(promise, ms, errorMessage) {
|
|
1596
|
+
let timer;
|
|
1597
|
+
return Promise.race([
|
|
1598
|
+
promise,
|
|
1599
|
+
new Promise((_, reject) => {
|
|
1600
|
+
timer = setTimeout(() => reject(new Error(errorMessage)), ms);
|
|
1601
|
+
})
|
|
1602
|
+
]).finally(() => clearTimeout(timer));
|
|
1603
|
+
}
|
|
1594
1604
|
var LSPClient = class {
|
|
1595
1605
|
connection = null;
|
|
1596
1606
|
handle = null;
|
|
@@ -1608,6 +1618,10 @@ var LSPClient = class {
|
|
|
1608
1618
|
get isAlive() {
|
|
1609
1619
|
return this.handle !== null && this.handle.exitCode === void 0;
|
|
1610
1620
|
}
|
|
1621
|
+
/** Name of the LSP server. */
|
|
1622
|
+
get serverName() {
|
|
1623
|
+
return this.serverDef.name;
|
|
1624
|
+
}
|
|
1611
1625
|
/**
|
|
1612
1626
|
* Initialize the LSP connection — spawns the server and performs the handshake.
|
|
1613
1627
|
*/
|
|
@@ -1779,6 +1793,56 @@ var LSPClient = class {
|
|
|
1779
1793
|
textDocument: { uri }
|
|
1780
1794
|
});
|
|
1781
1795
|
}
|
|
1796
|
+
/**
|
|
1797
|
+
* Query hover information at a position.
|
|
1798
|
+
*/
|
|
1799
|
+
async queryHover(uri, position, timeoutMs = 5e3) {
|
|
1800
|
+
if (!this.connection) return null;
|
|
1801
|
+
return withTimeout(
|
|
1802
|
+
this.connection.sendRequest("textDocument/hover", { textDocument: { uri }, position }),
|
|
1803
|
+
timeoutMs,
|
|
1804
|
+
"Hover request timed out"
|
|
1805
|
+
);
|
|
1806
|
+
}
|
|
1807
|
+
/**
|
|
1808
|
+
* Query definition(s) at a position.
|
|
1809
|
+
*/
|
|
1810
|
+
async queryDefinition(uri, position, timeoutMs = 5e3) {
|
|
1811
|
+
if (!this.connection) return [];
|
|
1812
|
+
const result = await withTimeout(
|
|
1813
|
+
this.connection.sendRequest("textDocument/definition", { textDocument: { uri }, position }),
|
|
1814
|
+
timeoutMs,
|
|
1815
|
+
"Definition request timed out"
|
|
1816
|
+
);
|
|
1817
|
+
if (!result) return [];
|
|
1818
|
+
return Array.isArray(result) ? result : result.uri ? [result] : [];
|
|
1819
|
+
}
|
|
1820
|
+
/**
|
|
1821
|
+
* Query type definition(s) at a position.
|
|
1822
|
+
*/
|
|
1823
|
+
async queryTypeDefinition(uri, position, timeoutMs = 5e3) {
|
|
1824
|
+
if (!this.connection) return [];
|
|
1825
|
+
const result = await withTimeout(
|
|
1826
|
+
this.connection.sendRequest("textDocument/typeDefinition", { textDocument: { uri }, position }),
|
|
1827
|
+
timeoutMs,
|
|
1828
|
+
"Type definition request timed out"
|
|
1829
|
+
);
|
|
1830
|
+
if (!result) return [];
|
|
1831
|
+
return Array.isArray(result) ? result : result.uri ? [result] : [];
|
|
1832
|
+
}
|
|
1833
|
+
/**
|
|
1834
|
+
* Query implementation(s) at a position.
|
|
1835
|
+
*/
|
|
1836
|
+
async queryImplementation(uri, position, timeoutMs = 5e3) {
|
|
1837
|
+
if (!this.connection) return [];
|
|
1838
|
+
const result = await withTimeout(
|
|
1839
|
+
this.connection.sendRequest("textDocument/implementation", { textDocument: { uri }, position }),
|
|
1840
|
+
timeoutMs,
|
|
1841
|
+
"Implementation request timed out"
|
|
1842
|
+
);
|
|
1843
|
+
if (!result) return [];
|
|
1844
|
+
return Array.isArray(result) ? result : result.uri ? [result] : [];
|
|
1845
|
+
}
|
|
1782
1846
|
/**
|
|
1783
1847
|
* Shutdown the connection and kill the process.
|
|
1784
1848
|
*/
|
|
@@ -1874,12 +1938,12 @@ function walkUp(startDir, markers) {
|
|
|
1874
1938
|
}
|
|
1875
1939
|
return null;
|
|
1876
1940
|
}
|
|
1877
|
-
async function walkUpAsync(startDir, markers,
|
|
1941
|
+
async function walkUpAsync(startDir, markers, fs6) {
|
|
1878
1942
|
let current = startDir;
|
|
1879
1943
|
const fsRoot = parse(current).root;
|
|
1880
1944
|
while (true) {
|
|
1881
1945
|
for (const marker of markers) {
|
|
1882
|
-
if (await
|
|
1946
|
+
if (await fs6.exists(join(current, marker))) {
|
|
1883
1947
|
return current;
|
|
1884
1948
|
}
|
|
1885
1949
|
}
|
|
@@ -2126,6 +2190,28 @@ var LSPManager = class {
|
|
|
2126
2190
|
}
|
|
2127
2191
|
return this.initClient(serverDef, projectRoot, key);
|
|
2128
2192
|
}
|
|
2193
|
+
/**
|
|
2194
|
+
* Get LSP client ready to query a file.
|
|
2195
|
+
* Opens the file in the client so queries can be made.
|
|
2196
|
+
* Returns null when no LSP client is available.
|
|
2197
|
+
*/
|
|
2198
|
+
async prepareQuery(filePath) {
|
|
2199
|
+
const client = await this.getClient(filePath);
|
|
2200
|
+
if (!client) return null;
|
|
2201
|
+
const languageId = getLanguageId(filePath);
|
|
2202
|
+
if (!languageId) return null;
|
|
2203
|
+
const fs6 = await import('fs/promises');
|
|
2204
|
+
let content = "";
|
|
2205
|
+
try {
|
|
2206
|
+
content = await fs6.readFile(filePath, "utf-8");
|
|
2207
|
+
} catch {
|
|
2208
|
+
content = "";
|
|
2209
|
+
}
|
|
2210
|
+
client.notifyOpen(filePath, content, languageId);
|
|
2211
|
+
const { pathToFileURL: pathToFileURL3 } = await import('url');
|
|
2212
|
+
const uri = pathToFileURL3(filePath).toString();
|
|
2213
|
+
return { client, uri, languageId, serverName: client.serverName };
|
|
2214
|
+
}
|
|
2129
2215
|
/**
|
|
2130
2216
|
* Convenience method: open file, send content, wait for diagnostics, return normalized results.
|
|
2131
2217
|
* Returns null when no LSP client is available; otherwise returns diagnostics
|
|
@@ -2709,14 +2795,14 @@ var MountManager = class {
|
|
|
2709
2795
|
/**
|
|
2710
2796
|
* Get a mount entry by path.
|
|
2711
2797
|
*/
|
|
2712
|
-
get(
|
|
2713
|
-
return this._entries.get(
|
|
2798
|
+
get(path8) {
|
|
2799
|
+
return this._entries.get(path8);
|
|
2714
2800
|
}
|
|
2715
2801
|
/**
|
|
2716
2802
|
* Check if a mount exists at the given path.
|
|
2717
2803
|
*/
|
|
2718
|
-
has(
|
|
2719
|
-
return this._entries.has(
|
|
2804
|
+
has(path8) {
|
|
2805
|
+
return this._entries.has(path8);
|
|
2720
2806
|
}
|
|
2721
2807
|
// ---------------------------------------------------------------------------
|
|
2722
2808
|
// Entry Modification
|
|
@@ -2728,8 +2814,8 @@ var MountManager = class {
|
|
|
2728
2814
|
add(mounts) {
|
|
2729
2815
|
const paths = Object.keys(mounts);
|
|
2730
2816
|
this.logger.debug(`Adding ${paths.length} pending mount(s)`, { paths });
|
|
2731
|
-
for (const [
|
|
2732
|
-
this._entries.set(
|
|
2817
|
+
for (const [path8, filesystem] of Object.entries(mounts)) {
|
|
2818
|
+
this._entries.set(path8, {
|
|
2733
2819
|
filesystem,
|
|
2734
2820
|
state: "pending"
|
|
2735
2821
|
});
|
|
@@ -2739,8 +2825,8 @@ var MountManager = class {
|
|
|
2739
2825
|
* Update a mount entry's state.
|
|
2740
2826
|
* Creates the entry if it doesn't exist.
|
|
2741
2827
|
*/
|
|
2742
|
-
set(
|
|
2743
|
-
const existing = this._entries.get(
|
|
2828
|
+
set(path8, updates) {
|
|
2829
|
+
const existing = this._entries.get(path8);
|
|
2744
2830
|
if (existing) {
|
|
2745
2831
|
existing.state = updates.state;
|
|
2746
2832
|
if (updates.config) {
|
|
@@ -2751,7 +2837,7 @@ var MountManager = class {
|
|
|
2751
2837
|
existing.error = updates.error;
|
|
2752
2838
|
}
|
|
2753
2839
|
} else if (updates.filesystem) {
|
|
2754
|
-
this._entries.set(
|
|
2840
|
+
this._entries.set(path8, {
|
|
2755
2841
|
filesystem: updates.filesystem,
|
|
2756
2842
|
state: updates.state,
|
|
2757
2843
|
config: updates.config,
|
|
@@ -2759,14 +2845,14 @@ var MountManager = class {
|
|
|
2759
2845
|
error: updates.error
|
|
2760
2846
|
});
|
|
2761
2847
|
} else {
|
|
2762
|
-
this.logger.debug(`set() called for unknown path "${
|
|
2848
|
+
this.logger.debug(`set() called for unknown path "${path8}" without filesystem \u2014 no entry created`);
|
|
2763
2849
|
}
|
|
2764
2850
|
}
|
|
2765
2851
|
/**
|
|
2766
2852
|
* Delete a mount entry.
|
|
2767
2853
|
*/
|
|
2768
|
-
delete(
|
|
2769
|
-
return this._entries.delete(
|
|
2854
|
+
delete(path8) {
|
|
2855
|
+
return this._entries.delete(path8);
|
|
2770
2856
|
}
|
|
2771
2857
|
/**
|
|
2772
2858
|
* Clear all mount entries.
|
|
@@ -2787,7 +2873,7 @@ var MountManager = class {
|
|
|
2787
2873
|
return;
|
|
2788
2874
|
}
|
|
2789
2875
|
this.logger.debug(`Processing ${pendingCount} pending mount(s)`);
|
|
2790
|
-
for (const [
|
|
2876
|
+
for (const [path8, entry] of this._entries) {
|
|
2791
2877
|
if (entry.state !== "pending") {
|
|
2792
2878
|
continue;
|
|
2793
2879
|
}
|
|
@@ -2797,7 +2883,7 @@ var MountManager = class {
|
|
|
2797
2883
|
try {
|
|
2798
2884
|
const hookResult = await this._onMount({
|
|
2799
2885
|
filesystem: entry.filesystem,
|
|
2800
|
-
mountPath:
|
|
2886
|
+
mountPath: path8,
|
|
2801
2887
|
config,
|
|
2802
2888
|
sandbox: this._sandbox,
|
|
2803
2889
|
workspace: this._workspace
|
|
@@ -2805,7 +2891,7 @@ var MountManager = class {
|
|
|
2805
2891
|
if (hookResult === false) {
|
|
2806
2892
|
entry.state = "unsupported";
|
|
2807
2893
|
entry.error = "Skipped by onMount hook";
|
|
2808
|
-
this.logger.debug(`Mount skipped by onMount hook`, { path:
|
|
2894
|
+
this.logger.debug(`Mount skipped by onMount hook`, { path: path8, provider: fsProvider });
|
|
2809
2895
|
continue;
|
|
2810
2896
|
}
|
|
2811
2897
|
if (hookResult && typeof hookResult === "object") {
|
|
@@ -2813,54 +2899,54 @@ var MountManager = class {
|
|
|
2813
2899
|
entry.state = "mounted";
|
|
2814
2900
|
entry.config = config;
|
|
2815
2901
|
entry.configHash = config ? this.hashConfig(config) : void 0;
|
|
2816
|
-
this.logger.info(`Mount handled by onMount hook`, { path:
|
|
2902
|
+
this.logger.info(`Mount handled by onMount hook`, { path: path8, provider: fsProvider });
|
|
2817
2903
|
} else {
|
|
2818
2904
|
entry.state = "error";
|
|
2819
2905
|
entry.error = hookResult.error ?? "Mount hook failed";
|
|
2820
|
-
this.logger.error(`Mount hook failed`, { path:
|
|
2906
|
+
this.logger.error(`Mount hook failed`, { path: path8, provider: fsProvider, error: entry.error });
|
|
2821
2907
|
}
|
|
2822
2908
|
continue;
|
|
2823
2909
|
}
|
|
2824
2910
|
} catch (err) {
|
|
2825
2911
|
entry.state = "error";
|
|
2826
2912
|
entry.error = `Mount hook error: ${String(err)}`;
|
|
2827
|
-
this.logger.error(`Mount hook threw error`, { path:
|
|
2913
|
+
this.logger.error(`Mount hook threw error`, { path: path8, provider: fsProvider, error: entry.error });
|
|
2828
2914
|
continue;
|
|
2829
2915
|
}
|
|
2830
2916
|
}
|
|
2831
2917
|
if (!config) {
|
|
2832
2918
|
entry.state = "unsupported";
|
|
2833
2919
|
entry.error = "Filesystem does not support mounting";
|
|
2834
|
-
this.logger.debug(`Filesystem does not support mounting`, { path:
|
|
2920
|
+
this.logger.debug(`Filesystem does not support mounting`, { path: path8, provider: fsProvider });
|
|
2835
2921
|
continue;
|
|
2836
2922
|
}
|
|
2837
2923
|
entry.config = config;
|
|
2838
2924
|
entry.configHash = this.hashConfig(config);
|
|
2839
2925
|
entry.state = "mounting";
|
|
2840
|
-
this.logger.debug(`Mounting filesystem`, { path:
|
|
2926
|
+
this.logger.debug(`Mounting filesystem`, { path: path8, provider: fsProvider, type: config.type });
|
|
2841
2927
|
try {
|
|
2842
|
-
const result = await this._mountFn(entry.filesystem,
|
|
2928
|
+
const result = await this._mountFn(entry.filesystem, path8);
|
|
2843
2929
|
if (result.success) {
|
|
2844
2930
|
entry.state = "mounted";
|
|
2845
|
-
this.logger.info(`Mount successful`, { path:
|
|
2931
|
+
this.logger.info(`Mount successful`, { path: path8, provider: fsProvider });
|
|
2846
2932
|
} else if (result.unavailable) {
|
|
2847
2933
|
entry.state = "unavailable";
|
|
2848
2934
|
entry.error = result.error ?? "FUSE tool not installed";
|
|
2849
|
-
this.logger.warn(`FUSE mount unavailable`, { path:
|
|
2935
|
+
this.logger.warn(`FUSE mount unavailable`, { path: path8, provider: fsProvider, error: entry.error });
|
|
2850
2936
|
} else {
|
|
2851
2937
|
entry.state = "error";
|
|
2852
2938
|
entry.error = result.error ?? "Mount failed";
|
|
2853
|
-
this.logger.error(`Mount failed`, { path:
|
|
2939
|
+
this.logger.error(`Mount failed`, { path: path8, provider: fsProvider, error: entry.error });
|
|
2854
2940
|
}
|
|
2855
2941
|
} catch (err) {
|
|
2856
2942
|
if (err instanceof MountToolNotFoundError) {
|
|
2857
2943
|
entry.state = "unavailable";
|
|
2858
2944
|
entry.error = String(err);
|
|
2859
|
-
this.logger.warn(`FUSE mount unavailable`, { path:
|
|
2945
|
+
this.logger.warn(`FUSE mount unavailable`, { path: path8, provider: fsProvider, error: entry.error });
|
|
2860
2946
|
} else {
|
|
2861
2947
|
entry.state = "error";
|
|
2862
2948
|
entry.error = String(err);
|
|
2863
|
-
this.logger.error(`Mount threw error`, { path:
|
|
2949
|
+
this.logger.error(`Mount threw error`, { path: path8, provider: fsProvider, error: entry.error });
|
|
2864
2950
|
}
|
|
2865
2951
|
}
|
|
2866
2952
|
}
|
|
@@ -2909,10 +2995,10 @@ var MountManager = class {
|
|
|
2909
2995
|
if (separatorIndex <= 0) {
|
|
2910
2996
|
return null;
|
|
2911
2997
|
}
|
|
2912
|
-
const
|
|
2998
|
+
const path8 = content.slice(0, separatorIndex);
|
|
2913
2999
|
const configHash = content.slice(separatorIndex + 1);
|
|
2914
|
-
if (!
|
|
2915
|
-
return { path:
|
|
3000
|
+
if (!path8 || !configHash) return null;
|
|
3001
|
+
return { path: path8, configHash };
|
|
2916
3002
|
}
|
|
2917
3003
|
/**
|
|
2918
3004
|
* Check if a config hash matches the expected hash for a mount path.
|
|
@@ -3398,11 +3484,11 @@ function buildBwrapCommand(command, workspacePath, config) {
|
|
|
3398
3484
|
}
|
|
3399
3485
|
bwrapArgs.push("--proc", "/proc");
|
|
3400
3486
|
bwrapArgs.push("--tmpfs", "/tmp");
|
|
3401
|
-
for (const
|
|
3402
|
-
bwrapArgs.push("--ro-bind-try",
|
|
3487
|
+
for (const path8 of DEFAULT_READONLY_BINDS) {
|
|
3488
|
+
bwrapArgs.push("--ro-bind-try", path8, path8);
|
|
3403
3489
|
}
|
|
3404
|
-
for (const
|
|
3405
|
-
bwrapArgs.push("--ro-bind",
|
|
3490
|
+
for (const path8 of config.readOnlyPaths ?? []) {
|
|
3491
|
+
bwrapArgs.push("--ro-bind", path8, path8);
|
|
3406
3492
|
}
|
|
3407
3493
|
if (config.allowSystemBinaries !== false) {
|
|
3408
3494
|
const nodePath4 = process.execPath;
|
|
@@ -3414,8 +3500,8 @@ function buildBwrapCommand(command, workspacePath, config) {
|
|
|
3414
3500
|
bwrapArgs.push("--ro-bind-try", "/snap", "/snap");
|
|
3415
3501
|
}
|
|
3416
3502
|
bwrapArgs.push("--bind", workspacePath, workspacePath);
|
|
3417
|
-
for (const
|
|
3418
|
-
bwrapArgs.push("--bind",
|
|
3503
|
+
for (const path8 of config.readWritePaths ?? []) {
|
|
3504
|
+
bwrapArgs.push("--bind", path8, path8);
|
|
3419
3505
|
}
|
|
3420
3506
|
bwrapArgs.push("--chdir", workspacePath);
|
|
3421
3507
|
bwrapArgs.push("--die-with-parent");
|
|
@@ -4823,18 +4909,18 @@ var VersionedSkillSource = class {
|
|
|
4823
4909
|
/**
|
|
4824
4910
|
* Normalize a path by stripping leading/trailing slashes and dots.
|
|
4825
4911
|
*/
|
|
4826
|
-
#normalizePath(
|
|
4827
|
-
let normalized =
|
|
4912
|
+
#normalizePath(path8) {
|
|
4913
|
+
let normalized = path8.replace(/^[./\\]+|[/\\]+$/g, "");
|
|
4828
4914
|
if (normalized === "") return "";
|
|
4829
4915
|
return normalized;
|
|
4830
4916
|
}
|
|
4831
|
-
async exists(
|
|
4832
|
-
const normalized = this.#normalizePath(
|
|
4917
|
+
async exists(path8) {
|
|
4918
|
+
const normalized = this.#normalizePath(path8);
|
|
4833
4919
|
if (this.#tree.entries[normalized]) return true;
|
|
4834
4920
|
return this.#directories.has(normalized);
|
|
4835
4921
|
}
|
|
4836
|
-
async stat(
|
|
4837
|
-
const normalized = this.#normalizePath(
|
|
4922
|
+
async stat(path8) {
|
|
4923
|
+
const normalized = this.#normalizePath(path8);
|
|
4838
4924
|
const name = normalized.split("/").pop() || normalized || ".";
|
|
4839
4925
|
const entry = this.#tree.entries[normalized];
|
|
4840
4926
|
if (entry) {
|
|
@@ -4856,27 +4942,27 @@ var VersionedSkillSource = class {
|
|
|
4856
4942
|
modifiedAt: this.#versionCreatedAt
|
|
4857
4943
|
};
|
|
4858
4944
|
}
|
|
4859
|
-
throw new Error(`Path not found in skill version tree: ${
|
|
4945
|
+
throw new Error(`Path not found in skill version tree: ${path8}`);
|
|
4860
4946
|
}
|
|
4861
|
-
async readFile(
|
|
4862
|
-
const normalized = this.#normalizePath(
|
|
4947
|
+
async readFile(path8) {
|
|
4948
|
+
const normalized = this.#normalizePath(path8);
|
|
4863
4949
|
const entry = this.#tree.entries[normalized];
|
|
4864
4950
|
if (!entry) {
|
|
4865
|
-
throw new Error(`File not found in skill version tree: ${
|
|
4951
|
+
throw new Error(`File not found in skill version tree: ${path8}`);
|
|
4866
4952
|
}
|
|
4867
4953
|
const blob = await this.#blobStore.get(entry.blobHash);
|
|
4868
4954
|
if (!blob) {
|
|
4869
|
-
throw new Error(`Blob not found for hash ${entry.blobHash} (file: ${
|
|
4955
|
+
throw new Error(`Blob not found for hash ${entry.blobHash} (file: ${path8})`);
|
|
4870
4956
|
}
|
|
4871
4957
|
if (entry.encoding === "base64") {
|
|
4872
4958
|
return Buffer.from(blob.content, "base64");
|
|
4873
4959
|
}
|
|
4874
4960
|
return blob.content;
|
|
4875
4961
|
}
|
|
4876
|
-
async readdir(
|
|
4877
|
-
const normalized = this.#normalizePath(
|
|
4962
|
+
async readdir(path8) {
|
|
4963
|
+
const normalized = this.#normalizePath(path8);
|
|
4878
4964
|
if (!this.#directories.has(normalized)) {
|
|
4879
|
-
throw new Error(`Directory not found in skill version tree: ${
|
|
4965
|
+
throw new Error(`Directory not found in skill version tree: ${path8}`);
|
|
4880
4966
|
}
|
|
4881
4967
|
const prefix = normalized === "" ? "" : normalized + "/";
|
|
4882
4968
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -4909,15 +4995,15 @@ var CompositeVersionedSkillSource = class {
|
|
|
4909
4995
|
this.#fallback = options?.fallback;
|
|
4910
4996
|
this.#fallbackSkills = new Set(options?.fallbackSkills ?? []);
|
|
4911
4997
|
}
|
|
4912
|
-
#normalizePath(
|
|
4913
|
-
return
|
|
4998
|
+
#normalizePath(path8) {
|
|
4999
|
+
return path8.replace(/^[./\\]+|[/\\]+$/g, "");
|
|
4914
5000
|
}
|
|
4915
5001
|
/**
|
|
4916
5002
|
* Route a path to the correct source.
|
|
4917
5003
|
* Returns the source and the remaining path within that source.
|
|
4918
5004
|
*/
|
|
4919
|
-
#routePath(
|
|
4920
|
-
const normalized = this.#normalizePath(
|
|
5005
|
+
#routePath(path8) {
|
|
5006
|
+
const normalized = this.#normalizePath(path8);
|
|
4921
5007
|
if (normalized === "") return null;
|
|
4922
5008
|
const segments = normalized.split("/");
|
|
4923
5009
|
const skillDir = segments[0];
|
|
@@ -4934,15 +5020,15 @@ var CompositeVersionedSkillSource = class {
|
|
|
4934
5020
|
}
|
|
4935
5021
|
return null;
|
|
4936
5022
|
}
|
|
4937
|
-
async exists(
|
|
4938
|
-
const normalized = this.#normalizePath(
|
|
5023
|
+
async exists(path8) {
|
|
5024
|
+
const normalized = this.#normalizePath(path8);
|
|
4939
5025
|
if (normalized === "") return true;
|
|
4940
|
-
const route = this.#routePath(
|
|
5026
|
+
const route = this.#routePath(path8);
|
|
4941
5027
|
if (!route) return false;
|
|
4942
5028
|
return route.source.exists(route.subPath);
|
|
4943
5029
|
}
|
|
4944
|
-
async stat(
|
|
4945
|
-
const normalized = this.#normalizePath(
|
|
5030
|
+
async stat(path8) {
|
|
5031
|
+
const normalized = this.#normalizePath(path8);
|
|
4946
5032
|
if (normalized === "") {
|
|
4947
5033
|
return {
|
|
4948
5034
|
name: ".",
|
|
@@ -4952,21 +5038,21 @@ var CompositeVersionedSkillSource = class {
|
|
|
4952
5038
|
modifiedAt: /* @__PURE__ */ new Date()
|
|
4953
5039
|
};
|
|
4954
5040
|
}
|
|
4955
|
-
const route = this.#routePath(
|
|
5041
|
+
const route = this.#routePath(path8);
|
|
4956
5042
|
if (!route) {
|
|
4957
|
-
throw new Error(`Path not found in composite skill source: ${
|
|
5043
|
+
throw new Error(`Path not found in composite skill source: ${path8}`);
|
|
4958
5044
|
}
|
|
4959
5045
|
return route.source.stat(route.subPath);
|
|
4960
5046
|
}
|
|
4961
|
-
async readFile(
|
|
4962
|
-
const route = this.#routePath(
|
|
5047
|
+
async readFile(path8) {
|
|
5048
|
+
const route = this.#routePath(path8);
|
|
4963
5049
|
if (!route) {
|
|
4964
|
-
throw new Error(`File not found in composite skill source: ${
|
|
5050
|
+
throw new Error(`File not found in composite skill source: ${path8}`);
|
|
4965
5051
|
}
|
|
4966
5052
|
return route.source.readFile(route.subPath);
|
|
4967
5053
|
}
|
|
4968
|
-
async readdir(
|
|
4969
|
-
const normalized = this.#normalizePath(
|
|
5054
|
+
async readdir(path8) {
|
|
5055
|
+
const normalized = this.#normalizePath(path8);
|
|
4970
5056
|
if (normalized === "") {
|
|
4971
5057
|
const entries = [];
|
|
4972
5058
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -4982,9 +5068,9 @@ var CompositeVersionedSkillSource = class {
|
|
|
4982
5068
|
}
|
|
4983
5069
|
return entries;
|
|
4984
5070
|
}
|
|
4985
|
-
const route = this.#routePath(
|
|
5071
|
+
const route = this.#routePath(path8);
|
|
4986
5072
|
if (!route) {
|
|
4987
|
-
throw new Error(`Directory not found in composite skill source: ${
|
|
5073
|
+
throw new Error(`Directory not found in composite skill source: ${path8}`);
|
|
4988
5074
|
}
|
|
4989
5075
|
return route.source.readdir(route.subPath);
|
|
4990
5076
|
}
|
|
@@ -5184,7 +5270,7 @@ var WorkspaceSkillsImpl = class _WorkspaceSkillsImpl {
|
|
|
5184
5270
|
if (a.length !== b.length) return false;
|
|
5185
5271
|
const sortedA = [...a].sort();
|
|
5186
5272
|
const sortedB = [...b].sort();
|
|
5187
|
-
return sortedA.every((
|
|
5273
|
+
return sortedA.every((path8, i) => path8 === sortedB[i]);
|
|
5188
5274
|
}
|
|
5189
5275
|
// ===========================================================================
|
|
5190
5276
|
// Search
|
|
@@ -5790,9 +5876,9 @@ ${validation.errors.join("\n")}`);
|
|
|
5790
5876
|
/**
|
|
5791
5877
|
* Get parent path
|
|
5792
5878
|
*/
|
|
5793
|
-
#getParentPath(
|
|
5794
|
-
const lastSlash =
|
|
5795
|
-
return lastSlash > 0 ?
|
|
5879
|
+
#getParentPath(path8) {
|
|
5880
|
+
const lastSlash = path8.lastIndexOf("/");
|
|
5881
|
+
return lastSlash > 0 ? path8.substring(0, lastSlash) : "/";
|
|
5796
5882
|
}
|
|
5797
5883
|
};
|
|
5798
5884
|
function hashContent(content) {
|
|
@@ -6023,14 +6109,14 @@ function createSkillReadTool(skills) {
|
|
|
6023
6109
|
startLine: z.number().optional().describe("Starting line number (1-indexed). If omitted, starts from the beginning."),
|
|
6024
6110
|
endLine: z.number().optional().describe("Ending line number (1-indexed, inclusive). If omitted, reads to the end.")
|
|
6025
6111
|
}),
|
|
6026
|
-
execute: async ({ skillName, path:
|
|
6112
|
+
execute: async ({ skillName, path: path8, startLine, endLine }) => {
|
|
6027
6113
|
const resolved = await resolveSkill(skills, skillName);
|
|
6028
6114
|
if ("notFound" in resolved) return resolved.notFound;
|
|
6029
6115
|
const resolvedPath = resolved.skill.path;
|
|
6030
6116
|
let content = null;
|
|
6031
|
-
content = await skills.getReference(resolvedPath,
|
|
6032
|
-
if (content === null) content = await skills.getScript(resolvedPath,
|
|
6033
|
-
if (content === null) content = await skills.getAsset(resolvedPath,
|
|
6117
|
+
content = await skills.getReference(resolvedPath, path8);
|
|
6118
|
+
if (content === null) content = await skills.getScript(resolvedPath, path8);
|
|
6119
|
+
if (content === null) content = await skills.getAsset(resolvedPath, path8);
|
|
6034
6120
|
if (content === null) {
|
|
6035
6121
|
const refs = (await skills.listReferences(resolvedPath)).map((f) => `references/${f}`);
|
|
6036
6122
|
const scriptsList = (await skills.listScripts(resolvedPath)).map((f) => `scripts/${f}`);
|
|
@@ -6038,11 +6124,11 @@ function createSkillReadTool(skills) {
|
|
|
6038
6124
|
const allFiles = [...refs, ...scriptsList, ...assets];
|
|
6039
6125
|
const fileList = allFiles.length > 0 ? `
|
|
6040
6126
|
Available files: ${allFiles.join(", ")}` : "";
|
|
6041
|
-
return `File "${
|
|
6127
|
+
return `File "${path8}" not found in skill "${skillName}".${fileList}`;
|
|
6042
6128
|
}
|
|
6043
6129
|
const textContent = typeof content === "string" ? content : content.toString("utf-8");
|
|
6044
6130
|
if (textContent.slice(0, 1e3).includes("\0")) {
|
|
6045
|
-
const fullPath = `${resolved.skill.path}/${
|
|
6131
|
+
const fullPath = `${resolved.skill.path}/${path8}`;
|
|
6046
6132
|
const size = typeof content === "string" ? Buffer.byteLength(content) : content.length;
|
|
6047
6133
|
return `Binary file: ${fullPath} (${size} bytes)`;
|
|
6048
6134
|
}
|
|
@@ -6078,8 +6164,8 @@ var Workspace = class {
|
|
|
6078
6164
|
if (config.filesystem) {
|
|
6079
6165
|
throw new WorkspaceError('Cannot use both "filesystem" and "mounts"', "INVALID_CONFIG");
|
|
6080
6166
|
}
|
|
6081
|
-
for (const [mountPath,
|
|
6082
|
-
if (
|
|
6167
|
+
for (const [mountPath, fs6] of Object.entries(config.mounts)) {
|
|
6168
|
+
if (fs6 instanceof LocalFilesystem && !fs6.contained) {
|
|
6083
6169
|
console.warn(
|
|
6084
6170
|
`[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.`
|
|
6085
6171
|
);
|
|
@@ -6275,13 +6361,13 @@ var Workspace = class {
|
|
|
6275
6361
|
* @param options - Index options (metadata, type hints)
|
|
6276
6362
|
* @throws {SearchNotAvailableError} if search is not configured
|
|
6277
6363
|
*/
|
|
6278
|
-
async index(
|
|
6364
|
+
async index(path8, content, options) {
|
|
6279
6365
|
if (!this._searchEngine) {
|
|
6280
6366
|
throw new SearchNotAvailableError();
|
|
6281
6367
|
}
|
|
6282
6368
|
this.lastAccessedAt = /* @__PURE__ */ new Date();
|
|
6283
6369
|
const doc = {
|
|
6284
|
-
id:
|
|
6370
|
+
id: path8,
|
|
6285
6371
|
content,
|
|
6286
6372
|
metadata: {
|
|
6287
6373
|
type: options?.type,
|
|
@@ -6590,6 +6676,9 @@ var WORKSPACE_TOOLS = {
|
|
|
6590
6676
|
SEARCH: {
|
|
6591
6677
|
SEARCH: `${WORKSPACE_TOOLS_PREFIX}_search`,
|
|
6592
6678
|
INDEX: `${WORKSPACE_TOOLS_PREFIX}_index`
|
|
6679
|
+
},
|
|
6680
|
+
LSP: {
|
|
6681
|
+
LSP_INSPECT: `${WORKSPACE_TOOLS_PREFIX}_lsp_inspect`
|
|
6593
6682
|
}
|
|
6594
6683
|
};
|
|
6595
6684
|
function requireWorkspace(context) {
|
|
@@ -6912,7 +7001,7 @@ Pattern replace (for everything else):
|
|
|
6912
7001
|
isDefault: z.boolean().optional().describe("Whether the first name is a default import")
|
|
6913
7002
|
}).optional().describe("Required for add-import transform. Specifies the module and names to import.")
|
|
6914
7003
|
}),
|
|
6915
|
-
execute: async ({ path:
|
|
7004
|
+
execute: async ({ path: path8, pattern, replacement, transform, targetName, newName, importSpec }, context) => {
|
|
6916
7005
|
const { workspace, filesystem } = requireFilesystem(context);
|
|
6917
7006
|
await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.AST_EDIT);
|
|
6918
7007
|
if (filesystem.readOnly) {
|
|
@@ -6925,19 +7014,19 @@ Pattern replace (for everything else):
|
|
|
6925
7014
|
const { parse: parse2, Lang } = astGrep;
|
|
6926
7015
|
let content;
|
|
6927
7016
|
try {
|
|
6928
|
-
content = await filesystem.readFile(
|
|
7017
|
+
content = await filesystem.readFile(path8, { encoding: "utf-8" });
|
|
6929
7018
|
} catch (error) {
|
|
6930
7019
|
if (error instanceof FileNotFoundError) {
|
|
6931
|
-
return `File not found: ${
|
|
7020
|
+
return `File not found: ${path8}. Use the write file tool to create it first.`;
|
|
6932
7021
|
}
|
|
6933
7022
|
throw error;
|
|
6934
7023
|
}
|
|
6935
7024
|
if (typeof content !== "string") {
|
|
6936
7025
|
return `Cannot perform AST edits on binary files. Use the write file tool instead.`;
|
|
6937
7026
|
}
|
|
6938
|
-
const lang = getLanguageFromPath(
|
|
7027
|
+
const lang = getLanguageFromPath(path8, Lang);
|
|
6939
7028
|
if (!lang) {
|
|
6940
|
-
return `Unsupported file type for AST editing: ${
|
|
7029
|
+
return `Unsupported file type for AST editing: ${path8}`;
|
|
6941
7030
|
}
|
|
6942
7031
|
const ast = parse2(lang, content);
|
|
6943
7032
|
const root = ast.root();
|
|
@@ -6987,16 +7076,16 @@ Pattern replace (for everything else):
|
|
|
6987
7076
|
}
|
|
6988
7077
|
const wasModified = modifiedContent !== content;
|
|
6989
7078
|
if (wasModified) {
|
|
6990
|
-
await filesystem.writeFile(
|
|
7079
|
+
await filesystem.writeFile(path8, modifiedContent, {
|
|
6991
7080
|
overwrite: true,
|
|
6992
7081
|
expectedMtime: context?.__expectedMtime
|
|
6993
7082
|
});
|
|
6994
7083
|
}
|
|
6995
7084
|
if (!wasModified) {
|
|
6996
|
-
return `No changes made to ${
|
|
7085
|
+
return `No changes made to ${path8} (${changes.join("; ")})`;
|
|
6997
7086
|
}
|
|
6998
|
-
let output = `${
|
|
6999
|
-
output += await getEditDiagnosticsText(workspace,
|
|
7087
|
+
let output = `${path8}: ${changes.join("; ")}`;
|
|
7088
|
+
output += await getEditDiagnosticsText(workspace, path8, modifiedContent);
|
|
7000
7089
|
return output;
|
|
7001
7090
|
}
|
|
7002
7091
|
});
|
|
@@ -7007,19 +7096,19 @@ var deleteFileTool = createTool({
|
|
|
7007
7096
|
path: z.string().describe("The path to the file or directory to delete"),
|
|
7008
7097
|
recursive: z.boolean().optional().default(false).describe("If true, delete directories and their contents recursively. Required for non-empty directories.")
|
|
7009
7098
|
}),
|
|
7010
|
-
execute: async ({ path:
|
|
7099
|
+
execute: async ({ path: path8, recursive }, context) => {
|
|
7011
7100
|
const { filesystem } = requireFilesystem(context);
|
|
7012
7101
|
await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.DELETE);
|
|
7013
7102
|
if (filesystem.readOnly) {
|
|
7014
7103
|
throw new WorkspaceReadOnlyError("delete");
|
|
7015
7104
|
}
|
|
7016
|
-
const stat3 = await filesystem.stat(
|
|
7105
|
+
const stat3 = await filesystem.stat(path8);
|
|
7017
7106
|
if (stat3.type === "directory") {
|
|
7018
|
-
await filesystem.rmdir(
|
|
7107
|
+
await filesystem.rmdir(path8, { recursive, force: recursive });
|
|
7019
7108
|
} else {
|
|
7020
|
-
await filesystem.deleteFile(
|
|
7109
|
+
await filesystem.deleteFile(path8);
|
|
7021
7110
|
}
|
|
7022
|
-
return `Deleted ${
|
|
7111
|
+
return `Deleted ${path8}`;
|
|
7023
7112
|
}
|
|
7024
7113
|
});
|
|
7025
7114
|
var editFileTool = createTool({
|
|
@@ -7037,24 +7126,24 @@ Usage:
|
|
|
7037
7126
|
new_string: z.string().describe("The text to replace old_string with"),
|
|
7038
7127
|
replace_all: z.boolean().optional().default(false).describe("If true, replace all occurrences. If false (default), old_string must be unique.")
|
|
7039
7128
|
}),
|
|
7040
|
-
execute: async ({ path:
|
|
7129
|
+
execute: async ({ path: path8, old_string, new_string, replace_all }, context) => {
|
|
7041
7130
|
const { workspace, filesystem } = requireFilesystem(context);
|
|
7042
7131
|
await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.EDIT_FILE);
|
|
7043
7132
|
if (filesystem.readOnly) {
|
|
7044
7133
|
throw new WorkspaceReadOnlyError("edit_file");
|
|
7045
7134
|
}
|
|
7046
7135
|
try {
|
|
7047
|
-
const content = await filesystem.readFile(
|
|
7136
|
+
const content = await filesystem.readFile(path8, { encoding: "utf-8" });
|
|
7048
7137
|
if (typeof content !== "string") {
|
|
7049
7138
|
return `Cannot edit binary files. Use the write file tool instead.`;
|
|
7050
7139
|
}
|
|
7051
7140
|
const result = replaceString(content, old_string, new_string, replace_all);
|
|
7052
|
-
await filesystem.writeFile(
|
|
7141
|
+
await filesystem.writeFile(path8, result.content, {
|
|
7053
7142
|
overwrite: true,
|
|
7054
7143
|
expectedMtime: context?.__expectedMtime
|
|
7055
7144
|
});
|
|
7056
|
-
let output = `Replaced ${result.replacements} occurrence${result.replacements !== 1 ? "s" : ""} in ${
|
|
7057
|
-
output += await getEditDiagnosticsText(workspace,
|
|
7145
|
+
let output = `Replaced ${result.replacements} occurrence${result.replacements !== 1 ? "s" : ""} in ${path8}`;
|
|
7146
|
+
output += await getEditDiagnosticsText(workspace, path8, result.content);
|
|
7058
7147
|
return output;
|
|
7059
7148
|
} catch (error) {
|
|
7060
7149
|
if (error instanceof StringNotFoundError) {
|
|
@@ -7306,19 +7395,19 @@ var fileStatTool = createTool({
|
|
|
7306
7395
|
inputSchema: z.object({
|
|
7307
7396
|
path: z.string().describe("The path to check")
|
|
7308
7397
|
}),
|
|
7309
|
-
execute: async ({ path:
|
|
7398
|
+
execute: async ({ path: path8 }, context) => {
|
|
7310
7399
|
const { filesystem } = requireFilesystem(context);
|
|
7311
7400
|
await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.FILE_STAT);
|
|
7312
7401
|
try {
|
|
7313
|
-
const stat3 = await filesystem.stat(
|
|
7402
|
+
const stat3 = await filesystem.stat(path8);
|
|
7314
7403
|
const modifiedAt = stat3.modifiedAt.toISOString();
|
|
7315
|
-
const parts = [`${
|
|
7404
|
+
const parts = [`${path8}`, `Type: ${stat3.type}`];
|
|
7316
7405
|
if (stat3.size !== void 0) parts.push(`Size: ${stat3.size} bytes`);
|
|
7317
7406
|
parts.push(`Modified: ${modifiedAt}`);
|
|
7318
7407
|
return parts.join(" ");
|
|
7319
7408
|
} catch (error) {
|
|
7320
7409
|
if (error instanceof FileNotFoundError) {
|
|
7321
|
-
return `${
|
|
7410
|
+
return `${path8}: not found`;
|
|
7322
7411
|
}
|
|
7323
7412
|
throw error;
|
|
7324
7413
|
}
|
|
@@ -7584,11 +7673,11 @@ var indexContentTool = createTool({
|
|
|
7584
7673
|
content: z.string().describe("The text content to index"),
|
|
7585
7674
|
metadata: z.record(z.string(), z.unknown()).optional().describe("Optional metadata to store with the document")
|
|
7586
7675
|
}),
|
|
7587
|
-
execute: async ({ path:
|
|
7676
|
+
execute: async ({ path: path8, content, metadata }, context) => {
|
|
7588
7677
|
const workspace = requireWorkspace(context);
|
|
7589
7678
|
await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.SEARCH.INDEX);
|
|
7590
|
-
await workspace.index(
|
|
7591
|
-
return `Indexed ${
|
|
7679
|
+
await workspace.index(path8, content, { metadata });
|
|
7680
|
+
return `Indexed ${path8}`;
|
|
7592
7681
|
}
|
|
7593
7682
|
});
|
|
7594
7683
|
var KILL_TAIL_LINES = 50;
|
|
@@ -7644,7 +7733,7 @@ Use this to stop a long-running background process that was started with execute
|
|
|
7644
7733
|
});
|
|
7645
7734
|
|
|
7646
7735
|
// src/workspace/tools/tree-formatter.ts
|
|
7647
|
-
async function formatAsTree(
|
|
7736
|
+
async function formatAsTree(fs6, path8, options) {
|
|
7648
7737
|
const maxDepth = options?.maxDepth ?? Infinity;
|
|
7649
7738
|
const showHidden = options?.showHidden ?? false;
|
|
7650
7739
|
const dirsOnly = options?.dirsOnly ?? false;
|
|
@@ -7654,9 +7743,9 @@ async function formatAsTree(fs5, path7, options) {
|
|
|
7654
7743
|
const respectGitignore = options?.respectGitignore ?? true;
|
|
7655
7744
|
let ignoreFilter = options?.ignoreFilter;
|
|
7656
7745
|
if (!ignoreFilter && respectGitignore) {
|
|
7657
|
-
const rawFilter = await loadGitignore(
|
|
7746
|
+
const rawFilter = await loadGitignore(fs6);
|
|
7658
7747
|
if (rawFilter) {
|
|
7659
|
-
const normalizedPath =
|
|
7748
|
+
const normalizedPath = path8.replace(/^\.\//, "").replace(/^\//, "").replace(/\/$/, "");
|
|
7660
7749
|
const targetIsIgnored = normalizedPath && rawFilter(normalizedPath + "/");
|
|
7661
7750
|
ignoreFilter = targetIsIgnored ? void 0 : rawFilter;
|
|
7662
7751
|
}
|
|
@@ -7678,7 +7767,7 @@ async function formatAsTree(fs5, path7, options) {
|
|
|
7678
7767
|
}
|
|
7679
7768
|
let entries;
|
|
7680
7769
|
try {
|
|
7681
|
-
entries = await
|
|
7770
|
+
entries = await fs6.readdir(currentPath);
|
|
7682
7771
|
} catch (error) {
|
|
7683
7772
|
if (depth === 0) {
|
|
7684
7773
|
throw error;
|
|
@@ -7718,7 +7807,7 @@ async function formatAsTree(fs5, path7, options) {
|
|
|
7718
7807
|
if (globMatcher && !dirsOnly) {
|
|
7719
7808
|
filtered = filtered.filter((e) => {
|
|
7720
7809
|
if (e.type === "directory") return true;
|
|
7721
|
-
const relativePath = getRelativePath(
|
|
7810
|
+
const relativePath = getRelativePath(path8, currentPath, e.name);
|
|
7722
7811
|
return globMatcher(relativePath);
|
|
7723
7812
|
});
|
|
7724
7813
|
}
|
|
@@ -7732,7 +7821,7 @@ async function formatAsTree(fs5, path7, options) {
|
|
|
7732
7821
|
const entry = filtered[i];
|
|
7733
7822
|
const displayName = entry.isSymlink && entry.symlinkTarget ? `${entry.name} -> ${entry.symlinkTarget}` : entry.name;
|
|
7734
7823
|
lines.push(`${indent}${displayName}`);
|
|
7735
|
-
paths.push(getRelativePath(
|
|
7824
|
+
paths.push(getRelativePath(path8, currentPath, entry.name));
|
|
7736
7825
|
if (entry.type === "directory") {
|
|
7737
7826
|
dirCount++;
|
|
7738
7827
|
if (!entry.isSymlink) {
|
|
@@ -7744,7 +7833,7 @@ async function formatAsTree(fs5, path7, options) {
|
|
|
7744
7833
|
}
|
|
7745
7834
|
}
|
|
7746
7835
|
}
|
|
7747
|
-
await buildTree(
|
|
7836
|
+
await buildTree(path8, 0);
|
|
7748
7837
|
const dirPart = dirCount === 1 ? "1 directory" : `${dirCount} directories`;
|
|
7749
7838
|
const filePart = fileCount === 1 ? "1 file" : `${fileCount} files`;
|
|
7750
7839
|
let summary = `${dirPart}, ${filePart}`;
|
|
@@ -7807,10 +7896,10 @@ Examples:
|
|
|
7807
7896
|
),
|
|
7808
7897
|
respectGitignore: z.boolean().optional().default(true).describe("Respect .gitignore in the listed directory (default: true).")
|
|
7809
7898
|
}),
|
|
7810
|
-
execute: async ({ path:
|
|
7899
|
+
execute: async ({ path: path8 = ".", maxDepth = 2, showHidden, dirsOnly, exclude, extension, pattern, respectGitignore }, context) => {
|
|
7811
7900
|
const { workspace, filesystem } = requireFilesystem(context);
|
|
7812
7901
|
await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.LIST_FILES);
|
|
7813
|
-
const result = await formatAsTree(filesystem,
|
|
7902
|
+
const result = await formatAsTree(filesystem, path8, {
|
|
7814
7903
|
maxDepth,
|
|
7815
7904
|
showHidden,
|
|
7816
7905
|
dirsOnly,
|
|
@@ -7828,6 +7917,194 @@ ${result.summary}`,
|
|
|
7828
7917
|
);
|
|
7829
7918
|
}
|
|
7830
7919
|
});
|
|
7920
|
+
var CURSOR_MARKER = "<<<";
|
|
7921
|
+
async function getLinePreview(filePath, lineNumber) {
|
|
7922
|
+
try {
|
|
7923
|
+
const content = await fs2__default.readFile(filePath, "utf-8");
|
|
7924
|
+
const lines = content.split("\n");
|
|
7925
|
+
const line = lines[lineNumber - 1];
|
|
7926
|
+
return line?.trim() ?? null;
|
|
7927
|
+
} catch {
|
|
7928
|
+
return null;
|
|
7929
|
+
}
|
|
7930
|
+
}
|
|
7931
|
+
function getAbsolutePath(workspacePath, lspRoot, resolveAbsolutePath) {
|
|
7932
|
+
const resolvedPath = resolveAbsolutePath?.(workspacePath);
|
|
7933
|
+
if (resolvedPath) {
|
|
7934
|
+
return resolvedPath;
|
|
7935
|
+
}
|
|
7936
|
+
if (nodePath__default.isAbsolute(workspacePath)) {
|
|
7937
|
+
return workspacePath;
|
|
7938
|
+
}
|
|
7939
|
+
return nodePath__default.resolve(lspRoot, workspacePath);
|
|
7940
|
+
}
|
|
7941
|
+
function locationUriToPath(uri) {
|
|
7942
|
+
if (!uri.startsWith("file://")) {
|
|
7943
|
+
return null;
|
|
7944
|
+
}
|
|
7945
|
+
try {
|
|
7946
|
+
return fileURLToPath(uri);
|
|
7947
|
+
} catch {
|
|
7948
|
+
return null;
|
|
7949
|
+
}
|
|
7950
|
+
}
|
|
7951
|
+
function locationKey(location) {
|
|
7952
|
+
return `${location.path}:L${location.line}`;
|
|
7953
|
+
}
|
|
7954
|
+
function compressPath(filePath) {
|
|
7955
|
+
const cwd = process.cwd();
|
|
7956
|
+
if (filePath.startsWith(cwd)) {
|
|
7957
|
+
return "$cwd" + filePath.slice(cwd.length);
|
|
7958
|
+
}
|
|
7959
|
+
return filePath;
|
|
7960
|
+
}
|
|
7961
|
+
var lspInspectTool = createTool({
|
|
7962
|
+
id: WORKSPACE_TOOLS.LSP.LSP_INSPECT,
|
|
7963
|
+
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.",
|
|
7964
|
+
inputSchema: z.object({
|
|
7965
|
+
path: z.string().describe("Absolute path to the file"),
|
|
7966
|
+
line: z.number().int().positive().describe("Line number (1-indexed)"),
|
|
7967
|
+
match: z.string().describe(
|
|
7968
|
+
'Line content with <<< marking the cursor position. Exactly one <<< marker is required. Example: "const foo = <<<bar()" means cursor is at bar'
|
|
7969
|
+
)
|
|
7970
|
+
}),
|
|
7971
|
+
execute: async ({ path: filePath, line, match }, context) => {
|
|
7972
|
+
const workspace = requireWorkspace(context);
|
|
7973
|
+
await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.LSP.LSP_INSPECT);
|
|
7974
|
+
const cursorPositions = [];
|
|
7975
|
+
let searchStart = 0;
|
|
7976
|
+
while (true) {
|
|
7977
|
+
const pos = match.indexOf(CURSOR_MARKER, searchStart);
|
|
7978
|
+
if (pos === -1) break;
|
|
7979
|
+
cursorPositions.push(pos);
|
|
7980
|
+
searchStart = pos + CURSOR_MARKER.length;
|
|
7981
|
+
}
|
|
7982
|
+
if (cursorPositions.length === 0) {
|
|
7983
|
+
return {
|
|
7984
|
+
error: `No <<< cursor marker found in match`
|
|
7985
|
+
};
|
|
7986
|
+
}
|
|
7987
|
+
if (cursorPositions.length > 1) {
|
|
7988
|
+
return {
|
|
7989
|
+
error: `Multiple <<< markers found (found ${cursorPositions.length}, expected 1)`
|
|
7990
|
+
};
|
|
7991
|
+
}
|
|
7992
|
+
const character = cursorPositions[0] + 1;
|
|
7993
|
+
const lspManager = workspace.lsp;
|
|
7994
|
+
if (!lspManager) {
|
|
7995
|
+
return {
|
|
7996
|
+
error: "LSP is not configured for this workspace. Enable LSP in workspace config to use this tool."
|
|
7997
|
+
};
|
|
7998
|
+
}
|
|
7999
|
+
const absolutePath = getAbsolutePath(
|
|
8000
|
+
filePath,
|
|
8001
|
+
lspManager.root,
|
|
8002
|
+
workspace.filesystem?.resolveAbsolutePath?.bind(workspace.filesystem)
|
|
8003
|
+
);
|
|
8004
|
+
let fileContent = "";
|
|
8005
|
+
try {
|
|
8006
|
+
fileContent = await fs2__default.readFile(absolutePath, "utf-8");
|
|
8007
|
+
} catch {
|
|
8008
|
+
fileContent = "";
|
|
8009
|
+
}
|
|
8010
|
+
let queryResult;
|
|
8011
|
+
try {
|
|
8012
|
+
queryResult = await lspManager.prepareQuery(absolutePath);
|
|
8013
|
+
} catch (err) {
|
|
8014
|
+
return {
|
|
8015
|
+
error: `Failed to initialize LSP client: ${err instanceof Error ? err.message : String(err)}`
|
|
8016
|
+
};
|
|
8017
|
+
}
|
|
8018
|
+
if (!queryResult) {
|
|
8019
|
+
return {
|
|
8020
|
+
error: `No language server available for files of this type: ${filePath}`
|
|
8021
|
+
};
|
|
8022
|
+
}
|
|
8023
|
+
const { client, uri } = queryResult;
|
|
8024
|
+
const position = { line: line - 1, character: character - 1 };
|
|
8025
|
+
const result = {};
|
|
8026
|
+
try {
|
|
8027
|
+
const hoverResult = await client.queryHover(uri, position).catch(() => null);
|
|
8028
|
+
if (hoverResult) {
|
|
8029
|
+
const contents = hoverResult.contents;
|
|
8030
|
+
if (contents) {
|
|
8031
|
+
if (typeof contents === "string") {
|
|
8032
|
+
result.hover = { value: contents, kind: "plaintext" };
|
|
8033
|
+
} else if (Array.isArray(contents)) {
|
|
8034
|
+
const first = contents[0];
|
|
8035
|
+
if (typeof first === "string") {
|
|
8036
|
+
result.hover = { value: first, kind: "plaintext" };
|
|
8037
|
+
} else if (first?.value) {
|
|
8038
|
+
result.hover = { value: first.value, kind: first.kind ?? "markdown" };
|
|
8039
|
+
}
|
|
8040
|
+
} else if (contents.value) {
|
|
8041
|
+
result.hover = { value: contents.value, kind: contents.kind ?? "markdown" };
|
|
8042
|
+
}
|
|
8043
|
+
}
|
|
8044
|
+
}
|
|
8045
|
+
const diagnosticsPromise = fileContent ? Promise.resolve().then(() => {
|
|
8046
|
+
client.notifyChange(absolutePath, fileContent, 1);
|
|
8047
|
+
return client.waitForDiagnostics(absolutePath, 5e3, true);
|
|
8048
|
+
}).catch(() => []) : Promise.resolve([]);
|
|
8049
|
+
const [diagnosticsResult, definitionResult, implResult] = await Promise.all([
|
|
8050
|
+
diagnosticsPromise,
|
|
8051
|
+
client.queryDefinition(uri, position).catch(() => []),
|
|
8052
|
+
client.queryImplementation(uri, position).catch(() => [])
|
|
8053
|
+
]);
|
|
8054
|
+
if (diagnosticsResult && diagnosticsResult.length > 0) {
|
|
8055
|
+
const lineDiagnostics = diagnosticsResult.map((diagnostic) => ({
|
|
8056
|
+
line: typeof diagnostic.line === "number" ? diagnostic.line : (diagnostic.range?.start?.line ?? -1) + 1,
|
|
8057
|
+
severity: typeof diagnostic.severity === "number" ? diagnostic.severity === 1 ? "error" : diagnostic.severity === 2 ? "warning" : diagnostic.severity === 3 ? "info" : "hint" : diagnostic.severity,
|
|
8058
|
+
message: diagnostic.message,
|
|
8059
|
+
source: diagnostic.source ?? null
|
|
8060
|
+
})).filter((diagnostic) => diagnostic.line === line).map(({ severity, message, source }) => ({ severity, message, source }));
|
|
8061
|
+
if (lineDiagnostics.length > 0) {
|
|
8062
|
+
result.diagnostics = lineDiagnostics;
|
|
8063
|
+
}
|
|
8064
|
+
}
|
|
8065
|
+
const definitionLocations = definitionResult.map((loc) => ({
|
|
8066
|
+
uri: loc.uri ?? loc.targetUri,
|
|
8067
|
+
range: loc.range ?? loc.targetRange
|
|
8068
|
+
})).map((loc) => {
|
|
8069
|
+
const resolvedPath = loc.uri ? locationUriToPath(String(loc.uri)) : null;
|
|
8070
|
+
return resolvedPath ? {
|
|
8071
|
+
path: resolvedPath,
|
|
8072
|
+
line: (loc.range?.start?.line ?? 0) + 1,
|
|
8073
|
+
character: (loc.range?.start?.character ?? 0) + 1
|
|
8074
|
+
} : null;
|
|
8075
|
+
}).filter((loc) => Boolean(loc)).filter((loc) => !(loc.path === absolutePath && loc.line === line));
|
|
8076
|
+
if (definitionLocations.length > 0) {
|
|
8077
|
+
const previews = await Promise.all(definitionLocations.map((loc) => getLinePreview(loc.path, loc.line)));
|
|
8078
|
+
result.definition = definitionLocations.map((loc, i) => ({
|
|
8079
|
+
location: `${compressPath(loc.path)}:L${loc.line}:C${loc.character}`,
|
|
8080
|
+
preview: previews[i]
|
|
8081
|
+
}));
|
|
8082
|
+
}
|
|
8083
|
+
const definitionKeys = new Set(definitionLocations.map(locationKey));
|
|
8084
|
+
const implementationLocations = implResult.map((loc) => ({
|
|
8085
|
+
uri: loc.uri ?? loc.targetUri,
|
|
8086
|
+
range: loc.range ?? loc.targetRange
|
|
8087
|
+
})).map((loc) => {
|
|
8088
|
+
const resolvedPath = loc.uri ? locationUriToPath(String(loc.uri)) : null;
|
|
8089
|
+
return resolvedPath ? {
|
|
8090
|
+
path: resolvedPath,
|
|
8091
|
+
line: (loc.range?.start?.line ?? 0) + 1,
|
|
8092
|
+
character: (loc.range?.start?.character ?? 0) + 1
|
|
8093
|
+
} : null;
|
|
8094
|
+
}).filter((loc) => Boolean(loc)).filter((loc) => !definitionKeys.has(locationKey(loc)) && !(loc.path === absolutePath && loc.line === line));
|
|
8095
|
+
if (implementationLocations.length > 0) {
|
|
8096
|
+
result.implementation = implementationLocations.map(
|
|
8097
|
+
(loc) => `${compressPath(loc.path)}:L${loc.line}:C${loc.character}`
|
|
8098
|
+
);
|
|
8099
|
+
}
|
|
8100
|
+
} catch (err) {
|
|
8101
|
+
result.error = `LSP query failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
8102
|
+
} finally {
|
|
8103
|
+
client.notifyClose(absolutePath);
|
|
8104
|
+
}
|
|
8105
|
+
return result;
|
|
8106
|
+
}
|
|
8107
|
+
});
|
|
7831
8108
|
var mkdirTool = createTool({
|
|
7832
8109
|
id: WORKSPACE_TOOLS.FILESYSTEM.MKDIR,
|
|
7833
8110
|
description: "Create a directory in the workspace filesystem",
|
|
@@ -7835,14 +8112,14 @@ var mkdirTool = createTool({
|
|
|
7835
8112
|
path: z.string().describe("The path of the directory to create"),
|
|
7836
8113
|
recursive: z.boolean().optional().default(true).describe("Whether to create parent directories if they do not exist")
|
|
7837
8114
|
}),
|
|
7838
|
-
execute: async ({ path:
|
|
8115
|
+
execute: async ({ path: path8, recursive }, context) => {
|
|
7839
8116
|
const { filesystem } = requireFilesystem(context);
|
|
7840
8117
|
await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.MKDIR);
|
|
7841
8118
|
if (filesystem.readOnly) {
|
|
7842
8119
|
throw new WorkspaceReadOnlyError("mkdir");
|
|
7843
8120
|
}
|
|
7844
|
-
await filesystem.mkdir(
|
|
7845
|
-
return `Created directory ${
|
|
8121
|
+
await filesystem.mkdir(path8, { recursive });
|
|
8122
|
+
return `Created directory ${path8}`;
|
|
7846
8123
|
}
|
|
7847
8124
|
});
|
|
7848
8125
|
var readFileTool = createTool({
|
|
@@ -7855,12 +8132,12 @@ var readFileTool = createTool({
|
|
|
7855
8132
|
limit: z.number().optional().describe("Maximum number of lines to read. If omitted, reads to the end of the file."),
|
|
7856
8133
|
showLineNumbers: z.boolean().optional().default(true).describe("Whether to prefix each line with its line number (default: true)")
|
|
7857
8134
|
}),
|
|
7858
|
-
execute: async ({ path:
|
|
8135
|
+
execute: async ({ path: path8, encoding, offset, limit, showLineNumbers }, context) => {
|
|
7859
8136
|
const { workspace, filesystem } = requireFilesystem(context);
|
|
7860
8137
|
await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.READ_FILE);
|
|
7861
8138
|
const effectiveEncoding = encoding ?? "utf-8";
|
|
7862
|
-
const fullContent = await filesystem.readFile(
|
|
7863
|
-
const stat3 = await filesystem.stat(
|
|
8139
|
+
const fullContent = await filesystem.readFile(path8, { encoding: effectiveEncoding });
|
|
8140
|
+
const stat3 = await filesystem.stat(path8);
|
|
7864
8141
|
const isTextEncoding = !encoding || encoding === "utf-8" || encoding === "utf8";
|
|
7865
8142
|
const tokenLimit = workspace.getToolsConfig()?.[WORKSPACE_TOOLS.FILESYSTEM.READ_FILE]?.maxOutputTokens;
|
|
7866
8143
|
if (!isTextEncoding) {
|
|
@@ -7928,19 +8205,19 @@ var writeFileTool = createTool({
|
|
|
7928
8205
|
content: z.string().describe("The content to write to the file"),
|
|
7929
8206
|
overwrite: z.boolean().optional().default(true).describe("Whether to overwrite the file if it already exists")
|
|
7930
8207
|
}),
|
|
7931
|
-
execute: async ({ path:
|
|
8208
|
+
execute: async ({ path: path8, content, overwrite }, context) => {
|
|
7932
8209
|
const { workspace, filesystem } = requireFilesystem(context);
|
|
7933
8210
|
await emitWorkspaceMetadata(context, WORKSPACE_TOOLS.FILESYSTEM.WRITE_FILE);
|
|
7934
8211
|
if (filesystem.readOnly) {
|
|
7935
8212
|
throw new WorkspaceReadOnlyError("write_file");
|
|
7936
8213
|
}
|
|
7937
|
-
await filesystem.writeFile(
|
|
8214
|
+
await filesystem.writeFile(path8, content, {
|
|
7938
8215
|
overwrite,
|
|
7939
8216
|
expectedMtime: context?.__expectedMtime
|
|
7940
8217
|
});
|
|
7941
8218
|
const size = Buffer.byteLength(content, "utf-8");
|
|
7942
|
-
let output = `Wrote ${size} bytes to ${
|
|
7943
|
-
output += await getEditDiagnosticsText(workspace,
|
|
8219
|
+
let output = `Wrote ${size} bytes to ${path8}`;
|
|
8220
|
+
output += await getEditDiagnosticsText(workspace, path8, content);
|
|
7944
8221
|
return output;
|
|
7945
8222
|
}
|
|
7946
8223
|
});
|
|
@@ -8095,9 +8372,10 @@ function createWorkspaceTools(workspace) {
|
|
|
8095
8372
|
addTool(WORKSPACE_TOOLS.SANDBOX.KILL_PROCESS, killProcessTool);
|
|
8096
8373
|
}
|
|
8097
8374
|
}
|
|
8375
|
+
addTool(WORKSPACE_TOOLS.LSP.LSP_INSPECT, lspInspectTool);
|
|
8098
8376
|
return tools;
|
|
8099
8377
|
}
|
|
8100
8378
|
|
|
8101
8379
|
export { BM25Index, CompositeFilesystem, CompositeVersionedSkillSource, DirectoryNotEmptyError, DirectoryNotFoundError, FileExistsError, FileNotFoundError, FileReadRequiredError, FilesystemError, FilesystemNotAvailableError, FilesystemNotMountableError, FilesystemNotReadyError, IsDirectoryError, IsolationUnavailableError, LocalFilesystem, LocalSandbox, LocalSkillSource, MastraFilesystem, MastraSandbox, MountError, MountManager, MountNotSupportedError, NotDirectoryError, PermissionError, ProcessHandle, SandboxError, SandboxExecutionError, SandboxFeatureNotSupportedError, SandboxNotAvailableError, SandboxNotReadyError, SandboxProcessManager, SandboxTimeoutError, SearchNotAvailableError, StaleFileError, VersionedSkillSource, WORKSPACE_TOOLS, WORKSPACE_TOOLS_PREFIX, Workspace, WorkspaceError, WorkspaceNotAvailableError, WorkspaceNotReadyError, WorkspaceReadOnlyError, callLifecycle, collectSkillForPublish, createGlobMatcher, createSkillTools, createWorkspaceTools, deleteFileTool, detectIsolation, editFileTool, executeCommandTool, extractGlobBase, fileStatTool, getRecommendedIsolation, getTiktoken, indexContentTool, isGlobPattern, isIsolationAvailable, listFilesTool, matchGlob, mkdirTool, publishSkillFromSource, readFileTool, requireFilesystem, requireSandbox, requireWorkspace, resolveToolConfig, searchTool, writeFileTool };
|
|
8102
|
-
//# sourceMappingURL=chunk-
|
|
8103
|
-
//# sourceMappingURL=chunk-
|
|
8380
|
+
//# sourceMappingURL=chunk-ABA3KD3X.js.map
|
|
8381
|
+
//# sourceMappingURL=chunk-ABA3KD3X.js.map
|