@sema-agent/server 7.118.0 → 7.120.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 (139) hide show
  1. package/MIGRATION.md +139 -0
  2. package/README.md +1 -1
  3. package/README.zh-CN.md +1 -1
  4. package/USAGE.md +26 -13
  5. package/deploy/sema-up/README.md +2 -0
  6. package/deploy/sema-up/chart/templates/minio.yaml +2 -1
  7. package/deploy/sema-up/chart/templates/server-v4pro.yaml +1 -0
  8. package/deploy/sema-up/chart/templates/server.yaml +1 -0
  9. package/deploy/sema-up/chart/values.yaml +7 -1
  10. package/deploy/sema-up/cluster-up.sh +20 -8
  11. package/deploy/sema-up/kube-up.sh +29 -16
  12. package/deploy/sema-up/lib/buckets.sh +21 -0
  13. package/deploy/sema-up/lib/health.sh +33 -0
  14. package/deploy/sema-up/sema-up.sh +14 -9
  15. package/deploy/sema-up/smoke.sh +16 -6
  16. package/deploy/sema-up/stack/compose.yaml +1 -1
  17. package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -1
  18. package/dist/approval-ask-audit-store.js +2 -7
  19. package/dist/approval-card.d.ts +5 -5
  20. package/dist/approval.d.ts +51 -5
  21. package/dist/approval.js +76 -13
  22. package/dist/audit.d.ts +12 -1
  23. package/dist/audit.js +62 -2
  24. package/dist/auto-mode-face.d.ts +2 -3
  25. package/dist/bake-runner/main.js +1 -6
  26. package/dist/bake-runner/protocol.d.ts +18 -0
  27. package/dist/bake-runner/protocol.js +22 -2
  28. package/dist/bake-runner/runner.d.ts +12 -8
  29. package/dist/bake-runner/runner.js +5 -9
  30. package/dist/boot/config-center.js +6 -6
  31. package/dist/boot/coordinators.js +4 -1
  32. package/dist/boot/device-lane.d.ts +3 -3
  33. package/dist/boot/device-lane.js +1 -2
  34. package/dist/boot/execution-env.js +3 -2
  35. package/dist/boot/fatal-exit.d.ts +7 -1
  36. package/dist/boot/fatal-exit.js +2 -1
  37. package/dist/boot/leader.d.ts +4 -4
  38. package/dist/boot/leader.js +1 -2
  39. package/dist/boot/parked-revive-gate.d.ts +5 -1
  40. package/dist/boot/parked-revive-gate.js +8 -2
  41. package/dist/boot/resolve-spec.js +7 -4
  42. package/dist/boot/runner-deps.d.ts +4 -3
  43. package/dist/boot/runner-deps.js +7 -3
  44. package/dist/boot/stage-01-config.js +2 -0
  45. package/dist/boot/stage-07-capability-layer.js +5 -1
  46. package/dist/boot/stage-10-http-server.js +3 -2
  47. package/dist/boot/stores.js +12 -7
  48. package/dist/capabilities/builtin-tools.d.ts +31 -8
  49. package/dist/capabilities/builtin-tools.js +22 -1
  50. package/dist/capabilities/center-plugins.d.ts +2 -0
  51. package/dist/capabilities/center-plugins.js +24 -6
  52. package/dist/capabilities/code-review-council.js +8 -11
  53. package/dist/capabilities/scenarios.d.ts +42 -13
  54. package/dist/capabilities/scenarios.js +36 -9
  55. package/dist/capabilities/send-user-file-tool.d.ts +6 -3
  56. package/dist/capabilities/send-user-file-tool.js +1 -1
  57. package/dist/config-catalog.js +5 -5
  58. package/dist/config-lkg.d.ts +33 -5
  59. package/dist/config-lkg.js +55 -11
  60. package/dist/config-types.d.ts +8 -1
  61. package/dist/config.js +11 -11
  62. package/dist/deployment-governance.d.ts +8 -3
  63. package/dist/deployment-governance.js +7 -4
  64. package/dist/device-store.d.ts +7 -0
  65. package/dist/device-store.js +4 -0
  66. package/dist/device-ws-hub.js +17 -9
  67. package/dist/device-ws-protocol.d.ts +15 -0
  68. package/dist/host-decision.d.ts +52 -27
  69. package/dist/host-decision.js +14 -7
  70. package/dist/http/admission.js +6 -6
  71. package/dist/http/resume-legs.js +6 -1
  72. package/dist/http/routes/approvals-assistant.d.ts +25 -3
  73. package/dist/http/routes/approvals-assistant.js +9 -5
  74. package/dist/http/routes/capabilities.js +5 -3
  75. package/dist/http/routes/devices.js +3 -3
  76. package/dist/http/routes/memory-origin.d.ts +1 -1
  77. package/dist/http/routes/rules.js +13 -6
  78. package/dist/http/routes/runs.js +11 -5
  79. package/dist/http/routes/sessions.js +20 -16
  80. package/dist/http/wire-types.d.ts +12 -13
  81. package/dist/images/manifest.d.ts +7 -1
  82. package/dist/images/manifest.js +18 -16
  83. package/dist/list-entry-display.d.ts +14 -0
  84. package/dist/list-entry-display.js +14 -0
  85. package/dist/memory-store-refusal.d.ts +7 -12
  86. package/dist/memory-store-refusal.js +4 -5
  87. package/dist/namespaced-rule-name.d.ts +4 -3
  88. package/dist/namespaced-rule-name.js +2 -6
  89. package/dist/observability/fail-open.d.ts +9 -1
  90. package/dist/observability/fail-open.js +9 -1
  91. package/dist/operator-ask.d.ts +7 -6
  92. package/dist/plugins/approval-exemption-store.d.ts +4 -0
  93. package/dist/plugins/approval-exemption-store.js +1 -0
  94. package/dist/plugins/blob-backend.d.ts +13 -0
  95. package/dist/plugins/blob-backend.js +26 -0
  96. package/dist/plugins/local-session-store.d.ts +78 -47
  97. package/dist/plugins/local-session-store.js +152 -122
  98. package/dist/plugins/one-time-migrations.d.ts +14 -0
  99. package/dist/plugins/one-time-migrations.js +90 -3
  100. package/dist/plugins/permission-rule-store-file.js +2 -6
  101. package/dist/plugins/permission-rule-store-sql.d.ts +64 -6
  102. package/dist/plugins/permission-rule-store-sql.js +166 -59
  103. package/dist/plugins/remote-env-device.d.ts +12 -1
  104. package/dist/plugins/remote-env-device.js +13 -5
  105. package/dist/plugins/scheduler-support.d.ts +8 -4
  106. package/dist/plugins/scheduler-support.js +5 -5
  107. package/dist/plugins/snapshot-bucket-presence.d.ts +36 -0
  108. package/dist/plugins/snapshot-bucket-presence.js +40 -0
  109. package/dist/plugins/store-backend.d.ts +17 -6
  110. package/dist/plugins/store-backend.js +46 -16
  111. package/dist/plugins/store-open-wait.d.ts +33 -0
  112. package/dist/plugins/store-open-wait.js +73 -0
  113. package/dist/rule-entry-list.d.ts +0 -1
  114. package/dist/rule-entry-list.js +5 -10
  115. package/dist/rules-consent.d.ts +12 -3
  116. package/dist/rules-consent.js +5 -4
  117. package/dist/run-local.js +6 -3
  118. package/dist/security.d.ts +5 -3
  119. package/dist/security.js +4 -0
  120. package/dist/sema-config-dir.d.ts +19 -0
  121. package/dist/sema-config-dir.js +33 -0
  122. package/dist/session-policy-wire.js +10 -14
  123. package/dist/spec-fields.d.ts +7 -2
  124. package/dist/store-posture.d.ts +14 -6
  125. package/dist/store-posture.js +7 -4
  126. package/dist/task-settings.d.ts +30 -58
  127. package/dist/task-settings.js +6 -18
  128. package/dist/tool-approval.d.ts +97 -43
  129. package/dist/tool-approval.js +120 -31
  130. package/dist/trace/engine-notice-wire.d.ts +6 -4
  131. package/dist/trace/engine-notice-wire.js +16 -9
  132. package/dist/trace/redact.d.ts +6 -0
  133. package/dist/trace/redact.js +9 -9
  134. package/dist/trace/self-minted-wire.d.ts +15 -1
  135. package/dist/trace/self-minted-wire.js +2 -0
  136. package/dist/user-input-ledger.d.ts +19 -15
  137. package/dist/user-input-ledger.js +12 -20
  138. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +56 -14
  139. package/package.json +2 -2
