@sema-agent/server 1.313.0 → 1.315.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 (83) hide show
  1. package/dist/approval-hmac.d.ts +17 -0
  2. package/dist/approval-hmac.js +27 -0
  3. package/dist/auth-bridge.d.ts +3 -2
  4. package/dist/bench/s1/live-deps.js +2 -2
  5. package/dist/budget.d.ts +4 -76
  6. package/dist/budget.js +4 -83
  7. package/dist/capabilities/sandbox-file-send.d.ts +2 -1
  8. package/dist/config-center/apply-effective.d.ts +22 -0
  9. package/dist/config-center/apply-effective.js +283 -0
  10. package/dist/config-center/http-client.d.ts +23 -0
  11. package/dist/config-center/http-client.js +109 -0
  12. package/dist/config-center/restart-signal.d.ts +12 -0
  13. package/dist/config-center/restart-signal.js +70 -0
  14. package/dist/config-center/skills-mcp.d.ts +13 -0
  15. package/dist/config-center/skills-mcp.js +113 -0
  16. package/dist/config-center/types.d.ts +143 -0
  17. package/dist/config-center/types.js +2 -0
  18. package/dist/config-types.d.ts +1 -1
  19. package/dist/elicitation.d.ts +5 -3
  20. package/dist/elicitation.js +3 -2
  21. package/dist/fleet/fleet-bus.js +92 -83
  22. package/dist/fleet-lease.d.ts +1 -1
  23. package/dist/fleet-lease.js +1 -1
  24. package/dist/hooks/hook-llm.d.ts +5 -4
  25. package/dist/hooks/hook-runner.d.ts +1 -1
  26. package/dist/hooks/hook-runner.js +19 -10
  27. package/dist/http/server.d.ts +95 -69
  28. package/dist/http/server.js +75 -86
  29. package/dist/index.d.ts +1 -1
  30. package/dist/key-resolver.d.ts +1 -1
  31. package/dist/key-resolver.js +1 -1
  32. package/dist/leader/grader-env-factory.d.ts +1 -1
  33. package/dist/leader/grader-env-factory.js +2 -2
  34. package/dist/leader/leader.js +5 -2
  35. package/dist/leader/wire.d.ts +1 -1
  36. package/dist/leader/wire.js +170 -166
  37. package/dist/main.js +487 -476
  38. package/dist/memory-scope.d.ts +18 -0
  39. package/dist/memory-scope.js +38 -0
  40. package/dist/observability/cost-taxonomy.d.ts +34 -0
  41. package/dist/observability/cost-taxonomy.js +26 -0
  42. package/dist/observability/prompt-manifest.d.ts +75 -0
  43. package/dist/observability/prompt-manifest.js +82 -0
  44. package/dist/plugins/checkpoint-store-sql.d.ts +67 -0
  45. package/dist/plugins/checkpoint-store-sql.js +224 -0
  46. package/dist/plugins/image-bake-store-sql.d.ts +53 -0
  47. package/dist/plugins/image-bake-store-sql.js +463 -0
  48. package/dist/plugins/k8s-bg-scripts.d.ts +19 -0
  49. package/dist/plugins/k8s-bg-scripts.js +129 -0
  50. package/dist/plugins/k8s-exec-protocol.d.ts +20 -0
  51. package/dist/plugins/k8s-exec-protocol.js +87 -0
  52. package/dist/plugins/pg-checkpoint-store.d.ts +1 -33
  53. package/dist/plugins/pg-checkpoint-store.js +1 -189
  54. package/dist/plugins/pg-cost-quota.js +3 -143
  55. package/dist/plugins/pg-image-bake.d.ts +1 -40
  56. package/dist/plugins/pg-image-bake.js +1 -420
  57. package/dist/plugins/pg-rate-limiter.d.ts +2 -32
  58. package/dist/plugins/pg-rate-limiter.js +4 -147
  59. package/dist/plugins/remote-env-k8s.d.ts +5 -38
  60. package/dist/plugins/remote-env-k8s.js +7 -213
  61. package/dist/plugins/sql-driver.d.ts +25 -0
  62. package/dist/plugins/sql-driver.js +59 -0
  63. package/dist/plugins/tidb-checkpoint-store.d.ts +1 -49
  64. package/dist/plugins/tidb-checkpoint-store.js +1 -191
  65. package/dist/plugins/tidb-image-bake.d.ts +1 -38
  66. package/dist/plugins/tidb-image-bake.js +1 -348
  67. package/dist/plugins/web-search.d.ts +4 -3
  68. package/dist/plugins/write-behind-counter.d.ts +14 -3
  69. package/dist/plugins/write-behind-counter.js +39 -12
  70. package/dist/principal-jwt.d.ts +44 -0
  71. package/dist/principal-jwt.js +95 -0
  72. package/dist/question.d.ts +2 -1
  73. package/dist/question.js +3 -2
  74. package/dist/run-local.js +2 -2
  75. package/dist/runtime-caps-resolver.d.ts +7 -7
  76. package/dist/runtime-caps-resolver.js +3 -3
  77. package/dist/security.d.ts +4 -74
  78. package/dist/security.js +6 -155
  79. package/dist/sema-registry.d.ts +5 -200
  80. package/dist/sema-registry.js +4 -567
  81. package/dist/tool-approval.d.ts +2 -1
  82. package/dist/tool-approval.js +3 -2
  83. package/package.json +1 -1
