@sema-agent/core 5.59.0 → 5.60.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.
Files changed (40) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/brain/anthropic.js +15 -5
  3. package/dist/brain/errors.d.ts +18 -1
  4. package/dist/brain/errors.js +7 -1
  5. package/dist/brain/input-too-long.d.ts +57 -0
  6. package/dist/brain/input-too-long.js +35 -0
  7. package/dist/brain/stream-engine.js +9 -1
  8. package/dist/core/auto-compaction.js +2 -2
  9. package/dist/core/checkpoint-store.d.ts +116 -19
  10. package/dist/core/checkpoint-store.js +15 -8
  11. package/dist/core/context-edit.d.ts +243 -41
  12. package/dist/core/context-edit.js +247 -32
  13. package/dist/core/governance-codes.d.ts +1 -1
  14. package/dist/core/governance-codes.js +5 -0
  15. package/dist/core/locked-config.d.ts +36 -4
  16. package/dist/core/locked-config.js +34 -1
  17. package/dist/core/mcp.js +10 -6
  18. package/dist/core/memory-engine/content-origin.d.ts +24 -2
  19. package/dist/core/memory-engine/content-origin.js +6 -1
  20. package/dist/core/memory.d.ts +10 -0
  21. package/dist/core/park-selfcheck.js +1 -0
  22. package/dist/core/permission-rule-consent.js +9 -5
  23. package/dist/core/runner/prepare-config-doors.d.ts +22 -1
  24. package/dist/core/runner/prepare-config-doors.js +36 -0
  25. package/dist/core/runner/prepare-task.d.ts +28 -1
  26. package/dist/core/runner/prepare-task.js +106 -8
  27. package/dist/core/runner/runtask.js +41 -4
  28. package/dist/core/store-contracts/checkpoint-store-contract.js +32 -0
  29. package/dist/core/tool-policy.d.ts +24 -8
  30. package/dist/core/tool-policy.js +3 -3
  31. package/dist/core/tools.js +1 -1
  32. package/dist/core/trace.d.ts +36 -0
  33. package/dist/core/types.d.ts +127 -2
  34. package/dist/core/untrusted-text.d.ts +11 -0
  35. package/dist/core/untrusted-text.js +1 -0
  36. package/dist/engine/llm/types.d.ts +21 -2
  37. package/dist/engine/loop/agent-loop.js +7 -1
  38. package/dist/engine/loop/types.d.ts +4 -1
  39. package/dist/tools/fs/fs-bash.js +1 -2
  40. package/package.json +1 -1
@@ -393,6 +393,17 @@ export declare function defuseControlChars(text: string): string;
393
393
  * Defense-in-depth, NOT a guarantee (same posture as the rest of this module).
394
394
  */
395
395
  export declare function inlineUntrusted(text: string, maxLen?: number): string;