@@ -46,7 +46,9 @@ which version the server speaks before you spend a handshake finding out.
46
46
  acquire the connection lease
47
47
  ◀── helloAck { gen, heartbeatIntervalMs,
48
48
  maxInflight, pendingInstructions,
49
- chunkWatermarks }
49
+ chunkWatermarks, reconnectGraceMs,
50
+ cancelGraceMs, chunkGapTimeoutMs,
51
+ executionCeilingGraceMs }
50
52
  … or helloReject { code }
51
53
  fence: kill/drain everything from older generations
52
54
  generationAck { gen } ───────────────────────▶ now (and only now) the
@@ -79,7 +81,7 @@ which version the server speaks before you spend a handshake finding out.
79
81
  | `platformOs` | yes | closed set `darwin` \| `linux` (anything else is a `400`; there is no third value) |
80
82
  | `platformArch` | no | ≤ 32 bytes |
81
83
  | `displayName` | no | ≤ 255 bytes |
82
- | `workspaceRoot` | yes | non-empty, ≤ 1024 bytes — the device-side root that path resolution falls back to |
84
+ | `workspaceRoot` | yes | ≤ 1024 bytes, **an absolute POSIX path** — the device-side root that path resolution and `exec` `cwd` fall back to. Registration refuses anything else (empty, relative, `~/…`) with `400 request.field_invalid`; the same check runs again when a session's execution environment is created, so a device registered with a non-absolute root by an older server is refused there |
83
85
 