@@ -0,0 +1,109 @@
1
+ import { createHash } from "node:crypto";
2
+ export async function fetchEffective(baseUrl, token, etag, fetchImpl = fetch, worker) {
3
+ const scheme = new URL(baseUrl).protocol;
4
+ if (scheme !== "http:" && scheme !== "https:")
5
+ throw new Error(`SEMA_REGISTRY_URL must be http(s), got "${scheme}"`);
6
+ const url = `${baseUrl.replace(/\/+$/, "")}/api/config/effective${worker ? `?worker=${encodeURIComponent(worker)}` : ""}`;
7
+ const res = await fetchImpl(url, {
8
+ headers: { authorization: `Bearer ${token}`, ...(etag ? { "if-none-match": etag } : {}) },
9
+ signal: AbortSignal.timeout(8000),
10
+ });
11
+ if (res.status === 304)
12
+ return null;
13
+ if (!res.ok)
14
+ throw new Error(`sema-registry HTTP ${res.status}`);
15
+ return { effective: (await res.json()), etag: res.headers.get("etag") ?? undefined };
16
+ }
17
+ export async function fetchPrincipalCaps(baseUrl, token, principal, etag, fetchImpl = fetch, worker) {
18
+ const scheme = new URL(baseUrl).protocol;
19
+ if (scheme !== "http:" && scheme !== "https:")
20
+ throw new Error(`SEMA_REGISTRY_URL must be http(s), got "${scheme}"`);
21
+ const params = new URLSearchParams({ principal });
22
+ if (worker)
23
+ params.set("worker", worker);
24
+ const url = `${baseUrl.replace(/\/+$/, "")}/api/config/effective?${params.toString()}`;
25
+ const res = await fetchImpl(url, {
26
+ headers: { authorization: `Bearer ${token}`, ...(etag ? { "if-none-match": etag } : {}) },
27
+ signal: AbortSignal.timeout(8000),
28
+ });
29
+ if (res.status === 304) {
30
+ if (!etag)
31
+ throw new Error("sema-registry returned 304 to a non-conditional principal-caps request");
32
+ return null;
33
+ }
34
+ if (!res.ok)
35
+ throw new Error(`sema-registry principal-caps HTTP ${res.status}`);
36
+ const body = (await res.json());
37
+ return {
38
+ runtimeCaps: body.runtimeCaps ?? null,
39
+ configured: Boolean(body.configured),
40
+ ...("scenario" in body || "allowlist" in body
41
+ ? {
42
+ scenario: {
43
+ scenario: typeof body.scenario === "string" ? body.scenario : null,
44
+ allowlist: Array.isArray(body.allowlist) ? body.allowlist.filter((s) => typeof s === "string") : [],
45
+ },
46
+ }
47
+ : {}),
48
+ ...((() => {
49
+ const ex = body.execution;
50
+ if (ex === undefined || ex === null)
51
+ return {};
52
+ if (typeof ex.required !== "boolean")
53
+ return { executionDrift: `execution.required is ${typeof ex.required}, expected boolean — ruling dropped (fail-open)` };
54
+ if (!Array.isArray(ex.allowedLanes))
55
+ return { executionDrift: `execution.allowedLanes is ${typeof ex.allowedLanes}, expected string[] — ruling dropped (fail-open)` };
56
+ const execution = { required: ex.required, allowedLanes: ex.allowedLanes.filter((s) => typeof s === "string") };
57
+ if (ex.sessionMirror !== undefined && ex.sessionMirror !== null) {
58
+ const sm = ex.sessionMirror;
59
+ const smOk = typeof sm === "object" && typeof sm.engineUrl === "string" && sm.engineUrl.length > 0 && (sm.required === undefined || typeof sm.required === "boolean");
60
+ if (smOk)
61
+ execution.sessionMirror = { engineUrl: sm.engineUrl, required: sm.required === true };
62
+ else
63
+ return { execution, executionDrift: "execution.sessionMirror malformed — mirror observation dropped (fail-open; lane ruling kept)" };
64
+ }
65
+ return { execution };
66
+ })()),
67
+ etag: res.headers.get("etag") ?? undefined,
68
+ };
69
+ }
70
+ export class ConfigCenterHttpError extends Error {
71
+ status;
72
+ constructor(message, status) {
73
+ super(message);
74
+ this.status = status;
75
+ this.name = "ConfigCenterHttpError";
76
+ }
77
+ }
78
+ export async function fetchSkillContent(baseUrl, token, contentHash, fetchImpl = fetch) {
79
+ const url = `${baseUrl.replace(/\/+$/, "")}/api/config/skills/content/${encodeURIComponent(contentHash)}`;
80
+ const res = await fetchImpl(url, { headers: { authorization: `Bearer ${token}` }, signal: AbortSignal.timeout(8000) });
81
+ if (!res.ok)
82
+ throw new ConfigCenterHttpError(`skill content HTTP ${res.status} for ${contentHash}`, res.status);
83
+ const content = await res.text();
84
+ const want = contentHash.replace(/^sha256:/, "").toLowerCase();
85
+ const got = createHash("sha256").update(content, "utf8").digest("hex");
86
+ if (got !== want)
87
+ throw new Error(`skill content hash mismatch for ${contentHash}: computed sha256:${got}`);
88
+ return content;
89
+ }
90
+ export async function fetchPromptArtifact(baseUrl, token, artifactDigest, fetchImpl = fetch) {
91
+ const url = `${baseUrl.replace(/\/+$/, "")}/api/config/prompts/epoch-artifacts/${encodeURIComponent(artifactDigest)}`;
92
+ const res = await fetchImpl(url, { headers: { authorization: `Bearer ${token}` }, signal: AbortSignal.timeout(8000) });
93
+ if (!res.ok)
94
+ throw new ConfigCenterHttpError(`prompt artifact HTTP ${res.status} for ${artifactDigest}`, res.status);
95
+ return await res.json();
96
+ }
97
+ export async function fetchPromptBlob(baseUrl, token, contentDigest, fetchImpl = fetch) {
98
+ const url = `${baseUrl.replace(/\/+$/, "")}/api/config/prompts/blobs/${encodeURIComponent(contentDigest)}`;
99
+ const res = await fetchImpl(url, { headers: { authorization: `Bearer ${token}` }, signal: AbortSignal.timeout(8000) });
100
+ if (!res.ok)
101
+ throw new ConfigCenterHttpError(`prompt blob HTTP ${res.status} for ${contentDigest}`, res.status);
102
+ const bytes = new Uint8Array(await res.arrayBuffer());
103
+ const want = contentDigest.replace(/^sha256:/, "").toLowerCase();
104
+ const got = createHash("sha256").update(bytes).digest("hex");
105
+ if (got !== want)
106
+ throw new Error(`prompt blob hash mismatch for ${contentDigest}: computed sha256:${got}`);
107
+ return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
108
+ }
109
+ //# sourceMappingURL=http-client.js.map
@@ -0,0 +1,12 @@
1
+ import type { EffectiveConfig } from "./types.js";
2
+ export type RestartSlice = "skills" | "mcp" | "scenarios" | "runtime-gates" | "models-tiers";
3
+ export interface RestartSignal {
4
+ restartRequired: true;
5
+ reasons: RestartSlice[];
6
+ version: number;
7
+ since: number;
8
+ }
9
+ export declare function restartReasons(boot: EffectiveConfig | undefined, current: EffectiveConfig): RestartSlice[];
10
+ export declare function planeHasActiveTiers(eff: EffectiveConfig): boolean;
11
+ export declare function modelPlaneChanged(prev: EffectiveConfig | undefined, next: EffectiveConfig): boolean;
12
+ //# sourceMappingURL=restart-signal.d.ts.map
@@ -0,0 +1,70 @@
1
+ import { resolveActiveTiers } from "@sema-agent/registry-core";
2
+ import { RUNTIME_GATE_KEYS, runtimeGatePresent, resolveDefaultModelName } from "./apply-effective.js";
3
+ const RESTART_SLICES = ["skills", "mcp", "scenarios", "runtime-gates", "models-tiers"];
4
+ function stableStringify(v) {
5
+ if (v === null || typeof v !== "object")
6
+ return JSON.stringify(v) ?? "null";
7
+ if (Array.isArray(v))
8
+ return `[${v.map(stableStringify).join(",")}]`;
9
+ const obj = v;
10
+ return `{${Object.keys(obj)
11
+ .sort()
12
+ .map((k) => `${JSON.stringify(k)}:${stableStringify(obj[k])}`)
13
+ .join(",")}}`;
14
+ }
15
+ function enabledOnly(rows) {
16
+ if (!rows)
17
+ return null;
18
+ return rows.filter((r) => r.enabled !== false);
19
+ }
20
+ function restartSliceValue(eff, slice) {
21
+ if (!eff)
22
+ return null;
23
+ switch (slice) {
24
+ case "skills":
25
+ return enabledOnly(eff.skills?.skills);
26
+ case "mcp":
27
+ return enabledOnly(eff.mcp?.servers);
28
+ case "scenarios":
29
+ return enabledOnly(eff.scenarios?.scenarios);
30
+ case "runtime-gates": {
31
+ const rt = eff.runtime;
32
+ if (!rt)
33
+ return null;
34
+ const present = {};
35
+ for (const k of RUNTIME_GATE_KEYS)
36
+ if (runtimeGatePresent(rt, k))
37
+ present[k] = rt[k];
38
+ return Object.keys(present).length ? present : null;
39
+ }
40
+ case "models-tiers": {
41
+ const active = eff.models ? resolveActiveTiers(eff.models) : undefined;
42
+ if (!active || Object.keys(active).length === 0)
43
+ return null;
44
+ const enabled = enabledOnly(eff.models?.models);
45
+ const names = new Set((enabled ?? []).map((m) => m.name));
46
+ const def = resolveDefaultModelName(eff, (n) => names.has(n), enabled?.[0]?.name ?? "");
47
+ return { models: enabled, tiers: active, default: def.name };
48
+ }
49
+ }
50
+ }
51
+ export function restartReasons(boot, current) {
52
+ return RESTART_SLICES.filter((s) => stableStringify(restartSliceValue(boot, s)) !== stableStringify(restartSliceValue(current, s)));
53
+ }
54
+ export function planeHasActiveTiers(eff) {
55
+ const active = eff.models ? resolveActiveTiers(eff.models) : undefined;
56
+ return active !== undefined && Object.keys(active).length > 0;
57
+ }
58
+ export function modelPlaneChanged(prev, next) {
59
+ if (!prev)
60
+ return true;
61
+ const fp = (e) => {
62
+ const enabled = enabledOnly(e.models?.models);
63
+ const active = e.models ? (resolveActiveTiers(e.models) ?? null) : null;
64
+ const names = new Set((enabled ?? []).map((m) => m.name));
65
+ const def = resolveDefaultModelName(e, (n) => names.has(n), enabled?.[0]?.name ?? "");
66
+ return stableStringify({ models: enabled, tiers: active, default: def.name });
67
+ };
68
+ return fp(prev) !== fp(next);
69
+ }
70
+ //# sourceMappingURL=restart-signal.js.map
@@ -0,0 +1,13 @@
1
+ import type { McpServerSpec } from "@sema-agent/core";
2
+ import type { ScopedMcpServer } from "../config-types.js";
3
+ import type { Logger } from "../observability/logger.js";
4
+ import type { LoadedSkill } from "../capabilities/skills.js";
5
+ import type { CenterMcpServer, CenterSkillManifest } from "./types.js";
6
+ export declare function applyCenterSkills(baseline: LoadedSkill[], manifest: {
7
+ skills: CenterSkillManifest[];
8
+ }, baseUrl: string, token: string, logger?: Logger, fetchImpl?: typeof fetch, diskCacheDir?: string): Promise<LoadedSkill[]>;
9
+ export declare function resolveMcpServers(mcp: {
10
+ servers: CenterMcpServer[];
11
+ }, logger?: Logger): ScopedMcpServer[];
12
+ export declare function mcpForScenario(servers: ScopedMcpServer[] | undefined, scenario: string): McpServerSpec[] | undefined;
13
+ //# sourceMappingURL=skills-mcp.d.ts.map
@@ -0,0 +1,113 @@
1
+ import { skillContentHash } from "@sema-agent/registry-core";
2
+ import { fetchSkillContent } from "./http-client.js";
3
+ export async function applyCenterSkills(baseline, manifest, baseUrl, token, logger, fetchImpl = fetch, diskCacheDir) {
4
+ const { promises: fsp } = await import("node:fs");
5
+ const { join: joinPath } = await import("node:path");
6
+ const diskRead = async (hash) => {
7
+ if (!diskCacheDir)
8
+ return undefined;
9
+ const hex = hash.replace(/^sha256:/, "");
10
+ if (!/^[0-9a-f]{64}$/.test(hex))
11
+ return undefined;
12
+ try {
13
+ const text = await fsp.readFile(joinPath(diskCacheDir, hex), "utf8");
14
+ if (skillContentHash(text) === hash)
15
+ return text;
16
+ logger?.warn("sema_registry_skill_cache_corrupt", { hash, note: "on-disk body fails its own hash — ignored, refetching from center" });
17
+ }
18
+ catch {
19
+ }
20
+ return undefined;
21
+ };
22
+ const pendingWrites = [];
23
+ const diskWrite = (hash, content) => {
24
+ if (!diskCacheDir)
25
+ return;
26
+ const hex = hash.replace(/^sha256:/, "");
27
+ pendingWrites.push((async () => {
28
+ await fsp.mkdir(diskCacheDir, { recursive: true });
29
+ const tmp = joinPath(diskCacheDir, `${hex}.${Math.random().toString(36).slice(2, 8)}.tmp`);
30
+ await fsp.writeFile(tmp, content, { mode: 0o600 });
31
+ await fsp.rename(tmp, joinPath(diskCacheDir, hex));
32
+ })().catch((err) => logger?.warn("sema_registry_skill_cache_write_failed", { hash, err: String(err) })));
33
+ };
34
+ const byName = new Map(baseline.map((s) => [s.spec.name, s]));
35
+ const contentCache = new Map();
36
+ const seenNames = new Set();
37
+ for (const m of manifest.skills ?? []) {
38
+ if (m.enabled === false)
39
+ continue;
40
+ if (seenNames.has(m.name))
41
+ logger?.warn("sema_registry_skill_duplicate_name", { name: m.name, note: "duplicate name in center manifest — last entry wins" });
42
+ seenNames.add(m.name);
43
+ try {
44
+ let content = contentCache.get(m.contentHash);
45
+ if (content === undefined)
46
+ content = await diskRead(m.contentHash);
47
+ if (content === undefined) {
48
+ content = await fetchSkillContent(baseUrl, token, m.contentHash, fetchImpl);
49
+ diskWrite(m.contentHash, content);
50
+ }
51
+ contentCache.set(m.contentHash, content);
52
+ const overrodeBuiltin = byName.has(m.name);
53
+ byName.set(m.name, { spec: { name: m.name, description: m.description, content }, scenarios: m.scenarios ?? [] });
54
+ logger?.info("sema_registry_skill", { name: m.name, hash: m.contentHash, scenarios: m.scenarios, overrodeBuiltin });
55
+ }
56
+ catch (err) {
57
+ logger?.warn("sema_registry_skill_failed", { name: m.name, hash: m.contentHash, err: String(err), note: "keeping baseline if any; skipping center version" });
58
+ }
59
+ }
60
+ await Promise.all(pendingWrites);
61
+ return [...byName.values()];
62
+ }
63
+ function resolveRefs(refs, server, kind, logger) {
64
+ if (!refs)
65
+ return {};
66
+ const out = {};
67
+ for (const [key, envName] of Object.entries(refs)) {
68
+ const v = process.env[envName];
69
+ if (v === undefined) {
70
+ logger?.warn("sema_registry_mcp_env_missing", { server, kind, key, envName, note: "skipping this MCP server — referenced env var is unset in this service" });
71
+ return null;
72
+ }
73
+ out[key] = v;
74
+ }
75
+ return out;
76
+ }
77
+ export function resolveMcpServers(mcp, logger) {
78
+ const out = [];
79
+ for (const s of mcp.servers ?? []) {
80
+ if (s.enabled === false)
81
+ continue;
82
+ const allow = s.allowTools && s.allowTools.length > 0 ? { allowTools: s.allowTools } : {};
83
+ const elicit = s.elicitation === true ? { elicitation: true } : {};
84
+ if (s.transport.kind === "stdio") {
85
+ const env = resolveRefs(s.transport.envRefs, s.name, "env", logger);
86
+ if (env === null)
87
+ continue;
88
+ out.push({
89
+ scenarios: s.scenarios ?? [],
90
+ spec: { name: s.name, transport: { kind: "stdio", command: s.transport.command, args: s.transport.args, ...(Object.keys(env).length ? { env } : {}) }, ...allow, ...elicit },
91
+ });
92
+ }
93
+ else {
94
+ const headers = resolveRefs(s.transport.headerRefs, s.name, "header", logger);
95
+ if (headers === null)
96
+ continue;
97
+ out.push({
98
+ scenarios: s.scenarios ?? [],
99
+ spec: { name: s.name, transport: { kind: "http", url: s.transport.url, ...(Object.keys(headers).length ? { headers } : {}), ...(s.transport.principalHeader ? { principalHeader: s.transport.principalHeader } : {}) }, ...allow, ...elicit },
100
+ });
101
+ }
102
+ }
103
+ if (out.length > 0)
104
+ logger?.info("sema_registry_mcp", { servers: out.map((s) => s.spec.name) });
105
+ return out;
106
+ }
107
+ export function mcpForScenario(servers, scenario) {
108
+ if (!servers || servers.length === 0)
109
+ return undefined;
110
+ const hit = servers.filter((s) => s.scenarios.length === 0 || s.scenarios.includes(scenario)).map((s) => s.spec);
111
+ return hit.length > 0 ? hit : undefined;
112
+ }
113
+ //# sourceMappingURL=skills-mcp.js.map
@@ -0,0 +1,143 @@
1
+ import type { CollabTemplateWire } from "../capabilities/collab-wire.js";
2
+ import type { Autonomy, CommandRule } from "../runtime-governance.js";
3
+ export interface CenterModel {
4
+ name: string;
5
+ id: string;
6
+ provider: string;
7
+ api: "openai-completions" | "anthropic-messages";
8
+ baseUrl?: string;
9
+ apiKeyEnv?: string;
10
+ sealedApiKey?: {
11
+ ciphertext: string;
12
+ publicKeyId: string;
13
+ alg: string;
14
+ setAt?: string;
15
+ };
16
+ tier?: string;
17
+ reasoning?: boolean;
18
+ vision?: boolean;
19
+ contextWindow?: number;
20
+ maxTokens?: number;
21
+ autoCompactTokens?: number;
22
+ charsPerToken?: number;
23
+ cost?: {
24
+ input: number;
25
+ output: number;
26
+ cacheRead?: number;
27
+ cacheWrite?: number;
28
+ };
29
+ quotaWeight?: number;
30
+ defaultThinking?: string;
31
+ reasoningEffortLevels?: string[];
32
+ extraBody?: Record<string, unknown>;
33
+ promptGuidance?: string[];
34
+ enabled?: boolean;
35
+ }
36
+ export type CenterRoleTarget = {
37
+ model: string;
38
+ } | {
39
+ select: unknown;
40
+ };
41
+ export interface CenterTeam {
42
+ name: string;
43
+ members: {
44
+ role: string;
45
+ modelRole?: string;
46
+ model?: string;
47
+ systemPrompt?: string;
48
+ }[];
49
+ rounds: number;
50
+ synthesizer?: {
51
+ role: string;
52
+ modelRole?: string;
53
+ systemPrompt?: string;
54
+ };
55
+ scenario?: string;
56
+ maxTranscriptTokens?: number;
57
+ enabled?: boolean;
58
+ }
59
+ export interface CenterSkillManifest {
60
+ name: string;
61
+ description: string;
62
+ scenarios: string[];
63
+ contentHash: string;
64
+ enabled?: boolean;
65
+ }
66
+ export interface CenterMcpServer {
67
+ name: string;
68
+ scenarios: string[];
69
+ enabled?: boolean;
70
+ allowTools?: string[];
71
+ elicitation?: boolean;
72
+ transport: {
73
+ kind: "stdio";
74
+ command: string;
75
+ args?: string[];
76
+ envRefs?: Record<string, string>;
77
+ } | {
78
+ kind: "http";
79
+ url: string;
80
+ headerRefs?: Record<string, string>;
81
+ principalHeader?: string;
82
+ };
83
+ }
84
+ export interface EffectiveConfig {
85
+ version: number;
86
+ updatedAt: string;
87
+ models: {
88
+ models: CenterModel[];
89
+ roles: Record<string, CenterRoleTarget>;
90
+ atModelAllowlist?: string[];
91
+ };
92
+ teams?: {
93
+ teams: CenterTeam[];
94
+ };
95
+ collab?: {
96
+ templates: CollabTemplateWire[];
97
+ };
98
+ skills?: {
99
+ skills: CenterSkillManifest[];
100
+ };
101
+ mcp?: {
102
+ servers: CenterMcpServer[];
103
+ };
104
+ scenarios?: {
105
+ scenarios: Array<{
106
+ name: string;
107
+ toolset: string;
108
+ enabled?: boolean;
109
+ }>;
110
+ };
111
+ runtime?: {
112
+ rateLimitPerMin?: number;
113
+ approvalRequire?: string[];
114
+ maxTaskCostUsd?: number;
115
+ maxTaskTokens?: number;
116
+ maxPrincipalCostUsd?: number;
117
+ costQuotaWindowSec?: number;
118
+ autonomy?: Autonomy;
119
+ commandPolicy?: CommandRule[];
120
+ };
121
+ projects?: {
122
+ projects?: Record<string, unknown>;
123
+ } | Record<string, unknown>;
124
+ governance?: {
125
+ autonomy?: Autonomy;
126
+ commandPolicy?: CommandRule[];
127
+ approvalRequire?: string[];
128
+ };
129
+ plugins?: {
130
+ plugins?: unknown[];
131
+ };
132
+ prompts?: unknown;
133
+ }
134
+ export interface ExecutionRuling {
135
+ required: boolean;
136
+ allowedLanes: string[];
137
+ sessionMirror?: SessionMirrorRuling;
138
+ }
139
+ export interface SessionMirrorRuling {
140
+ engineUrl: string;
141
+ required: boolean;
142
+ }
143
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -2,7 +2,7 @@ import type { SealedKeyPoison } from "./sealed-key.js";
2
2
  import type { McpServerSpec, Model, ModelRoles } from "@sema-agent/core";
