@sema-agent/server 7.69.0 → 7.71.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 (107) hide show
  1. package/README.md +4 -1
  2. package/README.zh-CN.md +4 -1
  3. package/USAGE.md +109 -10
  4. package/dist/approval-ask-machine.d.ts +1 -1
  5. package/dist/approval-card.d.ts +3 -2
  6. package/dist/approval-content-kind.d.ts +13 -7
  7. package/dist/approval-content-kind.js +3 -1
  8. package/dist/approval-reconciler.d.ts +0 -54
  9. package/dist/approval-reconciler.js +2 -2
  10. package/dist/approval.js +3 -2
  11. package/dist/bench/s1/live-deps.js +2 -0
  12. package/dist/boot/execution-env.js +12 -2
  13. package/dist/boot/memory-consolidation.d.ts +2 -1
  14. package/dist/boot/parked-revive-gate.d.ts +2 -0
  15. package/dist/boot/parked-revive-gate.js +15 -10
  16. package/dist/boot/resolve-spec.js +8 -3
  17. package/dist/boot/runner-deps.d.ts +50 -46
  18. package/dist/boot/runner-deps.js +12 -10
  19. package/dist/brain.d.ts +3 -1
  20. package/dist/brain.js +2 -1
  21. package/dist/budget.js +3 -2
  22. package/dist/config-catalog.d.ts +31 -2
  23. package/dist/config-catalog.js +44 -24
  24. package/dist/config-types.d.ts +31 -1
  25. package/dist/config-types.js +1 -0
  26. package/dist/config.js +15 -3
  27. package/dist/deployment-governance.d.ts +6 -3
  28. package/dist/deployment-governance.js +2 -1
  29. package/dist/execution-lane-caps.d.ts +51 -37
  30. package/dist/execution-lane-caps.js +23 -0
  31. package/dist/fleet/fleet-bus.d.ts +22 -1
  32. package/dist/fleet/fleet-bus.js +2 -1
  33. package/dist/http/routes/approvals-assistant.js +3 -12
  34. package/dist/http/routes/diagnostics.js +4 -0
  35. package/dist/http/routes/runs.js +2 -3
  36. package/dist/http/routes/tasks.js +22 -18
  37. package/dist/http/server.js +21 -7
  38. package/dist/index.d.ts +1 -1
  39. package/dist/leader/wire.js +4 -3
  40. package/dist/main.js +6 -4
  41. package/dist/memory-operator-faces.d.ts +1 -1
  42. package/dist/memory-scope.d.ts +24 -0
  43. package/dist/memory-scope.js +12 -3
  44. package/dist/observability/metrics.d.ts +4 -6
  45. package/dist/observability/metrics.js +5 -1
  46. package/dist/observability/permission-rule-events.d.ts +20 -0
  47. package/dist/observability/permission-rule-events.js +28 -0
  48. package/dist/observability/run-terminal-log.d.ts +13 -22
  49. package/dist/observability/run-terminal-log.js +187 -47
  50. package/dist/observability/tool-trace.d.ts +12 -0
  51. package/dist/observability/tool-trace.js +5 -1
  52. package/dist/orchestration/workflow-agent-session-index.d.ts +85 -2
  53. package/dist/orchestration/workflow-agent-session-index.js +38 -5
  54. package/dist/parked-decide.d.ts +40 -1
  55. package/dist/parked-decide.js +19 -2
  56. package/dist/plugins/checkpoint-store-sql.js +5 -5
  57. package/dist/plugins/local-checkpoint-store.js +3 -3
  58. package/dist/plugins/remote-env-adb.d.ts +11 -0
  59. package/dist/plugins/remote-env-adb.js +2 -0
  60. package/dist/plugins/remote-env-device.d.ts +9 -0
  61. package/dist/plugins/remote-env-device.js +3 -0
  62. package/dist/plugins/remote-env-e2b.d.ts +11 -0
  63. package/dist/plugins/remote-env-e2b.js +2 -0
  64. package/dist/plugins/remote-env-host.d.ts +11 -0
  65. package/dist/plugins/remote-env-host.js +2 -0
  66. package/dist/plugins/remote-env-k8s.d.ts +11 -0
  67. package/dist/plugins/remote-env-k8s.js +2 -0
  68. package/dist/plugins/remote-env-local-docker.d.ts +11 -0
  69. package/dist/plugins/remote-env-local-docker.js +2 -0
  70. package/dist/plugins/remote-env-ssh.d.ts +11 -0
  71. package/dist/plugins/remote-env-ssh.js +2 -0
  72. package/dist/plugins/store-backend.d.ts +36 -13
  73. package/dist/plugins/store-backend.js +12 -3
  74. package/dist/plugins/store-contracts.d.ts +54 -18
  75. package/dist/plugins/store-contracts.js +17 -30
  76. package/dist/plugins/workflow-journal-store-sql.d.ts +1 -1
  77. package/dist/plugins/workflow-journal-store-sql.js +3 -10
  78. package/dist/plugins/workflow-run-store-sql.d.ts +31 -9
  79. package/dist/plugins/workflow-run-store-sql.js +28 -1
  80. package/dist/posture-source.d.ts +23 -3
  81. package/dist/posture-source.js +1 -1
  82. package/dist/read-face-posture.d.ts +8 -1
  83. package/dist/read-face-posture.js +1 -0
  84. package/dist/run-cancel-context.d.ts +50 -1
  85. package/dist/run-cancel-context.js +22 -0
  86. package/dist/run-local.d.ts +14 -6
  87. package/dist/run-local.js +4 -1
  88. package/dist/runs.d.ts +0 -51
  89. package/dist/runs.js +40 -25
  90. package/dist/task-a2a.js +2 -2
  91. package/dist/task-mcp.js +2 -2
  92. package/dist/task-settings.d.ts +21 -8
  93. package/dist/task-settings.js +2 -2
  94. package/dist/tool-approval.d.ts +14 -8
  95. package/dist/tool-approval.js +3 -3
  96. package/dist/trace/core-keyset-guard.d.ts +135 -11
  97. package/dist/trace/engine-notice-wire.d.ts +1 -1
  98. package/dist/trace/engine-notice-wire.js +1 -0
  99. package/dist/trace/ledger-events.d.ts +22 -2
  100. package/dist/trace/ledger-events.js +6 -1
  101. package/dist/trace/ledger-sink.d.ts +10 -8
  102. package/dist/trace/ledger-sink.js +10 -2
  103. package/dist/trace/project.d.ts +24 -6
  104. package/dist/trace/project.js +5 -3
  105. package/dist/trace/redact.d.ts +28 -0
  106. package/dist/trace/redact.js +58 -30
  107. package/package.json +3 -3
