@sema-agent/server 1.314.0 → 1.316.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 (146) hide show
  1. package/dist/approval-hmac.d.ts +17 -0
  2. package/dist/approval-hmac.js +27 -0
  3. package/dist/config-center/apply-effective.d.ts +22 -0
  4. package/dist/config-center/apply-effective.js +283 -0
  5. package/dist/config-center/http-client.d.ts +23 -0
  6. package/dist/config-center/http-client.js +109 -0
  7. package/dist/config-center/restart-signal.d.ts +12 -0
  8. package/dist/config-center/restart-signal.js +70 -0
  9. package/dist/config-center/skills-mcp.d.ts +13 -0
  10. package/dist/config-center/skills-mcp.js +113 -0
  11. package/dist/config-center/types.d.ts +143 -0
  12. package/dist/config-center/types.js +2 -0
  13. package/dist/fleet/fleet-bus.js +92 -83
  14. package/dist/hooks/hook-runner.js +18 -9
  15. package/dist/http/idempotency.d.ts +1 -0
  16. package/dist/http/idempotency.js +3 -0
  17. package/dist/http/principal-gate.d.ts +12 -0
  18. package/dist/http/principal-gate.js +52 -0
  19. package/dist/http/route-ctx.d.ts +67 -0
  20. package/dist/http/route-ctx.js +2 -0
  21. package/dist/http/routes/attachments.d.ts +4 -0
  22. package/dist/http/routes/attachments.js +106 -0
  23. package/dist/http/routes/capabilities.d.ts +4 -0
  24. package/dist/http/routes/capabilities.js +111 -0
  25. package/dist/http/routes/images.d.ts +20 -0
  26. package/dist/http/routes/images.js +572 -0
  27. package/dist/http/routes/memory-policy.d.ts +4 -0
  28. package/dist/http/routes/memory-policy.js +105 -0
  29. package/dist/http/routes/observability.d.ts +4 -0
  30. package/dist/http/routes/observability.js +63 -0
  31. package/dist/http/routes/session-sync.d.ts +36 -0
  32. package/dist/http/routes/session-sync.js +513 -0
  33. package/dist/http/routes/sessions-list.d.ts +4 -0
  34. package/dist/http/routes/sessions-list.js +117 -0
  35. package/dist/http/routes/sessions.d.ts +17 -0
  36. package/dist/http/routes/sessions.js +746 -0
  37. package/dist/http/send.d.ts +6 -0
  38. package/dist/http/send.js +19 -0
  39. package/dist/http/server.d.ts +101 -76
  40. package/dist/http/server.js +129 -2410
  41. package/dist/http/sse-log.d.ts +25 -0
  42. package/dist/http/sse-log.js +59 -0
  43. package/dist/http/workspace-content.d.ts +3 -0
  44. package/dist/http/workspace-content.js +20 -0
  45. package/dist/index.d.ts +1 -1
  46. package/dist/leader/leader.js +5 -2
  47. package/dist/leader/wire.js +169 -165
  48. package/dist/main.js +462 -451
  49. package/dist/plugins/approval-store-sql.d.ts +52 -0
  50. package/dist/plugins/approval-store-sql.js +119 -0
  51. package/dist/plugins/breaker-state-sql.d.ts +29 -0
  52. package/dist/plugins/breaker-state-sql.js +104 -0
  53. package/dist/plugins/checkpoint-store-sql.d.ts +67 -0
  54. package/dist/plugins/checkpoint-store-sql.js +224 -0
  55. package/dist/plugins/file-snapshot-store-sql.d.ts +38 -0
  56. package/dist/plugins/file-snapshot-store-sql.js +210 -0
  57. package/dist/plugins/image-bake-store-sql.d.ts +53 -0
  58. package/dist/plugins/image-bake-store-sql.js +463 -0
  59. package/dist/plugins/image-index-sql.d.ts +33 -0
  60. package/dist/plugins/image-index-sql.js +328 -0
  61. package/dist/plugins/k8s-bg-scripts.d.ts +19 -0
  62. package/dist/plugins/k8s-bg-scripts.js +129 -0
  63. package/dist/plugins/k8s-exec-protocol.d.ts +20 -0
  64. package/dist/plugins/k8s-exec-protocol.js +87 -0
  65. package/dist/plugins/outcome-ledger-sql.d.ts +70 -0
  66. package/dist/plugins/outcome-ledger-sql.js +158 -0
  67. package/dist/plugins/pg-approval-store.d.ts +1 -27
  68. package/dist/plugins/pg-approval-store.js +1 -83
  69. package/dist/plugins/pg-breaker-state.d.ts +1 -19
  70. package/dist/plugins/pg-breaker-state.js +1 -88
  71. package/dist/plugins/pg-checkpoint-store.d.ts +1 -33
  72. package/dist/plugins/pg-checkpoint-store.js +1 -189
  73. package/dist/plugins/pg-cost-quota.js +3 -143
  74. package/dist/plugins/pg-file-snapshot-store.d.ts +1 -27
  75. package/dist/plugins/pg-file-snapshot-store.js +1 -190
  76. package/dist/plugins/pg-image-bake.d.ts +1 -40
  77. package/dist/plugins/pg-image-bake.js +1 -420
  78. package/dist/plugins/pg-image-index.d.ts +1 -21
  79. package/dist/plugins/pg-image-index.js +1 -217
  80. package/dist/plugins/pg-outcome-ledger.d.ts +2 -22
  81. package/dist/plugins/pg-outcome-ledger.js +1 -104
  82. package/dist/plugins/pg-rate-limiter.d.ts +2 -32
  83. package/dist/plugins/pg-rate-limiter.js +4 -147
  84. package/dist/plugins/pg-resume-anchor-store.d.ts +1 -13
  85. package/dist/plugins/pg-resume-anchor-store.js +1 -22
  86. package/dist/plugins/pg-run-store.d.ts +1 -75
  87. package/dist/plugins/pg-run-store.js +1 -287
  88. package/dist/plugins/pg-session-policy-store.d.ts +1 -11
  89. package/dist/plugins/pg-session-policy-store.js +1 -90
  90. package/dist/plugins/pg-tool-result-store.d.ts +1 -15
  91. package/dist/plugins/pg-tool-result-store.js +1 -52
  92. package/dist/plugins/pg-workflow-journal-store.d.ts +1 -20
  93. package/dist/plugins/pg-workflow-journal-store.js +1 -34
  94. package/dist/plugins/pg-workflow-run-store.d.ts +1 -55
  95. package/dist/plugins/pg-workflow-run-store.js +1 -220
  96. package/dist/plugins/remote-env-k8s.d.ts +5 -38
  97. package/dist/plugins/remote-env-k8s.js +7 -213
  98. package/dist/plugins/resume-anchor-store-sql.d.ts +23 -0
  99. package/dist/plugins/resume-anchor-store-sql.js +38 -0
  100. package/dist/plugins/run-store-sql.d.ts +89 -0
  101. package/dist/plugins/run-store-sql.js +397 -0
  102. package/dist/plugins/session-policy-store-sql.d.ts +22 -0
  103. package/dist/plugins/session-policy-store-sql.js +109 -0
  104. package/dist/plugins/sql-driver.d.ts +25 -0
  105. package/dist/plugins/sql-driver.js +59 -0
  106. package/dist/plugins/tidb-approval-store.d.ts +1 -39
  107. package/dist/plugins/tidb-approval-store.js +1 -71
  108. package/dist/plugins/tidb-breaker-state.d.ts +1 -17
  109. package/dist/plugins/tidb-breaker-state.js +1 -74
  110. package/dist/plugins/tidb-checkpoint-store.d.ts +1 -49
  111. package/dist/plugins/tidb-checkpoint-store.js +1 -191
  112. package/dist/plugins/tidb-file-snapshot-store.d.ts +1 -27
  113. package/dist/plugins/tidb-file-snapshot-store.js +1 -192
  114. package/dist/plugins/tidb-image-bake.d.ts +1 -38
  115. package/dist/plugins/tidb-image-bake.js +1 -348
  116. package/dist/plugins/tidb-image-index.d.ts +1 -19
  117. package/dist/plugins/tidb-image-index.js +1 -149
  118. package/dist/plugins/tidb-outcome-ledger.d.ts +1 -57
  119. package/dist/plugins/tidb-outcome-ledger.js +1 -97
  120. package/dist/plugins/tidb-resume-anchor-store.d.ts +1 -13
  121. package/dist/plugins/tidb-resume-anchor-store.js +1 -22
  122. package/dist/plugins/tidb-run-store.d.ts +1 -75
  123. package/dist/plugins/tidb-run-store.js +1 -306
  124. package/dist/plugins/tidb-session-policy-store.d.ts +1 -11
  125. package/dist/plugins/tidb-session-policy-store.js +1 -86
  126. package/dist/plugins/tidb-tool-result-store.d.ts +1 -13
  127. package/dist/plugins/tidb-tool-result-store.js +1 -38
  128. package/dist/plugins/tidb-workflow-journal-store.d.ts +1 -20
  129. package/dist/plugins/tidb-workflow-journal-store.js +1 -34
  130. package/dist/plugins/tidb-workflow-run-store.d.ts +1 -61
  131. package/dist/plugins/tidb-workflow-run-store.js +1 -231
  132. package/dist/plugins/tool-result-store-sql.d.ts +25 -0
  133. package/dist/plugins/tool-result-store-sql.js +69 -0
  134. package/dist/plugins/workflow-journal-store-sql.d.ts +30 -0
  135. package/dist/plugins/workflow-journal-store-sql.js +53 -0
  136. package/dist/plugins/workflow-run-store-sql.d.ts +85 -0
  137. package/dist/plugins/workflow-run-store-sql.js +299 -0
  138. package/dist/plugins/write-behind-counter.d.ts +14 -3
  139. package/dist/plugins/write-behind-counter.js +39 -12
  140. package/dist/principal-jwt.d.ts +44 -0
  141. package/dist/principal-jwt.js +95 -0
  142. package/dist/security.d.ts +2 -58
  143. package/dist/security.js +3 -118
  144. package/dist/sema-registry.d.ts +5 -200
  145. package/dist/sema-registry.js +4 -567
  146. package/package.json +1 -1
