@sema-agent/server 1.316.0 → 1.317.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 (50) hide show
  1. package/README.md +9 -0
  2. package/README.zh-CN.md +7 -0
  3. package/dist/config-types.d.ts +1 -1
  4. package/dist/config.d.ts +14 -0
  5. package/dist/config.js +148 -45
  6. package/dist/elicitation.js +2 -2
  7. package/dist/http/route-ctx.d.ts +51 -2
  8. package/dist/http/routes/approvals-assistant.d.ts +11 -0
  9. package/dist/http/routes/approvals-assistant.js +530 -0
  10. package/dist/http/routes/attachments.js +7 -7
  11. package/dist/http/routes/fleet.d.ts +4 -0
  12. package/dist/http/routes/fleet.js +147 -0
  13. package/dist/http/routes/images.js +29 -29
  14. package/dist/http/routes/leader.d.ts +4 -0
  15. package/dist/http/routes/leader.js +48 -0
  16. package/dist/http/routes/memory-policy.js +10 -10
  17. package/dist/http/routes/notify-wake.d.ts +4 -0
  18. package/dist/http/routes/notify-wake.js +133 -0
  19. package/dist/http/routes/observability.js +5 -5
  20. package/dist/http/routes/runs.d.ts +19 -0
  21. package/dist/http/routes/runs.js +967 -0
  22. package/dist/http/routes/session-sync.js +28 -28
  23. package/dist/http/routes/sessions-list.js +8 -8
  24. package/dist/http/routes/sessions.js +47 -47
  25. package/dist/http/routes/side-query.d.ts +4 -0
  26. package/dist/http/routes/side-query.js +88 -0
  27. package/dist/http/routes/tasks.d.ts +4 -0
  28. package/dist/http/routes/tasks.js +632 -0
  29. package/dist/http/routes/trace-usage.d.ts +4 -0
  30. package/dist/http/routes/trace-usage.js +239 -0
  31. package/dist/http/routes/workflows.d.ts +5 -0
  32. package/dist/http/routes/workflows.js +337 -0
  33. package/dist/http/run-meta.d.ts +11 -0
  34. package/dist/http/run-meta.js +16 -0
  35. package/dist/http/send.d.ts +1 -0
  36. package/dist/http/send.js +15 -0
  37. package/dist/http/server.d.ts +6 -5
  38. package/dist/http/server.js +241 -3166
  39. package/dist/http/sse-log.js +2 -2
  40. package/dist/http/wire-types.d.ts +6 -0
  41. package/dist/leader/endpoint.js +4 -4
  42. package/dist/main.js +5 -5
  43. package/dist/plugins/remote-env-host.js +4 -3
  44. package/dist/question.js +2 -2
  45. package/dist/run-local.js +1 -1
  46. package/dist/tool-approval.js +2 -2
  47. package/dist/trace/ledger-sink.js +1 -1
  48. package/dist/trace/project.d.ts +1 -0
  49. package/dist/trace/project.js +3 -0
  50. package/package.json +1 -1
