@prestyj/cli 5.32.0 → 5.32.2
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 +3 -2
- package/assets/skills/task-list/SKILL.md +39 -0
- package/dist/app-sidecar/app-settings.js +11 -5
- package/dist/app-sidecar/app-settings.js.map +1 -1
- package/dist/app-sidecar/auth-routes.js +10 -3
- package/dist/app-sidecar/auth-routes.js.map +1 -1
- package/dist/app-sidecar/git-target.d.ts +15 -2
- package/dist/app-sidecar/git-target.js +24 -10
- package/dist/app-sidecar/git-target.js.map +1 -1
- package/dist/app-sidecar/goal-routes.js +8 -0
- package/dist/app-sidecar/goal-routes.js.map +1 -1
- package/dist/app-sidecar/history-routes.js +7 -0
- package/dist/app-sidecar/history-routes.js.map +1 -1
- package/dist/app-sidecar/history.d.ts +5 -0
- package/dist/app-sidecar/history.js.map +1 -1
- package/dist/app-sidecar/integration-routes.js +4 -0
- package/dist/app-sidecar/integration-routes.js.map +1 -1
- package/dist/app-sidecar/mcp-routes.js +1 -0
- package/dist/app-sidecar/mcp-routes.js.map +1 -1
- package/dist/app-sidecar/mcp-rows.d.ts +2 -0
- package/dist/app-sidecar/mcp-rows.js +4 -1
- package/dist/app-sidecar/mcp-rows.js.map +1 -1
- package/dist/app-sidecar/prompt-routes.js +67 -1
- package/dist/app-sidecar/prompt-routes.js.map +1 -1
- package/dist/app-sidecar/route-context.d.ts +2 -0
- package/dist/app-sidecar/run-control-routes.js +43 -3
- package/dist/app-sidecar/run-control-routes.js.map +1 -1
- package/dist/app-sidecar/session-routes.js +10 -0
- package/dist/app-sidecar/session-routes.js.map +1 -1
- package/dist/app-sidecar/task-routes.js +2 -0
- package/dist/app-sidecar/task-routes.js.map +1 -1
- package/dist/app-sidecar/trophy-manager.d.ts +15 -0
- package/dist/app-sidecar/trophy-manager.js +71 -0
- package/dist/app-sidecar/trophy-manager.js.map +1 -0
- package/dist/app-sidecar/workspace-routes.js +1 -0
- package/dist/app-sidecar/workspace-routes.js.map +1 -1
- package/dist/app-sidecar.js +157 -30
- package/dist/app-sidecar.js.map +1 -1
- package/dist/cli/auth.js +22 -1
- package/dist/cli/auth.js.map +1 -1
- package/dist/cli/mcp.js +6 -1
- package/dist/cli/mcp.js.map +1 -1
- package/dist/cli.js +13 -9
- package/dist/cli.js.map +1 -1
- package/dist/config.js +4 -2
- package/dist/config.js.map +1 -1
- package/dist/core/action-threats.d.ts +68 -0
- package/dist/core/action-threats.js +894 -0
- package/dist/core/action-threats.js.map +1 -0
- package/dist/core/agent-notifications.d.ts +18 -0
- package/dist/core/agent-notifications.js +35 -2
- package/dist/core/agent-notifications.js.map +1 -1
- package/dist/core/agent-session/verification-tracker.d.ts +21 -0
- package/dist/core/agent-session/verification-tracker.js +39 -1
- package/dist/core/agent-session/verification-tracker.js.map +1 -1
- package/dist/core/agent-session.d.ts +168 -2
- package/dist/core/agent-session.js +486 -23
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/blocked-packages-file.d.ts +33 -0
- package/dist/core/blocked-packages-file.js +274 -0
- package/dist/core/blocked-packages-file.js.map +1 -0
- package/dist/core/compaction/policy.d.ts +2 -2
- package/dist/core/compaction/policy.js +86 -43
- package/dist/core/compaction/policy.js.map +1 -1
- package/dist/core/compaction/token-estimator.d.ts +4 -1
- package/dist/core/compaction/token-estimator.js +5 -2
- package/dist/core/compaction/token-estimator.js.map +1 -1
- package/dist/core/event-bus.d.ts +10 -0
- package/dist/core/event-bus.js +2 -0
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/idle-wake.d.ts +62 -0
- package/dist/core/idle-wake.js +103 -0
- package/dist/core/idle-wake.js.map +1 -0
- package/dist/core/injection-detect.d.ts +2 -1
- package/dist/core/injection-detect.js +13 -4
- package/dist/core/injection-detect.js.map +1 -1
- package/dist/core/installed-threats.d.ts +23 -0
- package/dist/core/installed-threats.js +71 -0
- package/dist/core/installed-threats.js.map +1 -0
- package/dist/core/mcp/catalog-cache.d.ts +2 -0
- package/dist/core/mcp/catalog-cache.js +4 -0
- package/dist/core/mcp/catalog-cache.js.map +1 -1
- package/dist/core/mcp/client.d.ts +8 -0
- package/dist/core/mcp/client.js +37 -3
- package/dist/core/mcp/client.js.map +1 -1
- package/dist/core/mcp/deferred-catalog.d.ts +12 -1
- package/dist/core/mcp/deferred-catalog.js +37 -10
- package/dist/core/mcp/deferred-catalog.js.map +1 -1
- package/dist/core/mcp/index.d.ts +2 -0
- package/dist/core/mcp/index.js +1 -0
- package/dist/core/mcp/index.js.map +1 -1
- package/dist/core/mcp/tool-guard.d.ts +58 -0
- package/dist/core/mcp/tool-guard.js +215 -0
- package/dist/core/mcp/tool-guard.js.map +1 -0
- package/dist/core/network-guard.d.ts +0 -20
- package/dist/core/network-guard.js +6 -0
- package/dist/core/network-guard.js.map +1 -1
- package/dist/core/package-cooldown.d.ts +71 -0
- package/dist/core/package-cooldown.js +301 -0
- package/dist/core/package-cooldown.js.map +1 -0
- package/dist/core/package-threats.d.ts +77 -3
- package/dist/core/package-threats.js +1250 -78
- package/dist/core/package-threats.js.map +1 -1
- package/dist/core/process-manager.d.ts +54 -12
- package/dist/core/process-manager.js +233 -56
- package/dist/core/process-manager.js.map +1 -1
- package/dist/core/project-files.d.ts +15 -0
- package/dist/core/project-files.js +37 -0
- package/dist/core/project-files.js.map +1 -0
- package/dist/core/prompt-commands.js +1 -0
- package/dist/core/prompt-commands.js.map +1 -1
- package/dist/core/session-manager.d.ts +3 -1
- package/dist/core/session-manager.js +2 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -0
- package/dist/core/settings-manager.js +4 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/shell-threats.d.ts +14 -1
- package/dist/core/shell-threats.js +73 -24
- package/dist/core/shell-threats.js.map +1 -1
- package/dist/core/skill-scan.d.ts +112 -0
- package/dist/core/skill-scan.js +781 -0
- package/dist/core/skill-scan.js.map +1 -0
- package/dist/core/skills.d.ts +33 -0
- package/dist/core/skills.js +87 -16
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts +5 -1
- package/dist/core/slash-commands.js +24 -9
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/steering.d.ts +7 -0
- package/dist/core/steering.js +13 -0
- package/dist/core/steering.js.map +1 -1
- package/dist/core/style-packs/index.js +1 -1
- package/dist/core/style-packs/index.js.map +1 -1
- package/dist/core/style-packs/packs.js +2 -2
- package/dist/core/subagent-manager.js +5 -4
- package/dist/core/subagent-manager.js.map +1 -1
- package/dist/core/threat-feed.d.ts +65 -0
- package/dist/core/threat-feed.js +335 -0
- package/dist/core/threat-feed.js.map +1 -0
- package/dist/core/trophies/catalog-more.d.ts +2 -0
- package/dist/core/trophies/catalog-more.js +857 -0
- package/dist/core/trophies/catalog-more.js.map +1 -0
- package/dist/core/trophies/catalog.d.ts +4 -0
- package/dist/core/trophies/catalog.js +649 -0
- package/dist/core/trophies/catalog.js.map +1 -0
- package/dist/core/trophies/engine.d.ts +70 -0
- package/dist/core/trophies/engine.js +351 -0
- package/dist/core/trophies/engine.js.map +1 -0
- package/dist/core/trophies/store.d.ts +17 -0
- package/dist/core/trophies/store.js +113 -0
- package/dist/core/trophies/store.js.map +1 -0
- package/dist/core/trophies/types.d.ts +119 -0
- package/dist/core/trophies/types.js +78 -0
- package/dist/core/trophies/types.js.map +1 -0
- package/dist/core/verification-evidence.d.ts +10 -6
- package/dist/core/verification-evidence.js +190 -11
- package/dist/core/verification-evidence.js.map +1 -1
- package/dist/goals-agent/goals-agent.js +3 -2
- package/dist/goals-agent/goals-agent.js.map +1 -1
- package/dist/interactive.js +16 -5
- package/dist/interactive.js.map +1 -1
- package/dist/modes/acp-mode.js +8 -1
- package/dist/modes/acp-mode.js.map +1 -1
- package/dist/modes/agent-home-mode.js +13 -1
- package/dist/modes/agent-home-mode.js.map +1 -1
- package/dist/modes/rpc-mode.d.ts +2 -1
- package/dist/modes/rpc-mode.js +15 -3
- package/dist/modes/rpc-mode.js.map +1 -1
- package/dist/modes/serve-mode.js +13 -1
- package/dist/modes/serve-mode.js.map +1 -1
- package/dist/system-prompt.d.ts +8 -0
- package/dist/system-prompt.js +34 -13
- package/dist/system-prompt.js.map +1 -1
- package/dist/test-support/slow-git.d.ts +1 -0
- package/dist/test-support/slow-git.js +21 -0
- package/dist/test-support/slow-git.js.map +1 -0
- package/dist/tools/background-watch-lint.d.ts +18 -0
- package/dist/tools/background-watch-lint.js +102 -0
- package/dist/tools/background-watch-lint.js.map +1 -0
- package/dist/tools/bash.d.ts +15 -4
- package/dist/tools/bash.js +75 -47
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/checklist.d.ts +3 -3
- package/dist/tools/compress.js +45 -0
- package/dist/tools/compress.js.map +1 -1
- package/dist/tools/edit.js +5 -0
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/generate-image.d.ts +29 -6
- package/dist/tools/generate-image.js +325 -151
- package/dist/tools/generate-image.js.map +1 -1
- package/dist/tools/grep.d.ts +14 -0
- package/dist/tools/grep.js +36 -2
- package/dist/tools/grep.js.map +1 -1
- package/dist/tools/index.d.ts +5 -1
- package/dist/tools/index.js +7 -4
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/prompt-hints.d.ts +8 -1
- package/dist/tools/prompt-hints.js +22 -2
- package/dist/tools/prompt-hints.js.map +1 -1
- package/dist/tools/routine-output.d.ts +30 -0
- package/dist/tools/routine-output.js +203 -0
- package/dist/tools/routine-output.js.map +1 -0
- package/dist/tools/skill.d.ts +2 -2
- package/dist/tools/skill.js +8 -1
- package/dist/tools/skill.js.map +1 -1
- package/dist/tools/subagent-shared.js +4 -1
- package/dist/tools/subagent-shared.js.map +1 -1
- package/dist/tools/task-output.js +11 -1
- package/dist/tools/task-output.js.map +1 -1
- package/dist/tools/write.js +8 -0
- package/dist/tools/write.js.map +1 -1
- package/dist/ui/components/ModelSelector.d.ts +10 -0
- package/dist/ui/components/ModelSelector.js +51 -5
- package/dist/ui/components/ModelSelector.js.map +1 -1
- package/dist/ui/components/ToolExecution.js +2 -2
- package/dist/ui/components/ToolExecution.js.map +1 -1
- package/dist/ui/mcp.d.ts +2 -0
- package/dist/ui/mcp.js.map +1 -1
- package/dist/ui/terminal-history.js +2 -1
- package/dist/ui/terminal-history.js.map +1 -1
- package/dist/ui/tool-line-summary.js +3 -1
- package/dist/ui/tool-line-summary.js.map +1 -1
- package/dist/utils/git.d.ts +12 -3
- package/dist/utils/git.js +21 -8
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/image.d.ts +14 -0
- package/dist/utils/image.js +23 -0
- package/dist/utils/image.js.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wake an idle session when its own background work needs attention.
|
|
3
|
+
*
|
|
4
|
+
* Background alerts — a build or CI watcher that failed, a task that exited
|
|
5
|
+
* non-zero, a child agent that finished — ride the steering path, which only
|
|
6
|
+
* exists while a run is live. Once the agent has ended its turn, an alert sat
|
|
7
|
+
* in the queue until the user happened to send another message (measured: 8 of
|
|
8
|
+
* 483 runs began with a status update that had been waiting for exactly that).
|
|
9
|
+
*
|
|
10
|
+
* This starts a run for the alert instead, inside hard limits:
|
|
11
|
+
*
|
|
12
|
+
* - Never while anything else could deliver it: a live run, a run being
|
|
13
|
+
* claimed, an autopilot cycle. The alert waits for that run's next steering
|
|
14
|
+
* boundary instead, and is retried here if the run ends without draining it.
|
|
15
|
+
* - Never while the user is deciding something (a plan awaiting review).
|
|
16
|
+
* - Never after the user pressed Stop, until they send another message. Stop
|
|
17
|
+
* means "stop acting on your own", and a background exit is not a reason to
|
|
18
|
+
* override it.
|
|
19
|
+
* - At most {@link DEFAULT_MAX_WAKES_PER_PROMPT} wakes per user message, so a
|
|
20
|
+
* flapping task cannot keep the agent (and the bill) running unattended.
|
|
21
|
+
*
|
|
22
|
+
* Pure policy over injected callbacks; the host owns the run itself.
|
|
23
|
+
*/
|
|
24
|
+
/** Batch alerts that land together (a failure line, then the exit) into one run. */
|
|
25
|
+
export declare const DEFAULT_IDLE_WAKE_DEBOUNCE_MS = 2000;
|
|
26
|
+
/** Unattended wakes allowed per human prompt. */
|
|
27
|
+
export declare const DEFAULT_MAX_WAKES_PER_PROMPT = 2;
|
|
28
|
+
export type IdleWakeSkip = "stopped" | "budget" | "blocked" | "nothing-pending";
|
|
29
|
+
export interface IdleWakeDeps {
|
|
30
|
+
/** A run, a run claim, or an autopilot cycle is live and will deliver it. */
|
|
31
|
+
isBusy: () => boolean;
|
|
32
|
+
/** The user is deciding something (a plan awaiting review). */
|
|
33
|
+
isBlocked: () => boolean;
|
|
34
|
+
/** An urgent alert is still waiting to be delivered. */
|
|
35
|
+
hasPendingAlert: () => boolean;
|
|
36
|
+
/** Monotonic count of human prompts; budgets and Stop reset when it moves. */
|
|
37
|
+
humanPromptSeq: () => number;
|
|
38
|
+
/** Start the wake run; resolves when it has settled. */
|
|
39
|
+
start: () => Promise<void>;
|
|
40
|
+
/** Observability hook for skipped wakes. */
|
|
41
|
+
onSkip?: (reason: IdleWakeSkip) => void;
|
|
42
|
+
debounceMs?: number;
|
|
43
|
+
maxWakesPerPrompt?: number;
|
|
44
|
+
}
|
|
45
|
+
export declare class IdleWakeController {
|
|
46
|
+
private readonly deps;
|
|
47
|
+
private timer;
|
|
48
|
+
private budgetSeq;
|
|
49
|
+
private wakesUsed;
|
|
50
|
+
private stoppedAtSeq;
|
|
51
|
+
private starting;
|
|
52
|
+
private disposed;
|
|
53
|
+
constructor(deps: IdleWakeDeps);
|
|
54
|
+
/** An urgent alert was queued. Debounced; safe to call often. */
|
|
55
|
+
trigger(): void;
|
|
56
|
+
/** The user pressed Stop: no unattended wakes until their next message. */
|
|
57
|
+
noteStop(): void;
|
|
58
|
+
dispose(): void;
|
|
59
|
+
private cancelTimer;
|
|
60
|
+
private fire;
|
|
61
|
+
private skip;
|
|
62
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wake an idle session when its own background work needs attention.
|
|
3
|
+
*
|
|
4
|
+
* Background alerts — a build or CI watcher that failed, a task that exited
|
|
5
|
+
* non-zero, a child agent that finished — ride the steering path, which only
|
|
6
|
+
* exists while a run is live. Once the agent has ended its turn, an alert sat
|
|
7
|
+
* in the queue until the user happened to send another message (measured: 8 of
|
|
8
|
+
* 483 runs began with a status update that had been waiting for exactly that).
|
|
9
|
+
*
|
|
10
|
+
* This starts a run for the alert instead, inside hard limits:
|
|
11
|
+
*
|
|
12
|
+
* - Never while anything else could deliver it: a live run, a run being
|
|
13
|
+
* claimed, an autopilot cycle. The alert waits for that run's next steering
|
|
14
|
+
* boundary instead, and is retried here if the run ends without draining it.
|
|
15
|
+
* - Never while the user is deciding something (a plan awaiting review).
|
|
16
|
+
* - Never after the user pressed Stop, until they send another message. Stop
|
|
17
|
+
* means "stop acting on your own", and a background exit is not a reason to
|
|
18
|
+
* override it.
|
|
19
|
+
* - At most {@link DEFAULT_MAX_WAKES_PER_PROMPT} wakes per user message, so a
|
|
20
|
+
* flapping task cannot keep the agent (and the bill) running unattended.
|
|
21
|
+
*
|
|
22
|
+
* Pure policy over injected callbacks; the host owns the run itself.
|
|
23
|
+
*/
|
|
24
|
+
/** Batch alerts that land together (a failure line, then the exit) into one run. */
|
|
25
|
+
export const DEFAULT_IDLE_WAKE_DEBOUNCE_MS = 2_000;
|
|
26
|
+
/** Unattended wakes allowed per human prompt. */
|
|
27
|
+
export const DEFAULT_MAX_WAKES_PER_PROMPT = 2;
|
|
28
|
+
export class IdleWakeController {
|
|
29
|
+
deps;
|
|
30
|
+
timer = null;
|
|
31
|
+
budgetSeq = -1;
|
|
32
|
+
wakesUsed = 0;
|
|
33
|
+
stoppedAtSeq = null;
|
|
34
|
+
starting = false;
|
|
35
|
+
disposed = false;
|
|
36
|
+
constructor(deps) {
|
|
37
|
+
this.deps = deps;
|
|
38
|
+
}
|
|
39
|
+
/** An urgent alert was queued. Debounced; safe to call often. */
|
|
40
|
+
trigger() {
|
|
41
|
+
if (this.disposed || this.timer !== null)
|
|
42
|
+
return;
|
|
43
|
+
this.timer = setTimeout(() => {
|
|
44
|
+
this.timer = null;
|
|
45
|
+
void this.fire();
|
|
46
|
+
}, this.deps.debounceMs ?? DEFAULT_IDLE_WAKE_DEBOUNCE_MS);
|
|
47
|
+
this.timer.unref?.();
|
|
48
|
+
}
|
|
49
|
+
/** The user pressed Stop: no unattended wakes until their next message. */
|
|
50
|
+
noteStop() {
|
|
51
|
+
this.stoppedAtSeq = this.deps.humanPromptSeq();
|
|
52
|
+
this.cancelTimer();
|
|
53
|
+
}
|
|
54
|
+
dispose() {
|
|
55
|
+
this.disposed = true;
|
|
56
|
+
this.cancelTimer();
|
|
57
|
+
}
|
|
58
|
+
cancelTimer() {
|
|
59
|
+
if (this.timer !== null)
|
|
60
|
+
clearTimeout(this.timer);
|
|
61
|
+
this.timer = null;
|
|
62
|
+
}
|
|
63
|
+
async fire() {
|
|
64
|
+
if (this.disposed || this.starting)
|
|
65
|
+
return;
|
|
66
|
+
if (!this.deps.hasPendingAlert())
|
|
67
|
+
return this.skip("nothing-pending");
|
|
68
|
+
const seq = this.deps.humanPromptSeq();
|
|
69
|
+
if (this.stoppedAtSeq === seq)
|
|
70
|
+
return this.skip("stopped");
|
|
71
|
+
if (seq !== this.budgetSeq) {
|
|
72
|
+
this.budgetSeq = seq;
|
|
73
|
+
this.wakesUsed = 0;
|
|
74
|
+
}
|
|
75
|
+
if (this.wakesUsed >= (this.deps.maxWakesPerPrompt ?? DEFAULT_MAX_WAKES_PER_PROMPT)) {
|
|
76
|
+
return this.skip("budget");
|
|
77
|
+
}
|
|
78
|
+
if (this.deps.isBusy()) {
|
|
79
|
+
// The live run should drain it at its next steering boundary. If that
|
|
80
|
+
// run is already past its last boundary, the alert would strand — so
|
|
81
|
+
// look again shortly rather than trusting the run to have taken it.
|
|
82
|
+
this.trigger();
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (this.deps.isBlocked())
|
|
86
|
+
return this.skip("blocked");
|
|
87
|
+
this.wakesUsed += 1;
|
|
88
|
+
this.starting = true;
|
|
89
|
+
try {
|
|
90
|
+
await this.deps.start();
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
this.starting = false;
|
|
94
|
+
}
|
|
95
|
+
// An alert that landed after the wake run's last steering boundary.
|
|
96
|
+
if (this.deps.hasPendingAlert())
|
|
97
|
+
this.trigger();
|
|
98
|
+
}
|
|
99
|
+
skip(reason) {
|
|
100
|
+
this.deps.onSkip?.(reason);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=idle-wake.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idle-wake.js","sourceRoot":"","sources":["../../src/core/idle-wake.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,7 +27,7 @@ export declare function normalizeForDetection(text: string): string;
|
|
|
27
27
|
/** Scan untrusted text; `null` when nothing instruction-like was found. */
|
|
28
28
|
export declare function detectInjection(text: string): InjectionHit | null;
|
|
29
29
|
/** Tools whose output is attacker-controllable content from outside the repo. */
|
|
30
|
-
export declare function isUntrustedTool(name: string): boolean;
|
|
30
|
+
export declare function isUntrustedTool(name: string, args?: Record<string, unknown>): boolean;
|
|
31
31
|
export declare function injectionWarning(kind: string): string;
|
|
32
32
|
/**
|
|
33
33
|
* `transformToolResult` hook body: for untrusted tools, append the warning
|
|
@@ -35,4 +35,5 @@ export declare function injectionWarning(kind: string): string;
|
|
|
35
35
|
*/
|
|
36
36
|
export declare function flagUntrustedToolResult(call: {
|
|
37
37
|
name: string;
|
|
38
|
+
args?: Record<string, unknown>;
|
|
38
39
|
}, content: ToolResultContent): ToolResultContent;
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* attacker would use. Mere mentions of the topic ("prompt injection",
|
|
16
16
|
* "system prompt") do not hit.
|
|
17
17
|
*/
|
|
18
|
-
const SCAN_WINDOW =
|
|
18
|
+
const SCAN_WINDOW = 100_000;
|
|
19
19
|
const MAX_BLOBS = 64;
|
|
20
20
|
const MAX_BLOB_CHARS = 16_384;
|
|
21
21
|
/** Zero-width, joiners, bidi controls/isolates, soft hyphen, BOM, tag chars. */
|
|
@@ -146,7 +146,7 @@ const RULES = [
|
|
|
146
146
|
kind: "fake role/tool marker",
|
|
147
147
|
re: new RegExp(String.raw `<\|im_start\|>\s*(?:system|assistant)|<\|(?:start_header_id|eot_id|endoftext|system)\|>` +
|
|
148
148
|
String.raw `|</?(?:tool_result|function_results|function_calls|system-reminder|system_prompt)>` +
|
|
149
|
-
String.raw `|(?:^|\n)[ \t]*\[(?:system|/?inst)\][ \t]
|
|
149
|
+
String.raw `|(?:^|\n)[ \t]*\[(?:system|/?inst)\][ \t]*\r?(?:\n|$|[a-z])`),
|
|
150
150
|
},
|
|
151
151
|
];
|
|
152
152
|
/** Encoded blobs: long base64 or hex runs. */
|
|
@@ -205,8 +205,17 @@ export function detectInjection(text) {
|
|
|
205
205
|
}
|
|
206
206
|
return scanBlobs(window.replace(INVISIBLE, ""));
|
|
207
207
|
}
|
|
208
|
+
/**
|
|
209
|
+
* Bash commands whose output is third-party text: issue/PR bodies and
|
|
210
|
+
* comments (`gh`, `glab`) and fetched web pages (`curl`/`wget`).
|
|
211
|
+
*/
|
|
212
|
+
const UNTRUSTED_BASH = /(?:^|[\s;&|(])(?:gh\s+(?:issue\s+(?:view|list)|pr\s+(?:view|diff|list)|api|release\s+view|search)\b|glab\s|curl\s|wget\s)/;
|
|
208
213
|
/** Tools whose output is attacker-controllable content from outside the repo. */
|
|
209
|
-
export function isUntrustedTool(name) {
|
|
214
|
+
export function isUntrustedTool(name, args) {
|
|
215
|
+
if (name === "bash") {
|
|
216
|
+
const command = args?.command;
|
|
217
|
+
return typeof command === "string" && UNTRUSTED_BASH.test(command);
|
|
218
|
+
}
|
|
210
219
|
return name === "web_fetch" || name === "web_search" || name.startsWith("mcp__");
|
|
211
220
|
}
|
|
212
221
|
export function injectionWarning(kind) {
|
|
@@ -217,7 +226,7 @@ export function injectionWarning(kind) {
|
|
|
217
226
|
* line on a hit. Content is never altered otherwise.
|
|
218
227
|
*/
|
|
219
228
|
export function flagUntrustedToolResult(call, content) {
|
|
220
|
-
if (!isUntrustedTool(call.name))
|
|
229
|
+
if (!isUntrustedTool(call.name, call.args))
|
|
221
230
|
return content;
|
|
222
231
|
if (typeof content === "string") {
|
|
223
232
|
const hit = detectInjection(content);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"injection-detect.js","sourceRoot":"","sources":["../../src/core/injection-detect.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"injection-detect.js","sourceRoot":"","sources":["../../src/core/injection-detect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { BlockedPackage } from "./shell-threats.js";
|
|
2
|
+
import { type PackageCheckOptions } from "./package-threats.js";
|
|
3
|
+
export interface InstalledThreat {
|
|
4
|
+
/** Stable id: lockfile path + flagged items (a fix or new hit is a new key). */
|
|
5
|
+
key: string;
|
|
6
|
+
/** Absolute lockfile path. */
|
|
7
|
+
file: string;
|
|
8
|
+
/** Flagged `name@version (IDs)` items. */
|
|
9
|
+
packages: string[];
|
|
10
|
+
/** The same, structured, for the project's "don't install" list. */
|
|
11
|
+
blocked: BlockedPackage[];
|
|
12
|
+
/** One plain line for the user. */
|
|
13
|
+
message: string;
|
|
14
|
+
/** What the agent is told to do. */
|
|
15
|
+
agentText: string;
|
|
16
|
+
}
|
|
17
|
+
/** Lockfile path → mtime, for "did a run change a lockfile?" checks. */
|
|
18
|
+
export type LockfileStamp = Map<string, number>;
|
|
19
|
+
/** Which known lockfiles exist in `dir`, with their mtimes. Missing ones are skipped. */
|
|
20
|
+
export declare function stampProjectLockfiles(dir: string): Promise<LockfileStamp>;
|
|
21
|
+
export declare function sameStamp(a: LockfileStamp, b: LockfileStamp): boolean;
|
|
22
|
+
/** Check every known lockfile in `dir`. Clean or nothing to check → []. */
|
|
23
|
+
export declare function scanProjectLockfiles(dir: string, options?: PackageCheckOptions): Promise<InstalledThreat[]>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Already-installed packages: check a project's existing lockfiles against the
|
|
3
|
+
* malware data (local daily feed + one batched OSV lookup per lockfile), so a
|
|
4
|
+
* package flagged AFTER it was installed is still found. Runs in the
|
|
5
|
+
* background (session start, after each daily feed update, after a run that
|
|
6
|
+
* changed a lockfile); never on a command's critical path, never a prompt.
|
|
7
|
+
*
|
|
8
|
+
* Cost: one `stat` per known lockfile name; a lockfile is only read when it
|
|
9
|
+
* exists, and its verdict is cached by content hash and re-asked of OSV at most
|
|
10
|
+
* once a day (core/package-threats.ts).
|
|
11
|
+
*/
|
|
12
|
+
import fsp from "node:fs/promises";
|
|
13
|
+
import path from "node:path";
|
|
14
|
+
import { checkLockfileMalware, PROJECT_LOCKFILES, } from "./package-threats.js";
|
|
15
|
+
/** Which known lockfiles exist in `dir`, with their mtimes. Missing ones are skipped. */
|
|
16
|
+
export async function stampProjectLockfiles(dir) {
|
|
17
|
+
const stamp = new Map();
|
|
18
|
+
await Promise.all(PROJECT_LOCKFILES.map(async (lock) => {
|
|
19
|
+
const file = path.join(dir, lock.file);
|
|
20
|
+
try {
|
|
21
|
+
const st = await fsp.stat(file);
|
|
22
|
+
if (st.isFile())
|
|
23
|
+
stamp.set(file, st.mtimeMs);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
// Not there: nothing to check.
|
|
27
|
+
}
|
|
28
|
+
}));
|
|
29
|
+
return stamp;
|
|
30
|
+
}
|
|
31
|
+
export function sameStamp(a, b) {
|
|
32
|
+
if (a.size !== b.size)
|
|
33
|
+
return false;
|
|
34
|
+
for (const [file, mtime] of a)
|
|
35
|
+
if (b.get(file) !== mtime)
|
|
36
|
+
return false;
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
function describe(file, dir, packages, blocked) {
|
|
40
|
+
const rel = path.relative(dir, file) || path.basename(file);
|
|
41
|
+
const list = packages.slice(0, 5).join(", ") +
|
|
42
|
+
(packages.length > 5 ? ` and ${packages.length - 5} more` : "");
|
|
43
|
+
return {
|
|
44
|
+
key: `${file}\0${[...packages].sort().join("\0")}`,
|
|
45
|
+
file,
|
|
46
|
+
packages,
|
|
47
|
+
blocked,
|
|
48
|
+
message: `This project uses a package now known to be infected: ${list} (in ${rel}). ` +
|
|
49
|
+
`The agent has been told to replace it.`,
|
|
50
|
+
agentText: `Security notice: ${rel} in this project pins a package that is now known to be malware: ${list}. ` +
|
|
51
|
+
`Before running any of the project's code, replace it: update the dependency to a clean version ` +
|
|
52
|
+
`(the release before the flagged one, or a newer fixed one), regenerate the lockfile and reinstall. ` +
|
|
53
|
+
`Then tell the user in one plain sentence what you changed. Do not run the flagged version.`,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/** Check every known lockfile in `dir`. Clean or nothing to check → []. */
|
|
57
|
+
export async function scanProjectLockfiles(dir, options = {}) {
|
|
58
|
+
const stamp = await stampProjectLockfiles(dir);
|
|
59
|
+
if (stamp.size === 0)
|
|
60
|
+
return [];
|
|
61
|
+
const found = await Promise.all(PROJECT_LOCKFILES.filter((lock) => stamp.has(path.join(dir, lock.file))).map(async (lock) => {
|
|
62
|
+
const threats = await checkLockfileMalware(lock, dir, options);
|
|
63
|
+
const packages = threats.flatMap((t) => t.packages ?? []);
|
|
64
|
+
const blocked = threats.flatMap((t) => t.blocked ?? []);
|
|
65
|
+
return packages.length > 0
|
|
66
|
+
? describe(path.join(dir, lock.file), dir, packages, blocked)
|
|
67
|
+
: null;
|
|
68
|
+
}));
|
|
69
|
+
return found.filter((t) => t !== null);
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=installed-threats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installed-threats.js","sourceRoot":"","sources":["../../src/core/installed-threats.ts"],"names":[],"mappings":"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"}
|
|
@@ -45,6 +45,8 @@ export declare class McpCatalogCache {
|
|
|
45
45
|
/** Serializes read-modify-write cycles within one process. */
|
|
46
46
|
private writeQueue;
|
|
47
47
|
constructor(filePath?: string);
|
|
48
|
+
/** Where this cache lives; sibling state (tool pins) is kept beside it. */
|
|
49
|
+
get path(): string;
|
|
48
50
|
private readAll;
|
|
49
51
|
private writeAll;
|
|
50
52
|
/**
|
|
@@ -70,6 +70,10 @@ export class McpCatalogCache {
|
|
|
70
70
|
constructor(filePath = getAppPaths().mcpCatalogFile) {
|
|
71
71
|
this.filePath = filePath;
|
|
72
72
|
}
|
|
73
|
+
/** Where this cache lives; sibling state (tool pins) is kept beside it. */
|
|
74
|
+
get path() {
|
|
75
|
+
return this.filePath;
|
|
76
|
+
}
|
|
73
77
|
async readAll() {
|
|
74
78
|
try {
|
|
75
79
|
const raw = await fs.readFile(this.filePath, "utf-8");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog-cache.js","sourceRoot":"","sources":["../../../src/core/mcp/catalog-cache.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"catalog-cache.js","sourceRoot":"","sources":["../../../src/core/mcp/catalog-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import type { ElicitResult } from "@modelcontextprotocol/client";
|
|
|
2
2
|
import type { AgentTool } from "@prestyj/agent";
|
|
3
3
|
import type { MCPServerConfig } from "./types.js";
|
|
4
4
|
import { McpCatalogCache } from "./catalog-cache.js";
|
|
5
|
+
import { McpToolGuard, type HiddenMcpTool } from "./tool-guard.js";
|
|
5
6
|
import { type SharedMcpPool } from "./shared-pool.js";
|
|
6
7
|
/**
|
|
7
8
|
* How long a stdio server may sit with no call in flight before its process is
|
|
@@ -33,6 +34,8 @@ export interface MCPConnectResult {
|
|
|
33
34
|
toolCount: number;
|
|
34
35
|
tools: AgentTool[];
|
|
35
36
|
error?: string;
|
|
37
|
+
/** Tools the ez-safe guard withheld from the model, with one-line reasons. */
|
|
38
|
+
hidden?: HiddenMcpTool[];
|
|
36
39
|
/** True when the server returned 401/Unauthorized and an OAuth login is
|
|
37
40
|
* required before it can connect. The UI surfaces this as "requires login". */
|
|
38
41
|
requiresAuth?: boolean;
|
|
@@ -95,6 +98,10 @@ export declare class MCPClientManager {
|
|
|
95
98
|
*/
|
|
96
99
|
private sharedHandles;
|
|
97
100
|
private readonly catalogCache;
|
|
101
|
+
/** Scans + pins each server's tool descriptions before exposure (ez-safe S2). */
|
|
102
|
+
private readonly toolGuard;
|
|
103
|
+
/** Tools hidden by the guard on the latest connect, per server. */
|
|
104
|
+
private readonly hiddenTools;
|
|
98
105
|
/**
|
|
99
106
|
* Opt into the 2026-07-28 revision. Off by default: `mode: "auto"` probes with
|
|
100
107
|
* `server/discover` before falling back to `initialize`, and a legacy stdio
|
|
@@ -132,6 +139,7 @@ export declare class MCPClientManager {
|
|
|
132
139
|
private idleStopped;
|
|
133
140
|
constructor(opts?: {
|
|
134
141
|
catalogCache?: McpCatalogCache;
|
|
142
|
+
toolGuard?: McpToolGuard;
|
|
135
143
|
modernProtocol?: boolean;
|
|
136
144
|
onElicit?: MCPElicitHandler;
|
|
137
145
|
sharedPool?: SharedMcpPool;
|
package/dist/core/mcp/client.js
CHANGED
|
@@ -3,13 +3,17 @@ import { Client, OAuthError, OAuthErrorCode, ProtocolError, SdkError, SdkErrorCo
|
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import http from "node:http";
|
|
5
5
|
import os from "node:os";
|
|
6
|
+
import path from "node:path";
|
|
6
7
|
import { log } from "../logger.js";
|
|
7
8
|
import { McpOAuthProvider, MCP_OAUTH_CALLBACK_PORT, MCP_OAUTH_CALLBACK_PATH, } from "./oauth-provider.js";
|
|
8
9
|
import { McpOAuthStore } from "./oauth-store.js";
|
|
9
10
|
import { isLocalhost, alternateLoopback, isNetworkError } from "./loopback.js";
|
|
10
11
|
import { toToolResult } from "./content.js";
|
|
11
12
|
import { resolveStdioCommand } from "./resolve-stdio.js";
|
|
13
|
+
import { checkMcpLaunch } from "../package-threats.js";
|
|
14
|
+
import { launchCooldownEnv } from "../package-cooldown.js";
|
|
12
15
|
import { McpCatalogCache } from "./catalog-cache.js";
|
|
16
|
+
import { McpToolGuard } from "./tool-guard.js";
|
|
13
17
|
import { isShareableServer, sharedMcpPool, } from "./shared-pool.js";
|
|
14
18
|
/**
|
|
15
19
|
* How long a stdio server may sit with no call in flight before its process is
|
|
@@ -76,6 +80,10 @@ export class MCPClientManager {
|
|
|
76
80
|
*/
|
|
77
81
|
sharedHandles = new Map();
|
|
78
82
|
catalogCache;
|
|
83
|
+
/** Scans + pins each server's tool descriptions before exposure (ez-safe S2). */
|
|
84
|
+
toolGuard;
|
|
85
|
+
/** Tools hidden by the guard on the latest connect, per server. */
|
|
86
|
+
hiddenTools = new Map();
|
|
79
87
|
/**
|
|
80
88
|
* Opt into the 2026-07-28 revision. Off by default: `mode: "auto"` probes with
|
|
81
89
|
* `server/discover` before falling back to `initialize`, and a legacy stdio
|
|
@@ -113,6 +121,11 @@ export class MCPClientManager {
|
|
|
113
121
|
idleStopped = new WeakSet();
|
|
114
122
|
constructor(opts = {}) {
|
|
115
123
|
this.catalogCache = opts.catalogCache ?? new McpCatalogCache();
|
|
124
|
+
// Pins sit beside the catalog cache, so a test that isolates the cache
|
|
125
|
+
// isolates the pins too (and the real ~/.ezcoder is never touched).
|
|
126
|
+
this.toolGuard =
|
|
127
|
+
opts.toolGuard ??
|
|
128
|
+
new McpToolGuard(path.join(path.dirname(this.catalogCache.path), "mcp-tool-pins.json"));
|
|
116
129
|
this.modernProtocol = opts.modernProtocol ?? false;
|
|
117
130
|
this.onElicit = opts.onElicit;
|
|
118
131
|
this.pool = opts.sharedPool ?? sharedMcpPool;
|
|
@@ -311,6 +324,7 @@ export class MCPClientManager {
|
|
|
311
324
|
throw new Error(handle.result.error ?? "connection failed");
|
|
312
325
|
}
|
|
313
326
|
this.sharedHandles.set(config.name, handle);
|
|
327
|
+
this.hiddenTools.set(config.name, handle.result.hidden ?? []);
|
|
314
328
|
// Wrap each pooled tool so a call from THIS session is attributable while
|
|
315
329
|
// it runs. The pool needs that to answer "which window asked?" when the
|
|
316
330
|
// server elicits mid-call; without it a shared server could only ever
|
|
@@ -394,7 +408,14 @@ export class MCPClientManager {
|
|
|
394
408
|
const results = settled.map((result, i) => {
|
|
395
409
|
const name = enabled[i].name;
|
|
396
410
|
if (result.status === "fulfilled") {
|
|
397
|
-
|
|
411
|
+
const hidden = this.hiddenTools.get(name) ?? [];
|
|
412
|
+
return {
|
|
413
|
+
name,
|
|
414
|
+
ok: true,
|
|
415
|
+
toolCount: result.value.length,
|
|
416
|
+
tools: result.value,
|
|
417
|
+
...(hidden.length > 0 ? { hidden } : {}),
|
|
418
|
+
};
|
|
398
419
|
}
|
|
399
420
|
const requiresAuth = isUnauthorized(result.reason);
|
|
400
421
|
const error = requiresAuth ? "Requires login." : formatConnectError(result.reason);
|
|
@@ -593,11 +614,19 @@ export class MCPClientManager {
|
|
|
593
614
|
// wrapper whose only job is to resolve+launch the real server, doubling
|
|
594
615
|
// memory per connection. Non-resolvable / non-npx commands pass through
|
|
595
616
|
// unchanged. Mirrors the LSP `process.execPath`+bin pattern.
|
|
617
|
+
// Same package guard as bash installs: a flagged `npx`/`uvx` package is
|
|
618
|
+
// never started (P7). Throws like any other connect failure.
|
|
619
|
+
const packageBlocked = await checkMcpLaunch(config.command, config.args ?? []);
|
|
620
|
+
if (packageBlocked) {
|
|
621
|
+
log("WARN", "mcp", `not starting "${config.name}": ${packageBlocked}`);
|
|
622
|
+
throw new Error(`MCP server "${config.name}" not started. ${packageBlocked}`);
|
|
623
|
+
}
|
|
624
|
+
const cooldownEnv = await launchCooldownEnv(config.command, config.args ?? [], os.homedir());
|
|
596
625
|
const resolved = resolveStdioCommand(config.command, config.args);
|
|
597
626
|
transport = new StdioClientTransport({
|
|
598
627
|
command: resolved.command,
|
|
599
628
|
args: resolved.args,
|
|
600
|
-
env: { ...process.env, ...config.env },
|
|
629
|
+
env: { ...process.env, ...cooldownEnv, ...config.env },
|
|
601
630
|
cwd: os.homedir(),
|
|
602
631
|
stderr: "pipe",
|
|
603
632
|
});
|
|
@@ -664,7 +693,12 @@ export class MCPClientManager {
|
|
|
664
693
|
log("WARN", "mcp", `MCP server "${config.name}" closed unexpectedly`);
|
|
665
694
|
this.onServerClosed?.(config.name);
|
|
666
695
|
};
|
|
667
|
-
const
|
|
696
|
+
const listed = await client.listTools(undefined, { timeout });
|
|
697
|
+
// ez-safe S2: hide poisoned / shadowing / rug-pulled tools before anything
|
|
698
|
+
// (catalog cache, deferred catalog, model) sees them.
|
|
699
|
+
const guarded = await this.toolGuard.filter(config.name, client.getServerVersion()?.version, listed.tools);
|
|
700
|
+
const tools = guarded.tools;
|
|
701
|
+
this.hiddenTools.set(config.name, guarded.hidden);
|
|
668
702
|
// Start the idle countdown (a no-op for HTTP / keepAlive / a call in
|
|
669
703
|
// flight). A probe connection is closed right away, so it never idles.
|
|
670
704
|
if (!opts.probe)
|