84
86
  `deviceId` and the owner are **not** inputs: the server mints `dev_<26-char ULID>` and takes the owner
85
87
  from the verified credential. The response is `200 { deviceId }` and contains no secret of any kind.
@@ -251,6 +253,17 @@ backoff, exponential to a 60 s ceiling, jittered — except for `revoked`, which
251
253
  | `gen` | **canonical decimal string** (`"7"`, never `7`, never `"07"`) | the connection generation. Stamp it on every frame you send |
252
254
  | `pendingInstructions` | `string[]` | instruction ids the server still considers in flight for you — see §5 R2 |
253
255
  | `chunkWatermarks` | `{ [instructionId]: number }` | per instruction, the highest **contiguous** `streamSeq` the server has already accepted. `-1` means "nothing accepted yet" |
256
+ | `reconnectGraceMs` | integer ms | the reconnect grace **in force on this server** (R4): how long in-flight work survives a dropped socket. Deployment-tunable, default 120000 |
257
+ | `cancelGraceMs` | integer ms | the cancel grace in force (R11): how long after a `cancel` is delivered the server waits for your terminal `result`. Default 10000 |
258
+ | `chunkGapTimeoutMs` | integer ms | the chunk-gap timeout in force (R8): how long the server waits for a missing `streamSeq` before failing the instruction. Default 30000 |
259
+ | `executionCeilingGraceMs` | integer ms | the grace added to an instruction's `timeoutMs` before the server gives up and settles it as outcome-unknown (R12: the ceiling is `timeoutMs + executionCeilingGraceMs`). Default 30000 |
260
+
261
+ The four grace fields are the values the server's own timers are armed with — not documentation defaults. Size
262
+ your reconnect backoff ceiling, your `cancel` answer deadline, your retransmission cadence and your own
263
+ `timeoutMs` enforcement from them. A server that predates them omits all four; treat absence as "not told" and
264
+ fall back to the defaults in the table above, never as zero. For the same reason the published TypeScript type
265
+ (`DeviceHelloAckFrame` from `@sema-agent/server/device-protocol`) declares the four as optional; a server from
266
+ 7.120.0 on always sends all four.
254
267
 
