@te-river/opencode-team-mode 1.5.4 → 1.5.6
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 +732 -634
- package/README.zh-CN.md +655 -576
- package/dist/agents.d.ts +6 -1
- package/dist/agents.d.ts.map +1 -1
- package/dist/agents.js +103 -522
- package/dist/agents.js.map +1 -1
- package/dist/approval-gate.d.ts +16 -0
- package/dist/approval-gate.d.ts.map +1 -1
- package/dist/approval-gate.js +8 -1
- package/dist/approval-gate.js.map +1 -1
- package/dist/blackboard.d.ts.map +1 -1
- package/dist/blackboard.js +3 -2
- package/dist/blackboard.js.map +1 -1
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +7 -6
- package/dist/commands.js.map +1 -1
- package/dist/envprotect/bash-classify.d.ts +42 -0
- package/dist/envprotect/bash-classify.d.ts.map +1 -0
- package/dist/envprotect/bash-classify.js +221 -0
- package/dist/envprotect/bash-classify.js.map +1 -0
- package/dist/envprotect/gate-predicates.d.ts +57 -0
- package/dist/envprotect/gate-predicates.d.ts.map +1 -0
- package/dist/envprotect/gate-predicates.js +174 -0
- package/dist/envprotect/gate-predicates.js.map +1 -0
- package/dist/envprotect/hook.d.ts +45 -0
- package/dist/envprotect/hook.d.ts.map +1 -0
- package/dist/envprotect/hook.js +158 -0
- package/dist/envprotect/hook.js.map +1 -0
- package/dist/envprotect/path-classify.d.ts +16 -0
- package/dist/envprotect/path-classify.d.ts.map +1 -0
- package/dist/envprotect/path-classify.js +72 -0
- package/dist/envprotect/path-classify.js.map +1 -0
- package/dist/envprotect/patterns.d.ts +77 -0
- package/dist/envprotect/patterns.d.ts.map +1 -0
- package/dist/envprotect/patterns.js +182 -0
- package/dist/envprotect/patterns.js.map +1 -0
- package/dist/envprotect.d.ts +19 -217
- package/dist/envprotect.d.ts.map +1 -1
- package/dist/envprotect.js +18 -803
- package/dist/envprotect.js.map +1 -1
- package/dist/fs-safe.d.ts +16 -0
- package/dist/fs-safe.d.ts.map +1 -0
- package/dist/fs-safe.js +56 -0
- package/dist/fs-safe.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -6
- package/dist/index.js.map +1 -1
- package/dist/prompts/lead.d.ts +7 -0
- package/dist/prompts/lead.d.ts.map +1 -0
- package/dist/prompts/lead.js +230 -0
- package/dist/prompts/lead.js.map +1 -0
- package/dist/prompts/shared.d.ts +8 -0
- package/dist/prompts/shared.d.ts.map +1 -0
- package/dist/prompts/shared.js +118 -0
- package/dist/prompts/shared.js.map +1 -0
- package/dist/prompts/specialists.d.ts +12 -0
- package/dist/prompts/specialists.d.ts.map +1 -0
- package/dist/prompts/specialists.js +218 -0
- package/dist/prompts/specialists.js.map +1 -0
- package/dist/shell-text.d.ts +14 -0
- package/dist/shell-text.d.ts.map +1 -0
- package/dist/shell-text.js +16 -0
- package/dist/shell-text.js.map +1 -0
- package/dist/tm/args-schema.d.ts +36 -0
- package/dist/tm/args-schema.d.ts.map +1 -0
- package/dist/tm/args-schema.js +191 -0
- package/dist/tm/args-schema.js.map +1 -0
- package/dist/tm/browser.d.ts +52 -0
- package/dist/tm/browser.d.ts.map +1 -0
- package/dist/tm/browser.js +361 -0
- package/dist/tm/browser.js.map +1 -0
- package/dist/tm/client-unwrap.d.ts +38 -0
- package/dist/tm/client-unwrap.d.ts.map +1 -0
- package/dist/tm/client-unwrap.js +113 -0
- package/dist/tm/client-unwrap.js.map +1 -0
- package/dist/tm/config.d.ts +46 -18
- package/dist/tm/config.d.ts.map +1 -1
- package/dist/tm/config.js +60 -17
- package/dist/tm/config.js.map +1 -1
- package/dist/tm/guard.d.ts.map +1 -1
- package/dist/tm/guard.js +4 -7
- package/dist/tm/guard.js.map +1 -1
- package/dist/tm/index.d.ts +15 -5
- package/dist/tm/index.d.ts.map +1 -1
- package/dist/tm/index.js +95 -19
- package/dist/tm/index.js.map +1 -1
- package/dist/tm/memory.d.ts +82 -0
- package/dist/tm/memory.d.ts.map +1 -0
- package/dist/tm/memory.js +350 -0
- package/dist/tm/memory.js.map +1 -0
- package/dist/tm/pipelines.d.ts +58 -0
- package/dist/tm/pipelines.d.ts.map +1 -0
- package/dist/tm/pipelines.js +301 -0
- package/dist/tm/pipelines.js.map +1 -0
- package/dist/tm/preview.d.ts +6 -1
- package/dist/tm/preview.d.ts.map +1 -1
- package/dist/tm/preview.js +31 -8
- package/dist/tm/preview.js.map +1 -1
- package/dist/tm/ptc/budgets.d.ts +38 -0
- package/dist/tm/ptc/budgets.d.ts.map +1 -0
- package/dist/tm/ptc/budgets.js +59 -0
- package/dist/tm/ptc/budgets.js.map +1 -0
- package/dist/tm/ptc/contract.d.ts +131 -0
- package/dist/tm/ptc/contract.d.ts.map +1 -0
- package/dist/tm/ptc/contract.js +47 -0
- package/dist/tm/ptc/contract.js.map +1 -0
- package/dist/tm/ptc/driver.d.ts +37 -0
- package/dist/tm/ptc/driver.d.ts.map +1 -0
- package/dist/tm/ptc/driver.js +181 -0
- package/dist/tm/ptc/driver.js.map +1 -0
- package/dist/tm/ptc/engines.d.ts +32 -0
- package/dist/tm/ptc/engines.d.ts.map +1 -0
- package/dist/tm/ptc/engines.js +201 -0
- package/dist/tm/ptc/engines.js.map +1 -0
- package/dist/tm/ptc/gate.d.ts +28 -0
- package/dist/tm/ptc/gate.d.ts.map +1 -0
- package/dist/tm/ptc/gate.js +127 -0
- package/dist/tm/ptc/gate.js.map +1 -0
- package/dist/tm/ptc/index.d.ts +19 -0
- package/dist/tm/ptc/index.d.ts.map +1 -0
- package/dist/tm/ptc/index.js +15 -0
- package/dist/tm/ptc/index.js.map +1 -0
- package/dist/tm/ptc/pscan.d.ts +11 -0
- package/dist/tm/ptc/pscan.d.ts.map +1 -0
- package/dist/tm/ptc/pscan.js +27 -0
- package/dist/tm/ptc/pscan.js.map +1 -0
- package/dist/tm/ptc/summary.d.ts +17 -0
- package/dist/tm/ptc/summary.d.ts.map +1 -0
- package/dist/tm/ptc/summary.js +107 -0
- package/dist/tm/ptc/summary.js.map +1 -0
- package/dist/tm/ptc/tool.d.ts +35 -0
- package/dist/tm/ptc/tool.d.ts.map +1 -0
- package/dist/tm/ptc/tool.js +135 -0
- package/dist/tm/ptc/tool.js.map +1 -0
- package/dist/tm/ptc.d.ts +45 -26
- package/dist/tm/ptc.d.ts.map +1 -1
- package/dist/tm/ptc.js +71 -45
- package/dist/tm/ptc.js.map +1 -1
- package/dist/tm/result.d.ts +34 -0
- package/dist/tm/result.d.ts.map +1 -0
- package/dist/tm/result.js +87 -0
- package/dist/tm/result.js.map +1 -0
- package/dist/tm/shell-bridge.d.ts +22 -0
- package/dist/tm/shell-bridge.d.ts.map +1 -0
- package/dist/tm/shell-bridge.js +70 -0
- package/dist/tm/shell-bridge.js.map +1 -0
- package/dist/tm/store.d.ts.map +1 -1
- package/dist/tm/store.js +2 -1
- package/dist/tm/store.js.map +1 -1
- package/dist/tm/tools.d.ts +13 -71
- package/dist/tm/tools.d.ts.map +1 -1
- package/dist/tm/tools.js +23 -656
- package/dist/tm/tools.js.map +1 -1
- package/dist/tm/webfetch.d.ts +94 -0
- package/dist/tm/webfetch.d.ts.map +1 -0
- package/dist/tm/webfetch.js +225 -0
- package/dist/tm/webfetch.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* R6/R2 — environment-protection constants, the host-native `ask` pattern
|
|
3
|
+
* sets (Layer 1 of the unified approval gate), and the mode/config parsing.
|
|
4
|
+
* Split out of the former monolithic envprotect.ts; behavior unchanged.
|
|
5
|
+
*
|
|
6
|
+
* These are the shapes a wildcard CAN express (head-anchored globs). The
|
|
7
|
+
* plugin NEVER self-allows; an unanswered dialog is auto-REJECTED by the
|
|
8
|
+
* approval timer (see approval-gate.ts).
|
|
9
|
+
*/
|
|
10
|
+
/** Audit log service identifier (also the query key for "what was blocked"). */
|
|
11
|
+
export const ENV_PROTECT_SERVICE = "team-mode-env-protect";
|
|
12
|
+
/**
|
|
13
|
+
* Fixed structured message returned to the model on every block. The
|
|
14
|
+
* category is appended as a machine-readable suffix; tests pin both.
|
|
15
|
+
*/
|
|
16
|
+
export const ENV_PROTECT_MESSAGE = "TeamMode R6 env protection: 环境变量读取已被拦截。需要变量值请向 HUMAN 申请。";
|
|
17
|
+
/** Pattern categories surfaced in the block message and the audit log. */
|
|
18
|
+
export const CATEGORY_BASH_ENV_COMMAND = "bash-env-command";
|
|
19
|
+
export const CATEGORY_BASH_ENV_EXPANSION = "bash-env-expansion";
|
|
20
|
+
export const CATEGORY_ENV_FILE_PATH = "env-file-path";
|
|
21
|
+
export const CATEGORY_EXTRA_DENY = "extra-deny";
|
|
22
|
+
/* ------------------------------------------------------------------ */
|
|
23
|
+
/* Unified approval gate — host-native `ask` pattern sets (Layer 1) */
|
|
24
|
+
/* ------------------------------------------------------------------ */
|
|
25
|
+
/**
|
|
26
|
+
* Two faces are routed to the OpenCode official confirmation dialog by
|
|
27
|
+
* declaring them `ask` in each agent's bash permission object. The host
|
|
28
|
+
* pops a dialog for any command matching one of these patterns and SUSPENDS
|
|
29
|
+
* it: a human reply ("once"/"always") runs the command, a "reject" or NO
|
|
30
|
+
* REPLY is handled by the approval timer (Layer 2, see approval-gate.ts)
|
|
31
|
+
* which auto-REJECTS after TM_ASK_TIMEOUT_MIN. The plugin NEVER self-allows.
|
|
32
|
+
*
|
|
33
|
+
* These are the shapes a wildcard CAN express (head-anchored globs, matching
|
|
34
|
+
* the probe-verified grammar: `printenv*`, `rm *`, `Get-ChildItem env:*`).
|
|
35
|
+
* Wildcards CANNOT express (embedded `${VAR}` / `$ALLCAPS` / `$env:` inside
|
|
36
|
+
* another command, command substitution `$(printenv)`, subshell/escaped/
|
|
37
|
+
* `time`-prefixed heads, `VAR=… env` assignment prefixes, split `declare -xp`,
|
|
38
|
+
* env-file paths at arbitrary positions) stay the classifier's HARD THROW —
|
|
39
|
+
* that is the `isAskGatedEnvCommand` boundary, kept in lockstep with the
|
|
40
|
+
* classifier so a form we stop throwing on is exactly a form the dialog shows.
|
|
41
|
+
*/
|
|
42
|
+
/** R6 env face — the wildcard-expressible environment-variable reads. */
|
|
43
|
+
export const R6_ENV_BASH_ASK = Object.freeze({
|
|
44
|
+
printenv: "ask",
|
|
45
|
+
"printenv *": "ask",
|
|
46
|
+
env: "ask",
|
|
47
|
+
"env *": "ask",
|
|
48
|
+
set: "ask",
|
|
49
|
+
"export -p": "ask",
|
|
50
|
+
"export -p *": "ask",
|
|
51
|
+
"declare -p": "ask",
|
|
52
|
+
"declare -p *": "ask",
|
|
53
|
+
"typeset -p": "ask",
|
|
54
|
+
"typeset -p *": "ask",
|
|
55
|
+
"local -p": "ask",
|
|
56
|
+
"local -p *": "ask",
|
|
57
|
+
"$env:*": "ask",
|
|
58
|
+
"Get-ChildItem env:*": "ask",
|
|
59
|
+
"gci env:*": "ask",
|
|
60
|
+
"dir env:*": "ask",
|
|
61
|
+
"ls env:*": "ask",
|
|
62
|
+
"Get-Item env:*": "ask",
|
|
63
|
+
"gi env:*": "ask",
|
|
64
|
+
"Get-Content env:*": "ask",
|
|
65
|
+
"gc env:*": "ask",
|
|
66
|
+
"cat env:*": "ask",
|
|
67
|
+
"type env:*": "ask",
|
|
68
|
+
});
|
|
69
|
+
/** R2 danger face — destructive / publishing / network / install / process /
|
|
70
|
+
* privilege commands. Independent of TM_ENV_PROTECT (R2 is its own red
|
|
71
|
+
* line); the built-in bash tool stays `allow` for everything else, so the
|
|
72
|
+
* normal verification stack (npm test, tsc, git status/diff) never pops. */
|
|
73
|
+
export const R2_DANGER_BASH_ASK = Object.freeze({
|
|
74
|
+
// deletion
|
|
75
|
+
rm: "ask",
|
|
76
|
+
"rm *": "ask",
|
|
77
|
+
rmdir: "ask",
|
|
78
|
+
"rmdir *": "ask",
|
|
79
|
+
rd: "ask",
|
|
80
|
+
"rd *": "ask",
|
|
81
|
+
del: "ask",
|
|
82
|
+
"del *": "ask",
|
|
83
|
+
Erase: "ask",
|
|
84
|
+
"Erase *": "ask",
|
|
85
|
+
"Remove-Item *": "ask",
|
|
86
|
+
"Remove-Item": "ask",
|
|
87
|
+
// git publish (bare forms too — `git push` / `git commit` WITHOUT args are
|
|
88
|
+
// the shapes the arg-carrying globs cannot match)
|
|
89
|
+
"git push *": "ask",
|
|
90
|
+
"git push": "ask",
|
|
91
|
+
"git commit *": "ask",
|
|
92
|
+
"git commit": "ask",
|
|
93
|
+
// network
|
|
94
|
+
curl: "ask",
|
|
95
|
+
"curl *": "ask",
|
|
96
|
+
"wget *": "ask",
|
|
97
|
+
"Invoke-WebRequest *": "ask",
|
|
98
|
+
"Invoke-RestMethod *": "ask",
|
|
99
|
+
// package management
|
|
100
|
+
"npm install *": "ask",
|
|
101
|
+
"npm i *": "ask",
|
|
102
|
+
"npm publish *": "ask",
|
|
103
|
+
"npm publish": "ask",
|
|
104
|
+
"pip install *": "ask",
|
|
105
|
+
"pip3 install *": "ask",
|
|
106
|
+
"winget *": "ask",
|
|
107
|
+
"choco *": "ask",
|
|
108
|
+
// process / system
|
|
109
|
+
"taskkill *": "ask",
|
|
110
|
+
"Stop-Process *": "ask",
|
|
111
|
+
"kill *": "ask",
|
|
112
|
+
"shutdown *": "ask",
|
|
113
|
+
"format *": "ask",
|
|
114
|
+
// privilege
|
|
115
|
+
"chmod *": "ask",
|
|
116
|
+
"takeown *": "ask",
|
|
117
|
+
"icacls *": "ask",
|
|
118
|
+
});
|
|
119
|
+
/** Ordered key lists (frozen) — single source for the matcher + the gate. */
|
|
120
|
+
export const R6_ENV_BASH_ASK_PATTERNS = Object.freeze(Object.keys(R6_ENV_BASH_ASK));
|
|
121
|
+
export const R2_DANGER_BASH_ASK_PATTERNS = Object.freeze(Object.keys(R2_DANGER_BASH_ASK));
|
|
122
|
+
/**
|
|
123
|
+
* The bash permission object injected into the four execution-role agents
|
|
124
|
+
* (team / implementer / reviewer / tester). Default stays `allow`
|
|
125
|
+
* (`"*": "allow"`, preserving the T2.1 matrix semantics — bash is granted,
|
|
126
|
+
* not removed); only the listed shapes escalate to the host dialog. The R6
|
|
127
|
+
* env face is dropped when `mode === "off"` (the R6 kill switch) AND when
|
|
128
|
+
* `envFace` is false — index.ts passes false while the approval gate cannot
|
|
129
|
+
* arm: the R6 hook then hard-throws every env read BEFORE its dialog could
|
|
130
|
+
* ever satisfy it, so injecting the env asks would only create dead popups
|
|
131
|
+
* a human can answer yet never make runnable. The R2 face is always
|
|
132
|
+
* present (its dialog is the whole gate — no code-level throw is involved).
|
|
133
|
+
*/
|
|
134
|
+
export function bashAskPatterns(mode, envFace = true) {
|
|
135
|
+
const out = { "*": "allow" };
|
|
136
|
+
if (mode !== "off" && envFace) {
|
|
137
|
+
for (const p of R6_ENV_BASH_ASK_PATTERNS)
|
|
138
|
+
out[p] = "ask";
|
|
139
|
+
}
|
|
140
|
+
for (const p of R2_DANGER_BASH_ASK_PATTERNS)
|
|
141
|
+
out[p] = "ask";
|
|
142
|
+
return out;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Resolve the protection mode. Only exact "standard" / "off" switch those
|
|
146
|
+
* modes on; everything else (unset, typos, wrong case) fails CLOSED into
|
|
147
|
+
* strict — a mistyped opt-out must never disable the red line.
|
|
148
|
+
*/
|
|
149
|
+
export function resolveEnvProtectMode(raw) {
|
|
150
|
+
if (raw === "standard")
|
|
151
|
+
return "standard";
|
|
152
|
+
if (raw === "off")
|
|
153
|
+
return "off";
|
|
154
|
+
return "strict";
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Parse `TM_ENV_PROTECT_EXTRA_DENY` (semicolon-separated regex bodies).
|
|
158
|
+
* Invalid regexes are skipped rather than crashing plugin startup; the
|
|
159
|
+
* remaining rules still apply. Empty/absent input yields no extra rules.
|
|
160
|
+
*/
|
|
161
|
+
export function parseExtraDeny(raw) {
|
|
162
|
+
if (typeof raw !== "string")
|
|
163
|
+
return [];
|
|
164
|
+
const rules = [];
|
|
165
|
+
for (const part of raw.split(";")) {
|
|
166
|
+
const body = part.trim();
|
|
167
|
+
if (!body)
|
|
168
|
+
continue;
|
|
169
|
+
try {
|
|
170
|
+
rules.push(new RegExp(body));
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
/* user regex failed to compile — skip it, keep the rest */
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return rules;
|
|
177
|
+
}
|
|
178
|
+
/** The block error handed back to the model (fixed text + category tag). */
|
|
179
|
+
export function envProtectError(category) {
|
|
180
|
+
return new Error(`${ENV_PROTECT_MESSAGE} [category=${category}]`);
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=patterns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../src/envprotect/patterns.ts"],"names":[],"mappings":"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"}
|
package/dist/envprotect.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* R6 — code-level environment-variable read protection for Team mode.
|
|
3
3
|
*
|
|
4
|
+
* MODULE FACADE: the implementation lives in ./envprotect/ (patterns,
|
|
5
|
+
* bash-classify, path-classify, gate-predicates, hook). This file only
|
|
6
|
+
* re-exports the historical surface so every existing import specifier
|
|
7
|
+
* (`../envprotect.js`, `./envprotect.js`) and the dist path keep working.
|
|
8
|
+
*
|
|
4
9
|
* HUMAN-approved feature: in Team mode, EVERY path the model can use to
|
|
5
10
|
* read environment variables / env files is intercepted in code, before
|
|
6
11
|
* the tool runs, independent of prompt compliance. This hook throws inside
|
|
@@ -8,227 +13,24 @@
|
|
|
8
13
|
* into a failed tool call whose error text is returned to the model — so
|
|
9
14
|
* the block is hard, not advisory.
|
|
10
15
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* word follows: flags/assignments only (`env -0`, `env -u HOME`,
|
|
16
|
-
* `env FOO=bar`) or a command word that is itself `env`/`printenv`
|
|
17
|
-
* (`env printenv`); a real launcher (`env node app.js`, `env -i node
|
|
18
|
-
* app.js`) passes — `printenv`, bare `set` (sh context only —
|
|
19
|
-
* PowerShell `Set-*` cmdlets are never matched), `declare -p` and
|
|
20
|
-
* its dump synonyms `typeset -p` / `export -p` / `local -p` (flags
|
|
21
|
-
* may be split: `declare -x -p FOO`), and the PowerShell `env:`
|
|
22
|
-
* drive via Get-ChildItem / gci / dir / ls / Get-Item / gi /
|
|
23
|
-
* Get-Content / gc / cat / type (flags and optional quotes allowed
|
|
24
|
-
* between cmdlet and drive: `Get-Content 'env:HOME'`). The same
|
|
25
|
-
* statement heads are caught behind statement noise: subshells and
|
|
26
|
-
* groups (`(env)`, `{ env; }`), escaped commands (`\env`), the `time`
|
|
27
|
-
* keyword prefix, command substitution (`$(printenv)`, backticks), the
|
|
28
|
-
* program-path twins of the dump heads (bare `/usr/bin/env` = full
|
|
29
|
-
* dump, `/usr/bin/printenv …`), and the Windows launcher head
|
|
30
|
-
* (`cmd /c set` = cmd.exe's own caseless full dump; `/k` and quoted
|
|
31
|
-
* inners included).
|
|
32
|
-
* 2. `$env:` / `${env:...}` expansion (PowerShell);
|
|
33
|
-
* 3. strict mode only: `${VAR}` and `$ALLCAPS_VAR` expansion;
|
|
34
|
-
* 4. env-file paths: `.env`, `.env.*`, `*.env`, `.bashrc`,
|
|
35
|
-
* `.bash_profile`, `.profile`, `.zshrc`, `.zprofile`, `.zshenv`
|
|
36
|
-
* (checked-in template copies like `.env.example` are exempt, and
|
|
37
|
-
* code identifiers like `process.env` are not files).
|
|
38
|
-
*
|
|
39
|
-
* TeamMode's own tm_* tools (tm_read / tm_grep / tm_bash) are aliased onto
|
|
40
|
-
* read/grep/bash in `inspectToolCall`, so this interception covers them
|
|
41
|
-
* identically — the plugin tools can never serve as an R6 bypass.
|
|
42
|
-
*
|
|
43
|
-
* Known limitation (accepted, documented): interpreter execution paths —
|
|
44
|
-
* `bash -c "env"`, `node -e 'process.env'`, `python -c "import os; ..."` —
|
|
45
|
-
* are NOT intercepted; the pattern surface stops at the command line
|
|
46
|
-
* itself. One decode pass covers URL-encoded names (`/%2Eenv`); a double
|
|
47
|
-
* encoding (`/%252Eenv`) and a quoted dump head behind `env`
|
|
48
|
-
* (`env 'printenv'`) stay ahead of the matcher by design.
|
|
49
|
-
*
|
|
50
|
-
* Configuration (read by the PLUGIN at startup — this is program-level
|
|
51
|
-
* configuration of the tool itself, the same category as the ttlDays
|
|
52
|
-
* option below; it is NOT what R6 defends against, which is the MODEL
|
|
53
|
-
* reading environment variables through tool calls at runtime):
|
|
16
|
+
* Configuration (plugin options + env, read at startup):
|
|
17
|
+
* - plugin option `envProtect` (v1.5.4, default FALSE) gates the whole
|
|
18
|
+
* feature: without opting in, nothing intercepts, no gate arms, no
|
|
19
|
+
* audit lines are written. When opted in:
|
|
54
20
|
* - `TM_ENV_PROTECT` = "strict" (default) | "standard" | "off";
|
|
55
21
|
* unknown values fail closed into strict.
|
|
56
22
|
* - `TM_ENV_PROTECT_EXTRA_DENY` = semicolon-separated user regexes,
|
|
57
23
|
* applied to every scanned string in any non-off mode.
|
|
58
24
|
*
|
|
59
25
|
* Audit red line (HUMAN privacy constraint): every interception is logged
|
|
60
|
-
* via `client.app.log()`
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
export
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
* category is appended as a machine-readable suffix; tests pin both.
|
|
71
|
-
*/
|
|
72
|
-
export declare const ENV_PROTECT_MESSAGE = "TeamMode R6 env protection: \u73AF\u5883\u53D8\u91CF\u8BFB\u53D6\u5DF2\u88AB\u62E6\u622A\u3002\u9700\u8981\u53D8\u91CF\u503C\u8BF7\u5411 HUMAN \u7533\u8BF7\u3002";
|
|
73
|
-
/** Pattern categories surfaced in the block message and the audit log. */
|
|
74
|
-
export declare const CATEGORY_BASH_ENV_COMMAND = "bash-env-command";
|
|
75
|
-
export declare const CATEGORY_BASH_ENV_EXPANSION = "bash-env-expansion";
|
|
76
|
-
export declare const CATEGORY_ENV_FILE_PATH = "env-file-path";
|
|
77
|
-
export declare const CATEGORY_EXTRA_DENY = "extra-deny";
|
|
78
|
-
/**
|
|
79
|
-
* Two faces are routed to the OpenCode official confirmation dialog by
|
|
80
|
-
* declaring them `ask` in each agent's bash permission object. The host
|
|
81
|
-
* pops a dialog for any command matching one of these patterns and SUSPENDS
|
|
82
|
-
* it: a human reply ("once"/"always") runs the command, a "reject" or NO
|
|
83
|
-
* REPLY is handled by the approval timer (Layer 2, see approval-gate.ts)
|
|
84
|
-
* which auto-REJECTS after TM_ASK_TIMEOUT_MIN. The plugin NEVER self-allows.
|
|
85
|
-
*
|
|
86
|
-
* These are the shapes a wildcard CAN express (head-anchored globs, matching
|
|
87
|
-
* the probe-verified grammar: `printenv*`, `rm *`, `Get-ChildItem env:*`).
|
|
88
|
-
* Wildcards CANNOT express (embedded `${VAR}` / `$ALLCAPS` / `$env:` inside
|
|
89
|
-
* another command, command substitution `$(printenv)`, subshell/escaped/
|
|
90
|
-
* `time`-prefixed heads, `VAR=… env` assignment prefixes, split `declare -xp`,
|
|
91
|
-
* env-file paths at arbitrary positions) stay the classifier's HARD THROW —
|
|
92
|
-
* that is the `isAskGatedEnvCommand` boundary, kept in lockstep with the
|
|
93
|
-
* classifier so a form we stop throwing on is exactly a form the dialog shows.
|
|
94
|
-
*/
|
|
95
|
-
/** R6 env face — the wildcard-expressible environment-variable reads. */
|
|
96
|
-
export declare const R6_ENV_BASH_ASK: Readonly<Record<string, "ask">>;
|
|
97
|
-
/** R2 danger face — destructive / publishing / network / install / process /
|
|
98
|
-
* privilege commands. Independent of TM_ENV_PROTECT (R2 is its own red
|
|
99
|
-
* line); the built-in bash tool stays `allow` for everything else, so the
|
|
100
|
-
* normal verification stack (npm test, tsc, git status/diff) never pops. */
|
|
101
|
-
export declare const R2_DANGER_BASH_ASK: Readonly<Record<string, "ask">>;
|
|
102
|
-
/** Ordered key lists (frozen) — single source for the matcher + the gate. */
|
|
103
|
-
export declare const R6_ENV_BASH_ASK_PATTERNS: readonly string[];
|
|
104
|
-
export declare const R2_DANGER_BASH_ASK_PATTERNS: readonly string[];
|
|
105
|
-
/**
|
|
106
|
-
* The bash permission object injected into the four execution-role agents
|
|
107
|
-
* (team / implementer / reviewer / tester). Default stays `allow`
|
|
108
|
-
* (`"*": "allow"`, preserving the T2.1 matrix semantics — bash is granted,
|
|
109
|
-
* not removed); only the listed shapes escalate to the host dialog. The R6
|
|
110
|
-
* env face is dropped when `mode === "off"` (the R6 kill switch) AND when
|
|
111
|
-
* `envFace` is false — index.ts passes false while the approval gate cannot
|
|
112
|
-
* arm: the R6 hook then hard-throws every env read BEFORE its dialog could
|
|
113
|
-
* ever satisfy it, so injecting the env asks would only create dead popups
|
|
114
|
-
* a human can answer yet never make runnable. The R2 face is always
|
|
115
|
-
* present (its dialog is the whole gate — no code-level throw is involved).
|
|
116
|
-
*/
|
|
117
|
-
export declare function bashAskPatterns(mode: EnvProtectMode, envFace?: boolean): Record<string, string>;
|
|
118
|
-
export type EnvProtectMode = "strict" | "standard" | "off";
|
|
119
|
-
/**
|
|
120
|
-
* Resolve the protection mode. Only exact "standard" / "off" switch those
|
|
121
|
-
* modes on; everything else (unset, typos, wrong case) fails CLOSED into
|
|
122
|
-
* strict — a mistyped opt-out must never disable the red line.
|
|
123
|
-
*/
|
|
124
|
-
export declare function resolveEnvProtectMode(raw: unknown): EnvProtectMode;
|
|
125
|
-
/**
|
|
126
|
-
* Parse `TM_ENV_PROTECT_EXTRA_DENY` (semicolon-separated regex bodies).
|
|
127
|
-
* Invalid regexes are skipped rather than crashing plugin startup; the
|
|
128
|
-
* remaining rules still apply. Empty/absent input yields no extra rules.
|
|
129
|
-
*/
|
|
130
|
-
export declare function parseExtraDeny(raw: unknown): RegExp[];
|
|
131
|
-
/** The block error handed back to the model (fixed text + category tag). */
|
|
132
|
-
export declare function envProtectError(category: string): Error;
|
|
133
|
-
/**
|
|
134
|
-
* True when the value points at an env file. Matches on the BASENAME with
|
|
135
|
-
* both separators handled; URL query/fragment tails are cut first so
|
|
136
|
-
* `https://x/.env?raw=1` matches the same basename as a plain path, and
|
|
137
|
-
* asterisks are stripped so glob patterns like "*.env" or a recursive deep
|
|
138
|
-
* form of ".env.local" are caught by the same matcher as real paths.
|
|
139
|
-
* (Note: glob spellings are written without backticks here — a double-star
|
|
140
|
-
* + slash inside JSDoc would close the comment block early.)
|
|
141
|
-
*/
|
|
142
|
-
export declare function isEnvFilePath(raw: string): boolean;
|
|
143
|
-
/**
|
|
144
|
-
* Classify a bash/PowerShell command string. Returns the pattern category
|
|
145
|
-
* when the command must be blocked, null when it may pass. `off` is
|
|
146
|
-
* handled by the caller; user extra-deny rules take precedence.
|
|
147
|
-
*/
|
|
148
|
-
export declare function classifyBashCommand(command: string, mode: EnvProtectMode, extra?: RegExp[]): string | null;
|
|
149
|
-
/** True when `text` matches ANY of the given ask globs (LOOSE, host-style). */
|
|
150
|
-
export declare function commandMatchesAnyAskPattern(text: unknown, patterns: readonly string[]): boolean;
|
|
151
|
-
/**
|
|
152
|
-
* True when a built-in-bash command is an environment read in a form the
|
|
153
|
-
* host is configured to ASK about (and therefore the dialog governs it).
|
|
154
|
-
* The hook then lets it proceed WITHOUT throwing, so a human approval is
|
|
155
|
-
* meaningful. Kept deliberately narrower than classifyBashCommand: every
|
|
156
|
-
* form it accepts is a head-anchored single statement that matches one of
|
|
157
|
-
* R6_ENV_BASH_ASK BYTE-EXACTLY (so the dialog WILL fire under any host
|
|
158
|
-
* grammar at least as greedy as ours — no case/trim leniency, see
|
|
159
|
-
* commandMatchesAnyAskPatternExact), and every hazard that breaks that
|
|
160
|
-
* alignment (compound statements, substitutions, `${…}`, `$ALLCAPS`,
|
|
161
|
-
* assignment prefixes, `time`/subshell/escaped heads, user extra-deny, path
|
|
162
|
-
* heads like `/usr/bin/env`, `cmd /c …`, and the PowerShell env-drive forms
|
|
163
|
-
* with intervening flags or quotes that the globs miss) returns false → the
|
|
164
|
-
* classifier keeps hard-throwing. tm_* channels are hard-blocked separately
|
|
165
|
-
* (the dialog never opens for them).
|
|
166
|
-
*/
|
|
167
|
-
export declare function isAskGatedEnvCommand(command: string, mode: EnvProtectMode, extra?: RegExp[]): boolean;
|
|
168
|
-
/**
|
|
169
|
-
* Coarse category for a host permission-event payload, used ONLY to gate the
|
|
170
|
-
* timer, to register the deferral session, and to tag the audit (never the
|
|
171
|
-
* pattern text itself). Returns null for anything that is not one of OUR
|
|
172
|
-
* injected bash asks, so the gate leaves other tools' dialogs (edit,
|
|
173
|
-
* webfetch, host-native rules) alone.
|
|
174
|
-
*
|
|
175
|
-
* Real 1.18.29 `permission.asked` props carry NO `type` field: the tool name
|
|
176
|
-
* rides in `permission` and the concrete command segments in `patterns[]`
|
|
177
|
-
* (plus `metadata.command` with the raw line). Inference order, defensive
|
|
178
|
-
* across builds:
|
|
179
|
-
* 1. explicit tool field (`type` || `permission`) — non-bash is a hard no;
|
|
180
|
-
* 2. absent tool field → bash evidence = `metadata.command` present, or a
|
|
181
|
-
* candidate that is COMMAND-SHAPED (contains whitespace: our command
|
|
182
|
-
* globs all need an embedded space except bare keys, and bare-key
|
|
183
|
-
* patterns like a file named `set` cannot prove bash without the
|
|
184
|
-
* command metadata beside them).
|
|
185
|
-
* Matching here is the LOOSE glob (case-insensitive): over-matching can only
|
|
186
|
-
* arm a timer for a dialog the host already opened, never run a command —
|
|
187
|
-
* the deferral side keeps the byte-exact matcher (isAskGatedEnvCommand).
|
|
188
|
-
*/
|
|
189
|
-
export declare function categorizePermission(props: {
|
|
190
|
-
type?: string;
|
|
191
|
-
permission?: string;
|
|
192
|
-
pattern?: string | string[];
|
|
193
|
-
patterns?: string | string[];
|
|
194
|
-
title?: string;
|
|
195
|
-
metadata?: Record<string, unknown>;
|
|
196
|
-
} | null | undefined): "env" | "danger" | null;
|
|
197
|
-
/**
|
|
198
|
-
* Classify the path-class arguments of a file tool. Returns the pattern
|
|
199
|
-
* category when the call must be blocked, null when it may pass.
|
|
200
|
-
*/
|
|
201
|
-
export declare function classifyPathFields(args: Record<string, unknown> | undefined, mode: EnvProtectMode, extra?: RegExp[]): string | null;
|
|
202
|
-
/**
|
|
203
|
-
* Top routing: tool name + tool args -> category to block, or null to pass.
|
|
204
|
-
* `off` always passes (the hook stays installed but is a no-op).
|
|
205
|
-
*/
|
|
206
|
-
export declare function inspectToolCall(tool: string, args: Record<string, unknown> | undefined, mode: EnvProtectMode, extra?: RegExp[]): string | null;
|
|
207
|
-
/**
|
|
208
|
-
* Build the `tool.execute.before` hook. The hook is installed in every
|
|
209
|
-
* mode; with mode "off" it returns immediately and everything passes.
|
|
210
|
-
* When a block triggers, the audit entry is written first, then the fixed
|
|
211
|
-
* structured error is thrown so opencode surfaces it to the model as the
|
|
212
|
-
* failed tool result.
|
|
213
|
-
*
|
|
214
|
-
* `options.deferToApproval` (the unified approval gate) — called with the
|
|
215
|
-
* tool call's `input.sessionID`; when it reports `true`, a built-in-bash
|
|
216
|
-
* environment read in an EXACT ask-glob form is passed through WITHOUT
|
|
217
|
-
* throwing, because the official confirmation dialog is the live gate for
|
|
218
|
-
* it (approve → runs, reject or timeout → the host blocks it). The signal
|
|
219
|
-
* is SESSION-SCOPED on purpose: the gate registers only sessions carrying
|
|
220
|
-
* our injected bash ask set (exec-role chat.message, or an R6-env-classified
|
|
221
|
-
* `permission.asked`), so a stock build/plan session — where no dialog would
|
|
222
|
-
* ever open for `printenv` — keeps the hard throw instead of slipping the
|
|
223
|
-
* read through a global arm flag. Reaching the deferral point at all
|
|
224
|
-
* additionally requires the command to match the config globs byte-exactly,
|
|
225
|
-
* so the dialog is GUARANTEED to fire wherever deferral happens. A failed
|
|
226
|
-
* auto-reject flips the gate back to `false` everywhere, restoring the hard
|
|
227
|
-
* throw (fail-closed). tm_* channels are never deferred (no dialog opens
|
|
228
|
-
* for them).
|
|
229
|
-
*/
|
|
230
|
-
export declare function createEnvProtectHook(client: unknown, mode: EnvProtectMode, extra?: RegExp[], options?: {
|
|
231
|
-
deferToApproval?: (sessionID?: string) => boolean;
|
|
232
|
-
envApproved?: (sessionID?: string) => boolean;
|
|
233
|
-
}): (input: unknown, output: unknown) => Promise<void>;
|
|
26
|
+
* via `client.app.log()` recording ONLY the tool name and the pattern
|
|
27
|
+
* category. Command text, paths, variable names and values are NEVER
|
|
28
|
+
* logged.
|
|
29
|
+
*/
|
|
30
|
+
export { CATEGORY_BASH_ENV_COMMAND, CATEGORY_BASH_ENV_EXPANSION, CATEGORY_ENV_FILE_PATH, CATEGORY_EXTRA_DENY, R2_DANGER_BASH_ASK, R2_DANGER_BASH_ASK_PATTERNS, R6_ENV_BASH_ASK, R6_ENV_BASH_ASK_PATTERNS, ENV_PROTECT_SERVICE, ENV_PROTECT_MESSAGE, bashAskPatterns, envProtectError, parseExtraDeny, resolveEnvProtectMode, } from "./envprotect/patterns.js";
|
|
31
|
+
export type { EnvProtectMode } from "./envprotect/patterns.js";
|
|
32
|
+
export { isEnvFilePath } from "./envprotect/path-classify.js";
|
|
33
|
+
export { classifyBashCommand } from "./envprotect/bash-classify.js";
|
|
34
|
+
export { categorizePermission, commandMatchesAnyAskPattern, isAskGatedEnvCommand, } from "./envprotect/gate-predicates.js";
|
|
35
|
+
export { classifyPathFields, createEnvProtectHook, inspectToolCall } from "./envprotect/hook.js";
|
|
234
36
|
//# sourceMappingURL=envprotect.d.ts.map
|
package/dist/envprotect.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"envprotect.d.ts","sourceRoot":"","sources":["../src/envprotect.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"envprotect.d.ts","sourceRoot":"","sources":["../src/envprotect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EACL,yBAAyB,EACzB,2BAA2B,EAC3B,sBAAsB,EACtB,mBAAmB,EACnB,kBAAkB,EAClB,2BAA2B,EAC3B,eAAe,EACf,wBAAwB,EACxB,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,cAAc,EACd,qBAAqB,GACtB,MAAM,0BAA0B,CAAA;AACjC,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAE9D,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAE7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAA;AAEnE,OAAO,EACL,oBAAoB,EACpB,2BAA2B,EAC3B,oBAAoB,GACrB,MAAM,iCAAiC,CAAA;AAExC,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA"}
|