@sema-agent/core 5.18.0 → 5.18.1
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 +42 -0
- package/dist/core/checkpoint-store.d.ts +3 -2
- package/dist/core/hooks.d.ts +1 -0
- package/dist/core/hooks.js +4 -0
- package/dist/core/permission-rule-consent.d.ts +8 -1
- package/dist/core/permission-rule-consent.js +21 -10
- package/dist/core/runner/prepare-task.d.ts +1 -0
- package/dist/core/runner/prepare-task.js +14 -2
- package/dist/core/runner/runtask.d.ts +3 -1
- package/dist/core/runner/runtask.js +23 -5
- package/dist/core/tool-policy.d.ts +5 -0
- package/dist/core/tool-policy.js +57 -12
- package/dist/core/types.d.ts +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,47 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 5.18.1 — 2026-08-10
|
|
4
|
+
|
|
5
|
+
> The 5.18.0 post-release verification round, folded back in. Every surface below was
|
|
6
|
+
> two-way-verified against the 5.18.0 artifact by the evaluation line before this release
|
|
7
|
+
> (pre-release criteria [3095], green-lit [3103]).
|
|
8
|
+
|
|
9
|
+
### BREAKING (vs 5.18.0; both APIs are new in 5.18.0 and cli has not consumed them yet)
|
|
10
|
+
|
|
11
|
+
- **`confirmRuleApproval` returns `{ ok: true } | { ok: false, reason }`** instead of a bare
|
|
12
|
+
boolean — seven-member closed reason set (`record_not_found` deliberately covers the
|
|
13
|
+
foreign-principal arm so record existence does not leak, `selection_missing`,
|
|
14
|
+
`selection_invalid`, `selection_mismatch`, `batch_takes_no_selection`, `not_pending`,
|
|
15
|
+
`conflict`). `selectedCandidate` is an integer index.
|
|
16
|
+
- **`prepareCardApproval` refuses caller-supplied `candidates` loudly**
|
|
17
|
+
(`config.invalid_argument`) instead of silently ignoring them — card options are
|
|
18
|
+
engine-minted, and a dropped supply attempt is the same silent-narrowing shape this
|
|
19
|
+
release family removes elsewhere.
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- **`settledBy` on approval settlements** (`"human" | "timeout" | "aborted"`): an optional
|
|
24
|
+
field on the durable resume outcome's `policy_ask` arm, carried onto the settled call's
|
|
25
|
+
`tool_end` (top-level key). Out-of-vocabulary values are refused pre-CAS
|
|
26
|
+
(`checkpoint.invalid_outcome`, `detail.field: "settledBy"` — the row stays pending);
|
|
27
|
+
`decision: "allow"` accepts only `"human"` or omission (a contradictory record must not
|
|
28
|
+
become an execution). Core's own arms fill it (elapsed window = `timeout`; abort /
|
|
29
|
+
unclonable / out-of-contract = `aborted`; human answers = `"human"`); posture arms
|
|
30
|
+
(headless auto-deny, blanket modes) leave it absent. Absence = an older caller — consumers
|
|
31
|
+
must not infer semantics from a missing key. New exports: `ApprovalSettledBy`,
|
|
32
|
+
`APPROVAL_SETTLED_BY_VALUES`, `isApprovalSettledBy`.
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
|
|
36
|
+
- **An elapsed approval window says nobody answered** — the live-deadline refusal no longer
|
|
37
|
+
borrows the sentence a person's refusal uses; human-refusal and no-provenance wordings are
|
|
38
|
+
byte-for-byte unchanged (269 existing approval strings verified untouched).
|
|
39
|
+
- **`createAllowDenyPolicy` screens malformed `mcp__` names** (empty segment: `mcp__`,
|
|
40
|
+
`mcp__a__`) alongside the content form; `mcp__server` / `mcp__server__tool` and the
|
|
41
|
+
conditionally-retired `Task` spelling stay accepted. The constructor-level retired-name
|
|
42
|
+
screen added briefly after 5.18.0 was withdrawn — the roster-aware prepare-time audit
|
|
43
|
+
(`config.legacy_tool_name`, all three kinds) already owns that refusal.
|
|
44
|
+
|
|
3
45
|
## 5.18.0 — 2026-08-10
|
|
4
46
|
|
|
5
47
|
> Two mainline features land together: design/178 personal-assistant memory v1 (the retrieval pair
|
|
@@ -95,6 +95,7 @@ export type ResumeOutcome = {
|
|
|
95
95
|
updatedInput?: unknown;
|
|
96
96
|
reason?: string;
|
|
97
97
|
answer?: QuestionAnswer;
|
|
98
|
+
settledBy?: import("./tool-policy.js").ApprovalSettledBy;
|
|
98
99
|
} | {
|
|
99
100
|
gate: "resource_limit";
|
|
100
101
|
decision: "continue";
|
|
@@ -277,10 +278,10 @@ export declare function summarizeCheckpoint(cp: Checkpoint): CheckpointSummary;
|
|
|
277
278
|
export declare class CheckpointError extends Error {
|
|
278
279
|
readonly code: "checkpoint.already_exists" | "checkpoint.already_resolved" | "checkpoint.not_found" | "checkpoint.gate_mismatch" | "checkpoint.resume_aborted" | "checkpoint.invalid_outcome" | "checkpoint.unsupported_version" | "checkpoint.walltime_axis_retired" | "checkpoint.reopen_revote" | "checkpoint.reopened_concurrently" | "checkpoint.reopen_failed" | "steering.invalid_content" | "steering.queue_full" | "steering.duplicate_input_id" | "wake.gate_pending" | "wake.nothing_to_deliver" | "resume.parent_constraint_missing" | "resume.parent_constraint_mismatch";
|
|
279
280
|
readonly detail?: {
|
|
280
|
-
field?: "boundCallId" | "boundInputHash" | "answer";
|
|
281
|
+
field?: "boundCallId" | "boundInputHash" | "answer" | "settledBy";
|
|
281
282
|
} | undefined;
|
|
282
283
|
constructor(code: "checkpoint.already_exists" | "checkpoint.already_resolved" | "checkpoint.not_found" | "checkpoint.gate_mismatch" | "checkpoint.resume_aborted" | "checkpoint.invalid_outcome" | "checkpoint.unsupported_version" | "checkpoint.walltime_axis_retired" | "checkpoint.reopen_revote" | "checkpoint.reopened_concurrently" | "checkpoint.reopen_failed" | "steering.invalid_content" | "steering.queue_full" | "steering.duplicate_input_id" | "wake.gate_pending" | "wake.nothing_to_deliver" | "resume.parent_constraint_missing" | "resume.parent_constraint_mismatch", message: string, detail?: {
|
|
283
|
-
field?: "boundCallId" | "boundInputHash" | "answer";
|
|
284
|
+
field?: "boundCallId" | "boundInputHash" | "answer" | "settledBy";
|
|
284
285
|
} | undefined);
|
|
285
286
|
}
|
|
286
287
|
export type StoreDurability = "durable" | "process-local";
|
package/dist/core/hooks.d.ts
CHANGED
|
@@ -104,6 +104,7 @@ export declare function formatHookFeedback(text: string): string;
|
|
|
104
104
|
export interface ToolGateResult {
|
|
105
105
|
block?: boolean;
|
|
106
106
|
reason?: string;
|
|
107
|
+
settledBy?: import("./tool-policy.js").ApprovalSettledBy;
|
|
107
108
|
updatedInput?: unknown;
|
|
108
109
|
suspend?: {
|
|
109
110
|
token: import("./checkpoint-store.js").CheckpointToken;
|
package/dist/core/hooks.js
CHANGED
|
@@ -411,9 +411,11 @@ export async function runToolGate(input) {
|
|
|
411
411
|
if (input.permissionDenied) {
|
|
412
412
|
await notifier.notifyAsync(() => input.permissionDenied?.({ toolName, input: cloneObserverInput(currentInput), toolCallId, reason: denyReason, source: denySource }), "toolGate.permissionDenied");
|
|
413
413
|
}
|
|
414
|
+
const denySettledBy = decision.settledBy;
|
|
414
415
|
return {
|
|
415
416
|
block: true,
|
|
416
417
|
reason: formatHookFeedback(denyReason),
|
|
418
|
+
...(denySettledBy !== undefined ? { settledBy: denySettledBy } : {}),
|
|
417
419
|
preToolContext,
|
|
418
420
|
};
|
|
419
421
|
}
|
|
@@ -422,8 +424,10 @@ export async function runToolGate(input) {
|
|
|
422
424
|
if (rw !== undefined)
|
|
423
425
|
currentInput = rw;
|
|
424
426
|
}
|
|
427
|
+
const allowSettledBy = decision.action === "allow" ? decision.settledBy : undefined;
|
|
425
428
|
return {
|
|
426
429
|
updatedInput: currentInput === event.input ? undefined : currentInput,
|
|
430
|
+
...(allowSettledBy !== undefined ? { settledBy: allowSettledBy } : {}),
|
|
427
431
|
preToolContext,
|
|
428
432
|
};
|
|
429
433
|
}
|
|
@@ -56,7 +56,14 @@ export declare function confirmRuleApproval(opts: {
|
|
|
56
56
|
principal: string;
|
|
57
57
|
selectedCandidate?: number;
|
|
58
58
|
deps: RuleConsentDeps;
|
|
59
|
-
}): Promise<
|
|
59
|
+
}): Promise<ConfirmResult>;
|
|
60
|
+
export type ConfirmRefusalReason = "record_not_found" | "selection_missing" | "selection_invalid" | "selection_mismatch" | "batch_takes_no_selection" | "not_pending" | "conflict";
|
|
61
|
+
export type ConfirmResult = {
|
|
62
|
+
ok: true;
|
|
63
|
+
} | {
|
|
64
|
+
ok: false;
|
|
65
|
+
reason: ConfirmRefusalReason;
|
|
66
|
+
};
|
|
60
67
|
export type RedeemResult = {
|
|
61
68
|
status: "redeemed";
|
|
62
69
|
rule: string;
|
|
@@ -47,6 +47,11 @@ function parseRuleTicket(ticket) {
|
|
|
47
47
|
}
|
|
48
48
|
export async function prepareCardApproval(opts) {
|
|
49
49
|
const principal = requirePrincipal(opts.principal, "prepareCardApproval");
|
|
50
|
+
if ("candidates" in opts) {
|
|
51
|
+
const e = new Error("prepareCardApproval does not accept caller candidates — card options are minted by the engine from the adjudicated command");
|
|
52
|
+
e.code = "config.invalid_argument";
|
|
53
|
+
throw e;
|
|
54
|
+
}
|
|
50
55
|
if (opts.toolName !== CARD_RULE_TOOL)
|
|
51
56
|
return undefined;
|
|
52
57
|
const scope = opts.scope ?? { kind: "global" };
|
|
@@ -70,24 +75,30 @@ export async function prepareCardApproval(opts) {
|
|
|
70
75
|
const CARD_RULE_TOOL = "Bash";
|
|
71
76
|
export async function confirmRuleApproval(opts) {
|
|
72
77
|
const principal = requirePrincipal(opts.principal, "confirmRuleApproval");
|
|
78
|
+
const no = (reason) => ({ ok: false, reason });
|
|
73
79
|
const rec = await opts.deps.approvals.get(opts.approvalId);
|
|
74
80
|
if (rec === undefined || rec.principal !== principal)
|
|
75
|
-
return
|
|
81
|
+
return no("record_not_found");
|
|
76
82
|
if (rec.kind === "card") {
|
|
77
83
|
const chosen = opts.selectedCandidate;
|
|
78
|
-
if (chosen === undefined
|
|
79
|
-
return
|
|
80
|
-
if (
|
|
81
|
-
return
|
|
82
|
-
|
|
84
|
+
if (chosen === undefined)
|
|
85
|
+
return no("selection_missing");
|
|
86
|
+
if (!Number.isInteger(chosen) || rec.candidates[chosen] === undefined)
|
|
87
|
+
return no("selection_invalid");
|
|
88
|
+
if (rec.state === "approved" || rec.state === "redeemed") {
|
|
89
|
+
return rec.selectedCandidate === chosen ? { ok: true } : no("selection_mismatch");
|
|
90
|
+
}
|
|
91
|
+
const won = await opts.deps.approvals.cas(rec.id, rec.rev, { ...rec, rev: rec.rev + 1, state: "approved", selectedCandidate: chosen });
|
|
92
|
+
return won ? { ok: true } : no("conflict");
|
|
83
93
|
}
|
|
84
94
|
if (opts.selectedCandidate !== undefined)
|
|
85
|
-
return
|
|
95
|
+
return no("batch_takes_no_selection");
|
|
86
96
|
if (rec.state === "approved")
|
|
87
|
-
return true;
|
|
97
|
+
return { ok: true };
|
|
88
98
|
if (rec.state !== "pending")
|
|
89
|
-
return
|
|
90
|
-
|
|
99
|
+
return no("not_pending");
|
|
100
|
+
const won = await opts.deps.approvals.cas(rec.id, rec.rev, { ...rec, rev: rec.rev + 1, state: "approved" });
|
|
101
|
+
return won ? { ok: true } : no("conflict");
|
|
91
102
|
}
|
|
92
103
|
export async function redeemRuleTicket(opts) {
|
|
93
104
|
const principal = requirePrincipal(opts.principal, "redeemRuleTicket");
|
|
@@ -64,6 +64,7 @@ export interface Prepared {
|
|
|
64
64
|
hit: boolean;
|
|
65
65
|
};
|
|
66
66
|
blockedToolCalls: Set<string>;
|
|
67
|
+
approvalSettledBy: Map<string, import("../tool-policy.js").ApprovalSettledBy>;
|
|
67
68
|
nestedStats: NestedUsageAccum;
|
|
68
69
|
rewindNotes?: NonNullable<TaskResult["rewindNotes"]>;
|
|
69
70
|
cwdRef?: CwdRef;
|
|
@@ -20,7 +20,7 @@ import { createSubagentWorktreeHelper, forkGovernanceDenial } from "../../agents
|
|
|
20
20
|
import { createAgentTranscriptTool, AGENT_TRANSCRIPT_TOOL_NAME } from "../../agents/agent-transcript-tool.js";
|
|
21
21
|
import { createSendMessageTool, SEND_MESSAGE_TOOL_NAME } from "../../agents/send-message-tool.js";
|
|
22
22
|
import { SubagentRetainLedger } from "../../agents/retain-ledger.js";
|
|
23
|
-
import { askApproverIdentity, combinePolicies, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, describeThrown, refuseOutOfContractDecision, resolveAsk, toolPolicyNameSets, tryCloneArgs } from "../tool-policy.js";
|
|
23
|
+
import { askApproverIdentity, combinePolicies, isApprovalSettledBy, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, describeThrown, refuseOutOfContractDecision, resolveAsk, toolPolicyNameSets, tryCloneArgs } from "../tool-policy.js";
|
|
24
24
|
const PERSISTED_RULE_TOOL = "Bash";
|
|
25
25
|
import { findAdmittingRule, suggestRulesForCommand } from "../permission-rule-model.js";
|
|
26
26
|
import { ActiveSkillScope, createActiveSkillScopePolicy } from "./active-skill-scope.js";
|
|
@@ -3304,6 +3304,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3304
3304
|
}
|
|
3305
3305
|
const preToolContexts = new Map();
|
|
3306
3306
|
const blockedToolCalls = new Set();
|
|
3307
|
+
const approvalSettledBy = new Map();
|
|
3307
3308
|
const blockedTracked = Boolean(hooks?.postToolUse || hooks?.preToolUse || hooks?.postToolUseFailure || hooks?.postToolBatch);
|
|
3308
3309
|
const restoreSurfaceGap = ownedEnv !== undefined && isRemoteExecutionEnv(ownedEnv) && ownedEnv.capabilities.suspendable ? missingRestoreSurface(ownedEnv) : [];
|
|
3309
3310
|
const incompleteSuspendAdapter = restoreSurfaceGap.length > 0 ? restoreSurfaceGap : undefined;
|
|
@@ -4156,6 +4157,17 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
4156
4157
|
if (blockedTracked && (result.block || result.suspend)) {
|
|
4157
4158
|
blockedToolCalls.add(e.toolCallId);
|
|
4158
4159
|
}
|
|
4160
|
+
const reported = result.settledBy;
|
|
4161
|
+
if (reported !== undefined) {
|
|
4162
|
+
const settling = result.block === true;
|
|
4163
|
+
if (!isApprovalSettledBy(reported) || (!settling && reported !== "human")) {
|
|
4164
|
+
deps.onError?.(new Error(`a tool-gate settlement reported settledBy "${String(reported)}" on ${settling ? "a blocked" : "an executing"} call — ` +
|
|
4165
|
+
`it is one of "human" / "timeout" / "aborted", and only "human" can be the source of a call that runs; the frame carries no source`), { phase: "config", sessionId });
|
|
4166
|
+
}
|
|
4167
|
+
else {
|
|
4168
|
+
approvalSettledBy.set(e.toolCallId, reported);
|
|
4169
|
+
}
|
|
4170
|
+
}
|
|
4159
4171
|
return result.block
|
|
4160
4172
|
? { block: true, reason: result.reason }
|
|
4161
4173
|
: result.updatedInput !== undefined
|
|
@@ -4444,7 +4456,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
4444
4456
|
: undefined;
|
|
4445
4457
|
overheadState.promptChars = systemPrompt.length;
|
|
4446
4458
|
const preparedHolder = {};
|
|
4447
|
-
const buildPrepared = () => ({ harness, session, sessionId, taskRootPath, model, thinking, compModel, mcp: mcp, ...(a2a !== undefined && a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), cwdRef: handsCwdRef, ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), denyNarrowingPolicy, ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), releaseSignal, settleContentAskBindings, cacheBreakDetector, cacheFingerprint, wiringManifest, promptManifest, epochDeclaredSections, activeTools, ...(deferred.size > 0 ? { deferredToolNames: deferred } : {}), toolMaterializeStatic, deferDirectCall, ...(staticFaceForRef.current !== undefined ? { staticFaceFor: staticFaceForRef.current } : {}), ownedEnv, suspendRef, suspendProgressRef, reviewRef, remoteEnvFailures, reviewRequestRef, suspendLoopRef, suspendForResource, ...(suspendForPlatformLimit !== undefined ? { suspendForPlatformLimit } : {}), ...(envLifetimeSuspendAt !== undefined ? { envLifetimeSuspendAt } : {}), ...(usageGovernance !== undefined ? { usageGovernance } : {}), callIssuedAtRef, brainCallGuardrailRef, suspendForReview, resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, readTaskFile, recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent } } : {}), planModeRef, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, listBackgroundTasks, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}) });
|
|
4459
|
+
const buildPrepared = () => ({ harness, session, sessionId, taskRootPath, model, thinking, compModel, mcp: mcp, ...(a2a !== undefined && a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, approvalSettledBy, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), cwdRef: handsCwdRef, ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), denyNarrowingPolicy, ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), releaseSignal, settleContentAskBindings, cacheBreakDetector, cacheFingerprint, wiringManifest, promptManifest, epochDeclaredSections, activeTools, ...(deferred.size > 0 ? { deferredToolNames: deferred } : {}), toolMaterializeStatic, deferDirectCall, ...(staticFaceForRef.current !== undefined ? { staticFaceFor: staticFaceForRef.current } : {}), ownedEnv, suspendRef, suspendProgressRef, reviewRef, remoteEnvFailures, reviewRequestRef, suspendLoopRef, suspendForResource, ...(suspendForPlatformLimit !== undefined ? { suspendForPlatformLimit } : {}), ...(envLifetimeSuspendAt !== undefined ? { envLifetimeSuspendAt } : {}), ...(usageGovernance !== undefined ? { usageGovernance } : {}), callIssuedAtRef, brainCallGuardrailRef, suspendForReview, resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, readTaskFile, recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent } } : {}), planModeRef, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, listBackgroundTasks, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}) });
|
|
4448
4460
|
const prepared = buildPrepared();
|
|
4449
4461
|
preparedHolder.current = prepared;
|
|
4450
4462
|
return prepared;
|
|
@@ -5,6 +5,7 @@ import { type TaskOutcome } from "../task-outcome.js";
|
|
|
5
5
|
import { type SideQuerySpec, type SideQueryResult } from "../side-query.js";
|
|
6
6
|
import type { SessionStore } from "../session.js";
|
|
7
7
|
import { type RecoveredOrphan } from "../session-reconcile.js";
|
|
8
|
+
import { type ApprovalSettledBy } from "../tool-policy.js";
|
|
8
9
|
import type { AgentDefinition, RunnerDeps, TaskEvent, TaskResult, TaskSpec, TaskStream } from "../types.js";
|
|
9
10
|
export type ResumeTaskConfig = Omit<TaskSpec, "objective" | "sessionId">;
|
|
10
11
|
interface ResumeRun {
|
|
@@ -17,12 +18,13 @@ interface ResumeRun {
|
|
|
17
18
|
onEnvRestoreFailed?: (reason: ReopenReason) => Promise<void>;
|
|
18
19
|
decisionDelivered?: boolean;
|
|
19
20
|
}
|
|
20
|
-
declare function toolEndBodyFrom(result: unknown, isError: boolean): {
|
|
21
|
+
declare function toolEndBodyFrom(result: unknown, isError: boolean, settledBy?: ApprovalSettledBy): {
|
|
21
22
|
output?: unknown;
|
|
22
23
|
truncated?: boolean;
|
|
23
24
|
totalChars?: number;
|
|
24
25
|
structured?: unknown;
|
|
25
26
|
errorCode?: string;
|
|
27
|
+
settledBy?: ApprovalSettledBy;
|
|
26
28
|
};
|
|
27
29
|
export declare function reconciledToolEndBody(orphan: Pick<RecoveredOrphan, "text" | "errorKind">): ReturnType<typeof toolEndBodyFrom>;
|
|
28
30
|
export declare const GOVERNANCE_READ_STALLED: unique symbol;
|
|
@@ -38,7 +38,7 @@ import { delimitUntrusted, inlineUntrusted, sanitizeUntrustedText } from "../unt
|
|
|
38
38
|
import { reconcileInterruptedSession } from "../session-reconcile.js";
|
|
39
39
|
import { RunnerSharedToolResultStore } from "../tool-result-store.js";
|
|
40
40
|
import { formatDiagnosticsBlock } from "../lsp-diagnostics.js";
|
|
41
|
-
import { refuseOutOfContractDecision, toolPolicyNameSets } from "../tool-policy.js";
|
|
41
|
+
import { isApprovalSettledBy, refuseOutOfContractDecision, toolPolicyNameSets } from "../tool-policy.js";
|
|
42
42
|
import { defaultTaskRegistry } from "../task-registry.js";
|
|
43
43
|
import { discloseDroppedPending, isDelegatedAgentTerminal, PendingSessionNotifications, renderTaskNotificationXml, SystemInjectionQueue, taskNotificationDedupKey } from "../task-notification.js";
|
|
44
44
|
import { ToolDetachHub } from "../tool-detach.js";
|
|
@@ -126,7 +126,7 @@ function resumeDecisionWasNegative(resume) {
|
|
|
126
126
|
}
|
|
127
127
|
const DEFERRED_REISSUE = "[DEFERRED] This tool call shared a batch with a call that suspended for durable approval, so it was " +
|
|
128
128
|
"NOT executed on resume. If you still need it, issue it again now.";
|
|
129
|
-
function toolEndBodyFrom(result, isError) {
|
|
129
|
+
function toolEndBodyFrom(result, isError, settledBy) {
|
|
130
130
|
const o = toolOutputFrom(result);
|
|
131
131
|
const st = structuredFrom(result);
|
|
132
132
|
const code = isError ? result?.details?.code : undefined;
|
|
@@ -134,6 +134,7 @@ function toolEndBodyFrom(result, isError) {
|
|
|
134
134
|
...(o !== undefined ? { output: o.output, ...(o.truncated ? { truncated: true } : {}), ...(o.totalChars !== undefined ? { totalChars: o.totalChars } : {}) } : {}),
|
|
135
135
|
...(st !== undefined ? { structured: st } : {}),
|
|
136
136
|
...(typeof code === "string" ? { errorCode: code } : {}),
|
|
137
|
+
...(settledBy !== undefined ? { settledBy } : {}),
|
|
137
138
|
};
|
|
138
139
|
}
|
|
139
140
|
export function reconciledToolEndBody(orphan) {
|
|
@@ -1202,13 +1203,16 @@ function makeHarnessHandlers(prepared, stats, rs, deps) {
|
|
|
1202
1203
|
prepared.lspDiagnostics.nudge(p);
|
|
1203
1204
|
}
|
|
1204
1205
|
}
|
|
1206
|
+
const settledBy = prepared.approvalSettledBy.get(event.toolCallId);
|
|
1207
|
+
if (settledBy !== undefined)
|
|
1208
|
+
prepared.approvalSettledBy.delete(event.toolCallId);
|
|
1205
1209
|
pushContent({
|
|
1206
1210
|
type: "tool_end",
|
|
1207
1211
|
toolCallId: event.toolCallId,
|
|
1208
1212
|
toolName: event.toolName,
|
|
1209
1213
|
...(toolLabels.get(event.toolName) !== undefined ? { label: toolLabels.get(event.toolName) } : {}),
|
|
1210
1214
|
isError: event.isError,
|
|
1211
|
-
...toolEndBodyFrom(event.result, event.isError),
|
|
1215
|
+
...toolEndBodyFrom(event.result, event.isError, settledBy),
|
|
1212
1216
|
...ident(),
|
|
1213
1217
|
});
|
|
1214
1218
|
announceWorkspaceMove();
|
|
@@ -3617,6 +3621,14 @@ export class Runner {
|
|
|
3617
3621
|
if (decision !== "allow" && decision !== "deny") {
|
|
3618
3622
|
throw new CheckpointError("checkpoint.invalid_outcome", `resume decision "${describeSuppliedValue(decision)}" is outside the policy_ask domain — a decide is exactly "allow" or "deny"; refusing pre-CAS, the checkpoint stays pending`);
|
|
3619
3623
|
}
|
|
3624
|
+
const settledBy = decide.settledBy;
|
|
3625
|
+
if (settledBy !== undefined && !isApprovalSettledBy(settledBy)) {
|
|
3626
|
+
throw new CheckpointError("checkpoint.invalid_outcome", `resume settledBy "${describeSuppliedValue(settledBy)}" is outside the settlement vocabulary — it is exactly "human", "timeout" or "aborted" (or omitted); refusing pre-CAS, the checkpoint stays pending`, { field: "settledBy" });
|
|
3627
|
+
}
|
|
3628
|
+
if (settledBy !== undefined && settledBy !== "human" && decision === "allow") {
|
|
3629
|
+
throw new CheckpointError("checkpoint.invalid_outcome", `resume carries decision "allow" with settledBy "${settledBy}" — a non-human settlement is a fail-closed end (nobody answered), so it cannot be the source of an approval that EXECUTES; ` +
|
|
3630
|
+
"supply \"human\", or omit the field if the allow came from configuration rather than a person; refusing pre-CAS, the checkpoint stays pending", { field: "settledBy" });
|
|
3631
|
+
}
|
|
3620
3632
|
const reason = decide.reason;
|
|
3621
3633
|
assertOutcomeText(reason, "reason");
|
|
3622
3634
|
plainPolicyOutcome = {
|
|
@@ -3627,6 +3639,7 @@ export class Runner {
|
|
|
3627
3639
|
...(updatedInput !== undefined ? { updatedInput } : {}),
|
|
3628
3640
|
...(reason !== undefined ? { reason } : {}),
|
|
3629
3641
|
...(redeemedAnswer !== undefined ? { answer: redeemedAnswer } : {}),
|
|
3642
|
+
...(settledBy !== undefined ? { settledBy } : {}),
|
|
3630
3643
|
};
|
|
3631
3644
|
if (plainPolicyOutcome.decision === "deny" && plainPolicyOutcome.reason && sanitizeUntrustedText(plainPolicyOutcome.reason) !== plainPolicyOutcome.reason) {
|
|
3632
3645
|
throw new CheckpointError("checkpoint.invalid_outcome", "resume deny/reject reason must not contain a </system-reminder> tag");
|
|
@@ -3823,9 +3836,14 @@ export class Runner {
|
|
|
3823
3836
|
const resolvedArgs = pendingAction.toolName === ASK_USER_QUESTION_TOOL_NAME ? pendingAction.args : (outcome.updatedInput !== undefined ? outcome.updatedInput : pendingAction.args);
|
|
3824
3837
|
const pendingLabel = (() => { const l = prepared.tools.find((t) => t.name === pendingAction.toolName)?.label; return l !== undefined && l !== pendingAction.toolName ? { label: l } : {}; })();
|
|
3825
3838
|
emit({ type: "tool_start", toolCallId: pendingAction.toolCallId, toolName: pendingAction.toolName, ...pendingLabel, args: resolvedArgs });
|
|
3826
|
-
const emitEnd = (isError, result) => emit({ type: "tool_end", toolCallId: pendingAction.toolCallId, toolName: pendingAction.toolName, ...pendingLabel, isError, ...toolEndBodyFrom(result, isError) });
|
|
3839
|
+
const emitEnd = (isError, result) => emit({ type: "tool_end", toolCallId: pendingAction.toolCallId, toolName: pendingAction.toolName, ...pendingLabel, isError, ...toolEndBodyFrom(result, isError, outcome.settledBy) });
|
|
3827
3840
|
if (outcome.decision === "deny") {
|
|
3828
|
-
const
|
|
3841
|
+
const defaultDenial = outcome.settledBy === "timeout"
|
|
3842
|
+
? `No one answered the approval request for the pending tool call "${pendingAction.toolName}" — the approval window elapsed with no answer, so it was not executed.`
|
|
3843
|
+
: outcome.settledBy === "aborted"
|
|
3844
|
+
? `The approval for the pending tool call "${pendingAction.toolName}" ended without anyone deciding it (it was cancelled or could not be delivered), so it was not executed.`
|
|
3845
|
+
: `The pending tool call "${pendingAction.toolName}" was denied by an approver.`;
|
|
3846
|
+
const reason = outcome.reason ? delimitUntrusted("reviewer note", outcome.reason) : defaultDenial;
|
|
3829
3847
|
emitEnd(true, { content: formatHookFeedback(reason) });
|
|
3830
3848
|
const eid = await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, formatHookFeedback(reason), true));
|
|
3831
3849
|
emitCommitted(eid, "toolResult", pendingAction.toolCallId);
|
|
@@ -9,11 +9,15 @@ export interface ToolCallRequest {
|
|
|
9
9
|
};
|
|
10
10
|
}
|
|
11
11
|
export type DecisionReason = "rule" | "mode" | "hook" | "safety" | "classifier" | "persisted_rule";
|
|
12
|
+
export type ApprovalSettledBy = "human" | "timeout" | "aborted";
|
|
13
|
+
export declare const APPROVAL_SETTLED_BY_VALUES: readonly ApprovalSettledBy[];
|
|
14
|
+
export declare function isApprovalSettledBy(v: unknown): v is ApprovalSettledBy;
|
|
12
15
|
export type PermissionResult = {
|
|
13
16
|
action: "allow";
|
|
14
17
|
updatedInput?: unknown;
|
|
15
18
|
message?: string;
|
|
16
19
|
decisionReason?: DecisionReason;
|
|
20
|
+
settledBy?: Extract<ApprovalSettledBy, "human">;
|
|
17
21
|
} | {
|
|
18
22
|
action: "ask";
|
|
19
23
|
updatedInput?: unknown;
|
|
@@ -25,6 +29,7 @@ export type PermissionResult = {
|
|
|
25
29
|
updatedInput?: unknown;
|
|
26
30
|
message?: string;
|
|
27
31
|
decisionReason?: DecisionReason;
|
|
32
|
+
settledBy?: ApprovalSettledBy;
|
|
28
33
|
};
|
|
29
34
|
export declare function decisionText(d: PermissionResult): string | undefined;
|
|
30
35
|
export interface ToolPolicy {
|
package/dist/core/tool-policy.js
CHANGED
|
@@ -5,6 +5,10 @@ import { boundInputHashOf } from "./canonical-json.js";
|
|
|
5
5
|
import { inlineUntrusted } from "./untrusted-text.js";
|
|
6
6
|
import { parsePermissionRule } from "./permission-rules.js";
|
|
7
7
|
import { writeTargetPath } from "../tools/fs/safety.js";
|
|
8
|
+
export const APPROVAL_SETTLED_BY_VALUES = ["human", "timeout", "aborted"];
|
|
9
|
+
export function isApprovalSettledBy(v) {
|
|
10
|
+
return typeof v === "string" && APPROVAL_SETTLED_BY_VALUES.includes(v);
|
|
11
|
+
}
|
|
8
12
|
export function decisionText(d) {
|
|
9
13
|
return d.message;
|
|
10
14
|
}
|
|
@@ -19,6 +23,7 @@ export function refuseOutOfContractDecision(d) {
|
|
|
19
23
|
return d;
|
|
20
24
|
return { action: "deny", message: RETIRED_TEXT_FIELD_DENY_MESSAGE, decisionReason: "rule" };
|
|
21
25
|
}
|
|
26
|
+
const DEADLINE_ELAPSED = Symbol("approval.deadline_elapsed");
|
|
22
27
|
function withTimeout(p, ms, onTimeout) {
|
|
23
28
|
if (ms === undefined) {
|
|
24
29
|
return p;
|
|
@@ -51,6 +56,18 @@ export function createAllowDenyPolicy(opts) {
|
|
|
51
56
|
return undefined;
|
|
52
57
|
const kept = [];
|
|
53
58
|
for (const entry of entries) {
|
|
59
|
+
if (entry.startsWith("mcp__")) {
|
|
60
|
+
const segments = entry.slice("mcp__".length).split("__");
|
|
61
|
+
if (segments.some((seg) => seg.length === 0)) {
|
|
62
|
+
invalid.push({
|
|
63
|
+
entry,
|
|
64
|
+
list,
|
|
65
|
+
message: `"${entry}" is a malformed MCP tool name (empty segment) — it can never match any mounted tool. ` +
|
|
66
|
+
`Use \`mcp__<server>\` for every tool of a server, or \`mcp__<server>__<tool>\` for one tool.`,
|
|
67
|
+
});
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
54
71
|
if (parsePermissionRule(entry).ruleContent === undefined) {
|
|
55
72
|
kept.push(entry);
|
|
56
73
|
continue;
|
|
@@ -118,25 +135,37 @@ export function createApprovalPolicy(opts) {
|
|
|
118
135
|
}
|
|
119
136
|
if (need.has(toolName)) {
|
|
120
137
|
if (signal?.aborted) {
|
|
121
|
-
return { action: "deny", message: `approval aborted for "${req.toolName}" (task ended)
|
|
138
|
+
return { action: "deny", message: `approval aborted for "${req.toolName}" (task ended)`, settledBy: "aborted" };
|
|
122
139
|
}
|
|
123
140
|
let ok;
|
|
124
141
|
try {
|
|
125
|
-
ok = await withTimeout(Promise.resolve(opts.approve(req, signal)), opts.approvalTimeoutMs, () =>
|
|
142
|
+
ok = await withTimeout(Promise.resolve(opts.approve(req, signal)), opts.approvalTimeoutMs, () => DEADLINE_ELAPSED);
|
|
126
143
|
}
|
|
127
144
|
catch (err) {
|
|
128
145
|
return {
|
|
129
146
|
action: "deny",
|
|
130
147
|
message: `approval errored for "${req.toolName}": ${describeThrown(err)}`,
|
|
148
|
+
settledBy: "aborted",
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
if (ok === DEADLINE_ELAPSED) {
|
|
152
|
+
return {
|
|
153
|
+
action: "deny",
|
|
154
|
+
message: `no one answered the approval request for "${req.toolName}" — the approval window elapsed ` +
|
|
155
|
+
`(${opts.approvalTimeoutMs}ms) with no answer; denied fail-closed`,
|
|
156
|
+
settledBy: "timeout",
|
|
131
157
|
};
|
|
132
158
|
}
|
|
159
|
+
if (signal?.aborted) {
|
|
160
|
+
return { action: "deny", message: `approval aborted for "${req.toolName}" (task ended)`, settledBy: "aborted" };
|
|
161
|
+
}
|
|
133
162
|
const okRaw = ok;
|
|
134
163
|
if (okRaw === true)
|
|
135
|
-
return
|
|
164
|
+
return { action: "allow", settledBy: "human" };
|
|
136
165
|
if (okRaw !== false) {
|
|
137
|
-
return { action: "deny", message: `approval callback for "${req.toolName}" returned an out-of-contract value (${typeof ok}) — denied fail-closed (this policy's \`approve\` returns a boolean: return true or false)
|
|
166
|
+
return { action: "deny", message: `approval callback for "${req.toolName}" returned an out-of-contract value (${typeof ok}) — denied fail-closed (this policy's \`approve\` returns a boolean: return true or false)`, settledBy: "aborted" };
|
|
138
167
|
}
|
|
139
|
-
return { action: "deny", message: `approval denied for "${req.toolName}"
|
|
168
|
+
return { action: "deny", message: `approval denied for "${req.toolName}"`, settledBy: "human" };
|
|
140
169
|
}
|
|
141
170
|
if (opts.denyByDefault && !auto.has(toolName)) {
|
|
142
171
|
return { action: "deny", message: `tool "${req.toolName}" requires explicit allow` };
|
|
@@ -153,6 +182,7 @@ export function combinePolicies(...policies) {
|
|
|
153
182
|
let asked;
|
|
154
183
|
let current = req;
|
|
155
184
|
let rewrite;
|
|
185
|
+
let settled;
|
|
156
186
|
for (const p of policies) {
|
|
157
187
|
const d = refuseOutOfContractDecision(await p.check(current, signal));
|
|
158
188
|
if (d.action === "deny") {
|
|
@@ -162,6 +192,11 @@ export function combinePolicies(...policies) {
|
|
|
162
192
|
current = { ...current, args: d.updatedInput };
|
|
163
193
|
rewrite = d;
|
|
164
194
|
}
|
|
195
|
+
if (d.action === "allow") {
|
|
196
|
+
const supplied = d.settledBy;
|
|
197
|
+
if (supplied !== undefined)
|
|
198
|
+
settled = supplied;
|
|
199
|
+
}
|
|
165
200
|
if (d.action === "ask" && (asked === undefined || (d.requiresRealApproval === true && asked.requiresRealApproval !== true))) {
|
|
166
201
|
asked = d;
|
|
167
202
|
}
|
|
@@ -170,7 +205,8 @@ export function combinePolicies(...policies) {
|
|
|
170
205
|
const merged = rewrite?.updatedInput;
|
|
171
206
|
return merged !== undefined ? { ...asked, updatedInput: merged } : asked;
|
|
172
207
|
}
|
|
173
|
-
|
|
208
|
+
const allowed = rewrite ?? ALLOW;
|
|
209
|
+
return settled !== undefined ? { ...allowed, settledBy: settled } : allowed;
|
|
174
210
|
},
|
|
175
211
|
};
|
|
176
212
|
}
|
|
@@ -643,7 +679,7 @@ export async function resolveAsk(req, onAsk, signal) {
|
|
|
643
679
|
};
|
|
644
680
|
}
|
|
645
681
|
if (signal?.aborted) {
|
|
646
|
-
return { action: "deny", message: `approval aborted for "${req.toolName}" (task ended)`, decisionReason: "mode" };
|
|
682
|
+
return { action: "deny", message: `approval aborted for "${req.toolName}" (task ended)`, decisionReason: "mode", settledBy: "aborted" };
|
|
647
683
|
}
|
|
648
684
|
const presented = tryCloneArgs(req.args);
|
|
649
685
|
if (!presented.ok) {
|
|
@@ -651,6 +687,7 @@ export async function resolveAsk(req, onAsk, signal) {
|
|
|
651
687
|
action: "deny",
|
|
652
688
|
message: `approval for "${req.toolName}" could not present the args safely (unclonable value: ${presented.reason}) — denied fail-closed`,
|
|
653
689
|
decisionReason: "mode",
|
|
690
|
+
settledBy: "aborted",
|
|
654
691
|
};
|
|
655
692
|
}
|
|
656
693
|
let ok;
|
|
@@ -661,6 +698,7 @@ export async function resolveAsk(req, onAsk, signal) {
|
|
|
661
698
|
action: "deny",
|
|
662
699
|
message: `approval for "${req.toolName}" could not present the args safely (unclonable value: ${approverView.reason}) — denied fail-closed`,
|
|
663
700
|
decisionReason: "mode",
|
|
701
|
+
settledBy: "aborted",
|
|
664
702
|
};
|
|
665
703
|
}
|
|
666
704
|
ok = await onAsk({ ...req, boundInputHash: boundInputHashOf(presented.value), args: approverView.value }, signal);
|
|
@@ -670,42 +708,49 @@ export async function resolveAsk(req, onAsk, signal) {
|
|
|
670
708
|
action: "deny",
|
|
671
709
|
message: `approval errored for "${req.toolName}": ${describeThrown(err)}`,
|
|
672
710
|
decisionReason: "mode",
|
|
711
|
+
settledBy: "aborted",
|
|
673
712
|
};
|
|
674
713
|
}
|
|
714
|
+
if (signal?.aborted) {
|
|
715
|
+
return { action: "deny", message: `approval aborted for "${req.toolName}" (task ended)`, decisionReason: "mode", settledBy: "aborted" };
|
|
716
|
+
}
|
|
675
717
|
if (ok === "unavailable") {
|
|
676
718
|
return {
|
|
677
719
|
action: "deny",
|
|
678
720
|
message: `approval required for "${req.toolName}" but the approver reported unavailable (no reachable ` +
|
|
679
721
|
`operator for this ask) and no durable approval gate is armed — denied fail-closed: ${req.message}`,
|
|
680
722
|
decisionReason: "mode",
|
|
723
|
+
settledBy: "aborted",
|
|
681
724
|
approverUnavailable: true,
|
|
682
725
|
};
|
|
683
726
|
}
|
|
684
727
|
if (typeof ok === "object" && ok !== null) {
|
|
685
728
|
if (ok.allow !== true) {
|
|
686
|
-
return { action: "deny", message: `approval denied for "${req.toolName}": ${req.message}`, decisionReason: "mode" };
|
|
729
|
+
return { action: "deny", message: `approval denied for "${req.toolName}": ${req.message}`, decisionReason: "mode", settledBy: "human" };
|
|
687
730
|
}
|
|
688
731
|
if (ok.updatedInput === undefined)
|
|
689
|
-
return { action: "allow", decisionReason: "mode", presentedInput: presented.value };
|
|
732
|
+
return { action: "allow", decisionReason: "mode", presentedInput: presented.value, settledBy: "human" };
|
|
690
733
|
const edit = tryCloneArgs(ok.updatedInput);
|
|
691
734
|
if (!edit.ok) {
|
|
692
735
|
return {
|
|
693
736
|
action: "deny",
|
|
694
737
|
message: `the approved edit for "${req.toolName}" is not safely clonable (${edit.reason}) — denied fail-closed`,
|
|
695
738
|
decisionReason: "mode",
|
|
739
|
+
settledBy: "aborted",
|
|
696
740
|
};
|
|
697
741
|
}
|
|
698
|
-
return { action: "allow", updatedInput: edit.value, decisionReason: "mode" };
|
|
742
|
+
return { action: "allow", updatedInput: edit.value, decisionReason: "mode", settledBy: "human" };
|
|
699
743
|
}
|
|
700
744
|
const okRaw = ok;
|
|
701
745
|
if (okRaw === true)
|
|
702
|
-
return { action: "allow", decisionReason: "mode", presentedInput: presented.value };
|
|
746
|
+
return { action: "allow", decisionReason: "mode", presentedInput: presented.value, settledBy: "human" };
|
|
703
747
|
if (okRaw !== false) {
|
|
704
748
|
return {
|
|
705
749
|
action: "deny",
|
|
706
750
|
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)`,
|
|
707
751
|
decisionReason: "mode",
|
|
752
|
+
settledBy: "aborted",
|
|
708
753
|
};
|
|
709
754
|
}
|
|
710
|
-
return { action: "deny", message: `approval denied for "${req.toolName}": ${req.message}`, decisionReason: "mode" };
|
|
755
|
+
return { action: "deny", message: `approval denied for "${req.toolName}": ${req.message}`, decisionReason: "mode", settledBy: "human" };
|
|
711
756
|
}
|
package/dist/core/types.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -122,14 +122,14 @@ export type { SchedulerCapability, SchedulerErrorCode, ScheduledIntent, Schedule
|
|
|
122
122
|
export { createSchedulerTools, type SchedulerToolContext, SCHEDULE_WAKEUP_TOOL_NAME, AUTONOMOUS_LOOP_SENTINEL, AUTONOMOUS_LOOP_DYNAMIC_SENTINEL, } from "./tools/scheduler-tools.js";
|
|
123
123
|
export { resolveAutonomousLoopPrompt, AUTONOMOUS_LOOP_PREAMBLE, AUTONOMOUS_LOOP_PREAMBLE_PERSISTENT, type AutonomousLoopPromptOptions, } from "./tools/loop-tick.js";
|
|
124
124
|
export { tightenTaskSpec, TaskSpecTightenError } from "./core/tighten-task-spec.js";
|
|
125
|
-
export { createAllowDenyPolicy, createApprovalPolicy, COARSE_SHELL_TOOLS, createCoarseCommandNamePolicy, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, findUnverifiableRecursiveDelete, combinePolicies, decisionText, resolveAsk, toolPolicyNameSets, type ToolPolicyNameSets, type NamedToolPolicy, type ToolPolicy, type ToolCallRequest, type PermissionResult, type DecisionReason, type OnAsk, type AskOutcome, type ResolvedAsk, type AskRequest, type AskDelegationProvenance, } from "./core/tool-policy.js";
|
|
125
|
+
export { createAllowDenyPolicy, createApprovalPolicy, COARSE_SHELL_TOOLS, createCoarseCommandNamePolicy, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, findUnverifiableRecursiveDelete, combinePolicies, decisionText, resolveAsk, toolPolicyNameSets, type ToolPolicyNameSets, type NamedToolPolicy, type ToolPolicy, type ToolCallRequest, type PermissionResult, type DecisionReason, type ApprovalSettledBy, APPROVAL_SETTLED_BY_VALUES, isApprovalSettledBy, type OnAsk, type AskOutcome, type ResolvedAsk, type AskRequest, type AskDelegationProvenance, } from "./core/tool-policy.js";
|
|
126
126
|
export { parseAutoModeResponse, createAutoModeDecider, type AutoModeVerdict, type AutoModeDecider, type AutoModeDeciderOptions, type AutoModeClassifyFn, type AutoModeClassifyInput, } from "./core/auto-mode.js";
|
|
127
127
|
export { buildAutoModePrompt, renderAutoModeWindow, renderAutoModeAction, AUTO_MODE_DEFAULTS_SENTINEL, type AutoModeRules, type BuildAutoModePromptOptions, type AutoModeWindowOptions, } from "./core/auto-mode-prompt.js";
|
|
128
128
|
export { AUTO_MODE_BASE_PROMPT, AUTO_MODE_PERMISSIONS_EXTERNAL } from "./core/auto-mode-prompt-assets.js";
|
|
129
129
|
export { createPermissionRulePolicy, validatePermissionRules, parsePermissionRule, wildcardMatch, type PermissionRule, type ParsedPermissionRule, type PermissionRuleIssue, type PermissionRuleCaps, type PermissionRulePolicyOptions, } from "./core/permission-rules.js";
|
|
130
130
|
export { parseAllowRuleText, formatAllowRuleText, ruleAdmitsCommand, findAdmittingRule, suggestRulesForCommand, scopeCoversCwd, pathWithinRoot, isRuleLive, BARE_INTERPRETER_NAMES, MAX_RULE_TEXT_CHARS, type PersistedAllowRule, type RuleTombstone, type RuleScope, type RuleDot, type RuleAdd, type RuleAddOrigin, type RuleSuggestion, type RuleReject, type RuleRejectCode, type ParsedAllowRule, type PersistedRuleTool, type PersistedRuleMatch, } from "./core/permission-rule-model.js";
|
|
131
131
|
export { removePersistedRule, applyTombstones, sameScope, InMemoryPermissionRuleStore, EMPTY_RULE_STORE, type PermissionRuleStore, type PermissionRuleStoreProvider, type StoredAllowRules, type RemoveResult, type PutResult, } from "./core/permission-rule-store.js";
|
|
132
|
-
export { prepareCardApproval, confirmRuleApproval, redeemRuleTicket, redeemRuleBatch, prepareCcImport, prepareStarterBatch, mintRuleTicket, STARTER_RULES, InMemoryRuleApprovalRecordStore, type RuleTicket, type RuleCandidate, type RuleApprovalKind, type RuleApprovalRecord, type RuleApprovalRecordStore, type RuleConsentDeps, type RedeemResult, type CcImportLayer, type ImportedSettingsLayer, type ImportPreview, type ImportResult, } from "./core/permission-rule-consent.js";
|
|
132
|
+
export { prepareCardApproval, confirmRuleApproval, type ConfirmResult, type ConfirmRefusalReason, redeemRuleTicket, redeemRuleBatch, prepareCcImport, prepareStarterBatch, mintRuleTicket, STARTER_RULES, InMemoryRuleApprovalRecordStore, type RuleTicket, type RuleCandidate, type RuleApprovalKind, type RuleApprovalRecord, type RuleApprovalRecordStore, type RuleConsentDeps, type RedeemResult, type CcImportLayer, type ImportedSettingsLayer, type ImportPreview, type ImportResult, } from "./core/permission-rule-consent.js";
|
|
133
133
|
export { FilePermissionRuleStoreProvider } from "./stores/file/permission-rule-store.js";
|
|
134
134
|
export { formatHookFeedback, runToolGate, createHookEnvCapabilities, type Hooks, type HookToolContext, type HookEnvCapabilities, type HookToolOutput, type PreToolUseResult, type PostToolUseResult, type UserPromptSubmitResult, type HookToolFailure, type PostToolUseFailureResult, type PostToolBatchCall, type PostToolBatchResult, type PreCompactContext, type PreCompactResult, type PostCompactContext, type StopFailureContext, type PermissionDeniedPayload, type PermissionDeniedSource, } from "./core/hooks.js";
|
|
135
135
|
export { InMemoryMemoryStore, composeMemoryBlock, composeLayeredMemoryBlock, normalizeMemorySpec, type NormalizedMemorySpec, type MemorySpecInput, supportsConsolidation, supportsPeriodicConsolidation, firstSentence, expandLexicalTerms, lexicalSearchMatch, type Embedder, classifyPromotable, enforcePromotableWriteGate, guardedMemoryStore, MemoryGateError, detectSecret, enforceSecretWriteGate, enforceStructuredNoteSecretGate, type UtilityGate, type MemoryStore, type MemoryVectorMode, type ScoredMemory, type MemoryNoteHeader, type MemoryNoteRecord, type MemoryNoteType, type StructuredNoteInput, } from "./core/memory.js";
|
package/dist/index.js
CHANGED
|
@@ -107,7 +107,7 @@ export { hasScheduler, isValidCronExpr, SchedulerError } from "./core/scheduler.
|
|
|
107
107
|
export { createSchedulerTools, SCHEDULE_WAKEUP_TOOL_NAME, AUTONOMOUS_LOOP_SENTINEL, AUTONOMOUS_LOOP_DYNAMIC_SENTINEL, } from "./tools/scheduler-tools.js";
|
|
108
108
|
export { resolveAutonomousLoopPrompt, AUTONOMOUS_LOOP_PREAMBLE, AUTONOMOUS_LOOP_PREAMBLE_PERSISTENT, } from "./tools/loop-tick.js";
|
|
109
109
|
export { tightenTaskSpec, TaskSpecTightenError } from "./core/tighten-task-spec.js";
|
|
110
|
-
export { createAllowDenyPolicy, createApprovalPolicy, COARSE_SHELL_TOOLS, createCoarseCommandNamePolicy, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, findUnverifiableRecursiveDelete, combinePolicies, decisionText, resolveAsk, toolPolicyNameSets, } from "./core/tool-policy.js";
|
|
110
|
+
export { createAllowDenyPolicy, createApprovalPolicy, COARSE_SHELL_TOOLS, createCoarseCommandNamePolicy, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, findUnverifiableRecursiveDelete, combinePolicies, decisionText, resolveAsk, toolPolicyNameSets, APPROVAL_SETTLED_BY_VALUES, isApprovalSettledBy, } from "./core/tool-policy.js";
|
|
111
111
|
export { parseAutoModeResponse, createAutoModeDecider, } from "./core/auto-mode.js";
|
|
112
112
|
export { buildAutoModePrompt, renderAutoModeWindow, renderAutoModeAction, AUTO_MODE_DEFAULTS_SENTINEL, } from "./core/auto-mode-prompt.js";
|
|
113
113
|
export { AUTO_MODE_BASE_PROMPT, AUTO_MODE_PERMISSIONS_EXTERNAL } from "./core/auto-mode-prompt-assets.js";
|