@sema-agent/core 5.18.1 → 5.20.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 +144 -0
- package/dist/agents/roster-store.js +3 -0
- package/dist/brain/circuit-breaker.js +14 -3
- package/dist/brain/timeout.d.ts +1 -0
- package/dist/brain/timeout.js +11 -0
- package/dist/core/background-agent-store.d.ts +1 -0
- package/dist/core/background-agent-store.js +5 -0
- package/dist/core/fs-write-gate-policy.js +1 -1
- package/dist/core/hooks.d.ts +3 -1
- package/dist/core/hooks.js +32 -0
- package/dist/core/mailbox-store.js +2 -0
- package/dist/core/mcp.d.ts +4 -0
- package/dist/core/mcp.js +58 -11
- package/dist/core/retention-policy.d.ts +7 -0
- package/dist/core/retention-policy.js +21 -0
- package/dist/core/runner/active-skill-scope.js +1 -1
- package/dist/core/runner/prepare-task.d.ts +3 -0
- package/dist/core/runner/prepare-task.js +195 -121
- package/dist/core/runner/runtask.js +29 -4
- package/dist/core/runner/session-rule-policy.js +1 -1
- package/dist/core/sensitive-path-policy.js +1 -1
- package/dist/core/task-registry-agent.js +2 -0
- package/dist/core/tool-policy.d.ts +1 -0
- package/dist/core/tool-policy.js +21 -12
- package/dist/core/workflow-run-store.js +2 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/orchestration/run-spec.js +5 -1
- package/dist/orchestration/workflow.js +13 -2
- package/dist/stores/file/background-agent-store.js +2 -1
- package/dist/stores/file/mailbox-store.js +2 -0
- package/dist/stores/file/workflow-run-store.js +2 -0
- package/dist/tools/fs/bash-readonly-classifier.d.ts +5 -2
- package/dist/tools/fs/bash-readonly-classifier.js +129 -17
- package/dist/tools/web.js +32 -5
- package/package.json +1 -1
|
@@ -28,7 +28,7 @@ import { CHANGED_FILES_MTIME_EPS_MS, fenceMcpServerInstructions, renderAgentList
|
|
|
28
28
|
import { inlineUntrusted } from "../untrusted-text.js";
|
|
29
29
|
import { emitTrace } from "../trace.js";
|
|
30
30
|
import { createSessionRulePolicy } from "./session-rule-policy.js";
|
|
31
|
-
import { cloneObserverInput, createHookEnvCapabilities, formatHookFeedback, runToolGate } from "../hooks.js";
|
|
31
|
+
import { cloneObserverInput, createHookEnvCapabilities, createPreToolUseConstraintPolicy, formatHookFeedback, runToolGate } from "../hooks.js";
|
|
32
32
|
import { reconcileInterruptedSession } from "../session-reconcile.js";
|
|
33
33
|
import { CacheBreakDetector, toolsToFingerprintInputs } from "../cache-break-detector.js";
|
|
34
34
|
import { reservedCollisions, reservedFor } from "../../brain/request-params.js";
|
|
@@ -1057,6 +1057,14 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1057
1057
|
const ownOrgVerdictRef = { current: undefined };
|
|
1058
1058
|
const orgAdmissionCheckpointState = () => inheritedAdmittedOrgScopes !== undefined || ownOrgVerdictRef.current !== undefined || orgGovernedProvenance;
|
|
1059
1059
|
const frozenOnAsk = spec.onAsk ?? deps.onAsk;
|
|
1060
|
+
const hookEnvSource = (ownedEnv ?? deps.executionEnv) != null ? executionEnv : undefined;
|
|
1061
|
+
const notifyOwnHookCrash = (err) => {
|
|
1062
|
+
try {
|
|
1063
|
+
deps.onError?.(err instanceof Error ? err : new Error(String(err)), { phase: "hook", sessionId });
|
|
1064
|
+
}
|
|
1065
|
+
catch {
|
|
1066
|
+
}
|
|
1067
|
+
};
|
|
1060
1068
|
const frozenOnQuestion = spec.onQuestion ?? deps.onQuestion;
|
|
1061
1069
|
const inheritedGateForChildren = () => {
|
|
1062
1070
|
const ancestorRules = [
|
|
@@ -1066,8 +1074,25 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
1066
1074
|
const ownCallerPolicy = lockedPreflight.toolPolicy;
|
|
1067
1075
|
const durableMandate = runtimeCaps?.forceDurableGate === true ||
|
|
1068
1076
|
(spec.durableApproval !== undefined && !isLiveApproverSeat(frozenOnAsk));
|
|
1077
|
+
const ownPreToolUse = preToolUseObservational ? undefined : hooks?.preToolUse;
|
|
1078
|
+
const hookConstraint = ownPreToolUse !== undefined &&
|
|
1079
|
+
!(inheritedParentConstraints ?? []).some((pc) => pc.preToolUse === ownPreToolUse &&
|
|
1080
|
+
askApproverIdentity(pc.onAsk) === askApproverIdentity(frozenOnAsk) &&
|
|
1081
|
+
(pc.durableMandate === true) === durableMandate &&
|
|
1082
|
+
pc.hookEnv === hookEnvSource)
|
|
1083
|
+
? [
|
|
1084
|
+
{
|
|
1085
|
+
policy: createPreToolUseConstraintPolicy(ownPreToolUse, hookEnvFace, notifyOwnHookCrash),
|
|
1086
|
+
preToolUse: ownPreToolUse,
|
|
1087
|
+
...(hookEnvSource !== undefined ? { hookEnv: hookEnvSource } : {}),
|
|
1088
|
+
...(frozenOnAsk !== undefined ? { onAsk: frozenOnAsk } : {}),
|
|
1089
|
+
...(durableMandate ? { durableMandate: true } : {}),
|
|
1090
|
+
},
|
|
1091
|
+
]
|
|
1092
|
+
: [];
|
|
1069
1093
|
const parentConstraints = [
|
|
1070
1094
|
...(inheritedParentConstraints ?? []),
|
|
1095
|
+
...hookConstraint,
|
|
1071
1096
|
...(ownCallerPolicy !== undefined
|
|
1072
1097
|
? [
|
|
1073
1098
|
{
|
|
@@ -2920,6 +2945,25 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
2920
2945
|
auditPolicyNames(layer);
|
|
2921
2946
|
const denyNarrowingPolicy = narrowingLayers.length === 0 ? undefined : narrowingLayers.length === 1 ? narrowingLayers[0] : combinePolicies(...narrowingLayers);
|
|
2922
2947
|
const basePolicyForResumeEdit = lockedPreflight.toolPolicy;
|
|
2948
|
+
const hooks = spec.hooks ?? deps.hooks;
|
|
2949
|
+
const preToolUseObservational = hooks?.preToolUse !== undefined && hooks.preToolUseObservational === true;
|
|
2950
|
+
const ownGatePreToolUse = !preToolUseObservational
|
|
2951
|
+
? hooks?.preToolUse
|
|
2952
|
+
: async (toolName, input, ctx) => {
|
|
2953
|
+
const r = await hooks.preToolUse(toolName, cloneObserverInput(input), ctx);
|
|
2954
|
+
if (r === undefined)
|
|
2955
|
+
return undefined;
|
|
2956
|
+
try {
|
|
2957
|
+
const action = typeof r.action === "string" ? r.action : "(non-string action)";
|
|
2958
|
+
deps.onError?.(new Error(`a PreToolUse hook declared observational (Hooks.preToolUseObservational) returned a decision ("${action}") while screening ` +
|
|
2959
|
+
`"${toolName}" — the decision was NOT adopted and the call proceeded as if the hook had no opinion. ` +
|
|
2960
|
+
`A declared-observational face must return undefined; drop the declaration if its verdicts are meant to count ` +
|
|
2961
|
+
`(they then also travel to delegated children as an inherited screening constraint).`), { phase: "hook", sessionId, classification: "observational-hook-verdict-ignored" });
|
|
2962
|
+
}
|
|
2963
|
+
catch {
|
|
2964
|
+
}
|
|
2965
|
+
return undefined;
|
|
2966
|
+
};
|
|
2923
2967
|
const sameInstanceAncestorCount = policy === undefined ? 0 : (inheritedParentConstraints ?? []).reduce((n, pc) => (pc.policy === policy ? n + 1 : n), 0);
|
|
2924
2968
|
const sharedFirstDecision = new Map();
|
|
2925
2969
|
const SHARED_FIRST_DECISION_CAP = 256;
|
|
@@ -3067,125 +3111,134 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3067
3111
|
editArgs = rr.updatedInput;
|
|
3068
3112
|
}
|
|
3069
3113
|
};
|
|
3070
|
-
const parentConstraintWrappers = (inheritedParentConstraints ?? []).map((pc) =>
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
}
|
|
3088
|
-
if (pc.durableMandate === true) {
|
|
3089
|
-
if (resolveCheckpointStore(spec, deps) !== undefined &&
|
|
3090
|
-
(spec.durableApproval !== undefined || runtimeCaps?.forceDurableGate === true) &&
|
|
3091
|
-
markInheritedUnavailable(creq.toolCallId)) {
|
|
3092
|
-
return first;
|
|
3114
|
+
const parentConstraintWrappers = (inheritedParentConstraints ?? []).map((pc) => pc.preToolUse !== undefined &&
|
|
3115
|
+
pc.preToolUse === hooks?.preToolUse &&
|
|
3116
|
+
!preToolUseObservational &&
|
|
3117
|
+
pc.durableMandate !== true &&
|
|
3118
|
+
askApproverIdentity(pc.onAsk) === askApproverIdentity(frozenOnAsk) &&
|
|
3119
|
+
pc.hookEnv === hookEnvSource
|
|
3120
|
+
? { check: () => ({ action: "allow" }) }
|
|
3121
|
+
: policy !== undefined && pc.policy === policy
|
|
3122
|
+
? {
|
|
3123
|
+
check: async (creq, csignal) => {
|
|
3124
|
+
const first = sharedFirstDecision.get(creq.toolCallId);
|
|
3125
|
+
if (first === undefined) {
|
|
3126
|
+
return {
|
|
3127
|
+
action: "deny",
|
|
3128
|
+
message: `inherited parent policy could not be arbitrated for "${creq.toolName}" ` +
|
|
3129
|
+
`(shared-instance first decision unavailable); denied fail-closed`,
|
|
3130
|
+
};
|
|
3093
3131
|
}
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
}
|
|
3100
|
-
const presentedArgs = creq.args;
|
|
3101
|
-
const askT0 = now();
|
|
3102
|
-
const resolved = await resolveAsk({
|
|
3103
|
-
toolName: creq.toolName,
|
|
3104
|
-
toolCallId: creq.toolCallId,
|
|
3105
|
-
args: presentedArgs,
|
|
3106
|
-
...ruleSuggestionsOf(creq.toolName, presentedArgs),
|
|
3107
|
-
message: first.message ?? `approval required for "${creq.toolName}" (inherited parent policy)`,
|
|
3108
|
-
...askSourceIdentity(),
|
|
3109
|
-
...riskAxesOf(creq.toolName),
|
|
3110
|
-
...(first.action === "ask" && first.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
|
|
3111
|
-
}, pc.onAsk, csignal ?? abortController.signal);
|
|
3112
|
-
const askWaitMs = Math.max(0, now() - askT0);
|
|
3113
|
-
if (resolved.action === "deny" && resolved.approverUnavailable === true) {
|
|
3114
|
-
if (markInheritedUnavailable(creq.toolCallId))
|
|
3132
|
+
if (first.action === "deny")
|
|
3133
|
+
return first;
|
|
3134
|
+
if (first.action === "allow")
|
|
3135
|
+
return { action: "allow" };
|
|
3136
|
+
if (creq.toolName === ASK_USER_QUESTION_TOOL_NAME && (pc.durableMandate !== true || markInheritedUnavailable(creq.toolCallId))) {
|
|
3115
3137
|
return first;
|
|
3116
|
-
return {
|
|
3117
|
-
action: "deny",
|
|
3118
|
-
message: `no approver is reachable for the inherited approval of "${creq.toolName}" and the marker channel is at capacity — denied fail-closed`,
|
|
3119
|
-
};
|
|
3120
|
-
}
|
|
3121
|
-
if (resolved.action !== "allow")
|
|
3122
|
-
return resolved;
|
|
3123
|
-
if (resolved.updatedInput !== undefined) {
|
|
3124
|
-
return recheckApprovedEdit(pc.policy, pc.onAsk, creq, resolved.updatedInput, csignal);
|
|
3125
|
-
}
|
|
3126
|
-
recordInheritedAskGrant(creq.toolCallId, pc.onAsk, resolved.presentedInput, askWaitMs);
|
|
3127
|
-
return { action: "allow" };
|
|
3128
|
-
},
|
|
3129
|
-
}
|
|
3130
|
-
: {
|
|
3131
|
-
check: async (creq, csignal) => {
|
|
3132
|
-
let decision;
|
|
3133
|
-
try {
|
|
3134
|
-
decision = await pc.policy.check(creq, csignal ?? abortController.signal);
|
|
3135
|
-
}
|
|
3136
|
-
catch (err) {
|
|
3137
|
-
return {
|
|
3138
|
-
action: "deny",
|
|
3139
|
-
message: `inherited parent policy errored for "${creq.toolName}": ${err instanceof Error ? err.message : String(err)}`,
|
|
3140
|
-
};
|
|
3141
|
-
}
|
|
3142
|
-
if (decision.action !== "ask")
|
|
3143
|
-
return decision;
|
|
3144
|
-
if (creq.toolName === ASK_USER_QUESTION_TOOL_NAME && (pc.durableMandate !== true || markInheritedUnavailable(creq.toolCallId))) {
|
|
3145
|
-
return decision;
|
|
3146
|
-
}
|
|
3147
|
-
if (pc.durableMandate === true) {
|
|
3148
|
-
if (resolveCheckpointStore(spec, deps) !== undefined &&
|
|
3149
|
-
(spec.durableApproval !== undefined || runtimeCaps?.forceDurableGate === true) &&
|
|
3150
|
-
markInheritedUnavailable(creq.toolCallId)) {
|
|
3151
|
-
return decision;
|
|
3152
3138
|
}
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3139
|
+
if (pc.durableMandate === true) {
|
|
3140
|
+
if (resolveCheckpointStore(spec, deps) !== undefined &&
|
|
3141
|
+
(spec.durableApproval !== undefined || runtimeCaps?.forceDurableGate === true) &&
|
|
3142
|
+
markInheritedUnavailable(creq.toolCallId)) {
|
|
3143
|
+
return first;
|
|
3144
|
+
}
|
|
3145
|
+
return {
|
|
3146
|
+
action: "deny",
|
|
3147
|
+
message: `inherited parent policy requires durable approval for "${creq.toolName}" — the parent's durable ` +
|
|
3148
|
+
`ask cannot be reconstructed in a delegated child; denied fail-closed (tighten-only)`,
|
|
3149
|
+
};
|
|
3150
|
+
}
|
|
3151
|
+
const presentedArgs = creq.args;
|
|
3152
|
+
const askT0 = now();
|
|
3153
|
+
const resolved = await resolveAsk({
|
|
3154
|
+
toolName: creq.toolName,
|
|
3155
|
+
toolCallId: creq.toolCallId,
|
|
3156
|
+
args: presentedArgs,
|
|
3157
|
+
...ruleSuggestionsOf(creq.toolName, presentedArgs),
|
|
3158
|
+
message: first.message ?? `approval required for "${creq.toolName}" (inherited parent policy)`,
|
|
3159
|
+
...askSourceIdentity(),
|
|
3160
|
+
...riskAxesOf(creq.toolName),
|
|
3161
|
+
...(first.action === "ask" && first.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
|
|
3162
|
+
}, pc.onAsk, csignal ?? abortController.signal);
|
|
3163
|
+
const askWaitMs = Math.max(0, now() - askT0);
|
|
3164
|
+
if (resolved.action === "deny" && resolved.approverUnavailable === true) {
|
|
3165
|
+
if (markInheritedUnavailable(creq.toolCallId))
|
|
3166
|
+
return first;
|
|
3167
|
+
return {
|
|
3168
|
+
action: "deny",
|
|
3169
|
+
message: `no approver is reachable for the inherited approval of "${creq.toolName}" and the marker channel is at capacity — denied fail-closed`,
|
|
3170
|
+
};
|
|
3171
|
+
}
|
|
3172
|
+
if (resolved.action !== "allow")
|
|
3173
|
+
return resolved;
|
|
3174
|
+
if (resolved.updatedInput !== undefined) {
|
|
3175
|
+
return recheckApprovedEdit(pc.policy, pc.onAsk, creq, resolved.updatedInput, csignal);
|
|
3176
|
+
}
|
|
3177
|
+
recordInheritedAskGrant(creq.toolCallId, pc.onAsk, resolved.presentedInput, askWaitMs);
|
|
3178
|
+
return { action: "allow" };
|
|
3179
|
+
},
|
|
3180
|
+
}
|
|
3181
|
+
: {
|
|
3182
|
+
check: async (creq, csignal) => {
|
|
3183
|
+
let decision;
|
|
3184
|
+
try {
|
|
3185
|
+
decision = await pc.policy.check(creq, csignal ?? abortController.signal);
|
|
3186
|
+
}
|
|
3187
|
+
catch (err) {
|
|
3188
|
+
return {
|
|
3189
|
+
action: "deny",
|
|
3190
|
+
message: `inherited parent policy errored for "${creq.toolName}": ${err instanceof Error ? err.message : String(err)}`,
|
|
3191
|
+
};
|
|
3192
|
+
}
|
|
3193
|
+
if (decision.action !== "ask")
|
|
3174
3194
|
return decision;
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3195
|
+
if (creq.toolName === ASK_USER_QUESTION_TOOL_NAME && (pc.durableMandate !== true || markInheritedUnavailable(creq.toolCallId))) {
|
|
3196
|
+
return decision;
|
|
3197
|
+
}
|
|
3198
|
+
if (pc.durableMandate === true) {
|
|
3199
|
+
if (resolveCheckpointStore(spec, deps) !== undefined &&
|
|
3200
|
+
(spec.durableApproval !== undefined || runtimeCaps?.forceDurableGate === true) &&
|
|
3201
|
+
markInheritedUnavailable(creq.toolCallId)) {
|
|
3202
|
+
return decision;
|
|
3203
|
+
}
|
|
3204
|
+
return {
|
|
3205
|
+
action: "deny",
|
|
3206
|
+
message: `inherited parent policy requires durable approval for "${creq.toolName}" — the parent's durable ` +
|
|
3207
|
+
`ask cannot be reconstructed in a delegated child; denied fail-closed (tighten-only)`,
|
|
3208
|
+
};
|
|
3209
|
+
}
|
|
3210
|
+
const presentedArgs = decision.updatedInput !== undefined ? decision.updatedInput : creq.args;
|
|
3211
|
+
const askT0 = now();
|
|
3212
|
+
const resolved = await resolveAsk({
|
|
3213
|
+
toolName: creq.toolName,
|
|
3214
|
+
toolCallId: creq.toolCallId,
|
|
3215
|
+
args: presentedArgs,
|
|
3216
|
+
...ruleSuggestionsOf(creq.toolName, presentedArgs),
|
|
3217
|
+
message: decision.message ?? `approval required for "${creq.toolName}" (inherited parent policy)`,
|
|
3218
|
+
...askSourceIdentity(),
|
|
3219
|
+
...riskAxesOf(creq.toolName),
|
|
3220
|
+
...(decision.action === "ask" && decision.requiresRealApproval === true ? { requiresRealApproval: true } : {}),
|
|
3221
|
+
}, pc.onAsk, csignal ?? abortController.signal);
|
|
3222
|
+
const askWaitMs = Math.max(0, now() - askT0);
|
|
3223
|
+
if (resolved.action === "deny" && resolved.approverUnavailable === true) {
|
|
3224
|
+
if (markInheritedUnavailable(creq.toolCallId))
|
|
3225
|
+
return decision;
|
|
3226
|
+
return {
|
|
3227
|
+
action: "deny",
|
|
3228
|
+
message: `no approver is reachable for the inherited approval of "${creq.toolName}" and the marker channel is at capacity — denied fail-closed`,
|
|
3229
|
+
};
|
|
3230
|
+
}
|
|
3231
|
+
if (resolved.action !== "allow")
|
|
3232
|
+
return resolved;
|
|
3233
|
+
if (resolved.updatedInput !== undefined) {
|
|
3234
|
+
return recheckApprovedEdit(pc.policy, pc.onAsk, creq, resolved.updatedInput, csignal);
|
|
3235
|
+
}
|
|
3236
|
+
if (pc.preToolUse === undefined) {
|
|
3237
|
+
recordInheritedAskGrant(creq.toolCallId, pc.onAsk, resolved.presentedInput, askWaitMs);
|
|
3238
|
+
}
|
|
3239
|
+
return decision.updatedInput !== undefined ? { ...resolved, updatedInput: decision.updatedInput } : resolved;
|
|
3240
|
+
},
|
|
3241
|
+
});
|
|
3189
3242
|
const rewriteCapableLayers = policy !== undefined || parentConstraintWrappers.length > 0;
|
|
3190
3243
|
const rewriteEmitterIndex = new Map();
|
|
3191
3244
|
const rewriteCapableChain = [
|
|
@@ -3269,7 +3322,6 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3269
3322
|
},
|
|
3270
3323
|
}
|
|
3271
3324
|
: foldedPolicy;
|
|
3272
|
-
const hooks = spec.hooks ?? deps.hooks;
|
|
3273
3325
|
const onAsk = spec.onAsk ?? deps.onAsk;
|
|
3274
3326
|
const handWriteTools = handsEnabled && spec.handsReadOnly !== true
|
|
3275
3327
|
? Object.keys(HAND_TOOL_EFFECTS).filter((name) => {
|
|
@@ -3277,7 +3329,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3277
3329
|
return eff === "write" || eff === "idempotent";
|
|
3278
3330
|
})
|
|
3279
3331
|
: [];
|
|
3280
|
-
const hasEffectAwareGate = Boolean(policyLayers.length > 0 || hooks?.preToolUse);
|
|
3332
|
+
const hasEffectAwareGate = Boolean(policyLayers.length > 0 || (hooks?.preToolUse !== undefined && !preToolUseObservational));
|
|
3281
3333
|
const destructiveMcpUngated = mcp.tools.some((t) => !irreversibleTools.has(t.name) && !egressTools.has(t.name) && (toolEffects.get(t.name) ?? "write") !== "read");
|
|
3282
3334
|
const firstPartyWriteUngated = (spec.tools ?? [])
|
|
3283
3335
|
.map((t) => t.name)
|
|
@@ -3391,7 +3443,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3391
3443
|
const hookEnvFace = hookContextConsumerWired && (ownedEnv ?? deps.executionEnv) != null ? createHookEnvCapabilities(executionEnv) : undefined;
|
|
3392
3444
|
if (effectivePolicy || hooks?.preToolUse || egressTools.size > 0 || irreversibleTools.size > 0 || resourceSuspendEligible || platformSuspendArmed || spec.enablePlanMode === true) {
|
|
3393
3445
|
const adjudicate = effectivePolicy
|
|
3394
|
-
? (req) => raceAbort(Promise.resolve(effectivePolicy.check({ ...req, budget: budgetSnapshot }, abortController.signal)), abortController.signal, () => ({
|
|
3446
|
+
? (req) => raceAbort(Promise.resolve(effectivePolicy.check({ ...req, budget: budgetSnapshot, ...(handsCwdRef !== undefined ? { cwd: handsCwdRef.current } : {}) }, abortController.signal)), abortController.signal, () => ({
|
|
3395
3447
|
action: "deny",
|
|
3396
3448
|
message: "policy check aborted (task timed out or cancelled)",
|
|
3397
3449
|
}))
|
|
@@ -3531,6 +3583,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3531
3583
|
carried.spentMicroUsd = prior + parkedSpendMicroUsd;
|
|
3532
3584
|
return carried;
|
|
3533
3585
|
};
|
|
3586
|
+
const screeningParkDisclosedRef = { done: false };
|
|
3534
3587
|
const serializeCheckpointState = (workspaceHandle, parkedSpendMicroUsd) => ({
|
|
3535
3588
|
activeTools: [...activeTools],
|
|
3536
3589
|
outputRef: { value: outputRef.value, set: outputRef.set },
|
|
@@ -3587,6 +3640,22 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3587
3640
|
await memoryEngineSession.harvest("checkpoint");
|
|
3588
3641
|
try {
|
|
3589
3642
|
await checkpointStore.put(token, cp);
|
|
3643
|
+
const committedCount = cp.state.inheritedGate?.parentConstraintCount;
|
|
3644
|
+
if (cp.state.inheritedGate?.requiresParentConstraint === true &&
|
|
3645
|
+
!screeningParkDisclosedRef.done &&
|
|
3646
|
+
(inheritedParentConstraints ?? []).some((pc) => pc.preToolUse !== undefined)) {
|
|
3647
|
+
screeningParkDisclosedRef.done = true;
|
|
3648
|
+
try {
|
|
3649
|
+
deps.onError?.(new Error(`durable park under an inherited PreToolUse SCREENING constraint: this checkpoint records ` +
|
|
3650
|
+
`requiresParentConstraint with parentConstraintCount=${committedCount ?? "(unrecorded)"}, and the live ` +
|
|
3651
|
+
`closures cannot be persisted. A resume on THIS Runner re-supplies them automatically; a resume on a fresh ` +
|
|
3652
|
+
`Runner (restart / another replica) must hand back the whole chain via resumeStream(..., internals), ` +
|
|
3653
|
+
`rebuilding the screening entry with createPreToolUseConstraintPolicy(hook, env) — otherwise the row stays ` +
|
|
3654
|
+
`pending. If the face only observes, declare Hooks.preToolUseObservational and it stops entering the chain.`), { phase: "degraded", sessionId, classification: "screening-constraint-in-durable-chain" });
|
|
3655
|
+
}
|
|
3656
|
+
catch {
|
|
3657
|
+
}
|
|
3658
|
+
}
|
|
3590
3659
|
return { ok: true };
|
|
3591
3660
|
}
|
|
3592
3661
|
catch (putErr) {
|
|
@@ -3918,7 +3987,12 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
3918
3987
|
if (!presented.ok) {
|
|
3919
3988
|
throw new ParkRefusal(`the stored form of "${req.toolName}"'s arguments could not be presented for re-adjudication (${describeThrown(presented.cause)})`, { cause: presented.cause });
|
|
3920
3989
|
}
|
|
3921
|
-
const reprojected = refuseOutOfContractDecision(await basePolicyForResumeEdit.check({
|
|
3990
|
+
const reprojected = refuseOutOfContractDecision(await basePolicyForResumeEdit.check({
|
|
3991
|
+
toolName: req.toolName,
|
|
3992
|
+
args: presented.value,
|
|
3993
|
+
toolCallId: req.toolCallId,
|
|
3994
|
+
...(handsCwdRef !== undefined ? { cwd: handsCwdRef.current } : {}),
|
|
3995
|
+
}, abortController.signal));
|
|
3922
3996
|
const demanded = reprojected.updatedInput !== undefined ? tryCloneArgs(reprojected.updatedInput) : undefined;
|
|
3923
3997
|
const rewroteTheFiledValue = reprojected.updatedInput !== undefined &&
|
|
3924
3998
|
!(demanded?.ok === true &&
|
|
@@ -4114,7 +4188,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
4114
4188
|
result = await runToolGate({
|
|
4115
4189
|
onNotifyError: (f) => emitTrace(deps.tracer, () => ({ kind: "observer.notify_failed", version: 1, taskId: spec.taskId ?? sessionId, site: f.site, message: f.error.message, ts: Date.now() })),
|
|
4116
4190
|
event: e,
|
|
4117
|
-
preToolUse:
|
|
4191
|
+
preToolUse: ownGatePreToolUse,
|
|
4118
4192
|
...(hookEnvFace !== undefined ? { hookEnv: hookEnvFace } : {}),
|
|
4119
4193
|
adjudicate,
|
|
4120
4194
|
resolveAsk: resolveAskBound,
|
|
@@ -1357,6 +1357,7 @@ export class Runner {
|
|
|
1357
1357
|
const hooks = h
|
|
1358
1358
|
? {
|
|
1359
1359
|
...(typeof h.preToolUse === "function" ? { preToolUse: (t, i, c) => h.preToolUse(t, i, c) } : {}),
|
|
1360
|
+
...(typeof h.preToolUse === "function" && h.preToolUseObservational === true ? { preToolUseObservational: true } : {}),
|
|
1360
1361
|
...(typeof h.postToolUse === "function" ? { postToolUse: (t, i, o, c) => h.postToolUse(t, i, o, c) } : {}),
|
|
1361
1362
|
...(typeof h.userPromptSubmit === "function" ? { userPromptSubmit: (p) => h.userPromptSubmit(p) } : {}),
|
|
1362
1363
|
...(typeof h.stop === "function" ? { stop: (c) => h.stop(c) } : {}),
|
|
@@ -3853,7 +3854,12 @@ export class Runner {
|
|
|
3853
3854
|
throw new CheckpointError("checkpoint.invalid_outcome", `pending action reached the resolver with decision "${String(outcome.decision)}" — only "allow" executes and only "deny" injects a denial; refusing to execute`);
|
|
3854
3855
|
}
|
|
3855
3856
|
if (outcome.decision === "allow" && outcome.updatedInput !== undefined && prepared.basePolicyForResumeEdit) {
|
|
3856
|
-
const rechecked = refuseOutOfContractDecision(await prepared.basePolicyForResumeEdit.check({
|
|
3857
|
+
const rechecked = refuseOutOfContractDecision(await prepared.basePolicyForResumeEdit.check({
|
|
3858
|
+
toolName: pendingAction.toolName,
|
|
3859
|
+
args: resolvedArgs,
|
|
3860
|
+
toolCallId: pendingAction.toolCallId,
|
|
3861
|
+
...(prepared.cwdRef !== undefined ? { cwd: prepared.cwdRef.current } : {}),
|
|
3862
|
+
}, prepared.abortController.signal));
|
|
3857
3863
|
if (rechecked.action === "deny") {
|
|
3858
3864
|
const editedDenial = formatHookFeedback(`The approver EDITED this call's input; the edited call is denied by the deployment's tool policy and was not executed${rechecked.message ? `: ${rechecked.message}` : ""}.`);
|
|
3859
3865
|
emitEnd(true, { content: editedDenial });
|
|
@@ -3863,7 +3869,12 @@ export class Runner {
|
|
|
3863
3869
|
}
|
|
3864
3870
|
}
|
|
3865
3871
|
if (prepared.denyNarrowingPolicy) {
|
|
3866
|
-
const narrowed = refuseOutOfContractDecision(await prepared.denyNarrowingPolicy.check({
|
|
3872
|
+
const narrowed = refuseOutOfContractDecision(await prepared.denyNarrowingPolicy.check({
|
|
3873
|
+
toolName: pendingAction.toolName,
|
|
3874
|
+
args: resolvedArgs,
|
|
3875
|
+
toolCallId: pendingAction.toolCallId,
|
|
3876
|
+
...(prepared.cwdRef !== undefined ? { cwd: prepared.cwdRef.current } : {}),
|
|
3877
|
+
}, prepared.abortController.signal));
|
|
3867
3878
|
if (narrowed.action === "deny") {
|
|
3868
3879
|
const narrowedDenial = formatHookFeedback(`The approved tool call "${pendingAction.toolName}" is now denied by a session rule and was not executed${narrowed.message ? `: ${narrowed.message}` : ""}.`);
|
|
3869
3880
|
emitEnd(true, { content: narrowedDenial });
|
|
@@ -4074,14 +4085,28 @@ function startTimeout(harness, abortController, remainingMs, softSuspendable = f
|
|
|
4074
4085
|
if (remainingMs !== undefined) {
|
|
4075
4086
|
const hardMs = Math.max(0, remainingMs + (softSuspendable ? WALLTIME_SUSPEND_GRACE_SEC * 1000 : 0));
|
|
4076
4087
|
const scheduledAtMs = Date.now() + hardMs;
|
|
4077
|
-
|
|
4088
|
+
let leftMs = hardMs;
|
|
4089
|
+
let timer;
|
|
4090
|
+
const armChunk = () => {
|
|
4091
|
+
const chunk = Math.max(0, Math.min(leftMs, MAX_TIMER_DELAY_MS));
|
|
4092
|
+
timer = setTimeout(() => {
|
|
4093
|
+
leftMs -= chunk;
|
|
4094
|
+
if (leftMs > 0) {
|
|
4095
|
+
armChunk();
|
|
4096
|
+
return;
|
|
4097
|
+
}
|
|
4098
|
+
fireHardAbort();
|
|
4099
|
+
}, chunk);
|
|
4100
|
+
};
|
|
4101
|
+
const fireHardAbort = () => {
|
|
4078
4102
|
if (state.fired)
|
|
4079
4103
|
return;
|
|
4080
4104
|
state.fired = true;
|
|
4081
4105
|
state.latenessMs = Math.max(0, Date.now() - scheduledAtMs);
|
|
4082
4106
|
abortController.abort();
|
|
4083
4107
|
void harness.abort();
|
|
4084
|
-
}
|
|
4108
|
+
};
|
|
4109
|
+
armChunk();
|
|
4085
4110
|
state.clear = () => clearTimeout(timer);
|
|
4086
4111
|
}
|
|
4087
4112
|
return state;
|
|
@@ -58,7 +58,7 @@ export function createSessionRulePolicy(rules, opts) {
|
|
|
58
58
|
if (typeof path !== "string" || path.length === 0) {
|
|
59
59
|
return deny(`write tool "${req.toolName}" denied: session rule confines writes to allowDirs but the call has no resolvable path`);
|
|
60
60
|
}
|
|
61
|
-
const canon = await canonicalizeTarget(env, path, signal, rootPath);
|
|
61
|
+
const canon = await canonicalizeTarget(env, path, signal, req.cwd ?? rootPath);
|
|
62
62
|
if (!canon.ok) {
|
|
63
63
|
return deny(`write to "${path}" denied: its real target could not be resolved against the session-rule allowDirs`);
|
|
64
64
|
}
|
|
@@ -64,7 +64,7 @@ export function createSensitivePathPolicy(opts) {
|
|
|
64
64
|
const path = writeTargetPath(canonical, req.args);
|
|
65
65
|
if (typeof path !== "string" || path.length === 0)
|
|
66
66
|
return { action: "allow" };
|
|
67
|
-
const canon = await canonicalizeTarget(opts.env, path, signal, opts.rootPath);
|
|
67
|
+
const canon = await canonicalizeTarget(opts.env, path, signal, req.cwd ?? opts.rootPath);
|
|
68
68
|
if (!canon.ok) {
|
|
69
69
|
if (canon.unresolvedSymlink) {
|
|
70
70
|
return {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { assertRetentionPolicy } from "./retention-policy.js";
|
|
2
3
|
import { uuidv7 } from "../internal/harness.js";
|
|
3
4
|
import { canAccessAgentRecord, BackgroundAgentStoreError, clearRevivedRowTerminalPayload, REVIVED_ROW_CLEARED_FIELDS, STALE_RUNNING_REAP_ATTRIBUTION, } from "./background-agent-store.js";
|
|
4
5
|
import { shutdownDebug } from "./shutdown-debug.js";
|
|
@@ -163,6 +164,7 @@ export function endDurableClaimLane(core, id) {
|
|
|
163
164
|
core.claimingHandles.delete(id);
|
|
164
165
|
}
|
|
165
166
|
export async function reapDurableAgentsLane(core, scope, deps, policy) {
|
|
167
|
+
assertRetentionPolicy("reapDurableAgents", policy);
|
|
166
168
|
const now = policy.now ?? Date.now();
|
|
167
169
|
if (policy.staleRunningMaxAgeMs !== undefined) {
|
|
168
170
|
await deps.store.reap(scope, now, { staleRunningMaxAgeMs: policy.staleRunningMaxAgeMs });
|
package/dist/core/tool-policy.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { homedir } from "node:os";
|
|
2
|
-
import {
|
|
2
|
+
import { join, normalize as normalizePath, posix as posixPath, sep, win32 as winPath } from "node:path";
|
|
3
3
|
import { BASH_READONLY_DEFAULT_ALLOW, parseLeadingCommandName } from "../tools/fs/index.js";
|
|
4
4
|
import { boundInputHashOf } from "./canonical-json.js";
|
|
5
5
|
import { inlineUntrusted } from "./untrusted-text.js";
|
|
6
6
|
import { parsePermissionRule } from "./permission-rules.js";
|
|
7
|
-
import { writeTargetPath } from "../tools/fs/safety.js";
|
|
7
|
+
import { isAbsolutePathForm, isWinFormPath, writeTargetPath } from "../tools/fs/safety.js";
|
|
8
8
|
export const APPROVAL_SETTLED_BY_VALUES = ["human", "timeout", "aborted"];
|
|
9
9
|
export function isApprovalSettledBy(v) {
|
|
10
10
|
return typeof v === "string" && APPROVAL_SETTLED_BY_VALUES.includes(v);
|
|
@@ -117,6 +117,9 @@ export function createApprovalPolicy(opts) {
|
|
|
117
117
|
if (opts.approvalTimeoutMs !== undefined && !Number.isFinite(opts.approvalTimeoutMs)) {
|
|
118
118
|
throw new Error(`createApprovalPolicy: approvalTimeoutMs must be a finite number of ms (got ${opts.approvalTimeoutMs}) — omit it to wait indefinitely`);
|
|
119
119
|
}
|
|
120
|
+
if (opts.approvalTimeoutMs !== undefined && opts.approvalTimeoutMs > 2_147_483_647) {
|
|
121
|
+
throw new Error(`createApprovalPolicy: approvalTimeoutMs must not exceed 2147483647ms (~24.8 days) (got ${opts.approvalTimeoutMs}) — a host timer truncates a larger delay and fires immediately, denying every request at once; omit it to wait indefinitely`);
|
|
122
|
+
}
|
|
120
123
|
const need = new Set(opts.requireApproval);
|
|
121
124
|
const deny = new Set(opts.deny ?? []);
|
|
122
125
|
const auto = new Set(opts.autoAllow ?? []);
|
|
@@ -526,13 +529,16 @@ export function createTranscriptIntegrityPolicy(opts) {
|
|
|
526
529
|
const readAllow = new Set(opts?.readAllow ?? BASH_READONLY_DEFAULT_ALLOW);
|
|
527
530
|
const shellTools = canonicalToolNameSet(opts?.tools);
|
|
528
531
|
const dirSegs = dirs.map((d) => pathSegments(d).map(foldPathCase));
|
|
529
|
-
const inProtectedDir = (p) => {
|
|
530
|
-
const
|
|
532
|
+
const inProtectedDir = (p, liveCwd) => {
|
|
533
|
+
const rawRelative = !isAbsolutePathForm(p);
|
|
534
|
+
const joinInFamily = (base, rel) => isWinFormPath(base) ? winPath.join(base, rel) : posixPath.join(base, rel);
|
|
535
|
+
const abs = liveCwd !== undefined && rawRelative ? lexicalPath(joinInFamily(liveCwd, p), home) : lexicalPath(p, home);
|
|
531
536
|
const segs = pathSegments(abs).map(foldPathCase);
|
|
532
|
-
if (
|
|
533
|
-
return
|
|
534
|
-
|
|
535
|
-
|
|
537
|
+
if (isAbsolutePathForm(abs) && dirSegs.some((d) => d.length <= segs.length && d.every((s, i) => s === segs[i])))
|
|
538
|
+
return true;
|
|
539
|
+
if (!rawRelative)
|
|
540
|
+
return false;
|
|
541
|
+
return dirSegs.some((d) => relativeContinuesDirTail(pathSegments(lexicalPath(p, home)).map(foldPathCase), d));
|
|
536
542
|
};
|
|
537
543
|
const referencesProtectedDir = (cmd) => {
|
|
538
544
|
const hay = foldPathCase(cmd);
|
|
@@ -571,18 +577,21 @@ export function createTranscriptIntegrityPolicy(opts) {
|
|
|
571
577
|
if (typeof command !== "string")
|
|
572
578
|
return ALLOW;
|
|
573
579
|
const cmd = command.normalize("NFC");
|
|
574
|
-
|
|
580
|
+
const cwdInsideProtected = req.cwd !== undefined && inProtectedDir(req.cwd);
|
|
581
|
+
if (!referencesProtectedDir(cmd) && !cwdInsideProtected)
|
|
575
582
|
return ALLOW;
|
|
576
583
|
const parsed = parseLeadingCommandName(command);
|
|
577
584
|
if ("name" in parsed && readAllow.has(parsed.name))
|
|
578
585
|
return ALLOW;
|
|
579
586
|
return askReason("name" in parsed
|
|
580
|
-
? `\`${parsed.name}\` is not a read-only command`
|
|
581
|
-
:
|
|
587
|
+
? `\`${parsed.name}\` is not a read-only command${cwdInsideProtected ? " and the shell's working directory is inside the transcript directory" : ""}`
|
|
588
|
+
: cwdInsideProtected
|
|
589
|
+
? "the shell's working directory is inside the transcript directory and this is not a single read-only command (fail-closed)"
|
|
590
|
+
: "the command references the transcript directory and is not a single read-only command (fail-closed)");
|
|
582
591
|
}
|
|
583
592
|
if (toolName === "Write" || toolName === "Edit" || toolName === "NotebookEdit") {
|
|
584
593
|
const p = writeTargetPath(toolName, req.args);
|
|
585
|
-
if (typeof p === "string" && inProtectedDir(p)) {
|
|
594
|
+
if (typeof p === "string" && inProtectedDir(p, req.cwd)) {
|
|
586
595
|
return askReason(`"${p}" is inside the session-transcript directory`);
|
|
587
596
|
}
|
|
588
597
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { assertRetentionPolicy } from "./retention-policy.js";
|
|
1
2
|
export function summarizeWorkflowRun(run) {
|
|
2
3
|
const latestPhase = run.phases.at(-1);
|
|
3
4
|
return {
|
|
@@ -73,6 +74,7 @@ export class InMemoryWorkflowRunStore {
|
|
|
73
74
|
return queryWorkflowRuns(this.runs.values(), scope, opts);
|
|
74
75
|
}
|
|
75
76
|
async reap(scope, now, opts) {
|
|
77
|
+
assertRetentionPolicy("WorkflowRunStore.reap", opts);
|
|
76
78
|
if (opts?.maxAgeMs === undefined && opts?.keep === undefined)
|
|
77
79
|
return 0;
|
|
78
80
|
const terminal = [...this.runs.values()].filter((r) => r.scope === scope && isTerminalWorkflowStatus(r.status));
|
package/dist/index.d.ts
CHANGED
|
@@ -131,7 +131,7 @@ export { parseAllowRuleText, formatAllowRuleText, ruleAdmitsCommand, findAdmitti
|
|
|
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
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
|
-
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";
|
|
134
|
+
export { formatHookFeedback, runToolGate, createHookEnvCapabilities, createPreToolUseConstraintPolicy, 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";
|
|
136
136
|
export { MemoryEngine, FileMemoryEngineBackend, memoryBackendContract, assertMemoryBackendSearchEquivalence, type MemoryBackendContractHooks, buildMemoryInstruction, truncateIndex, scanEntryFiles, deriveRepoKey, deriveRepoMemoryDir, deriveControlPlaneDir, deriveRepoControlPlaneDir, resolveMemoryEngineRoot, scopeDirName, ControlPlaneCorruptError, parseEntryFile, serializeEntryFile, computeEntryRev, entryFromFile, MEMORY_INSTRUCTION_TEMPLATE, MEMORY_RECALL_DISCIPLINE, MEMORY_INDEX_FILENAME, MEMORY_INDEX_MAX_LINES, MEMORY_INDEX_MAX_BYTES, MEMORY_SEARCH_TOOL_NAME, MEMORY_GET_TOOL_NAME, MEMORY_ENGINE_TOOL_NAMES, type MemorySearchDetails, type MemorySearchHit, type MemoryGetDetails, STUB_ARCHIVED_LINE, DEFAULT_MAX_MEMORY_FILES, DEFAULT_MAX_ENTRY_DEPTH, DEFAULT_HARVEST_DEADLINE_MS, DEFAULT_HARVEST_FILE_BUDGET, MASS_DELETION_FUSE_RATIO, scanMemoryWrite, scanMemoryFileName, scanRemediation, MEMORY_FILENAME_SEGMENT_RE, renderAnnouncements, enqueueMemoryAnnouncement, drainMemoryAnnouncements, peekMemoryAnnouncements, bumpScanFuse, scanFuseCount, clearScanFuse, ANNOUNCEMENTS_FILE, MEMORY_ANNOUNCEMENTS_MAX, SCAN_FUSE_FILE, SCAN_FUSE_THRESHOLD, type MemoryAnnouncement, type ScanFinding, type MemoryEngineOptions, type MemoryInjection, type MemoryBackend, type MemoryEntry, type MemoryEntryFrontmatter, type MemoryEntryHeader, type ScoredMemoryEntry, type NotePatch, type PatchReport, type MaterializedFile, type MemorySessionHandle, type HarvestReport, type HarvestRejection, type HarvestRejectionCode, type ParsedEntryFile, type ScannedEntryFile, SCOPE_SEGMENT_MAX_ENCODED, PROJECT_MARKER_PATH, encodeScopeSegment, decodeScopeSegment, parseScopeKey, formatUserScope, formatOrgScope, formatProjScope, formatUserProjScope, isPersonalScope, assertScopeContractPlacement, formatProjectMarker, parseProjectMarker, resolveProjectId, PROJECT_ID_REGEX, type ParsedScopeKey, migrateScope, type MigrateScopeReport, materializeEntriesToFiles, harvestFilesToPatches, projectionsToWriteBack, screenInboundEntries, REMOTE_HARVEST_PER_FILE_BYTES, REMOTE_MASS_DELETION_FUSE_RATIO, type RemoteMemoryFile, type RemoteMemoryBaseline, type RemoteMaterialization, type RemoteHarvestResult, type InboundEntryFinding, deriveProjectMemoryDir, deriveProjectControlDir, recordProjectIdHint, lookupProjectIdHint, PROJECT_ID_HINTS_FILE, reconcileMemoryEntries, nextSyncBaseline, mergeRecallHits, type MemorySyncCursor, type MemorySyncConflict, type MemorySyncPlan, type RecallSource, syncMemoryScope, type MemorySyncTransport, type MemorySyncRequestBody, type MemorySyncResponseBody, type MemorySyncClientConflict, type SyncMemoryScopeOptions, type MemorySyncClientResult, } from "./core/memory-engine/index.js";
|
|
137
137
|
export { SHARED_MEMORY_READ_CAP_BYTES, SHARED_MEMORY_LIST_PAGE_SIZE, SharedMemoryStoreError, type SharedMemoryStoreProvider, type SharedMemoryStoreReader, type SharedMemoryStoreInfo, type SharedMemoryDocumentEntry, type SharedMemorySnapshot, type SharedMemoryRequestContext, type MemoryListDetails, type MemoryReadDetails, } from "./core/shared-memory/types.js";
|