@sema-agent/server 7.102.0 → 7.103.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/MIGRATION.md +61 -0
- package/README.md +3 -3
- package/README.zh-CN.md +3 -3
- package/USAGE.md +99 -6
- package/dist/background-session-reap.d.ts +4 -1
- package/dist/bake-runner/main.d.ts +21 -3
- package/dist/bake-runner/main.js +18 -11
- package/dist/boot/config-center.d.ts +7 -2
- package/dist/boot/config-center.js +18 -4
- package/dist/boot/stage-01-config.js +2 -0
- package/dist/boot/stage-10-http-server.js +6 -1
- package/dist/brain.d.ts +28 -8
- package/dist/brain.js +20 -4
- package/dist/capabilities/center-plugins.d.ts +9 -3
- package/dist/capabilities/center-plugins.js +5 -10
- package/dist/config-catalog.js +9 -5
- package/dist/config-center/apply-effective.d.ts +16 -0
- package/dist/config-center/apply-effective.js +23 -11
- package/dist/config-center/mcp-revocation.d.ts +2 -2
- package/dist/config-center/mcp-revocation.js +1 -1
- package/dist/config-center/restart-signal.d.ts +0 -10
- package/dist/config-center/restart-signal.js +2 -12
- package/dist/config-types.d.ts +35 -17
- package/dist/config-types.js +3 -3
- package/dist/config.d.ts +7 -0
- package/dist/config.js +43 -17
- package/dist/env-name-allowlist-knobs.d.ts +21 -7
- package/dist/env-name-allowlist-knobs.js +7 -2
- package/dist/fleet-client.d.ts +9 -3
- package/dist/fleet-client.js +2 -0
- package/dist/host-lsp-manager.d.ts +4 -3
- package/dist/host-lsp-manager.js +2 -6
- package/dist/http/dispatch.js +4 -0
- package/dist/http/server.d.ts +4 -0
- package/dist/leader/wire.d.ts +8 -1
- package/dist/leader/wire.js +4 -3
- package/dist/model-entry-refusal.d.ts +31 -9
- package/dist/model-entry-refusal.js +22 -10
- package/dist/model-route-endpoint.d.ts +10 -0
- package/dist/model-route-endpoint.js +6 -2
- package/dist/observability/secret-env-scrub.d.ts +12 -0
- package/dist/observability/secret-env-scrub.js +12 -0
- package/dist/outbound-dispatcher.d.ts +125 -0
- package/dist/outbound-dispatcher.js +211 -0
- package/dist/plugins/host-platform.d.ts +6 -1
- package/dist/plugins/remote-env-host.js +3 -11
- package/dist/project-memory.js +3 -6
- package/dist/run-local.js +2 -0
- package/dist/server-secret-env.d.ts +97 -24
- package/dist/server-secret-env.js +37 -1
- package/dist/trace/core-keyset-guard.d.ts +6 -1
- package/dist/trace/project.js +13 -0
- package/dist/trace/redact.d.ts +11 -0
- package/dist/trace/redact.js +1 -0
- package/package.json +4 -3
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { scrubSecretEnv } from "@sema-agent/core";
|
|
2
2
|
import { CONFIG_CATALOG } from "./config-catalog.js";
|
|
3
|
+
import { ENV_NAME_ALLOWLIST_KNOB_NAMES } from "./env-name-allowlist-knobs.js";
|
|
4
|
+
import { recordSecretEnvScrub } from "./observability/secret-env-scrub.js";
|
|
3
5
|
export const CATALOG_SECRET_ENV_NAMES = new Set(CONFIG_CATALOG.filter((spec) => spec.type === "secret").map((spec) => spec.name.toUpperCase()));
|
|
4
6
|
export function scrubServerSecrets(env, findings) {
|
|
5
7
|
const shapeFindings = [];
|
|
@@ -7,14 +9,48 @@ export function scrubServerSecrets(env, findings) {
|
|
|
7
9
|
findings.push(...shapeFindings);
|
|
8
10
|
const out = {};
|
|
9
11
|
for (const key of Object.keys(shaped)) {
|
|
10
|
-
|
|
12
|
+
const upper = key.toUpperCase();
|
|
13
|
+
if (CATALOG_SECRET_ENV_NAMES.has(upper)) {
|
|
11
14
|
findings.push({ key, kind: "config-catalog", confidence: "high", source: "server-config-catalog" });
|
|
12
15
|
continue;
|
|
13
16
|
}
|
|
17
|
+
if (ENV_NAME_ALLOWLIST_KNOB_NAMES.has(upper)) {
|
|
18
|
+
findings.push({ key, kind: "name-list-knob", confidence: "high", source: "server-name-list-knob" });
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
14
21
|
out[key] = shaped[key];
|
|
15
22
|
}
|
|
16
23
|
return out;
|
|
17
24
|
}
|
|
25
|
+
export function hostSubprocessEnv(o) {
|
|
26
|
+
const scrubFindings = [];
|
|
27
|
+
const composed = { ...scrubServerSecrets(process.env, scrubFindings), ...allowlistedEnv(o.allow, process.env) };
|
|
28
|
+
const stripped = scrubFindings.filter((f) => composed[f.key] === undefined);
|
|
29
|
+
const grouped = withholdBrokenGitConfigGroup(process.env, composed).map((key) => ({ key, kind: "git-config-group", confidence: "high", source: "server-git-config-group" }));
|
|
30
|
+
recordSecretEnvScrub(o.site, [...stripped, ...grouped], o.allow);
|
|
31
|
+
return composed;
|
|
32
|
+
}
|
|
33
|
+
const GIT_CONFIG_GROUP_MEMBER_RE = /^GIT_CONFIG_(?:COUNT|(?:KEY|VALUE)_\d+)$/;
|
|
34
|
+
function withholdBrokenGitConfigGroup(source, composed) {
|
|
35
|
+
const isMember = (k) => GIT_CONFIG_GROUP_MEMBER_RE.test(k.toUpperCase());
|
|
36
|
+
const sourceMembers = new Set(Object.keys(source).filter(isMember).map((k) => k.toUpperCase()));
|
|
37
|
+
if (!sourceMembers.has("GIT_CONFIG_COUNT"))
|
|
38
|
+
return [];
|
|
39
|
+
const composedMembers = Object.keys(composed).filter(isMember);
|
|
40
|
+
const present = new Set(composedMembers.map((k) => k.toUpperCase()));
|
|
41
|
+
if ([...sourceMembers].every((m) => present.has(m)))
|
|
42
|
+
return [];
|
|
43
|
+
for (const k of composedMembers)
|
|
44
|
+
delete composed[k];
|
|
45
|
+
return composedMembers;
|
|
46
|
+
}
|
|
47
|
+
export function gitSubprocessEnv(o) {
|
|
48
|
+
return {
|
|
49
|
+
...hostSubprocessEnv({ site: o.site, allow: [] }),
|
|
50
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
51
|
+
...(o.isolateConfig ? { GIT_CONFIG_GLOBAL: "/dev/null", GIT_CONFIG_SYSTEM: "/dev/null" } : {}),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
18
54
|
export function allowlistedEnv(names, env) {
|
|
19
55
|
const out = {};
|
|
20
56
|
for (const name of names) {
|
|
@@ -59,7 +59,7 @@ type _GuardMailboxReverse = AssertAllKeysHandled<Exclude<MailboxProjected, keyof
|
|
|
59
59
|
type MailboxAppendProjected = "from" | "content" | "sentAt" | "hopChain" | "peerMeta";
|
|
60
60
|
type _GuardMailboxAppend = AssertAllKeysHandled<Exclude<keyof MailboxAppendMessage, MailboxAppendProjected>>;
|
|
61
61
|
type _GuardMailboxAppendReverse = AssertAllKeysHandled<Exclude<MailboxAppendProjected, keyof MailboxAppendMessage>>;
|
|
62
|
-
type WiringSectionProjected = "schemaVersion" | "leg" | "ask" | "question" | "interaction" | "elicit" | "parkLane" | "session" | "fleet" | "permissionRules" | "modelGate" | "autoMode" | "mcp" | "tools" | "hooks" | "lsp" | "writeProtection" | "teamRole";
|
|
62
|
+
type WiringSectionProjected = "schemaVersion" | "leg" | "ask" | "question" | "interaction" | "elicit" | "parkLane" | "session" | "fleet" | "permissionRules" | "modelGate" | "autoMode" | "mcp" | "tools" | "hooks" | "lsp" | "hands" | "writeProtection" | "teamRole";
|
|
63
63
|
type WiringSectionExcluded = "governance" | "configFingerprint" | "autoConsolidation" | "readDeny" | "peerPresence" | "fileHistory";
|
|
64
64
|
type _GuardWiringSections = AssertAllKeysHandled<Exclude<keyof WiringManifest, WiringSectionProjected | WiringSectionExcluded>>;
|
|
65
65
|
type _GuardWiringSectionsReverse = AssertAllKeysHandled<Exclude<WiringSectionProjected | WiringSectionExcluded, keyof WiringManifest>>;
|
|
@@ -104,6 +104,9 @@ type _GuardWiringMcpLivenessReverse = AssertAllKeysHandled<Exclude<WiringMcpLive
|
|
|
104
104
|
type WiringRulesHandled = "storeWired" | "syncWired" | "orgGoverned";
|
|
105
105
|
type _GuardWiringRules = AssertAllKeysHandled<Exclude<keyof WiringSection<"permissionRules">, WiringRulesHandled>>;
|
|
106
106
|
type _GuardWiringRulesReverse = AssertAllKeysHandled<Exclude<WiringRulesHandled, keyof WiringSection<"permissionRules">>>;
|
|
107
|
+
type WiringHandsHandled = "mounted" | "reason";
|
|
108
|
+
type _GuardWiringHands = AssertAllKeysHandled<Exclude<keyof WiringSection<"hands">, WiringHandsHandled>>;
|
|
109
|
+
type _GuardWiringHandsReverse = AssertAllKeysHandled<Exclude<WiringHandsHandled, keyof WiringSection<"hands">>>;
|
|
107
110
|
type WiringWriteProtectionHandled = "targetView";
|
|
108
111
|
type _GuardWiringWriteProtection = AssertAllKeysHandled<Exclude<keyof WiringSection<"writeProtection">, WiringWriteProtectionHandled>>;
|
|
109
112
|
type _GuardWiringWriteProtectionReverse = AssertAllKeysHandled<Exclude<WiringWriteProtectionHandled, keyof WiringSection<"writeProtection">>>;
|
|
@@ -236,6 +239,8 @@ export type CoreKeysetGuards = [
|
|
|
236
239
|
_GuardWiringSections,
|
|
237
240
|
_GuardWiringWriteProtection,
|
|
238
241
|
_GuardWiringWriteProtectionReverse,
|
|
242
|
+
_GuardWiringHands,
|
|
243
|
+
_GuardWiringHandsReverse,
|
|
239
244
|
_GuardWiringReadDeny,
|
|
240
245
|
_GuardWiringReadDenyReverse,
|
|
241
246
|
_GuardWiringAutoConsolidation,
|
package/dist/trace/project.js
CHANGED
|
@@ -521,6 +521,18 @@ export function wiringManifestEventData(ev) {
|
|
|
521
521
|
const lane = str(lspIn.lane);
|
|
522
522
|
return { mounted, ...(lane === undefined ? {} : { lane }) };
|
|
523
523
|
})();
|
|
524
|
+
const handsIn = sec(m.hands);
|
|
525
|
+
const hands = (() => {
|
|
526
|
+
if (m.hands === undefined)
|
|
527
|
+
return undefined;
|
|
528
|
+
if (handsIn === undefined)
|
|
529
|
+
return dropProjectedFace("wiring_manifest.hands is not an object");
|
|
530
|
+
const mounted = bool(handsIn.mounted);
|
|
531
|
+
if (mounted === undefined)
|
|
532
|
+
return dropProjectedFace("wiring_manifest.hands.mounted is not a boolean");
|
|
533
|
+
const reason = str(handsIn.reason);
|
|
534
|
+
return { mounted, ...(reason === undefined ? {} : { reason }) };
|
|
535
|
+
})();
|
|
524
536
|
const wpIn = sec(m.writeProtection);
|
|
525
537
|
const writeProtection = (() => {
|
|
526
538
|
if (m.writeProtection === undefined)
|
|
@@ -560,6 +572,7 @@ export function wiringManifestEventData(ev) {
|
|
|
560
572
|
...(mcp !== undefined ? { mcp } : {}),
|
|
561
573
|
...(hooks !== undefined ? { hooks } : {}),
|
|
562
574
|
...(lsp !== undefined ? { lsp } : {}),
|
|
575
|
+
...(hands !== undefined ? { hands } : {}),
|
|
563
576
|
...(writeProtection !== undefined ? { writeProtection } : {}),
|
|
564
577
|
...identityFields(ev),
|
|
565
578
|
};
|
package/dist/trace/redact.d.ts
CHANGED
|
@@ -61,6 +61,17 @@ export declare function armPoolBudgetForTest(): {
|
|
|
61
61
|
ssh2ScanBytes: number;
|
|
62
62
|
};
|
|
63
63
|
export declare function resetArmPoolBudgetForTest(): void;
|
|
64
|
+
/** 本模块会写进文本的全部替换 token(`«…»` 字面),从三张表现算 —— 表改这里自动跟,不另抄一份。
|
|
65
|
+
* 🔴 **S-223 v2 修复轮起它只剩一个语义:闭形闭集的加载期校验**。运行期「这一段是不是一枚记号」已经由
|
|
66
|
+
* {@link credentialSpans} 的闭**形**那一支一处答完({@link opaqueUnitEnd}),按闭**集**再认一遍的
|
|
67
|
+
* `redactionTokenEndAt` 与它同义而更窄,已删 —— 两只「什么算记号」的判别器就是两个定义。 */
|
|
68
|
+
/** {@link buildDisplaySafeUrl} 解析不动一个配置型 URL 时的**占位**(S-475 件B)——fail-closed:输出**不含原串的
|
|
69
|
+
* 任何字节**(连 host 都不留),不许回落成原值。它不是任何一条臂的产物,所以要在这里**显式**进闭集
|
|
70
|
+
* {@link REDACTION_TOKENS}(闭形的加载期校验对它同样成立),消费端按契约 §5.1 的闭形逐枚解析时认得它。 */
|
|
71
|
+
declare const DISPLAY_SAFE_URL_TOKEN = "\u00ABredacted:url\u00BB";
|
|
72
|
+
/** S-776:出网代理 URL 的回显尺(`outbound-dispatcher.ts` `displayProxyUrl`)形不干净时整只用**同一枚**占位 —— 单独一行导出,
|
|
73
|
+
* 上面那行字面量保持 `const NAME = "…";` 形(`test/api-notice-text-freeze.test.ts` §6 的冻结扫描按这一形认替换 token)。 */
|
|
74
|
+
export { DISPLAY_SAFE_URL_TOKEN };
|
|
64
75
|
/** 测试可见:扫描器 indexOf 实际扫过的字节数(摊还线性 ⇒ ≤ 常数 × 输入长)。 */
|
|
65
76
|
export declare function ppkScanBytesForTest(): number;
|
|
66
77
|
export declare function resetPpkScanBytesForTest(): void;
|
package/dist/trace/redact.js
CHANGED
|
@@ -1091,6 +1091,7 @@ const FRAGMENT_SECRET_PATTERNS = [
|
|
|
1091
1091
|
[valueArm("xapp-\\d-", "[A-Za-z0-9-]", 4, "needs-left-boundary"), "«redacted:slack-token:partial»"],
|
|
1092
1092
|
];
|
|
1093
1093
|
const DISPLAY_SAFE_URL_TOKEN = "«redacted:url»";
|
|
1094
|
+
export { DISPLAY_SAFE_URL_TOKEN };
|
|
1094
1095
|
const WITHHELD_VALUE_TOKEN = "«redacted»";
|
|
1095
1096
|
const REDACTION_TOKENS = new Set([...FULL_ARM_PATTERNS.map(([, r]) => r), PEM_FRAGMENT_TOKEN, DISPLAY_SAFE_URL_TOKEN, ...FRAGMENT_SECRET_PATTERNS.map(([, r]) => r)]
|
|
1096
1097
|
.flatMap((r) => r.match(/«[^»]*»/g) ?? []));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/server",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.103.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",
|
|
@@ -61,14 +61,15 @@
|
|
|
61
61
|
"build:binary:run-local:darwin-arm64": "bun build --compile --target=bun-darwin-arm64 src/run-local.ts --outfile dist/run-local-darwin-arm64"
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
|
-
"@sema-agent/core": "7.
|
|
65
|
-
"@sema-agent/settings-schema": "6.
|
|
64
|
+
"@sema-agent/core": "7.33.4",
|
|
65
|
+
"@sema-agent/settings-schema": "6.2.0",
|
|
66
66
|
"e2b": "^2.28.0",
|
|
67
67
|
"libsodium-wrappers": "^0.8.4",
|
|
68
68
|
"mysql2": "^3.22.4",
|
|
69
69
|
"pg": "^8.22.0",
|
|
70
70
|
"ssh2": "^1.17.0",
|
|
71
71
|
"typebox": "1.1.39",
|
|
72
|
+
"undici": "7.30.0",
|
|
72
73
|
"ws": "^8.21.0",
|
|
73
74
|
"zod": "^4.4.3"
|
|
74
75
|
},
|