255
268
  `gen` is a string because it is a 64-bit database value; parse it as an integer only if your language can
256
269
  hold it, and always **echo the string you were given** rather than re-formatting a number.
@@ -276,7 +289,7 @@ fenced — that half is yours, and it is the reason a device-level single-instan
276
289
 
277
290
  Send `goodbye { gen, reason, graceMs? }`. The server stops *starting* new dispatches for this connection
278
291
  and keeps collecting results for the ones already in flight, then closes the socket after `graceMs` (if you
279
- omit it, the deployment's reconnect grace — default 120000 ms — is used). Sending `goodbye` does not settle
292
+ omit it, the deployment's reconnect grace — `helloAck.reconnectGraceMs`, default 120000 ms — is used). Sending `goodbye` does not settle
280
293
  anything: finish or fail your in-flight instructions properly before you exit.
281
294
 
282
295
  ⚠️ **`goodbye` is not a hard barrier.** The check happens when a dispatch *enters* the pipeline, and a
@@ -341,9 +354,9 @@ zeros, a plus sign, whitespace or a float form are rejected as malformed.
341
354
  | `t` | Fields | Notes |
342
355
  |---|---|---|
343
356
  | `challenge` | `nonce` string, `protocolVersion` int | first frame the server sends, immediately on open |
344
- | `helloAck` | `ok`, `heartbeatIntervalMs`, `maxInflight`, `gen`, `pendingInstructions`, `chunkWatermarks` | §1.5 |
357
+ | `helloAck` | `ok`, `heartbeatIntervalMs`, `maxInflight`, `gen`, `pendingInstructions`, `chunkWatermarks`, `reconnectGraceMs`, `cancelGraceMs`, `chunkGapTimeoutMs`, `executionCeilingGraceMs` | §1.5 |
345
358
  | `helloReject` | `code`, `minProtocolVersion?` | §1.4; the socket closes right after |
346
- | `instruction` | `gen`, `instructionId`, `rootSessionId`, `issuedSeq` int, `kind`, `args`, `cwd?`, `shellEnv?`, `timeoutMs` int | one unit of work (§3) |
359
+ | `instruction` | `gen`, `instructionId`, `rootSessionId`, `issuedSeq` int, `kind`, `args`, `cwd?`, `shellEnv?`, `timeoutMs` int | one unit of work (§3). `cwd` appears on `exec` / `execStream` only, and always there (§3.1) |
347
360
  | `payload` | `gen`, `instructionId`, `part` (`begin` \| `chunk` \| `commit`), `offset?`, `dataB64?`, `totalLen?`, `sha256?` | the bytes for a write-family instruction (§3.4) |
348
361
  | `cancel` | `gen`, `instructionId` | idempotent; answer with a terminal `result` (§5 R11) |
349
362
  | `resultAck` | `gen`, `instructionId` | you may release that instruction's buffers |
@@ -416,8 +429,10 @@ silently forgiven: it becomes a gap or a missing terminal, and the instruction e
416
429
  ### 3.1 The closed set, its arguments, and the success outcome each one owes
417
430
 
418
431
  Every `path` in `args` arrives **already absolute and POSIX-normalized** — the server resolved it against
419
- the session's working directory before sending. `cwd` (when present) is likewise absolute; when it is
420
- absent, run in the instruction's implied working directory (the resolution base the server already used).
432
+ the session's working directory before sending. `exec` and `execStream` additionally carry `cwd`, which is
433
+ **always present and always absolute**: run the command in exactly that directory. There is no implicit
434
+ base to fall back to, so an executor needs no branch for a missing or relative `cwd`. Every other kind
435
+ carries no `cwd` — its paths are already absolute.
421
436
 
422
437
  <!-- closed-set: DEVICE_INSTRUCTION_KINDS -->
423
438
 
@@ -551,10 +566,37 @@ payload { part: "commit", instructionId, totalLen, sha256 }
551
566
  2. on `commit`, verify the length **and** the digest;
552
567
  3. only then rename into place — atomically, honouring the instruction's semantics (exclusive create,
553
568
  guarded expectation, append);
