@lazyingart/agintiflow 0.20.91 → 0.20.93
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/package.json +1 -1
- package/scripts/smoke-coding-tools.js +13 -0
- package/scripts/smoke-tmux-tools.js +55 -0
- package/skills/github-maintenance/SKILL.md +1 -1
- package/src/agent-runner.js +1 -1
- package/src/command-policy.js +4 -0
- package/src/model-client.js +1 -1
- package/src/task-profiles.js +1 -1
- package/src/tmux-tools.js +69 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazyingart/agintiflow",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.93",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Low-cost, project-aware Web and CLI agents with DeepSeek/Venice/OpenAI routing, visible tool calls, durable sessions, scouts, AAPS, SCS, and guarded local execution.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -338,8 +338,21 @@ try {
|
|
|
338
338
|
assert(localGitCommitPolicy.category === "git-workflow", "local git commit should be classified as git-workflow");
|
|
339
339
|
const localGitSwitchPolicy = evaluateCommandPolicy("git switch -c feature-a", dockerWorkspaceNoInstallsPolicy);
|
|
340
340
|
assert(localGitSwitchPolicy.allowed, "local git switch -c should be allowed without package installs");
|
|
341
|
+
const localGitCheckoutExistingPolicy = evaluateCommandPolicy("git checkout main", dockerWorkspaceNoInstallsPolicy);
|
|
342
|
+
assert(localGitCheckoutExistingPolicy.allowed, "local git checkout existing branch should be allowed without package installs");
|
|
341
343
|
const localGitMergePolicy = evaluateCommandPolicy("git merge --ff-only feature-a", dockerWorkspaceNoInstallsPolicy);
|
|
342
344
|
assert(localGitMergePolicy.allowed, "local git fast-forward merge should be allowed without package installs");
|
|
345
|
+
const localGitNoFfMergePolicy = evaluateCommandPolicy("git merge --no-ff --no-edit feature-b", dockerWorkspaceNoInstallsPolicy);
|
|
346
|
+
assert(localGitNoFfMergePolicy.allowed, "local git explicit no-ff merge should be allowed without package installs");
|
|
347
|
+
const localGitNoFfMergeAltPolicy = evaluateCommandPolicy("git merge --no-ff feature-b --no-edit", dockerWorkspaceNoInstallsPolicy);
|
|
348
|
+
assert(localGitNoFfMergeAltPolicy.allowed, "local git explicit no-ff merge alternate arg order should be allowed");
|
|
349
|
+
const localGitWorkflowSequencePolicy = evaluateCommandPolicy(
|
|
350
|
+
"cd /workspace/git-practice && git checkout main && git merge --ff-only feature-a",
|
|
351
|
+
dockerWorkspaceNoInstallsPolicy
|
|
352
|
+
);
|
|
353
|
+
assert(localGitWorkflowSequencePolicy.allowed, "local git checkout + ff-only merge sequence should be allowed without package installs");
|
|
354
|
+
const plainGitMergePolicy = evaluateCommandPolicy("git merge feature-a", dockerWorkspaceNoInstallsPolicy);
|
|
355
|
+
assert(!plainGitMergePolicy.allowed, "plain git merge should stay guarded because it can hang or make an ambiguous merge");
|
|
343
356
|
const unsafeRebasePolicy = evaluateCommandPolicy("git rebase main", dockerWorkspaceNoInstallsPolicy);
|
|
344
357
|
assert(!unsafeRebasePolicy.allowed, "git rebase should still require stronger permission because it rewrites history");
|
|
345
358
|
const unsafeCloneTarget = evaluateCommandPolicy("git clone https://github.com/lazyingart/AgInTiFlow.git ../AgInTiFlow", dockerWorkspacePolicy);
|
|
@@ -36,6 +36,10 @@ const dockerConfig = {
|
|
|
36
36
|
sandboxMode: "docker-workspace",
|
|
37
37
|
packageInstallPolicy: "allow",
|
|
38
38
|
};
|
|
39
|
+
const dockerNoInstallsConfig = {
|
|
40
|
+
...dockerConfig,
|
|
41
|
+
packageInstallPolicy: "block",
|
|
42
|
+
};
|
|
39
43
|
|
|
40
44
|
function sleep(ms) {
|
|
41
45
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -122,6 +126,52 @@ try {
|
|
|
122
126
|
});
|
|
123
127
|
assert.equal(dockerTmuxRelativeStart.allowed, true, "Docker-mode tmux_start_session should allow workspace-relative paths");
|
|
124
128
|
|
|
129
|
+
const dockerTmuxGitFfMergeStart = checkToolUse({
|
|
130
|
+
toolName: "tmux_start_session",
|
|
131
|
+
args: {
|
|
132
|
+
name: `${session}-docker-git-ff`,
|
|
133
|
+
cwd: ".",
|
|
134
|
+
command: "git checkout main && git merge --ff-only feature-a",
|
|
135
|
+
},
|
|
136
|
+
config: dockerNoInstallsConfig,
|
|
137
|
+
});
|
|
138
|
+
assert.equal(dockerTmuxGitFfMergeStart.allowed, true, "Docker-mode tmux should allow explicit local checkout + ff-only merge workflow");
|
|
139
|
+
|
|
140
|
+
const dockerTmuxGitPlainMergeStart = checkToolUse({
|
|
141
|
+
toolName: "tmux_start_session",
|
|
142
|
+
args: { name: `${session}-docker-git-plain-merge`, cwd: ".", command: "git merge feature-a" },
|
|
143
|
+
config: dockerNoInstallsConfig,
|
|
144
|
+
});
|
|
145
|
+
assert.equal(dockerTmuxGitPlainMergeStart.allowed, false, "Docker-mode tmux should keep plain git merge guarded");
|
|
146
|
+
assert.equal(dockerTmuxGitPlainMergeStart.category, "destructive", "plain git merge should keep destructive category");
|
|
147
|
+
|
|
148
|
+
const dockerTmuxRebaseStart = checkToolUse({
|
|
149
|
+
toolName: "tmux_start_session",
|
|
150
|
+
args: { name: `${session}-docker-rebase`, cwd: ".", command: "git rebase main" },
|
|
151
|
+
config: dockerNoInstallsConfig,
|
|
152
|
+
});
|
|
153
|
+
assert.equal(dockerTmuxRebaseStart.allowed, false, "Docker-mode tmux_start_session should not bypass git rebase guard");
|
|
154
|
+
assert.equal(dockerTmuxRebaseStart.category, "destructive", "Docker tmux rebase block should keep command-policy category");
|
|
155
|
+
|
|
156
|
+
const directDockerRebaseStart = await startTmuxSession(
|
|
157
|
+
{ name: `${session}-direct-docker-rebase`, cwd: ".", command: "git rebase main" },
|
|
158
|
+
dockerNoInstallsConfig
|
|
159
|
+
);
|
|
160
|
+
assert.equal(directDockerRebaseStart.ok, false, "tmux_start_session direct path should enforce Docker shell policy");
|
|
161
|
+
|
|
162
|
+
const dockerTmuxRebaseSend = await sendTmuxKeys(
|
|
163
|
+
{ target: start.target, text: "git rebase main", enter: true },
|
|
164
|
+
dockerNoInstallsConfig
|
|
165
|
+
);
|
|
166
|
+
assert.equal(dockerTmuxRebaseSend.ok, false, "Docker-mode tmux_send_keys should not bypass git rebase guard in shell panes");
|
|
167
|
+
assert.equal(dockerTmuxRebaseSend.category, "destructive", "Docker tmux send rebase block should keep command-policy category");
|
|
168
|
+
|
|
169
|
+
const dockerTmuxGitStatusSend = await sendTmuxKeys(
|
|
170
|
+
{ target: start.target, text: "git status --short", enter: true },
|
|
171
|
+
dockerNoInstallsConfig
|
|
172
|
+
);
|
|
173
|
+
assert.equal(dockerTmuxGitStatusSend.ok, true, "Docker-mode tmux_send_keys should allow read-only git status in shell panes");
|
|
174
|
+
|
|
125
175
|
const hostBroadTmuxStart = checkToolUse({
|
|
126
176
|
toolName: "tmux_start_session",
|
|
127
177
|
args: { name: `${session}-host-broad`, cwd: ".", command: 'echo "HOST_TMUX_STARTED"; sleep 1' },
|
|
@@ -203,6 +253,11 @@ try {
|
|
|
203
253
|
"docker-tmux-send-outside-path-guardrail",
|
|
204
254
|
"docker-tmux-start-project-path-allowed",
|
|
205
255
|
"docker-tmux-start-relative-path-allowed",
|
|
256
|
+
"docker-tmux-start-command-policy-guardrail",
|
|
257
|
+
"docker-tmux-start-git-ff-merge-allowed",
|
|
258
|
+
"docker-tmux-start-plain-git-merge-guarded",
|
|
259
|
+
"docker-tmux-send-command-policy-guardrail",
|
|
260
|
+
"docker-tmux-send-readonly-command-allowed",
|
|
206
261
|
"host-tmux-start-shell-policy-guardrail",
|
|
207
262
|
"host-tmux-send-shell-policy-guardrail",
|
|
208
263
|
"host-tmux-control-key-allowed",
|
|
@@ -20,6 +20,6 @@ tools:
|
|
|
20
20
|
|
|
21
21
|
Always inspect `git status --short` and relevant diffs before committing or pushing. Keep commits scoped and stop on conflicts, divergence, or unrelated dirty work.
|
|
22
22
|
|
|
23
|
-
For local workflow practice or repository setup, prefer a disposable subdirectory if the user did not clearly target the current repository. Configure only local git identity (`git config user.name`, `git config user.email`) inside that repo; never change global git config. Use accurate git scenarios: a fast-forward merge means the target branch has not diverged; a non-fast-forward merge intentionally creates a merge commit after both branches diverge; a rebase rewrites local branch commits and should be used only in an explicitly disposable/local branch or after user approval.
|
|
23
|
+
For local workflow practice or repository setup, prefer a disposable subdirectory if the user did not clearly target the current repository. Configure only local git identity (`git config user.name`, `git config user.email`) inside that repo; never change global git config. Use policy-friendly local commands: `git switch <branch>` or `git checkout <branch>` for existing branches, `git switch -c <branch>` or `git checkout -b <branch>` for new branches, `git merge --ff-only <branch>` for fast-forward evidence, and `git merge --no-ff --no-edit <branch>` for explicit merge-commit evidence. Avoid plain `git merge <branch>` because it can hang on an editor or make an ambiguous merge. Use accurate git scenarios: a fast-forward merge means the target branch has not diverged; a non-fast-forward merge intentionally creates a merge commit after both branches diverge; a rebase rewrites local branch commits and should be used only in an explicitly disposable/local branch or after user approval.
|
|
24
24
|
|
|
25
25
|
Use `gh` for PR/release/status workflows when authenticated. Fold long command output but preserve key errors, URLs, branch names, and commit hashes.
|
package/src/agent-runner.js
CHANGED
|
@@ -894,7 +894,7 @@ async function captureSyntheticSnapshot(store, step, config) {
|
|
|
894
894
|
: `Shell tool available in: ${config.commandCwd} on ${platformLabel(platform)}. Use OS-compatible commands; prefer WSL/Docker for bash-heavy workflows on Windows.`
|
|
895
895
|
: "Shell tool disabled.",
|
|
896
896
|
config.allowShellTool
|
|
897
|
-
? "Host tmux tools available: tmux_list_sessions, tmux_capture_pane, tmux_send_keys, tmux_start_session. Use them for long-running jobs and agent terminals; capture before sending input. Docker run_command containers are ephemeral, so tmux there will not persist. In Docker sandbox mode, tmux start/send commands must stay workspace-bound and cannot reference absolute host paths outside the project;
|
|
897
|
+
? "Host tmux tools available: tmux_list_sessions, tmux_capture_pane, tmux_send_keys, tmux_start_session. Use them for long-running jobs and agent terminals; capture before sending input. Docker run_command containers are ephemeral, so tmux there will not persist. In Docker sandbox mode, tmux start/send commands must stay workspace-bound and cannot reference absolute host paths outside the project; when sending text into a shell pane, tmux follows the same Docker workspace command policy as run_command and is not a bypass for package installs, destructive git history rewrites, or broad shell text. Use --sandbox-mode host for trusted whole-host work. In host mode, tmux startup/send command text follows the same host shell policy as run_command; if a broad host command is blocked, present the approval/rerun path instead of trying tmux as a workaround. For one-shot tmux commands, redirect output and exit status to a durable workspace log or keep the pane alive for capture; if capture fails because the session ended, do not infer output or exit status."
|
|
898
898
|
: "",
|
|
899
899
|
config.allowFileTools
|
|
900
900
|
? `Workspace file tools available in: ${config.commandCwd}. Use inspect_project first for large or unfamiliar codebases, then search/read exact files before editing. Use workspace-relative paths. Use apply_patch for code edits; it supports exact single-file replacement and multi-file Codex-style/unified patches. For new standalone generated content, pick a descriptive non-conflicting filename and avoid overwriting unless explicitly requested.`
|
package/src/command-policy.js
CHANGED
|
@@ -81,9 +81,13 @@ const GIT_WORKFLOW_PATTERNS = [
|
|
|
81
81
|
/^git\s+branch\s+[A-Za-z0-9][-\w./]*$/,
|
|
82
82
|
/^git\s+switch\s+(?:-c\s+)?[A-Za-z0-9][-\w./]*$/,
|
|
83
83
|
/^git\s+checkout\s+-b\s+[A-Za-z0-9][-\w./]*$/,
|
|
84
|
+
/^git\s+checkout\s+[A-Za-z0-9][-\w./]*$/,
|
|
84
85
|
/^git\s+merge\s+--ff-only\s+[A-Za-z0-9][-\w./]*$/,
|
|
85
86
|
/^git\s+merge\s+--no-ff\s+--no-edit\s+[A-Za-z0-9][-\w./]*$/,
|
|
87
|
+
/^git\s+merge\s+--no-ff\s+[A-Za-z0-9][-\w./]*\s+--no-edit$/,
|
|
88
|
+
/^git\s+merge\s+--no-edit\s+--no-ff\s+[A-Za-z0-9][-\w./]*$/,
|
|
86
89
|
/^git\s+merge\s+[A-Za-z0-9][-\w./]*\s+--no-ff\s+--no-edit$/,
|
|
90
|
+
/^git\s+merge\s+[A-Za-z0-9][-\w./]*\s+--no-edit\s+--no-ff$/,
|
|
87
91
|
/^git\s+fetch(?:\s+[-\w./:=]+)*$/,
|
|
88
92
|
/^git\s+pull\s+--ff-only(?:\s+[-\w./:=]+)*$/,
|
|
89
93
|
/^git\s+push(?:\s+[-\w./:=]+)*$/,
|
package/src/model-client.js
CHANGED
|
@@ -512,7 +512,7 @@ export async function createPlan(client, config, state) {
|
|
|
512
512
|
? `Shell tool is enabled in ${config.commandCwd}. Host platform: ${platformLabel(platform)}. In Docker, this path is mounted as /workspace with persistent /aginti-env and /aginti-cache mounts. Use relative paths or /workspace paths, not absolute host temp paths. Sandbox mode: ${config.sandboxMode}. Package install policy: ${config.packageInstallPolicy}. For npm/pip/conda/venv setup, explain the need and wait for approval unless policy is allow. Do not run npx aginti, npm exec aginti, or nested aginti diagnostics from this shell; they may resolve stale project packages or create recursive agent sessions. On native Windows host mode, prefer PowerShell/cmd-compatible commands or WSL/Docker for bash-like toolchains.`
|
|
513
513
|
: "",
|
|
514
514
|
config.allowShellTool
|
|
515
|
-
? "Host tmux tools are enabled for long-running sessions. Plan to use tmux_start_session for durable jobs, tmux_capture_pane to monitor, tmux_send_keys to interact after capture, and tmux_list_sessions to discover existing sessions. Do not install or run tmux inside Docker run_command containers; those containers are short-lived and cannot preserve tmux servers. In Docker sandbox mode, tmux startup/send commands are still workspace-bound: use relative project paths, not absolute host paths outside the workspace. In host mode, tmux startup/send command text follows the same host shell policy as run_command; if blocked, present the suggested approval/rerun path instead of trying tmux as a workaround. Ask for --sandbox-mode host --allow-destructive before trusted whole-host tmux work."
|
|
515
|
+
? "Host tmux tools are enabled for long-running sessions. Plan to use tmux_start_session for durable jobs, tmux_capture_pane to monitor, tmux_send_keys to interact after capture, and tmux_list_sessions to discover existing sessions. Do not install or run tmux inside Docker run_command containers; those containers are short-lived and cannot preserve tmux servers. In Docker sandbox mode, tmux startup/send commands are still workspace-bound and shell-pane text follows the same Docker workspace command policy as run_command: use relative project paths, not absolute host paths outside the workspace, and do not use tmux as a workaround for package installs, destructive git rewrites, or broad shell commands. In host mode, tmux startup/send command text follows the same host shell policy as run_command; if blocked, present the suggested approval/rerun path instead of trying tmux as a workaround. Ask for --sandbox-mode host --allow-destructive before trusted whole-host tmux work."
|
|
516
516
|
: "",
|
|
517
517
|
config.allowFileTools
|
|
518
518
|
? `Workspace file tools are enabled in ${config.commandCwd}: inspect_project, list_files, read_file, search_files, write_file, apply_patch, open_workspace_file, preview_workspace. For large or unfamiliar repos, plan to call inspect_project first, then search/read AGINTI.md/AGENTS.md/README/manifests and exact files. apply_patch supports exact single-file replacements and Codex-style/unified multi-file patches; prefer it for edits after reading relevant context. Keep all paths workspace-relative, for example plot_fx.svg or docs/report.tex, and avoid secrets. For newly generated standalone prose/docs/stories/assets, choose a descriptive non-conflicting filename from the topic/language instead of generic names like story.txt or output.txt; do not overwrite existing files unless the user explicitly asked to update/replace/overwrite that file. For generated local HTML/SVG/PDF/static sites, plan to use open_workspace_file or preview_workspace rather than starting a localhost server inside Docker.`
|
package/src/task-profiles.js
CHANGED
|
@@ -255,7 +255,7 @@ export const TASK_PROFILES = {
|
|
|
255
255
|
id: "github",
|
|
256
256
|
label: "GitHub maintenance",
|
|
257
257
|
prompt:
|
|
258
|
-
"Bias toward safe git and GitHub maintenance while still fixing code/docs when asked. Always inspect git status and remotes first, separate unrelated changes, run relevant checks before commits, use gh when available for PR/issues/releases, prefer fast-forward pulls, and stop on conflicts or ambiguous history. For local workflow practice, use a disposable subdirectory, set only local git identity, avoid real remotes unless explicitly requested, and describe fast-forward, non-fast-forward merge, and rebase evidence accurately.",
|
|
258
|
+
"Bias toward safe git and GitHub maintenance while still fixing code/docs when asked. Always inspect git status and remotes first, separate unrelated changes, run relevant checks before commits, use gh when available for PR/issues/releases, prefer fast-forward pulls, and stop on conflicts or ambiguous history. For local workflow practice, use a disposable subdirectory, set only local git identity, avoid real remotes unless explicitly requested, prefer `git switch <branch>`/`git checkout <branch>` for branch changes, use `git merge --ff-only <branch>` for fast-forward evidence, use `git merge --no-ff --no-edit <branch>` for intentional merge commits, avoid plain `git merge <branch>`, and describe fast-forward, non-fast-forward merge, and rebase evidence accurately.",
|
|
259
259
|
tools: ["shell", "files", "web_search", "inspect_project"],
|
|
260
260
|
},
|
|
261
261
|
word: {
|
package/src/tmux-tools.js
CHANGED
|
@@ -153,6 +153,36 @@ function checkHostShellPolicyForTmuxText(text = "", config = {}, label = "tmux t
|
|
|
153
153
|
};
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
+
function shouldApplyDockerShellPolicy(config = {}) {
|
|
157
|
+
return Boolean(config.useDockerSandbox && config.sandboxMode === "docker-workspace");
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function isShellPaneCommand(command = "") {
|
|
161
|
+
return /^(?:ba|z|fi|da|k)?sh$|^fish$/.test(String(command || "").trim());
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async function getPaneCurrentCommand(target) {
|
|
165
|
+
const result = await runTmux(["display-message", "-p", "-t", target, "#{pane_current_command}"], {
|
|
166
|
+
timeout: 4000,
|
|
167
|
+
maxBuffer: 16 * 1024,
|
|
168
|
+
});
|
|
169
|
+
if (!result.ok) return "";
|
|
170
|
+
return String(result.stdout || "").trim();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function checkDockerShellPolicyForTmuxText(text = "", config = {}, label = "tmux text") {
|
|
174
|
+
const command = String(text || "").trim();
|
|
175
|
+
if (!command || !shouldApplyDockerShellPolicy(config)) return { ok: true };
|
|
176
|
+
const policy = evaluateCommandPolicy(command, config);
|
|
177
|
+
if (policy.allowed) return { ok: true, category: policy.category };
|
|
178
|
+
return {
|
|
179
|
+
ok: false,
|
|
180
|
+
reason: `${label} is blocked by the same Docker workspace shell policy as run_command: ${policy.reason}`,
|
|
181
|
+
category: policy.category || "tmux",
|
|
182
|
+
needsApproval: policy.needsApproval,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
156
186
|
function parseSessions(stdout = "") {
|
|
157
187
|
return String(stdout || "")
|
|
158
188
|
.split(/\r?\n/)
|
|
@@ -266,6 +296,25 @@ export async function sendTmuxKeys(args = {}, config = {}) {
|
|
|
266
296
|
needsApproval: hostPolicy.needsApproval,
|
|
267
297
|
};
|
|
268
298
|
}
|
|
299
|
+
const keyArgsForPolicy = [...keys];
|
|
300
|
+
if (enter) keyArgsForPolicy.push("Enter");
|
|
301
|
+
if (text && keyArgsForPolicy.includes("Enter") && shouldApplyDockerShellPolicy(config)) {
|
|
302
|
+
const paneCommand = await getPaneCurrentCommand(target.target);
|
|
303
|
+
if (isShellPaneCommand(paneCommand)) {
|
|
304
|
+
const dockerPolicy = checkDockerShellPolicyForTmuxText(text, config, "tmux text");
|
|
305
|
+
if (!dockerPolicy.ok) {
|
|
306
|
+
return {
|
|
307
|
+
ok: false,
|
|
308
|
+
toolName: "tmux_send_keys",
|
|
309
|
+
blocked: true,
|
|
310
|
+
reason: dockerPolicy.reason,
|
|
311
|
+
category: dockerPolicy.category,
|
|
312
|
+
needsApproval: dockerPolicy.needsApproval,
|
|
313
|
+
paneCommand,
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
269
318
|
for (const key of keys) {
|
|
270
319
|
if (!ALLOWED_KEYS.has(key)) {
|
|
271
320
|
return { ok: false, toolName: "tmux_send_keys", blocked: true, reason: `Unsupported tmux key: ${key}` };
|
|
@@ -321,6 +370,17 @@ export async function startTmuxSession(args = {}, config = {}) {
|
|
|
321
370
|
if (!workspaceBound.ok) {
|
|
322
371
|
return { ok: false, toolName: "tmux_start_session", blocked: true, reason: workspaceBound.reason };
|
|
323
372
|
}
|
|
373
|
+
const dockerPolicy = checkDockerShellPolicyForTmuxText(command, config, "tmux startup command");
|
|
374
|
+
if (!dockerPolicy.ok) {
|
|
375
|
+
return {
|
|
376
|
+
ok: false,
|
|
377
|
+
toolName: "tmux_start_session",
|
|
378
|
+
blocked: true,
|
|
379
|
+
reason: dockerPolicy.reason,
|
|
380
|
+
category: dockerPolicy.category,
|
|
381
|
+
needsApproval: dockerPolicy.needsApproval,
|
|
382
|
+
};
|
|
383
|
+
}
|
|
324
384
|
const hostPolicy = checkHostShellPolicyForTmuxText(command, config, "tmux startup command");
|
|
325
385
|
if (!hostPolicy.ok) {
|
|
326
386
|
return {
|
|
@@ -402,6 +462,15 @@ export function checkTmuxToolUse(toolName, args = {}, config = {}) {
|
|
|
402
462
|
}
|
|
403
463
|
const workspaceBound = checkWorkspaceBoundTmuxText(command, config, "tmux startup command");
|
|
404
464
|
if (!workspaceBound.ok) return { allowed: false, reason: workspaceBound.reason, category: "tmux" };
|
|
465
|
+
const dockerPolicy = checkDockerShellPolicyForTmuxText(command, config, "tmux startup command");
|
|
466
|
+
if (!dockerPolicy.ok) {
|
|
467
|
+
return {
|
|
468
|
+
allowed: false,
|
|
469
|
+
reason: dockerPolicy.reason,
|
|
470
|
+
category: dockerPolicy.category || "tmux",
|
|
471
|
+
needsApproval: dockerPolicy.needsApproval,
|
|
472
|
+
};
|
|
473
|
+
}
|
|
405
474
|
const hostPolicy = checkHostShellPolicyForTmuxText(command, config, "tmux startup command");
|
|
406
475
|
if (!hostPolicy.ok) {
|
|
407
476
|
return {
|