396
+ /** backlog #239: the per-ENTRY ceiling inside a `ProbeCause` operand family (checkpoint-store's
397
+ * structured probe account), sized like the descriptor's own `touchedPaths` entries (the same thing
398
+ * on the same card). Per entry, not per cause: that is the whole point of the structured shape —
399
+ * one pathological path costs only itself, where a single joined string let it consume every other
400
+ * entry's room. HOMED HERE (the leaf neutralizer module) rather than with the `ProbeCause` types:
401
+ * its two consumers — the shell probe that sanitizes at the entry boundary (tools/fs) and the
402
+ * descriptor builder that re-sanitizes at the persist boundary (core/checkpoint-store) — sit on
403
+ * opposite sides of a value-import boundary, and a value import from the shell tool back into
404
+ * checkpoint-store closed an ESM evaluation cycle (checkpoint-store → tool-policy → tools/fs →
405
+ * checkpoint-store, a latent TDZ). Both already import this module; one cap, no cycle. */
406
+ export declare const PROBE_CAUSE_PATH_MAX = 200;
396
407
  /** The one body bound every "reviewer note" relay passes to {@link delimitUntrusted} — the decider's
397
408
  * free text attached to a deny (sync `AskOutcome.reason` and the durable `ResumeOutcome` `reason`
398
409
  * legs alike). A note is steering, not payload: unbounded it can flood the transcript/context the
@@ -568,6 +568,7 @@ export function inlineUntrusted(text, maxLen = LABEL_MAX) {
568
568
  function sanitizeLabel(label) {
569
569
  return inlineUntrusted(label, LABEL_MAX);
570
570
  }
571
+ export const PROBE_CAUSE_PATH_MAX = 200;
571
572
  export const REVIEWER_NOTE_MAX_BODY = 2048;
572
573
  export function delimitUntrusted(label, text, maxBody) {
573
574
  return delimitUntrustedWithClip(label, text, maxBody).text;
@@ -413,8 +413,27 @@ export interface AssistantMessage {
413
413
  * ⚠️ Brain OBLIGATION (RB-482 #12, 5.1.0): stamping this field on every cut turn is part of the
414
414
  * Brain contract — the sentinel-prose fallback readers are RETIRED, so a custom Brain that stamps
415
415
  * only `errorMessage` prose is no longer recognized as a cut (terminal-cause.ts reads this field
416
- * and nothing else). Widening note: exhaustive switches on this union gain arms as it grows. */
417
- errorKind?: "length_empty" | "degenerate";
416
+ * and nothing else). Widening note: exhaustive switches on this union gain arms as it grows.
417
+ *
418
+ * `"input_too_long"` (design/374 slice 2): the provider refused because the request INPUT alone
419
+ * exceeds its context limit — classified at the brain boundary from provenance-checked signals
420
+ * only (`brain/input-too-long.ts`: the diagnostic field of a JSON error envelope, anchored
421
+ * provider openings, the OpenAI `context_length_exceeded` structural code, HTTP 413, and the
422
+ * Anthropic in-band `model_context_window_exceeded` stop / streamed `invalid_request_error`
423
+ * twin). The loop's prompt-too-long recovery reads THIS seat first; the historic prose regex
424
+ * over `errorMessage` remains as the fallback for brains that do not stamp it (additive — the
425
+ * stamping obligation above extends to this member for cuts a Brain can classify structurally,
426
+ * but unlike the two cut kinds there is no retired fallback: prose detection still works). */
427
+ errorKind?: "length_empty" | "degenerate" | "input_too_long";
428
+ /** design/374 slice 2, the AUTHORITATIVE-NEGATIVE twin of `errorKind: "input_too_long"`: the
429
+ * brain's provenance-checked classifier RAN and ruled this failure NOT input-too-long (wrong
430
+ * status family, or the provider's own diagnostic envelope states a different error). The
431
+ * loop's prompt-too-long recovery treats it as a hard negative and SKIPS its prose fallback —
432
+ * a "prompt is too long" sentence reflected inside an unrelated error body must never drive a
433
+ * context-shrinking recovery (adversarial-review r1). Absent = classification could not
434
+ * establish provenance (prose-only gateway, truncated body, non-classifying custom Brain), and
435
+ * the historic prose fallback keeps its reach. Mutually exclusive with the positive stamp. */
436
+ inputTooLongRuledOut?: true;
418
437
  /**
419
438
  * design/124 tier A: this final message was PARTIALLY FINALIZED after a mid-stream connection
420
439
  * loss/stall — the substantive streamed prefix (text and/or completed tool calls) was promoted to
@@ -39,7 +39,13 @@ function isBlankFailureContent(message) {
39
39
  return message.content.every((c) => c.type === "text" ? c.text.trim() === "" : c.type === "thinking" ? c.thinking.trim() === "" : false);
40
40
  }
41
41
  function defaultDetectPromptTooLong(message) {
42
- return message.stopReason === "error" && PROMPT_TOO_LONG_RE.test(message.errorMessage ?? "");
42
+ if (message.stopReason !== "error")
43
+ return false;
44
+ if (message.errorKind === "input_too_long")
45
+ return true;
46
+ if (message.inputTooLongRuledOut === true)
47
+ return false;
48
+ return PROMPT_TOO_LONG_RE.test(message.errorMessage ?? "");
43
49
  }
44
50
  function createPtlWithholdBuffer(emit, detect) {
45
51
  const held = [];
@@ -161,7 +161,10 @@ export interface LoopPromptTooLongRecovery {
161
161
  * Contract: must not throw or reject.
162
162
  */
163
163
  recover: (messages: AgentMessage[], attempt: number) => Promise<AgentMessage[] | undefined>;
164
- /** Override the prompt-too-long classifier. Default: a conservative provider-message pattern. */
164
+ /** Override the prompt-too-long classifier. Default (design/374 slice 2): the TYPED cause first
165
+ * (`errorKind: "input_too_long"`, stamped by the brains from provenance-checked provider
166
+ * signals), then the conservative provider-message prose pattern as the fallback for brains
167
+ * that do not stamp it. */
165
168
  detect?: (message: AssistantMessage) => boolean;
166
169
  /** Max recovery retries per turn. Default: 2. */
167
170
  maxRetries?: number;
@@ -10,8 +10,7 @@ import { imageMagicMatches, withinAnyRoot } from "./safety.js";
10
10
  import { isRemoteExecutionEnv, hasDestroy, isIsolated } from "../../core/remote-env.js";
11
11
  import { ghRateLimitHint } from "./gh-rate-limit.js";
12
12
  import { resolveBashTimeoutCaps, bashTimeoutCapsSec, bashTimeoutArgRefusal, bashTimeoutParamDescription, envErrorDetail, bashMaxOutputChars, clipShellOutput, writeShellOverflowFile, createShellOverflowSpoolFence, shellRecoveryHint, CWD_SENTINEL, BASH_READONLY_CONFINEMENT_NOTE, } from "./fs-shared.js";
13
- import { PROBE_CAUSE_PATH_MAX } from "../../core/checkpoint-store.js";
14
- import { inlineUntrusted } from "../../core/untrusted-text.js";
13
+ import { PROBE_CAUSE_PATH_MAX, inlineUntrusted } from "../../core/untrusted-text.js";
15
14
  import { BASH_READONLY_DEFAULT_ALLOW, coarseReadonlyCheck, classifyBoundedReadonlyPollLoop, classifyCompoundReadonlyDetailed, classifySimpleCommandReadBoundary, NOT_AUTO_ALLOWED, } from "./bash-readonly-classifier.js";
16
15
  const RECURSIVE_CAUSE_MAX_PATHS = 3;
17
16
  const RECURSIVE_READ_CAUSE_CODE = "shell.recursive_read_unbounded";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/core",
3
- "version": "5.59.0",
3
+ "version": "5.60.0",
4
4
  "description": "Stateless, task-oriented AI agent core",
5
5
  "type": "module",
6
6
  "license": "BUSL-1.1",