554
- 4. any failure at any step fails the **whole instruction** and leaves **no half-written file**.
569
+ 4. any failure at any step fails the **whole instruction** and leaves **no half-written file** — with one
570
+ exception, `appendFile`, which is stated next.
555
571
 
556
572
  `defaultPayloadPartBytes` is 262144, but do not assume it: use `offset` and `totalLen`.
557
573
 
574
+ **`appendFile` is the one write that cannot be all-or-nothing.** Steps 1–3 give `writeFile`,
575
+ `writeFileExclusive` and `writeFileGuarded` their guarantee by building the complete file beside the target
576
+ and swapping it in. An append has no such swap: it extends the existing target **in place**, so there is a
577
+ moment after which the target has changed and the instruction has not finished. What POSIX guarantees for an
578
+ `O_APPEND` write is that the position is taken at end-of-file atomically; it does not promise that the payload
579
+ lands in one piece. This protocol therefore asks you to treat `PIPE_BUF` bytes (the POSIX minimum is 512; Linux
580
+ uses 4096) as the largest append you may regard as indivisible — the conservative bound, borrowed from the
581
+ rule POSIX states for pipe writes — and to assume that anything larger can reach the file in several writes,
582
+ interleave with another writer's appends, or stop part-way. So what you answer depends on *when* you fail:
583
+
584
+ - **The target cannot have been touched yet** — the payload failed its length or digest check, the target
585
+ could not be opened, your own containment policy refused the path. Answer the ordinary code
586
+ (`permission_denied`, `not_found`, `is_directory`, `invalid`, …). Nothing changed, so the caller may safely
587
+ retry.
588
+ - **The target may already have been changed** — a short write, an I/O error part-way through, or the process
589
+ or the machine going away while the append was running, so that you cannot say how much landed. Answer
590
+ `outcome_unknown` (§3.3). Never answer `timeout` or `transport_lost` here: both are retryable, and a retry
591
+ appends the content a second time.
592
+ - **The whole payload was appended.** Answer `{ok:true, kind:"void"}`. Do not report success for a partial
593
+ append.
594
+
595
+ The server settles an executor-reported `outcome_unknown` exactly like one it reaches by its own deadlines:
596
+ the caller gets the code `outcome_unknown`, which nothing upstream retries, and your message is kept and
597
+ followed by a fixed sentence telling the model to verify the file's contents before running the append again.
598
+ So make your message specific about what you know (bytes written, where it stopped).
599
+
558
600
  ### 3.5 `writeFileGuarded` and its `expect`
559
601
 
560
602
  `expect` is `{ canonicalPath: string, fileId?: string, exclusive?: boolean, noFollow?: boolean }`:
