@sema-agent/core 5.0.0 → 5.1.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/CHANGELOG.md +50 -0
- package/dist/agents/repair-loop.js +9 -1
- package/dist/agents/roster-store.d.ts +9 -2
- package/dist/agents/roster-store.js +26 -5
- package/dist/agents/send-message-tool.js +1 -1
- package/dist/agents/subagent.js +15 -5
- package/dist/bin/sema-tb.d.ts +1 -2
- package/dist/bin/sema-tb.js +13 -25
- package/dist/brain/anthropic.js +2 -3
- package/dist/brain/degrading.d.ts +2 -8
- package/dist/brain/degrading.js +3 -3
- package/dist/brain/terminal-cause.js +2 -8
- package/dist/core/hooks.js +4 -4
- package/dist/core/lsp.js +2 -3
- package/dist/core/mcp.d.ts +1 -1
- package/dist/core/mcp.js +2 -1
- package/dist/core/memory-engine/engine.js +2 -2
- package/dist/core/memory-engine/file-backend.js +3 -1
- package/dist/core/memory-engine/layout.d.ts +3 -0
- package/dist/core/memory-engine/layout.js +51 -0
- package/dist/core/memory.d.ts +0 -1
- package/dist/core/memory.js +1 -1
- package/dist/core/permission-rules.d.ts +2 -2
- package/dist/core/permission-rules.js +18 -7
- package/dist/core/protocol-table.d.ts +14 -0
- package/dist/core/protocol-table.js +23 -0
- package/dist/core/runner/active-skill-scope.js +7 -7
- package/dist/core/runner/prepare-memory.js +4 -1
- package/dist/core/runner/prepare-task.js +38 -25
- package/dist/core/runner/runtask.js +9 -3
- package/dist/core/runner/session-rule-policy.d.ts +2 -2
- package/dist/core/runner/session-rule-policy.js +2 -1
- package/dist/core/runner/synthetic-tools.js +2 -2
- package/dist/core/runner/tool-disclosure.d.ts +0 -1
- package/dist/core/runner/tool-disclosure.js +0 -2
- package/dist/core/runner/turn-attachments.js +2 -1
- package/dist/core/sensitive-path-policy.js +2 -2
- package/dist/core/tool-policy.d.ts +0 -3
- package/dist/core/tool-policy.js +29 -15
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/orchestration/run-spec.js +1 -1
- package/dist/orchestration/run-workflow-tool.js +2 -2
- package/dist/orchestration/workflow-script-store.d.ts +1 -1
- package/dist/orchestration/workflow-script-store.js +1 -1
- package/dist/prompt-assembly/assemble.js +0 -1
- package/dist/prompt-assembly/tool-catalog.d.ts +2 -1
- package/dist/prompts/default.d.ts +0 -2
- package/dist/prompts/default.js +1 -5
- package/dist/stores/cc/mailbox-store.d.ts +4 -0
- package/dist/stores/cc/mailbox-store.js +16 -2
- package/dist/stores/file/session-policy-store.d.ts +10 -1
- package/dist/stores/file/session-policy-store.js +20 -4
- package/dist/tools/fs/fs-search-tools.js +1 -2
- package/dist/tools/fs/fs-shared.d.ts +0 -1
- package/dist/tools/fs/fs-shared.js +0 -1
- package/dist/tools/todo.js +1 -1
- package/package.json +1 -1
package/dist/core/tool-policy.js
CHANGED
|
@@ -3,7 +3,7 @@ import { isAbsolute, join, normalize as normalizePath, sep } from "node:path";
|
|
|
3
3
|
import { BASH_READONLY_DEFAULT_ALLOW, parseLeadingCommandName } from "../tools/fs/index.js";
|
|
4
4
|
import { writeTargetPath } from "../tools/fs/safety.js";
|
|
5
5
|
export function decisionText(d) {
|
|
6
|
-
return d.message
|
|
6
|
+
return d.message;
|
|
7
7
|
}
|
|
8
8
|
const ALLOW = { action: "allow" };
|
|
9
9
|
function withTimeout(p, ms, onTimeout) {
|
|
@@ -39,10 +39,10 @@ export function createAllowDenyPolicy(opts) {
|
|
|
39
39
|
check(req) {
|
|
40
40
|
const toolName = req.toolName;
|
|
41
41
|
if (deny.has(toolName)) {
|
|
42
|
-
return { action: "deny",
|
|
42
|
+
return { action: "deny", message: `tool "${req.toolName}" is denied by policy` };
|
|
43
43
|
}
|
|
44
44
|
if (allow && !allow.has(toolName)) {
|
|
45
|
-
return { action: "deny",
|
|
45
|
+
return { action: "deny", message: `tool "${req.toolName}" is not in the allowlist` };
|
|
46
46
|
}
|
|
47
47
|
return ALLOW;
|
|
48
48
|
},
|
|
@@ -66,11 +66,11 @@ export function createApprovalPolicy(opts) {
|
|
|
66
66
|
async check(req, signal) {
|
|
67
67
|
const toolName = req.toolName;
|
|
68
68
|
if (deny.has(toolName)) {
|
|
69
|
-
return { action: "deny",
|
|
69
|
+
return { action: "deny", message: `tool "${req.toolName}" is denied by policy` };
|
|
70
70
|
}
|
|
71
71
|
if (need.has(toolName)) {
|
|
72
72
|
if (signal?.aborted) {
|
|
73
|
-
return { action: "deny",
|
|
73
|
+
return { action: "deny", message: `approval aborted for "${req.toolName}" (task ended)` };
|
|
74
74
|
}
|
|
75
75
|
let ok;
|
|
76
76
|
try {
|
|
@@ -79,13 +79,19 @@ export function createApprovalPolicy(opts) {
|
|
|
79
79
|
catch (err) {
|
|
80
80
|
return {
|
|
81
81
|
action: "deny",
|
|
82
|
-
|
|
82
|
+
message: `approval errored for "${req.toolName}": ${err instanceof Error ? err.message : String(err)}`,
|
|
83
83
|
};
|
|
84
84
|
}
|
|
85
|
-
|
|
85
|
+
const okRaw = ok;
|
|
86
|
+
if (okRaw === true)
|
|
87
|
+
return ALLOW;
|
|
88
|
+
if (okRaw !== false) {
|
|
89
|
+
return { action: "deny", message: `approval callback for "${req.toolName}" returned an out-of-contract value (${typeof ok}) — denied fail-closed (return true, false, or the {allow} object)` };
|
|
90
|
+
}
|
|
91
|
+
return { action: "deny", message: `approval denied for "${req.toolName}"` };
|
|
86
92
|
}
|
|
87
93
|
if (opts.denyByDefault && !auto.has(toolName)) {
|
|
88
|
-
return { action: "deny",
|
|
94
|
+
return { action: "deny", message: `tool "${req.toolName}" requires explicit allow` };
|
|
89
95
|
}
|
|
90
96
|
return ALLOW;
|
|
91
97
|
},
|
|
@@ -130,7 +136,7 @@ export function createCoarseCommandNamePolicy(opts) {
|
|
|
130
136
|
const shellTools = canonicalToolNameSet(opts.tools);
|
|
131
137
|
const defaultAction = opts.defaultAction ?? "ask";
|
|
132
138
|
const fallback = (reason) => defaultAction === "deny"
|
|
133
|
-
? { action: "deny", reason, decisionReason: "rule" }
|
|
139
|
+
? { action: "deny", message: reason, decisionReason: "rule" }
|
|
134
140
|
: { action: "ask", message: reason, decisionReason: "rule" };
|
|
135
141
|
return {
|
|
136
142
|
check(req) {
|
|
@@ -145,7 +151,7 @@ export function createCoarseCommandNamePolicy(opts) {
|
|
|
145
151
|
return fallback(`command is not a single simple command (${parsed.reject})`);
|
|
146
152
|
}
|
|
147
153
|
if (deny.has(parsed.name)) {
|
|
148
|
-
return { action: "deny",
|
|
154
|
+
return { action: "deny", message: `command "${parsed.name}" is denied by policy`, decisionReason: "rule" };
|
|
149
155
|
}
|
|
150
156
|
if (allow && !allow.has(parsed.name)) {
|
|
151
157
|
return fallback(`command "${parsed.name}" is not in the allowlist`);
|
|
@@ -394,7 +400,7 @@ export function createUnverifiableDeletePolicy(opts) {
|
|
|
394
400
|
action: "ask",
|
|
395
401
|
decisionReason: "safety",
|
|
396
402
|
requiresRealApproval: true,
|
|
397
|
-
|
|
403
|
+
message: `Unverifiable recursive delete (fail-closed unless cleared): ${finding}. ` +
|
|
398
404
|
`Re-run the delete with the resolved literal path written into the command itself ` +
|
|
399
405
|
`(or assign the variable in the same command, e.g. \`DIR=/exact/path; rm -rf "$DIR"\`) so the target can be verified.`,
|
|
400
406
|
};
|
|
@@ -468,7 +474,7 @@ export function createTranscriptIntegrityPolicy(opts) {
|
|
|
468
474
|
action: "ask",
|
|
469
475
|
decisionReason: "safety",
|
|
470
476
|
requiresRealApproval: true,
|
|
471
|
-
|
|
477
|
+
message: `Session-transcript write (fail-closed unless cleared): ${what}. Session transcripts (the .jsonl files ` +
|
|
472
478
|
`under the agent data dir's sessions/ directory) are harness-written session state, not agent working ` +
|
|
473
479
|
`files — modifying or deleting them tampers with the run's own audit trail. Reading them (ls/cat/grep ` +
|
|
474
480
|
`as a single simple command) is fine.`,
|
|
@@ -613,7 +619,15 @@ export async function resolveAsk(req, onAsk, signal) {
|
|
|
613
619
|
}
|
|
614
620
|
return { action: "allow", updatedInput: edit.value, decisionReason: "mode" };
|
|
615
621
|
}
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
622
|
+
const okRaw = ok;
|
|
623
|
+
if (okRaw === true)
|
|
624
|
+
return { action: "allow", decisionReason: "mode", presentedInput: presented.value };
|
|
625
|
+
if (okRaw !== false) {
|
|
626
|
+
return {
|
|
627
|
+
action: "deny",
|
|
628
|
+
message: `the approver for "${req.toolName}" returned an out-of-contract value (${typeof ok}) — denied fail-closed (return true, false, "unavailable", or the {allow} object)`,
|
|
629
|
+
decisionReason: "mode",
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
return { action: "deny", message: `approval denied for "${req.toolName}": ${req.message}`, decisionReason: "mode" };
|
|
619
633
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -40,6 +40,7 @@ export { decideAutoPromote, deriveTripwire, FROZEN_DENYLIST_FLOOR, type AutoProm
|
|
|
40
40
|
export { runCascade, type CascadeRung, type CascadeConfig, type CascadeAttempt, type CascadeRunResult, type GateVerdict, } from "./agents/cascade.js";
|
|
41
41
|
export { pgQuery, mysqlQuery, sqliteQuery } from "./tools/sql-adapters.js";
|
|
42
42
|
export { materializeMcpTools, MCP_PREFIX, type MaterializedMcp, type McpServerStatus, type McpRefreshResult } from "./core/mcp.js";
|
|
43
|
+
export { PROTOCOL_TABLE, MCP_NAMESPACE, protocolOf, type ProtocolNamespace, type ProtocolId } from "./core/protocol-table.js";
|
|
43
44
|
export { InMemorySessionPolicyStore, SessionPolicyError, loosenReasons, normalizeRules, stripRev, type SessionPolicyStore, type SessionPermissionRules, type StoredSessionRules, type SessionRulesRecord, type PutRulesOptions, } from "./core/session-policy-store.js";
|
|
44
45
|
export { SAFETY_MERGE_CONFORMANCE_CORPUS, type SafetyMergeVector } from "./core/safety-merge-corpus.js";
|
|
45
46
|
export { SAFETY_AXIS_VOCABULARY } from "./core/safety-axis-vocab.js";
|
package/dist/index.js
CHANGED
|
@@ -37,6 +37,7 @@ export { decideAutoPromote, deriveTripwire, FROZEN_DENYLIST_FLOOR, } from "./cor
|
|
|
37
37
|
export { runCascade, } from "./agents/cascade.js";
|
|
38
38
|
export { pgQuery, mysqlQuery, sqliteQuery } from "./tools/sql-adapters.js";
|
|
39
39
|
export { materializeMcpTools, MCP_PREFIX } from "./core/mcp.js";
|
|
40
|
+
export { PROTOCOL_TABLE, MCP_NAMESPACE, protocolOf } from "./core/protocol-table.js";
|
|
40
41
|
export { InMemorySessionPolicyStore, SessionPolicyError, loosenReasons, normalizeRules, stripRev, } from "./core/session-policy-store.js";
|
|
41
42
|
export { SAFETY_MERGE_CONFORMANCE_CORPUS } from "./core/safety-merge-corpus.js";
|
|
42
43
|
export { SAFETY_AXIS_VOCABULARY } from "./core/safety-axis-vocab.js";
|
|
@@ -28,7 +28,7 @@ function frozenDenyPolicy(rootDir, frozenResolved) {
|
|
|
28
28
|
const absForm = isAbsolutePathForm(raw);
|
|
29
29
|
const abs = pathKey(absForm ? raw : resolve(rootDir, raw));
|
|
30
30
|
if (frozen.has(abs)) {
|
|
31
|
-
return { action: "deny",
|
|
31
|
+
return { action: "deny", message: `${raw} is part of the frozen specification surface (read-only).` };
|
|
32
32
|
}
|
|
33
33
|
return { action: "allow" };
|
|
34
34
|
},
|
|
@@ -344,8 +344,8 @@ export async function createRunWorkflowTool(d) {
|
|
|
344
344
|
}
|
|
345
345
|
if (resolved === undefined)
|
|
346
346
|
return structuredError(`unknown workflow name: ${JSON.stringify(rawName)}`);
|
|
347
|
-
script =
|
|
348
|
-
if (
|
|
347
|
+
script = resolved.script;
|
|
348
|
+
if ("defaultArgs" in resolved)
|
|
349
349
|
registeredDefaultArgs = resolved.defaultArgs;
|
|
350
350
|
if (typeof resolved !== "string" && typeof resolved.stringArgKey === "string" && resolved.stringArgKey.length > 0) {
|
|
351
351
|
registeredStringArgKey = resolved.stringArgKey;
|
|
@@ -12,7 +12,7 @@ export interface WorkflowScriptStore {
|
|
|
12
12
|
readonly scopePartitioned: true;
|
|
13
13
|
persist(runId: string, script: string, scope: string): Promise<string> | string;
|
|
14
14
|
load(scriptPath: string, scope: string): Promise<string> | string;
|
|
15
|
-
resolveName?(name: string): Promise<
|
|
15
|
+
resolveName?(name: string): Promise<NamedWorkflowResolution | undefined> | NamedWorkflowResolution | undefined;
|
|
16
16
|
list?(): NamedWorkflowListing[] | Promise<NamedWorkflowListing[]>;
|
|
17
17
|
}
|
|
18
18
|
export declare function mergeWorkflowArgs(callArgs: unknown, defaultArgs: unknown): unknown;
|
|
@@ -95,7 +95,7 @@ export function createFileWorkflowScriptStore(dir) {
|
|
|
95
95
|
const script = readFileSync(path, "utf-8");
|
|
96
96
|
const argsPath = join(root, `${stem}.args.json`);
|
|
97
97
|
if (!existsSync(argsPath))
|
|
98
|
-
return script;
|
|
98
|
+
return { script };
|
|
99
99
|
let defaultArgs;
|
|
100
100
|
try {
|
|
101
101
|
defaultArgs = JSON.parse(readFileSync(argsPath, "utf-8"));
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { TSchema } from "typebox";
|
|
2
2
|
import type { AgentTool } from "../internal/harness-types.js";
|
|
3
|
-
|
|
3
|
+
import type { ProtocolId } from "../core/protocol-table.js";
|
|
4
|
+
export type ToolOrigin = "core" | "caller" | "synthetic" | ProtocolId;
|
|
4
5
|
export interface ToolContractDescriptor {
|
|
5
6
|
contractId: string;
|
|
6
7
|
implementationRevision: string;
|
|
@@ -64,8 +64,6 @@ export interface StablePromptContext {
|
|
|
64
64
|
userSystemPrompt?: string;
|
|
65
65
|
userAppendSystemPrompt?: string;
|
|
66
66
|
tools: AgentTool[];
|
|
67
|
-
memoryEnabled: boolean;
|
|
68
|
-
consolidationEnabled?: boolean;
|
|
69
67
|
policyEnabled?: boolean;
|
|
70
68
|
hooksEnabled?: boolean;
|
|
71
69
|
isolationEnabled?: boolean;
|
package/dist/prompts/default.js
CHANGED
|
@@ -365,10 +365,6 @@ export function constitutionBlocks(ctx) {
|
|
|
365
365
|
blocks.push({ id: "mode.worktree", text: WORKTREE_NOTICE });
|
|
366
366
|
if (ctx.goalEnabled)
|
|
367
367
|
blocks.push({ id: "mode.goal", text: GOAL_COMPLETION_GUIDANCE });
|
|
368
|
-
if (ctx.memoryEnabled)
|
|
369
|
-
blocks.push({ id: "memory.safety", text: MEMORY_SAFETY });
|
|
370
|
-
if (ctx.memoryEnabled && !ctx.consolidationEnabled)
|
|
371
|
-
blocks.push({ id: "memory.hygiene", text: MEMORY_HYGIENE });
|
|
372
368
|
return blocks;
|
|
373
369
|
}
|
|
374
370
|
export function composeConstitution(roleBase, ctx) {
|
|
@@ -393,7 +389,7 @@ export function analyzePromptCacheFriendliness(provider, opts = {}) {
|
|
|
393
389
|
const build = (memoryBlock) => {
|
|
394
390
|
if (!provider.stableSystem)
|
|
395
391
|
throw new Error("PromptProvider does not implement stableSystem");
|
|
396
|
-
return composeSystemPrompt(provider.stableSystem({ userSystemPrompt: opts.userSystemPrompt, tools
|
|
392
|
+
return composeSystemPrompt(provider.stableSystem({ userSystemPrompt: opts.userSystemPrompt, tools }), memoryBlock);
|
|
397
393
|
};
|
|
398
394
|
const a = build(PROBE_MEMORY_A);
|
|
399
395
|
const b = build(PROBE_MEMORY_B);
|
|
@@ -4,5 +4,9 @@ export interface CcFileMailboxStoreOptions {
|
|
|
4
4
|
teamDir: string;
|
|
5
5
|
agentNameOf?: (handle: string) => string | undefined;
|
|
6
6
|
now?: () => number;
|
|
7
|
+
onCorruptRead?: (info: {
|
|
8
|
+
path: string;
|
|
9
|
+
reason: string;
|
|
10
|
+
}) => void;
|
|
7
11
|
}
|
|
8
12
|
export declare function createCcFileMailboxStore(opts: CcFileMailboxStoreOptions): MailboxStore;
|
|
@@ -27,19 +27,33 @@ export function createCcFileMailboxStore(opts) {
|
|
|
27
27
|
const name = opts.agentNameOf?.(handle) ?? handle;
|
|
28
28
|
return join(inboxDir, `${sanitizeCcAgentName(name)}.json`);
|
|
29
29
|
};
|
|
30
|
+
const discloseCorrupt = (path, reason) => {
|
|
31
|
+
try {
|
|
32
|
+
opts.onCorruptRead?.({ path, reason });
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
}
|
|
36
|
+
};
|
|
30
37
|
const loadBox = (path) => {
|
|
31
38
|
let raw;
|
|
32
39
|
try {
|
|
33
40
|
raw = readFileSync(path, "utf8");
|
|
34
41
|
}
|
|
35
|
-
catch {
|
|
42
|
+
catch (err) {
|
|
43
|
+
if (err.code !== "ENOENT")
|
|
44
|
+
discloseCorrupt(path, `read failed (non-ENOENT): ${err.message}`);
|
|
36
45
|
return [];
|
|
37
46
|
}
|
|
38
47
|
try {
|
|
39
48
|
const parsed = JSON.parse(raw);
|
|
40
|
-
|
|
49
|
+
if (!Array.isArray(parsed)) {
|
|
50
|
+
discloseCorrupt(path, "inbox document is not an array");
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
return parsed;
|
|
41
54
|
}
|
|
42
55
|
catch {
|
|
56
|
+
discloseCorrupt(path, "unparseable inbox JSON (torn write?)");
|
|
43
57
|
return [];
|
|
44
58
|
}
|
|
45
59
|
};
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import { type PutRulesOptions, type SessionPermissionRules, type SessionPolicyStore, type SessionRulesRecord, type StoredSessionRules } from "../../core/session-policy-store.js";
|
|
2
2
|
export declare class FileSessionPolicyStore implements SessionPolicyStore {
|
|
3
3
|
private readonly dir;
|
|
4
|
-
|
|
4
|
+
private readonly onCorruptRead;
|
|
5
|
+
constructor(root: string, opts?: {
|
|
6
|
+
onCorruptRead?: (info: {
|
|
7
|
+
sessionId: string;
|
|
8
|
+
principal?: string;
|
|
9
|
+
path: string;
|
|
10
|
+
reason: string;
|
|
11
|
+
}) => void;
|
|
12
|
+
});
|
|
13
|
+
private discloseCorrupt;
|
|
5
14
|
private pathFor;
|
|
6
15
|
private read;
|
|
7
16
|
getRules(sessionId: string, principal?: string): Promise<StoredSessionRules | null>;
|
|
@@ -4,9 +4,18 @@ import { loosenReasons, normalizeRules, stripRev, SessionPolicyError, } from "..
|
|
|
4
4
|
import { atomicWriteFile, ensureDir, sanitizeScope } from "./fs-atomic.js";
|
|
5
5
|
export class FileSessionPolicyStore {
|
|
6
6
|
dir;
|
|
7
|
-
|
|
7
|
+
onCorruptRead;
|
|
8
|
+
constructor(root, opts) {
|
|
8
9
|
this.dir = join(root, "session-policy");
|
|
9
10
|
ensureDir(this.dir);
|
|
11
|
+
this.onCorruptRead = opts?.onCorruptRead;
|
|
12
|
+
}
|
|
13
|
+
discloseCorrupt(sessionId, principal, reason) {
|
|
14
|
+
try {
|
|
15
|
+
this.onCorruptRead?.({ sessionId, ...(principal !== undefined ? { principal } : {}), path: this.pathFor(sessionId, principal), reason });
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
}
|
|
10
19
|
}
|
|
11
20
|
pathFor(sessionId, principal) {
|
|
12
21
|
const composite = JSON.stringify([sessionId, principal ?? null]);
|
|
@@ -24,20 +33,27 @@ export class FileSessionPolicyStore {
|
|
|
24
33
|
}
|
|
25
34
|
try {
|
|
26
35
|
const parsed = JSON.parse(raw);
|
|
27
|
-
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
|
|
36
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
37
|
+
this.discloseCorrupt(sessionId, principal, "not a JSON object");
|
|
28
38
|
return null;
|
|
39
|
+
}
|
|
29
40
|
const r = parsed;
|
|
30
|
-
if (r.rev !== undefined && (typeof r.rev !== "number" || !Number.isFinite(r.rev)))
|
|
41
|
+
if (r.rev !== undefined && (typeof r.rev !== "number" || !Number.isFinite(r.rev))) {
|
|
42
|
+
this.discloseCorrupt(sessionId, principal, "non-numeric rev");
|
|
31
43
|
return null;
|
|
44
|
+
}
|
|
32
45
|
const strArr = (x) => x === undefined || (Array.isArray(x) && x.every((e) => typeof e === "string"));
|
|
33
|
-
if (!strArr(r.toolAllow) || !strArr(r.toolDeny) || !strArr(r.commandAllow) || !strArr(r.commandDeny) || !strArr(r.allowDirs))
|
|
46
|
+
if (!strArr(r.toolAllow) || !strArr(r.toolDeny) || !strArr(r.commandAllow) || !strArr(r.commandDeny) || !strArr(r.allowDirs)) {
|
|
47
|
+
this.discloseCorrupt(sessionId, principal, "malformed rule field");
|
|
34
48
|
return null;
|
|
49
|
+
}
|
|
35
50
|
const { __sid: _sid, __principal: _principal, ...clean } = r;
|
|
36
51
|
void _sid;
|
|
37
52
|
void _principal;
|
|
38
53
|
return clean;
|
|
39
54
|
}
|
|
40
55
|
catch {
|
|
56
|
+
this.discloseCorrupt(sessionId, principal, "unparseable JSON (torn/zero-byte write?)");
|
|
41
57
|
return null;
|
|
42
58
|
}
|
|
43
59
|
}
|
|
@@ -37,7 +37,6 @@ export function createGrepTool(env, rootCanonical, additionalRoots) {
|
|
|
37
37
|
description: 'Limit output to first N lines/entries, equivalent to "| head -N". Works across all output modes: content (limits output lines), files_with_matches (limits file paths), count (limits count entries). Defaults to 250 when unspecified. Pass 0 for unlimited (use sparingly — large result sets waste context).',
|
|
38
38
|
})),
|
|
39
39
|
offset: Type.Optional(Type.Number({ description: "Skip the first N output lines (pagination partner of head_limit)." })),
|
|
40
|
-
max_results: Type.Optional(Type.Number({ description: "Deprecated alias for head_limit." })),
|
|
41
40
|
}),
|
|
42
41
|
effect: "read",
|
|
43
42
|
execute: async (args, ctx) => {
|
|
@@ -69,7 +68,7 @@ export function createGrepTool(env, rootCanonical, additionalRoots) {
|
|
|
69
68
|
const grepRun = await runGrepDetailed(env, rootCanonical, {
|
|
70
69
|
...a,
|
|
71
70
|
path: scoped,
|
|
72
|
-
head_limit: a.head_limit
|
|
71
|
+
head_limit: a.head_limit,
|
|
73
72
|
context: a.context ?? a["-C"],
|
|
74
73
|
context_after: a.context_after ?? a["-A"],
|
|
75
74
|
context_before: a.context_before ?? a["-B"],
|
|
@@ -43,7 +43,6 @@ export declare function bashTimeoutCapsSec(caps: {
|
|
|
43
43
|
export declare function bashMaxOutputChars(): number;
|
|
44
44
|
export declare const FILE_PATH_PARAMS: {
|
|
45
45
|
file_path: Type.TOptional<Type.TString>;
|
|
46
|
-
path: Type.TOptional<Type.TString>;
|
|
47
46
|
};
|
|
48
47
|
export declare function clipShellOutput(s: string): string;
|
|
49
48
|
export declare function writeShellOverflowFile(env: ExecutionEnv, stdout: string, stderr: string): Promise<string | undefined>;
|
|
@@ -77,7 +77,6 @@ export function bashMaxOutputChars() {
|
|
|
77
77
|
}
|
|
78
78
|
export const FILE_PATH_PARAMS = {
|
|
79
79
|
file_path: Type.Optional(Type.String({ description: "File path (within the configured root)." })),
|
|
80
|
-
path: Type.Optional(Type.String({ description: "Deprecated alias for `file_path` (back-compat; prefer file_path)." })),
|
|
81
80
|
};
|
|
82
81
|
export function clipShellOutput(s) {
|
|
83
82
|
return clipWithFilePointer(s, bashMaxOutputChars());
|
package/dist/tools/todo.js
CHANGED
|
@@ -76,7 +76,7 @@ export function createTodoWriteTool() {
|
|
|
76
76
|
todos: Type.Array(Type.Object({
|
|
77
77
|
content: Type.String({ description: "The task, in imperative form (e.g. \"Run the tests\")." }),
|
|
78
78
|
status: Type.Union([Type.Literal("pending"), Type.Literal("in_progress"), Type.Literal("completed")]),
|
|
79
|
-
activeForm: Type.
|
|
79
|
+
activeForm: Type.String({ minLength: 1, description: "Present-continuous form shown while in progress (e.g. \"Running the tests\")." }),
|
|
80
80
|
})),
|
|
81
81
|
}),
|
|
82
82
|
effect: "idempotent",
|