@wrongstack/core 0.283.1 → 0.284.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{compactor-BxddyCFu.d.ts → compactor-DQLL4HTo.d.ts} +1 -1
- package/dist/{config-DkCbA3Bw.d.ts → config-MRqn1V-u.d.ts} +130 -22
- package/dist/coordination/index.d.ts +43 -20
- package/dist/coordination/index.js +1744 -912
- package/dist/coordination/index.js.map +1 -1
- package/dist/{default-config-Buho8yge.d.ts → default-config-B79_gJYv.d.ts} +7 -0
- package/dist/defaults/index.d.ts +25 -29
- package/dist/defaults/index.js +2546 -7396
- package/dist/defaults/index.js.map +1 -1
- package/dist/{director-state-B_GPa78Q.d.ts → director-state-CMS_bMs4.d.ts} +2 -0
- package/dist/{events-KmxSmvho.d.ts → events-Bgnh43r9.d.ts} +27 -10
- package/dist/execution/index.d.ts +15 -16
- package/dist/execution/index.js +534 -140
- package/dist/execution/index.js.map +1 -1
- package/dist/execution/prompt-enhancer.d.ts +1 -1
- package/dist/extension/index.d.ts +6 -6
- package/dist/{global-mailbox-rWVt8YlO.d.ts → global-mailbox-sZwyI6CS.d.ts} +13 -2
- package/dist/{goal-store-8owBXJT2.d.ts → goal-store-Datpp-ar.d.ts} +1 -1
- package/dist/hq/index.d.ts +6 -6
- package/dist/hq/index.js +58 -7
- package/dist/hq/index.js.map +1 -1
- package/dist/{index-BhCteHAF.d.ts → index--Gm41aBJ.d.ts} +26 -11
- package/dist/{index-BEFWNZYs.d.ts → index-CbyuOE5y.d.ts} +5 -1
- package/dist/index.d.ts +50 -1015
- package/dist/index.js +21028 -27775
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +9 -7
- package/dist/infrastructure/index.js +7 -2
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/kernel/index.d.ts +11 -11
- package/dist/kernel/index.js.map +1 -1
- package/dist/{mcp-servers-BUx9A_AQ.d.ts → mcp-servers-DEV4s6Ks.d.ts} +3 -3
- package/dist/models/index.d.ts +4 -4
- package/dist/models/index.js +18 -3
- package/dist/models/index.js.map +1 -1
- package/dist/{agent-subagent-runner-BsuWhB28.d.ts → multi-agent-coordinator-4RCRZKjN.d.ts} +417 -9
- package/dist/{null-fleet-bus-D4e9R7Qc.d.ts → null-fleet-bus-CFoNVQEK.d.ts} +53 -12
- package/dist/observability/index.d.ts +3 -3
- package/dist/{parallel-eternal-engine-iY2uxocj.d.ts → parallel-eternal-engine-HUrtePLd.d.ts} +4 -5
- package/dist/{permission-B6YAtNFz.d.ts → permission-ByDKXEcG.d.ts} +1 -1
- package/dist/{pipeline-ixSFe5jg.d.ts → pipeline-DGDyIohT.d.ts} +28 -7
- package/dist/{provider-model-resolve-DIxKL_T-.d.ts → provider-model-resolve-o2hHLs79.d.ts} +3 -3
- package/dist/{provider-runner-oQhDaZmH.d.ts → provider-runner-ChL-kVg6.d.ts} +3 -3
- package/dist/{retry-policy-V67lBOJz.d.ts → retry-policy-CQ7KwXJa.d.ts} +2 -2
- package/dist/{secret-vault-D7jeyXUQ.d.ts → secret-vault-DxohkUBc.d.ts} +3 -2
- package/dist/security/index.d.ts +4 -4
- package/dist/security/index.js +232 -2
- package/dist/security/index.js.map +1 -1
- package/dist/{selector-Bx2HgUkU.d.ts → selector-D8O6B_Rm.d.ts} +1 -1
- package/dist/{session-event-bridge-Bkp7ORfc.d.ts → session-event-bridge-D_z_mBwk.d.ts} +3 -3
- package/dist/{session-reader-B-Fi9L6I.d.ts → session-reader-7Esxrkpw.d.ts} +1 -1
- package/dist/storage/index.d.ts +77 -39
- package/dist/storage/index.js +1223 -288
- package/dist/storage/index.js.map +1 -1
- package/dist/tasking/index.d.ts +124 -0
- package/dist/tasking/index.js +492 -0
- package/dist/tasking/index.js.map +1 -0
- package/dist/{todos-checkpoint-BwCrj4Cb.d.ts → todos-checkpoint-FY7PjmMx.d.ts} +13 -4
- package/dist/{tool-LVSLiE1s.d.ts → tool-BNlnIJvo.d.ts} +216 -17
- package/dist/{tool-executor-kElSEgO0.d.ts → tool-executor-CckSCM5E.d.ts} +12 -15
- package/dist/tools/index.d.ts +2 -2
- package/dist/tools/index.js.map +1 -1
- package/dist/types/index.d.ts +94 -19
- package/dist/types/index.js +76 -12
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +44 -10
- package/dist/utils/index.js +106 -17
- package/dist/utils/index.js.map +1 -1
- package/dist/{worktree-manager-BjyAW30D.d.ts → worktree-manager-DzwxKE35.d.ts} +1 -1
- package/instructions/coordination/subagent-baseline.md +5 -0
- package/instructions/llm/autonomy-brain.md +3 -2
- package/instructions/system.md +4 -0
- package/package.json +10 -3
- package/dist/multi-agent-coordinator-CrjeTB9i.d.ts +0 -357
- package/dist/sdd/index.d.ts +0 -1993
- package/dist/sdd/index.js +0 -9500
- package/dist/sdd/index.js.map +0 -1
- package/dist/spec-TBi3Jr6T.d.ts +0 -78
package/dist/{parallel-eternal-engine-iY2uxocj.d.ts → parallel-eternal-engine-HUrtePLd.d.ts}
RENAMED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { A as Agent, a as AgentFactory } from './agent-
|
|
2
|
-
import { B as BrainArbiter, E as EventBus } from './events-
|
|
3
|
-
import { C as Compactor } from './compactor-
|
|
4
|
-
import { J as JournalEntry } from './goal-store-
|
|
5
|
-
import { D as DispatchClassifier, a as DefaultMultiAgentCoordinator } from './multi-agent-coordinator-CrjeTB9i.js';
|
|
1
|
+
import { A as Agent, a as AgentFactory, D as DispatchClassifier, b as DefaultMultiAgentCoordinator } from './multi-agent-coordinator-4RCRZKjN.js';
|
|
2
|
+
import { B as BrainArbiter, E as EventBus } from './events-Bgnh43r9.js';
|
|
3
|
+
import { C as Compactor } from './compactor-DQLL4HTo.js';
|
|
4
|
+
import { J as JournalEntry } from './goal-store-Datpp-ar.js';
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* Design Studio — curated frontend/mobile UI design kits.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { g as Tool, s as TextBlock, i as ContentBlock } from './tool-
|
|
1
|
+
import { g as Tool, s as TextBlock, i as ContentBlock } from './tool-BNlnIJvo.js';
|
|
2
2
|
import { a as MailboxAgentStatus } from './mailbox-types-BGZWrYTJ.js';
|
|
3
|
-
import { H as HookEvent, f as HookMatcher, I as InProcessHook, S as ShellHook,
|
|
3
|
+
import { H as HookEvent, f as HookMatcher, I as InProcessHook, g as HookRegistrationOptions, S as ShellHook, h as HttpHook, C as ConfiguredHook, i as HookEntry, T as ToolResultRenderMode } from './config-MRqn1V-u.js';
|
|
4
4
|
|
|
5
5
|
/** Model capabilities relevant to prompt composition. */
|
|
6
6
|
interface ModelCapabilities {
|
|
@@ -31,10 +31,29 @@ interface BuildContext {
|
|
|
31
31
|
*/
|
|
32
32
|
onlineAgents?: MailboxAgentStatus[] | undefined;
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Stability regions for the system prompt.
|
|
36
|
+
*
|
|
37
|
+
* `core` and `session` form the provider-cache prefix and must remain byte-for-byte
|
|
38
|
+
* stable after the first request in a session. `volatile` is appended at request
|
|
39
|
+
* time and may change between turns without rewriting that prefix.
|
|
40
|
+
*/
|
|
41
|
+
interface SystemPromptRegions {
|
|
42
|
+
readonly core: readonly TextBlock[];
|
|
43
|
+
readonly session: readonly TextBlock[];
|
|
44
|
+
readonly volatile: readonly TextBlock[];
|
|
45
|
+
}
|
|
46
|
+
declare function flattenSystemPromptRegions(regions: SystemPromptRegions): TextBlock[];
|
|
34
47
|
interface SystemPromptBuilder {
|
|
35
48
|
build(ctx: BuildContext): Promise<TextBlock[]>;
|
|
49
|
+
/** Region-aware build used by hosts that enforce prompt-prefix stability. */
|
|
50
|
+
buildRegions?(ctx: BuildContext): Promise<SystemPromptRegions>;
|
|
36
51
|
}
|
|
37
52
|
|
|
53
|
+
interface LoadConfiguredHooksOptions {
|
|
54
|
+
/** Load only trusted hooks that remain active under `--no-hooks`. */
|
|
55
|
+
policyOnly?: boolean | undefined;
|
|
56
|
+
}
|
|
38
57
|
/**
|
|
39
58
|
* Registry of lifecycle hooks (both in-process and shell). One instance is
|
|
40
59
|
* shared per session: the boot path loads `config.hooks` as shell entries and
|
|
@@ -44,14 +63,16 @@ interface SystemPromptBuilder {
|
|
|
44
63
|
declare class HookRegistry {
|
|
45
64
|
private readonly entries;
|
|
46
65
|
/** Register an in-process hook. Returns an unsubscribe function. */
|
|
47
|
-
registerInProcess(event: HookEvent, matcher: HookMatcher | undefined, hook: InProcessHook, owner?: string | undefined): () => void;
|
|
66
|
+
registerInProcess(event: HookEvent, matcher: HookMatcher | undefined, hook: InProcessHook, owner?: string | undefined, options?: HookRegistrationOptions): () => void;
|
|
48
67
|
/**
|
|
49
68
|
* Register a single shell hook. The hook is owned by the runtime (no plugin
|
|
50
69
|
* name) — it survives plugin uninstalls. Returns an unsubscribe function.
|
|
51
70
|
*/
|
|
52
71
|
registerShell(event: HookEvent, hook: ShellHook): () => void;
|
|
53
|
-
/**
|
|
54
|
-
|
|
72
|
+
/** Register a native HTTP hook. */
|
|
73
|
+
registerHttp(event: HookEvent, hook: HttpHook): () => void;
|
|
74
|
+
/** Bulk-load command/HTTP hooks from a `config.hooks` map. */
|
|
75
|
+
loadShellHooks(hooks: Partial<Record<HookEvent, ConfiguredHook[]>> | undefined, options?: LoadConfiguredHooksOptions): void;
|
|
55
76
|
/**
|
|
56
77
|
* Atomically replace the shell-hook set: drop every currently-registered
|
|
57
78
|
* shell entry, then load the supplied `config.hooks` map. In-process
|
|
@@ -65,7 +86,7 @@ declare class HookRegistry {
|
|
|
65
86
|
* with the same map yields the same registry state (callers should still
|
|
66
87
|
* guard at the change-detection layer to avoid wasted work).
|
|
67
88
|
*/
|
|
68
|
-
replaceShellHooks(hooks: Partial<Record<HookEvent,
|
|
89
|
+
replaceShellHooks(hooks: Partial<Record<HookEvent, ConfiguredHook[]>> | undefined, options?: LoadConfiguredHooksOptions): void;
|
|
69
90
|
/** All entries registered for an event, in registration order. */
|
|
70
91
|
list(event: HookEvent): readonly HookEntry[];
|
|
71
92
|
/** True when any entry is registered for the event. */
|
|
@@ -307,4 +328,4 @@ declare class Pipeline<T> {
|
|
|
307
328
|
private ensureUnique;
|
|
308
329
|
}
|
|
309
330
|
|
|
310
|
-
export { type BuildContext as B, Container as C, type Decorator as D, type Factory as F, HookRegistry as H, type MiddlewareHandler as M, type NextFn as N, Pipeline as P, type ReadonlyPipeline as R, type SystemPromptBuilder as S, type Token as T, type Renderer as a, type Middleware as b, type ModelCapabilities as c, type
|
|
331
|
+
export { type BuildContext as B, Container as C, type Decorator as D, type Factory as F, HookRegistry as H, type MiddlewareHandler as M, type NextFn as N, Pipeline as P, type ReadonlyPipeline as R, type SystemPromptBuilder as S, type Token as T, type Renderer as a, type Middleware as b, type ModelCapabilities as c, type SystemPromptRegions as d, type BindOptions as e, type PipelineOptions as f, flattenSystemPromptRegions as g, hookMatcherMatches as h };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { P as Provider, M as Message } from './tool-
|
|
2
|
-
import { M as MessageSelector, S as SelectorResult } from './selector-
|
|
1
|
+
import { P as Provider, M as Message } from './tool-BNlnIJvo.js';
|
|
2
|
+
import { M as MessageSelector, S as SelectorResult } from './selector-D8O6B_Rm.js';
|
|
3
3
|
import { M as ModeStore, a as ModeConfig, b as Mode } from './mode-CZlO9iU1.js';
|
|
4
|
-
import { M as ModelsRegistry, c as ModelsDevPayload, d as ResolvedProvider, R as ResolvedModel, W as WireFamily, e as ModelsDevModel } from './config-
|
|
4
|
+
import { M as ModelsRegistry, c as ModelsDevPayload, d as ResolvedProvider, R as ResolvedModel, W as WireFamily, e as ModelsDevModel } from './config-MRqn1V-u.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Offline **floor** for the ChatGPT "Sign in with ChatGPT" (`openai-codex`)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { E as EventBus } from './events-
|
|
1
|
+
import { E as EventBus } from './events-Bgnh43r9.js';
|
|
2
2
|
import { L as Logger } from './logger-B63L5bTg.js';
|
|
3
3
|
import { T as Tracer } from './observability-D-HZN_mF.js';
|
|
4
|
-
import { P as Provider, c as Request, d as Context, e as Response } from './tool-
|
|
5
|
-
import { R as RetryPolicy } from './retry-policy-
|
|
4
|
+
import { P as Provider, c as Request, d as Context, e as Response } from './tool-BNlnIJvo.js';
|
|
5
|
+
import { R as RetryPolicy } from './retry-policy-CQ7KwXJa.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Options passed to a ProviderRunner when calling the provider.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as Context, e as Response, h as ProviderError } from './tool-
|
|
1
|
+
import { d as Context, e as Response, h as ProviderError } from './tool-BNlnIJvo.js';
|
|
2
2
|
|
|
3
3
|
type RecoveryDecision = {
|
|
4
4
|
/**
|
|
@@ -32,7 +32,7 @@ interface ErrorHandler {
|
|
|
32
32
|
*/
|
|
33
33
|
recover(err: unknown, ctx: Context): Promise<RecoveryDecision | null>;
|
|
34
34
|
classify(err: unknown): {
|
|
35
|
-
kind: 'rate_limit' | 'overloaded' | 'server' | 'client' | 'network' | 'abort' | 'context_overflow' | 'unknown';
|
|
35
|
+
kind: 'rate_limit' | 'overloaded' | 'server' | 'client' | 'network' | 'abort' | 'context_overflow' | 'content_filter' | 'unknown';
|
|
36
36
|
retryable: boolean;
|
|
37
37
|
};
|
|
38
38
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { g as Tool, d as Context } from './tool-
|
|
1
|
+
import { g as Tool, d as Context } from './tool-BNlnIJvo.js';
|
|
2
2
|
import { I as InputReader } from './input-reader-E-ffP2ee.js';
|
|
3
|
-
import { P as PermissionPolicy, a as PermissionDecision } from './permission-
|
|
3
|
+
import { P as PermissionPolicy, a as PermissionDecision } from './permission-ByDKXEcG.js';
|
|
4
4
|
import { S as SecretScrubber } from './secret-scrubber-3MHDDAtm.js';
|
|
5
5
|
import { L as Logger } from './logger-B63L5bTg.js';
|
|
6
6
|
import { R as RotatableSecretVault, S as SecretVault } from './secret-vault-BAKpgFw_.js';
|
|
@@ -102,6 +102,7 @@ declare class DefaultPermissionPolicy implements PermissionPolicy {
|
|
|
102
102
|
evaluate(tool: Tool, input: unknown, ctx: Context): Promise<PermissionDecision>;
|
|
103
103
|
private isDestructiveByCapability;
|
|
104
104
|
private isDestructiveYoloCall;
|
|
105
|
+
private isSensitiveReadCall;
|
|
105
106
|
trust(rule: {
|
|
106
107
|
tool: string;
|
|
107
108
|
pattern: string;
|
package/dist/security/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { A as AutoApprovePermissionPolicy, a as DefaultPermissionPolicy, b as DefaultSecretScrubber, D as DefaultSecretVault, P as PermissionPolicyOptions, S as SecretVaultOptions, d as decryptConfigSecrets, e as encryptConfigSecrets, i as isSecretField, m as migratePlaintextSecrets, r as rewriteConfigEncrypted, c as rotateConfigKeys } from '../secret-vault-
|
|
2
|
-
export { D as DANGEROUS_FOR_SUBAGENTS, T as ToolCapabilities, a as ToolCapability, g as getDangerousCapabilities, h as hasCapability, b as hasDangerousCapabilityForSubagents } from '../index-
|
|
3
|
-
import '../tool-
|
|
1
|
+
export { A as AutoApprovePermissionPolicy, a as DefaultPermissionPolicy, b as DefaultSecretScrubber, D as DefaultSecretVault, P as PermissionPolicyOptions, S as SecretVaultOptions, d as decryptConfigSecrets, e as encryptConfigSecrets, i as isSecretField, m as migratePlaintextSecrets, r as rewriteConfigEncrypted, c as rotateConfigKeys } from '../secret-vault-DxohkUBc.js';
|
|
2
|
+
export { D as DANGEROUS_FOR_SUBAGENTS, T as ToolCapabilities, a as ToolCapability, g as getDangerousCapabilities, h as hasCapability, b as hasDangerousCapabilityForSubagents } from '../index-CbyuOE5y.js';
|
|
3
|
+
import '../tool-BNlnIJvo.js';
|
|
4
4
|
import '../input-reader-E-ffP2ee.js';
|
|
5
|
-
import '../permission-
|
|
5
|
+
import '../permission-ByDKXEcG.js';
|
|
6
6
|
import '../secret-scrubber-3MHDDAtm.js';
|
|
7
7
|
import '../logger-B63L5bTg.js';
|
|
8
8
|
import '../secret-vault-BAKpgFw_.js';
|
package/dist/security/index.js
CHANGED
|
@@ -1131,6 +1131,10 @@ var ToolCapabilities = {
|
|
|
1131
1131
|
SUBAGENT_SPAWN: "subagent.spawn",
|
|
1132
1132
|
/** Can inspect fleet/subagent coordination state without mutating it. */
|
|
1133
1133
|
COORDINATION_FLEET_READ: "coordination.fleet.read",
|
|
1134
|
+
/** Can publish attributed, schema-checked events onto the fleet bus. */
|
|
1135
|
+
COORDINATION_FLEET_EMIT: "coordination.fleet.emit",
|
|
1136
|
+
/** Can submit a task-local structured result to the parent Director. */
|
|
1137
|
+
COORDINATION_RESULT_SUBMIT: "coordination.result.submit",
|
|
1134
1138
|
/** Can read or write inter-agent mailbox messages. */
|
|
1135
1139
|
COORDINATION_MAIL: "coordination.mail",
|
|
1136
1140
|
/** Can schedule, inspect, or cancel in-session cron jobs. */
|
|
@@ -1167,7 +1171,8 @@ var DANGEROUS_FOR_SUBAGENTS = [
|
|
|
1167
1171
|
ToolCapabilities.PACKAGE_INSTALL,
|
|
1168
1172
|
// Read-only fleet visibility (fleet_status) — peer awareness has no blast
|
|
1169
1173
|
// radius and every fleet worker should coordinate around its peers.
|
|
1170
|
-
ToolCapabilities.COORDINATION_FLEET_READ
|
|
1174
|
+
ToolCapabilities.COORDINATION_FLEET_READ,
|
|
1175
|
+
ToolCapabilities.COORDINATION_RESULT_SUBMIT
|
|
1171
1176
|
];
|
|
1172
1177
|
function hasDangerousCapabilityForSubagents(toolOrCaps) {
|
|
1173
1178
|
if (!toolOrCaps) return false;
|
|
@@ -1239,6 +1244,11 @@ var CATASTROPHIC_PATTERNS = [
|
|
|
1239
1244
|
/:\(\)\s*\{\s*:\|:&\s*\}\s*;/
|
|
1240
1245
|
// classic fork bomb
|
|
1241
1246
|
];
|
|
1247
|
+
var HIGH_IMPACT_PATTERNS = [
|
|
1248
|
+
/\b(?:curl|wget|fetch|httpie|http|irm|iwr|Invoke-WebRequest|Invoke-RestMethod)\b[\s\S]{0,300}\|\s*(?:sudo\s+)?(?:sh|bash|zsh|fish|pwsh|powershell|iex|Invoke-Expression)\b/i,
|
|
1249
|
+
/\b(?:powershell|pwsh)(?:\.exe)?\b[\s\S]{0,120}-(?:enc|encodedcommand)\b/i,
|
|
1250
|
+
/\b(?:shutdown|reboot)\b/i
|
|
1251
|
+
];
|
|
1242
1252
|
var CATASTROPHIC_POSIX_ROOTS = /* @__PURE__ */ new Set([
|
|
1243
1253
|
"/etc",
|
|
1244
1254
|
"/usr",
|
|
@@ -1286,6 +1296,121 @@ function pathLooksInsideProject(rawPath, projectRoot) {
|
|
|
1286
1296
|
function tokenizeShell(command) {
|
|
1287
1297
|
return command.match(/"[^"]*"|'[^']*'|\S+/g)?.map((token) => token.replace(/^['"]|['"]$/g, "")) ?? [];
|
|
1288
1298
|
}
|
|
1299
|
+
function commandSegment(tokens, start) {
|
|
1300
|
+
const out = [];
|
|
1301
|
+
for (let i = start; i < tokens.length; i++) {
|
|
1302
|
+
const token = tokens[i];
|
|
1303
|
+
if (token === void 0 || SHELL_OPERATORS.has(token)) break;
|
|
1304
|
+
out.push(token);
|
|
1305
|
+
}
|
|
1306
|
+
return out;
|
|
1307
|
+
}
|
|
1308
|
+
function hasShortFlag(args, letters) {
|
|
1309
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1310
|
+
for (const arg of args) {
|
|
1311
|
+
if (!arg.startsWith("-") || arg.startsWith("--")) continue;
|
|
1312
|
+
for (const ch of arg.replace(/^-+/, "")) seen.add(ch.toLowerCase());
|
|
1313
|
+
}
|
|
1314
|
+
return letters.split("").every((letter) => seen.has(letter));
|
|
1315
|
+
}
|
|
1316
|
+
function hasRecursiveForceDelete(command, projectRoot) {
|
|
1317
|
+
const tokens = tokenizeShell(command);
|
|
1318
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
1319
|
+
const token = tokens[i]?.toLowerCase();
|
|
1320
|
+
if (!token) continue;
|
|
1321
|
+
if (token === "rm" || token === "rmdir") {
|
|
1322
|
+
const args = commandSegment(tokens, i + 1);
|
|
1323
|
+
const recursiveForce = hasShortFlag(args, "rf") || args.some((arg) => arg === "--recursive") && args.some((arg) => arg === "--force");
|
|
1324
|
+
if (recursiveForce) {
|
|
1325
|
+
const targets = args.filter((arg) => !arg.startsWith("-") && !SHELL_OPERATORS.has(arg));
|
|
1326
|
+
if (targets.length > 0 && targets.every((target) => target.trim().length === 0)) {
|
|
1327
|
+
continue;
|
|
1328
|
+
}
|
|
1329
|
+
if (targets.length === 0) return true;
|
|
1330
|
+
if (targets.some(isCatastrophicDeleteTarget)) return true;
|
|
1331
|
+
if (targets.some((target) => !pathLooksInsideProject(target, projectRoot))) return true;
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
if (token === "remove-item" || token === "ri") {
|
|
1335
|
+
const args = commandSegment(tokens, i + 1).map((arg) => arg.toLowerCase());
|
|
1336
|
+
const recurse = args.some((arg) => arg === "-recurse" || arg === "-r");
|
|
1337
|
+
const force = args.some((arg) => arg === "-force" || arg === "-f");
|
|
1338
|
+
if (recurse && force && !args.includes("-whatif")) {
|
|
1339
|
+
const targets = args.filter((arg) => !arg.startsWith("-") && !SHELL_OPERATORS.has(arg));
|
|
1340
|
+
if (targets.length === 0) return true;
|
|
1341
|
+
if (targets.some(isCatastrophicDeleteTarget)) return true;
|
|
1342
|
+
if (targets.some((target) => !pathLooksInsideProject(target, projectRoot))) return true;
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
if (token === "rd" || token === "rmdir") {
|
|
1346
|
+
const args = commandSegment(tokens, i + 1).map((arg) => arg.toLowerCase());
|
|
1347
|
+
if (args.includes("/s")) {
|
|
1348
|
+
const targets = args.filter((arg) => !arg.startsWith("-") && !arg.startsWith("/") && !SHELL_OPERATORS.has(arg));
|
|
1349
|
+
if (targets.length === 0) return true;
|
|
1350
|
+
if (targets.some(isCatastrophicDeleteTarget)) return true;
|
|
1351
|
+
if (targets.some((target) => !pathLooksInsideProject(target, projectRoot))) return true;
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
return false;
|
|
1356
|
+
}
|
|
1357
|
+
function hasGitHistoryRewrite(command) {
|
|
1358
|
+
const tokens = tokenizeShell(command).map((token) => token.toLowerCase());
|
|
1359
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
1360
|
+
if (tokens[i] !== "git") continue;
|
|
1361
|
+
const args = commandSegment(tokens, i + 1);
|
|
1362
|
+
if (args.includes("reset") && args.some((arg) => arg === "--hard" || arg.startsWith("--hard="))) {
|
|
1363
|
+
return true;
|
|
1364
|
+
}
|
|
1365
|
+
const cleanIdx = args.indexOf("clean");
|
|
1366
|
+
if (cleanIdx >= 0) {
|
|
1367
|
+
const cleanArgs = args.slice(cleanIdx + 1);
|
|
1368
|
+
if (cleanArgs.some((arg) => arg === "-f" || arg === "--force" || /^-[a-z]*f[a-z]*$/i.test(arg))) {
|
|
1369
|
+
return true;
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
const pushIdx = args.indexOf("push");
|
|
1373
|
+
if (pushIdx >= 0) {
|
|
1374
|
+
const pushArgs = args.slice(pushIdx + 1);
|
|
1375
|
+
if (pushArgs.some(
|
|
1376
|
+
(arg) => arg === "-f" || arg === "--force" || arg === "--force-with-lease" || arg.startsWith("--force=") || arg.startsWith("--force-with-lease=")
|
|
1377
|
+
)) {
|
|
1378
|
+
return true;
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
return false;
|
|
1383
|
+
}
|
|
1384
|
+
function hasExternalPublish(command) {
|
|
1385
|
+
const tokens = tokenizeShell(command).map((token) => token.toLowerCase());
|
|
1386
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
1387
|
+
const cmd = tokens[i];
|
|
1388
|
+
if (!cmd) continue;
|
|
1389
|
+
const args = commandSegment(tokens, i + 1);
|
|
1390
|
+
if (["npm", "pnpm", "yarn", "bun"].includes(cmd) && (args.includes("publish") || args.includes("deploy"))) {
|
|
1391
|
+
return true;
|
|
1392
|
+
}
|
|
1393
|
+
if (cmd === "cargo" && (args.includes("publish") || args.includes("yank"))) return true;
|
|
1394
|
+
if ((cmd === "docker" || cmd === "podman") && args.includes("push")) return true;
|
|
1395
|
+
if (cmd === "kubectl") {
|
|
1396
|
+
const deleteIdx = args.indexOf("delete");
|
|
1397
|
+
if (deleteIdx >= 0 && (args[deleteIdx + 1] === "namespace" || args[deleteIdx + 1] === "ns")) {
|
|
1398
|
+
return true;
|
|
1399
|
+
}
|
|
1400
|
+
if (args.includes("drain")) return true;
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
return false;
|
|
1404
|
+
}
|
|
1405
|
+
function hasFindExec(command) {
|
|
1406
|
+
const tokens = tokenizeShell(command).map((token) => token.toLowerCase());
|
|
1407
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
1408
|
+
if (tokens[i] !== "find") continue;
|
|
1409
|
+
const args = commandSegment(tokens, i + 1);
|
|
1410
|
+
if (args.some((arg) => arg === "-exec" || arg === "-ok" || arg === "-execdir")) return true;
|
|
1411
|
+
}
|
|
1412
|
+
return false;
|
|
1413
|
+
}
|
|
1289
1414
|
function isCatastrophicDeleteTarget(rawTarget) {
|
|
1290
1415
|
const t = rawTarget.replace(/^['"]|['"]$/g, "").trim();
|
|
1291
1416
|
if (!t) return false;
|
|
@@ -1340,11 +1465,16 @@ function hasCatastrophicDelete(command) {
|
|
|
1340
1465
|
}
|
|
1341
1466
|
return false;
|
|
1342
1467
|
}
|
|
1343
|
-
function isClearlyDestructiveBashCommand(command,
|
|
1468
|
+
function isClearlyDestructiveBashCommand(command, projectRoot) {
|
|
1344
1469
|
const trimmed = command.trim();
|
|
1345
1470
|
if (!trimmed) return false;
|
|
1471
|
+
if (hasRecursiveForceDelete(trimmed, projectRoot)) return true;
|
|
1472
|
+
if (hasGitHistoryRewrite(trimmed)) return true;
|
|
1473
|
+
if (hasExternalPublish(trimmed)) return true;
|
|
1474
|
+
if (hasFindExec(trimmed)) return true;
|
|
1346
1475
|
if (hasCatastrophicDelete(trimmed)) return true;
|
|
1347
1476
|
if (CATASTROPHIC_PATTERNS.some((pattern) => pattern.test(trimmed))) return true;
|
|
1477
|
+
if (HIGH_IMPACT_PATTERNS.some((pattern) => pattern.test(trimmed))) return true;
|
|
1348
1478
|
return false;
|
|
1349
1479
|
}
|
|
1350
1480
|
|
|
@@ -1361,6 +1491,64 @@ function shellCommandLineFromInput(input) {
|
|
|
1361
1491
|
const renderedArgs = args.filter((arg) => typeof arg === "string").map((arg) => /\s/.test(arg) ? `"${arg.replace(/"/g, '\\"')}"` : arg);
|
|
1362
1492
|
return [command, ...renderedArgs].join(" ");
|
|
1363
1493
|
}
|
|
1494
|
+
var SENSITIVE_READ_PATHS = [
|
|
1495
|
+
/(?:^|[\\/])\.env(?:[.\w-]*)?$/i,
|
|
1496
|
+
/(?:^|[\\/])\.npmrc$/i,
|
|
1497
|
+
/(?:^|[\\/])\.pypirc$/i,
|
|
1498
|
+
/(?:^|[\\/])\.netrc$/i,
|
|
1499
|
+
/(?:^|[\\/])id_(?:rsa|dsa|ecdsa|ed25519)$/i,
|
|
1500
|
+
/(?:^|[\\/])\.aws[\\/]credentials$/i,
|
|
1501
|
+
/(?:^|[\\/])\.kube[\\/]config$/i,
|
|
1502
|
+
/(?:^|[\\/])(?:secrets?|tokens?|credentials?|private[_-]?keys?)$/i,
|
|
1503
|
+
/(?:^|[\\/])[^\\/]*(?:secret|token|credential|private[_-]?key)[^\\/]*(?:\.json|\.ya?ml|\.toml|\.ini|\.txt|\.env|\.properties|\.key|\.pem)$/i
|
|
1504
|
+
];
|
|
1505
|
+
var SHELL_READ_VERBS = /* @__PURE__ */ new Set([
|
|
1506
|
+
"cat",
|
|
1507
|
+
"type",
|
|
1508
|
+
"get-content",
|
|
1509
|
+
"gc",
|
|
1510
|
+
"more",
|
|
1511
|
+
"less",
|
|
1512
|
+
"head",
|
|
1513
|
+
"tail",
|
|
1514
|
+
"grep",
|
|
1515
|
+
"rg",
|
|
1516
|
+
"sed",
|
|
1517
|
+
"awk",
|
|
1518
|
+
"findstr",
|
|
1519
|
+
"select-string",
|
|
1520
|
+
"strings",
|
|
1521
|
+
"cp",
|
|
1522
|
+
"copy",
|
|
1523
|
+
"scp"
|
|
1524
|
+
]);
|
|
1525
|
+
function stripShellQuotes(value) {
|
|
1526
|
+
return value.replace(/^['"]|['"]$/g, "");
|
|
1527
|
+
}
|
|
1528
|
+
function pathLooksSensitive(rawPath) {
|
|
1529
|
+
const normalized = stripShellQuotes(rawPath).replace(/\\/g, "/");
|
|
1530
|
+
return SENSITIVE_READ_PATHS.some((pattern) => pattern.test(normalized));
|
|
1531
|
+
}
|
|
1532
|
+
function inputPathLooksSensitive(input) {
|
|
1533
|
+
if (!input || typeof input !== "object") return false;
|
|
1534
|
+
const obj = input;
|
|
1535
|
+
for (const key of ["path", "file", "file_path", "filePath", "target", "targetPath"]) {
|
|
1536
|
+
const value = obj[key];
|
|
1537
|
+
if (typeof value === "string" && pathLooksSensitive(value)) return true;
|
|
1538
|
+
}
|
|
1539
|
+
return false;
|
|
1540
|
+
}
|
|
1541
|
+
function shellCommandReadsSensitivePath(command) {
|
|
1542
|
+
const tokens = command.match(/"[^"]*"|'[^']*'|\S+/g)?.map((token) => stripShellQuotes(token).toLowerCase()) ?? [];
|
|
1543
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
1544
|
+
const token = tokens[i];
|
|
1545
|
+
if (!token) continue;
|
|
1546
|
+
if (!SHELL_READ_VERBS.has(token)) continue;
|
|
1547
|
+
const rest = tokens.slice(i + 1);
|
|
1548
|
+
if (rest.some((arg) => pathLooksSensitive(arg))) return true;
|
|
1549
|
+
}
|
|
1550
|
+
return false;
|
|
1551
|
+
}
|
|
1364
1552
|
var DefaultPermissionPolicy = class {
|
|
1365
1553
|
policy = {};
|
|
1366
1554
|
loaded = false;
|
|
@@ -1543,6 +1731,34 @@ var DefaultPermissionPolicy = class {
|
|
|
1543
1731
|
this._evalCache.set(cacheKey, decision);
|
|
1544
1732
|
return decision;
|
|
1545
1733
|
}
|
|
1734
|
+
if (!this.yolo && this.isSensitiveReadCall(tool, input)) {
|
|
1735
|
+
if (this.promptDelegate) {
|
|
1736
|
+
const userDecision = await this.promptDelegate(tool, input, subject ?? tool.name);
|
|
1737
|
+
if (userDecision === "always") {
|
|
1738
|
+
await this.trust({ tool: tool.name, pattern: subject ?? tool.name });
|
|
1739
|
+
return {
|
|
1740
|
+
permission: "auto",
|
|
1741
|
+
source: "user",
|
|
1742
|
+
reason: "user always-allowed sensitive read"
|
|
1743
|
+
};
|
|
1744
|
+
}
|
|
1745
|
+
if (userDecision === "deny") {
|
|
1746
|
+
await this.deny({ tool: tool.name, pattern: subject ?? tool.name });
|
|
1747
|
+
return { permission: "deny", source: "user", reason: "user denied sensitive read" };
|
|
1748
|
+
}
|
|
1749
|
+
return {
|
|
1750
|
+
permission: userDecision === "yes" ? "auto" : "deny",
|
|
1751
|
+
source: "user",
|
|
1752
|
+
reason: "sensitive read user decision"
|
|
1753
|
+
};
|
|
1754
|
+
}
|
|
1755
|
+
return {
|
|
1756
|
+
permission: "confirm",
|
|
1757
|
+
source: "default",
|
|
1758
|
+
riskTier: "standard",
|
|
1759
|
+
reason: "sensitive file read needs explicit approval"
|
|
1760
|
+
};
|
|
1761
|
+
}
|
|
1546
1762
|
if (this.yolo) {
|
|
1547
1763
|
const decision = { permission: "auto", source: "yolo" };
|
|
1548
1764
|
this._evalCache.set(cacheKey, decision);
|
|
@@ -1627,6 +1843,20 @@ var DefaultPermissionPolicy = class {
|
|
|
1627
1843
|
}
|
|
1628
1844
|
return tool.riskTier === "destructive";
|
|
1629
1845
|
}
|
|
1846
|
+
isSensitiveReadCall(tool, input) {
|
|
1847
|
+
const isReadTool = hasCapability(tool, ToolCapabilities.FS_READ) || tool.name === "read" || tool.name === "grep" || tool.name === "glob" || tool.name === "tree";
|
|
1848
|
+
if (isReadTool && inputPathLooksSensitive(input)) return true;
|
|
1849
|
+
const hasShellCap = hasCapability(tool, [
|
|
1850
|
+
ToolCapabilities.SHELL_ARBITRARY,
|
|
1851
|
+
ToolCapabilities.SHELL_RESTRICTED,
|
|
1852
|
+
ToolCapabilities.SHELL_EXEC
|
|
1853
|
+
]);
|
|
1854
|
+
if (!hasShellCap && tool.name !== "bash" && tool.name !== "shell" && tool.name !== "exec") {
|
|
1855
|
+
return false;
|
|
1856
|
+
}
|
|
1857
|
+
const command = shellCommandLineFromInput(input);
|
|
1858
|
+
return command ? shellCommandReadsSensitivePath(command) : false;
|
|
1859
|
+
}
|
|
1630
1860
|
async trust(rule) {
|
|
1631
1861
|
if (!this.loaded) await this.reload();
|
|
1632
1862
|
const entry = this.policy[rule.tool] ?? {};
|