dsh-lsp-actions 0.2.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/CHANGELOG.md +79 -0
- package/LICENSE +201 -0
- package/README.es.md +177 -0
- package/README.hi.md +177 -0
- package/README.md +183 -0
- package/README.pt.md +177 -0
- package/README.zh-CN.md +181 -0
- package/cordis.patch.yml +17 -0
- package/lib/abort.d.ts +13 -0
- package/lib/abort.d.ts.map +1 -0
- package/lib/abort.js +31 -0
- package/lib/abort.js.map +1 -0
- package/lib/client.d.ts +173 -0
- package/lib/client.d.ts.map +1 -0
- package/lib/client.js +926 -0
- package/lib/client.js.map +1 -0
- package/lib/connection.d.ts +103 -0
- package/lib/connection.d.ts.map +1 -0
- package/lib/connection.js +241 -0
- package/lib/connection.js.map +1 -0
- package/lib/edits.d.ts +17 -0
- package/lib/edits.d.ts.map +1 -0
- package/lib/edits.js +76 -0
- package/lib/edits.js.map +1 -0
- package/lib/extension.d.ts +9 -0
- package/lib/extension.d.ts.map +1 -0
- package/lib/extension.js +17 -0
- package/lib/extension.js.map +1 -0
- package/lib/extra-tools.d.ts +45 -0
- package/lib/extra-tools.d.ts.map +1 -0
- package/lib/extra-tools.js +406 -0
- package/lib/extra-tools.js.map +1 -0
- package/lib/framing.d.ts +33 -0
- package/lib/framing.d.ts.map +1 -0
- package/lib/framing.js +80 -0
- package/lib/framing.js.map +1 -0
- package/lib/host.d.ts +64 -0
- package/lib/host.d.ts.map +1 -0
- package/lib/host.js +152 -0
- package/lib/host.js.map +1 -0
- package/lib/index.d.ts +42 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +78 -0
- package/lib/index.js.map +1 -0
- package/lib/render.d.ts +364 -0
- package/lib/render.d.ts.map +1 -0
- package/lib/render.js +485 -0
- package/lib/render.js.map +1 -0
- package/lib/runner.d.ts +55 -0
- package/lib/runner.d.ts.map +1 -0
- package/lib/runner.js +149 -0
- package/lib/runner.js.map +1 -0
- package/lib/sandbox.d.ts +69 -0
- package/lib/sandbox.d.ts.map +1 -0
- package/lib/sandbox.js +98 -0
- package/lib/sandbox.js.map +1 -0
- package/lib/seam.d.ts +67 -0
- package/lib/seam.d.ts.map +1 -0
- package/lib/seam.js +62 -0
- package/lib/seam.js.map +1 -0
- package/lib/servers.d.ts +120 -0
- package/lib/servers.d.ts.map +1 -0
- package/lib/servers.js +216 -0
- package/lib/servers.js.map +1 -0
- package/lib/session-cwd.d.ts +15 -0
- package/lib/session-cwd.d.ts.map +1 -0
- package/lib/session-cwd.js +16 -0
- package/lib/session-cwd.js.map +1 -0
- package/lib/tools.d.ts +150 -0
- package/lib/tools.d.ts.map +1 -0
- package/lib/tools.js +543 -0
- package/lib/tools.js.map +1 -0
- package/lib/translate.d.ts +181 -0
- package/lib/translate.d.ts.map +1 -0
- package/lib/translate.js +715 -0
- package/lib/translate.js.map +1 -0
- package/lib/vocabulary.d.ts +167 -0
- package/lib/vocabulary.d.ts.map +1 -0
- package/lib/vocabulary.js +20 -0
- package/lib/vocabulary.js.map +1 -0
- package/package.json +95 -0
package/lib/runner.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The action runner the three tools call: official-seam-first, own-client-fallback. When the
|
|
3
|
+
* extended `ctx.lsp` seam is mounted, actions go through it; when the seam is absent, too old, or
|
|
4
|
+
* has no provider for the file, the plugin's own client serves the call from the `servers` table.
|
|
5
|
+
* A seam provider that exists but lacks the capability fails loud — the user configured the
|
|
6
|
+
* server in one place and gets a real error instead of a silently spawned duplicate.
|
|
7
|
+
* @module dsh-lsp-actions/runner
|
|
8
|
+
*/
|
|
9
|
+
import { finalExtension } from "./extension.js";
|
|
10
|
+
import { firstLanguageId, routeFile } from "./servers.js";
|
|
11
|
+
import { trySeamAction } from "./seam.js";
|
|
12
|
+
import { LspActionError } from "./vocabulary.js";
|
|
13
|
+
/**
|
|
14
|
+
* Create the seam-first action runner. The seam is resolved through `getSeam` on every call, not
|
|
15
|
+
* captured at apply time, so the plugin serves through a seam that loads after it or is re-added
|
|
16
|
+
* later; a seam that is absent at call time falls back to the own client.
|
|
17
|
+
* @param options - the per-call seam resolver, the own client, and the resolved server table.
|
|
18
|
+
* @returns the runner facade.
|
|
19
|
+
*/
|
|
20
|
+
export function createActionRunner(options) {
|
|
21
|
+
return {
|
|
22
|
+
diagnostics: (request, signal) => runOp({ ...options, seam: options.getSeam() }, 'diagnostics', request, signal),
|
|
23
|
+
formatDocument: (request, signal) => runOp({ ...options, seam: options.getSeam() }, 'formatDocument', request, signal),
|
|
24
|
+
completion: (request, signal) => runOp({ ...options, seam: options.getSeam() }, 'completion', request, signal),
|
|
25
|
+
codeActions: (request, signal) => runOp({ ...options, seam: options.getSeam() }, 'codeAction', request, signal),
|
|
26
|
+
workspaceSymbols: (request, signal) => runOp({ ...options, seam: options.getSeam() }, 'workspaceSymbol', request, signal),
|
|
27
|
+
documentSymbols: (request, signal) => runOp({ ...options, seam: options.getSeam() }, 'documentSymbol', request, signal),
|
|
28
|
+
signatureHelp: (request, signal) => runOp({ ...options, seam: options.getSeam() }, 'signatureHelp', request, signal),
|
|
29
|
+
inlayHints: (request, signal) => runOp({ ...options, seam: options.getSeam() }, 'inlayHint', request, signal),
|
|
30
|
+
rename: (request, newName, signal) => renameOp({ ...options, seam: options.getSeam() }, request, newName, signal),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
async function runOp(options, operation, request, signal) {
|
|
34
|
+
if (options.seam !== undefined) {
|
|
35
|
+
const attempt = await trySeamAction(options.seam, operation, request.filePath, request.workspaceRoot, request.position, request.range, signal, extrasFor(operation, request));
|
|
36
|
+
if (attempt.ok)
|
|
37
|
+
return attempt.result;
|
|
38
|
+
if (attempt.reason === 'unsupported') {
|
|
39
|
+
throw new LspActionError(`the mounted ctx.lsp provider does not support ${operation}; configure a server that advertises it`, 'LSP_ACTION_UNSUPPORTED');
|
|
40
|
+
}
|
|
41
|
+
if (attempt.reason === 'error')
|
|
42
|
+
throw attempt.error;
|
|
43
|
+
// absent / legacy / unavailable: the seam cannot serve this action — fall through to the
|
|
44
|
+
// plugin's own client, which fails loud itself when no server entry handles the file.
|
|
45
|
+
}
|
|
46
|
+
// Workspace symbol search has no document to route by: when no entry matches (or no file path
|
|
47
|
+
// was supplied), fall back to the first configured server.
|
|
48
|
+
const route = routeFile(options.servers, request.filePath) ?? firstServerRoute(options.servers, operation);
|
|
49
|
+
if (route === undefined) {
|
|
50
|
+
throw new LspActionError(noRouteMessage(request.filePath), 'LSP_ACTION_UNAVAILABLE');
|
|
51
|
+
}
|
|
52
|
+
if (operation === 'workspaceSymbol') {
|
|
53
|
+
// With a routing file, keep it open for the request: project-based servers (tsls) refuse
|
|
54
|
+
// document-free workspace/symbol.
|
|
55
|
+
if (request.source !== undefined) {
|
|
56
|
+
const actionRequest = {
|
|
57
|
+
filePath: request.filePath,
|
|
58
|
+
workspaceRoot: request.workspaceRoot,
|
|
59
|
+
source: request.source,
|
|
60
|
+
languageId: route.languageId,
|
|
61
|
+
};
|
|
62
|
+
return await options.client.workspaceSymbolsInDocument(route.server, actionRequest, request.query ?? '', signal);
|
|
63
|
+
}
|
|
64
|
+
return await options.client.workspaceSymbols(route.server, request.workspaceRoot, request.query ?? '', signal);
|
|
65
|
+
}
|
|
66
|
+
if (request.source === undefined) {
|
|
67
|
+
throw new LspActionError(`the ${operation} action requires a source document`, 'LSP_ACTION_WORKSPACE_REQUIRED');
|
|
68
|
+
}
|
|
69
|
+
const actionRequest = {
|
|
70
|
+
filePath: request.filePath,
|
|
71
|
+
workspaceRoot: request.workspaceRoot,
|
|
72
|
+
source: request.source,
|
|
73
|
+
languageId: route.languageId,
|
|
74
|
+
...request.position === undefined ? {} : { position: request.position },
|
|
75
|
+
...request.range === undefined ? {} : { range: request.range },
|
|
76
|
+
...request.onlyKinds === undefined ? {} : { onlyKinds: request.onlyKinds },
|
|
77
|
+
};
|
|
78
|
+
switch (operation) {
|
|
79
|
+
case 'diagnostics': return await options.client.diagnostics(route.server, actionRequest, signal);
|
|
80
|
+
case 'formatDocument': return await options.client.formatDocument(route.server, actionRequest, signal);
|
|
81
|
+
case 'completion': return await options.client.completion(route.server, actionRequest, signal);
|
|
82
|
+
case 'codeAction': return await options.client.codeActions(route.server, actionRequest, signal);
|
|
83
|
+
case 'documentSymbol': return await options.client.documentSymbols(route.server, actionRequest, signal);
|
|
84
|
+
case 'signatureHelp': return await options.client.signatureHelp(route.server, actionRequest, signal);
|
|
85
|
+
case 'inlayHint': return await options.client.inlayHints(route.server, actionRequest, signal);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/** The first configured server's route, for workspace-scoped actions without a file to route by. */
|
|
89
|
+
function firstServerRoute(servers, operation) {
|
|
90
|
+
if (operation !== 'workspaceSymbol')
|
|
91
|
+
return undefined;
|
|
92
|
+
const first = servers[0];
|
|
93
|
+
if (first === undefined)
|
|
94
|
+
return undefined;
|
|
95
|
+
return { server: first, languageId: firstLanguageId(first) };
|
|
96
|
+
}
|
|
97
|
+
/** The operation-specific extras one seam query carries (`query` for symbol search, `only` filters). */
|
|
98
|
+
function extrasFor(operation, request) {
|
|
99
|
+
switch (operation) {
|
|
100
|
+
case 'workspaceSymbol': return request.query === undefined ? {} : { query: request.query };
|
|
101
|
+
case 'codeAction': return request.onlyKinds === undefined ? {} : { onlyKinds: request.onlyKinds };
|
|
102
|
+
default: return {};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Serve the rename action: seam first (only a seam that answers with the `rename` result kind
|
|
107
|
+
* serves it — any current seam vintage falls back), then the plugin's own client.
|
|
108
|
+
*/
|
|
109
|
+
async function renameOp(options, request, newName, signal) {
|
|
110
|
+
if (options.seam !== undefined) {
|
|
111
|
+
const attempt = await trySeamAction(options.seam, 'rename', request.filePath, request.workspaceRoot, request.position, request.range, signal, { newName });
|
|
112
|
+
if (attempt.ok) {
|
|
113
|
+
if (attempt.result.kind === 'rename')
|
|
114
|
+
return attempt.result;
|
|
115
|
+
// A seam answered with a different result kind: it cannot serve rename — fall through.
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
if (attempt.reason === 'unsupported') {
|
|
119
|
+
throw new LspActionError('the mounted ctx.lsp provider does not support rename; configure a server that advertises it', 'LSP_ACTION_UNSUPPORTED');
|
|
120
|
+
}
|
|
121
|
+
if (attempt.reason === 'error')
|
|
122
|
+
throw attempt.error;
|
|
123
|
+
// absent / legacy / unavailable: the seam cannot serve rename — fall through to the
|
|
124
|
+
// plugin's own client, which fails loud itself when no entry handles the file.
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const route = routeFile(options.servers, request.filePath);
|
|
128
|
+
if (route === undefined) {
|
|
129
|
+
throw new LspActionError(noRouteMessage(request.filePath), 'LSP_ACTION_UNAVAILABLE');
|
|
130
|
+
}
|
|
131
|
+
if (request.source === undefined) {
|
|
132
|
+
throw new LspActionError('the rename action requires a source document', 'LSP_ACTION_WORKSPACE_REQUIRED');
|
|
133
|
+
}
|
|
134
|
+
const actionRequest = {
|
|
135
|
+
filePath: request.filePath,
|
|
136
|
+
workspaceRoot: request.workspaceRoot,
|
|
137
|
+
source: request.source,
|
|
138
|
+
languageId: route.languageId,
|
|
139
|
+
...request.position === undefined ? {} : { position: request.position },
|
|
140
|
+
};
|
|
141
|
+
return await options.client.rename(route.server, actionRequest, newName, signal);
|
|
142
|
+
}
|
|
143
|
+
/** The fail-loud message when neither the seam nor the servers table handles the file. */
|
|
144
|
+
function noRouteMessage(filePath) {
|
|
145
|
+
const extension = finalExtension(filePath);
|
|
146
|
+
const subject = extension === '' ? 'this file type' : `files with the "${extension}" extension`;
|
|
147
|
+
return `no LSP server is configured for ${subject} — add an entry to the lsp-actions servers table, or register an LSP provider on ctx.lsp`;
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
|
package/lib/sandbox.d.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The sandbox-escalation API for the mutation tools (`lsp_format` / `lsp_rename`): per-call policy
|
|
3
|
+
* resolution, the advertised escalation fields, and denial-marker mapping — delegating the
|
|
4
|
+
* vocabulary and the fail-closed approval sequence to `@deepseek-ai/dsh-sandbox`, exactly as
|
|
5
|
+
* `dsh-tool-fs` does for `write`/`edit`, so formatting and rename escalate identically to the
|
|
6
|
+
* official mutation tools.
|
|
7
|
+
* @module dsh-lsp-actions/sandbox
|
|
8
|
+
*/
|
|
9
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
10
|
+
import type { SandboxExecutionPolicy, SandboxMode } from '@deepseek-ai/dsh-sandbox';
|
|
11
|
+
import type { ToolExecution } from '@deepseek-ai/dsh-tools';
|
|
12
|
+
/** The two escalation arguments a mutation tool may carry (advertised only under a confining backend). */
|
|
13
|
+
export interface FormatEscalationArgs {
|
|
14
|
+
sandbox_permissions?: string;
|
|
15
|
+
justification?: string;
|
|
16
|
+
}
|
|
17
|
+
/** The schema fields for the escalation arguments, spread into the tool's `parameters`. */
|
|
18
|
+
export interface EscalationSchemaFields {
|
|
19
|
+
sandbox_permissions: {
|
|
20
|
+
type: 'string';
|
|
21
|
+
enum: string[];
|
|
22
|
+
description: string;
|
|
23
|
+
};
|
|
24
|
+
justification: {
|
|
25
|
+
type: 'string';
|
|
26
|
+
description: string;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The mutation-escalation API: advertisement gating, per-call policy resolution, the one-approved
|
|
31
|
+
* wider retry, and denial-marker mapping. A pure product of `ctx` at plugin apply time.
|
|
32
|
+
*/
|
|
33
|
+
export declare class FormatSandboxController {
|
|
34
|
+
private readonly ctx;
|
|
35
|
+
/** The escalation targets this composition advertises (`[]` when no confining backend is mounted). */
|
|
36
|
+
readonly escalationModes: readonly SandboxMode[];
|
|
37
|
+
/** Shared per-session policy resolver, required by a confining backend. */
|
|
38
|
+
private readonly policy;
|
|
39
|
+
constructor(ctx: Context);
|
|
40
|
+
/**
|
|
41
|
+
* The escalation schema fields for a mutation tool's `parameters`. Call it only under a confining
|
|
42
|
+
* backend (guard on {@link escalationModes}); the enum pins the closed target vocabulary, the
|
|
43
|
+
* strict-wider check happens per call at execution.
|
|
44
|
+
* @param actionLabel - the action named in the advertised descriptions (`formatting`, `rename`).
|
|
45
|
+
* @returns the two escalation parameter specs.
|
|
46
|
+
*/
|
|
47
|
+
schemaFields(actionLabel: string): EscalationSchemaFields;
|
|
48
|
+
/**
|
|
49
|
+
* The policy to stamp onto this formatting: an approved escalation grant (a strictly wider retry
|
|
50
|
+
* resolved through `ctx.approval` before anything executes), else the session's standing mode.
|
|
51
|
+
* The calling session's cwd is always carried as the workspace root. Validates the escalation
|
|
52
|
+
* argument pairing first.
|
|
53
|
+
* @param toolName - the tool's name, for the approval audit trail.
|
|
54
|
+
* @param args - the call's escalation arguments.
|
|
55
|
+
* @param exec - the tool-execution context (agent, callId, signal).
|
|
56
|
+
* @returns the policy to pass to the write, or undefined for an unsandboxed backend.
|
|
57
|
+
*/
|
|
58
|
+
resolvePolicy(toolName: string, args: FormatEscalationArgs, exec: ToolExecution): Promise<SandboxExecutionPolicy | undefined>;
|
|
59
|
+
/**
|
|
60
|
+
* Map a thrown provider error for the model: a `FS_SANDBOX_DENIED` becomes an `FsError` whose
|
|
61
|
+
* text is the shared `[sandbox: …]` denial marker plus the same-turn escalation hint, so a policy
|
|
62
|
+
* denial reads identically to bash's WHILE keeping the structured `FS_SANDBOX_DENIED` code.
|
|
63
|
+
* @param error - the error thrown by the write.
|
|
64
|
+
* @param policy - the policy stamped onto the call (names the mode in the marker).
|
|
65
|
+
* @returns the error to throw — the marker `FsError` for a sandbox denial, else the original.
|
|
66
|
+
*/
|
|
67
|
+
mapError(error: unknown, policy: SandboxExecutionPolicy | undefined): unknown;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=sandbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,sBAAsB,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAInF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAE3D,0GAA0G;AAC1G,MAAM,WAAW,oBAAoB;IACnC,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,2FAA2F;AAC3F,MAAM,WAAW,sBAAsB;IACrC,mBAAmB,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5E,aAAa,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAA;CACvD;AAED;;;GAGG;AACH,qBAAa,uBAAuB;IAMtB,OAAO,CAAC,QAAQ,CAAC,GAAG;IALhC,sGAAsG;IACtG,QAAQ,CAAC,eAAe,EAAE,SAAS,WAAW,EAAE,CAAA;IAChD,2EAA2E;IAC3E,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;gBAE5B,GAAG,EAAE,OAAO;IASzC;;;;;;OAMG;IACH,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,sBAAsB;IAgBzD;;;;;;;;;OASG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,oBAAoB,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,sBAAsB,GAAG,SAAS,CAAC;IAuBnI;;;;;;;OAOG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,sBAAsB,GAAG,SAAS,GAAG,OAAO;CAO9E"}
|
package/lib/sandbox.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The sandbox-escalation API for the mutation tools (`lsp_format` / `lsp_rename`): per-call policy
|
|
3
|
+
* resolution, the advertised escalation fields, and denial-marker mapping — delegating the
|
|
4
|
+
* vocabulary and the fail-closed approval sequence to `@deepseek-ai/dsh-sandbox`, exactly as
|
|
5
|
+
* `dsh-tool-fs` does for `write`/`edit`, so formatting and rename escalate identically to the
|
|
6
|
+
* official mutation tools.
|
|
7
|
+
* @module dsh-lsp-actions/sandbox
|
|
8
|
+
*/
|
|
9
|
+
import { ESCALATION_TARGETS, approveEscalation, escalationHintMarker, sandboxDenialMarker, validateEscalationArgs } from '@deepseek-ai/dsh-sandbox';
|
|
10
|
+
import { FsError } from '@deepseek-ai/dsh-fs';
|
|
11
|
+
/**
|
|
12
|
+
* The mutation-escalation API: advertisement gating, per-call policy resolution, the one-approved
|
|
13
|
+
* wider retry, and denial-marker mapping. A pure product of `ctx` at plugin apply time.
|
|
14
|
+
*/
|
|
15
|
+
export class FormatSandboxController {
|
|
16
|
+
ctx;
|
|
17
|
+
/** The escalation targets this composition advertises (`[]` when no confining backend is mounted). */
|
|
18
|
+
escalationModes;
|
|
19
|
+
/** Shared per-session policy resolver, required by a confining backend. */
|
|
20
|
+
policy;
|
|
21
|
+
constructor(ctx) {
|
|
22
|
+
this.ctx = ctx;
|
|
23
|
+
const defaultMode = ctx.fs.sandboxMode;
|
|
24
|
+
this.escalationModes = defaultMode === undefined ? [] : ESCALATION_TARGETS;
|
|
25
|
+
this.policy = defaultMode === undefined ? undefined : ctx.get('sandboxPolicy');
|
|
26
|
+
if (defaultMode !== undefined && this.policy === undefined) {
|
|
27
|
+
throw new Error('lsp-actions: the mounted filesystem confines but ctx.sandboxPolicy is missing');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The escalation schema fields for a mutation tool's `parameters`. Call it only under a confining
|
|
32
|
+
* backend (guard on {@link escalationModes}); the enum pins the closed target vocabulary, the
|
|
33
|
+
* strict-wider check happens per call at execution.
|
|
34
|
+
* @param actionLabel - the action named in the advertised descriptions (`formatting`, `rename`).
|
|
35
|
+
* @returns the two escalation parameter specs.
|
|
36
|
+
*/
|
|
37
|
+
schemaFields(actionLabel) {
|
|
38
|
+
return {
|
|
39
|
+
sandbox_permissions: {
|
|
40
|
+
type: 'string',
|
|
41
|
+
enum: [...this.escalationModes],
|
|
42
|
+
description: 'The wider sandbox mode this operation needs. Only valid as a one-shot retry '
|
|
43
|
+
+ 'of an operation the sandbox just denied; requires justification and user approval.',
|
|
44
|
+
},
|
|
45
|
+
justification: {
|
|
46
|
+
type: 'string',
|
|
47
|
+
description: 'Required with sandbox_permissions: one sentence for the user explaining '
|
|
48
|
+
+ `why this exact ${actionLabel} needs the wider access.`,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The policy to stamp onto this formatting: an approved escalation grant (a strictly wider retry
|
|
54
|
+
* resolved through `ctx.approval` before anything executes), else the session's standing mode.
|
|
55
|
+
* The calling session's cwd is always carried as the workspace root. Validates the escalation
|
|
56
|
+
* argument pairing first.
|
|
57
|
+
* @param toolName - the tool's name, for the approval audit trail.
|
|
58
|
+
* @param args - the call's escalation arguments.
|
|
59
|
+
* @param exec - the tool-execution context (agent, callId, signal).
|
|
60
|
+
* @returns the policy to pass to the write, or undefined for an unsandboxed backend.
|
|
61
|
+
*/
|
|
62
|
+
async resolvePolicy(toolName, args, exec) {
|
|
63
|
+
validateEscalationArgs(args.sandbox_permissions, args.justification);
|
|
64
|
+
const standingPolicy = this.policy?.resolve({ ...exec.agent ? { session: exec.agent.session } : {} });
|
|
65
|
+
if (args.sandbox_permissions === undefined || args.justification === undefined) {
|
|
66
|
+
return standingPolicy;
|
|
67
|
+
}
|
|
68
|
+
if (this.escalationModes.length === 0) {
|
|
69
|
+
throw new Error('sandbox_permissions is not available in this composition (no sandboxing filesystem to escalate)');
|
|
70
|
+
}
|
|
71
|
+
const policy = standingPolicy;
|
|
72
|
+
const approvedMode = await approveEscalation({ requestedMode: args.sandbox_permissions, justification: args.justification, effectiveMode: policy.mode, subject: 'operation' }, {
|
|
73
|
+
approver: this.ctx.get('approval'),
|
|
74
|
+
agent: exec.agent,
|
|
75
|
+
callId: exec.callId,
|
|
76
|
+
toolName,
|
|
77
|
+
signal: exec.signal,
|
|
78
|
+
});
|
|
79
|
+
return { ...policy, mode: approvedMode };
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Map a thrown provider error for the model: a `FS_SANDBOX_DENIED` becomes an `FsError` whose
|
|
83
|
+
* text is the shared `[sandbox: …]` denial marker plus the same-turn escalation hint, so a policy
|
|
84
|
+
* denial reads identically to bash's WHILE keeping the structured `FS_SANDBOX_DENIED` code.
|
|
85
|
+
* @param error - the error thrown by the write.
|
|
86
|
+
* @param policy - the policy stamped onto the call (names the mode in the marker).
|
|
87
|
+
* @returns the error to throw — the marker `FsError` for a sandbox denial, else the original.
|
|
88
|
+
*/
|
|
89
|
+
mapError(error, policy) {
|
|
90
|
+
if (!(error instanceof FsError) || error.code !== 'FS_SANDBOX_DENIED')
|
|
91
|
+
return error;
|
|
92
|
+
// A FS_SANDBOX_DENIED only arises under a confining backend, whose tool path always resolves a
|
|
93
|
+
// policy before the write.
|
|
94
|
+
const mode = policy.mode;
|
|
95
|
+
return new FsError(`${sandboxDenialMarker(mode)}\n${escalationHintMarker('operation')}`, 'FS_SANDBOX_DENIED', { cause: error });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=sandbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAA;AAEnJ,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAe7C;;;GAGG;AACH,MAAM,OAAO,uBAAuB;IAML;IAL7B,sGAAsG;IAC7F,eAAe,CAAwB;IAChD,2EAA2E;IAC1D,MAAM,CAAkC;IAEzD,YAA6B,GAAY;QAAZ,QAAG,GAAH,GAAG,CAAS;QACvC,MAAM,WAAW,GAAG,GAAG,CAAC,EAAE,CAAC,WAAW,CAAA;QACtC,IAAI,CAAC,eAAe,GAAG,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAA;QAC1E,IAAI,CAAC,MAAM,GAAG,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;QAC9E,IAAI,WAAW,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC3D,MAAM,IAAI,KAAK,CAAC,+EAA+E,CAAC,CAAA;QAClG,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,YAAY,CAAC,WAAmB;QAC9B,OAAO;YACL,mBAAmB,EAAE;gBACnB,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC;gBAC/B,WAAW,EAAE,8EAA8E;sBACvF,oFAAoF;aACzF;YACD,aAAa,EAAE;gBACb,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,0EAA0E;sBACnF,kBAAkB,WAAW,0BAA0B;aAC5D;SACF,CAAA;IACH,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,aAAa,CAAC,QAAgB,EAAE,IAA0B,EAAE,IAAmB;QACnF,sBAAsB,CAAC,IAAI,CAAC,mBAAmB,EAAE,IAAI,CAAC,aAAa,CAAC,CAAA;QACpE,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;QACrG,IAAI,IAAI,CAAC,mBAAmB,KAAK,SAAS,IAAI,IAAI,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;YAC/E,OAAO,cAAc,CAAA;QACvB,CAAC;QACD,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtC,MAAM,IAAI,KAAK,CAAC,iGAAiG,CAAC,CAAA;QACpH,CAAC;QACD,MAAM,MAAM,GAAG,cAAwC,CAAA;QACvD,MAAM,YAAY,GAAG,MAAM,iBAAiB,CAC1C,EAAE,aAAa,EAAE,IAAI,CAAC,mBAAmB,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,aAAa,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,EAChI;YACE,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC;YAClC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,QAAQ;YACR,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CACF,CAAA;QACD,OAAO,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,CAAA;IAC1C,CAAC;IAED;;;;;;;OAOG;IACH,QAAQ,CAAC,KAAc,EAAE,MAA0C;QACjE,IAAI,CAAC,CAAC,KAAK,YAAY,OAAO,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,mBAAmB;YAAE,OAAO,KAAK,CAAA;QACnF,+FAA+F;QAC/F,2BAA2B;QAC3B,MAAM,IAAI,GAAI,MAAiC,CAAC,IAAI,CAAA;QACpD,OAAO,IAAI,OAAO,CAAC,GAAG,mBAAmB,CAAC,IAAI,CAAC,KAAK,oBAAoB,CAAC,WAAW,CAAC,EAAE,EAAE,mBAAmB,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAA;IACjI,CAAC;CACF"}
|
package/lib/seam.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The official-seam consumer (path one): run each action through the extended `ctx.lsp` seam when
|
|
3
|
+
* it is mounted and serves the operation, and classify failures so the runner can fall back to
|
|
4
|
+
* the plugin's own client only where that is the right call. The seam vocabulary is consumed
|
|
5
|
+
* structurally, never by import, so the plugin keeps working against every seam vintage.
|
|
6
|
+
* @module dsh-lsp-actions/seam
|
|
7
|
+
*/
|
|
8
|
+
import type { LspActionOperation, LspActionResult, LspPosition, LspRange } from './vocabulary.ts';
|
|
9
|
+
/** The structural surface the extended `ctx.lsp` seam exposes (see the upstream PR proposal). */
|
|
10
|
+
export interface SeamService {
|
|
11
|
+
query(request: {
|
|
12
|
+
readonly operation: LspActionOperation;
|
|
13
|
+
readonly filePath: string;
|
|
14
|
+
readonly position?: LspPosition;
|
|
15
|
+
readonly range?: LspRange;
|
|
16
|
+
readonly workspaceRoot: string;
|
|
17
|
+
/** The symbol-name query, for workspace symbol search. */
|
|
18
|
+
readonly query?: string;
|
|
19
|
+
/** CodeActionKind filters, for code actions. */
|
|
20
|
+
readonly onlyKinds?: readonly string[];
|
|
21
|
+
/** The new symbol name, for rename. */
|
|
22
|
+
readonly newName?: string;
|
|
23
|
+
}, signal?: AbortSignal): Promise<LspActionResult>;
|
|
24
|
+
}
|
|
25
|
+
/** Operation-specific extras a seam query may carry (`query`, `onlyKinds`, `newName`). */
|
|
26
|
+
export interface SeamExtras {
|
|
27
|
+
readonly query?: string;
|
|
28
|
+
readonly onlyKinds?: readonly string[];
|
|
29
|
+
readonly newName?: string;
|
|
30
|
+
}
|
|
31
|
+
/** The classification of one seam attempt, deciding whether the runner falls back or fails. */
|
|
32
|
+
export type SeamAttempt = {
|
|
33
|
+
readonly ok: true;
|
|
34
|
+
readonly result: LspActionResult;
|
|
35
|
+
} | {
|
|
36
|
+
readonly ok: false;
|
|
37
|
+
readonly reason: 'absent';
|
|
38
|
+
} | {
|
|
39
|
+
readonly ok: false;
|
|
40
|
+
readonly reason: 'legacy';
|
|
41
|
+
} | {
|
|
42
|
+
readonly ok: false;
|
|
43
|
+
readonly reason: 'unavailable';
|
|
44
|
+
} | {
|
|
45
|
+
readonly ok: false;
|
|
46
|
+
readonly reason: 'unsupported';
|
|
47
|
+
} | {
|
|
48
|
+
readonly ok: false;
|
|
49
|
+
readonly reason: 'error';
|
|
50
|
+
readonly error: unknown;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Run one action through the seam and classify the outcome. Success returns the result; the
|
|
54
|
+
* fallback reasons (`absent`, `legacy`, `unavailable`) let the runner serve the call through the
|
|
55
|
+
* plugin's own client, while `unsupported` and `error` fail loud.
|
|
56
|
+
* @param seam - the mounted `ctx.lsp` service, when present.
|
|
57
|
+
* @param operation - the action to run.
|
|
58
|
+
* @param filePath - the source file.
|
|
59
|
+
* @param workspaceRoot - the workspace root.
|
|
60
|
+
* @param position - the cursor position, for completion, signature help, and rename.
|
|
61
|
+
* @param range - the formatting/code-action/inlay-hint range.
|
|
62
|
+
* @param signal - optional cancellation.
|
|
63
|
+
* @param extras - operation-specific extras (`query`, `onlyKinds`, `newName`) the operation carries.
|
|
64
|
+
* @returns the classified attempt.
|
|
65
|
+
*/
|
|
66
|
+
export declare function trySeamAction(seam: SeamService | undefined, operation: LspActionOperation, filePath: string, workspaceRoot: string, position: LspPosition | undefined, range: LspRange | undefined, signal: AbortSignal | undefined, extras?: SeamExtras): Promise<SeamAttempt>;
|
|
67
|
+
//# sourceMappingURL=seam.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seam.d.ts","sourceRoot":"","sources":["../src/seam.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAEjG,iGAAiG;AACjG,MAAM,WAAW,WAAW;IAC1B,KAAK,CACH,OAAO,EAAE;QACP,QAAQ,CAAC,SAAS,EAAE,kBAAkB,CAAA;QACtC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;QACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,WAAW,CAAA;QAC/B,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAA;QACzB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;QAC9B,0DAA0D;QAC1D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;QACvB,gDAAgD;QAChD,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;QACtC,uCAAuC;QACvC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAC1B,EACD,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,eAAe,CAAC,CAAA;CAC5B;AAED,0FAA0F;AAC1F,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACtC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,+FAA+F;AAC/F,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAA;CAAE,GACvD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAA;CAAE,GACjD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAA;CAAE,GACjD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAA;AAE7E;;;;;;;;;;;;;GAaG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,WAAW,GAAG,SAAS,EAC7B,SAAS,EAAE,kBAAkB,EAC7B,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,WAAW,GAAG,SAAS,EACjC,KAAK,EAAE,QAAQ,GAAG,SAAS,EAC3B,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,MAAM,GAAE,UAAe,GACtB,OAAO,CAAC,WAAW,CAAC,CA0BtB"}
|
package/lib/seam.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The official-seam consumer (path one): run each action through the extended `ctx.lsp` seam when
|
|
3
|
+
* it is mounted and serves the operation, and classify failures so the runner can fall back to
|
|
4
|
+
* the plugin's own client only where that is the right call. The seam vocabulary is consumed
|
|
5
|
+
* structurally, never by import, so the plugin keeps working against every seam vintage.
|
|
6
|
+
* @module dsh-lsp-actions/seam
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Run one action through the seam and classify the outcome. Success returns the result; the
|
|
10
|
+
* fallback reasons (`absent`, `legacy`, `unavailable`) let the runner serve the call through the
|
|
11
|
+
* plugin's own client, while `unsupported` and `error` fail loud.
|
|
12
|
+
* @param seam - the mounted `ctx.lsp` service, when present.
|
|
13
|
+
* @param operation - the action to run.
|
|
14
|
+
* @param filePath - the source file.
|
|
15
|
+
* @param workspaceRoot - the workspace root.
|
|
16
|
+
* @param position - the cursor position, for completion, signature help, and rename.
|
|
17
|
+
* @param range - the formatting/code-action/inlay-hint range.
|
|
18
|
+
* @param signal - optional cancellation.
|
|
19
|
+
* @param extras - operation-specific extras (`query`, `onlyKinds`, `newName`) the operation carries.
|
|
20
|
+
* @returns the classified attempt.
|
|
21
|
+
*/
|
|
22
|
+
export async function trySeamAction(seam, operation, filePath, workspaceRoot, position, range, signal, extras = {}) {
|
|
23
|
+
if (seam === undefined)
|
|
24
|
+
return { ok: false, reason: 'absent' };
|
|
25
|
+
try {
|
|
26
|
+
const result = await seam.query({
|
|
27
|
+
operation,
|
|
28
|
+
filePath,
|
|
29
|
+
workspaceRoot,
|
|
30
|
+
...position === undefined ? {} : { position },
|
|
31
|
+
...range === undefined ? {} : { range },
|
|
32
|
+
...extras.query === undefined ? {} : { query: extras.query },
|
|
33
|
+
...extras.onlyKinds === undefined ? {} : { onlyKinds: extras.onlyKinds },
|
|
34
|
+
...extras.newName === undefined ? {} : { newName: extras.newName },
|
|
35
|
+
}, signal);
|
|
36
|
+
return { ok: true, result };
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
// An abort is the caller's own cancellation (timeout policy), not a seam capability fact:
|
|
40
|
+
// surface the signal's reason, never the seam's unrelated error or a fallback classification.
|
|
41
|
+
if (signal?.aborted)
|
|
42
|
+
throw signal.reason;
|
|
43
|
+
const code = errorCodeOf(error);
|
|
44
|
+
if (code === 'LSP_UNAVAILABLE')
|
|
45
|
+
return { ok: false, reason: 'unavailable' };
|
|
46
|
+
if (code === 'LSP_UNSUPPORTED_OPERATION')
|
|
47
|
+
return { ok: false, reason: 'unsupported' };
|
|
48
|
+
// A code-less failure is the pre-action seam (or its provider) rejecting an unknown operation:
|
|
49
|
+
// it can never serve actions, so the runner falls back to the plugin's own client.
|
|
50
|
+
if (code === undefined)
|
|
51
|
+
return { ok: false, reason: 'legacy' };
|
|
52
|
+
return { ok: false, reason: 'error', error };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/** Extract a stable error code from an unknown thrown value, without instanceof across copies. */
|
|
56
|
+
function errorCodeOf(error) {
|
|
57
|
+
if (error === null || typeof error !== 'object')
|
|
58
|
+
return undefined;
|
|
59
|
+
const code = error.code;
|
|
60
|
+
return typeof code === 'string' ? code : undefined;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=seam.js.map
|
package/lib/seam.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seam.js","sourceRoot":"","sources":["../src/seam.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAwCH;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAA6B,EAC7B,SAA6B,EAC7B,QAAgB,EAChB,aAAqB,EACrB,QAAiC,EACjC,KAA2B,EAC3B,MAA+B,EAC/B,SAAqB,EAAE;IAEvB,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAA;IAC9D,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC;YAC9B,SAAS;YACT,QAAQ;YACR,aAAa;YACb,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE;YAC7C,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE;YACvC,GAAG,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE;YAC5D,GAAG,MAAM,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE;YACxE,GAAG,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE;SACnE,EAAE,MAAM,CAAC,CAAA;QACV,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,0FAA0F;QAC1F,8FAA8F;QAC9F,IAAI,MAAM,EAAE,OAAO;YAAE,MAAM,MAAM,CAAC,MAAM,CAAA;QACxC,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,CAAA;QAC/B,IAAI,IAAI,KAAK,iBAAiB;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,CAAA;QAC3E,IAAI,IAAI,KAAK,2BAA2B;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,CAAA;QACrF,+FAA+F;QAC/F,mFAAmF;QACnF,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAA;QAC9D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAA;IAC9C,CAAC;AACH,CAAC;AAED,kGAAkG;AAClG,SAAS,WAAW,CAAC,KAAc;IACjC,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAA;IACjE,MAAM,IAAI,GAAI,KAA4B,CAAC,IAAI,CAAA;IAC/C,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAA;AACpD,CAAC"}
|
package/lib/servers.d.ts
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server configuration and routing: the `servers` table schema, load-time validation and
|
|
3
|
+
* executable resolution, and the per-file routing that picks one server entry (glob patterns
|
|
4
|
+
* first, then the extension map) plus its language id.
|
|
5
|
+
* @module dsh-lsp-actions/servers
|
|
6
|
+
*/
|
|
7
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
8
|
+
import z from '@deepseek-ai/schemastery';
|
|
9
|
+
/** The default byte cap for any single source document a tool opens for a language server. */
|
|
10
|
+
export declare const DEFAULT_MAX_DOCUMENT_BYTES = 4000000;
|
|
11
|
+
/** One configured local language server and its host bounds. */
|
|
12
|
+
export interface LspServerEntry {
|
|
13
|
+
/** Executable to spawn (absolute, or resolved on PATH at load). */
|
|
14
|
+
command: string;
|
|
15
|
+
/** Lowercase leading-dot extension → LSP language id (e.g. `{ '.ts': 'typescript' }`). */
|
|
16
|
+
extensionToLanguage: Record<string, string>;
|
|
17
|
+
/** Optional path globs (e.g. `src/**\/*.ts`); when a file matches, this entry wins over the extension map. */
|
|
18
|
+
fileGlobs?: string[];
|
|
19
|
+
/** Arguments passed to the executable (no shell). Default `[]`. */
|
|
20
|
+
args?: string[];
|
|
21
|
+
/** Extra env vars merged on top of the scrubbed ambient env. Default `{}`. */
|
|
22
|
+
env?: Record<string, string>;
|
|
23
|
+
/** Static `initialize` options forwarded to the server. Default `null`. */
|
|
24
|
+
initializationOptions?: unknown;
|
|
25
|
+
/** Static answer to every `workspace/configuration` item. Default `null`. */
|
|
26
|
+
configuration?: unknown;
|
|
27
|
+
/** Static `textDocument/formatting` options (`{ tabSize, insertSpaces }`); omitted when null. Default `null`. */
|
|
28
|
+
formattingOptions?: unknown;
|
|
29
|
+
/** Largest single framed message accepted from the server (bytes). Default 16000000. */
|
|
30
|
+
maxMessageBytes?: number;
|
|
31
|
+
/** Largest stderr tail retained for diagnostics (bytes). Default 1000000. */
|
|
32
|
+
maxStderrBytes?: number;
|
|
33
|
+
/** Request-cancel and SIGTERM→SIGKILL grace (ms). Default 2000. */
|
|
34
|
+
killGraceMs?: number;
|
|
35
|
+
/** Graceful `shutdown`/`exit` budget before escalation (ms). Default 5000. */
|
|
36
|
+
shutdownTimeoutMs?: number;
|
|
37
|
+
/** Settle window for push-only diagnostics after `didOpen` (ms). Default 2000. */
|
|
38
|
+
diagnosticsSettleMs?: number;
|
|
39
|
+
/** Quiet period after the last pushed batch before the client returns it (ms). Default 250. */
|
|
40
|
+
diagnosticsDebounceMs?: number;
|
|
41
|
+
/** Idle time before an unused server instance is disposed (ms); 0 keeps it alive. Default 0. */
|
|
42
|
+
idleTimeoutMs?: number;
|
|
43
|
+
}
|
|
44
|
+
/** Plugin configuration: a named table of local language servers plus tool result caps. */
|
|
45
|
+
export interface Config {
|
|
46
|
+
/** Named server entries; empty disables the plugin's own client (the official seam may still serve). */
|
|
47
|
+
servers: Record<string, LspServerEntry>;
|
|
48
|
+
/** Largest number of rendered diagnostics before an omission marker. Default 200. */
|
|
49
|
+
maxDiagnostics?: number;
|
|
50
|
+
/** Largest number of rendered completion items before an omission marker. Default 20. */
|
|
51
|
+
maxCompletionItems?: number;
|
|
52
|
+
/** Largest number of rendered code actions before an omission marker. Default 50. */
|
|
53
|
+
maxCodeActions?: number;
|
|
54
|
+
/** Largest number of rendered symbols before an omission marker. Default 100. */
|
|
55
|
+
maxSymbols?: number;
|
|
56
|
+
/** Largest number of rendered signatures in one signature-help result. Default 10. */
|
|
57
|
+
maxSignatures?: number;
|
|
58
|
+
/** Largest number of rendered inlay hints before an omission marker. Default 200. */
|
|
59
|
+
maxInlayHints?: number;
|
|
60
|
+
/** Largest complete rendered result in characters, including truncation metadata. Default 16000. */
|
|
61
|
+
maxResultChars?: number;
|
|
62
|
+
/** Largest source file a tool will open for a language server (bytes). Default 4000000. */
|
|
63
|
+
maxDocumentBytes?: number;
|
|
64
|
+
/** Tool-call timeout budget in ms, enforced by the official timeout policy. Default 60000. */
|
|
65
|
+
timeoutMs?: number;
|
|
66
|
+
}
|
|
67
|
+
export declare const LspServerEntry: z<LspServerEntry>;
|
|
68
|
+
export declare const Config: z<Config>;
|
|
69
|
+
/** One server entry after schemastery filled every default. */
|
|
70
|
+
export type ResolvedServerEntry = Required<LspServerEntry>;
|
|
71
|
+
/** The plugin config after schemastery filled every default. */
|
|
72
|
+
export type ResolvedConfig = Required<Config>;
|
|
73
|
+
/** One resolved, executable server plus its routing. */
|
|
74
|
+
export interface ResolvedServer {
|
|
75
|
+
/** The entry's stable key in the `servers` table. */
|
|
76
|
+
readonly serverId: string;
|
|
77
|
+
/** The entry with every default filled and validated. */
|
|
78
|
+
readonly entry: ResolvedServerEntry;
|
|
79
|
+
/** The absolute executable resolved at load. */
|
|
80
|
+
readonly executable: string;
|
|
81
|
+
}
|
|
82
|
+
/** The route one file selects: which server and what language id to open it with. */
|
|
83
|
+
export interface ServerRoute {
|
|
84
|
+
readonly server: ResolvedServer;
|
|
85
|
+
readonly languageId: string;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Resolve every server entry's executable at load (fail loud on a missing command or an invalid
|
|
89
|
+
* bound) before any provider publishes. Mirrors the official `lsp-stdio` load contract.
|
|
90
|
+
* @param ctx - the plugin context (uses `ctx.subprocess.resolveExecutable`).
|
|
91
|
+
* @param servers - the schemastery-resolved servers table.
|
|
92
|
+
* @param signal - load cancellation.
|
|
93
|
+
* @returns the resolved servers in config order.
|
|
94
|
+
*/
|
|
95
|
+
export declare function resolveServers(ctx: Context, servers: Record<string, ResolvedServerEntry>, signal?: AbortSignal): Promise<ResolvedServer[]>;
|
|
96
|
+
/**
|
|
97
|
+
* Route one file to a server entry: entries with matching `fileGlobs` first, then entries whose
|
|
98
|
+
* `extensionToLanguage` maps the file's extension, both in config order. A glob route uses the
|
|
99
|
+
* file's own extension mapping when the entry maps it; the entry's first mapping is the fallback
|
|
100
|
+
* only for files whose extension the glob — not the map — selected.
|
|
101
|
+
* @param servers - the resolved servers.
|
|
102
|
+
* @param filePath - the source file path (absolute or workspace-relative).
|
|
103
|
+
* @returns the route, or undefined when no entry handles the file.
|
|
104
|
+
*/
|
|
105
|
+
export declare function routeFile(servers: readonly ResolvedServer[], filePath: string): ServerRoute | undefined;
|
|
106
|
+
/** The first extension mapping's language id, used when a glob route wins without an extension hit. */
|
|
107
|
+
export declare function firstLanguageId(server: ResolvedServer): string;
|
|
108
|
+
/**
|
|
109
|
+
* Compile a path glob (`*`/`**`/`?`) to an anchored regular expression. `*` and `?` do not cross
|
|
110
|
+
* separators; `**` does. Matching runs against `/`-normalized paths.
|
|
111
|
+
* @param pattern - the glob pattern.
|
|
112
|
+
* @returns the compiled, anchored expression.
|
|
113
|
+
* @throws Error when the pattern is empty or contains unbalanced brackets.
|
|
114
|
+
*/
|
|
115
|
+
export declare function globToRegExp(pattern: string): RegExp;
|
|
116
|
+
/** Reject a timer value Node would clamp instead of scheduling as configured. */
|
|
117
|
+
export declare function assertTimer(name: string, value: number): void;
|
|
118
|
+
/** Reject a nonpositive or non-integer config value at load. */
|
|
119
|
+
export declare function assertPositiveInteger(name: string, value: number): void;
|
|
120
|
+
//# sourceMappingURL=servers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"servers.d.ts","sourceRoot":"","sources":["../src/servers.ts"],"names":[],"mappings":"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"}
|