@@ -605,7 +647,7 @@ server delivers in order and buffers out-of-order chunks; it acks with `chunkAck
605
647
  **cumulative** watermark meaning "everything up to and including this is accepted" (`-1` = nothing yet).
606
648
  You may release buffers at or below the watermark.
607
649
 
608
- - A gap that is not filled within the deployment's gap timeout (default 30 s) **fails the instruction**
650
+ - A gap that is not filled within the deployment's gap timeout (`helloAck.chunkGapTimeoutMs`, default 30 s) **fails the instruction**
609
651
  with `outcome_unknown` — output is never silently truncated.
610
652
  - The reorder buffer is bounded (default 64 entries / 2 MiB decoded). Running far ahead of the watermark
611
653
  overflows it and also fails the instruction.
@@ -711,7 +753,7 @@ process — that work is accounted for as "may have run".
711
753
 
712
754
  **R4 — no reconnect within the grace ⇒ the books close.**
713
755
  *Given* the socket dropped with `I` in flight, *when* no connection for this device is established within
714
- the reconnect grace (default 120 s), *then* `I` settles `outcome_unknown`; a later reconnect does not list
756
+ the reconnect grace (`helloAck.reconnectGraceMs`, default 120 s), *then* `I` settles `outcome_unknown`; a later reconnect does not list
715
757
  it, and its `result` is either refused or memo-acked without being believed (§2.4).
716
758
  *Executor:* reconnect promptly. If you were offline longer than the grace, your results are no longer
717
759
  deliverable — that is not a licence to re-run anything.
@@ -742,7 +784,7 @@ as the original — the first copy the server buffered is the one it will delive
742
784
 
743
785
  **R8 — a gap is a failure, not a truncation.**
744
786
  *Given* the server is waiting for `streamSeq k`, *when* `k` does not arrive within the gap timeout
745
- (default 30 s) or the reorder buffer overflows (default 64 entries / 2 MiB), *then* `I` fails with
787
+ (`helloAck.chunkGapTimeoutMs`, default 30 s) or the reorder buffer overflows (default 64 entries / 2 MiB), *then* `I` fails with
746
788
  `outcome_unknown` — the command already ran, so the result cannot be faithfully reported.
747
789
  *Executor:* never skip a `streamSeq`, never renumber after a reconnect, never "compact" a stream.
748
790
 
@@ -766,18 +808,18 @@ machine from taking over the lease mid-command; only you can.
766
808
 
767
809
  **R11 — `cancel` demands a terminal, within a grace.**
768
810
  *Given* the server sent `cancel` for `I`, *when* you do not send a terminal `result` within the cancel
769
- grace (default 10 s, restarted each time the cancel is delivered), *then* `I` settles `outcome_unknown`.
811
+ grace (`helloAck.cancelGraceMs`, default 10 s, restarted each time the cancel is delivered), *then* `I` settles `outcome_unknown`.
770
812
  `cancel` is idempotent, is delivered at most once per generation, and **is replayed on the first active
771
813
  tick after a same-epoch reconnect** (a cancel written to a socket that then dropped may never have
772
814
  arrived).
773
815
  *Executor:* treat a repeated `cancel` for the same `I` as a no-op. Answer exactly one terminal:
774
816
  `{ok:true, kind:"cancelled", state:"not_started"}` if the work had not begun, `state:"killed"` if you
775
- killed it, or the work's ordinary outcome if it had already finished. Answer promptly — 10 s is the budget.
817
+ killed it, or the work's ordinary outcome if it had already finished. Answer promptly — `cancelGraceMs` (default 10 s) is the budget.
776
818
 
777
819
  **R12 — two-layer timeout: yours is authoritative, the server's is a backstop.**
778
820
  *Given* an instruction carrying `timeoutMs`, *when* that budget elapses, *then* you must kill the work and
779
821
  answer `{ok:false, errorCode:"timeout"}` — that is the only path to the retryable `timeout` word. *When*
780
- you answer nothing, the server gives up at `timeoutMs` + a grace (default 30 s) and settles
822
+ you answer nothing, the server gives up at `timeoutMs` + `helloAck.executionCeilingGraceMs` (default 30 s) and settles
781
823
  `outcome_unknown`; a later result for `I` is then undeliverable.
782
824
  *Executor:* enforce `timeoutMs` yourself, and prefer answering late-but-honestly over not answering.
783
825
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/server",
3
- "version": "7.118.0",
3
+ "version": "7.120.0",
4
4
  "description": "Sema Server — the server/API implementation layer for Sema, wiring core, registry, model providers, and cloud agent execution. Built on @sema-agent/core.",
5
5
  "type": "module",
6
6
  "license": "BUSL-1.1",
@@ -64,7 +64,7 @@
64
64
  "build:binary:run-local:darwin-arm64": "bun build --compile --target=bun-darwin-arm64 src/run-local.ts --outfile dist/run-local-darwin-arm64"
65
65
  },
66
66
  "dependencies": {
67
- "@sema-agent/core": "7.44.0",
67
+ "@sema-agent/core": "7.46.0",
68
68
  "@sema-agent/settings-schema": "8.0.0",
69
69
  "e2b": "^2.28.0",
70
70
  "libsodium-wrappers": "^0.8.4",