@@ -0,0 +1,67 @@
1
+ import type { IncomingMessage, ServerResponse } from "node:http";
2
+ import type { TaskStream } from "@sema-agent/core";
3
+ import type { FlatServiceDeps } from "./server.js";
4
+ import type { IdempotencyCache } from "./idempotency.js";
5
+ import type { ImagesLocal } from "./routes/images.js";
6
+ import type { SessionsLocal } from "./routes/sessions.js";
7
+ import type { SessionSyncLocal } from "./routes/session-sync.js";
8
+ export interface RunRegistry {
9
+ idemCache: IdempotencyCache<{
10
+ status: number;
11
+ body: unknown;
12
+ }>;
13
+ inflightRuns: Map<string, AbortController>;
14
+ preemptableRuns: Map<string, AbortController>;
15
+ cancelledViaVerb: Set<string>;
16
+ steerableRuns: Map<string, TaskStream>;
17
+ wakeParkMints: Map<string, Promise<void>>;
18
+ counters: {
19
+ uncountedBillableInflight: number;
20
+ admittedInflight: number;
21
+ };
22
+ }
23
+ export interface RouteHelpers {
24
+ readJson(req: IncomingMessage): Promise<unknown>;
25
+ readRawBody(req: IncomingMessage, max: number): Promise<Buffer>;
26
+ rateLimited(req: IncomingMessage, res: ServerResponse): boolean;
27
+ quotaExceeded(req: IncomingMessage, res: ServerResponse): boolean;
28
+ leaseDenied(req: IncomingMessage, res: ServerResponse): Promise<boolean>;
29
+ safeDecode(seg: string): string | null;
30
+ isFleetWide(req: IncomingMessage): boolean;
31
+ runOwnerOk(req: IncomingMessage, res: ServerResponse, owner: string | null): boolean;
32
+ sessionOwnerScope(req: IncomingMessage): {
33
+ fleetWide: boolean;
34
+ gateOwner: string | null;
35
+ };
36
+ sessionOwnerScopeForWrite(req: IncomingMessage): {
37
+ fleetWide: boolean;
38
+ gateOwner: string | null;
39
+ };
40
+ runSessionAcceptOk(req: IncomingMessage, res: ServerResponse, run: {
41
+ sessionId: string | null;
42
+ }, face: string, notFoundError?: string): boolean;
43
+ }
44
+ export interface RouteLocals {
45
+ images: ImagesLocal;
46
+ sessions: SessionsLocal;
47
+ sessionSync: SessionSyncLocal;
48
+ }
49
+ export interface RouteRequestState {
50
+ streamTaskId: string | undefined;
51
+ streamDetached: boolean;
52
+ source: string | null;
53
+ }
54
+ export interface RouteCtxBase {
55
+ deps: FlatServiceDeps;
56
+ registry: RunRegistry;
57
+ helpers: RouteHelpers;
58
+ local: RouteLocals;
59
+ }
60
+ export interface RouteCtx extends RouteCtxBase {
61
+ req: RouteRequestState;
62
+ }
63
+ export type RouteHandler = (req: IncomingMessage, res: ServerResponse, url: string, ctx: RouteCtx) => Promise<boolean>;
64
+ export interface RouteMiss {
65
+ fell: boolean;
66
+ }
67
+ //# sourceMappingURL=route-ctx.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=route-ctx.js.map
@@ -0,0 +1,4 @@
1
+ import type { IncomingMessage, ServerResponse } from "node:http";
2
+ import type { RouteCtx } from "../route-ctx.js";
3
+ export declare function handleAttachments(req: IncomingMessage, res: ServerResponse, url: string, ctx: RouteCtx): Promise<boolean>;
4
+ //# sourceMappingURL=attachments.d.ts.map
@@ -0,0 +1,106 @@
1
+ import { createHash } from "node:crypto";
2
+ import { uuidv7, sanitizePathComponent } from "@sema-agent/core";
3
+ import { HttpError } from "../../security.js";
4
+ import { sendJson, sendError } from "../send.js";
5
+ import { gatedPrincipal } from "../principal-gate.js";
6
+ export async function handleAttachments(req, res, url, ctx) {
7
+ const miss = { fell: false };
8
+ await handleAttachmentsBody(req, res, url, ctx, miss);
9
+ return !miss.fell;
10
+ }
11
+ async function handleAttachmentsBody(req, res, url, ctx, miss) {
12
+ const { deps } = ctx;
13
+ const { rateLimited, quotaExceeded, safeDecode, readRawBody } = ctx.helpers;
14
+ {
15
+ const am = /^\/v1\/attachments(?:\/([^/?]+))?$/.exec(url);
16
+ if (am) {
17
+ if (rateLimited(req, res) || quotaExceeded(req, res))
18
+ return;
19
+ const store = deps.taskAttachmentStore;
20
+ if (!store) {
21
+ sendJson(res, 501, { error: "attachment store not configured" });
22
+ return;
23
+ }
24
+ const principal = gatedPrincipal(req, deps.config);
25
+ if (deps.config.requirePrincipal && principal === undefined) {
26
+ sendJson(res, 401, { error: `missing principal header '${deps.config.principalHeader}'` });
27
+ return;
28
+ }
29
+ const owner = principal ?? "default";
30
+ const attId = am[1] !== undefined ? safeDecode(am[1]) : undefined;
31
+ if (attId === undefined && req.method === "POST") {
32
+ const q = new URL(req.url ?? "", "http://x").searchParams;
33
+ const rawName = q.get("name");
34
+ const base = ((rawName ?? "").split(/[/\\]/).filter(Boolean).pop() ?? "").slice(0, 128);
35
+ if (!rawName || base === "" || base === "." || base === ".." || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(base)) {
36
+ sendJson(res, 400, { error: "query param `name` is required and must reduce to a safe basename ([A-Za-z0-9._-], not starting with a dot)" });
37
+ return;
38
+ }
39
+ const name = sanitizePathComponent(base);
40
+ const mime = String(req.headers["content-type"] ?? "").split(";")[0].trim().toLowerCase();
41
+ if (!/^[a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]+$/.test(mime) || mime.length > 128) {
42
+ sendJson(res, 400, { error: "content-type must be a well-formed mime type (type/subtype)" });
43
+ return;
44
+ }
45
+ const allow = deps.config.attachmentMimeAllowlist;
46
+ if (allow && !allow.some((a) => a === mime || (a.endsWith("/*") && mime.startsWith(a.slice(0, -1))))) {
47
+ sendError(res, 415, "attachment.mime_not_allowed", `mime '${mime}' is not in this deployment's allowlist`, { code: "attachment.mime_not_allowed", allowed: allow });
48
+ return;
49
+ }
50
+ const max = deps.config.attachmentMaxBytes ?? 32 * 1024 * 1024;
51
+ let body;
52
+ try {
53
+ body = await readRawBody(req, max);
54
+ }
55
+ catch (err) {
56
+ if (err instanceof HttpError && err.status === 413) {
57
+ sendError(res, 413, "attachment.too_large", `attachment exceeds the per-file limit (${max} bytes)`, { code: "attachment.too_large", maxBytes: max });
58
+ return;
59
+ }
60
+ throw err;
61
+ }
62
+ const rec = {
63
+ id: uuidv7(),
64
+ owner,
65
+ name,
66
+ mime,
67
+ sha256: createHash("sha256").update(body).digest("hex"),
68
+ sizeBytes: body.length,
69
+ createdAtMs: Date.now(),
70
+ };
71
+ await store.put({ ...rec, content: new Uint8Array(body) });
72
+ deps.metrics?.inc("attachment_uploads_total");
73
+ sendJson(res, 201, { id: rec.id, name: rec.name, mime: rec.mime, sha256: rec.sha256, sizeBytes: rec.sizeBytes });
74
+ return;
75
+ }
76
+ if (attId !== undefined && attId !== null && req.method === "GET") {
77
+ const meta = await store.get(owner, attId);
78
+ const bytes = meta ? await store.getContent(owner, attId) : null;
79
+ if (!meta || !bytes) {
80
+ sendJson(res, 404, { error: "not found" });
81
+ return;
82
+ }
83
+ res.writeHead(200, {
84
+ "content-type": meta.mime,
85
+ "content-length": String(bytes.byteLength),
86
+ "content-disposition": `attachment; filename*=UTF-8''${encodeURIComponent(meta.name)}`,
87
+ });
88
+ res.end(Buffer.from(bytes));
89
+ return;
90
+ }
91
+ if (attId !== undefined && attId !== null && req.method === "DELETE") {
92
+ const ok = await store.delete(owner, attId);
93
+ if (!ok) {
94
+ sendJson(res, 404, { error: "not found" });
95
+ return;
96
+ }
97
+ res.writeHead(204).end();
98
+ return;
99
+ }
100
+ sendJson(res, 404, { error: "not found" });
101
+ return;
102
+ }
103
+ }
104
+ miss.fell = true;
105
+ }
106
+ //# sourceMappingURL=attachments.js.map
@@ -0,0 +1,4 @@
1
+ import type { IncomingMessage, ServerResponse } from "node:http";
2
+ import type { RouteCtx } from "../route-ctx.js";
3
+ export declare function handleCapabilities(req: IncomingMessage, res: ServerResponse, url: string, ctx: RouteCtx): Promise<boolean>;
4
+ //# sourceMappingURL=capabilities.d.ts.map
@@ -0,0 +1,111 @@
1
+ import { DEFAULT_EFFORT_LEVELS } from "@sema-agent/core";
2
+ import { cwdHonored } from "../../task-cwd.js";
3
+ import { mcpInjectionHonored } from "../../task-mcp.js";
4
+ import { sendJson, sendError } from "../send.js";
5
+ export async function handleCapabilities(req, res, url, ctx) {
6
+ const miss = { fell: false };
7
+ await handleCapabilitiesBody(req, res, url, ctx, miss);
8
+ return !miss.fell;
9
+ }
10
+ async function handleCapabilitiesBody(req, res, url, ctx, miss) {
11
+ const { deps } = ctx;
12
+ if (req.method === "GET" && url.startsWith("/v1/capabilities/scenarios/")) {
13
+ const name = url.slice("/v1/capabilities/scenarios/".length).split("?")[0];
14
+ const detail = deps.scenarioDetails?.[name];
15
+ if (!detail) {
16
+ sendError(res, 404, "scenario_not_found", "scenario not found");
17
+ return;
18
+ }
19
+ sendJson(res, 200, detail);
20
+ return;
21
+ }
22
+ if (req.method === "GET" && url === "/v1/capabilities") {
23
+ sendJson(res, 200, {
24
+ ...deps.capabilities,
25
+ asyncRuns: Boolean(deps.runStore),
26
+ artifacts: Boolean(deps.runStore),
27
+ approvals: Boolean(deps.checkpointStore),
28
+ sessions: Boolean(deps.sessionAudit),
29
+ sessionEvents: Boolean(deps.sessionWatch && deps.sessionStorage?.getLeafId && deps.sessionStorage?.ownerOf),
30
+ fleet: deps.fleetBus
31
+ ? { stream: true, sessionScope: true, observe: true, resume: "snapshot", bgNotifyFailClosed: true, steerPriority: "advisory" }
32
+ : false,
33
+ workspace: (() => {
34
+ const wfs = deps.fileSnapshotStore;
35
+ return wfs && typeof wfs.listKeys === "function" && typeof wfs.exportManifest === "function" && typeof wfs.getBlob === "function" && Boolean(deps.sessionStorage?.ownerOf)
36
+ ? { browse: true, archive: true, maxFileBytes: deps.config.workspaceFileMaxBytes ?? 8 * 1024 * 1024 }
37
+ : false;
38
+ })(),
39
+ leader: Boolean(deps.leaderEndpoint),
40
+ memory: false,
41
+ memoryWrite: false,
42
+ policy: true,
43
+ usage: Boolean(deps.costQuota),
44
+ permissionModeWrite: false,
45
+ modelSelection: true,
46
+ effortSelection: true,
47
+ toolOutput: true,
48
+ messageIdentity: true,
49
+ forwardSubagentEvents: true,
50
+ scratchpadDir: true,
51
+ subagentSteer: Boolean(deps.subagentSteerRegistry) && Boolean(deps.runStore),
52
+ subagentResume: Boolean(deps.subagentSteerRegistry) && Boolean(deps.runStore),
53
+ taskSettings: { permissions: true, permissionMode: true, model: true, outputStyle: true, env: false, hooks: deps.config.requirePrincipal !== true },
54
+ appendSystemPrompt: true,
55
+ compactionModel: true,
56
+ subagentOutput: Boolean(deps.subagentTaskOutput) && Boolean(deps.runStore),
57
+ subagentStream: Boolean(deps.subagentTaskOutput) && Boolean(deps.runStore),
58
+ taskHandles: Boolean(deps.taskHandleOutput) && Boolean(deps.taskHandleStop) && Boolean(deps.runStore),
59
+ taskAgents: deps.config.requirePrincipal !== true,
60
+ retainBackgroundProcesses: deps.config.requirePrincipal !== true,
61
+ interactiveTools: true,
62
+ projectContext: cwdHonored(deps.config),
63
+ mcpInjection: mcpInjectionHonored(deps.config),
64
+ modelUsage: Boolean(deps.runStore && deps.modelUsage),
65
+ sessionInit: true,
66
+ mcp: true,
67
+ mcpElicitation: Boolean(deps.elicitation),
68
+ askUserQuestion: Boolean(deps.question),
69
+ toolApproval: Boolean(deps.toolApproval),
70
+ sideQuery: true,
71
+ sessionList: Boolean(deps.sessionStorage?.listSessions ?? deps.runStore?.listSessions),
72
+ sessionSearch: Boolean(deps.sessionStorage?.listSessions ?? deps.runStore?.listSessions),
73
+ sessionFork: Boolean(deps.sessionStorage?.fork),
74
+ sessionDelete: Boolean(deps.purgeSession),
75
+ resumeAt: Boolean(deps.resumeAnchorStore && deps.sessionStorage?.getLeafId),
76
+ promptSuggestions: true,
77
+ sessionPolicy: Boolean(deps.sessionPolicyStore),
78
+ rewindFiles: Boolean(deps.fileSnapshotStore),
79
+ rewindFilesTo: Boolean(deps.fileSnapshotStore && deps.resumeAnchorStore && deps.sessionStorage?.getLeafId),
80
+ scheduler: Boolean(deps.config.schedulerEnabled && deps.config.requirePrincipal !== true && deps.config.remoteExec?.provider === "host"),
81
+ sessionSync: Boolean(deps.backend && deps.sessionStorage?.exportEntries && deps.fileSnapshotStore),
82
+ sendUserFile: Boolean(deps.sendUserFile && deps.config.sendUserFile?.publicEndpoint),
83
+ s3PublicEndpoint: deps.config.sendUserFile?.publicEndpoint ?? null,
84
+ sendUserFileLedger: Boolean(deps.sendFileLedger),
85
+ workflows: deps.workflowsCapable ?? Boolean(deps.workflowRunStore),
86
+ workflowsList: Boolean(deps.workflowRunStore),
87
+ manualCompact: Boolean(deps.runStore),
88
+ });
89
+ return;
90
+ }
91
+ if (req.method === "GET" && url === "/v1/models") {
92
+ const models = Object.entries(deps.config.models)
93
+ .filter(([name]) => name !== "default")
94
+ .map(([name, m]) => ({
95
+ name,
96
+ id: m.id,
97
+ provider: m.provider,
98
+ reasoning: m.reasoning,
99
+ vision: Array.isArray(m.input) ? m.input.includes("image") : false,
100
+ ...(m.contextWindow ? { contextWindow: m.contextWindow } : {}),
101
+ ...(m.maxTokens ? { maxOutputTokens: m.maxTokens } : {}),
102
+ ...(m.reasoning ? { supportedEffortLevels: [...DEFAULT_EFFORT_LEVELS] } : {}),
103
+ }));
104
+ const nonAlias = Object.entries(deps.config.models).filter(([n]) => n !== "default");
105
+ const defaultName = (nonAlias.find(([, m]) => m === deps.config.model) ?? nonAlias.find(([, m]) => m.id === deps.config.model.id))?.[0];
106
+ sendJson(res, 200, { models, default: deps.config.model.id, defaultModel: { id: deps.config.model.id, ...(defaultName ? { name: defaultName } : {}) } });
107
+ return;
108
+ }
109
+ miss.fell = true;
110
+ }
111
+ //# sourceMappingURL=capabilities.js.map
@@ -0,0 +1,20 @@
1
+ import type { IncomingMessage, ServerResponse } from "node:http";
2
+ import { RateLimiter } from "../../observability/rate-limit.js";
3
+ import type { BakeState, BakeErrorCode } from "../../plugins/store-contracts.js";
4
+ import type { FlatServiceDeps } from "../server.js";
5
+ import type { RouteCtx } from "../route-ctx.js";
6
+ export interface ImagesLocal {
7
+ bakeSubmitLimiter: RateLimiter;
8
+ }
9
+ export declare function createImagesLocal(deps: FlatServiceDeps): ImagesLocal;
10
+ export declare function coarseStatusForState(state: BakeState): "running" | "done" | "failed";
11
+ export declare function errorCodeForExit(exitCode: number | null | undefined, cancelled: boolean): BakeErrorCode;
12
+ export declare const IMAGE_DIGEST_RE: RegExp;
13
+ export declare const IMAGE_PROFILE_RE: RegExp;
14
+ export declare const BAKE_ID_RE: RegExp;
15
+ export declare const BAKE_EVENTS_RE: RegExp;
16
+ export declare const BAKE_CANCEL_RE: RegExp;
17
+ export declare const BAKE_CLAIM_RE: RegExp;
18
+ export declare const BAKE_INGEST_RE: RegExp;
19
+ export declare function handleImages(req: IncomingMessage, res: ServerResponse, url: string, ctx: RouteCtx): Promise<boolean>;
20
+ //# sourceMappingURL=images.d.ts.map