@ai-agent-forge/plugin-workspace-files 0.85.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -0
- package/agent-forge.json +12 -0
- package/dist/capability.d.ts +5 -0
- package/dist/capability.d.ts.map +1 -0
- package/dist/capability.js +246 -0
- package/dist/capability.js.map +1 -0
- package/dist/entry.d.ts +14 -0
- package/dist/entry.d.ts.map +1 -0
- package/dist/entry.js +15 -0
- package/dist/entry.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/node-adapter.d.ts +21 -0
- package/dist/node-adapter.d.ts.map +1 -0
- package/dist/node-adapter.js +313 -0
- package/dist/node-adapter.js.map +1 -0
- package/dist/types.d.ts +80 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +55 -0
- package/plugin.json +9 -0
package/README.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# @agent-forge/plugin-workspace-files
|
|
2
|
+
|
|
3
|
+
Workspace files capability plugin for [Agent Forge](https://github.com/agent-forge/agent-forge), extracted from the
|
|
4
|
+
host's `src/plugins/workspace-files` (D-075 S3). It registers three read-only tools — `workspace_list`,
|
|
5
|
+
`workspace_read`, `workspace_find` — which operate purely through opaque host-owned workspace references; the model
|
|
6
|
+
never supplies or receives a local path.
|
|
7
|
+
|
|
8
|
+
The plugin has no standalone filesystem binding at load time. Without host-injected list/read/find seams the tools
|
|
9
|
+
report an explicit `unsupported` result; hosts that want real file access bind their own opaque-ref file host through
|
|
10
|
+
their profile machinery.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
# from a local checkout
|
|
16
|
+
agent-forge plugin install ./plugins/workspace-files
|
|
17
|
+
|
|
18
|
+
# from npm
|
|
19
|
+
agent-forge plugin install @agent-forge/plugin-workspace-files
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The package ships two manifests: `agent-forge.json` (ecosystem manifest for the deterministic plugin resolver) and
|
|
23
|
+
`plugin.json` (host-load manifest consumed by `loadCapabilityPluginFromManifest`, entry `./dist/entry.js`).
|
|
24
|
+
|
|
25
|
+
## Library surface
|
|
26
|
+
|
|
27
|
+
`import { createNodeWorkspaceFilesAdapterV1, createWorkspaceFilesCapabilityFactoryV1 } from "@agent-forge/plugin-workspace-files";`
|
|
28
|
+
|
|
29
|
+
- `createNodeWorkspaceFilesAdapterV1(options?)` — read-only adapter; requires host-injected `list`/`read`/`find`
|
|
30
|
+
callbacks to produce results, otherwise returns `unsupported`.
|
|
31
|
+
- `sanitizeWorkspaceFilesTextV1(value, maximum?)` — redacts credentials and host paths from previews.
|
|
32
|
+
- `createWorkspaceFilesCapabilityFactoryV1(adapter)` — registers the three workspace tools on a `CapabilityAPI`.
|
|
33
|
+
- Default export of `dist/entry.js` — the precomposed factory used by external plugin loading.
|
|
34
|
+
|
|
35
|
+
## Development
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
npm install --ignore-scripts # repo root, creates the workspace symlink
|
|
39
|
+
npm run build # plugins/workspace-files (tsgo)
|
|
40
|
+
npm test # vitest; the entry fidelity test requires `npm run build` first
|
|
41
|
+
```
|
package/agent-forge.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"packageFormatVersion": 1,
|
|
3
|
+
"id": "agent-forge.plugin.workspace-files",
|
|
4
|
+
"pluginVersion": "0.84.4",
|
|
5
|
+
"apiVersion": "1",
|
|
6
|
+
"minHostVersion": "0.84.4",
|
|
7
|
+
"capabilityRefs": [{ "id": "workspace.files", "version": 1 }],
|
|
8
|
+
"platform": {
|
|
9
|
+
"os": ["windows", "macos", "linux"],
|
|
10
|
+
"runtime": [{ "name": "node" }]
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { CapabilityPluginSyncFactory } from "@agent-forge/plugin-sdk";
|
|
2
|
+
import type { WorkspaceFilesAdapterV1 } from "./types.ts";
|
|
3
|
+
/** Registers bounded workspace reads using only opaque host-owned references. */
|
|
4
|
+
export declare function createWorkspaceFilesCapabilityFactoryV1(runtime: WorkspaceFilesAdapterV1): CapabilityPluginSyncFactory;
|
|
5
|
+
//# sourceMappingURL=capability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAY3E,OAAO,KAAK,EACX,uBAAuB,EAIvB,MAAM,YAAY,CAAC;AA+NpB,iFAAiF;AACjF,wBAAgB,uCAAuC,CAAC,OAAO,EAAE,uBAAuB,GAAG,2BAA2B,CAiGrH","sourcesContent":["import type { CapabilityPluginSyncFactory } from \"@agent-forge/plugin-sdk\";\nimport { Type } from \"typebox\";\nimport {\n\tprojectFind,\n\tprojectList,\n\tprojectRead,\n\tsanitizeWorkspaceFilesTextV1,\n\tWORKSPACE_FILES_MAX_MATCHES_V1,\n\tWORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1,\n\tWORKSPACE_FILES_MAX_QUERY_CHARS_V1,\n\tWORKSPACE_FILES_MAX_READ_BYTES_V1,\n} from \"./node-adapter.ts\";\nimport type {\n\tWorkspaceFilesAdapterV1,\n\tWorkspaceFilesFindResultV1,\n\tWorkspaceFilesListResultV1,\n\tWorkspaceFilesReadResultV1,\n} from \"./types.ts\";\n\nconst refSchema = Type.String({ minLength: 1, maxLength: 256, pattern: \"^[A-Za-z0-9][A-Za-z0-9._:-]*$\" });\nconst listSchema = Type.Object(\n\t{\n\t\tworkspaceRef: refSchema,\n\t\tdirectoryRef: Type.Optional(refSchema),\n\t\tlimit: Type.Optional(Type.Integer({ minimum: 1, maximum: 256 })),\n\t},\n\t{ additionalProperties: false },\n);\nconst readSchema = Type.Object(\n\t{\n\t\tfileRef: refSchema,\n\t\tmaxBytes: Type.Optional(Type.Integer({ minimum: 1, maximum: WORKSPACE_FILES_MAX_READ_BYTES_V1 })),\n\t},\n\t{ additionalProperties: false },\n);\nconst findSchema = Type.Object(\n\t{\n\t\tworkspaceRef: refSchema,\n\t\tquery: Type.String({ minLength: 1, maxLength: WORKSPACE_FILES_MAX_QUERY_CHARS_V1 }),\n\t\tlimit: Type.Optional(Type.Integer({ minimum: 1, maximum: WORKSPACE_FILES_MAX_MATCHES_V1 })),\n\t},\n\t{ additionalProperties: false },\n);\n\ntype Result = WorkspaceFilesListResultV1 | WorkspaceFilesReadResultV1 | WorkspaceFilesFindResultV1;\n\nfunction input(\n\tfirst: unknown,\n\tsecond: unknown,\n): { readonly request: Record<string, unknown>; readonly operationId: string } {\n\tconst value = second === undefined ? first : second;\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value))\n\t\tthrow new Error(\"workspace input must be an object\");\n\tconst operationId =\n\t\ttypeof first === \"string\" && first.trim() !== \"\" && first.length <= WORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1\n\t\t\t? first\n\t\t\t: \"profile-runtime-tool-call\";\n\tconst outer = value as Record<string, unknown>;\n\tif (outer.request === null || typeof outer.request !== \"object\" || Array.isArray(outer.request))\n\t\tthrow new Error(\"workspace request must be an object\");\n\treturn { request: outer.request as Record<string, unknown>, operationId };\n}\n\nfunction signalFrom(value: unknown): AbortSignal | undefined {\n\treturn value instanceof AbortSignal ? value : undefined;\n}\n\nconst NON_SUCCESS_STATUSES = new Set([\"failed\", \"cancelled\", \"needs_user\", \"unsupported\"]);\n\nfunction nonSuccessError(value: unknown): WorkspaceFilesListResultV1[\"error\"] | undefined {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n\tconst error = value as Record<string, unknown>;\n\tif (\n\t\terror.version !== 1 ||\n\t\ttypeof error.code !== \"string\" ||\n\t\t!/^[a-z][a-z0-9_]{0,127}$/u.test(error.code) ||\n\t\ttypeof error.message !== \"string\" ||\n\t\terror.message.trim() === \"\" ||\n\t\terror.message.length > 512\n\t)\n\t\treturn undefined;\n\treturn { version: 1, code: error.code, message: sanitizeWorkspaceFilesTextV1(error.message, 512) };\n}\n\nfunction projectNonSuccess(value: unknown, operationId: string, kind: \"list\" | \"read\" | \"find\"): Result | undefined {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n\tconst result = value as Record<string, unknown>;\n\tif (result.version !== 1 || result.operationId !== operationId || typeof result.status !== \"string\")\n\t\treturn undefined;\n\tif (!NON_SUCCESS_STATUSES.has(result.status)) return undefined;\n\tconst error = nonSuccessError(result.error);\n\tif (error === undefined) return undefined;\n\tif (kind === \"list\") {\n\t\tif (\n\t\t\tObject.keys(result).some(\n\t\t\t\t(key) => ![\"version\", \"operationId\", \"status\", \"entries\", \"entriesTruncated\", \"error\"].includes(key),\n\t\t\t) ||\n\t\t\t!Array.isArray(result.entries) ||\n\t\t\tresult.entries.length !== 0 ||\n\t\t\tresult.entriesTruncated !== false\n\t\t)\n\t\t\treturn undefined;\n\t\treturn {\n\t\t\tversion: 1,\n\t\t\toperationId,\n\t\t\tstatus: result.status as WorkspaceFilesListResultV1[\"status\"],\n\t\t\tentries: [],\n\t\t\tentriesTruncated: false,\n\t\t\terror,\n\t\t};\n\t}\n\tif (kind === \"read\") {\n\t\tif (\n\t\t\tObject.keys(result).some(\n\t\t\t\t(key) =>\n\t\t\t\t\t![\n\t\t\t\t\t\t\"version\",\n\t\t\t\t\t\t\"operationId\",\n\t\t\t\t\t\t\"status\",\n\t\t\t\t\t\t\"contentPreview\",\n\t\t\t\t\t\t\"contentBytes\",\n\t\t\t\t\t\t\"contentTruncated\",\n\t\t\t\t\t\t\"artifactRef\",\n\t\t\t\t\t\t\"error\",\n\t\t\t\t\t].includes(key),\n\t\t\t) ||\n\t\t\tresult.contentPreview !== \"\" ||\n\t\t\tresult.contentBytes !== 0 ||\n\t\t\tresult.contentTruncated !== false\n\t\t)\n\t\t\treturn undefined;\n\t\treturn {\n\t\t\tversion: 1,\n\t\t\toperationId,\n\t\t\tstatus: result.status as WorkspaceFilesReadResultV1[\"status\"],\n\t\t\tcontentPreview: \"\",\n\t\t\tcontentBytes: 0,\n\t\t\tcontentTruncated: false,\n\t\t\terror,\n\t\t};\n\t}\n\tif (\n\t\tObject.keys(result).some(\n\t\t\t(key) => ![\"version\", \"operationId\", \"status\", \"matches\", \"matchesTruncated\", \"error\"].includes(key),\n\t\t) ||\n\t\t!Array.isArray(result.matches) ||\n\t\tresult.matches.length !== 0 ||\n\t\tresult.matchesTruncated !== false\n\t)\n\t\treturn undefined;\n\treturn {\n\t\tversion: 1,\n\t\toperationId,\n\t\tstatus: result.status as WorkspaceFilesFindResultV1[\"status\"],\n\t\tmatches: [],\n\t\tmatchesTruncated: false,\n\t\terror,\n\t};\n}\n\nfunction projectListResult(value: unknown, operationId: string): WorkspaceFilesListResultV1 | undefined {\n\treturn (\n\t\tprojectList(value, operationId) ??\n\t\t(projectNonSuccess(value, operationId, \"list\") as WorkspaceFilesListResultV1 | undefined)\n\t);\n}\n\nfunction projectReadResult(value: unknown, operationId: string): WorkspaceFilesReadResultV1 | undefined {\n\treturn (\n\t\tprojectRead(value, operationId) ??\n\t\t(projectNonSuccess(value, operationId, \"read\") as WorkspaceFilesReadResultV1 | undefined)\n\t);\n}\n\nfunction projectFindResult(value: unknown, operationId: string): WorkspaceFilesFindResultV1 | undefined {\n\treturn (\n\t\tprojectFind(value, operationId) ??\n\t\t(projectNonSuccess(value, operationId, \"find\") as WorkspaceFilesFindResultV1 | undefined)\n\t);\n}\n\nfunction errorFor(status: \"failed\" | \"cancelled\") {\n\tconst error = {\n\t\tversion: 1 as const,\n\t\tcode: status === \"cancelled\" ? \"cancelled\" : \"adapter_failed\",\n\t\tmessage: status === \"cancelled\" ? \"Workspace operation was cancelled\" : \"Workspace file adapter failed\",\n\t};\n\treturn error;\n}\n\nfunction listFallback(operationId: string, status: \"failed\" | \"cancelled\"): WorkspaceFilesListResultV1 {\n\treturn {\n\t\tversion: 1,\n\t\toperationId,\n\t\tstatus,\n\t\tentries: [],\n\t\tentriesTruncated: false,\n\t\terror: errorFor(status),\n\t};\n}\n\nfunction readFallback(operationId: string, status: \"failed\" | \"cancelled\"): WorkspaceFilesReadResultV1 {\n\treturn {\n\t\tversion: 1,\n\t\toperationId,\n\t\tstatus,\n\t\tcontentPreview: \"\",\n\t\tcontentBytes: 0,\n\t\tcontentTruncated: false,\n\t\terror: errorFor(status),\n\t};\n}\n\nfunction findFallback(operationId: string, status: \"failed\" | \"cancelled\"): WorkspaceFilesFindResultV1 {\n\treturn {\n\t\tversion: 1,\n\t\toperationId,\n\t\tstatus,\n\t\tmatches: [],\n\t\tmatchesTruncated: false,\n\t\terror: errorFor(status),\n\t};\n}\n\nasync function execute<T extends Result>(\n\toperationId: string,\n\tsignal: AbortSignal | undefined,\n\trun: () => Promise<T>,\n\tproject: (value: unknown, operationId: string) => T | undefined,\n\tfallbackResult: (status: \"failed\" | \"cancelled\") => T,\n): Promise<T> {\n\tif (signal?.aborted) return fallbackResult(\"cancelled\");\n\ttry {\n\t\tconst result = await run();\n\t\treturn project(result, operationId) ?? fallbackResult(\"failed\");\n\t} catch {\n\t\treturn fallbackResult(\"failed\");\n\t}\n}\n\n/** Registers bounded workspace reads using only opaque host-owned references. */\nexport function createWorkspaceFilesCapabilityFactoryV1(runtime: WorkspaceFilesAdapterV1): CapabilityPluginSyncFactory {\n\treturn (api) => {\n\t\tapi.registerTool({\n\t\t\tname: \"workspace_list\",\n\t\t\tlabel: \"List workspace files\",\n\t\t\tdescription: \"List bounded workspace entries through host-owned opaque references\",\n\t\t\tparameters: Type.Object({ request: listSchema }, { additionalProperties: false }),\n\t\t\texecute: async (first: unknown, second?: unknown, third?: unknown) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst { request, operationId } = input(first, second);\n\t\t\t\t\tconst signal = signalFrom(third);\n\t\t\t\t\treturn execute(\n\t\t\t\t\t\toperationId,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t() =>\n\t\t\t\t\t\t\truntime.list(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t\toperationId,\n\t\t\t\t\t\t\t\t\tworkspaceRef: request.workspaceRef as string,\n\t\t\t\t\t\t\t\t\t...(request.directoryRef === undefined\n\t\t\t\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t\t\t\t: { directoryRef: request.directoryRef as string }),\n\t\t\t\t\t\t\t\t\t...(request.limit === undefined ? {} : { limit: request.limit as number }),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t(value, id) => projectListResult(value, id),\n\t\t\t\t\t\t(status) => listFallback(operationId, status),\n\t\t\t\t\t);\n\t\t\t\t} catch {\n\t\t\t\t\treturn listFallback(\"profile-runtime-tool-call\", \"failed\");\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t\tapi.registerTool({\n\t\t\tname: \"workspace_read\",\n\t\t\tlabel: \"Read workspace file\",\n\t\t\tdescription: \"Read a bounded preview from a host-owned workspace file reference\",\n\t\t\tparameters: Type.Object({ request: readSchema }, { additionalProperties: false }),\n\t\t\texecute: async (first: unknown, second?: unknown, third?: unknown) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst { request, operationId } = input(first, second);\n\t\t\t\t\tconst signal = signalFrom(third);\n\t\t\t\t\treturn execute(\n\t\t\t\t\t\toperationId,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t() =>\n\t\t\t\t\t\t\truntime.read(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t\toperationId,\n\t\t\t\t\t\t\t\t\tfileRef: request.fileRef as string,\n\t\t\t\t\t\t\t\t\t...(request.maxBytes === undefined ? {} : { maxBytes: request.maxBytes as number }),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t(value, id) => projectReadResult(value, id),\n\t\t\t\t\t\t(status) => readFallback(operationId, status),\n\t\t\t\t\t);\n\t\t\t\t} catch {\n\t\t\t\t\treturn readFallback(\"profile-runtime-tool-call\", \"failed\");\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t\tapi.registerTool({\n\t\t\tname: \"workspace_find\",\n\t\t\tlabel: \"Find in workspace\",\n\t\t\tdescription: \"Return bounded workspace matches without injecting the full file contents\",\n\t\t\tparameters: Type.Object({ request: findSchema }, { additionalProperties: false }),\n\t\t\texecute: async (first: unknown, second?: unknown, third?: unknown) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst { request, operationId } = input(first, second);\n\t\t\t\t\tconst signal = signalFrom(third);\n\t\t\t\t\treturn execute(\n\t\t\t\t\t\toperationId,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t() =>\n\t\t\t\t\t\t\truntime.find(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t\toperationId,\n\t\t\t\t\t\t\t\t\tworkspaceRef: request.workspaceRef as string,\n\t\t\t\t\t\t\t\t\tquery: request.query as string,\n\t\t\t\t\t\t\t\t\t...(request.limit === undefined ? {} : { limit: request.limit as number }),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t(value, id) => projectFindResult(value, id),\n\t\t\t\t\t\t(status) => findFallback(operationId, status),\n\t\t\t\t\t);\n\t\t\t\t} catch {\n\t\t\t\t\treturn findFallback(\"profile-runtime-tool-call\", \"failed\");\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t};\n}\n"]}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
import { projectFind, projectList, projectRead, sanitizeWorkspaceFilesTextV1, WORKSPACE_FILES_MAX_MATCHES_V1, WORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1, WORKSPACE_FILES_MAX_QUERY_CHARS_V1, WORKSPACE_FILES_MAX_READ_BYTES_V1, } from "./node-adapter.js";
|
|
3
|
+
const refSchema = Type.String({ minLength: 1, maxLength: 256, pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$" });
|
|
4
|
+
const listSchema = Type.Object({
|
|
5
|
+
workspaceRef: refSchema,
|
|
6
|
+
directoryRef: Type.Optional(refSchema),
|
|
7
|
+
limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 256 })),
|
|
8
|
+
}, { additionalProperties: false });
|
|
9
|
+
const readSchema = Type.Object({
|
|
10
|
+
fileRef: refSchema,
|
|
11
|
+
maxBytes: Type.Optional(Type.Integer({ minimum: 1, maximum: WORKSPACE_FILES_MAX_READ_BYTES_V1 })),
|
|
12
|
+
}, { additionalProperties: false });
|
|
13
|
+
const findSchema = Type.Object({
|
|
14
|
+
workspaceRef: refSchema,
|
|
15
|
+
query: Type.String({ minLength: 1, maxLength: WORKSPACE_FILES_MAX_QUERY_CHARS_V1 }),
|
|
16
|
+
limit: Type.Optional(Type.Integer({ minimum: 1, maximum: WORKSPACE_FILES_MAX_MATCHES_V1 })),
|
|
17
|
+
}, { additionalProperties: false });
|
|
18
|
+
function input(first, second) {
|
|
19
|
+
const value = second === undefined ? first : second;
|
|
20
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
21
|
+
throw new Error("workspace input must be an object");
|
|
22
|
+
const operationId = typeof first === "string" && first.trim() !== "" && first.length <= WORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1
|
|
23
|
+
? first
|
|
24
|
+
: "profile-runtime-tool-call";
|
|
25
|
+
const outer = value;
|
|
26
|
+
if (outer.request === null || typeof outer.request !== "object" || Array.isArray(outer.request))
|
|
27
|
+
throw new Error("workspace request must be an object");
|
|
28
|
+
return { request: outer.request, operationId };
|
|
29
|
+
}
|
|
30
|
+
function signalFrom(value) {
|
|
31
|
+
return value instanceof AbortSignal ? value : undefined;
|
|
32
|
+
}
|
|
33
|
+
const NON_SUCCESS_STATUSES = new Set(["failed", "cancelled", "needs_user", "unsupported"]);
|
|
34
|
+
function nonSuccessError(value) {
|
|
35
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
36
|
+
return undefined;
|
|
37
|
+
const error = value;
|
|
38
|
+
if (error.version !== 1 ||
|
|
39
|
+
typeof error.code !== "string" ||
|
|
40
|
+
!/^[a-z][a-z0-9_]{0,127}$/u.test(error.code) ||
|
|
41
|
+
typeof error.message !== "string" ||
|
|
42
|
+
error.message.trim() === "" ||
|
|
43
|
+
error.message.length > 512)
|
|
44
|
+
return undefined;
|
|
45
|
+
return { version: 1, code: error.code, message: sanitizeWorkspaceFilesTextV1(error.message, 512) };
|
|
46
|
+
}
|
|
47
|
+
function projectNonSuccess(value, operationId, kind) {
|
|
48
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
49
|
+
return undefined;
|
|
50
|
+
const result = value;
|
|
51
|
+
if (result.version !== 1 || result.operationId !== operationId || typeof result.status !== "string")
|
|
52
|
+
return undefined;
|
|
53
|
+
if (!NON_SUCCESS_STATUSES.has(result.status))
|
|
54
|
+
return undefined;
|
|
55
|
+
const error = nonSuccessError(result.error);
|
|
56
|
+
if (error === undefined)
|
|
57
|
+
return undefined;
|
|
58
|
+
if (kind === "list") {
|
|
59
|
+
if (Object.keys(result).some((key) => !["version", "operationId", "status", "entries", "entriesTruncated", "error"].includes(key)) ||
|
|
60
|
+
!Array.isArray(result.entries) ||
|
|
61
|
+
result.entries.length !== 0 ||
|
|
62
|
+
result.entriesTruncated !== false)
|
|
63
|
+
return undefined;
|
|
64
|
+
return {
|
|
65
|
+
version: 1,
|
|
66
|
+
operationId,
|
|
67
|
+
status: result.status,
|
|
68
|
+
entries: [],
|
|
69
|
+
entriesTruncated: false,
|
|
70
|
+
error,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
if (kind === "read") {
|
|
74
|
+
if (Object.keys(result).some((key) => ![
|
|
75
|
+
"version",
|
|
76
|
+
"operationId",
|
|
77
|
+
"status",
|
|
78
|
+
"contentPreview",
|
|
79
|
+
"contentBytes",
|
|
80
|
+
"contentTruncated",
|
|
81
|
+
"artifactRef",
|
|
82
|
+
"error",
|
|
83
|
+
].includes(key)) ||
|
|
84
|
+
result.contentPreview !== "" ||
|
|
85
|
+
result.contentBytes !== 0 ||
|
|
86
|
+
result.contentTruncated !== false)
|
|
87
|
+
return undefined;
|
|
88
|
+
return {
|
|
89
|
+
version: 1,
|
|
90
|
+
operationId,
|
|
91
|
+
status: result.status,
|
|
92
|
+
contentPreview: "",
|
|
93
|
+
contentBytes: 0,
|
|
94
|
+
contentTruncated: false,
|
|
95
|
+
error,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
if (Object.keys(result).some((key) => !["version", "operationId", "status", "matches", "matchesTruncated", "error"].includes(key)) ||
|
|
99
|
+
!Array.isArray(result.matches) ||
|
|
100
|
+
result.matches.length !== 0 ||
|
|
101
|
+
result.matchesTruncated !== false)
|
|
102
|
+
return undefined;
|
|
103
|
+
return {
|
|
104
|
+
version: 1,
|
|
105
|
+
operationId,
|
|
106
|
+
status: result.status,
|
|
107
|
+
matches: [],
|
|
108
|
+
matchesTruncated: false,
|
|
109
|
+
error,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function projectListResult(value, operationId) {
|
|
113
|
+
return (projectList(value, operationId) ??
|
|
114
|
+
projectNonSuccess(value, operationId, "list"));
|
|
115
|
+
}
|
|
116
|
+
function projectReadResult(value, operationId) {
|
|
117
|
+
return (projectRead(value, operationId) ??
|
|
118
|
+
projectNonSuccess(value, operationId, "read"));
|
|
119
|
+
}
|
|
120
|
+
function projectFindResult(value, operationId) {
|
|
121
|
+
return (projectFind(value, operationId) ??
|
|
122
|
+
projectNonSuccess(value, operationId, "find"));
|
|
123
|
+
}
|
|
124
|
+
function errorFor(status) {
|
|
125
|
+
const error = {
|
|
126
|
+
version: 1,
|
|
127
|
+
code: status === "cancelled" ? "cancelled" : "adapter_failed",
|
|
128
|
+
message: status === "cancelled" ? "Workspace operation was cancelled" : "Workspace file adapter failed",
|
|
129
|
+
};
|
|
130
|
+
return error;
|
|
131
|
+
}
|
|
132
|
+
function listFallback(operationId, status) {
|
|
133
|
+
return {
|
|
134
|
+
version: 1,
|
|
135
|
+
operationId,
|
|
136
|
+
status,
|
|
137
|
+
entries: [],
|
|
138
|
+
entriesTruncated: false,
|
|
139
|
+
error: errorFor(status),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function readFallback(operationId, status) {
|
|
143
|
+
return {
|
|
144
|
+
version: 1,
|
|
145
|
+
operationId,
|
|
146
|
+
status,
|
|
147
|
+
contentPreview: "",
|
|
148
|
+
contentBytes: 0,
|
|
149
|
+
contentTruncated: false,
|
|
150
|
+
error: errorFor(status),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
function findFallback(operationId, status) {
|
|
154
|
+
return {
|
|
155
|
+
version: 1,
|
|
156
|
+
operationId,
|
|
157
|
+
status,
|
|
158
|
+
matches: [],
|
|
159
|
+
matchesTruncated: false,
|
|
160
|
+
error: errorFor(status),
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
async function execute(operationId, signal, run, project, fallbackResult) {
|
|
164
|
+
if (signal?.aborted)
|
|
165
|
+
return fallbackResult("cancelled");
|
|
166
|
+
try {
|
|
167
|
+
const result = await run();
|
|
168
|
+
return project(result, operationId) ?? fallbackResult("failed");
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
return fallbackResult("failed");
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/** Registers bounded workspace reads using only opaque host-owned references. */
|
|
175
|
+
export function createWorkspaceFilesCapabilityFactoryV1(runtime) {
|
|
176
|
+
return (api) => {
|
|
177
|
+
api.registerTool({
|
|
178
|
+
name: "workspace_list",
|
|
179
|
+
label: "List workspace files",
|
|
180
|
+
description: "List bounded workspace entries through host-owned opaque references",
|
|
181
|
+
parameters: Type.Object({ request: listSchema }, { additionalProperties: false }),
|
|
182
|
+
execute: async (first, second, third) => {
|
|
183
|
+
try {
|
|
184
|
+
const { request, operationId } = input(first, second);
|
|
185
|
+
const signal = signalFrom(third);
|
|
186
|
+
return execute(operationId, signal, () => runtime.list({
|
|
187
|
+
version: 1,
|
|
188
|
+
operationId,
|
|
189
|
+
workspaceRef: request.workspaceRef,
|
|
190
|
+
...(request.directoryRef === undefined
|
|
191
|
+
? {}
|
|
192
|
+
: { directoryRef: request.directoryRef }),
|
|
193
|
+
...(request.limit === undefined ? {} : { limit: request.limit }),
|
|
194
|
+
}, signal), (value, id) => projectListResult(value, id), (status) => listFallback(operationId, status));
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
return listFallback("profile-runtime-tool-call", "failed");
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
api.registerTool({
|
|
202
|
+
name: "workspace_read",
|
|
203
|
+
label: "Read workspace file",
|
|
204
|
+
description: "Read a bounded preview from a host-owned workspace file reference",
|
|
205
|
+
parameters: Type.Object({ request: readSchema }, { additionalProperties: false }),
|
|
206
|
+
execute: async (first, second, third) => {
|
|
207
|
+
try {
|
|
208
|
+
const { request, operationId } = input(first, second);
|
|
209
|
+
const signal = signalFrom(third);
|
|
210
|
+
return execute(operationId, signal, () => runtime.read({
|
|
211
|
+
version: 1,
|
|
212
|
+
operationId,
|
|
213
|
+
fileRef: request.fileRef,
|
|
214
|
+
...(request.maxBytes === undefined ? {} : { maxBytes: request.maxBytes }),
|
|
215
|
+
}, signal), (value, id) => projectReadResult(value, id), (status) => readFallback(operationId, status));
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
return readFallback("profile-runtime-tool-call", "failed");
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
api.registerTool({
|
|
223
|
+
name: "workspace_find",
|
|
224
|
+
label: "Find in workspace",
|
|
225
|
+
description: "Return bounded workspace matches without injecting the full file contents",
|
|
226
|
+
parameters: Type.Object({ request: findSchema }, { additionalProperties: false }),
|
|
227
|
+
execute: async (first, second, third) => {
|
|
228
|
+
try {
|
|
229
|
+
const { request, operationId } = input(first, second);
|
|
230
|
+
const signal = signalFrom(third);
|
|
231
|
+
return execute(operationId, signal, () => runtime.find({
|
|
232
|
+
version: 1,
|
|
233
|
+
operationId,
|
|
234
|
+
workspaceRef: request.workspaceRef,
|
|
235
|
+
query: request.query,
|
|
236
|
+
...(request.limit === undefined ? {} : { limit: request.limit }),
|
|
237
|
+
}, signal), (value, id) => projectFindResult(value, id), (status) => findFallback(operationId, status));
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
return findFallback("profile-runtime-tool-call", "failed");
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=capability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability.js","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CapabilityPluginSyncFactory } from \"@agent-forge/plugin-sdk\";\nimport { Type } from \"typebox\";\nimport {\n\tprojectFind,\n\tprojectList,\n\tprojectRead,\n\tsanitizeWorkspaceFilesTextV1,\n\tWORKSPACE_FILES_MAX_MATCHES_V1,\n\tWORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1,\n\tWORKSPACE_FILES_MAX_QUERY_CHARS_V1,\n\tWORKSPACE_FILES_MAX_READ_BYTES_V1,\n} from \"./node-adapter.ts\";\nimport type {\n\tWorkspaceFilesAdapterV1,\n\tWorkspaceFilesFindResultV1,\n\tWorkspaceFilesListResultV1,\n\tWorkspaceFilesReadResultV1,\n} from \"./types.ts\";\n\nconst refSchema = Type.String({ minLength: 1, maxLength: 256, pattern: \"^[A-Za-z0-9][A-Za-z0-9._:-]*$\" });\nconst listSchema = Type.Object(\n\t{\n\t\tworkspaceRef: refSchema,\n\t\tdirectoryRef: Type.Optional(refSchema),\n\t\tlimit: Type.Optional(Type.Integer({ minimum: 1, maximum: 256 })),\n\t},\n\t{ additionalProperties: false },\n);\nconst readSchema = Type.Object(\n\t{\n\t\tfileRef: refSchema,\n\t\tmaxBytes: Type.Optional(Type.Integer({ minimum: 1, maximum: WORKSPACE_FILES_MAX_READ_BYTES_V1 })),\n\t},\n\t{ additionalProperties: false },\n);\nconst findSchema = Type.Object(\n\t{\n\t\tworkspaceRef: refSchema,\n\t\tquery: Type.String({ minLength: 1, maxLength: WORKSPACE_FILES_MAX_QUERY_CHARS_V1 }),\n\t\tlimit: Type.Optional(Type.Integer({ minimum: 1, maximum: WORKSPACE_FILES_MAX_MATCHES_V1 })),\n\t},\n\t{ additionalProperties: false },\n);\n\ntype Result = WorkspaceFilesListResultV1 | WorkspaceFilesReadResultV1 | WorkspaceFilesFindResultV1;\n\nfunction input(\n\tfirst: unknown,\n\tsecond: unknown,\n): { readonly request: Record<string, unknown>; readonly operationId: string } {\n\tconst value = second === undefined ? first : second;\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value))\n\t\tthrow new Error(\"workspace input must be an object\");\n\tconst operationId =\n\t\ttypeof first === \"string\" && first.trim() !== \"\" && first.length <= WORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1\n\t\t\t? first\n\t\t\t: \"profile-runtime-tool-call\";\n\tconst outer = value as Record<string, unknown>;\n\tif (outer.request === null || typeof outer.request !== \"object\" || Array.isArray(outer.request))\n\t\tthrow new Error(\"workspace request must be an object\");\n\treturn { request: outer.request as Record<string, unknown>, operationId };\n}\n\nfunction signalFrom(value: unknown): AbortSignal | undefined {\n\treturn value instanceof AbortSignal ? value : undefined;\n}\n\nconst NON_SUCCESS_STATUSES = new Set([\"failed\", \"cancelled\", \"needs_user\", \"unsupported\"]);\n\nfunction nonSuccessError(value: unknown): WorkspaceFilesListResultV1[\"error\"] | undefined {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n\tconst error = value as Record<string, unknown>;\n\tif (\n\t\terror.version !== 1 ||\n\t\ttypeof error.code !== \"string\" ||\n\t\t!/^[a-z][a-z0-9_]{0,127}$/u.test(error.code) ||\n\t\ttypeof error.message !== \"string\" ||\n\t\terror.message.trim() === \"\" ||\n\t\terror.message.length > 512\n\t)\n\t\treturn undefined;\n\treturn { version: 1, code: error.code, message: sanitizeWorkspaceFilesTextV1(error.message, 512) };\n}\n\nfunction projectNonSuccess(value: unknown, operationId: string, kind: \"list\" | \"read\" | \"find\"): Result | undefined {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n\tconst result = value as Record<string, unknown>;\n\tif (result.version !== 1 || result.operationId !== operationId || typeof result.status !== \"string\")\n\t\treturn undefined;\n\tif (!NON_SUCCESS_STATUSES.has(result.status)) return undefined;\n\tconst error = nonSuccessError(result.error);\n\tif (error === undefined) return undefined;\n\tif (kind === \"list\") {\n\t\tif (\n\t\t\tObject.keys(result).some(\n\t\t\t\t(key) => ![\"version\", \"operationId\", \"status\", \"entries\", \"entriesTruncated\", \"error\"].includes(key),\n\t\t\t) ||\n\t\t\t!Array.isArray(result.entries) ||\n\t\t\tresult.entries.length !== 0 ||\n\t\t\tresult.entriesTruncated !== false\n\t\t)\n\t\t\treturn undefined;\n\t\treturn {\n\t\t\tversion: 1,\n\t\t\toperationId,\n\t\t\tstatus: result.status as WorkspaceFilesListResultV1[\"status\"],\n\t\t\tentries: [],\n\t\t\tentriesTruncated: false,\n\t\t\terror,\n\t\t};\n\t}\n\tif (kind === \"read\") {\n\t\tif (\n\t\t\tObject.keys(result).some(\n\t\t\t\t(key) =>\n\t\t\t\t\t![\n\t\t\t\t\t\t\"version\",\n\t\t\t\t\t\t\"operationId\",\n\t\t\t\t\t\t\"status\",\n\t\t\t\t\t\t\"contentPreview\",\n\t\t\t\t\t\t\"contentBytes\",\n\t\t\t\t\t\t\"contentTruncated\",\n\t\t\t\t\t\t\"artifactRef\",\n\t\t\t\t\t\t\"error\",\n\t\t\t\t\t].includes(key),\n\t\t\t) ||\n\t\t\tresult.contentPreview !== \"\" ||\n\t\t\tresult.contentBytes !== 0 ||\n\t\t\tresult.contentTruncated !== false\n\t\t)\n\t\t\treturn undefined;\n\t\treturn {\n\t\t\tversion: 1,\n\t\t\toperationId,\n\t\t\tstatus: result.status as WorkspaceFilesReadResultV1[\"status\"],\n\t\t\tcontentPreview: \"\",\n\t\t\tcontentBytes: 0,\n\t\t\tcontentTruncated: false,\n\t\t\terror,\n\t\t};\n\t}\n\tif (\n\t\tObject.keys(result).some(\n\t\t\t(key) => ![\"version\", \"operationId\", \"status\", \"matches\", \"matchesTruncated\", \"error\"].includes(key),\n\t\t) ||\n\t\t!Array.isArray(result.matches) ||\n\t\tresult.matches.length !== 0 ||\n\t\tresult.matchesTruncated !== false\n\t)\n\t\treturn undefined;\n\treturn {\n\t\tversion: 1,\n\t\toperationId,\n\t\tstatus: result.status as WorkspaceFilesFindResultV1[\"status\"],\n\t\tmatches: [],\n\t\tmatchesTruncated: false,\n\t\terror,\n\t};\n}\n\nfunction projectListResult(value: unknown, operationId: string): WorkspaceFilesListResultV1 | undefined {\n\treturn (\n\t\tprojectList(value, operationId) ??\n\t\t(projectNonSuccess(value, operationId, \"list\") as WorkspaceFilesListResultV1 | undefined)\n\t);\n}\n\nfunction projectReadResult(value: unknown, operationId: string): WorkspaceFilesReadResultV1 | undefined {\n\treturn (\n\t\tprojectRead(value, operationId) ??\n\t\t(projectNonSuccess(value, operationId, \"read\") as WorkspaceFilesReadResultV1 | undefined)\n\t);\n}\n\nfunction projectFindResult(value: unknown, operationId: string): WorkspaceFilesFindResultV1 | undefined {\n\treturn (\n\t\tprojectFind(value, operationId) ??\n\t\t(projectNonSuccess(value, operationId, \"find\") as WorkspaceFilesFindResultV1 | undefined)\n\t);\n}\n\nfunction errorFor(status: \"failed\" | \"cancelled\") {\n\tconst error = {\n\t\tversion: 1 as const,\n\t\tcode: status === \"cancelled\" ? \"cancelled\" : \"adapter_failed\",\n\t\tmessage: status === \"cancelled\" ? \"Workspace operation was cancelled\" : \"Workspace file adapter failed\",\n\t};\n\treturn error;\n}\n\nfunction listFallback(operationId: string, status: \"failed\" | \"cancelled\"): WorkspaceFilesListResultV1 {\n\treturn {\n\t\tversion: 1,\n\t\toperationId,\n\t\tstatus,\n\t\tentries: [],\n\t\tentriesTruncated: false,\n\t\terror: errorFor(status),\n\t};\n}\n\nfunction readFallback(operationId: string, status: \"failed\" | \"cancelled\"): WorkspaceFilesReadResultV1 {\n\treturn {\n\t\tversion: 1,\n\t\toperationId,\n\t\tstatus,\n\t\tcontentPreview: \"\",\n\t\tcontentBytes: 0,\n\t\tcontentTruncated: false,\n\t\terror: errorFor(status),\n\t};\n}\n\nfunction findFallback(operationId: string, status: \"failed\" | \"cancelled\"): WorkspaceFilesFindResultV1 {\n\treturn {\n\t\tversion: 1,\n\t\toperationId,\n\t\tstatus,\n\t\tmatches: [],\n\t\tmatchesTruncated: false,\n\t\terror: errorFor(status),\n\t};\n}\n\nasync function execute<T extends Result>(\n\toperationId: string,\n\tsignal: AbortSignal | undefined,\n\trun: () => Promise<T>,\n\tproject: (value: unknown, operationId: string) => T | undefined,\n\tfallbackResult: (status: \"failed\" | \"cancelled\") => T,\n): Promise<T> {\n\tif (signal?.aborted) return fallbackResult(\"cancelled\");\n\ttry {\n\t\tconst result = await run();\n\t\treturn project(result, operationId) ?? fallbackResult(\"failed\");\n\t} catch {\n\t\treturn fallbackResult(\"failed\");\n\t}\n}\n\n/** Registers bounded workspace reads using only opaque host-owned references. */\nexport function createWorkspaceFilesCapabilityFactoryV1(runtime: WorkspaceFilesAdapterV1): CapabilityPluginSyncFactory {\n\treturn (api) => {\n\t\tapi.registerTool({\n\t\t\tname: \"workspace_list\",\n\t\t\tlabel: \"List workspace files\",\n\t\t\tdescription: \"List bounded workspace entries through host-owned opaque references\",\n\t\t\tparameters: Type.Object({ request: listSchema }, { additionalProperties: false }),\n\t\t\texecute: async (first: unknown, second?: unknown, third?: unknown) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst { request, operationId } = input(first, second);\n\t\t\t\t\tconst signal = signalFrom(third);\n\t\t\t\t\treturn execute(\n\t\t\t\t\t\toperationId,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t() =>\n\t\t\t\t\t\t\truntime.list(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t\toperationId,\n\t\t\t\t\t\t\t\t\tworkspaceRef: request.workspaceRef as string,\n\t\t\t\t\t\t\t\t\t...(request.directoryRef === undefined\n\t\t\t\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t\t\t\t: { directoryRef: request.directoryRef as string }),\n\t\t\t\t\t\t\t\t\t...(request.limit === undefined ? {} : { limit: request.limit as number }),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t(value, id) => projectListResult(value, id),\n\t\t\t\t\t\t(status) => listFallback(operationId, status),\n\t\t\t\t\t);\n\t\t\t\t} catch {\n\t\t\t\t\treturn listFallback(\"profile-runtime-tool-call\", \"failed\");\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t\tapi.registerTool({\n\t\t\tname: \"workspace_read\",\n\t\t\tlabel: \"Read workspace file\",\n\t\t\tdescription: \"Read a bounded preview from a host-owned workspace file reference\",\n\t\t\tparameters: Type.Object({ request: readSchema }, { additionalProperties: false }),\n\t\t\texecute: async (first: unknown, second?: unknown, third?: unknown) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst { request, operationId } = input(first, second);\n\t\t\t\t\tconst signal = signalFrom(third);\n\t\t\t\t\treturn execute(\n\t\t\t\t\t\toperationId,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t() =>\n\t\t\t\t\t\t\truntime.read(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t\toperationId,\n\t\t\t\t\t\t\t\t\tfileRef: request.fileRef as string,\n\t\t\t\t\t\t\t\t\t...(request.maxBytes === undefined ? {} : { maxBytes: request.maxBytes as number }),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t(value, id) => projectReadResult(value, id),\n\t\t\t\t\t\t(status) => readFallback(operationId, status),\n\t\t\t\t\t);\n\t\t\t\t} catch {\n\t\t\t\t\treturn readFallback(\"profile-runtime-tool-call\", \"failed\");\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t\tapi.registerTool({\n\t\t\tname: \"workspace_find\",\n\t\t\tlabel: \"Find in workspace\",\n\t\t\tdescription: \"Return bounded workspace matches without injecting the full file contents\",\n\t\t\tparameters: Type.Object({ request: findSchema }, { additionalProperties: false }),\n\t\t\texecute: async (first: unknown, second?: unknown, third?: unknown) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst { request, operationId } = input(first, second);\n\t\t\t\t\tconst signal = signalFrom(third);\n\t\t\t\t\treturn execute(\n\t\t\t\t\t\toperationId,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t() =>\n\t\t\t\t\t\t\truntime.find(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\t\t\t\toperationId,\n\t\t\t\t\t\t\t\t\tworkspaceRef: request.workspaceRef as string,\n\t\t\t\t\t\t\t\t\tquery: request.query as string,\n\t\t\t\t\t\t\t\t\t...(request.limit === undefined ? {} : { limit: request.limit as number }),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t(value, id) => projectFindResult(value, id),\n\t\t\t\t\t\t(status) => findFallback(operationId, status),\n\t\t\t\t\t);\n\t\t\t\t} catch {\n\t\t\t\t\treturn findFallback(\"profile-runtime-tool-call\", \"failed\");\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t};\n}\n"]}
|
package/dist/entry.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default-export factory consumed by the host's `loadCapabilityPluginFromManifest`.
|
|
3
|
+
*
|
|
4
|
+
* The adapter is deliberately constructed without host injection: workspace
|
|
5
|
+
* listing, reading, and search are host-owned per workspace (list/read/find
|
|
6
|
+
* seams resolve opaque refs to real files), so the registered
|
|
7
|
+
* `workspace_list`/`workspace_read`/`workspace_find` tools report an explicit
|
|
8
|
+
* `unsupported` result until a host binds a real file host through its own
|
|
9
|
+
* profile machinery (fail-closed by design, same contract as the embedded
|
|
10
|
+
* build).
|
|
11
|
+
*/
|
|
12
|
+
declare const _default: import("@agent-forge/plugin-sdk").CapabilityPluginSyncFactory;
|
|
13
|
+
export default _default;
|
|
14
|
+
//# sourceMappingURL=entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry.d.ts","sourceRoot":"","sources":["../src/entry.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;;AACH,wBAA4F","sourcesContent":["import { createWorkspaceFilesCapabilityFactoryV1 } from \"./capability.ts\";\nimport { createNodeWorkspaceFilesAdapterV1 } from \"./node-adapter.ts\";\n\n/**\n * Default-export factory consumed by the host's `loadCapabilityPluginFromManifest`.\n *\n * The adapter is deliberately constructed without host injection: workspace\n * listing, reading, and search are host-owned per workspace (list/read/find\n * seams resolve opaque refs to real files), so the registered\n * `workspace_list`/`workspace_read`/`workspace_find` tools report an explicit\n * `unsupported` result until a host binds a real file host through its own\n * profile machinery (fail-closed by design, same contract as the embedded\n * build).\n */\nexport default createWorkspaceFilesCapabilityFactoryV1(createNodeWorkspaceFilesAdapterV1());\n"]}
|
package/dist/entry.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createWorkspaceFilesCapabilityFactoryV1 } from "./capability.js";
|
|
2
|
+
import { createNodeWorkspaceFilesAdapterV1 } from "./node-adapter.js";
|
|
3
|
+
/**
|
|
4
|
+
* Default-export factory consumed by the host's `loadCapabilityPluginFromManifest`.
|
|
5
|
+
*
|
|
6
|
+
* The adapter is deliberately constructed without host injection: workspace
|
|
7
|
+
* listing, reading, and search are host-owned per workspace (list/read/find
|
|
8
|
+
* seams resolve opaque refs to real files), so the registered
|
|
9
|
+
* `workspace_list`/`workspace_read`/`workspace_find` tools report an explicit
|
|
10
|
+
* `unsupported` result until a host binds a real file host through its own
|
|
11
|
+
* profile machinery (fail-closed by design, same contract as the embedded
|
|
12
|
+
* build).
|
|
13
|
+
*/
|
|
14
|
+
export default createWorkspaceFilesCapabilityFactoryV1(createNodeWorkspaceFilesAdapterV1());
|
|
15
|
+
//# sourceMappingURL=entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry.js","sourceRoot":"","sources":["../src/entry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uCAAuC,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAE,iCAAiC,EAAE,MAAM,mBAAmB,CAAC;AAEtE;;;;;;;;;;GAUG;AACH,eAAe,uCAAuC,CAAC,iCAAiC,EAAE,CAAC,CAAC","sourcesContent":["import { createWorkspaceFilesCapabilityFactoryV1 } from \"./capability.ts\";\nimport { createNodeWorkspaceFilesAdapterV1 } from \"./node-adapter.ts\";\n\n/**\n * Default-export factory consumed by the host's `loadCapabilityPluginFromManifest`.\n *\n * The adapter is deliberately constructed without host injection: workspace\n * listing, reading, and search are host-owned per workspace (list/read/find\n * seams resolve opaque refs to real files), so the registered\n * `workspace_list`/`workspace_read`/`workspace_find` tools report an explicit\n * `unsupported` result until a host binds a real file host through its own\n * profile machinery (fail-closed by design, same contract as the embedded\n * build).\n */\nexport default createWorkspaceFilesCapabilityFactoryV1(createNodeWorkspaceFilesAdapterV1());\n"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createWorkspaceFilesCapabilityFactoryV1 } from "./capability.ts";
|
|
2
|
+
export { contextSafe, createNodeWorkspaceFilesAdapterV1, projectFind, projectList, projectRead, sanitizeWorkspaceFilesTextV1, validateFindRequest, validateListRequest, validateReadRequest, WORKSPACE_FILES_MAX_ENTRIES_V1, WORKSPACE_FILES_MAX_MATCHES_V1, WORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1, WORKSPACE_FILES_MAX_OUTPUT_BYTES_V1, WORKSPACE_FILES_MAX_PREVIEW_CHARS_V1, WORKSPACE_FILES_MAX_QUERY_CHARS_V1, WORKSPACE_FILES_MAX_READ_BYTES_V1, } from "./node-adapter.ts";
|
|
3
|
+
export type * from "./types.ts";
|
|
4
|
+
export type { NodeWorkspaceFilesAdapterOptionsV1 } from "./types.ts";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uCAAuC,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EACN,WAAW,EACX,iCAAiC,EACjC,WAAW,EACX,WAAW,EACX,WAAW,EACX,4BAA4B,EAC5B,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,8BAA8B,EAC9B,8BAA8B,EAC9B,yCAAyC,EACzC,mCAAmC,EACnC,oCAAoC,EACpC,kCAAkC,EAClC,iCAAiC,GACjC,MAAM,mBAAmB,CAAC;AAC3B,mBAAmB,YAAY,CAAC;AAChC,YAAY,EAAE,kCAAkC,EAAE,MAAM,YAAY,CAAC","sourcesContent":["export { createWorkspaceFilesCapabilityFactoryV1 } from \"./capability.ts\";\nexport {\n\tcontextSafe,\n\tcreateNodeWorkspaceFilesAdapterV1,\n\tprojectFind,\n\tprojectList,\n\tprojectRead,\n\tsanitizeWorkspaceFilesTextV1,\n\tvalidateFindRequest,\n\tvalidateListRequest,\n\tvalidateReadRequest,\n\tWORKSPACE_FILES_MAX_ENTRIES_V1,\n\tWORKSPACE_FILES_MAX_MATCHES_V1,\n\tWORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1,\n\tWORKSPACE_FILES_MAX_OUTPUT_BYTES_V1,\n\tWORKSPACE_FILES_MAX_PREVIEW_CHARS_V1,\n\tWORKSPACE_FILES_MAX_QUERY_CHARS_V1,\n\tWORKSPACE_FILES_MAX_READ_BYTES_V1,\n} from \"./node-adapter.ts\";\nexport type * from \"./types.ts\";\nexport type { NodeWorkspaceFilesAdapterOptionsV1 } from \"./types.ts\";\n"]}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { createWorkspaceFilesCapabilityFactoryV1 } from "./capability.js";
|
|
2
|
+
export { contextSafe, createNodeWorkspaceFilesAdapterV1, projectFind, projectList, projectRead, sanitizeWorkspaceFilesTextV1, validateFindRequest, validateListRequest, validateReadRequest, WORKSPACE_FILES_MAX_ENTRIES_V1, WORKSPACE_FILES_MAX_MATCHES_V1, WORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1, WORKSPACE_FILES_MAX_OUTPUT_BYTES_V1, WORKSPACE_FILES_MAX_PREVIEW_CHARS_V1, WORKSPACE_FILES_MAX_QUERY_CHARS_V1, WORKSPACE_FILES_MAX_READ_BYTES_V1, } from "./node-adapter.js";
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uCAAuC,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EACN,WAAW,EACX,iCAAiC,EACjC,WAAW,EACX,WAAW,EACX,WAAW,EACX,4BAA4B,EAC5B,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,8BAA8B,EAC9B,8BAA8B,EAC9B,yCAAyC,EACzC,mCAAmC,EACnC,oCAAoC,EACpC,kCAAkC,EAClC,iCAAiC,GACjC,MAAM,mBAAmB,CAAC","sourcesContent":["export { createWorkspaceFilesCapabilityFactoryV1 } from \"./capability.ts\";\nexport {\n\tcontextSafe,\n\tcreateNodeWorkspaceFilesAdapterV1,\n\tprojectFind,\n\tprojectList,\n\tprojectRead,\n\tsanitizeWorkspaceFilesTextV1,\n\tvalidateFindRequest,\n\tvalidateListRequest,\n\tvalidateReadRequest,\n\tWORKSPACE_FILES_MAX_ENTRIES_V1,\n\tWORKSPACE_FILES_MAX_MATCHES_V1,\n\tWORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1,\n\tWORKSPACE_FILES_MAX_OUTPUT_BYTES_V1,\n\tWORKSPACE_FILES_MAX_PREVIEW_CHARS_V1,\n\tWORKSPACE_FILES_MAX_QUERY_CHARS_V1,\n\tWORKSPACE_FILES_MAX_READ_BYTES_V1,\n} from \"./node-adapter.ts\";\nexport type * from \"./types.ts\";\nexport type { NodeWorkspaceFilesAdapterOptionsV1 } from \"./types.ts\";\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type NodeWorkspaceFilesAdapterOptionsV1, type WorkspaceFilesAdapterV1, type WorkspaceFilesFindRequestV1, type WorkspaceFilesFindResultV1, type WorkspaceFilesListRequestV1, type WorkspaceFilesListResultV1, type WorkspaceFilesReadRequestV1, type WorkspaceFilesReadResultV1 } from "./types.ts";
|
|
2
|
+
export declare const WORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1 = 256;
|
|
3
|
+
export declare const WORKSPACE_FILES_MAX_OUTPUT_BYTES_V1: number;
|
|
4
|
+
export declare const WORKSPACE_FILES_MAX_ENTRIES_V1 = 256;
|
|
5
|
+
export declare const WORKSPACE_FILES_MAX_MATCHES_V1 = 128;
|
|
6
|
+
export declare const WORKSPACE_FILES_MAX_PREVIEW_CHARS_V1 = 4096;
|
|
7
|
+
export declare const WORKSPACE_FILES_MAX_REF_CHARS_V1 = 256;
|
|
8
|
+
export declare const WORKSPACE_FILES_MAX_NAME_CHARS_V1 = 256;
|
|
9
|
+
export declare const WORKSPACE_FILES_MAX_QUERY_CHARS_V1 = 512;
|
|
10
|
+
export declare const WORKSPACE_FILES_MAX_READ_BYTES_V1: number;
|
|
11
|
+
export declare function sanitizeWorkspaceFilesTextV1(value: string, maximum?: number): string;
|
|
12
|
+
declare function validateListRequest(request: WorkspaceFilesListRequestV1): string | undefined;
|
|
13
|
+
declare function validateReadRequest(request: WorkspaceFilesReadRequestV1): string | undefined;
|
|
14
|
+
declare function validateFindRequest(request: WorkspaceFilesFindRequestV1): string | undefined;
|
|
15
|
+
declare function projectList(value: unknown, operationId: string): WorkspaceFilesListResultV1 | undefined;
|
|
16
|
+
declare function projectRead(value: unknown, operationId: string): WorkspaceFilesReadResultV1 | undefined;
|
|
17
|
+
declare function projectFind(value: unknown, operationId: string): WorkspaceFilesFindResultV1 | undefined;
|
|
18
|
+
declare function contextSafe(operationId: string, items: readonly object[], truncated: boolean, outputArtifactRef?: string): boolean;
|
|
19
|
+
export declare function createNodeWorkspaceFilesAdapterV1(options?: NodeWorkspaceFilesAdapterOptionsV1): WorkspaceFilesAdapterV1;
|
|
20
|
+
export { contextSafe, projectFind, projectList, projectRead, validateFindRequest, validateListRequest, validateReadRequest, };
|
|
21
|
+
//# sourceMappingURL=node-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-adapter.d.ts","sourceRoot":"","sources":["../src/node-adapter.ts"],"names":[],"mappings":"AAEA,OAAO,EACN,KAAK,kCAAkC,EAKvC,KAAK,uBAAuB,EAC5B,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,yCAAyC,MAAM,CAAC;AAC7D,eAAO,MAAM,mCAAmC,QAAY,CAAC;AAC7D,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAClD,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAClD,eAAO,MAAM,oCAAoC,OAAO,CAAC;AACzD,eAAO,MAAM,gCAAgC,MAAM,CAAC;AACpD,eAAO,MAAM,iCAAiC,MAAM,CAAC;AACrD,eAAO,MAAM,kCAAkC,MAAM,CAAC;AACtD,eAAO,MAAM,iCAAiC,QAAkB,CAAC;AAwCjE,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,SAAuC,GAAG,MAAM,CAElH;AAmDD,iBAAS,mBAAmB,CAAC,OAAO,EAAE,2BAA2B,GAAG,MAAM,GAAG,SAAS,CAcrF;AAED,iBAAS,mBAAmB,CAAC,OAAO,EAAE,2BAA2B,GAAG,MAAM,GAAG,SAAS,CAYrF;AAED,iBAAS,mBAAmB,CAAC,OAAO,EAAE,2BAA2B,GAAG,MAAM,GAAG,SAAS,CAkBrF;AAuBD,iBAAS,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,GAAG,0BAA0B,GAAG,SAAS,CAuBhG;AAED,iBAAS,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,GAAG,0BAA0B,GAAG,SAAS,CA6BhG;AAeD,iBAAS,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,GAAG,0BAA0B,GAAG,SAAS,CAuBhG;AAMD,iBAAS,WAAW,CACnB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,SAAS,EAAE,OAAO,EAClB,iBAAiB,CAAC,EAAE,MAAM,GACxB,OAAO,CAiBT;AAuDD,wBAAgB,iCAAiC,CAChD,OAAO,GAAE,kCAAuC,GAC9C,uBAAuB,CA4DzB;AAED,OAAO,EACN,WAAW,EACX,WAAW,EACX,WAAW,EACX,WAAW,EACX,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,GACnB,CAAC","sourcesContent":["import type { JsonValue } from \"@agent-forge/plugin-sdk\";\nimport { projectPluginContextV1 } from \"@agent-forge/plugin-sdk\";\nimport {\n\ttype NodeWorkspaceFilesAdapterOptionsV1,\n\tWORKSPACE_FILES_HOST_ADAPTER_ID_V1,\n\tWORKSPACE_FILES_HOST_ADAPTER_VERSION_V1,\n\ttype WorkspaceFileEntryV1,\n\ttype WorkspaceFileMatchV1,\n\ttype WorkspaceFilesAdapterV1,\n\ttype WorkspaceFilesFindRequestV1,\n\ttype WorkspaceFilesFindResultV1,\n\ttype WorkspaceFilesListRequestV1,\n\ttype WorkspaceFilesListResultV1,\n\ttype WorkspaceFilesReadRequestV1,\n\ttype WorkspaceFilesReadResultV1,\n} from \"./types.ts\";\n\nexport const WORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1 = 256;\nexport const WORKSPACE_FILES_MAX_OUTPUT_BYTES_V1 = 64 * 1024;\nexport const WORKSPACE_FILES_MAX_ENTRIES_V1 = 256;\nexport const WORKSPACE_FILES_MAX_MATCHES_V1 = 128;\nexport const WORKSPACE_FILES_MAX_PREVIEW_CHARS_V1 = 4096;\nexport const WORKSPACE_FILES_MAX_REF_CHARS_V1 = 256;\nexport const WORKSPACE_FILES_MAX_NAME_CHARS_V1 = 256;\nexport const WORKSPACE_FILES_MAX_QUERY_CHARS_V1 = 512;\nexport const WORKSPACE_FILES_MAX_READ_BYTES_V1 = 4 * 1024 * 1024;\n\nconst OPAQUE_REF_V1 = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$/u;\nconst SAFE_NAME_V1 = /^[^\\u0000\\r\\n\\\\/]{1,256}$/u;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction hasOnlyKeys(value: Record<string, unknown>, keys: readonly string[]): boolean {\n\treturn Object.keys(value).every((key) => keys.includes(key));\n}\n\nfunction safeRef(value: unknown): value is string {\n\treturn typeof value === \"string\" && OPAQUE_REF_V1.test(value);\n}\n\nfunction safeArtifactRef(value: unknown): value is string {\n\treturn value === undefined || safeRef(value);\n}\n\nfunction positiveInteger(value: unknown, maximum: number): value is number {\n\treturn Number.isSafeInteger(value) && (value as number) >= 1 && (value as number) <= maximum;\n}\n\nfunction nonNegativeInteger(value: unknown, maximum: number): value is number {\n\treturn Number.isSafeInteger(value) && (value as number) >= 0 && (value as number) <= maximum;\n}\n\nfunction sanitizeText(value: string, maximum = WORKSPACE_FILES_MAX_PREVIEW_CHARS_V1): string {\n\tconst sanitized = value\n\t\t.replace(\n\t\t\t/((?:api[-_ ]?key|access[-_ ]?token|auth(?:orization)?|bearer|password|passwd|secret|token)\\s*[:=]\\s*)([^\\s,;]+)/giu,\n\t\t\t\"$1[redacted-secret]\",\n\t\t)\n\t\t.replace(/(?:[A-Za-z]:[\\\\/]|\\\\\\\\|\\/(?:home|Users|private|tmp|var|workspace)\\/)[^\\s\"'<>]*/gu, \"[redacted-path]\");\n\tconst characters = [...sanitized];\n\treturn characters.length <= maximum ? sanitized : characters.slice(0, maximum).join(\"\");\n}\n\nexport function sanitizeWorkspaceFilesTextV1(value: string, maximum = WORKSPACE_FILES_MAX_PREVIEW_CHARS_V1): string {\n\treturn sanitizeText(value, maximum);\n}\n\nfunction error(\n\toperationId: string,\n\tstatus: WorkspaceFilesListResultV1[\"status\"],\n\tcode: string,\n\tmessage: string,\n): WorkspaceFilesListResultV1 {\n\treturn {\n\t\tversion: 1 as const,\n\t\toperationId,\n\t\tstatus,\n\t\tentries: [] as readonly WorkspaceFileEntryV1[],\n\t\tentriesTruncated: false,\n\t\terror: { version: 1 as const, code, message },\n\t};\n}\n\nfunction readError(\n\toperationId: string,\n\tstatus: WorkspaceFilesReadResultV1[\"status\"],\n\tcode: string,\n\tmessage: string,\n): WorkspaceFilesReadResultV1 {\n\treturn {\n\t\tversion: 1 as const,\n\t\toperationId,\n\t\tstatus,\n\t\tcontentPreview: \"\",\n\t\tcontentBytes: 0,\n\t\tcontentTruncated: false,\n\t\terror: { version: 1 as const, code, message },\n\t};\n}\n\nfunction findError(\n\toperationId: string,\n\tstatus: WorkspaceFilesFindResultV1[\"status\"],\n\tcode: string,\n\tmessage: string,\n): WorkspaceFilesFindResultV1 {\n\treturn {\n\t\tversion: 1 as const,\n\t\toperationId,\n\t\tstatus,\n\t\tmatches: [] as readonly WorkspaceFileMatchV1[],\n\t\tmatchesTruncated: false,\n\t\terror: { version: 1 as const, code, message },\n\t};\n}\n\nfunction validateListRequest(request: WorkspaceFilesListRequestV1): string | undefined {\n\tif (request.version !== 1) return \"version must be 1\";\n\tif (\n\t\ttypeof request.operationId !== \"string\" ||\n\t\trequest.operationId.trim() === \"\" ||\n\t\trequest.operationId.length > WORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1\n\t)\n\t\treturn \"operationId is invalid\";\n\tif (!safeRef(request.workspaceRef)) return \"workspaceRef must be an opaque host handle\";\n\tif (request.directoryRef !== undefined && !safeRef(request.directoryRef))\n\t\treturn \"directoryRef must be an opaque host handle\";\n\tif (request.limit !== undefined && !positiveInteger(request.limit, WORKSPACE_FILES_MAX_ENTRIES_V1))\n\t\treturn \"limit is invalid\";\n\treturn undefined;\n}\n\nfunction validateReadRequest(request: WorkspaceFilesReadRequestV1): string | undefined {\n\tif (request.version !== 1) return \"version must be 1\";\n\tif (\n\t\ttypeof request.operationId !== \"string\" ||\n\t\trequest.operationId.trim() === \"\" ||\n\t\trequest.operationId.length > WORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1\n\t)\n\t\treturn \"operationId is invalid\";\n\tif (!safeRef(request.fileRef)) return \"fileRef must be an opaque host handle\";\n\tif (request.maxBytes !== undefined && !positiveInteger(request.maxBytes, WORKSPACE_FILES_MAX_READ_BYTES_V1))\n\t\treturn \"maxBytes is invalid\";\n\treturn undefined;\n}\n\nfunction validateFindRequest(request: WorkspaceFilesFindRequestV1): string | undefined {\n\tif (request.version !== 1) return \"version must be 1\";\n\tif (\n\t\ttypeof request.operationId !== \"string\" ||\n\t\trequest.operationId.trim() === \"\" ||\n\t\trequest.operationId.length > WORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1\n\t)\n\t\treturn \"operationId is invalid\";\n\tif (!safeRef(request.workspaceRef)) return \"workspaceRef must be an opaque host handle\";\n\tif (\n\t\ttypeof request.query !== \"string\" ||\n\t\trequest.query.trim() === \"\" ||\n\t\trequest.query.length > WORKSPACE_FILES_MAX_QUERY_CHARS_V1\n\t)\n\t\treturn \"query is invalid\";\n\tif (request.limit !== undefined && !positiveInteger(request.limit, WORKSPACE_FILES_MAX_MATCHES_V1))\n\t\treturn \"limit is invalid\";\n\treturn undefined;\n}\n\nfunction projectEntry(value: unknown): WorkspaceFileEntryV1 | undefined {\n\tif (!isRecord(value) || !hasOnlyKeys(value, [\"version\", \"fileRef\", \"name\", \"kind\", \"sizeBytes\"])) return undefined;\n\tif (\n\t\tvalue.version !== 1 ||\n\t\t!safeRef(value.fileRef) ||\n\t\ttypeof value.name !== \"string\" ||\n\t\t!SAFE_NAME_V1.test(value.name)\n\t)\n\t\treturn undefined;\n\tif (value.kind !== \"file\" && value.kind !== \"directory\") return undefined;\n\tif (value.sizeBytes !== undefined && !nonNegativeInteger(value.sizeBytes, WORKSPACE_FILES_MAX_READ_BYTES_V1))\n\t\treturn undefined;\n\treturn {\n\t\tversion: 1,\n\t\tfileRef: value.fileRef,\n\t\tname: sanitizeText(value.name, WORKSPACE_FILES_MAX_NAME_CHARS_V1),\n\t\tkind: value.kind,\n\t\t...(value.sizeBytes === undefined ? {} : { sizeBytes: value.sizeBytes }),\n\t};\n}\n\nfunction projectList(value: unknown, operationId: string): WorkspaceFilesListResultV1 | undefined {\n\tif (!isRecord(value) || value.version !== 1 || value.operationId !== operationId || value.status !== \"succeeded\")\n\t\treturn undefined;\n\tif (\n\t\t!Array.isArray(value.entries) ||\n\t\tvalue.entries.length > WORKSPACE_FILES_MAX_ENTRIES_V1 ||\n\t\ttypeof value.entriesTruncated !== \"boolean\"\n\t)\n\t\treturn undefined;\n\tconst entries = value.entries.map(projectEntry);\n\tif (entries.some((entry) => entry === undefined)) return undefined;\n\tfor (let count = entries.length; count >= 0; count -= 1) {\n\t\tconst projected: WorkspaceFilesListResultV1 = {\n\t\t\tversion: 1,\n\t\t\toperationId,\n\t\t\tstatus: \"succeeded\",\n\t\t\tentries: (entries as WorkspaceFileEntryV1[]).slice(0, count),\n\t\t\tentriesTruncated: value.entriesTruncated || count < entries.length,\n\t\t};\n\t\tif (boundedResult(projected) && contextSafe(operationId, projected.entries, projected.entriesTruncated))\n\t\t\treturn projected;\n\t}\n\treturn undefined;\n}\n\nfunction projectRead(value: unknown, operationId: string): WorkspaceFilesReadResultV1 | undefined {\n\tif (!isRecord(value) || value.version !== 1 || value.operationId !== operationId || value.status !== \"succeeded\")\n\t\treturn undefined;\n\tif (\n\t\ttypeof value.contentPreview !== \"string\" ||\n\t\tvalue.contentPreview.length > WORKSPACE_FILES_MAX_PREVIEW_CHARS_V1 ||\n\t\t!nonNegativeInteger(value.contentBytes, WORKSPACE_FILES_MAX_READ_BYTES_V1) ||\n\t\ttypeof value.contentTruncated !== \"boolean\" ||\n\t\t!safeArtifactRef(value.artifactRef)\n\t)\n\t\treturn undefined;\n\tconst projected: WorkspaceFilesReadResultV1 = {\n\t\tversion: 1,\n\t\toperationId,\n\t\tstatus: \"succeeded\",\n\t\tcontentPreview: sanitizeText(value.contentPreview),\n\t\tcontentBytes: value.contentBytes,\n\t\tcontentTruncated: value.contentTruncated,\n\t\t...(value.artifactRef === undefined ? {} : { artifactRef: value.artifactRef }),\n\t};\n\treturn boundedResult(projected) &&\n\t\tcontextSafe(\n\t\t\toperationId,\n\t\t\t[{ contentPreview: projected.contentPreview }],\n\t\t\tprojected.contentTruncated,\n\t\t\tprojected.artifactRef,\n\t\t)\n\t\t? projected\n\t\t: undefined;\n}\n\nfunction projectMatch(value: unknown): WorkspaceFileMatchV1 | undefined {\n\tif (!isRecord(value) || !hasOnlyKeys(value, [\"fileRef\", \"line\", \"column\", \"preview\"])) return undefined;\n\tif (\n\t\t!safeRef(value.fileRef) ||\n\t\t!positiveInteger(value.line, 10_000_000) ||\n\t\t!positiveInteger(value.column, 10_000_000)\n\t)\n\t\treturn undefined;\n\tif (typeof value.preview !== \"string\" || value.preview.length > WORKSPACE_FILES_MAX_PREVIEW_CHARS_V1)\n\t\treturn undefined;\n\treturn { fileRef: value.fileRef, line: value.line, column: value.column, preview: sanitizeText(value.preview) };\n}\n\nfunction projectFind(value: unknown, operationId: string): WorkspaceFilesFindResultV1 | undefined {\n\tif (!isRecord(value) || value.version !== 1 || value.operationId !== operationId || value.status !== \"succeeded\")\n\t\treturn undefined;\n\tif (\n\t\t!Array.isArray(value.matches) ||\n\t\tvalue.matches.length > WORKSPACE_FILES_MAX_MATCHES_V1 ||\n\t\ttypeof value.matchesTruncated !== \"boolean\"\n\t)\n\t\treturn undefined;\n\tconst matches = value.matches.map(projectMatch);\n\tif (matches.some((match) => match === undefined)) return undefined;\n\tfor (let count = matches.length; count >= 0; count -= 1) {\n\t\tconst projected: WorkspaceFilesFindResultV1 = {\n\t\t\tversion: 1,\n\t\t\toperationId,\n\t\t\tstatus: \"succeeded\",\n\t\t\tmatches: (matches as WorkspaceFileMatchV1[]).slice(0, count),\n\t\t\tmatchesTruncated: value.matchesTruncated || count < matches.length,\n\t\t};\n\t\tif (boundedResult(projected) && contextSafe(operationId, projected.matches, projected.matchesTruncated))\n\t\t\treturn projected;\n\t}\n\treturn undefined;\n}\n\nfunction boundedResult(value: object): boolean {\n\treturn new TextEncoder().encode(JSON.stringify(value)).byteLength <= WORKSPACE_FILES_MAX_OUTPUT_BYTES_V1;\n}\n\nfunction contextSafe(\n\toperationId: string,\n\titems: readonly object[],\n\ttruncated: boolean,\n\toutputArtifactRef?: string,\n): boolean {\n\treturn (\n\t\tprojectPluginContextV1(\n\t\t\t{\n\t\t\t\tversion: 1,\n\t\t\t\toperationId,\n\t\t\t\titems: items as unknown as JsonValue[],\n\t\t\t\ttruncated,\n\t\t\t\t...(outputArtifactRef === undefined ? {} : { outputArtifactRef }),\n\t\t\t},\n\t\t\t{\n\t\t\t\tmaxOutputBytes: WORKSPACE_FILES_MAX_OUTPUT_BYTES_V1,\n\t\t\t\tmaxInlineItems: WORKSPACE_FILES_MAX_ENTRIES_V1,\n\t\t\t\tmaxCellChars: 4096,\n\t\t\t},\n\t\t).status === \"succeeded\"\n\t);\n}\n\nfunction timeoutMs(value: number | undefined): number {\n\tif (value === undefined) return 30_000;\n\tif (!Number.isSafeInteger(value) || value < 1 || value > 120_000) throw new Error(\"defaultTimeoutMs is invalid\");\n\treturn value;\n}\n\nasync function runHost<T>(\n\tcallback: ((signal: AbortSignal) => Promise<unknown>) | undefined,\n\ttimeout: number,\n\tproject: (value: unknown) => T | undefined,\n\tunsupported: () => T,\n\tsignal: AbortSignal | undefined,\n): Promise<T> {\n\tif (callback === undefined) return unsupported();\n\tif (signal?.aborted) return unsupported();\n\tconst controller = new AbortController();\n\tlet stop: \"timeout\" | \"cancelled\" | undefined;\n\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\tlet removeExternalAbort: (() => void) | undefined;\n\tconst stopPromise = new Promise<{ readonly kind: \"stop\" }>((resolve) => {\n\t\tconst cancel = () => {\n\t\t\tstop ??= \"cancelled\";\n\t\t\tcontroller.abort();\n\t\t\tresolve({ kind: \"stop\" });\n\t\t};\n\t\tif (signal !== undefined) {\n\t\t\tsignal.addEventListener(\"abort\", cancel, { once: true });\n\t\t\tremoveExternalAbort = () => signal.removeEventListener(\"abort\", cancel);\n\t\t}\n\t\ttimer = setTimeout(() => {\n\t\t\tif (stop === undefined) {\n\t\t\t\tstop = \"timeout\";\n\t\t\t\tcontroller.abort();\n\t\t\t\tresolve({ kind: \"stop\" });\n\t\t\t}\n\t\t}, timeout);\n\t});\n\tconst callbackPromise = callback(controller.signal).then(\n\t\t(value) => ({ kind: \"value\" as const, value }),\n\t\t() => ({ kind: \"failed\" as const }),\n\t);\n\ttry {\n\t\tconst outcome = await Promise.race([callbackPromise, stopPromise]);\n\t\tif (outcome.kind !== \"value\" || stop !== undefined) return unsupported();\n\t\treturn project(outcome.value) ?? unsupported();\n\t} catch {\n\t\treturn unsupported();\n\t} finally {\n\t\tif (timer !== undefined) clearTimeout(timer);\n\t\tremoveExternalAbort?.();\n\t}\n}\n\nexport function createNodeWorkspaceFilesAdapterV1(\n\toptions: NodeWorkspaceFilesAdapterOptionsV1 = {},\n): WorkspaceFilesAdapterV1 {\n\tconst timeout = timeoutMs(options.defaultTimeoutMs);\n\tconst listHost = options.list;\n\tconst readHost = options.read;\n\tconst findHost = options.find;\n\treturn {\n\t\tadapterId: WORKSPACE_FILES_HOST_ADAPTER_ID_V1,\n\t\tadapterVersion: WORKSPACE_FILES_HOST_ADAPTER_VERSION_V1,\n\t\tlist: async (request, signal) => {\n\t\t\tconst invalid = validateListRequest(request);\n\t\t\tif (invalid !== undefined) return error(request.operationId, \"failed\", \"invalid_input\", invalid);\n\t\t\treturn runHost(\n\t\t\t\tlistHost === undefined ? undefined : (hostSignal) => listHost(request, hostSignal),\n\t\t\t\ttimeout,\n\t\t\t\t(value) => projectList(value, request.operationId),\n\t\t\t\t() =>\n\t\t\t\t\terror(\n\t\t\t\t\t\trequest.operationId,\n\t\t\t\t\t\t\"unsupported\",\n\t\t\t\t\t\t\"workspace_files_unavailable\",\n\t\t\t\t\t\t\"No workspace file host is bound\",\n\t\t\t\t\t),\n\t\t\t\tsignal,\n\t\t\t);\n\t\t},\n\t\tread: async (request, signal) => {\n\t\t\tconst invalid = validateReadRequest(request);\n\t\t\tif (invalid !== undefined) return readError(request.operationId, \"failed\", \"invalid_input\", invalid);\n\t\t\treturn runHost(\n\t\t\t\treadHost === undefined ? undefined : (hostSignal) => readHost(request, hostSignal),\n\t\t\t\ttimeout,\n\t\t\t\t(value) => projectRead(value, request.operationId),\n\t\t\t\t() =>\n\t\t\t\t\treadError(\n\t\t\t\t\t\trequest.operationId,\n\t\t\t\t\t\t\"unsupported\",\n\t\t\t\t\t\t\"workspace_files_unavailable\",\n\t\t\t\t\t\t\"No workspace file host is bound\",\n\t\t\t\t\t),\n\t\t\t\tsignal,\n\t\t\t);\n\t\t},\n\t\tfind: async (request, signal) => {\n\t\t\tconst invalid = validateFindRequest(request);\n\t\t\tif (invalid !== undefined) return findError(request.operationId, \"failed\", \"invalid_input\", invalid);\n\t\t\treturn runHost(\n\t\t\t\tfindHost === undefined ? undefined : (hostSignal) => findHost(request, hostSignal),\n\t\t\t\ttimeout,\n\t\t\t\t(value) => projectFind(value, request.operationId),\n\t\t\t\t() =>\n\t\t\t\t\tfindError(\n\t\t\t\t\t\trequest.operationId,\n\t\t\t\t\t\t\"unsupported\",\n\t\t\t\t\t\t\"workspace_files_unavailable\",\n\t\t\t\t\t\t\"No workspace file host is bound\",\n\t\t\t\t\t),\n\t\t\t\tsignal,\n\t\t\t);\n\t\t},\n\t};\n}\n\nexport {\n\tcontextSafe,\n\tprojectFind,\n\tprojectList,\n\tprojectRead,\n\tvalidateFindRequest,\n\tvalidateListRequest,\n\tvalidateReadRequest,\n};\n"]}
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import { projectPluginContextV1 } from "@agent-forge/plugin-sdk";
|
|
2
|
+
import { WORKSPACE_FILES_HOST_ADAPTER_ID_V1, WORKSPACE_FILES_HOST_ADAPTER_VERSION_V1, } from "./types.js";
|
|
3
|
+
export const WORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1 = 256;
|
|
4
|
+
export const WORKSPACE_FILES_MAX_OUTPUT_BYTES_V1 = 64 * 1024;
|
|
5
|
+
export const WORKSPACE_FILES_MAX_ENTRIES_V1 = 256;
|
|
6
|
+
export const WORKSPACE_FILES_MAX_MATCHES_V1 = 128;
|
|
7
|
+
export const WORKSPACE_FILES_MAX_PREVIEW_CHARS_V1 = 4096;
|
|
8
|
+
export const WORKSPACE_FILES_MAX_REF_CHARS_V1 = 256;
|
|
9
|
+
export const WORKSPACE_FILES_MAX_NAME_CHARS_V1 = 256;
|
|
10
|
+
export const WORKSPACE_FILES_MAX_QUERY_CHARS_V1 = 512;
|
|
11
|
+
export const WORKSPACE_FILES_MAX_READ_BYTES_V1 = 4 * 1024 * 1024;
|
|
12
|
+
const OPAQUE_REF_V1 = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$/u;
|
|
13
|
+
const SAFE_NAME_V1 = /^[^\u0000\r\n\\/]{1,256}$/u;
|
|
14
|
+
function isRecord(value) {
|
|
15
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
16
|
+
}
|
|
17
|
+
function hasOnlyKeys(value, keys) {
|
|
18
|
+
return Object.keys(value).every((key) => keys.includes(key));
|
|
19
|
+
}
|
|
20
|
+
function safeRef(value) {
|
|
21
|
+
return typeof value === "string" && OPAQUE_REF_V1.test(value);
|
|
22
|
+
}
|
|
23
|
+
function safeArtifactRef(value) {
|
|
24
|
+
return value === undefined || safeRef(value);
|
|
25
|
+
}
|
|
26
|
+
function positiveInteger(value, maximum) {
|
|
27
|
+
return Number.isSafeInteger(value) && value >= 1 && value <= maximum;
|
|
28
|
+
}
|
|
29
|
+
function nonNegativeInteger(value, maximum) {
|
|
30
|
+
return Number.isSafeInteger(value) && value >= 0 && value <= maximum;
|
|
31
|
+
}
|
|
32
|
+
function sanitizeText(value, maximum = WORKSPACE_FILES_MAX_PREVIEW_CHARS_V1) {
|
|
33
|
+
const sanitized = value
|
|
34
|
+
.replace(/((?:api[-_ ]?key|access[-_ ]?token|auth(?:orization)?|bearer|password|passwd|secret|token)\s*[:=]\s*)([^\s,;]+)/giu, "$1[redacted-secret]")
|
|
35
|
+
.replace(/(?:[A-Za-z]:[\\/]|\\\\|\/(?:home|Users|private|tmp|var|workspace)\/)[^\s"'<>]*/gu, "[redacted-path]");
|
|
36
|
+
const characters = [...sanitized];
|
|
37
|
+
return characters.length <= maximum ? sanitized : characters.slice(0, maximum).join("");
|
|
38
|
+
}
|
|
39
|
+
export function sanitizeWorkspaceFilesTextV1(value, maximum = WORKSPACE_FILES_MAX_PREVIEW_CHARS_V1) {
|
|
40
|
+
return sanitizeText(value, maximum);
|
|
41
|
+
}
|
|
42
|
+
function error(operationId, status, code, message) {
|
|
43
|
+
return {
|
|
44
|
+
version: 1,
|
|
45
|
+
operationId,
|
|
46
|
+
status,
|
|
47
|
+
entries: [],
|
|
48
|
+
entriesTruncated: false,
|
|
49
|
+
error: { version: 1, code, message },
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function readError(operationId, status, code, message) {
|
|
53
|
+
return {
|
|
54
|
+
version: 1,
|
|
55
|
+
operationId,
|
|
56
|
+
status,
|
|
57
|
+
contentPreview: "",
|
|
58
|
+
contentBytes: 0,
|
|
59
|
+
contentTruncated: false,
|
|
60
|
+
error: { version: 1, code, message },
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function findError(operationId, status, code, message) {
|
|
64
|
+
return {
|
|
65
|
+
version: 1,
|
|
66
|
+
operationId,
|
|
67
|
+
status,
|
|
68
|
+
matches: [],
|
|
69
|
+
matchesTruncated: false,
|
|
70
|
+
error: { version: 1, code, message },
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function validateListRequest(request) {
|
|
74
|
+
if (request.version !== 1)
|
|
75
|
+
return "version must be 1";
|
|
76
|
+
if (typeof request.operationId !== "string" ||
|
|
77
|
+
request.operationId.trim() === "" ||
|
|
78
|
+
request.operationId.length > WORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1)
|
|
79
|
+
return "operationId is invalid";
|
|
80
|
+
if (!safeRef(request.workspaceRef))
|
|
81
|
+
return "workspaceRef must be an opaque host handle";
|
|
82
|
+
if (request.directoryRef !== undefined && !safeRef(request.directoryRef))
|
|
83
|
+
return "directoryRef must be an opaque host handle";
|
|
84
|
+
if (request.limit !== undefined && !positiveInteger(request.limit, WORKSPACE_FILES_MAX_ENTRIES_V1))
|
|
85
|
+
return "limit is invalid";
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
function validateReadRequest(request) {
|
|
89
|
+
if (request.version !== 1)
|
|
90
|
+
return "version must be 1";
|
|
91
|
+
if (typeof request.operationId !== "string" ||
|
|
92
|
+
request.operationId.trim() === "" ||
|
|
93
|
+
request.operationId.length > WORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1)
|
|
94
|
+
return "operationId is invalid";
|
|
95
|
+
if (!safeRef(request.fileRef))
|
|
96
|
+
return "fileRef must be an opaque host handle";
|
|
97
|
+
if (request.maxBytes !== undefined && !positiveInteger(request.maxBytes, WORKSPACE_FILES_MAX_READ_BYTES_V1))
|
|
98
|
+
return "maxBytes is invalid";
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
function validateFindRequest(request) {
|
|
102
|
+
if (request.version !== 1)
|
|
103
|
+
return "version must be 1";
|
|
104
|
+
if (typeof request.operationId !== "string" ||
|
|
105
|
+
request.operationId.trim() === "" ||
|
|
106
|
+
request.operationId.length > WORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1)
|
|
107
|
+
return "operationId is invalid";
|
|
108
|
+
if (!safeRef(request.workspaceRef))
|
|
109
|
+
return "workspaceRef must be an opaque host handle";
|
|
110
|
+
if (typeof request.query !== "string" ||
|
|
111
|
+
request.query.trim() === "" ||
|
|
112
|
+
request.query.length > WORKSPACE_FILES_MAX_QUERY_CHARS_V1)
|
|
113
|
+
return "query is invalid";
|
|
114
|
+
if (request.limit !== undefined && !positiveInteger(request.limit, WORKSPACE_FILES_MAX_MATCHES_V1))
|
|
115
|
+
return "limit is invalid";
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
function projectEntry(value) {
|
|
119
|
+
if (!isRecord(value) || !hasOnlyKeys(value, ["version", "fileRef", "name", "kind", "sizeBytes"]))
|
|
120
|
+
return undefined;
|
|
121
|
+
if (value.version !== 1 ||
|
|
122
|
+
!safeRef(value.fileRef) ||
|
|
123
|
+
typeof value.name !== "string" ||
|
|
124
|
+
!SAFE_NAME_V1.test(value.name))
|
|
125
|
+
return undefined;
|
|
126
|
+
if (value.kind !== "file" && value.kind !== "directory")
|
|
127
|
+
return undefined;
|
|
128
|
+
if (value.sizeBytes !== undefined && !nonNegativeInteger(value.sizeBytes, WORKSPACE_FILES_MAX_READ_BYTES_V1))
|
|
129
|
+
return undefined;
|
|
130
|
+
return {
|
|
131
|
+
version: 1,
|
|
132
|
+
fileRef: value.fileRef,
|
|
133
|
+
name: sanitizeText(value.name, WORKSPACE_FILES_MAX_NAME_CHARS_V1),
|
|
134
|
+
kind: value.kind,
|
|
135
|
+
...(value.sizeBytes === undefined ? {} : { sizeBytes: value.sizeBytes }),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function projectList(value, operationId) {
|
|
139
|
+
if (!isRecord(value) || value.version !== 1 || value.operationId !== operationId || value.status !== "succeeded")
|
|
140
|
+
return undefined;
|
|
141
|
+
if (!Array.isArray(value.entries) ||
|
|
142
|
+
value.entries.length > WORKSPACE_FILES_MAX_ENTRIES_V1 ||
|
|
143
|
+
typeof value.entriesTruncated !== "boolean")
|
|
144
|
+
return undefined;
|
|
145
|
+
const entries = value.entries.map(projectEntry);
|
|
146
|
+
if (entries.some((entry) => entry === undefined))
|
|
147
|
+
return undefined;
|
|
148
|
+
for (let count = entries.length; count >= 0; count -= 1) {
|
|
149
|
+
const projected = {
|
|
150
|
+
version: 1,
|
|
151
|
+
operationId,
|
|
152
|
+
status: "succeeded",
|
|
153
|
+
entries: entries.slice(0, count),
|
|
154
|
+
entriesTruncated: value.entriesTruncated || count < entries.length,
|
|
155
|
+
};
|
|
156
|
+
if (boundedResult(projected) && contextSafe(operationId, projected.entries, projected.entriesTruncated))
|
|
157
|
+
return projected;
|
|
158
|
+
}
|
|
159
|
+
return undefined;
|
|
160
|
+
}
|
|
161
|
+
function projectRead(value, operationId) {
|
|
162
|
+
if (!isRecord(value) || value.version !== 1 || value.operationId !== operationId || value.status !== "succeeded")
|
|
163
|
+
return undefined;
|
|
164
|
+
if (typeof value.contentPreview !== "string" ||
|
|
165
|
+
value.contentPreview.length > WORKSPACE_FILES_MAX_PREVIEW_CHARS_V1 ||
|
|
166
|
+
!nonNegativeInteger(value.contentBytes, WORKSPACE_FILES_MAX_READ_BYTES_V1) ||
|
|
167
|
+
typeof value.contentTruncated !== "boolean" ||
|
|
168
|
+
!safeArtifactRef(value.artifactRef))
|
|
169
|
+
return undefined;
|
|
170
|
+
const projected = {
|
|
171
|
+
version: 1,
|
|
172
|
+
operationId,
|
|
173
|
+
status: "succeeded",
|
|
174
|
+
contentPreview: sanitizeText(value.contentPreview),
|
|
175
|
+
contentBytes: value.contentBytes,
|
|
176
|
+
contentTruncated: value.contentTruncated,
|
|
177
|
+
...(value.artifactRef === undefined ? {} : { artifactRef: value.artifactRef }),
|
|
178
|
+
};
|
|
179
|
+
return boundedResult(projected) &&
|
|
180
|
+
contextSafe(operationId, [{ contentPreview: projected.contentPreview }], projected.contentTruncated, projected.artifactRef)
|
|
181
|
+
? projected
|
|
182
|
+
: undefined;
|
|
183
|
+
}
|
|
184
|
+
function projectMatch(value) {
|
|
185
|
+
if (!isRecord(value) || !hasOnlyKeys(value, ["fileRef", "line", "column", "preview"]))
|
|
186
|
+
return undefined;
|
|
187
|
+
if (!safeRef(value.fileRef) ||
|
|
188
|
+
!positiveInteger(value.line, 10_000_000) ||
|
|
189
|
+
!positiveInteger(value.column, 10_000_000))
|
|
190
|
+
return undefined;
|
|
191
|
+
if (typeof value.preview !== "string" || value.preview.length > WORKSPACE_FILES_MAX_PREVIEW_CHARS_V1)
|
|
192
|
+
return undefined;
|
|
193
|
+
return { fileRef: value.fileRef, line: value.line, column: value.column, preview: sanitizeText(value.preview) };
|
|
194
|
+
}
|
|
195
|
+
function projectFind(value, operationId) {
|
|
196
|
+
if (!isRecord(value) || value.version !== 1 || value.operationId !== operationId || value.status !== "succeeded")
|
|
197
|
+
return undefined;
|
|
198
|
+
if (!Array.isArray(value.matches) ||
|
|
199
|
+
value.matches.length > WORKSPACE_FILES_MAX_MATCHES_V1 ||
|
|
200
|
+
typeof value.matchesTruncated !== "boolean")
|
|
201
|
+
return undefined;
|
|
202
|
+
const matches = value.matches.map(projectMatch);
|
|
203
|
+
if (matches.some((match) => match === undefined))
|
|
204
|
+
return undefined;
|
|
205
|
+
for (let count = matches.length; count >= 0; count -= 1) {
|
|
206
|
+
const projected = {
|
|
207
|
+
version: 1,
|
|
208
|
+
operationId,
|
|
209
|
+
status: "succeeded",
|
|
210
|
+
matches: matches.slice(0, count),
|
|
211
|
+
matchesTruncated: value.matchesTruncated || count < matches.length,
|
|
212
|
+
};
|
|
213
|
+
if (boundedResult(projected) && contextSafe(operationId, projected.matches, projected.matchesTruncated))
|
|
214
|
+
return projected;
|
|
215
|
+
}
|
|
216
|
+
return undefined;
|
|
217
|
+
}
|
|
218
|
+
function boundedResult(value) {
|
|
219
|
+
return new TextEncoder().encode(JSON.stringify(value)).byteLength <= WORKSPACE_FILES_MAX_OUTPUT_BYTES_V1;
|
|
220
|
+
}
|
|
221
|
+
function contextSafe(operationId, items, truncated, outputArtifactRef) {
|
|
222
|
+
return (projectPluginContextV1({
|
|
223
|
+
version: 1,
|
|
224
|
+
operationId,
|
|
225
|
+
items: items,
|
|
226
|
+
truncated,
|
|
227
|
+
...(outputArtifactRef === undefined ? {} : { outputArtifactRef }),
|
|
228
|
+
}, {
|
|
229
|
+
maxOutputBytes: WORKSPACE_FILES_MAX_OUTPUT_BYTES_V1,
|
|
230
|
+
maxInlineItems: WORKSPACE_FILES_MAX_ENTRIES_V1,
|
|
231
|
+
maxCellChars: 4096,
|
|
232
|
+
}).status === "succeeded");
|
|
233
|
+
}
|
|
234
|
+
function timeoutMs(value) {
|
|
235
|
+
if (value === undefined)
|
|
236
|
+
return 30_000;
|
|
237
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > 120_000)
|
|
238
|
+
throw new Error("defaultTimeoutMs is invalid");
|
|
239
|
+
return value;
|
|
240
|
+
}
|
|
241
|
+
async function runHost(callback, timeout, project, unsupported, signal) {
|
|
242
|
+
if (callback === undefined)
|
|
243
|
+
return unsupported();
|
|
244
|
+
if (signal?.aborted)
|
|
245
|
+
return unsupported();
|
|
246
|
+
const controller = new AbortController();
|
|
247
|
+
let stop;
|
|
248
|
+
let timer;
|
|
249
|
+
let removeExternalAbort;
|
|
250
|
+
const stopPromise = new Promise((resolve) => {
|
|
251
|
+
const cancel = () => {
|
|
252
|
+
stop ??= "cancelled";
|
|
253
|
+
controller.abort();
|
|
254
|
+
resolve({ kind: "stop" });
|
|
255
|
+
};
|
|
256
|
+
if (signal !== undefined) {
|
|
257
|
+
signal.addEventListener("abort", cancel, { once: true });
|
|
258
|
+
removeExternalAbort = () => signal.removeEventListener("abort", cancel);
|
|
259
|
+
}
|
|
260
|
+
timer = setTimeout(() => {
|
|
261
|
+
if (stop === undefined) {
|
|
262
|
+
stop = "timeout";
|
|
263
|
+
controller.abort();
|
|
264
|
+
resolve({ kind: "stop" });
|
|
265
|
+
}
|
|
266
|
+
}, timeout);
|
|
267
|
+
});
|
|
268
|
+
const callbackPromise = callback(controller.signal).then((value) => ({ kind: "value", value }), () => ({ kind: "failed" }));
|
|
269
|
+
try {
|
|
270
|
+
const outcome = await Promise.race([callbackPromise, stopPromise]);
|
|
271
|
+
if (outcome.kind !== "value" || stop !== undefined)
|
|
272
|
+
return unsupported();
|
|
273
|
+
return project(outcome.value) ?? unsupported();
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
return unsupported();
|
|
277
|
+
}
|
|
278
|
+
finally {
|
|
279
|
+
if (timer !== undefined)
|
|
280
|
+
clearTimeout(timer);
|
|
281
|
+
removeExternalAbort?.();
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
export function createNodeWorkspaceFilesAdapterV1(options = {}) {
|
|
285
|
+
const timeout = timeoutMs(options.defaultTimeoutMs);
|
|
286
|
+
const listHost = options.list;
|
|
287
|
+
const readHost = options.read;
|
|
288
|
+
const findHost = options.find;
|
|
289
|
+
return {
|
|
290
|
+
adapterId: WORKSPACE_FILES_HOST_ADAPTER_ID_V1,
|
|
291
|
+
adapterVersion: WORKSPACE_FILES_HOST_ADAPTER_VERSION_V1,
|
|
292
|
+
list: async (request, signal) => {
|
|
293
|
+
const invalid = validateListRequest(request);
|
|
294
|
+
if (invalid !== undefined)
|
|
295
|
+
return error(request.operationId, "failed", "invalid_input", invalid);
|
|
296
|
+
return runHost(listHost === undefined ? undefined : (hostSignal) => listHost(request, hostSignal), timeout, (value) => projectList(value, request.operationId), () => error(request.operationId, "unsupported", "workspace_files_unavailable", "No workspace file host is bound"), signal);
|
|
297
|
+
},
|
|
298
|
+
read: async (request, signal) => {
|
|
299
|
+
const invalid = validateReadRequest(request);
|
|
300
|
+
if (invalid !== undefined)
|
|
301
|
+
return readError(request.operationId, "failed", "invalid_input", invalid);
|
|
302
|
+
return runHost(readHost === undefined ? undefined : (hostSignal) => readHost(request, hostSignal), timeout, (value) => projectRead(value, request.operationId), () => readError(request.operationId, "unsupported", "workspace_files_unavailable", "No workspace file host is bound"), signal);
|
|
303
|
+
},
|
|
304
|
+
find: async (request, signal) => {
|
|
305
|
+
const invalid = validateFindRequest(request);
|
|
306
|
+
if (invalid !== undefined)
|
|
307
|
+
return findError(request.operationId, "failed", "invalid_input", invalid);
|
|
308
|
+
return runHost(findHost === undefined ? undefined : (hostSignal) => findHost(request, hostSignal), timeout, (value) => projectFind(value, request.operationId), () => findError(request.operationId, "unsupported", "workspace_files_unavailable", "No workspace file host is bound"), signal);
|
|
309
|
+
},
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
export { contextSafe, projectFind, projectList, projectRead, validateFindRequest, validateListRequest, validateReadRequest, };
|
|
313
|
+
//# sourceMappingURL=node-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-adapter.js","sourceRoot":"","sources":["../src/node-adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import type { JsonValue } from \"@agent-forge/plugin-sdk\";\nimport { projectPluginContextV1 } from \"@agent-forge/plugin-sdk\";\nimport {\n\ttype NodeWorkspaceFilesAdapterOptionsV1,\n\tWORKSPACE_FILES_HOST_ADAPTER_ID_V1,\n\tWORKSPACE_FILES_HOST_ADAPTER_VERSION_V1,\n\ttype WorkspaceFileEntryV1,\n\ttype WorkspaceFileMatchV1,\n\ttype WorkspaceFilesAdapterV1,\n\ttype WorkspaceFilesFindRequestV1,\n\ttype WorkspaceFilesFindResultV1,\n\ttype WorkspaceFilesListRequestV1,\n\ttype WorkspaceFilesListResultV1,\n\ttype WorkspaceFilesReadRequestV1,\n\ttype WorkspaceFilesReadResultV1,\n} from \"./types.ts\";\n\nexport const WORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1 = 256;\nexport const WORKSPACE_FILES_MAX_OUTPUT_BYTES_V1 = 64 * 1024;\nexport const WORKSPACE_FILES_MAX_ENTRIES_V1 = 256;\nexport const WORKSPACE_FILES_MAX_MATCHES_V1 = 128;\nexport const WORKSPACE_FILES_MAX_PREVIEW_CHARS_V1 = 4096;\nexport const WORKSPACE_FILES_MAX_REF_CHARS_V1 = 256;\nexport const WORKSPACE_FILES_MAX_NAME_CHARS_V1 = 256;\nexport const WORKSPACE_FILES_MAX_QUERY_CHARS_V1 = 512;\nexport const WORKSPACE_FILES_MAX_READ_BYTES_V1 = 4 * 1024 * 1024;\n\nconst OPAQUE_REF_V1 = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$/u;\nconst SAFE_NAME_V1 = /^[^\\u0000\\r\\n\\\\/]{1,256}$/u;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction hasOnlyKeys(value: Record<string, unknown>, keys: readonly string[]): boolean {\n\treturn Object.keys(value).every((key) => keys.includes(key));\n}\n\nfunction safeRef(value: unknown): value is string {\n\treturn typeof value === \"string\" && OPAQUE_REF_V1.test(value);\n}\n\nfunction safeArtifactRef(value: unknown): value is string {\n\treturn value === undefined || safeRef(value);\n}\n\nfunction positiveInteger(value: unknown, maximum: number): value is number {\n\treturn Number.isSafeInteger(value) && (value as number) >= 1 && (value as number) <= maximum;\n}\n\nfunction nonNegativeInteger(value: unknown, maximum: number): value is number {\n\treturn Number.isSafeInteger(value) && (value as number) >= 0 && (value as number) <= maximum;\n}\n\nfunction sanitizeText(value: string, maximum = WORKSPACE_FILES_MAX_PREVIEW_CHARS_V1): string {\n\tconst sanitized = value\n\t\t.replace(\n\t\t\t/((?:api[-_ ]?key|access[-_ ]?token|auth(?:orization)?|bearer|password|passwd|secret|token)\\s*[:=]\\s*)([^\\s,;]+)/giu,\n\t\t\t\"$1[redacted-secret]\",\n\t\t)\n\t\t.replace(/(?:[A-Za-z]:[\\\\/]|\\\\\\\\|\\/(?:home|Users|private|tmp|var|workspace)\\/)[^\\s\"'<>]*/gu, \"[redacted-path]\");\n\tconst characters = [...sanitized];\n\treturn characters.length <= maximum ? sanitized : characters.slice(0, maximum).join(\"\");\n}\n\nexport function sanitizeWorkspaceFilesTextV1(value: string, maximum = WORKSPACE_FILES_MAX_PREVIEW_CHARS_V1): string {\n\treturn sanitizeText(value, maximum);\n}\n\nfunction error(\n\toperationId: string,\n\tstatus: WorkspaceFilesListResultV1[\"status\"],\n\tcode: string,\n\tmessage: string,\n): WorkspaceFilesListResultV1 {\n\treturn {\n\t\tversion: 1 as const,\n\t\toperationId,\n\t\tstatus,\n\t\tentries: [] as readonly WorkspaceFileEntryV1[],\n\t\tentriesTruncated: false,\n\t\terror: { version: 1 as const, code, message },\n\t};\n}\n\nfunction readError(\n\toperationId: string,\n\tstatus: WorkspaceFilesReadResultV1[\"status\"],\n\tcode: string,\n\tmessage: string,\n): WorkspaceFilesReadResultV1 {\n\treturn {\n\t\tversion: 1 as const,\n\t\toperationId,\n\t\tstatus,\n\t\tcontentPreview: \"\",\n\t\tcontentBytes: 0,\n\t\tcontentTruncated: false,\n\t\terror: { version: 1 as const, code, message },\n\t};\n}\n\nfunction findError(\n\toperationId: string,\n\tstatus: WorkspaceFilesFindResultV1[\"status\"],\n\tcode: string,\n\tmessage: string,\n): WorkspaceFilesFindResultV1 {\n\treturn {\n\t\tversion: 1 as const,\n\t\toperationId,\n\t\tstatus,\n\t\tmatches: [] as readonly WorkspaceFileMatchV1[],\n\t\tmatchesTruncated: false,\n\t\terror: { version: 1 as const, code, message },\n\t};\n}\n\nfunction validateListRequest(request: WorkspaceFilesListRequestV1): string | undefined {\n\tif (request.version !== 1) return \"version must be 1\";\n\tif (\n\t\ttypeof request.operationId !== \"string\" ||\n\t\trequest.operationId.trim() === \"\" ||\n\t\trequest.operationId.length > WORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1\n\t)\n\t\treturn \"operationId is invalid\";\n\tif (!safeRef(request.workspaceRef)) return \"workspaceRef must be an opaque host handle\";\n\tif (request.directoryRef !== undefined && !safeRef(request.directoryRef))\n\t\treturn \"directoryRef must be an opaque host handle\";\n\tif (request.limit !== undefined && !positiveInteger(request.limit, WORKSPACE_FILES_MAX_ENTRIES_V1))\n\t\treturn \"limit is invalid\";\n\treturn undefined;\n}\n\nfunction validateReadRequest(request: WorkspaceFilesReadRequestV1): string | undefined {\n\tif (request.version !== 1) return \"version must be 1\";\n\tif (\n\t\ttypeof request.operationId !== \"string\" ||\n\t\trequest.operationId.trim() === \"\" ||\n\t\trequest.operationId.length > WORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1\n\t)\n\t\treturn \"operationId is invalid\";\n\tif (!safeRef(request.fileRef)) return \"fileRef must be an opaque host handle\";\n\tif (request.maxBytes !== undefined && !positiveInteger(request.maxBytes, WORKSPACE_FILES_MAX_READ_BYTES_V1))\n\t\treturn \"maxBytes is invalid\";\n\treturn undefined;\n}\n\nfunction validateFindRequest(request: WorkspaceFilesFindRequestV1): string | undefined {\n\tif (request.version !== 1) return \"version must be 1\";\n\tif (\n\t\ttypeof request.operationId !== \"string\" ||\n\t\trequest.operationId.trim() === \"\" ||\n\t\trequest.operationId.length > WORKSPACE_FILES_MAX_OPERATION_ID_CHARS_V1\n\t)\n\t\treturn \"operationId is invalid\";\n\tif (!safeRef(request.workspaceRef)) return \"workspaceRef must be an opaque host handle\";\n\tif (\n\t\ttypeof request.query !== \"string\" ||\n\t\trequest.query.trim() === \"\" ||\n\t\trequest.query.length > WORKSPACE_FILES_MAX_QUERY_CHARS_V1\n\t)\n\t\treturn \"query is invalid\";\n\tif (request.limit !== undefined && !positiveInteger(request.limit, WORKSPACE_FILES_MAX_MATCHES_V1))\n\t\treturn \"limit is invalid\";\n\treturn undefined;\n}\n\nfunction projectEntry(value: unknown): WorkspaceFileEntryV1 | undefined {\n\tif (!isRecord(value) || !hasOnlyKeys(value, [\"version\", \"fileRef\", \"name\", \"kind\", \"sizeBytes\"])) return undefined;\n\tif (\n\t\tvalue.version !== 1 ||\n\t\t!safeRef(value.fileRef) ||\n\t\ttypeof value.name !== \"string\" ||\n\t\t!SAFE_NAME_V1.test(value.name)\n\t)\n\t\treturn undefined;\n\tif (value.kind !== \"file\" && value.kind !== \"directory\") return undefined;\n\tif (value.sizeBytes !== undefined && !nonNegativeInteger(value.sizeBytes, WORKSPACE_FILES_MAX_READ_BYTES_V1))\n\t\treturn undefined;\n\treturn {\n\t\tversion: 1,\n\t\tfileRef: value.fileRef,\n\t\tname: sanitizeText(value.name, WORKSPACE_FILES_MAX_NAME_CHARS_V1),\n\t\tkind: value.kind,\n\t\t...(value.sizeBytes === undefined ? {} : { sizeBytes: value.sizeBytes }),\n\t};\n}\n\nfunction projectList(value: unknown, operationId: string): WorkspaceFilesListResultV1 | undefined {\n\tif (!isRecord(value) || value.version !== 1 || value.operationId !== operationId || value.status !== \"succeeded\")\n\t\treturn undefined;\n\tif (\n\t\t!Array.isArray(value.entries) ||\n\t\tvalue.entries.length > WORKSPACE_FILES_MAX_ENTRIES_V1 ||\n\t\ttypeof value.entriesTruncated !== \"boolean\"\n\t)\n\t\treturn undefined;\n\tconst entries = value.entries.map(projectEntry);\n\tif (entries.some((entry) => entry === undefined)) return undefined;\n\tfor (let count = entries.length; count >= 0; count -= 1) {\n\t\tconst projected: WorkspaceFilesListResultV1 = {\n\t\t\tversion: 1,\n\t\t\toperationId,\n\t\t\tstatus: \"succeeded\",\n\t\t\tentries: (entries as WorkspaceFileEntryV1[]).slice(0, count),\n\t\t\tentriesTruncated: value.entriesTruncated || count < entries.length,\n\t\t};\n\t\tif (boundedResult(projected) && contextSafe(operationId, projected.entries, projected.entriesTruncated))\n\t\t\treturn projected;\n\t}\n\treturn undefined;\n}\n\nfunction projectRead(value: unknown, operationId: string): WorkspaceFilesReadResultV1 | undefined {\n\tif (!isRecord(value) || value.version !== 1 || value.operationId !== operationId || value.status !== \"succeeded\")\n\t\treturn undefined;\n\tif (\n\t\ttypeof value.contentPreview !== \"string\" ||\n\t\tvalue.contentPreview.length > WORKSPACE_FILES_MAX_PREVIEW_CHARS_V1 ||\n\t\t!nonNegativeInteger(value.contentBytes, WORKSPACE_FILES_MAX_READ_BYTES_V1) ||\n\t\ttypeof value.contentTruncated !== \"boolean\" ||\n\t\t!safeArtifactRef(value.artifactRef)\n\t)\n\t\treturn undefined;\n\tconst projected: WorkspaceFilesReadResultV1 = {\n\t\tversion: 1,\n\t\toperationId,\n\t\tstatus: \"succeeded\",\n\t\tcontentPreview: sanitizeText(value.contentPreview),\n\t\tcontentBytes: value.contentBytes,\n\t\tcontentTruncated: value.contentTruncated,\n\t\t...(value.artifactRef === undefined ? {} : { artifactRef: value.artifactRef }),\n\t};\n\treturn boundedResult(projected) &&\n\t\tcontextSafe(\n\t\t\toperationId,\n\t\t\t[{ contentPreview: projected.contentPreview }],\n\t\t\tprojected.contentTruncated,\n\t\t\tprojected.artifactRef,\n\t\t)\n\t\t? projected\n\t\t: undefined;\n}\n\nfunction projectMatch(value: unknown): WorkspaceFileMatchV1 | undefined {\n\tif (!isRecord(value) || !hasOnlyKeys(value, [\"fileRef\", \"line\", \"column\", \"preview\"])) return undefined;\n\tif (\n\t\t!safeRef(value.fileRef) ||\n\t\t!positiveInteger(value.line, 10_000_000) ||\n\t\t!positiveInteger(value.column, 10_000_000)\n\t)\n\t\treturn undefined;\n\tif (typeof value.preview !== \"string\" || value.preview.length > WORKSPACE_FILES_MAX_PREVIEW_CHARS_V1)\n\t\treturn undefined;\n\treturn { fileRef: value.fileRef, line: value.line, column: value.column, preview: sanitizeText(value.preview) };\n}\n\nfunction projectFind(value: unknown, operationId: string): WorkspaceFilesFindResultV1 | undefined {\n\tif (!isRecord(value) || value.version !== 1 || value.operationId !== operationId || value.status !== \"succeeded\")\n\t\treturn undefined;\n\tif (\n\t\t!Array.isArray(value.matches) ||\n\t\tvalue.matches.length > WORKSPACE_FILES_MAX_MATCHES_V1 ||\n\t\ttypeof value.matchesTruncated !== \"boolean\"\n\t)\n\t\treturn undefined;\n\tconst matches = value.matches.map(projectMatch);\n\tif (matches.some((match) => match === undefined)) return undefined;\n\tfor (let count = matches.length; count >= 0; count -= 1) {\n\t\tconst projected: WorkspaceFilesFindResultV1 = {\n\t\t\tversion: 1,\n\t\t\toperationId,\n\t\t\tstatus: \"succeeded\",\n\t\t\tmatches: (matches as WorkspaceFileMatchV1[]).slice(0, count),\n\t\t\tmatchesTruncated: value.matchesTruncated || count < matches.length,\n\t\t};\n\t\tif (boundedResult(projected) && contextSafe(operationId, projected.matches, projected.matchesTruncated))\n\t\t\treturn projected;\n\t}\n\treturn undefined;\n}\n\nfunction boundedResult(value: object): boolean {\n\treturn new TextEncoder().encode(JSON.stringify(value)).byteLength <= WORKSPACE_FILES_MAX_OUTPUT_BYTES_V1;\n}\n\nfunction contextSafe(\n\toperationId: string,\n\titems: readonly object[],\n\ttruncated: boolean,\n\toutputArtifactRef?: string,\n): boolean {\n\treturn (\n\t\tprojectPluginContextV1(\n\t\t\t{\n\t\t\t\tversion: 1,\n\t\t\t\toperationId,\n\t\t\t\titems: items as unknown as JsonValue[],\n\t\t\t\ttruncated,\n\t\t\t\t...(outputArtifactRef === undefined ? {} : { outputArtifactRef }),\n\t\t\t},\n\t\t\t{\n\t\t\t\tmaxOutputBytes: WORKSPACE_FILES_MAX_OUTPUT_BYTES_V1,\n\t\t\t\tmaxInlineItems: WORKSPACE_FILES_MAX_ENTRIES_V1,\n\t\t\t\tmaxCellChars: 4096,\n\t\t\t},\n\t\t).status === \"succeeded\"\n\t);\n}\n\nfunction timeoutMs(value: number | undefined): number {\n\tif (value === undefined) return 30_000;\n\tif (!Number.isSafeInteger(value) || value < 1 || value > 120_000) throw new Error(\"defaultTimeoutMs is invalid\");\n\treturn value;\n}\n\nasync function runHost<T>(\n\tcallback: ((signal: AbortSignal) => Promise<unknown>) | undefined,\n\ttimeout: number,\n\tproject: (value: unknown) => T | undefined,\n\tunsupported: () => T,\n\tsignal: AbortSignal | undefined,\n): Promise<T> {\n\tif (callback === undefined) return unsupported();\n\tif (signal?.aborted) return unsupported();\n\tconst controller = new AbortController();\n\tlet stop: \"timeout\" | \"cancelled\" | undefined;\n\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\tlet removeExternalAbort: (() => void) | undefined;\n\tconst stopPromise = new Promise<{ readonly kind: \"stop\" }>((resolve) => {\n\t\tconst cancel = () => {\n\t\t\tstop ??= \"cancelled\";\n\t\t\tcontroller.abort();\n\t\t\tresolve({ kind: \"stop\" });\n\t\t};\n\t\tif (signal !== undefined) {\n\t\t\tsignal.addEventListener(\"abort\", cancel, { once: true });\n\t\t\tremoveExternalAbort = () => signal.removeEventListener(\"abort\", cancel);\n\t\t}\n\t\ttimer = setTimeout(() => {\n\t\t\tif (stop === undefined) {\n\t\t\t\tstop = \"timeout\";\n\t\t\t\tcontroller.abort();\n\t\t\t\tresolve({ kind: \"stop\" });\n\t\t\t}\n\t\t}, timeout);\n\t});\n\tconst callbackPromise = callback(controller.signal).then(\n\t\t(value) => ({ kind: \"value\" as const, value }),\n\t\t() => ({ kind: \"failed\" as const }),\n\t);\n\ttry {\n\t\tconst outcome = await Promise.race([callbackPromise, stopPromise]);\n\t\tif (outcome.kind !== \"value\" || stop !== undefined) return unsupported();\n\t\treturn project(outcome.value) ?? unsupported();\n\t} catch {\n\t\treturn unsupported();\n\t} finally {\n\t\tif (timer !== undefined) clearTimeout(timer);\n\t\tremoveExternalAbort?.();\n\t}\n}\n\nexport function createNodeWorkspaceFilesAdapterV1(\n\toptions: NodeWorkspaceFilesAdapterOptionsV1 = {},\n): WorkspaceFilesAdapterV1 {\n\tconst timeout = timeoutMs(options.defaultTimeoutMs);\n\tconst listHost = options.list;\n\tconst readHost = options.read;\n\tconst findHost = options.find;\n\treturn {\n\t\tadapterId: WORKSPACE_FILES_HOST_ADAPTER_ID_V1,\n\t\tadapterVersion: WORKSPACE_FILES_HOST_ADAPTER_VERSION_V1,\n\t\tlist: async (request, signal) => {\n\t\t\tconst invalid = validateListRequest(request);\n\t\t\tif (invalid !== undefined) return error(request.operationId, \"failed\", \"invalid_input\", invalid);\n\t\t\treturn runHost(\n\t\t\t\tlistHost === undefined ? undefined : (hostSignal) => listHost(request, hostSignal),\n\t\t\t\ttimeout,\n\t\t\t\t(value) => projectList(value, request.operationId),\n\t\t\t\t() =>\n\t\t\t\t\terror(\n\t\t\t\t\t\trequest.operationId,\n\t\t\t\t\t\t\"unsupported\",\n\t\t\t\t\t\t\"workspace_files_unavailable\",\n\t\t\t\t\t\t\"No workspace file host is bound\",\n\t\t\t\t\t),\n\t\t\t\tsignal,\n\t\t\t);\n\t\t},\n\t\tread: async (request, signal) => {\n\t\t\tconst invalid = validateReadRequest(request);\n\t\t\tif (invalid !== undefined) return readError(request.operationId, \"failed\", \"invalid_input\", invalid);\n\t\t\treturn runHost(\n\t\t\t\treadHost === undefined ? undefined : (hostSignal) => readHost(request, hostSignal),\n\t\t\t\ttimeout,\n\t\t\t\t(value) => projectRead(value, request.operationId),\n\t\t\t\t() =>\n\t\t\t\t\treadError(\n\t\t\t\t\t\trequest.operationId,\n\t\t\t\t\t\t\"unsupported\",\n\t\t\t\t\t\t\"workspace_files_unavailable\",\n\t\t\t\t\t\t\"No workspace file host is bound\",\n\t\t\t\t\t),\n\t\t\t\tsignal,\n\t\t\t);\n\t\t},\n\t\tfind: async (request, signal) => {\n\t\t\tconst invalid = validateFindRequest(request);\n\t\t\tif (invalid !== undefined) return findError(request.operationId, \"failed\", \"invalid_input\", invalid);\n\t\t\treturn runHost(\n\t\t\t\tfindHost === undefined ? undefined : (hostSignal) => findHost(request, hostSignal),\n\t\t\t\ttimeout,\n\t\t\t\t(value) => projectFind(value, request.operationId),\n\t\t\t\t() =>\n\t\t\t\t\tfindError(\n\t\t\t\t\t\trequest.operationId,\n\t\t\t\t\t\t\"unsupported\",\n\t\t\t\t\t\t\"workspace_files_unavailable\",\n\t\t\t\t\t\t\"No workspace file host is bound\",\n\t\t\t\t\t),\n\t\t\t\tsignal,\n\t\t\t);\n\t\t},\n\t};\n}\n\nexport {\n\tcontextSafe,\n\tprojectFind,\n\tprojectList,\n\tprojectRead,\n\tvalidateFindRequest,\n\tvalidateListRequest,\n\tvalidateReadRequest,\n};\n"]}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { PluginErrorV1, PluginResultStatusV1 } from "@agent-forge/plugin-sdk";
|
|
2
|
+
export declare const WORKSPACE_FILES_PLUGIN_ID_V1: "agent-forge.plugin.workspace-files";
|
|
3
|
+
export declare const WORKSPACE_FILES_CAPABILITY_VERSION_V1: 1;
|
|
4
|
+
export declare const WORKSPACE_FILES_HOST_ADAPTER_ID_V1: "node-workspace-files";
|
|
5
|
+
export declare const WORKSPACE_FILES_HOST_ADAPTER_VERSION_V1: "1.0.0";
|
|
6
|
+
export type WorkspaceFileKindV1 = "file" | "directory";
|
|
7
|
+
export interface WorkspaceFilesListRequestV1 {
|
|
8
|
+
readonly version: 1;
|
|
9
|
+
readonly operationId: string;
|
|
10
|
+
readonly workspaceRef: string;
|
|
11
|
+
readonly directoryRef?: string;
|
|
12
|
+
readonly limit?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface WorkspaceFilesReadRequestV1 {
|
|
15
|
+
readonly version: 1;
|
|
16
|
+
readonly operationId: string;
|
|
17
|
+
readonly fileRef: string;
|
|
18
|
+
readonly maxBytes?: number;
|
|
19
|
+
}
|
|
20
|
+
export interface WorkspaceFilesFindRequestV1 {
|
|
21
|
+
readonly version: 1;
|
|
22
|
+
readonly operationId: string;
|
|
23
|
+
readonly workspaceRef: string;
|
|
24
|
+
readonly query: string;
|
|
25
|
+
readonly limit?: number;
|
|
26
|
+
}
|
|
27
|
+
export interface WorkspaceFileEntryV1 {
|
|
28
|
+
readonly version: 1;
|
|
29
|
+
readonly fileRef: string;
|
|
30
|
+
readonly name: string;
|
|
31
|
+
readonly kind: WorkspaceFileKindV1;
|
|
32
|
+
readonly sizeBytes?: number;
|
|
33
|
+
}
|
|
34
|
+
export interface WorkspaceFileMatchV1 {
|
|
35
|
+
readonly fileRef: string;
|
|
36
|
+
readonly line: number;
|
|
37
|
+
readonly column: number;
|
|
38
|
+
readonly preview: string;
|
|
39
|
+
}
|
|
40
|
+
export interface WorkspaceFilesListResultV1 {
|
|
41
|
+
readonly version: 1;
|
|
42
|
+
readonly operationId: string;
|
|
43
|
+
readonly status: PluginResultStatusV1;
|
|
44
|
+
readonly entries: readonly WorkspaceFileEntryV1[];
|
|
45
|
+
readonly entriesTruncated: boolean;
|
|
46
|
+
readonly error?: PluginErrorV1;
|
|
47
|
+
}
|
|
48
|
+
export interface WorkspaceFilesReadResultV1 {
|
|
49
|
+
readonly version: 1;
|
|
50
|
+
readonly operationId: string;
|
|
51
|
+
readonly status: PluginResultStatusV1;
|
|
52
|
+
readonly contentPreview: string;
|
|
53
|
+
readonly contentBytes: number;
|
|
54
|
+
readonly contentTruncated: boolean;
|
|
55
|
+
readonly artifactRef?: string;
|
|
56
|
+
readonly error?: PluginErrorV1;
|
|
57
|
+
}
|
|
58
|
+
export interface WorkspaceFilesFindResultV1 {
|
|
59
|
+
readonly version: 1;
|
|
60
|
+
readonly operationId: string;
|
|
61
|
+
readonly status: PluginResultStatusV1;
|
|
62
|
+
readonly matches: readonly WorkspaceFileMatchV1[];
|
|
63
|
+
readonly matchesTruncated: boolean;
|
|
64
|
+
readonly error?: PluginErrorV1;
|
|
65
|
+
}
|
|
66
|
+
export interface WorkspaceFilesAdapterV1 {
|
|
67
|
+
readonly adapterId: string;
|
|
68
|
+
readonly adapterVersion: string;
|
|
69
|
+
readonly list: (request: WorkspaceFilesListRequestV1, signal?: AbortSignal) => Promise<WorkspaceFilesListResultV1>;
|
|
70
|
+
readonly read: (request: WorkspaceFilesReadRequestV1, signal?: AbortSignal) => Promise<WorkspaceFilesReadResultV1>;
|
|
71
|
+
readonly find: (request: WorkspaceFilesFindRequestV1, signal?: AbortSignal) => Promise<WorkspaceFilesFindResultV1>;
|
|
72
|
+
}
|
|
73
|
+
export interface NodeWorkspaceFilesAdapterOptionsV1 {
|
|
74
|
+
/** Host-owned resolver; the model never supplies a local path. */
|
|
75
|
+
readonly list?: (request: WorkspaceFilesListRequestV1, signal: AbortSignal) => Promise<unknown>;
|
|
76
|
+
readonly read?: (request: WorkspaceFilesReadRequestV1, signal: AbortSignal) => Promise<unknown>;
|
|
77
|
+
readonly find?: (request: WorkspaceFilesFindRequestV1, signal: AbortSignal) => Promise<unknown>;
|
|
78
|
+
readonly defaultTimeoutMs?: number;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PluginErrorV1, PluginResultStatusV1 } from \"@agent-forge/plugin-sdk\";\n\nexport const WORKSPACE_FILES_PLUGIN_ID_V1 = \"agent-forge.plugin.workspace-files\" as const;\nexport const WORKSPACE_FILES_CAPABILITY_VERSION_V1 = 1 as const;\nexport const WORKSPACE_FILES_HOST_ADAPTER_ID_V1 = \"node-workspace-files\" as const;\nexport const WORKSPACE_FILES_HOST_ADAPTER_VERSION_V1 = \"1.0.0\" as const;\n\nexport type WorkspaceFileKindV1 = \"file\" | \"directory\";\n\nexport interface WorkspaceFilesListRequestV1 {\n\treadonly version: 1;\n\treadonly operationId: string;\n\treadonly workspaceRef: string;\n\treadonly directoryRef?: string;\n\treadonly limit?: number;\n}\n\nexport interface WorkspaceFilesReadRequestV1 {\n\treadonly version: 1;\n\treadonly operationId: string;\n\treadonly fileRef: string;\n\treadonly maxBytes?: number;\n}\n\nexport interface WorkspaceFilesFindRequestV1 {\n\treadonly version: 1;\n\treadonly operationId: string;\n\treadonly workspaceRef: string;\n\treadonly query: string;\n\treadonly limit?: number;\n}\n\nexport interface WorkspaceFileEntryV1 {\n\treadonly version: 1;\n\treadonly fileRef: string;\n\treadonly name: string;\n\treadonly kind: WorkspaceFileKindV1;\n\treadonly sizeBytes?: number;\n}\n\nexport interface WorkspaceFileMatchV1 {\n\treadonly fileRef: string;\n\treadonly line: number;\n\treadonly column: number;\n\treadonly preview: string;\n}\n\nexport interface WorkspaceFilesListResultV1 {\n\treadonly version: 1;\n\treadonly operationId: string;\n\treadonly status: PluginResultStatusV1;\n\treadonly entries: readonly WorkspaceFileEntryV1[];\n\treadonly entriesTruncated: boolean;\n\treadonly error?: PluginErrorV1;\n}\n\nexport interface WorkspaceFilesReadResultV1 {\n\treadonly version: 1;\n\treadonly operationId: string;\n\treadonly status: PluginResultStatusV1;\n\treadonly contentPreview: string;\n\treadonly contentBytes: number;\n\treadonly contentTruncated: boolean;\n\treadonly artifactRef?: string;\n\treadonly error?: PluginErrorV1;\n}\n\nexport interface WorkspaceFilesFindResultV1 {\n\treadonly version: 1;\n\treadonly operationId: string;\n\treadonly status: PluginResultStatusV1;\n\treadonly matches: readonly WorkspaceFileMatchV1[];\n\treadonly matchesTruncated: boolean;\n\treadonly error?: PluginErrorV1;\n}\n\nexport interface WorkspaceFilesAdapterV1 {\n\treadonly adapterId: string;\n\treadonly adapterVersion: string;\n\treadonly list: (request: WorkspaceFilesListRequestV1, signal?: AbortSignal) => Promise<WorkspaceFilesListResultV1>;\n\treadonly read: (request: WorkspaceFilesReadRequestV1, signal?: AbortSignal) => Promise<WorkspaceFilesReadResultV1>;\n\treadonly find: (request: WorkspaceFilesFindRequestV1, signal?: AbortSignal) => Promise<WorkspaceFilesFindResultV1>;\n}\n\nexport interface NodeWorkspaceFilesAdapterOptionsV1 {\n\t/** Host-owned resolver; the model never supplies a local path. */\n\treadonly list?: (request: WorkspaceFilesListRequestV1, signal: AbortSignal) => Promise<unknown>;\n\treadonly read?: (request: WorkspaceFilesReadRequestV1, signal: AbortSignal) => Promise<unknown>;\n\treadonly find?: (request: WorkspaceFilesFindRequestV1, signal: AbortSignal) => Promise<unknown>;\n\treadonly defaultTimeoutMs?: number;\n}\n"]}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export const WORKSPACE_FILES_PLUGIN_ID_V1 = "agent-forge.plugin.workspace-files";
|
|
2
|
+
export const WORKSPACE_FILES_CAPABILITY_VERSION_V1 = 1;
|
|
3
|
+
export const WORKSPACE_FILES_HOST_ADAPTER_ID_V1 = "node-workspace-files";
|
|
4
|
+
export const WORKSPACE_FILES_HOST_ADAPTER_VERSION_V1 = "1.0.0";
|
|
5
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,4BAA4B,GAAG,oCAA6C,CAAC;AAC1F,MAAM,CAAC,MAAM,qCAAqC,GAAG,CAAU,CAAC;AAChE,MAAM,CAAC,MAAM,kCAAkC,GAAG,sBAA+B,CAAC;AAClF,MAAM,CAAC,MAAM,uCAAuC,GAAG,OAAgB,CAAC","sourcesContent":["import type { PluginErrorV1, PluginResultStatusV1 } from \"@agent-forge/plugin-sdk\";\n\nexport const WORKSPACE_FILES_PLUGIN_ID_V1 = \"agent-forge.plugin.workspace-files\" as const;\nexport const WORKSPACE_FILES_CAPABILITY_VERSION_V1 = 1 as const;\nexport const WORKSPACE_FILES_HOST_ADAPTER_ID_V1 = \"node-workspace-files\" as const;\nexport const WORKSPACE_FILES_HOST_ADAPTER_VERSION_V1 = \"1.0.0\" as const;\n\nexport type WorkspaceFileKindV1 = \"file\" | \"directory\";\n\nexport interface WorkspaceFilesListRequestV1 {\n\treadonly version: 1;\n\treadonly operationId: string;\n\treadonly workspaceRef: string;\n\treadonly directoryRef?: string;\n\treadonly limit?: number;\n}\n\nexport interface WorkspaceFilesReadRequestV1 {\n\treadonly version: 1;\n\treadonly operationId: string;\n\treadonly fileRef: string;\n\treadonly maxBytes?: number;\n}\n\nexport interface WorkspaceFilesFindRequestV1 {\n\treadonly version: 1;\n\treadonly operationId: string;\n\treadonly workspaceRef: string;\n\treadonly query: string;\n\treadonly limit?: number;\n}\n\nexport interface WorkspaceFileEntryV1 {\n\treadonly version: 1;\n\treadonly fileRef: string;\n\treadonly name: string;\n\treadonly kind: WorkspaceFileKindV1;\n\treadonly sizeBytes?: number;\n}\n\nexport interface WorkspaceFileMatchV1 {\n\treadonly fileRef: string;\n\treadonly line: number;\n\treadonly column: number;\n\treadonly preview: string;\n}\n\nexport interface WorkspaceFilesListResultV1 {\n\treadonly version: 1;\n\treadonly operationId: string;\n\treadonly status: PluginResultStatusV1;\n\treadonly entries: readonly WorkspaceFileEntryV1[];\n\treadonly entriesTruncated: boolean;\n\treadonly error?: PluginErrorV1;\n}\n\nexport interface WorkspaceFilesReadResultV1 {\n\treadonly version: 1;\n\treadonly operationId: string;\n\treadonly status: PluginResultStatusV1;\n\treadonly contentPreview: string;\n\treadonly contentBytes: number;\n\treadonly contentTruncated: boolean;\n\treadonly artifactRef?: string;\n\treadonly error?: PluginErrorV1;\n}\n\nexport interface WorkspaceFilesFindResultV1 {\n\treadonly version: 1;\n\treadonly operationId: string;\n\treadonly status: PluginResultStatusV1;\n\treadonly matches: readonly WorkspaceFileMatchV1[];\n\treadonly matchesTruncated: boolean;\n\treadonly error?: PluginErrorV1;\n}\n\nexport interface WorkspaceFilesAdapterV1 {\n\treadonly adapterId: string;\n\treadonly adapterVersion: string;\n\treadonly list: (request: WorkspaceFilesListRequestV1, signal?: AbortSignal) => Promise<WorkspaceFilesListResultV1>;\n\treadonly read: (request: WorkspaceFilesReadRequestV1, signal?: AbortSignal) => Promise<WorkspaceFilesReadResultV1>;\n\treadonly find: (request: WorkspaceFilesFindRequestV1, signal?: AbortSignal) => Promise<WorkspaceFilesFindResultV1>;\n}\n\nexport interface NodeWorkspaceFilesAdapterOptionsV1 {\n\t/** Host-owned resolver; the model never supplies a local path. */\n\treadonly list?: (request: WorkspaceFilesListRequestV1, signal: AbortSignal) => Promise<unknown>;\n\treadonly read?: (request: WorkspaceFilesReadRequestV1, signal: AbortSignal) => Promise<unknown>;\n\treadonly find?: (request: WorkspaceFilesFindRequestV1, signal: AbortSignal) => Promise<unknown>;\n\treadonly defaultTimeoutMs?: number;\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ai-agent-forge/plugin-workspace-files",
|
|
3
|
+
"version": "0.85.0",
|
|
4
|
+
"description": "Workspace files capability plugin for Agent Forge (read-only workspace_list/workspace_read/workspace_find tools)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"agent-forge.json",
|
|
17
|
+
"plugin.json",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"clean": "shx rm -rf dist",
|
|
22
|
+
"build": "tsgo -p tsconfig.build.json",
|
|
23
|
+
"test": "vitest --run",
|
|
24
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"agent-forge",
|
|
28
|
+
"plugin",
|
|
29
|
+
"workspace",
|
|
30
|
+
"files"
|
|
31
|
+
],
|
|
32
|
+
"author": "Agent Forge contributors",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "git+https://github.com/agent-forge/agent-forge.git",
|
|
37
|
+
"directory": "plugins/workspace-files"
|
|
38
|
+
},
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/agent-forge/agent-forge/issues"
|
|
41
|
+
},
|
|
42
|
+
"homepage": "https://github.com/agent-forge/agent-forge#readme",
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=22.19.0"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@agent-forge/plugin-sdk": "^0.85.0",
|
|
48
|
+
"typebox": "1.3.27"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@agent-forge/agent-forge": "^0.85.0",
|
|
52
|
+
"shx": "0.4.0",
|
|
53
|
+
"vitest": "4.1.9"
|
|
54
|
+
}
|
|
55
|
+
}
|
package/plugin.json
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "agent-forge.plugin.workspace-files",
|
|
3
|
+
"version": "0.84.4",
|
|
4
|
+
"apiVersion": "1-draft",
|
|
5
|
+
"entry": "./dist/entry.js",
|
|
6
|
+
"hostVersion": ">=0.84.4",
|
|
7
|
+
"requiredCapabilities": ["tools"],
|
|
8
|
+
"provides": [{ "id": "workspace.files", "version": 1, "kind": "contribution" }]
|
|
9
|
+
}
|