kritya 0.8.4-beta → 0.8.6-beta
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/agent/loop.js +7 -0
- package/dist/agent/toolExecutor.js +17 -1
- package/dist/config/models.js +5 -0
- package/dist/headless.js +4 -0
- package/dist/index.js +4 -0
- package/dist/shell/sandbox.js +39 -0
- package/package.json +1 -1
package/dist/agent/loop.js
CHANGED
|
@@ -45,6 +45,13 @@ export class Agent {
|
|
|
45
45
|
dryRunMode = false;
|
|
46
46
|
/** When true, file-edit tools auto-approve without prompting (see ACCEPT_EDITS_TOOL_NAMES). */
|
|
47
47
|
acceptEdits = false;
|
|
48
|
+
/**
|
|
49
|
+
* Whether a human can see and respond to a permission prompt right now.
|
|
50
|
+
* True by default (the CLI and its subagents render one); headless runs
|
|
51
|
+
* set this false because there is no one to answer it, so a forced
|
|
52
|
+
* warning prompt there must resolve on its own rather than block forever.
|
|
53
|
+
*/
|
|
54
|
+
interactive = true;
|
|
48
55
|
/** Fires each time a tool call is auto-approved because of acceptEdits, for a UI counter. */
|
|
49
56
|
onAutoApprove;
|
|
50
57
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { classifyDanger } from "../permissions/danger.js";
|
|
2
|
+
import { acknowledgeUnsandboxedFallback, sandboxFallbackWarning } from "../shell/sandbox.js";
|
|
2
3
|
import { isPlanningDocWrite, loadProjectState } from "./workflow.js";
|
|
3
4
|
/** How much tool output to hand the UI (it shows a preview and expands on toggle). */
|
|
4
5
|
const PREVIEW_CHARS = 4000;
|
|
@@ -190,7 +191,16 @@ export class ToolExecutor {
|
|
|
190
191
|
return "This action is blocked by a deny rule in the user's settings. Do not retry it; take a different approach.";
|
|
191
192
|
}
|
|
192
193
|
// Destructive shell commands always prompt with a warning, even if allowlisted.
|
|
193
|
-
const
|
|
194
|
+
const shellCommand = tool.name === "shell" ? String(args.command ?? "") : "";
|
|
195
|
+
const dangerLabel = tool.name === "shell" ? classifyDanger(shellCommand) : null;
|
|
196
|
+
// Separate from dangerLabel: this one only fires when no sandbox binary
|
|
197
|
+
// is installed, so a flagged command is about to run fully unconfined.
|
|
198
|
+
// Only surfaced when a human can actually see and answer the prompt —
|
|
199
|
+
// see `Agent.interactive`.
|
|
200
|
+
const sandboxWarning = tool.name === "shell" && dangerLabel === null && host.interactive
|
|
201
|
+
? sandboxFallbackWarning(host.ctx.sandboxMode, shellCommand)
|
|
202
|
+
: null;
|
|
203
|
+
const danger = dangerLabel ?? sandboxWarning;
|
|
194
204
|
const autoApproveEdit = host.acceptEdits &&
|
|
195
205
|
danger === null &&
|
|
196
206
|
tool.requiresPermission &&
|
|
@@ -214,6 +224,12 @@ export class ToolExecutor {
|
|
|
214
224
|
// A forced (danger) prompt does not grant a lasting allowance.
|
|
215
225
|
if (danger === null)
|
|
216
226
|
host.permissions.record(tool.name, decision, args);
|
|
227
|
+
// Unlike a dangerLabel prompt (which re-warns every time on purpose),
|
|
228
|
+
// approving the unsandboxed-fallback warning once is enough — "auto"
|
|
229
|
+
// sandboxes nearly every command, so re-asking on each one would be
|
|
230
|
+
// an unusable wall of prompts for a fact that won't change mid-session.
|
|
231
|
+
if (decision === "yes" && sandboxWarning !== null)
|
|
232
|
+
acknowledgeUnsandboxedFallback();
|
|
217
233
|
if (decision === "no") {
|
|
218
234
|
host.audit?.logPermission({
|
|
219
235
|
tool: name,
|
package/dist/config/models.js
CHANGED
|
@@ -23,6 +23,11 @@ export const CURATED_MODELS = [
|
|
|
23
23
|
label: "Nemotron 3 Ultra 550B",
|
|
24
24
|
contextWindow: 128_000,
|
|
25
25
|
},
|
|
26
|
+
{
|
|
27
|
+
id: "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning",
|
|
28
|
+
label: "Nemotron 3 Nano Omni 30B Reasoning",
|
|
29
|
+
contextWindow: 128_000,
|
|
30
|
+
},
|
|
26
31
|
{
|
|
27
32
|
id: "meta/muse-glimmer-30b",
|
|
28
33
|
label: "Muse Glimmer 30B",
|
package/dist/headless.js
CHANGED
|
@@ -164,6 +164,10 @@ export async function runHeadless(args) {
|
|
|
164
164
|
// declined" for a question no one was actually asked.
|
|
165
165
|
{ workspace, sandboxMode: config.sandboxExec ?? defaultSandboxMode(), trustWorkspace }, permissions, session, initialHistory);
|
|
166
166
|
agent.contextWindow = contextWindowFor(model, config);
|
|
167
|
+
// No one is present to answer a permission prompt, so a forced
|
|
168
|
+
// unsandboxed-fallback warning must resolve on its own (see
|
|
169
|
+
// requestPermission below) rather than be raised at all.
|
|
170
|
+
agent.interactive = false;
|
|
167
171
|
if (config.maxSteps && config.maxSteps > 0)
|
|
168
172
|
agent.maxSteps = config.maxSteps;
|
|
169
173
|
if (config.toolTimeoutSeconds !== undefined) {
|
package/dist/index.js
CHANGED
|
@@ -526,6 +526,10 @@ async function main() {
|
|
|
526
526
|
// network access).
|
|
527
527
|
const sub = new Agent(client, () => modelRef.current, writeSubTools, { workspace: wt.dir, sandboxMode, trustWorkspace }, new PermissionManager({ allow: ["write_file", "edit_file", "shell(*)"], deny: [] }, wt.dir), new SessionStore(wt.dir, true), []);
|
|
528
528
|
sub.maxSteps = 30;
|
|
529
|
+
// No human is watching this run (see the auto-allow comment above) —
|
|
530
|
+
// the forced unsandboxed-fallback warning must resolve on its own via
|
|
531
|
+
// the handler below rather than be raised at all.
|
|
532
|
+
sub.interactive = false;
|
|
529
533
|
sub.audit = sessionAudit;
|
|
530
534
|
sub.tracer = sessionTracer;
|
|
531
535
|
sub.meter = sessionMeter;
|
package/dist/shell/sandbox.js
CHANGED
|
@@ -81,6 +81,45 @@ export function shouldSandbox(mode, command) {
|
|
|
81
81
|
export function requiresSandbox(mode) {
|
|
82
82
|
return mode === "strict";
|
|
83
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* True once the user has explicitly approved running unsandboxed for the rest
|
|
86
|
+
* of this process — see `sandboxFallbackWarning`. Resets on restart; there is
|
|
87
|
+
* no persistent "don't ask again" for this, since a different host without
|
|
88
|
+
* the sandbox binary could be running next time.
|
|
89
|
+
*/
|
|
90
|
+
let unsandboxedFallbackAcknowledged = false;
|
|
91
|
+
/** Records that the user approved the one-time unsandboxed-fallback warning. */
|
|
92
|
+
export function acknowledgeUnsandboxedFallback() {
|
|
93
|
+
unsandboxedFallbackAcknowledged = true;
|
|
94
|
+
}
|
|
95
|
+
/** Test-only: undoes `acknowledgeUnsandboxedFallback` between test cases. */
|
|
96
|
+
export function resetUnsandboxedFallbackAcknowledgement() {
|
|
97
|
+
unsandboxedFallbackAcknowledged = false;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* A one-time, forced permission-prompt warning for the fail-open gap in
|
|
101
|
+
* "auto"/"always": sandboxing was requested for `command` but no sandbox
|
|
102
|
+
* binary is installed, so it's about to run completely unconfined — able to
|
|
103
|
+
* read, write, or delete anywhere the real user can, not just inside the
|
|
104
|
+
* workspace. Returns null (nothing to warn about) once
|
|
105
|
+
* `acknowledgeUnsandboxedFallback` has been called this run, when sandboxing
|
|
106
|
+
* wasn't requested for this command, when a sandbox binary IS available, or
|
|
107
|
+
* under "strict" (which refuses instead of falling back, so it has no silent
|
|
108
|
+
* gap to warn about).
|
|
109
|
+
*/
|
|
110
|
+
export function sandboxFallbackWarning(mode, command) {
|
|
111
|
+
if (unsandboxedFallbackAcknowledged)
|
|
112
|
+
return null;
|
|
113
|
+
if (!shouldSandbox(mode, command))
|
|
114
|
+
return null;
|
|
115
|
+
if (requiresSandbox(mode))
|
|
116
|
+
return null;
|
|
117
|
+
if (sandboxAvailable())
|
|
118
|
+
return null;
|
|
119
|
+
return (`a command running with NO sandbox isolation (${sandboxUnavailableReason()}) — ` +
|
|
120
|
+
`it can read, write, or delete anywhere you can, not just inside the workspace. ` +
|
|
121
|
+
`Approving runs this command now and skips this warning for the rest of the session`);
|
|
122
|
+
}
|
|
84
123
|
/**
|
|
85
124
|
* Common tool-cache / global-install directories outside the workspace that
|
|
86
125
|
* legitimate commands need to write to (package manager caches, toolchain
|