@@ -1,23 +1,40 @@
1
+ import { stripFormatCharacters } from "@sema-agent/core";
1
2
  import { recordFailOpen } from "../observability/fail-open.js";
3
+ export const normalizeForRedaction = stripFormatCharacters;
2
4
  const REDACTION_TOKEN_RE_SRC = String.raw `«redacted(?::[a-z-]{1,16}){0,2}»`;
3
- const FULL_SECRET_PATTERNS = [
4
- [/-----BEGIN[^-](?:[^-](?:[^-]|-(?!-))*)?PRIVATE KEY(?: BLOCK)?-----[\s\S]{0,8192}?-----END[^-](?:[^-](?:[^-]|-(?!-))*)?PRIVATE KEY(?: BLOCK)?-----/g, "«redacted:private-key»"],
5
+ const ENTROPY_SCAN_MAX = 96;
6
+ const twoStrongAhead = (valueClass) => String.raw `(?=${valueClass}{0,${ENTROPY_SCAN_MAX}}[0-9A-Z]${valueClass}{0,${ENTROPY_SCAN_MAX}}[0-9A-Z])`;
7
+ const IDENT_CONNECTORS = "[_./-]";
8
+ const noConnectorAhead = (valueClass) => String.raw `(?!${valueClass}{0,${ENTROPY_SCAN_MAX}}${IDENT_CONNECTORS}${valueClass})`;
9
+ const valueArm = (prefixSrc, valueClass, min) => new RegExp(`${prefixSrc}${twoStrongAhead(valueClass)}${valueClass}{${min},}`, "g");
10
+ const WORD_SEGMENT_CLASS = "[A-Za-z0-9._~+/-]";
11
+ const keywordArm = (keywordSrc, valueClass, min, tailSrc = "") => new RegExp(`(?:${keywordSrc}\\s+${valueClass}{${min},}${tailSrc}` +
12
+ `|(?<!${WORD_SEGMENT_CLASS})${keywordSrc}(?:${twoStrongAhead(valueClass)}|${noConnectorAhead(valueClass)})${valueClass}{${min},}${tailSrc})`, "g");
13
+ const STRUCTURAL_SECRET_PATTERNS = [
14
+ [/-----BEGIN(?:[^-](?:[^-](?:[^-]|-(?!-))*)?)?PRIVATE KEY(?: BLOCK)?-----[\s\S]{0,8192}?-----END(?:[^-](?:[^-](?:[^-]|-(?!-))*)?)?PRIVATE KEY(?: BLOCK)?-----/g, "«redacted:private-key»"],
5
15
  [/---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----[\s\S]{0,8192}?---- END SSH2 ENCRYPTED PRIVATE KEY ----/g, "«redacted:private-key»"],
6
- [/\bsk-[A-Za-z0-9_-]{16,}\b/g, "«redacted:key»"],
7
- [/\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{20,}\b/g, "«redacted:gh-token»"],
8
- [/\bgithub_pat_[A-Za-z0-9]{22}_[A-Za-z0-9]{59}\b/g, "«redacted:gh-token»"],
9
- [/\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g, "«redacted:slack-token»"],
10
- [/\bAKIA[0-9A-Z]{16}\b/g, "«redacted:aws-key»"],
11
- [/\bASIA[0-9A-Z]{16}\b/g, "«redacted:aws-key»"],
12
- [/\b(?:gl(?:pat|dt|rt|rtr|cbt|ptt|oas|ft|imt|agent|wt|soat|ffct)-[A-Za-z0-9_-]{20,}|(?:sk|rk)_(?:live|test|org)_[A-Za-z0-9]{24,}|pypi-[A-Za-z0-9_-]{85,})\b/g, "«redacted:key»"],
13
- [/\bxapp-\d-[A-Za-z0-9-]{20,}\b/g, "«redacted:slack-token»"],
14
- [/\b[Bb]earer\s+[A-Za-z0-9._~+/-]{20,}=*/g, "Bearer «redacted»"],
15
- [/\bBasic\s+[A-Za-z0-9+/]{16,}={0,2}/g, "Basic «redacted»"],
16
- [/:(?<=\b[A-Za-z][A-Za-z0-9+.-]*:)\/\//g, "$1:«redacted»@"],
17
- [/\b[Tt]oken\s+[A-Za-z0-9._~+/-]{20,}/g, "token «redacted»"],
16
+ [/:(?<=[A-Za-z][A-Za-z0-9+.-]*:)\/\//g, "$1:«redacted»@"],
18
17
  [/("(?:private_key|client_secret|password|api[_-]?key|secret|token)"\s*:\s*)"[^"\\]*(?:\\.[^"\\]*)*"/gi, '$1"«redacted»"'],
19
18
  ];
19
+ const PPK_CONTAINER_TOKEN = "«redacted:private-key»";
20
20
  const PEM_FRAGMENT_TOKEN = "«redacted:private-key:partial»";
21
+ const HEADLESS_PPK_TOKEN = "«redacted:private-key:partial»";
22
+ const KEYWORD_SECRET_PATTERNS = [
23
+ [keywordArm("[Bb]earer", "[A-Za-z0-9._~+/-]", 20, "=*"), "Bearer «redacted»"],
24
+ [keywordArm("Basic", "[A-Za-z0-9+/]", 16, "={0,2}"), "Basic «redacted»"],
25
+ [keywordArm("[Tt]oken", "[A-Za-z0-9._~+/-]", 20), "token «redacted»"],
26
+ ];
27
+ const SHAPE_SECRET_PATTERNS = [
28
+ [valueArm("sk-", "[A-Za-z0-9_-]", 16), "«redacted:key»"],
29
+ [/(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{20,}/g, "«redacted:gh-token»"],
30
+ [/github_pat_[A-Za-z0-9]{22}_[A-Za-z0-9]{59,}/g, "«redacted:gh-token»"],
31
+ [/xox[baprs]-[A-Za-z0-9-]{10,}/g, "«redacted:slack-token»"],
32
+ [/AKIA[0-9A-Z]{16,}/g, "«redacted:aws-key»"],
33
+ [/ASIA[0-9A-Z]{16,}/g, "«redacted:aws-key»"],
34
+ [/(?:gl(?:pat|dt|rt|rtr|cbt|ptt|oas|ft|imt|agent|wt|soat|ffct)-[A-Za-z0-9_-]{20,}|(?:sk|rk)_(?:live|test|org)_[A-Za-z0-9]{24,}|pypi-[A-Za-z0-9_-]{85,})/g, "«redacted:key»"],
35
+ [/xapp-\d-[A-Za-z0-9-]{20,}/g, "«redacted:slack-token»"],
36
+ ];
37
+ const FULL_SECRET_PATTERNS = [...STRUCTURAL_SECRET_PATTERNS, ...KEYWORD_SECRET_PATTERNS, ...SHAPE_SECRET_PATTERNS];
21
38
  const PEM_HEADER_IDENT_MAX = 31;
22
39
  const PEM_BODY_RUN_MIN = 8;
23
40
  const CH_TAB = 9, CH_LF = 10, CH_CR = 13, CH_SPACE = 32, CH_PLUS = 43, CH_MINUS = 45, CH_SLASH = 47;
@@ -216,7 +233,7 @@ function isPemFenceLabel(s, from, to) {
216
233
  let end = to;
217
234
  if (end - from > PEM_BLOCK_WORD.length && s.startsWith(PEM_BLOCK_WORD, end - PEM_BLOCK_WORD.length))
218
235
  end -= PEM_BLOCK_WORD.length;
219
- if (end - from <= PEM_KEY_WORD.length)
236
+ if (end - from < PEM_KEY_WORD.length)
220
237
  return false;
221
238
  if (!s.startsWith(PEM_KEY_WORD, end - PEM_KEY_WORD.length))
222
239
  return false;
@@ -289,7 +306,6 @@ function redactPemFragments(text, json) {
289
306
  out.push(text.slice(copied));
290
307
  return { out: out.join(""), count };
291
308
  }
292
- const HEADLESS_PPK_TOKEN = "«redacted:private-key:partial»";
293
309
  function redactHeadlessPpkBodies(text) {
294
310
  const KEY = "Private-Lines: ";
295
311
  const n = text.length;
@@ -399,14 +415,14 @@ function redactHeadlessPpkBodies(text) {
399
415
  return count === 0 ? { out: text, count: 0 } : { out: out + text.slice(last), count };
400
416
  }
401
417
  const FRAGMENT_SECRET_PATTERNS = [
402
- [/\bsk-(?=[A-Za-z0-9_-]{6,})(?=[A-Za-z0-9_-]{0,64}[0-9A-Z][A-Za-z0-9_-]{0,64}[0-9A-Z])[A-Za-z0-9_-]{6,}/g, "«redacted:key:partial»"],
403
- [/\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{8,}/g, "«redacted:gh-token:partial»"],
404
- [/\bgithub_pat_[A-Za-z0-9_]{8,}/g, "«redacted:gh-token:partial»"],
405
- [/\bxox[baprs]-[A-Za-z0-9-]{4,}/g, "«redacted:slack-token:partial»"],
406
- [/\bAKIA[0-9A-Z]{6,}/g, "«redacted:aws-key:partial»"],
407
- [/\bASIA[0-9A-Z]{8,}/g, "«redacted:aws-key:partial»"],
408
- [/\b(?:gl(?:pat|dt|rt|rtr|cbt|ptt|oas|ft|imt|agent|wt|soat|ffct)-|(?:sk|rk)_(?:live|test|org)_|pypi-)(?=[A-Za-z0-9_-]{8,})(?=[A-Za-z0-9_-]{0,90}[0-9A-Z][A-Za-z0-9_-]{0,90}[0-9A-Z])[A-Za-z0-9_-]{8,}/g, "«redacted:key:partial»"],
409
- [/\bxapp-\d-[A-Za-z0-9-]{4,}/g, "«redacted:slack-token:partial»"],
418
+ [valueArm("sk-", "[A-Za-z0-9_-]", 6), "«redacted:key:partial»"],
419
+ [valueArm("(?:ghp|gho|ghu|ghs|ghr)_", "[A-Za-z0-9]", 8), "«redacted:gh-token:partial»"],
420
+ [/github_pat_[A-Za-z0-9_]{8,}/g, "«redacted:gh-token:partial»"],
421
+ [valueArm("xox[baprs]-", "[A-Za-z0-9-]", 4), "«redacted:slack-token:partial»"],
422
+ [valueArm("AKIA", "[0-9A-Z]", 6), "«redacted:aws-key:partial»"],
423
+ [valueArm("ASIA", "[0-9A-Z]", 8), "«redacted:aws-key:partial»"],
424
+ [valueArm("(?:gl(?:pat|dt|rt|rtr|cbt|ptt|oas|ft|imt|agent|wt|soat|ffct)-|(?:sk|rk)_(?:live|test|org)_|pypi-)", "[A-Za-z0-9_-]", 8), "«redacted:key:partial»"],
425
+ [valueArm("xapp-\\d-", "[A-Za-z0-9-]", 4), "«redacted:slack-token:partial»"],
410
426
  ];
411
427
  const REDACTION_TOKENS = new Set([...FULL_SECRET_PATTERNS.map(([, r]) => r), PEM_FRAGMENT_TOKEN, ...FRAGMENT_SECRET_PATTERNS.map(([, r]) => r)]
412
428
  .flatMap((r) => r.match(/«[^»]*»/g) ?? []));
@@ -490,21 +506,33 @@ function scanUserinfoRun(text, i, kind, json) {
490
506
  return i;
491
507
  }
492
508
  const REDACTION_TOKEN_Y = new RegExp(REDACTION_TOKEN_RE_SRC, "y");
509
+ const SHAPE_STICKY = SHAPE_SECRET_PATTERNS.map(([re]) => new RegExp(re.source, "y"));
510
+ function keyShapedUsernameEnd(text, p) {
511
+ for (const re of SHAPE_STICKY) {
512
+ re.lastIndex = p;
513
+ if (re.test(text))
514
+ return re.lastIndex;
515
+ }
516
+ return -1;
517
+ }
493
518
  function matchUserinfoAt(text, p, json) {
494
519
  REDACTION_TOKEN_Y.lastIndex = p;
495
520
  const tokEnd = REDACTION_TOKEN_Y.test(text) ? REDACTION_TOKEN_Y.lastIndex : -1;
496
521
  const afterTok = tokEnd >= 0 ? text.charCodeAt(tokEnd) : -1;
497
522
  if (afterTok === 64)
498
523
  return null;
499
- let userEnd;
524
+ let userEnd = -1;
500
525
  let kind;
501
526
  if (afterTok === 58) {
502
527
  userEnd = tokEnd;
503
528
  kind = "token-pass";
504
529
  }
530
+ else if ((() => { const e = keyShapedUsernameEnd(text, p); return e >= 0 && text.charCodeAt(e) === 58 ? ((userEnd = e), true) : false; })()) {
531
+ kind = "token-pass";
532
+ }
505
533
  else {
506
534
  userEnd = scanUserinfoRun(text, p, "plain-user", json);
507
- if (userEnd === p || text.charCodeAt(userEnd) !== 58)
535
+ if (text.charCodeAt(userEnd) !== 58)
508
536
  return null;
509
537
  kind = "plain-pass";
510
538
  }
@@ -534,7 +562,6 @@ function redactUrlUserinfo(text, json) {
534
562
  }
535
563
  return count === 0 ? { out: text, count: 0 } : { out: out + text.slice(last), count };
536
564
  }
537
- const PPK_CONTAINER_TOKEN = "«redacted:private-key»";
538
565
  let ppkScanBytes = 0;
539
566
  export function ppkScanBytesForTest() { return ppkScanBytes; }
540
567
  export function resetPpkScanBytesForTest() { ppkScanBytes = 0; }
@@ -634,10 +661,12 @@ function redactPpkContainers(text, record) {
634
661
  }
635
662
  const urlUserinfoRule = { label: labelOfToken(URL_USERINFO_PATTERN[1]), arm: "full", run: (text, _wantCount, json) => redactUrlUserinfo(text, json) };
636
663
  const SECRET_RULES = [
637
- ...FULL_SECRET_PATTERNS.map((p) => (p === URL_USERINFO_PATTERN ? urlUserinfoRule : regexRule(p, "full"))),
664
+ ...STRUCTURAL_SECRET_PATTERNS.map((p) => (p === URL_USERINFO_PATTERN ? urlUserinfoRule : regexRule(p, "full"))),
638
665
  { label: labelOfToken(PPK_CONTAINER_TOKEN), arm: "full", run: (text, _wantCount, _json, observe) => redactPpkContainers(text, observe) },
639
666
  { label: labelOfToken(PEM_FRAGMENT_TOKEN), arm: "fragment", run: (text, _wantCount, json) => redactPemFragments(text, json) },
640
667
  { label: labelOfToken(HEADLESS_PPK_TOKEN), arm: "fragment", run: (text) => redactHeadlessPpkBodies(text) },
668
+ ...KEYWORD_SECRET_PATTERNS.map((p) => regexRule(p, "full")),
669
+ ...SHAPE_SECRET_PATTERNS.map((p) => regexRule(p, "full")),
641
670
  ...FRAGMENT_SECRET_PATTERNS.map((p) => regexRule(p, "fragment")),
642
671
  { ...urlUserinfoRule, run: (text, _wantCount, json) => ({ out: redactUrlUserinfo(text, json).out, count: 0 }) },
643
672
  ];
@@ -670,8 +699,7 @@ function reportHits(hits) {
670
699
  export function redactSecrets(text, opts) {
671
700
  const wantCount = onRedaction !== undefined && (opts?.observe ?? true);
672
701
  const json = opts?.json === true;
673
- let r;
674
- r = applyRules(text, wantCount, json, opts?.observe ?? true);
702
+ const r = applyRules(normalizeForRedaction(text), wantCount, json, opts?.observe ?? true);
675
703
  reportHits(r.hits);
676
704
  return r.out;
677
705
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/server",
3
- "version": "7.69.0",
3
+ "version": "7.71.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",
@@ -54,7 +54,7 @@
54
54
  "build:binary:run-local:darwin-arm64": "bun build --compile --target=bun-darwin-arm64 src/run-local.ts --outfile dist/run-local-darwin-arm64"
55
55
  },
56
56
  "dependencies": {
57
- "@sema-agent/core": "7.11.2",
57
+ "@sema-agent/core": "7.13.0",
58
58
  "@sema-agent/settings-schema": "1.10.0",
59
59
  "e2b": "^2.28.0",
60
60
  "libsodium-wrappers": "^0.8.4",
@@ -69,7 +69,7 @@
69
69
  "sharp": "^0.35.3"
70
70
  },
71
71
  "devDependencies": {
72
- "@sema-agent/sdk": "8.8.0",
72
+ "@sema-agent/sdk": "9.1.0",
73
73
  "@types/libsodium-wrappers": "^0.7.14",
74
74
  "@types/node": "22.10.2",
75
75
  "@types/pg": "^8.20.0",