@@ -1,11 +1,11 @@
1
- import { sendJson, sseHeaders } from "./send.js";
1
+ import { sendJson, sendError, sseHeaders } from "./send.js";
2
2
  export async function streamSseLog(req, res, provider, id, staleMs) {
3
3
  const lastId = Number(req.headers["last-event-id"] ?? new URL(req.url ?? "", "http://x").searchParams.get("from") ?? 0);
4
4
  let from = Number.isFinite(lastId) ? lastId : 0;
5
5
  if (from > 0) {
6
6
  const retainedFrom = await provider.retainedFrom(id);
7
7
  if (retainedFrom > from + 1) {
8
- sendJson(res, 416, { error: "resume point evicted past retention", retainedFrom });
8
+ sendError(res, 416, "limit.retention_evicted", "resume point evicted past retention", { retainedFrom });
9
9
  return;
10
10
  }
11
11
  }
@@ -81,4 +81,10 @@ export interface TaskRequestBody {
81
81
  enableFork?: boolean;
82
82
  [k: string]: unknown;
83
83
  }
84
+ export type DecideBinding = {
85
+ checkpointToken?: string;
86
+ boundCallId?: string;
87
+ boundInputHash?: string;
88
+ updatedInput?: unknown;
89
+ };
84
90
  //# sourceMappingURL=wire-types.d.ts.map
@@ -27,12 +27,12 @@ export function createLeaderEndpoint(runLeader, opts = {}) {
27
27
  if (method === "POST" && url === "/v1/leader") {
28
28
  const b = body;
29
29
  if (!b || typeof b.objective !== "string" || b.objective.trim() === "") {
30
- return { status: 400, body: { error: "missing 'objective' string" } };
30
+ return { status: 400, body: { error: "missing 'objective' string", errorCode: "request.body_shape" } };
31
31
  }
32
32
  if (opts.requiredFields) {
33
33
  const missing = opts.requiredFields.filter((f) => typeof b[f] !== "string" || b[f].trim() === "");
34
34
  if (missing.length > 0) {
35
- return { status: 400, body: { error: `missing required field(s): ${missing.join(", ")}` } };
35
+ return { status: 400, body: { error: `missing required field(s): ${missing.join(", ")}`, errorCode: "request.body_shape" } };
36
36
  }
37
37
  }
38
38
  reap();
@@ -61,9 +61,9 @@ export function createLeaderEndpoint(runLeader, opts = {}) {
61
61
  if (m) {
62
62
  const run = runs.get(m[1]);
63
63
  if (!run)
64
- return { status: 404, body: { error: "leader run not found" } };
64
+ return { status: 404, body: { error: "leader run not found", errorCode: "not_found.leader_run" } };
65
65
  if (run.owner != null && run.owner !== (requester ?? null)) {
66
- return { status: 404, body: { error: "leader run not found" } };
66
+ return { status: 404, body: { error: "leader run not found", errorCode: "not_found.leader_run" } };
67
67
  }
68
68
  return {
69
69
  status: 200,
package/dist/main.js CHANGED
@@ -24,7 +24,7 @@ import { stat as fsStat, readFile as fsReadFile } from "node:fs/promises";
24
24
  import { acceptShellScratchpadDir, buildEnvFacts, egressForRemoteExec, ensureScratchpadDir, purgeScratchpadDir, sweepStaleScratchpads, resumeFactsForLane } from "./env-facts.js";
25
25
  import { normalizeSuggestNextPrompts, normalizeResilience, normalizeAttachments, normalizeResumeAtMode, resolveTaskLimits, taskAgentsSpecFragment, retainBackgroundProcessesFromBody, toolNameListFromBody, promptProfileFromBody } from "./spec-fields.js";
26
26
  import { createBrain, brainSummary } from "./brain.js";
27
- import { loadConfig, logConfigDiagnostics, resolveBindHost } from "./config.js";
27
+ import { configLkgEnabled, loadConfig, logConfigDiagnostics, resolveBindHost } from "./config.js";
28
28
  import { resourceSuspendOptIn } from "./resource-suspend.js";
29
29
  import { createSessionStore, ensureChildSessionDurableWithPromotion } from "./plugins/session-store.js";
30
30
  import { ForkRoutingSessionStore } from "./plugins/fork-routing-session-store.js";
@@ -247,7 +247,7 @@ async function main() {
247
247
  }
248
248
  };
249
249
  let bootConfigPending;
250
- const lkgEnabled = configProvider?.kind === "remote" && process.env.CONFIG_LKG_DISABLED !== "true";
250
+ const lkgEnabled = configProvider?.kind === "remote" && configLkgEnabled();
251
251
  const lkgPath = process.env.CONFIG_LKG_PATH ?? defaultLkgPath(cc?.worker);
252
252
  const lkgSurvivesRestart = lkgEnabled && process.env.CONFIG_LKG_DURABLE === "true";
253
253
  let lkgBooted = false;
@@ -1089,8 +1089,8 @@ async function main() {
1089
1089
  executionEnvFactory: executionEnvFactory ? executionEnvFactory : undefined,
1090
1090
  lspManager: lspManager ? lspManager : undefined,
1091
1091
  onBackgroundChildEvent: fleetBackgroundChildPublisher(fleetBus, (msg, fields) => logger.info(msg, fields)),
1092
- loadProjectMemory: config.requirePrincipal !== true && !config.projectMemoryDisabled ? makeLoadProjectMemory({ logger }) : undefined,
1093
- probeInstructionSources: config.remoteExec?.provider === "host" && config.requirePrincipal !== true && !config.projectMemoryDisabled
1092
+ loadProjectMemory: config.requirePrincipal !== true && config.projectMemoryEnabled ? makeLoadProjectMemory({ logger }) : undefined,
1093
+ probeInstructionSources: config.remoteExec?.provider === "host" && config.requirePrincipal !== true && config.projectMemoryEnabled
1094
1094
  ? makeProbeInstructionSources()
1095
1095
  : undefined,
1096
1096
  hooks: deploymentHooks,
@@ -1266,7 +1266,7 @@ async function main() {
1266
1266
  : undefined;
1267
1267
  let skills = loadSkills(config.skillsDir);
1268
1268
  if (effective?.skills && config.configCenter) {
1269
- skills = await applyCenterSkills(skills, effective.skills, config.configCenter.baseUrl, config.configCenter.token, logger, undefined, process.env.CONFIG_LKG_DISABLED !== "true" ? defaultSkillCacheDir() : undefined);
1269
+ skills = await applyCenterSkills(skills, effective.skills, config.configCenter.baseUrl, config.configCenter.token, logger, undefined, configLkgEnabled() ? defaultSkillCacheDir() : undefined);
1270
1270
  }
1271
1271
  if (effective?.plugins && config.configCenter) {
1272
1272
  const pluginOut = await applyCenterPlugins(skills, effective, {
@@ -6,6 +6,7 @@ import { randomBytes } from "node:crypto";
6
6
  import { openSync, closeSync, readSync, statSync, truncateSync, unlinkSync, mkdirSync, rmdirSync, mkdtempSync, existsSync, realpathSync } from "node:fs";
7
7
  import { StringDecoder } from "node:string_decoder";
8
8
  import { armPipeDestroyGrace } from "./remote-shell.js";
9
+ import { hostBackgroundShellEnabled, hostExecSpoolEnabled } from "../config.js";
9
10
  import { resolveHostShell, hostShell, spawnGroupOptions, killTreeHard, killTreeSoft, collapseWin32EnvKeys } from "./host-platform.js";
10
11
  import { BackgroundShellManager, seedMemStream, feedMemStream, drainMemStream } from "./background-shell-support.js";
11
12
  import { FileError, ExecutionError, RemoteExecutionError, scrubSecretEnv, RollingTailBuffer, markTruncated, SchedulerError, BackgroundShellError, } from "@sema-agent/core";
@@ -149,11 +150,11 @@ export class RemoteHostExecutionEnv {
149
150
  }
150
151
  get backgroundCapabilities() {
151
152
  return {
152
- supported: (this.cfg.backgroundShell ?? true) && process.env.HOST_BG_DISABLED !== "true",
153
+ supported: (this.cfg.backgroundShell ?? true) && hostBackgroundShellEnabled(),
153
154
  maxConcurrent: HOST_BG_MAX_CONCURRENT,
154
155
  defaultBgTimeoutSec: HOST_BG_DEFAULT_TIMEOUT_SEC,
155
156
  maxBgTimeoutSec: HOST_BG_MAX_TIMEOUT_SEC,
156
- supportsDetach: (this.cfg.backgroundShell ?? true) && process.env.HOST_BG_DISABLED !== "true",
157
+ supportsDetach: (this.cfg.backgroundShell ?? true) && hostBackgroundShellEnabled(),
157
158
  };
158
159
  }
159
160
  _bgManager;
@@ -331,7 +332,7 @@ export class RemoteHostExecutionEnv {
331
332
  const cwd = this.resolve(options?.cwd ?? this.cwd);
332
333
  const timeoutMs = options?.timeout != null ? options.timeout * 1000 : this.cfg.commandTimeoutMs;
333
334
  const detachSignal = options?.detachSignal;
334
- if (process.platform !== "win32" && process.env.HOST_EXEC_SPOOL_DISABLED !== "true") {
335
+ if (process.platform !== "win32" && hostExecSpoolEnabled()) {
335
336
  const spool = this.openFgSpool();
336
337
  if (spool)
337
338
  return this.execViaSpool(command, options, cwd, timeoutMs, detachSignal, spool);
package/dist/question.js CHANGED
@@ -118,10 +118,10 @@ export class QuestionCoordinator {
118
118
  respond(id, principal, body) {
119
119
  const parsed = parseQuestionResponse(body);
120
120
  if (!parsed.ok)
121
- return { status: 400, body: { error: parsed.error } };
121
+ return { status: 400, body: { error: parsed.error, errorCode: "request.body_shape" } };
122
122
  const entry = this.pending.get(id);
123
123
  if (!entry || (entry.owner !== null && entry.owner !== principal)) {
124
- return { status: 404, body: { error: "no pending question for this id (answered, expired, or not on this replica)" } };
124
+ return { status: 404, body: { error: "no pending question for this id (answered, expired, or not on this replica)", errorCode: "question.not_pending" } };
125
125
  }
126
126
  entry.settle(parsed.value, "answered");
127
127
  return { status: 200, body: { questionId: id, delivery: "applied" } };
package/dist/run-local.js CHANGED
@@ -254,7 +254,7 @@ export async function runLocal(argv, deps = {}) {
254
254
  toolResultStore: fileBackend.toolResultStore,
255
255
  ...(executionEnvFactory ? { executionEnvFactory } : {}),
256
256
  ...(lspManager ? { lspManager } : {}),
257
- ...(!config.projectMemoryDisabled
257
+ ...(config.projectMemoryEnabled
258
258
  ? { loadProjectMemory: makeLoadProjectMemory({ logger }), probeInstructionSources: makeProbeInstructionSources() }
259
259
  : {}),
260
260
  });
@@ -211,10 +211,10 @@ export class ToolApprovalCoordinator {
211
211
  respond(id, principal, body) {
212
212
  const parsed = parseToolApprovalResponse(body);
213
213
  if (!parsed.ok)
214
- return { status: 400, body: { error: parsed.error } };
214
+ return { status: 400, body: { error: parsed.error, errorCode: "request.body_shape" } };
215
215
  const entry = this.pending.get(id);
216
216
  if (!entry || (entry.owner !== null && entry.owner !== principal)) {
217
- return { status: 404, body: { error: "no pending tool approval for this id (settled, expired, or not on this replica)" } };
217
+ return { status: 404, body: { error: "no pending tool approval for this id (settled, expired, or not on this replica)", errorCode: "tool_approval.not_pending" } };
218
218
  }
219
219
  let rememberApplied;
220
220
  if (parsed.value === "allow_session")
@@ -45,7 +45,7 @@ export function createLedgerSink(opts) {
45
45
  break;
46
46
  case "status":
47
47
  await flush();
48
- await append("brain_status", brainStatusEventData(ev));
48
+ await append("status", brainStatusEventData(ev));
49
49
  break;
50
50
  case "context_usage":
51
51
  await flush();
@@ -221,6 +221,7 @@ export interface TaskSummary {
221
221
  };
222
222
  }
223
223
  export declare function runSummary(run: RunRecord, latestEventType?: string): TaskSummary;
224
+ export declare function normalizeRunEventType(type: string): string;
224
225
  export declare function mapTraceEvent(type: string, seq: number, data: Record<string, unknown>): {
225
226
  event: string;
226
227
  data: Record<string, unknown>;
@@ -299,6 +299,9 @@ export function runSummary(run, latestEventType) {
299
299
  lastStep: lastStep(latestEventType, run.status),
300
300
  };
301
301
  }
302
+ export function normalizeRunEventType(type) {
303
+ return type === "brain_status" ? "status" : type;
304
+ }
302
305
  export function mapTraceEvent(type, seq, data) {
303
306
  switch (type) {
304
307
  case "reasoning":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/server",
3
- "version": "1.316.0",
3
+ "version": "1.317.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",