3
3
  import type { ApprovalHmacKey, PrincipalJwtKey } from "./auth-keys.js";
4
4
  import type { ElicitationThrottle } from "./elicitation.js";
5
- import type { InfraCostRates } from "./finance/cost-taxonomy.js";
5
+ import type { InfraCostRates } from "./observability/cost-taxonomy.js";
6
6
  import type { Autonomy, CommandRule } from "./runtime-governance.js";
7
7
  export interface ScopedMcpServer {
8
8
  scenarios: string[];
@@ -8,12 +8,13 @@ export interface ElicitationFrame {
8
8
  mode?: "form";
9
9
  action?: McpElicitResponse["action"];
10
10
  }
11
- export interface ElicitRunContext {
11
+ export interface ElicitationRunContext {
12
12
  taskId: string;
13
13
  owner: string | null;
14
14
  emit: (frame: ElicitationFrame) => void | Promise<void>;
15
15
  abortSignal?: AbortSignal;
16
16
  }
17
+ export type ElicitRunContext = ElicitationRunContext;
17
18
  export interface ElicitationThrottle {
18
19
  maxConcurrentPerRun: number;
19
20
  maxTotalPerRun: number;
@@ -21,13 +22,14 @@ export interface ElicitationThrottle {
21
22
  ttlMs: number;
22
23
  }
23
24
  export declare const DEFAULT_ELICITATION_THROTTLE: ElicitationThrottle;
24
- export declare function parseElicitResponse(body: unknown): {
25
+ export declare function parseElicitationResponse(body: unknown): {
25
26
  ok: true;
26
27
  value: McpElicitResponse;
27
28
  } | {
28
29
  ok: false;
29
30
  error: string;
30
31
  };
32
+ export declare const parseElicitResponse: typeof parseElicitationResponse;
31
33
  export declare class ElicitationCoordinator {
32
34
  private readonly als;
33
35
  private readonly pending;
@@ -35,7 +37,7 @@ export declare class ElicitationCoordinator {
35
37
  private readonly throttle;
36
38
  private readonly now;
37
39
  constructor(throttle?: ElicitationThrottle, now?: () => number);
38
- runWithContext<T>(ctx: ElicitRunContext, fn: () => Promise<T>): Promise<T>;
40
+ runWithContext<T>(ctx: ElicitationRunContext, fn: () => Promise<T>): Promise<T>;
39
41
  elicit: (req: McpElicitRequest, signal?: AbortSignal) => Promise<McpElicitResponse>;
40
42
  respond(id: string, principal: string | undefined, body: unknown): {
41
43
  status: number;
@@ -9,7 +9,7 @@ export const DEFAULT_ELICITATION_THROTTLE = {
9
9
  minIntervalMsPerServer: 1_000,
10
10
  ttlMs: 5 * 60_000,
11
11
  };
12
- export function parseElicitResponse(body) {
12
+ export function parseElicitationResponse(body) {
13
13
  if (body === null || typeof body !== "object" || Array.isArray(body))
14
14
  return { ok: false, error: "body must be an object" };
15
15
  const b = body;
@@ -32,6 +32,7 @@ export function parseElicitResponse(body) {
32
32
  }
33
33
  return { ok: true, value: { action: b.action } };
34
34
  }
35
+ export const parseElicitResponse = parseElicitationResponse;
35
36
  function boundSchema(schema) {
36
37
  if (schema === undefined)
37
38
  return undefined;
@@ -126,7 +127,7 @@ export class ElicitationCoordinator {
126
127
  return answer;
127
128
  };
128
129
  respond(id, principal, body) {
129
- const parsed = parseElicitResponse(body);
130
+ const parsed = parseElicitationResponse(body);
130
131
  if (!parsed.ok)
131
132
  return { status: 400, body: { error: parsed.error } };
132
133
  const entry = this.pending.get(id);