@ordis_co_th/execute-powershell 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +65 -15
- package/dist/tools/execute_powershell.d.ts.map +1 -1
- package/dist/tools/execute_powershell.js +19 -4
- package/dist/tools/execute_powershell.js.map +1 -1
- package/dist/tools/metadata.d.ts +4 -0
- package/dist/tools/metadata.d.ts.map +1 -1
- package/dist/tools/metadata.js +3 -1
- package/dist/tools/metadata.js.map +1 -1
- package/dist/tools/truncation.d.ts +25 -0
- package/dist/tools/truncation.d.ts.map +1 -0
- package/dist/tools/truncation.js +104 -0
- package/dist/tools/truncation.js.map +1 -0
- package/dist/tools/workdir.d.ts +14 -0
- package/dist/tools/workdir.d.ts.map +1 -1
- package/dist/tools/workdir.js +286 -8
- package/dist/tools/workdir.js.map +1 -1
- package/package.json +1 -1
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -2,35 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
An OpenCode plugin that provides PowerShell script execution capabilities with built-in safety controls and permission management.
|
|
4
4
|
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
bun install @ordis_co_th/execute-powershell
|
|
9
|
-
```
|
|
10
|
-
|
|
11
5
|
## Usage
|
|
12
6
|
|
|
13
7
|
### Register in `opencode.json`
|
|
14
8
|
|
|
15
|
-
Add the plugin to your OpenCode configuration:
|
|
9
|
+
Add the plugin to your OpenCode configuration. OpenCode expects the `plugin` key (singular) with a string array:
|
|
16
10
|
|
|
17
11
|
```json
|
|
18
12
|
{
|
|
19
13
|
"plugin": [
|
|
20
|
-
"@ordis_co_th/execute-powershell@1.0.
|
|
14
|
+
"@ordis_co_th/execute-powershell@1.0.4"
|
|
21
15
|
]
|
|
22
16
|
}
|
|
23
17
|
```
|
|
24
18
|
|
|
25
|
-
###
|
|
19
|
+
### Tool
|
|
26
20
|
|
|
27
|
-
Once registered, the plugin provides
|
|
21
|
+
Once registered, the plugin provides one tool: `execute_powershell`.
|
|
28
22
|
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
- **Output Streaming**: Real-time stdout/stderr capture
|
|
23
|
+
- Required params: `command`, `description`
|
|
24
|
+
- Optional params: `timeout_ms`, `workdir`
|
|
25
|
+
- `timeout_ms` default: `120000` (2 minutes)
|
|
26
|
+
- `workdir` default: current OpenCode directory (`context.directory`)
|
|
34
27
|
|
|
35
28
|
### Example Tool Call
|
|
36
29
|
|
|
@@ -45,6 +38,63 @@ Once registered, the plugin provides the `execute_powershell` tool with the foll
|
|
|
45
38
|
}
|
|
46
39
|
```
|
|
47
40
|
|
|
41
|
+
### Permission Integration (`ask` / `allow` / `deny`)
|
|
42
|
+
|
|
43
|
+
This plugin uses OpenCode's native permission engine and asks for permission key `execute_powershell` before spawning any command.
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"permission": {
|
|
48
|
+
"execute_powershell": {
|
|
49
|
+
"*": "ask",
|
|
50
|
+
"Get-Process*": "allow",
|
|
51
|
+
"Get-ChildItem*": "allow",
|
|
52
|
+
"Invoke-Expression*": "deny",
|
|
53
|
+
"Remove-Item*": "deny"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
OpenCode evaluates rules with "last matching rule wins", so put broad defaults first and specific overrides later.
|
|
60
|
+
|
|
61
|
+
### External Directory Permission
|
|
62
|
+
|
|
63
|
+
If `workdir` resolves outside the active project/worktree boundary, the tool asks for OpenCode permission key `external_directory` using a recursive glob pattern. The tool also performs a best-effort scan of path arguments in common filesystem PowerShell commands (for example `Get-Content`, `Set-Content`, `Copy-Item`, `Move-Item`, `Remove-Item`, `Set-Location`) and asks `external_directory` for out-of-bound path targets.
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"permission": {
|
|
68
|
+
"execute_powershell": "ask",
|
|
69
|
+
"external_directory": "ask"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Output Metadata Footer
|
|
75
|
+
|
|
76
|
+
Tool output includes a metadata footer:
|
|
77
|
+
|
|
78
|
+
`<powershell_metadata>{...}</powershell_metadata>`
|
|
79
|
+
|
|
80
|
+
Long output is truncated using OpenCode-compatible defaults (`2000` lines or `50 KiB`), and the full output is written to OpenCode's `tool-output` directory. The returned content includes a preview and the full output path.
|
|
81
|
+
|
|
82
|
+
Metadata fields:
|
|
83
|
+
- `exitCode`
|
|
84
|
+
- `endedBy` (`exit`, `timeout`, or `abort`)
|
|
85
|
+
- `shell` (`pwsh`, `powershell`, or `unknown`)
|
|
86
|
+
- `resolvedWorkdir`
|
|
87
|
+
- `timeoutMs`
|
|
88
|
+
- `durationMs`
|
|
89
|
+
- `truncated` (optional)
|
|
90
|
+
- `outputPath` (optional)
|
|
91
|
+
|
|
92
|
+
### Platform and Security Notes
|
|
93
|
+
|
|
94
|
+
- Intended for Windows PowerShell command execution.
|
|
95
|
+
- Permission checks run before execution.
|
|
96
|
+
- For safer defaults, deny high-risk command patterns such as `Invoke-Expression*` and `Remove-Item*`.
|
|
97
|
+
|
|
48
98
|
## Development
|
|
49
99
|
|
|
50
100
|
```bash
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execute_powershell.d.ts","sourceRoot":"","sources":["../../src/tools/execute_powershell.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AACvF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"execute_powershell.d.ts","sourceRoot":"","sources":["../../src/tools/execute_powershell.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AACvF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAaxB,QAAA,MAAM,UAAU;;;;;CAKN,CAAC;AASX,eAAO,MAAM,kBAAkB,EAAE,cAoF/B,CAAC;AAEH,OAAO,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { tool } from "@opencode-ai/plugin/tool";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { askExecutePowerShellPermission } from "./permissions.js";
|
|
4
|
-
import {
|
|
4
|
+
import { askExternalDirectoriesIfRequired, extractPowerShellCommandDirectories, resolveWorkdir, } from "./workdir.js";
|
|
5
5
|
import { formatMetadataFooter } from "./metadata.js";
|
|
6
6
|
import { resolvePowerShellExecutable } from "./powershell_exe.js";
|
|
7
7
|
import { spawnPowerShell, createTerminationSignal, terminateProcessTree } from "./process.js";
|
|
8
8
|
import { collectCombinedOutput } from "./output.js";
|
|
9
|
+
import { truncateToolOutput } from "./truncation.js";
|
|
9
10
|
const argsSchema = {
|
|
10
11
|
command: z.string(),
|
|
11
12
|
description: z.string(),
|
|
@@ -18,7 +19,11 @@ export const execute_powershell = tool({
|
|
|
18
19
|
async execute(args, context) {
|
|
19
20
|
await askExecutePowerShellPermission(context, args.command);
|
|
20
21
|
const resolvedWorkdir = resolveWorkdir(context.directory, args.workdir);
|
|
21
|
-
|
|
22
|
+
const commandDirectories = extractPowerShellCommandDirectories(args.command, resolvedWorkdir);
|
|
23
|
+
await askExternalDirectoriesIfRequired(context, [
|
|
24
|
+
resolvedWorkdir,
|
|
25
|
+
...commandDirectories,
|
|
26
|
+
]);
|
|
22
27
|
const timeoutMs = args.timeout_ms ?? 120000;
|
|
23
28
|
const { signal, getEndedBy } = createTerminationSignal(context.abort, timeoutMs);
|
|
24
29
|
const startTime = Date.now();
|
|
@@ -46,7 +51,12 @@ export const execute_powershell = tool({
|
|
|
46
51
|
timeoutMs,
|
|
47
52
|
durationMs,
|
|
48
53
|
};
|
|
49
|
-
|
|
54
|
+
const truncated = await truncateToolOutput(output);
|
|
55
|
+
if (truncated.truncated) {
|
|
56
|
+
metadata.truncated = true;
|
|
57
|
+
metadata.outputPath = truncated.outputPath;
|
|
58
|
+
}
|
|
59
|
+
return truncated.content + formatMetadataFooter(metadata);
|
|
50
60
|
}
|
|
51
61
|
catch (error) {
|
|
52
62
|
const durationMs = Date.now() - startTime;
|
|
@@ -61,7 +71,12 @@ export const execute_powershell = tool({
|
|
|
61
71
|
durationMs,
|
|
62
72
|
};
|
|
63
73
|
const errorOutput = error instanceof Error ? error.message : String(error);
|
|
64
|
-
|
|
74
|
+
const truncated = await truncateToolOutput(errorOutput);
|
|
75
|
+
if (truncated.truncated) {
|
|
76
|
+
metadata.truncated = true;
|
|
77
|
+
metadata.outputPath = truncated.outputPath;
|
|
78
|
+
}
|
|
79
|
+
return truncated.content + formatMetadataFooter(metadata);
|
|
65
80
|
}
|
|
66
81
|
finally {
|
|
67
82
|
const endedBy = getEndedBy();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execute_powershell.js","sourceRoot":"","sources":["../../src/tools/execute_powershell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAyC,MAAM,0BAA0B,CAAC;AACvF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,8BAA8B,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,
|
|
1
|
+
{"version":3,"file":"execute_powershell.js","sourceRoot":"","sources":["../../src/tools/execute_powershell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAyC,MAAM,0BAA0B,CAAC;AACvF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,8BAA8B,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EACL,gCAAgC,EAChC,mCAAmC,EACnC,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,oBAAoB,EAA2B,MAAM,eAAe,CAAC;AAC9E,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAC9F,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,UAAU,GAAG;IACjB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IACnD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACtB,CAAC;AASX,MAAM,CAAC,MAAM,kBAAkB,GAAmB,IAAI,CAAC;IACrD,WAAW,EAAE,wCAAwC;IACrD,IAAI,EAAE,UAAiB;IACvB,KAAK,CAAC,OAAO,CAAC,IAAc,EAAE,OAAoB;QAChD,MAAM,8BAA8B,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAC5D,MAAM,eAAe,GAAG,cAAc,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACxE,MAAM,kBAAkB,GAAG,mCAAmC,CAC5D,IAAI,CAAC,OAAO,EACZ,eAAe,CAChB,CAAC;QACF,MAAM,gCAAgC,CAAC,OAAO,EAAE;YAC9C,eAAe;YACf,GAAG,kBAAkB;SACtB,CAAC,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC;QAC5C,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,uBAAuB,CACpD,OAAO,CAAC,KAAK,EACb,SAAS,CACV,CAAC;QACF,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,IAAI,KAAK,GAAG,SAAS,CAAC;QACtB,IAAI,IAAoD,CAAC;QAEzD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,2BAA2B,EAAE,CAAC;YAC1C,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC;YAEjB,IAAI,GAAG,eAAe,CAAC;gBACrB,OAAO,EAAE,GAAG,CAAC,IAAI;gBACjB,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,GAAG,EAAE,eAAe;gBACpB,MAAM;aACP,CAAC,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC;YACjD,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC;YAC7B,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAC1C,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;YAE7B,MAAM,QAAQ,GAAuB;gBACnC,QAAQ;gBACR,OAAO;gBACP,KAAK;gBACL,eAAe;gBACf,SAAS;gBACT,UAAU;aACX,CAAC;YAEF,MAAM,SAAS,GAAG,MAAM,kBAAkB,CAAC,MAAM,CAAC,CAAC;YACnD,IAAI,SAAS,CAAC,SAAS,EAAE,CAAC;gBACxB,QAAQ,CAAC,SAAS,GAAG,IAAI,CAAC;gBAC1B,QAAQ,CAAC,UAAU,GAAG,SAAS,CAAC,UAAU,CAAC;YAC7C,CAAC;YAED,OAAO,SAAS,CAAC,OAAO,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;QAC5D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAC1C,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;YAC7B,QAAQ,GAAG,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAE1C,MAAM,QAAQ,GAAuB;gBACnC,QAAQ;gBACR,OAAO;gBACP,KAAK;gBACL,eAAe;gBACf,SAAS;gBACT,UAAU;aACX,CAAC;YAEF,MAAM,WAAW,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC3E,MAAM,SAAS,GAAG,MAAM,kBAAkB,CAAC,WAAW,CAAC,CAAC;YACxD,IAAI,SAAS,CAAC,SAAS,EAAE,CAAC;gBACxB,QAAQ,CAAC,SAAS,GAAG,IAAI,CAAC;gBAC1B,QAAQ,CAAC,UAAU,GAAG,SAAS,CAAC,UAAU,CAAC;YAC7C,CAAC;YAED,OAAO,SAAS,CAAC,OAAO,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;QAC5D,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;YAC7B,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,OAAO,CAAC,IAAI,IAAI,EAAE,GAAG,EAAE,CAAC;gBAChE,MAAM,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;IACH,CAAC;CACF,CAAC,CAAC;AAEH,OAAO,EAAE,UAAU,EAAE,CAAC"}
|
package/dist/tools/metadata.d.ts
CHANGED
|
@@ -21,6 +21,10 @@ export interface PowerShellMetadata {
|
|
|
21
21
|
timeoutMs: number;
|
|
22
22
|
/** Duration of execution in milliseconds */
|
|
23
23
|
durationMs: number;
|
|
24
|
+
/** Whether output was truncated due to size limits */
|
|
25
|
+
truncated?: boolean;
|
|
26
|
+
/** Path to full output file when output is truncated */
|
|
27
|
+
outputPath?: string;
|
|
24
28
|
}
|
|
25
29
|
/**
|
|
26
30
|
* Format metadata as a tagged JSON footer.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/tools/metadata.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;IACtC,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,eAAe,EAAE,MAAM,CAAC;IACxB,8BAA8B;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,UAAU,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/tools/metadata.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;IACtC,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,eAAe,EAAE,MAAM,CAAC;IACxB,8BAA8B;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAErE;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CA0B3E"}
|
package/dist/tools/metadata.js
CHANGED
|
@@ -40,7 +40,9 @@ export function parseMetadataFooter(text) {
|
|
|
40
40
|
typeof parsed.shell !== "string" ||
|
|
41
41
|
typeof parsed.resolvedWorkdir !== "string" ||
|
|
42
42
|
typeof parsed.timeoutMs !== "number" ||
|
|
43
|
-
typeof parsed.durationMs !== "number"
|
|
43
|
+
typeof parsed.durationMs !== "number" ||
|
|
44
|
+
(parsed.truncated !== undefined && typeof parsed.truncated !== "boolean") ||
|
|
45
|
+
(parsed.outputPath !== undefined && typeof parsed.outputPath !== "string")) {
|
|
44
46
|
return null;
|
|
45
47
|
}
|
|
46
48
|
return parsed;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/tools/metadata.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/tools/metadata.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAwBH;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAwB;IAC3D,OAAO,wBAAwB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,wBAAwB,CAAC;AAC9E,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,qEAAqE;IACrE,0DAA0D;IAC1D,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,qDAAqD,CAAC,CAAC,CAAC;IAC1F,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtC,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC9C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QACxC,+BAA+B;QAC/B,IACE,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ;YACnC,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC;YACtD,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ;YAChC,OAAO,MAAM,CAAC,eAAe,KAAK,QAAQ;YAC1C,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ;YACpC,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ;YACrC,CAAC,MAAM,CAAC,SAAS,KAAK,SAAS,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,SAAS,CAAC;YACzE,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,CAAC,EAC1E,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,MAA4B,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export declare const MAX_LINES = 2000;
|
|
2
|
+
export declare const MAX_BYTES: number;
|
|
3
|
+
export interface TruncateOptions {
|
|
4
|
+
maxLines?: number;
|
|
5
|
+
maxBytes?: number;
|
|
6
|
+
direction?: "head" | "tail";
|
|
7
|
+
}
|
|
8
|
+
export type TruncateResult = {
|
|
9
|
+
content: string;
|
|
10
|
+
truncated: false;
|
|
11
|
+
} | {
|
|
12
|
+
content: string;
|
|
13
|
+
truncated: true;
|
|
14
|
+
outputPath: string;
|
|
15
|
+
};
|
|
16
|
+
interface DataDirRuntime {
|
|
17
|
+
env?: NodeJS.ProcessEnv;
|
|
18
|
+
platform?: NodeJS.Platform;
|
|
19
|
+
homeDir?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function resolveOpenCodeDataDir(runtime?: DataDirRuntime): string;
|
|
22
|
+
export declare function resolveToolOutputDir(): string;
|
|
23
|
+
export declare function truncateToolOutput(text: string, options?: TruncateOptions): Promise<TruncateResult>;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=truncation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"truncation.d.ts","sourceRoot":"","sources":["../../src/tools/truncation.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,SAAS,OAAO,CAAC;AAC9B,eAAO,MAAM,SAAS,QAAY,CAAC;AAGnC,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC7B;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,KAAK,CAAA;CAAE,GACrC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7D,UAAU,cAAc;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,cAAmB,GAAG,MAAM,CAwB3E;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,cAAc,CAAC,CAwDzB"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { mkdir, readdir, stat, unlink, writeFile, } from "node:fs/promises";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
export const MAX_LINES = 2000;
|
|
6
|
+
export const MAX_BYTES = 50 * 1024;
|
|
7
|
+
const RETENTION_MS = 7 * 24 * 60 * 60 * 1000;
|
|
8
|
+
export function resolveOpenCodeDataDir(runtime = {}) {
|
|
9
|
+
const env = runtime.env ?? process.env;
|
|
10
|
+
const platform = runtime.platform ?? process.platform;
|
|
11
|
+
const homeDir = runtime.homeDir ?? os.homedir();
|
|
12
|
+
const pathApi = platform === "win32" ? path.win32 : path.posix;
|
|
13
|
+
const override = env.OPENCODE_PLUGIN_DATA_DIR;
|
|
14
|
+
if (override)
|
|
15
|
+
return override;
|
|
16
|
+
if (env.XDG_DATA_HOME) {
|
|
17
|
+
return pathApi.join(env.XDG_DATA_HOME, "opencode");
|
|
18
|
+
}
|
|
19
|
+
if (platform === "darwin") {
|
|
20
|
+
return pathApi.join(homeDir, "Library", "Application Support", "opencode");
|
|
21
|
+
}
|
|
22
|
+
if (platform === "win32") {
|
|
23
|
+
const localAppData = env.LOCALAPPDATA ?? pathApi.join(homeDir, "AppData", "Local");
|
|
24
|
+
return pathApi.join(localAppData, "opencode");
|
|
25
|
+
}
|
|
26
|
+
return pathApi.join(homeDir, ".local", "share", "opencode");
|
|
27
|
+
}
|
|
28
|
+
export function resolveToolOutputDir() {
|
|
29
|
+
return path.join(resolveOpenCodeDataDir(), "tool-output");
|
|
30
|
+
}
|
|
31
|
+
export async function truncateToolOutput(text, options = {}) {
|
|
32
|
+
const maxLines = options.maxLines ?? MAX_LINES;
|
|
33
|
+
const maxBytes = options.maxBytes ?? MAX_BYTES;
|
|
34
|
+
const direction = options.direction ?? "head";
|
|
35
|
+
const lines = text.split("\n");
|
|
36
|
+
const totalBytes = Buffer.byteLength(text, "utf-8");
|
|
37
|
+
if (lines.length <= maxLines && totalBytes <= maxBytes) {
|
|
38
|
+
return { content: text, truncated: false };
|
|
39
|
+
}
|
|
40
|
+
const out = [];
|
|
41
|
+
let bytes = 0;
|
|
42
|
+
let hitBytes = false;
|
|
43
|
+
if (direction === "head") {
|
|
44
|
+
for (let i = 0; i < lines.length && i < maxLines; i++) {
|
|
45
|
+
const size = Buffer.byteLength(lines[i], "utf-8") + (i > 0 ? 1 : 0);
|
|
46
|
+
if (bytes + size > maxBytes) {
|
|
47
|
+
hitBytes = true;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
out.push(lines[i]);
|
|
51
|
+
bytes += size;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
for (let i = lines.length - 1; i >= 0 && out.length < maxLines; i--) {
|
|
56
|
+
const size = Buffer.byteLength(lines[i], "utf-8") + (out.length > 0 ? 1 : 0);
|
|
57
|
+
if (bytes + size > maxBytes) {
|
|
58
|
+
hitBytes = true;
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
out.unshift(lines[i]);
|
|
62
|
+
bytes += size;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const removed = hitBytes ? totalBytes - bytes : lines.length - out.length;
|
|
66
|
+
const unit = hitBytes ? "bytes" : "lines";
|
|
67
|
+
const preview = out.join("\n");
|
|
68
|
+
const outputPath = await writeFullOutput(text);
|
|
69
|
+
const hint = `The tool call succeeded but the output was truncated. Full output saved to: ${outputPath}\n` +
|
|
70
|
+
"Use Grep to search the full content or Read with offset/limit to view specific sections.";
|
|
71
|
+
const message = direction === "head"
|
|
72
|
+
? `${preview}\n\n...${removed} ${unit} truncated...\n\n${hint}`
|
|
73
|
+
: `...${removed} ${unit} truncated...\n\n${hint}\n\n${preview}`;
|
|
74
|
+
return {
|
|
75
|
+
content: message,
|
|
76
|
+
truncated: true,
|
|
77
|
+
outputPath,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
async function writeFullOutput(text) {
|
|
81
|
+
const dir = resolveToolOutputDir();
|
|
82
|
+
await mkdir(dir, { recursive: true });
|
|
83
|
+
const filename = `tool_${Date.now()}_${randomUUID().replace(/-/g, "").slice(0, 12)}`;
|
|
84
|
+
const outputPath = path.join(dir, filename);
|
|
85
|
+
await writeFile(outputPath, text, "utf-8");
|
|
86
|
+
void cleanupOldToolOutputFiles(dir);
|
|
87
|
+
return outputPath;
|
|
88
|
+
}
|
|
89
|
+
async function cleanupOldToolOutputFiles(dir) {
|
|
90
|
+
const cutoff = Date.now() - RETENTION_MS;
|
|
91
|
+
const entries = await readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
92
|
+
for (const entry of entries) {
|
|
93
|
+
if (!entry.isFile())
|
|
94
|
+
continue;
|
|
95
|
+
const filepath = path.join(dir, entry.name);
|
|
96
|
+
const fileStat = await stat(filepath).catch(() => null);
|
|
97
|
+
if (!fileStat)
|
|
98
|
+
continue;
|
|
99
|
+
if (fileStat.mtimeMs < cutoff) {
|
|
100
|
+
await unlink(filepath).catch(() => { });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=truncation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"truncation.js","sourceRoot":"","sources":["../../src/tools/truncation.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/workdir.d.ts
CHANGED
|
@@ -12,6 +12,20 @@ import type { ToolContext } from "@opencode-ai/plugin/tool";
|
|
|
12
12
|
* @param resolvedWorkdir - The absolute, normalized workdir path
|
|
13
13
|
*/
|
|
14
14
|
export declare function askExternalDirectoryIfRequired(context: ToolContext, resolvedWorkdir: string): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Ask external_directory permission for one or more resolved directories/paths.
|
|
17
|
+
*
|
|
18
|
+
* All paths are normalized and deduplicated before permission check.
|
|
19
|
+
* Only paths outside project/worktree boundary trigger a permission prompt.
|
|
20
|
+
*/
|
|
21
|
+
export declare function askExternalDirectoriesIfRequired(context: ToolContext, resolvedPaths: string[]): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Extract path-like directory targets from PowerShell command text.
|
|
24
|
+
*
|
|
25
|
+
* This mirrors OpenCode's bash behavior: best-effort extraction for path-aware
|
|
26
|
+
* commands so external_directory can be enforced for command arguments, not just workdir.
|
|
27
|
+
*/
|
|
28
|
+
export declare function extractPowerShellCommandDirectories(command: string, cwd: string): string[];
|
|
15
29
|
/**
|
|
16
30
|
* Resolves a workdir argument to an absolute path.
|
|
17
31
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workdir.d.ts","sourceRoot":"","sources":["../../src/tools/workdir.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"workdir.d.ts","sourceRoot":"","sources":["../../src/tools/workdir.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AA4D5D;;;;;;;;;;;GAWG;AACH,wBAAsB,8BAA8B,CAClD,OAAO,EAAE,WAAW,EACpB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,CAEf;AAED;;;;;GAKG;AACH,wBAAsB,gCAAgC,CACpD,OAAO,EAAE,WAAW,EACpB,aAAa,EAAE,MAAM,EAAE,GACtB,OAAO,CAAC,IAAI,CAAC,CAuBf;AAED;;;;;GAKG;AACH,wBAAgB,mCAAmC,CACjD,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,GACV,MAAM,EAAE,CAuDV;AA2KD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,gBAAgB,EAAE,MAAM,EACxB,UAAU,CAAC,EAAE,MAAM,GAClB,MAAM,CAMR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EAAE,GACrB,OAAO,CAsBT;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,EAAE,CAMhE"}
|
package/dist/tools/workdir.js
CHANGED
|
@@ -1,4 +1,59 @@
|
|
|
1
1
|
import path from "path";
|
|
2
|
+
import { statSync } from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
const PATH_AWARE_COMMANDS = new Set([
|
|
5
|
+
"cd",
|
|
6
|
+
"chdir",
|
|
7
|
+
"set-location",
|
|
8
|
+
"sl",
|
|
9
|
+
"push-location",
|
|
10
|
+
"pushd",
|
|
11
|
+
"remove-item",
|
|
12
|
+
"ri",
|
|
13
|
+
"rm",
|
|
14
|
+
"del",
|
|
15
|
+
"erase",
|
|
16
|
+
"copy-item",
|
|
17
|
+
"copy",
|
|
18
|
+
"cp",
|
|
19
|
+
"cpi",
|
|
20
|
+
"move-item",
|
|
21
|
+
"move",
|
|
22
|
+
"mv",
|
|
23
|
+
"mi",
|
|
24
|
+
"new-item",
|
|
25
|
+
"ni",
|
|
26
|
+
"mkdir",
|
|
27
|
+
"md",
|
|
28
|
+
"get-content",
|
|
29
|
+
"gc",
|
|
30
|
+
"cat",
|
|
31
|
+
"type",
|
|
32
|
+
"set-content",
|
|
33
|
+
"sc",
|
|
34
|
+
"add-content",
|
|
35
|
+
"ac",
|
|
36
|
+
"out-file",
|
|
37
|
+
"get-childitem",
|
|
38
|
+
"gci",
|
|
39
|
+
"ls",
|
|
40
|
+
"dir",
|
|
41
|
+
]);
|
|
42
|
+
const PATH_VALUE_PARAMS = new Set([
|
|
43
|
+
"path",
|
|
44
|
+
"literalpath",
|
|
45
|
+
"destination",
|
|
46
|
+
"source",
|
|
47
|
+
"filepath",
|
|
48
|
+
"outfilepath",
|
|
49
|
+
]);
|
|
50
|
+
const NO_VALUE_SWITCHES = new Set([
|
|
51
|
+
"recurse",
|
|
52
|
+
"force",
|
|
53
|
+
"name",
|
|
54
|
+
"file",
|
|
55
|
+
"directory",
|
|
56
|
+
]);
|
|
2
57
|
/**
|
|
3
58
|
* Asks for external_directory permission if the resolved workdir is outside the allowed boundary.
|
|
4
59
|
*
|
|
@@ -12,21 +67,244 @@ import path from "path";
|
|
|
12
67
|
* @param resolvedWorkdir - The absolute, normalized workdir path
|
|
13
68
|
*/
|
|
14
69
|
export async function askExternalDirectoryIfRequired(context, resolvedWorkdir) {
|
|
70
|
+
await askExternalDirectoriesIfRequired(context, [resolvedWorkdir]);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Ask external_directory permission for one or more resolved directories/paths.
|
|
74
|
+
*
|
|
75
|
+
* All paths are normalized and deduplicated before permission check.
|
|
76
|
+
* Only paths outside project/worktree boundary trigger a permission prompt.
|
|
77
|
+
*/
|
|
78
|
+
export async function askExternalDirectoriesIfRequired(context, resolvedPaths) {
|
|
15
79
|
const allowedRoots = buildAllowedRoots(context);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
80
|
+
const externalDirs = new Set();
|
|
81
|
+
for (const p of resolvedPaths) {
|
|
82
|
+
const normalized = path.normalize(p);
|
|
83
|
+
if (!isWithinBoundary(normalized, allowedRoots)) {
|
|
84
|
+
externalDirs.add(normalized);
|
|
85
|
+
}
|
|
19
86
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
87
|
+
if (externalDirs.size === 0)
|
|
88
|
+
return;
|
|
89
|
+
const globPatterns = Array.from(externalDirs).map((dir) => dir.replace(/\\/g, "/") + "/**");
|
|
23
90
|
await context.ask({
|
|
24
91
|
permission: "external_directory",
|
|
25
|
-
patterns:
|
|
26
|
-
always:
|
|
92
|
+
patterns: globPatterns,
|
|
93
|
+
always: globPatterns,
|
|
27
94
|
metadata: {},
|
|
28
95
|
});
|
|
29
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Extract path-like directory targets from PowerShell command text.
|
|
99
|
+
*
|
|
100
|
+
* This mirrors OpenCode's bash behavior: best-effort extraction for path-aware
|
|
101
|
+
* commands so external_directory can be enforced for command arguments, not just workdir.
|
|
102
|
+
*/
|
|
103
|
+
export function extractPowerShellCommandDirectories(command, cwd) {
|
|
104
|
+
const tokens = tokenizePowerShell(command);
|
|
105
|
+
const segments = splitCommandSegments(tokens);
|
|
106
|
+
const result = new Set();
|
|
107
|
+
for (const segment of segments) {
|
|
108
|
+
const commandInfo = parseSegment(segment);
|
|
109
|
+
if (!commandInfo)
|
|
110
|
+
continue;
|
|
111
|
+
const { commandName, args } = commandInfo;
|
|
112
|
+
if (!PATH_AWARE_COMMANDS.has(commandName))
|
|
113
|
+
continue;
|
|
114
|
+
let expectation = "none";
|
|
115
|
+
for (const arg of args) {
|
|
116
|
+
const stripped = stripOuterQuotes(arg);
|
|
117
|
+
if (!stripped)
|
|
118
|
+
continue;
|
|
119
|
+
if (expectation === "path") {
|
|
120
|
+
const resolved = resolvePathLike(cwd, stripped);
|
|
121
|
+
if (resolved)
|
|
122
|
+
result.add(resolveDirectoryTarget(resolved));
|
|
123
|
+
expectation = "none";
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (expectation === "skip") {
|
|
127
|
+
expectation = "none";
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (stripped.startsWith("-")) {
|
|
131
|
+
const inlinePath = parseInlinePathParameter(stripped);
|
|
132
|
+
if (inlinePath) {
|
|
133
|
+
const resolved = resolvePathLike(cwd, inlinePath);
|
|
134
|
+
if (resolved)
|
|
135
|
+
result.add(resolveDirectoryTarget(resolved));
|
|
136
|
+
expectation = "none";
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
const param = stripped.replace(/^-+/, "").toLowerCase();
|
|
140
|
+
if (PATH_VALUE_PARAMS.has(param)) {
|
|
141
|
+
expectation = "path";
|
|
142
|
+
}
|
|
143
|
+
else if (NO_VALUE_SWITCHES.has(param) || param.includes(":")) {
|
|
144
|
+
expectation = "none";
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
expectation = "skip";
|
|
148
|
+
}
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
const resolved = resolvePathLike(cwd, stripped);
|
|
152
|
+
if (resolved)
|
|
153
|
+
result.add(resolveDirectoryTarget(resolved));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return Array.from(result);
|
|
157
|
+
}
|
|
158
|
+
function tokenizePowerShell(command) {
|
|
159
|
+
const tokens = [];
|
|
160
|
+
let current = "";
|
|
161
|
+
let quote = null;
|
|
162
|
+
for (let i = 0; i < command.length; i++) {
|
|
163
|
+
const char = command[i];
|
|
164
|
+
if (quote) {
|
|
165
|
+
current += char;
|
|
166
|
+
if (char === quote) {
|
|
167
|
+
if (quote === "'" && command[i + 1] === "'") {
|
|
168
|
+
current += command[++i];
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
if (quote === '"' && command[i - 1] === "`") {
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
quote = null;
|
|
175
|
+
}
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
if (char === "'" || char === '"') {
|
|
179
|
+
quote = char;
|
|
180
|
+
current += char;
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
if (/\s/.test(char)) {
|
|
184
|
+
if (current) {
|
|
185
|
+
tokens.push(current);
|
|
186
|
+
current = "";
|
|
187
|
+
}
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
if (char === "|" || char === ";") {
|
|
191
|
+
if (current) {
|
|
192
|
+
tokens.push(current);
|
|
193
|
+
current = "";
|
|
194
|
+
}
|
|
195
|
+
tokens.push(char);
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
current += char;
|
|
199
|
+
}
|
|
200
|
+
if (current)
|
|
201
|
+
tokens.push(current);
|
|
202
|
+
return tokens;
|
|
203
|
+
}
|
|
204
|
+
function splitCommandSegments(tokens) {
|
|
205
|
+
const segments = [];
|
|
206
|
+
let current = [];
|
|
207
|
+
for (const token of tokens) {
|
|
208
|
+
if (token === "|" || token === ";") {
|
|
209
|
+
if (current.length > 0)
|
|
210
|
+
segments.push(current);
|
|
211
|
+
current = [];
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
current.push(token);
|
|
215
|
+
}
|
|
216
|
+
if (current.length > 0)
|
|
217
|
+
segments.push(current);
|
|
218
|
+
return segments;
|
|
219
|
+
}
|
|
220
|
+
function parseSegment(segment) {
|
|
221
|
+
const working = [...segment];
|
|
222
|
+
while (working.length > 0 && (working[0] === "&" || working[0] === ".")) {
|
|
223
|
+
working.shift();
|
|
224
|
+
}
|
|
225
|
+
if (working.length === 0)
|
|
226
|
+
return null;
|
|
227
|
+
const commandName = stripOuterQuotes(working[0]).toLowerCase();
|
|
228
|
+
if (!commandName)
|
|
229
|
+
return null;
|
|
230
|
+
return {
|
|
231
|
+
commandName,
|
|
232
|
+
args: working.slice(1),
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
function stripOuterQuotes(value) {
|
|
236
|
+
const trimmed = value.trim();
|
|
237
|
+
if (trimmed.length >= 2) {
|
|
238
|
+
if (trimmed.startsWith("\"") && trimmed.endsWith("\"")) {
|
|
239
|
+
return trimmed.slice(1, -1);
|
|
240
|
+
}
|
|
241
|
+
if (trimmed.startsWith("'") && trimmed.endsWith("'")) {
|
|
242
|
+
return trimmed.slice(1, -1);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return trimmed;
|
|
246
|
+
}
|
|
247
|
+
function parseInlinePathParameter(token) {
|
|
248
|
+
const normalized = token.replace(/^-+/, "");
|
|
249
|
+
const separatorIndex = normalized.indexOf(":");
|
|
250
|
+
if (separatorIndex <= 0)
|
|
251
|
+
return null;
|
|
252
|
+
const paramName = normalized.slice(0, separatorIndex).toLowerCase();
|
|
253
|
+
const value = normalized.slice(separatorIndex + 1);
|
|
254
|
+
if (!PATH_VALUE_PARAMS.has(paramName))
|
|
255
|
+
return null;
|
|
256
|
+
const stripped = stripOuterQuotes(value);
|
|
257
|
+
return stripped.length > 0 ? stripped : null;
|
|
258
|
+
}
|
|
259
|
+
function resolvePathLike(cwd, value) {
|
|
260
|
+
if (!value)
|
|
261
|
+
return null;
|
|
262
|
+
if (value.startsWith("http://") || value.startsWith("https://"))
|
|
263
|
+
return null;
|
|
264
|
+
if (value === "~") {
|
|
265
|
+
return os.homedir();
|
|
266
|
+
}
|
|
267
|
+
if (value.startsWith("~/") || value.startsWith("~\\")) {
|
|
268
|
+
return path.resolve(os.homedir(), value.slice(2));
|
|
269
|
+
}
|
|
270
|
+
if (/^\$home$/i.test(value)) {
|
|
271
|
+
return os.homedir();
|
|
272
|
+
}
|
|
273
|
+
if (/^\$home[\\/]/i.test(value)) {
|
|
274
|
+
return path.resolve(os.homedir(), value.slice(6));
|
|
275
|
+
}
|
|
276
|
+
if (value.startsWith("$"))
|
|
277
|
+
return null;
|
|
278
|
+
// Skip PowerShell provider paths like HKLM:\, Env:\ etc.
|
|
279
|
+
if (/^[A-Za-z]{2,}:[\\/]/.test(value))
|
|
280
|
+
return null;
|
|
281
|
+
if (isAbsolutePathLike(value)) {
|
|
282
|
+
return path.normalize(value);
|
|
283
|
+
}
|
|
284
|
+
return path.resolve(cwd, value);
|
|
285
|
+
}
|
|
286
|
+
function isAbsolutePathLike(value) {
|
|
287
|
+
return (path.isAbsolute(value) ||
|
|
288
|
+
/^[A-Za-z]:[\\/]/.test(value) ||
|
|
289
|
+
value.startsWith("\\\\"));
|
|
290
|
+
}
|
|
291
|
+
function resolveDirectoryTarget(resolvedPath) {
|
|
292
|
+
try {
|
|
293
|
+
const stats = statSync(resolvedPath);
|
|
294
|
+
if (stats.isDirectory())
|
|
295
|
+
return path.normalize(resolvedPath);
|
|
296
|
+
return path.dirname(resolvedPath);
|
|
297
|
+
}
|
|
298
|
+
catch {
|
|
299
|
+
// Fall back to heuristic for non-existent paths.
|
|
300
|
+
}
|
|
301
|
+
if (resolvedPath.endsWith(path.sep))
|
|
302
|
+
return path.normalize(resolvedPath);
|
|
303
|
+
if (path.extname(path.basename(resolvedPath))) {
|
|
304
|
+
return path.dirname(resolvedPath);
|
|
305
|
+
}
|
|
306
|
+
return path.normalize(resolvedPath);
|
|
307
|
+
}
|
|
30
308
|
/**
|
|
31
309
|
* Resolves a workdir argument to an absolute path.
|
|
32
310
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workdir.js","sourceRoot":"","sources":["../../src/tools/workdir.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"workdir.js","sourceRoot":"","sources":["../../src/tools/workdir.ts"],"names":[],"mappings":"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"}
|