@rivus/agent 0.6.2 → 0.7.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/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import { a as createAgentLoopSkillExecutionStart, c as createAgentLoopToolExecutionEnd, d as createAsyncIterableAgentLoop, f as createEventAgentLoop, i as createAgentLoopSkillExecutionEnd, l as createAgentLoopToolExecutionStart, m as createTextAgentLoopFromCallback, n as createAgentLoopModelExecutionEnd, o as createAgentLoopTextDelta, p as createTextAgentLoop, r as createAgentLoopModelExecutionStart, s as createAgentLoopThinkingDelta, t as createAgentLoopFromCallback, u as createAgentLoopToolExecutionUpdate } from "./agent-loop.js";
2
2
  import { a as createMemoryNamespace, c as InvalidRivusPlugin, d as requiresToolApproval, i as RIVUS_MEMORY_TOOL_VERSION, l as RIVUS_PLUGIN_API_VERSION, n as RIVUS_MEMORY_TOOL_ID, o as createRivusMemoryToolContract, r as RIVUS_MEMORY_TOOL_PLUGIN_ID, s as restrictMemoryScopesForAudience, t as MEMORY_SCOPES, u as RivusToolInputRejected } from "./agent-memory.js";
3
- import { n as resolveRivusAgentDefinition, t as createRivusPluginCatalog } from "./rivus-plugin-registry.js";
4
- import { A as CardPresentationTransitionDenied, B as FeishuEndpointCredentialError, C as loadRivusDaemonConfig, D as loadRivusDeploymentManifest, E as RivusDeploymentManifestError, F as completeCardPresentationHandoff, G as validateRivusDeploymentManifest, I as createCardPresentationChain, L as failCardPresentationHandoff, M as activeCardPresentation, N as beginCardPresentationHandoff, O as DEFAULT_CARD_STREAM_LEASE_MS, P as compensateCardPresentationHandoff, R as isCardPresentationHandoffDue, S as RivusDaemonConfigError, U as RivusPluginLoadError, V as resolveFeishuEndpointCredentials, W as loadRivusDeployment, _ as createStableId, a as InvalidRivusProjectSpace, b as createRivusEnvFromOpenClawConfig, c as RivusDeploymentReadinessError, d as createRivusAgentHost, f as AgentInstanceBusy, g as createAgentInstanceRegistry, h as AgentInstanceConflict, i as resolveRivusProjectSpace, j as acceptsCardPresentationProgress, k as createFeishuCardRollover, l as createRivusDeploymentDaemon, m as createAgentRuntimePool, n as createRivusDeploymentCliProcess, o as RivusDeploymentAutomationReadinessError, p as AgentRuntimeDisposed, r as createConfiguredRivusDeploymentDaemon, s as RivusDeploymentDaemonLifecycleError, t as runRivusDaemonCli, u as InvalidRivusEndpointBinding, v as createRivusDaemonShutdownController, w as loadNodeRivusPluginModule, x as formatRivusEnvFile, y as OpenClawEnvImportError, z as markCardPresentationTerminal } from "./rivus-daemon-cli.js";
3
+ import { a as BACKGROUND_SESSION_START_TOOL_ID, c as BACKGROUND_SESSION_TOOL_VERSION, d as createBackgroundSessionStepSourceMessageId, f as createBackgroundSessionToolContracts, h as narrowBackgroundSessionDefinition, i as BACKGROUND_SESSION_SESSION_KEY_PREFIX, l as backgroundSessionToolIds, m as isBackgroundSessionToolId, n as resolveRivusAgentDefinition, o as BACKGROUND_SESSION_TOOL_IDS, p as extendBackgroundSessionDefinition, s as BACKGROUND_SESSION_TOOL_PLUGIN_ID, t as createRivusPluginCatalog, u as createBackgroundSessionKey } from "./rivus-plugin-registry.js";
4
+ import { $ as loadRivusDeployment, A as DEFAULT_BACKGROUND_SESSION_LIFETIME_MS, B as acceptsCardPresentationProgress, C as loadRivusDaemonConfig, D as loadRivusDeploymentManifest, E as RivusDeploymentManifestError, F as DEFAULT_BACKGROUND_SESSION_SUPERVISOR_INTERVAL_MS, G as createCardPresentationChain, H as beginCardPresentationHandoff, I as resolveBackgroundSessionSupervisorIntervalMs, J as markCardPresentationTerminal, K as failCardPresentationHandoff, L as DEFAULT_CARD_STREAM_LEASE_MS, M as DEFAULT_BACKGROUND_SESSION_MAX_CONSECUTIVE_FAILURES, N as DEFAULT_BACKGROUND_SESSION_RETRY_BACKOFF_MS, O as DEFAULT_BACKGROUND_SESSION_LEASE_MS, P as DEFAULT_BACKGROUND_SESSION_STEP_TIMEOUT_MS, Q as RivusPluginLoadError, R as createFeishuCardRollover, S as RivusDaemonConfigError, U as compensateCardPresentationHandoff, V as activeCardPresentation, W as completeCardPresentationHandoff, X as resolveFeishuEndpointCredentials, Y as FeishuEndpointCredentialError, _ as createStableId, a as InvalidRivusProjectSpace, b as createRivusEnvFromOpenClawConfig, c as RivusDeploymentReadinessError, d as createRivusAgentHost, et as validateRivusDeploymentManifest, f as AgentInstanceBusy, g as createAgentInstanceRegistry, h as AgentInstanceConflict, i as resolveRivusProjectSpace, j as DEFAULT_BACKGROUND_SESSION_MAX_CONCURRENT_SESSIONS, k as DEFAULT_BACKGROUND_SESSION_LEASE_RENEWAL_INTERVAL_MS, l as createRivusDeploymentDaemon, m as createAgentRuntimePool, n as createRivusDeploymentCliProcess, o as RivusDeploymentAutomationReadinessError, p as AgentRuntimeDisposed, q as isCardPresentationHandoffDue, r as createConfiguredRivusDeploymentDaemon, s as RivusDeploymentDaemonLifecycleError, t as runRivusDaemonCli, u as InvalidRivusEndpointBinding, v as createRivusDaemonShutdownController, w as loadNodeRivusPluginModule, x as formatRivusEnvFile, y as OpenClawEnvImportError, z as CardPresentationTransitionDenied } from "./rivus-daemon-cli.js";
5
5
  import { a as InvalidInvocationAuthority, i as normalizeStableJson, n as InvalidToolInput, o as createInvocationAuthority, r as createToolInputDigest, s as resolveInvocationAuthority, t as InvalidStableJson } from "./tool-input-digest.js";
6
6
  import { n as assertRivusPluginConforms, r as createFakeRivusPlugin, t as RivusPluginConformanceError } from "./rivus-plugin-testkit.js";
7
7
  import { Cause, Deferred, Effect, Either, Exit, Fiber, Option, Stream } from "effect";
8
8
  import { createHash, randomUUID } from "node:crypto";
9
9
  import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
10
- import { appendFile, lstat, mkdir, readFile, readdir, realpath, rename, stat, unlink, writeFile } from "node:fs/promises";
10
+ import { appendFile, lstat, mkdir, readFile, readdir, realpath, rename, stat, truncate, unlink, writeFile } from "node:fs/promises";
11
11
  import { isDeepStrictEqual } from "node:util";
12
12
  import { createServer } from "node:http";
13
13
  import { Buffer as Buffer$1 } from "node:buffer";
@@ -3443,36 +3443,36 @@ function parseAgentDomainEvent(value, lineNumber) {
3443
3443
  switch (value.type) {
3444
3444
  case "agent_run_accepted": return {
3445
3445
  occurredAt,
3446
- prompt: readString(value, "prompt", lineNumber),
3447
- runId: readString(value, "runId", lineNumber),
3448
- sessionKey: readString(value, "sessionKey", lineNumber),
3446
+ prompt: readString$1(value, "prompt", lineNumber),
3447
+ runId: readString$1(value, "runId", lineNumber),
3448
+ sessionKey: readString$1(value, "sessionKey", lineNumber),
3449
3449
  type: value.type
3450
3450
  };
3451
3451
  case "agent_turn_started": return {
3452
3452
  occurredAt,
3453
- runId: readString(value, "runId", lineNumber),
3454
- sessionKey: readString(value, "sessionKey", lineNumber),
3453
+ runId: readString$1(value, "runId", lineNumber),
3454
+ sessionKey: readString$1(value, "sessionKey", lineNumber),
3455
3455
  type: value.type
3456
3456
  };
3457
3457
  case "assistant_text_delta": return {
3458
- delta: readString(value, "delta", lineNumber),
3458
+ delta: readString$1(value, "delta", lineNumber),
3459
3459
  occurredAt,
3460
- runId: readString(value, "runId", lineNumber),
3460
+ runId: readString$1(value, "runId", lineNumber),
3461
3461
  type: value.type
3462
3462
  };
3463
3463
  case "assistant_thinking_delta": return {
3464
- delta: readString(value, "delta", lineNumber),
3464
+ delta: readString$1(value, "delta", lineNumber),
3465
3465
  occurredAt,
3466
- runId: readString(value, "runId", lineNumber),
3466
+ runId: readString$1(value, "runId", lineNumber),
3467
3467
  type: value.type
3468
3468
  };
3469
3469
  case "agent_model_execution_started": return {
3470
- api: readString(value, "api", lineNumber),
3471
- model: readString(value, "model", lineNumber),
3472
- modelCallId: readString(value, "modelCallId", lineNumber),
3470
+ api: readString$1(value, "api", lineNumber),
3471
+ model: readString$1(value, "model", lineNumber),
3472
+ modelCallId: readString$1(value, "modelCallId", lineNumber),
3473
3473
  occurredAt,
3474
- provider: readString(value, "provider", lineNumber),
3475
- runId: readString(value, "runId", lineNumber),
3474
+ provider: readString$1(value, "provider", lineNumber),
3475
+ runId: readString$1(value, "runId", lineNumber),
3476
3476
  type: value.type
3477
3477
  };
3478
3478
  case "agent_model_execution_ended": {
@@ -3481,15 +3481,15 @@ function parseAgentDomainEvent(value, lineNumber) {
3481
3481
  const responseModel = readOptionalString(value, "responseModel", lineNumber);
3482
3482
  const reasoning = readOptionalNumber(usage, "reasoning", lineNumber);
3483
3483
  return {
3484
- api: readString(value, "api", lineNumber),
3484
+ api: readString$1(value, "api", lineNumber),
3485
3485
  ...errorMessage ? { errorMessage } : {},
3486
- model: readString(value, "model", lineNumber),
3487
- modelCallId: readString(value, "modelCallId", lineNumber),
3486
+ model: readString$1(value, "model", lineNumber),
3487
+ modelCallId: readString$1(value, "modelCallId", lineNumber),
3488
3488
  occurredAt,
3489
- provider: readString(value, "provider", lineNumber),
3489
+ provider: readString$1(value, "provider", lineNumber),
3490
3490
  ...responseModel ? { responseModel } : {},
3491
- runId: readString(value, "runId", lineNumber),
3492
- stopReason: readString(value, "stopReason", lineNumber),
3491
+ runId: readString$1(value, "runId", lineNumber),
3492
+ stopReason: readString$1(value, "stopReason", lineNumber),
3493
3493
  type: value.type,
3494
3494
  usage: {
3495
3495
  cacheRead: readNumber(usage, "cacheRead", lineNumber),
@@ -3519,10 +3519,10 @@ function parseAgentDomainEvent(value, lineNumber) {
3519
3519
  } : {
3520
3520
  ...common,
3521
3521
  contentLength: readNumber(value, "contentLength", lineNumber),
3522
- digest: readString(value, "digest", lineNumber),
3522
+ digest: readString$1(value, "digest", lineNumber),
3523
3523
  isError: false,
3524
- title: readString(value, "title", lineNumber),
3525
- version: readString(value, "version", lineNumber)
3524
+ title: readString$1(value, "title", lineNumber),
3525
+ version: readString$1(value, "version", lineNumber)
3526
3526
  };
3527
3527
  }
3528
3528
  case "agent_tool_execution_started": return {
@@ -3546,21 +3546,21 @@ function parseAgentDomainEvent(value, lineNumber) {
3546
3546
  type: value.type
3547
3547
  };
3548
3548
  case "agent_turn_completed": return {
3549
- finalText: readString(value, "finalText", lineNumber),
3549
+ finalText: readString$1(value, "finalText", lineNumber),
3550
3550
  occurredAt,
3551
- runId: readString(value, "runId", lineNumber),
3551
+ runId: readString$1(value, "runId", lineNumber),
3552
3552
  type: value.type
3553
3553
  };
3554
3554
  case "agent_run_completed": return {
3555
- finalText: readString(value, "finalText", lineNumber),
3555
+ finalText: readString$1(value, "finalText", lineNumber),
3556
3556
  occurredAt,
3557
- runId: readString(value, "runId", lineNumber),
3557
+ runId: readString$1(value, "runId", lineNumber),
3558
3558
  type: value.type
3559
3559
  };
3560
3560
  case "agent_run_failed": return {
3561
- errorMessage: readString(value, "errorMessage", lineNumber),
3561
+ errorMessage: readString$1(value, "errorMessage", lineNumber),
3562
3562
  occurredAt,
3563
- runId: readString(value, "runId", lineNumber),
3563
+ runId: readString$1(value, "runId", lineNumber),
3564
3564
  type: value.type
3565
3565
  };
3566
3566
  case "agent_run_cancelled": {
@@ -3568,7 +3568,7 @@ function parseAgentDomainEvent(value, lineNumber) {
3568
3568
  return {
3569
3569
  occurredAt,
3570
3570
  ...reason ? { reason } : {},
3571
- runId: readString(value, "runId", lineNumber),
3571
+ runId: readString$1(value, "runId", lineNumber),
3572
3572
  type: value.type
3573
3573
  };
3574
3574
  }
@@ -3577,19 +3577,19 @@ function parseAgentDomainEvent(value, lineNumber) {
3577
3577
  }
3578
3578
  function readSkillExecutionIdentity(value, lineNumber) {
3579
3579
  return {
3580
- runId: readString(value, "runId", lineNumber),
3581
- skillCallId: readString(value, "skillCallId", lineNumber),
3582
- skillId: readString(value, "skillId", lineNumber)
3580
+ runId: readString$1(value, "runId", lineNumber),
3581
+ skillCallId: readString$1(value, "skillCallId", lineNumber),
3582
+ skillId: readString$1(value, "skillId", lineNumber)
3583
3583
  };
3584
3584
  }
3585
3585
  function readToolExecutionIdentity(value, lineNumber) {
3586
3586
  return {
3587
- runId: readString(value, "runId", lineNumber),
3588
- toolCallId: readString(value, "toolCallId", lineNumber),
3589
- toolName: readString(value, "toolName", lineNumber)
3587
+ runId: readString$1(value, "runId", lineNumber),
3588
+ toolCallId: readString$1(value, "toolCallId", lineNumber),
3589
+ toolName: readString$1(value, "toolName", lineNumber)
3590
3590
  };
3591
3591
  }
3592
- function readString(value, field, lineNumber) {
3592
+ function readString$1(value, field, lineNumber) {
3593
3593
  const fieldValue = value[field];
3594
3594
  if (typeof fieldValue !== "string") throw new Error(`Invalid agent event field '${field}' at line ${lineNumber}.`);
3595
3595
  return fieldValue;
@@ -4760,7 +4760,7 @@ function unwrapResult(value) {
4760
4760
  }
4761
4761
  function presentResult(toolName, value) {
4762
4762
  if (isTruncated(value)) return "结果过长,已省略。";
4763
- if (!isRecord(value)) return truncate(presentValue(value) ?? "工具执行完成。", 2e3);
4763
+ if (!isRecord(value)) return truncate$1(presentValue(value) ?? "工具执行完成。", 2e3);
4764
4764
  const tool = resolveTool(toolName);
4765
4765
  const orderedKeys = tool.fields?.map(([key]) => key) ?? [];
4766
4766
  const lines = Object.entries(value).sort(([left], [right]) => {
@@ -4772,7 +4772,7 @@ function presentResult(toolName, value) {
4772
4772
  const presented = presentValue(item, field?.[2]);
4773
4773
  return presented ? [`${clean(field?.[1] ?? humanizeKey(key), 80)}:${presented}`] : [];
4774
4774
  }).slice(0, 12);
4775
- return truncate(lines.length > 0 ? lines.join("\n") : "工具执行完成。", 2e3);
4775
+ return truncate$1(lines.length > 0 ? lines.join("\n") : "工具执行完成。", 2e3);
4776
4776
  }
4777
4777
  function presentValue(value, unit) {
4778
4778
  if (value === REDACTED || value === TRUNCATED || value === void 0) return void 0;
@@ -4796,9 +4796,9 @@ function humanizeKey(key) {
4796
4796
  return `${text.slice(0, 1).toUpperCase()}${text.slice(1)}` || "结果";
4797
4797
  }
4798
4798
  function clean(value, maxLength) {
4799
- return truncate(value.replace(/[\p{Cc}\p{Cf}]+/gu, " ").replace(/\s+/gu, " ").trim(), maxLength);
4799
+ return truncate$1(value.replace(/[\p{Cc}\p{Cf}]+/gu, " ").replace(/\s+/gu, " ").trim(), maxLength);
4800
4800
  }
4801
- function truncate(value, maxLength) {
4801
+ function truncate$1(value, maxLength) {
4802
4802
  return value.length <= maxLength ? value : `${value.slice(0, maxLength - 1)}…`;
4803
4803
  }
4804
4804
  function isRecord(value) {
@@ -5346,7 +5346,14 @@ function createToolBroker(options) {
5346
5346
  runId: authority.runId,
5347
5347
  sessionKey: authority.sessionKey,
5348
5348
  toolId: tool.id,
5349
- toolVersion: tool.version
5349
+ toolVersion: tool.version,
5350
+ ...authority.endpointId ? { origin: Object.freeze({
5351
+ ...authority.allowedActorOpenIds ? { allowedActorOpenIds: authority.allowedActorOpenIds } : { allowedActorOpenIds: Object.freeze([]) },
5352
+ endpointId: authority.endpointId,
5353
+ tenantKey: authority.tenantKey,
5354
+ ...authority.conversationId ? { conversationId: authority.conversationId } : {}
5355
+ }) } : {},
5356
+ ...authority.sourceMessageId ? { sourceMessageId: authority.sourceMessageId } : {}
5350
5357
  });
5351
5358
  const replayCompleted = (result) => "replayCompleted" in tool && tool.replayCompleted ? tool.replayCompleted(request.input, result, context) : result;
5352
5359
  if (request.operationId) {
@@ -5881,6 +5888,1483 @@ function isVisibleMemory(record) {
5881
5888
  return record.scope !== "shared-user-profile" && record.scope !== "project" || record.state === "confirmed";
5882
5889
  }
5883
5890
  //#endregion
5891
+ //#region src/domain/background-agent-session.ts
5892
+ const BACKGROUND_SESSION_TERMINAL_PHASES = /* @__PURE__ */ new Set([
5893
+ "stopped",
5894
+ "completed",
5895
+ "failed",
5896
+ "reconciliation-required"
5897
+ ]);
5898
+ function isBackgroundSessionTerminalPhase(phase) {
5899
+ return BACKGROUND_SESSION_TERMINAL_PHASES.has(phase);
5900
+ }
5901
+ var BackgroundSessionTransitionDenied = class extends Error {
5902
+ sessionId;
5903
+ name = "BackgroundSessionTransitionDenied";
5904
+ constructor(sessionId, message) {
5905
+ super(message);
5906
+ this.sessionId = sessionId;
5907
+ }
5908
+ };
5909
+ function createBackgroundSession(input) {
5910
+ if (!input.sessionId.trim()) throw new BackgroundSessionTransitionDenied(input.sessionId, "background session id must not be empty");
5911
+ if (!input.authority.sessionKey.trim()) throw new BackgroundSessionTransitionDenied(input.sessionId, "background session key must not be empty");
5912
+ if (!input.authority.agentId.trim()) throw new BackgroundSessionTransitionDenied(input.sessionId, "background session authority requires an agent id");
5913
+ if (!input.sourceMessageId.trim()) throw new BackgroundSessionTransitionDenied(input.sessionId, "background session requires a trusted source message id");
5914
+ return Object.freeze({
5915
+ authority: Object.freeze({
5916
+ ...input.authority,
5917
+ memoryScopes: Object.freeze([...input.authority.memoryScopes])
5918
+ }),
5919
+ consecutiveFailures: 0,
5920
+ createdAt: input.now,
5921
+ displayName: input.displayName,
5922
+ origin: Object.freeze({
5923
+ ...input.origin,
5924
+ allowedActorOpenIds: Object.freeze([...input.origin.allowedActorOpenIds])
5925
+ }),
5926
+ parentRunId: input.parentRunId,
5927
+ pendingInput: Object.freeze([]),
5928
+ phase: "queued",
5929
+ prompt: input.prompt,
5930
+ revision: 1,
5931
+ sessionId: input.sessionId,
5932
+ sourceMessageId: input.sourceMessageId,
5933
+ stepCount: 0,
5934
+ updatedAt: input.now,
5935
+ wakeCount: 0
5936
+ });
5937
+ }
5938
+ function claimBackgroundSession(state, input) {
5939
+ if (isBackgroundSessionTerminalPhase(state.phase)) throw new BackgroundSessionTransitionDenied(state.sessionId, `terminal ${state.phase} session cannot run again`);
5940
+ if (state.phase !== "queued" && state.phase !== "waiting") throw new BackgroundSessionTransitionDenied(state.sessionId, `background session cannot start a step while ${state.phase}`);
5941
+ if (state.wakeAt !== void 0 && state.wakeAt > input.now) throw new BackgroundSessionTransitionDenied(state.sessionId, "background session is not due");
5942
+ return next(state, {
5943
+ currentStepRunId: input.stepRunId,
5944
+ lastWakeText: input.wakeText,
5945
+ lease: input.lease,
5946
+ pendingInput: Object.freeze([]),
5947
+ phase: "running",
5948
+ stepCount: state.stepCount + 1,
5949
+ updatedAt: input.now,
5950
+ wakeAt: void 0,
5951
+ wakeCount: state.wakeCount + 1
5952
+ });
5953
+ }
5954
+ function renewBackgroundSessionLease(state, lease) {
5955
+ if (state.lease === void 0) throw new BackgroundSessionTransitionDenied(state.sessionId, "cannot renew a lease that is not held");
5956
+ if (state.lease.owner !== lease.owner || state.lease.epoch !== lease.epoch) throw new BackgroundSessionTransitionDenied(state.sessionId, "cannot renew a lease from another worker");
5957
+ return next(state, { lease });
5958
+ }
5959
+ function releaseBackgroundSessionLease(state) {
5960
+ if (state.lease === void 0) throw new BackgroundSessionTransitionDenied(state.sessionId, "no lease to release");
5961
+ return next(state, { lease: void 0 });
5962
+ }
5963
+ function suspendBackgroundSession(state, input) {
5964
+ if (state.phase !== "running") throw new BackgroundSessionTransitionDenied(state.sessionId, `background session cannot wait while ${state.phase}`);
5965
+ if (input.wakeAt !== void 0 && input.wakeAt <= input.now) throw new BackgroundSessionTransitionDenied(state.sessionId, "background session wake time must be in the future");
5966
+ return next(state, {
5967
+ currentStepRunId: void 0,
5968
+ phase: input.wakeAt === void 0 ? "input-required" : "waiting",
5969
+ updatedAt: input.now,
5970
+ ...input.wakeAt === void 0 ? {} : { wakeAt: input.wakeAt }
5971
+ });
5972
+ }
5973
+ function completeBackgroundSessionStep(state, input) {
5974
+ if (state.phase !== "running") throw new BackgroundSessionTransitionDenied(state.sessionId, `background session cannot complete while ${state.phase}`);
5975
+ return next(state, {
5976
+ consecutiveFailures: 0,
5977
+ currentStepRunId: void 0,
5978
+ lease: void 0,
5979
+ phase: "completed",
5980
+ result: {
5981
+ completedAt: input.now,
5982
+ stepRunId: input.stepRunId,
5983
+ text: input.text
5984
+ },
5985
+ updatedAt: input.now
5986
+ });
5987
+ }
5988
+ function failBackgroundSessionStep(state, input) {
5989
+ if (state.phase !== "running") throw new BackgroundSessionTransitionDenied(state.sessionId, `background session cannot fail while ${state.phase}`);
5990
+ if (input.retryable) {
5991
+ if (input.wakeAt === void 0 || input.wakeAt <= input.now) throw new BackgroundSessionTransitionDenied(state.sessionId, "retryable failure requires a future wake time");
5992
+ return next(state, {
5993
+ consecutiveFailures: state.consecutiveFailures + 1,
5994
+ currentStepRunId: void 0,
5995
+ errorMessage: input.errorMessage,
5996
+ lease: void 0,
5997
+ phase: "queued",
5998
+ updatedAt: input.now,
5999
+ wakeAt: input.wakeAt
6000
+ });
6001
+ }
6002
+ return next(state, {
6003
+ consecutiveFailures: state.consecutiveFailures + 1,
6004
+ currentStepRunId: void 0,
6005
+ errorMessage: input.errorMessage,
6006
+ lease: void 0,
6007
+ phase: "failed",
6008
+ updatedAt: input.now
6009
+ });
6010
+ }
6011
+ function requestBackgroundSessionStop(state, input) {
6012
+ if (isBackgroundSessionTerminalPhase(state.phase)) throw new BackgroundSessionTransitionDenied(state.sessionId, `terminal ${state.phase} session cannot stop`);
6013
+ if (state.phase === "stopping") throw new BackgroundSessionTransitionDenied(state.sessionId, "background session is already stopping");
6014
+ if (state.phase === "running") return next(state, {
6015
+ cancellation: {
6016
+ reason: input.reason,
6017
+ requestedAt: input.now
6018
+ },
6019
+ phase: "stopping",
6020
+ updatedAt: input.now
6021
+ });
6022
+ return next(state, {
6023
+ cancellation: {
6024
+ reason: input.reason,
6025
+ requestedAt: input.now
6026
+ },
6027
+ currentStepRunId: void 0,
6028
+ lease: void 0,
6029
+ phase: "stopped",
6030
+ updatedAt: input.now,
6031
+ wakeAt: void 0
6032
+ });
6033
+ }
6034
+ function completeBackgroundSessionStop(state, input) {
6035
+ if (state.phase !== "stopping") throw new BackgroundSessionTransitionDenied(state.sessionId, `background session cannot finish stopping while ${state.phase}`);
6036
+ return next(state, {
6037
+ currentStepRunId: void 0,
6038
+ lease: void 0,
6039
+ phase: "stopped",
6040
+ updatedAt: input.now,
6041
+ wakeAt: void 0
6042
+ });
6043
+ }
6044
+ function parkBackgroundSessionForReconciliation(state, input) {
6045
+ if (isBackgroundSessionTerminalPhase(state.phase) && state.phase !== "reconciliation-required") throw new BackgroundSessionTransitionDenied(state.sessionId, `terminal ${state.phase} session cannot be reconciled`);
6046
+ return next(state, {
6047
+ currentStepRunId: void 0,
6048
+ errorMessage: input.reason,
6049
+ lease: void 0,
6050
+ phase: "reconciliation-required",
6051
+ reconciliationNote: input.reason,
6052
+ updatedAt: input.now,
6053
+ wakeAt: void 0
6054
+ });
6055
+ }
6056
+ function resolveBackgroundSessionReconciliation(state, input) {
6057
+ if (state.phase !== "reconciliation-required") throw new BackgroundSessionTransitionDenied(state.sessionId, `background session cannot resolve while ${state.phase}`);
6058
+ if (input.outcome === "continue") return next(state, {
6059
+ errorMessage: void 0,
6060
+ phase: "queued",
6061
+ reconciliationNote: void 0,
6062
+ updatedAt: input.now,
6063
+ wakeAt: input.now
6064
+ });
6065
+ return next(state, {
6066
+ errorMessage: void 0,
6067
+ phase: "stopped",
6068
+ reconciliationNote: void 0,
6069
+ updatedAt: input.now,
6070
+ wakeAt: void 0
6071
+ });
6072
+ }
6073
+ function appendBackgroundSessionInput(state, input) {
6074
+ if (isBackgroundSessionTerminalPhase(state.phase)) throw new BackgroundSessionTransitionDenied(state.sessionId, `terminal ${state.phase} session cannot accept input`);
6075
+ return next(state, {
6076
+ pendingInput: Object.freeze([...state.pendingInput, input.message]),
6077
+ updatedAt: input.now,
6078
+ ...state.phase === "waiting" || state.phase === "input-required" ? {
6079
+ phase: "queued",
6080
+ wakeAt: input.now
6081
+ } : {}
6082
+ });
6083
+ }
6084
+ function requeueInterruptedBackgroundSessionStep(state, input) {
6085
+ if (state.phase !== "running") throw new BackgroundSessionTransitionDenied(state.sessionId, "interrupted step recovery requires a running session");
6086
+ return next(state, {
6087
+ currentStepRunId: void 0,
6088
+ lastWakeText: input.wakeText,
6089
+ lease: void 0,
6090
+ phase: "queued",
6091
+ updatedAt: input.now,
6092
+ wakeAt: input.now
6093
+ });
6094
+ }
6095
+ function isBackgroundSessionLeaseExpired(state, now) {
6096
+ return state.lease !== void 0 && state.lease.expiresAt <= now;
6097
+ }
6098
+ function isBackgroundSessionDue(state, now) {
6099
+ if (state.phase !== "queued" && state.phase !== "waiting") return false;
6100
+ return state.wakeAt === void 0 || state.wakeAt <= now;
6101
+ }
6102
+ function next(state, changes) {
6103
+ const merged = {
6104
+ ...state,
6105
+ ...changes,
6106
+ revision: state.revision + 1
6107
+ };
6108
+ for (const key of Object.keys(merged)) if (merged[key] === void 0) delete merged[key];
6109
+ return Object.freeze(merged);
6110
+ }
6111
+ function isValidBackgroundSessionTransition(previous, nextState) {
6112
+ if (nextState.sessionId !== previous.sessionId) return "session id must not change";
6113
+ if (nextState.revision !== previous.revision + 1) return "revision must increase by exactly one";
6114
+ if (nextState.authority.agentId !== previous.authority.agentId) return "authority agent must not change";
6115
+ if (nextState.authority.profileRevision !== previous.authority.profileRevision) return "authority profile revision must not change";
6116
+ if (nextState.authority.toolGrantRevision !== previous.authority.toolGrantRevision) return "authority tool grant revision must not change";
6117
+ if (nextState.authority.sessionKey !== previous.authority.sessionKey) return "authority session key must not change";
6118
+ if (nextState.origin.endpointId !== previous.origin.endpointId) return "origin endpoint must not change";
6119
+ if (nextState.origin.tenantKey !== previous.origin.tenantKey) return "origin tenant must not change";
6120
+ if (nextState.origin.conversationId !== previous.origin.conversationId) return "origin conversation must not change";
6121
+ if (nextState.parentRunId !== previous.parentRunId) return "parent run must not change";
6122
+ if (nextState.sourceMessageId !== previous.sourceMessageId) return "source message must not change";
6123
+ if (nextState.prompt !== previous.prompt) return "prompt must not change";
6124
+ if (nextState.stepCount < previous.stepCount) return "step count must not decrease";
6125
+ if (nextState.wakeCount < previous.wakeCount) return "wake count must not decrease";
6126
+ if (nextState.consecutiveFailures < previous.consecutiveFailures) {
6127
+ if (previous.consecutiveFailures > 0 && nextState.phase === "completed" && nextState.consecutiveFailures === 0) return;
6128
+ return "failure count must not decrease";
6129
+ }
6130
+ if (nextState.createdAt !== previous.createdAt) return "created time must not change";
6131
+ if (previous.phase === "running") {
6132
+ if (nextState.phase === "running") return holdsSameLease(previous, nextState) ? void 0 : "running lease owner or epoch must not change";
6133
+ if (nextState.phase === "waiting" || nextState.phase === "input-required") return holdsSameLease(previous, nextState) ? void 0 : "suspension requires the same lease";
6134
+ if (nextState.phase === "completed" && nextState.result !== void 0 && nextState.lease === void 0) return;
6135
+ if (nextState.phase === "failed" && nextState.errorMessage !== void 0 && nextState.lease === void 0) return;
6136
+ if (nextState.phase === "stopping" && nextState.cancellation !== void 0) return void 0;
6137
+ if (nextState.phase === "reconciliation-required" && nextState.lease === void 0) return void 0;
6138
+ if (nextState.phase === "queued" && nextState.lease === void 0 && nextState.wakeAt !== void 0) return;
6139
+ return `running session cannot transition to ${nextState.phase}`;
6140
+ }
6141
+ if (previous.phase === "stopping") {
6142
+ if (nextState.phase === "stopped" && nextState.lease === void 0 && nextState.cancellation !== void 0) return;
6143
+ if (nextState.phase === "reconciliation-required" && nextState.lease === void 0) return void 0;
6144
+ return `stopping session cannot transition to ${nextState.phase}`;
6145
+ }
6146
+ if (previous.phase === "queued") {
6147
+ if (nextState.phase === "running" && nextState.lease !== void 0) return void 0;
6148
+ if (nextState.phase === "queued" && nextState.lease === void 0 && nextState.wakeAt === previous.wakeAt) return;
6149
+ if (nextState.phase === "stopped" && nextState.lease === void 0) return void 0;
6150
+ if (nextState.phase === "reconciliation-required" && nextState.lease === void 0) return void 0;
6151
+ return `queued session cannot transition to ${nextState.phase}`;
6152
+ }
6153
+ if (previous.phase === "waiting") {
6154
+ if (nextState.phase === "running" && nextState.lease !== void 0) return void 0;
6155
+ if (nextState.phase === "waiting" && nextState.lease === void 0 && nextState.wakeAt === previous.wakeAt) return;
6156
+ if (nextState.phase === "queued" && nextState.wakeAt !== void 0) return void 0;
6157
+ if (nextState.phase === "stopped" && nextState.lease === void 0) return void 0;
6158
+ if (nextState.phase === "reconciliation-required" && nextState.lease === void 0) return void 0;
6159
+ return `waiting session cannot transition to ${nextState.phase}`;
6160
+ }
6161
+ if (previous.phase === "input-required") {
6162
+ if (nextState.phase === "input-required" && nextState.lease === void 0) return void 0;
6163
+ if (nextState.phase === "queued" && nextState.wakeAt !== void 0) return void 0;
6164
+ if (nextState.phase === "stopped" && nextState.lease === void 0) return void 0;
6165
+ if (nextState.phase === "reconciliation-required" && nextState.lease === void 0) return void 0;
6166
+ return `input-required session cannot transition to ${nextState.phase}`;
6167
+ }
6168
+ if (isBackgroundSessionTerminalPhase(previous.phase)) {
6169
+ if (previous.phase === "reconciliation-required") {
6170
+ if (nextState.phase !== "queued" && nextState.phase !== "stopped") return "reconciliation-required session can only continue or stop";
6171
+ return;
6172
+ }
6173
+ return `terminal ${previous.phase} session cannot transition`;
6174
+ }
6175
+ }
6176
+ function holdsSameLease(previous, nextState) {
6177
+ return nextState.lease !== void 0 && previous.lease !== void 0 && nextState.lease.owner === previous.lease.owner && nextState.lease.epoch === previous.lease.epoch;
6178
+ }
6179
+ //#endregion
6180
+ //#region src/application/background-session/background-session-service.ts
6181
+ var BackgroundSessionCallerDenied = class extends Error {
6182
+ name = "BackgroundSessionCallerDenied";
6183
+ constructor(message) {
6184
+ super(message);
6185
+ }
6186
+ };
6187
+ function createBackgroundSessionService(options) {
6188
+ const serial = createSerialExecutor();
6189
+ const start = async (input) => {
6190
+ const now = options.clock.now();
6191
+ const origin = requireOrigin(input.context);
6192
+ const state = createBackgroundSession({
6193
+ authority: input.authority,
6194
+ displayName: input.displayName?.trim() || input.sessionId,
6195
+ now,
6196
+ origin: {
6197
+ allowedActorOpenIds: origin.allowedActorOpenIds,
6198
+ ...origin.conversationId === void 0 ? {} : { conversationId: origin.conversationId },
6199
+ endpointId: origin.endpointId,
6200
+ ...input.context.memory ? { memory: {
6201
+ audience: input.context.memory.audience,
6202
+ ...input.context.memory.conversationId ? { conversationId: input.context.memory.conversationId } : {},
6203
+ ...input.context.memory.projectId ? { projectId: input.context.memory.projectId } : {},
6204
+ subjectId: input.context.memory.subjectId,
6205
+ tenantId: input.context.memory.tenantId
6206
+ } } : {},
6207
+ tenantKey: origin.tenantKey
6208
+ },
6209
+ parentRunId: input.context.runId,
6210
+ prompt: input.prompt,
6211
+ sessionId: input.sessionId,
6212
+ sourceMessageId: requireSourceMessageId(input.context)
6213
+ });
6214
+ return toSummary(await options.repository.create(state));
6215
+ };
6216
+ const wait = async (input) => {
6217
+ const sessionId = sessionIdFromSessionKey(input.context.sessionKey);
6218
+ if (!sessionId) throw new BackgroundSessionCallerDenied("background.wait is only available inside a background session step");
6219
+ if (input.delayMs !== void 0 && input.until !== void 0) throw new BackgroundSessionCallerDenied("background.wait cannot combine delayMs and until");
6220
+ const now = options.clock.now();
6221
+ let wakeAt;
6222
+ if (input.delayMs !== void 0) {
6223
+ if (!Number.isSafeInteger(input.delayMs) || input.delayMs < 1) throw new BackgroundSessionCallerDenied("background.wait delayMs must be a positive integer");
6224
+ wakeAt = new Date(Date.parse(now) + input.delayMs).toISOString();
6225
+ } else if (input.until !== void 0) {
6226
+ const parsed = Date.parse(input.until);
6227
+ if (!Number.isFinite(parsed)) throw new BackgroundSessionCallerDenied("background.wait until must be an ISO 8601 timestamp");
6228
+ wakeAt = new Date(parsed).toISOString();
6229
+ }
6230
+ return toSummary(requireState(await serial.run(async () => {
6231
+ const state = await options.repository.get(sessionId);
6232
+ if (!state) throw new BackgroundSessionCallerDenied(`background session not found: ${sessionId}`);
6233
+ requireMatchingOrigin(state, input.context);
6234
+ const nextState = suspendBackgroundSession(state, {
6235
+ now,
6236
+ ...input.reason === void 0 ? {} : { reason: input.reason },
6237
+ ...wakeAt ? { wakeAt } : {}
6238
+ });
6239
+ return options.repository.update({
6240
+ build: () => nextState,
6241
+ expectedRevision: state.revision,
6242
+ sessionId
6243
+ });
6244
+ }), sessionId));
6245
+ };
6246
+ const list = async (input) => {
6247
+ return (await options.repository.list(input.phase === void 0 ? void 0 : { phase: input.phase })).filter((state) => matchesOrigin(state, input.context)).sort((left, right) => right.createdAt.localeCompare(left.createdAt)).slice(0, input.limit).map(toSummary);
6248
+ };
6249
+ const status = async (input) => {
6250
+ return toDetail(await requireOwnedState(input.sessionId, input.context));
6251
+ };
6252
+ const send = async (input) => {
6253
+ return toSummary(requireState(await serial.run(async () => {
6254
+ const state = await requireOwnedState(input.sessionId, input.context);
6255
+ const nextState = appendBackgroundSessionInput(state, {
6256
+ message: input.message,
6257
+ now: options.clock.now()
6258
+ });
6259
+ return options.repository.update({
6260
+ build: () => nextState,
6261
+ expectedRevision: state.revision,
6262
+ sessionId: input.sessionId
6263
+ });
6264
+ }), input.sessionId));
6265
+ };
6266
+ const stop = async (input) => {
6267
+ return toSummary(requireState(await serial.run(async () => {
6268
+ const state = await requireOwnedState(input.sessionId, input.context);
6269
+ const nextState = requestBackgroundSessionStop(state, {
6270
+ now: options.clock.now(),
6271
+ reason: input.reason ?? "stopped by conversation"
6272
+ });
6273
+ return updateAndEnqueueStopped(input.sessionId, state.revision, nextState);
6274
+ }), input.sessionId));
6275
+ };
6276
+ const requireOwnedState = async (sessionId, context) => {
6277
+ const state = await options.repository.get(sessionId);
6278
+ if (!state) throw new BackgroundSessionCallerDenied(`background session not found: ${sessionId}`);
6279
+ requireMatchingOrigin(state, context);
6280
+ return state;
6281
+ };
6282
+ const updateAndEnqueueStopped = async (sessionId, expectedRevision, nextState) => {
6283
+ const stored = await options.repository.update({
6284
+ build: () => nextState,
6285
+ expectedRevision,
6286
+ sessionId
6287
+ });
6288
+ if (stored?.phase === "stopped") await options.deliveries.enqueue({
6289
+ createdAt: options.clock.now(),
6290
+ deliveryId: terminalDeliveryId(sessionId, "stopped"),
6291
+ kind: "stopped",
6292
+ sessionId,
6293
+ text: stopNotice$1(stored)
6294
+ });
6295
+ return stored;
6296
+ };
6297
+ const resolveReconciliation = async (input) => {
6298
+ return toSummary(requireState(await serial.run(async () => {
6299
+ const state = await options.repository.get(input.sessionId);
6300
+ if (!state) throw new BackgroundSessionCallerDenied(`background session not found: ${input.sessionId}`);
6301
+ const nextState = resolveBackgroundSessionReconciliation(state, {
6302
+ now: options.clock.now(),
6303
+ outcome: input.outcome
6304
+ });
6305
+ return updateAndEnqueueStopped(input.sessionId, state.revision, nextState);
6306
+ }), input.sessionId));
6307
+ };
6308
+ return {
6309
+ list,
6310
+ resolveReconciliation,
6311
+ send,
6312
+ start,
6313
+ status,
6314
+ stop,
6315
+ wait
6316
+ };
6317
+ }
6318
+ function sessionIdFromSessionKey(sessionKey) {
6319
+ const prefix = `${createBackgroundSessionKey("")}`;
6320
+ return sessionKey.startsWith(prefix) ? sessionKey.slice(prefix.length) : void 0;
6321
+ }
6322
+ function terminalDeliveryId(sessionId, kind) {
6323
+ return `bg-final:${sessionId}:${kind}`;
6324
+ }
6325
+ function progressDeliveryId(sessionId, stepCount) {
6326
+ return `bg-progress:${sessionId}:${stepCount}`;
6327
+ }
6328
+ function requireOrigin(context) {
6329
+ if (!context.origin || !context.origin.endpointId || !context.origin.tenantKey) throw new BackgroundSessionCallerDenied("background tools require a trusted invocation origin; this run has none");
6330
+ return context.origin;
6331
+ }
6332
+ function requireSourceMessageId(context) {
6333
+ if (!context.sourceMessageId?.trim()) throw new BackgroundSessionCallerDenied("background.start requires a trusted source message id");
6334
+ return context.sourceMessageId;
6335
+ }
6336
+ function requireMatchingOrigin(state, context) {
6337
+ if (!matchesOrigin(state, context)) throw new BackgroundSessionCallerDenied("background session is not owned by this conversation");
6338
+ }
6339
+ function matchesOrigin(state, context) {
6340
+ const origin = context.origin;
6341
+ if (!origin) return false;
6342
+ if (context.agentId !== state.authority.agentId) return false;
6343
+ if (state.origin.endpointId !== origin.endpointId) return false;
6344
+ if (state.origin.tenantKey !== origin.tenantKey) return false;
6345
+ if ((state.origin.conversationId ?? void 0) !== (origin.conversationId ?? void 0)) return false;
6346
+ return true;
6347
+ }
6348
+ function requireState(state, sessionId) {
6349
+ if (!state) throw new BackgroundSessionCallerDenied(`background session not found: ${sessionId}`);
6350
+ return state;
6351
+ }
6352
+ function toSummary(state) {
6353
+ return {
6354
+ createdAt: state.createdAt,
6355
+ displayName: state.displayName,
6356
+ phase: state.phase,
6357
+ sessionId: state.sessionId,
6358
+ stepCount: state.stepCount,
6359
+ updatedAt: state.updatedAt,
6360
+ ...state.wakeAt ? { wakeAt: state.wakeAt } : {}
6361
+ };
6362
+ }
6363
+ function toDetail(state) {
6364
+ return {
6365
+ ...toSummary(state),
6366
+ ...state.cancellation ? { cancellationReason: state.cancellation.reason } : {},
6367
+ ...state.errorMessage ? { errorMessage: state.errorMessage } : {},
6368
+ parentRunId: state.parentRunId,
6369
+ pendingInput: state.pendingInput,
6370
+ ...state.reconciliationNote ? { reconciliationNote: state.reconciliationNote } : {},
6371
+ ...state.result ? { result: state.result } : {}
6372
+ };
6373
+ }
6374
+ function stopNotice$1(state) {
6375
+ return `后台会话「${state.displayName}」已停止。${state.cancellation ? `原因:${state.cancellation.reason}` : ""}`.trim();
6376
+ }
6377
+ //#endregion
6378
+ //#region src/application/background-session/background-session-repository.ts
6379
+ var BackgroundSessionRepositoryConflict = class extends Error {
6380
+ name = "BackgroundSessionRepositoryConflict";
6381
+ constructor(sessionId, message) {
6382
+ super(`${sessionId}: ${message}`);
6383
+ }
6384
+ };
6385
+ var BackgroundSessionRepositoryCorrupted = class extends Error {
6386
+ name = "BackgroundSessionRepositoryCorrupted";
6387
+ };
6388
+ function createBackgroundSessionRepository(options = {}) {
6389
+ const serial = createSerialExecutor();
6390
+ const states = /* @__PURE__ */ new Map();
6391
+ for (const state of options.initial ?? []) states.set(state.sessionId, structuredClone(state));
6392
+ const persist = async (state) => {
6393
+ if (options.persist) await options.persist(state);
6394
+ };
6395
+ return {
6396
+ create: (state) => serial.run(async () => {
6397
+ if (states.has(state.sessionId)) throw new BackgroundSessionRepositoryConflict(state.sessionId, "duplicate background session id");
6398
+ states.set(state.sessionId, structuredClone(state));
6399
+ await persist(state);
6400
+ return structuredClone(state);
6401
+ }),
6402
+ get: (sessionId) => serial.run(async () => {
6403
+ const state = states.get(sessionId);
6404
+ return state ? structuredClone(state) : void 0;
6405
+ }),
6406
+ list: (options) => serial.run(async () => {
6407
+ let results = [...states.values()];
6408
+ if (options?.phase !== void 0) results = results.filter((state) => state.phase === options.phase);
6409
+ results.sort((left, right) => left.createdAt.localeCompare(right.createdAt));
6410
+ if (options?.limit !== void 0) results = results.slice(0, options.limit);
6411
+ return results.map((state) => structuredClone(state));
6412
+ }),
6413
+ update: (input) => serial.run(async () => {
6414
+ const previous = states.get(input.sessionId);
6415
+ if (!previous) return void 0;
6416
+ if (previous.revision !== input.expectedRevision) throw new BackgroundSessionRepositoryConflict(input.sessionId, `revision conflict: expected ${input.expectedRevision}, found ${previous.revision}`);
6417
+ if (input.expectedLease !== void 0) {
6418
+ const leaseMismatch = leaseConflict(input.sessionId, previous.lease, input.expectedLease, input.now);
6419
+ if (leaseMismatch) throw new BackgroundSessionRepositoryConflict(input.sessionId, leaseMismatch);
6420
+ }
6421
+ const nextState = input.build(previous);
6422
+ const invalid = isValidBackgroundSessionTransition(previous, nextState);
6423
+ if (invalid) throw new BackgroundSessionRepositoryConflict(input.sessionId, `invalid transition: ${invalid}`);
6424
+ states.set(input.sessionId, structuredClone(nextState));
6425
+ await persist(nextState);
6426
+ return structuredClone(nextState);
6427
+ })
6428
+ };
6429
+ }
6430
+ function leaseConflict(_sessionId, lease, expected, now) {
6431
+ if (expected.kind === "absent") {
6432
+ if (lease !== void 0) return `lease conflict: expected no lease, found owner ${lease.owner} epoch ${lease.epoch}`;
6433
+ return;
6434
+ }
6435
+ if (expected.kind === "absent-or-stale") {
6436
+ if (lease !== void 0 && !isExpired(lease, now)) return `lease conflict: expected absent or stale lease, found live lease owner ${lease.owner} epoch ${lease.epoch}`;
6437
+ return;
6438
+ }
6439
+ if (lease === void 0 || lease.owner !== expected.owner || lease.epoch !== expected.epoch) return `lease conflict: expected owner ${expected.owner} epoch ${expected.epoch}`;
6440
+ }
6441
+ function isExpired(lease, now) {
6442
+ return lease !== void 0 && lease.expiresAt <= (now ?? (/* @__PURE__ */ new Date()).toISOString());
6443
+ }
6444
+ //#endregion
6445
+ //#region src/application/background-session/background-session-delivery-store.ts
6446
+ var BackgroundSessionDeliveryConflict = class extends Error {
6447
+ name = "BackgroundSessionDeliveryConflict";
6448
+ constructor(deliveryId, message) {
6449
+ super(`${deliveryId}: ${message}`);
6450
+ }
6451
+ };
6452
+ function createBackgroundSessionDeliveryStore(options = {}) {
6453
+ const serial = createSerialExecutor();
6454
+ const records = /* @__PURE__ */ new Map();
6455
+ for (const record of options.initial ?? []) records.set(record.deliveryId, structuredClone(record));
6456
+ const persist = async (record) => {
6457
+ if (options.persist) await options.persist(record);
6458
+ };
6459
+ return {
6460
+ enqueue: (input) => serial.run(async () => {
6461
+ const existing = records.get(input.deliveryId);
6462
+ if (existing) return structuredClone(existing);
6463
+ const record = {
6464
+ createdAt: input.createdAt,
6465
+ deliveryId: input.deliveryId,
6466
+ kind: input.kind,
6467
+ revision: 1,
6468
+ sessionId: input.sessionId,
6469
+ state: "pending",
6470
+ text: input.text
6471
+ };
6472
+ records.set(input.deliveryId, structuredClone(record));
6473
+ await persist(record);
6474
+ return structuredClone(record);
6475
+ }),
6476
+ pending: () => serial.run(async () => {
6477
+ return [...records.values()].filter((record) => record.state === "pending").sort((left, right) => left.createdAt.localeCompare(right.createdAt)).map((record) => structuredClone(record));
6478
+ }),
6479
+ markDelivered: (deliveryId, providerMessageId) => serial.run(async () => {
6480
+ const previous = records.get(deliveryId);
6481
+ if (!previous) return void 0;
6482
+ if (previous.state !== "pending") return structuredClone(previous);
6483
+ const nextState = {
6484
+ ...previous,
6485
+ providerMessageId,
6486
+ revision: previous.revision + 1,
6487
+ state: "delivered"
6488
+ };
6489
+ records.set(deliveryId, structuredClone(nextState));
6490
+ await persist(nextState);
6491
+ return structuredClone(nextState);
6492
+ })
6493
+ };
6494
+ }
6495
+ //#endregion
6496
+ //#region src/application/background-session/background-session-supervisor.ts
6497
+ function createBackgroundSessionSupervisor(options) {
6498
+ const owner = `supervisor:${randomUUID()}`;
6499
+ const inFlight = /* @__PURE__ */ new Map();
6500
+ const stepControllers = /* @__PURE__ */ new Map();
6501
+ const counters = {
6502
+ completed: 0,
6503
+ deliveriesDelivered: 0,
6504
+ failed: 0,
6505
+ started: 0,
6506
+ staleLeaseEventsDropped: 0,
6507
+ stopped: 0
6508
+ };
6509
+ let repositoryHealthy = true;
6510
+ let snapshot = emptyPhaseCounts();
6511
+ let oldestDueAt;
6512
+ const requeuedInPass = /* @__PURE__ */ new Set();
6513
+ const refreshSnapshot = async () => {
6514
+ const counts = {
6515
+ completed: 0,
6516
+ failed: 0,
6517
+ "input-required": 0,
6518
+ queued: 0,
6519
+ "reconciliation-required": 0,
6520
+ running: 0,
6521
+ stopped: 0,
6522
+ stopping: 0,
6523
+ waiting: 0
6524
+ };
6525
+ let oldest;
6526
+ const now = options.clock.now();
6527
+ for (const session of await options.repository.list()) {
6528
+ counts[session.phase] += 1;
6529
+ if (isBackgroundSessionDue(session, now)) {
6530
+ const dueAt = session.wakeAt ?? session.createdAt;
6531
+ if (oldest === void 0 || dueAt < oldest) oldest = dueAt;
6532
+ }
6533
+ }
6534
+ snapshot = Object.freeze(counts);
6535
+ oldestDueAt = oldest;
6536
+ };
6537
+ const supervisionPass = async () => {
6538
+ try {
6539
+ await resolveStaleLeases();
6540
+ await expireLifetime();
6541
+ await stopStoppingSessions();
6542
+ await drainDeliveries();
6543
+ await startDueSessions();
6544
+ await refreshSnapshot();
6545
+ repositoryHealthy = true;
6546
+ } catch (error) {
6547
+ repositoryHealthy = false;
6548
+ throw error;
6549
+ }
6550
+ };
6551
+ const resolveStaleLeases = async () => {
6552
+ const now = options.clock.now();
6553
+ for (const session of await options.repository.list()) {
6554
+ if (session.lease === void 0 || inFlight.has(session.sessionId)) continue;
6555
+ if (!(session.lease.owner !== owner || isBackgroundSessionLeaseExpired(session, now))) continue;
6556
+ counters.staleLeaseEventsDropped += 1;
6557
+ const expectedLease = {
6558
+ kind: "held",
6559
+ owner: session.lease.owner,
6560
+ epoch: session.lease.epoch
6561
+ };
6562
+ if (session.phase === "running") {
6563
+ await options.repository.update({
6564
+ build: (state) => requeueInterruptedBackgroundSessionStep(state, {
6565
+ now,
6566
+ wakeText: interruptedStepWakeText(state)
6567
+ }),
6568
+ expectedLease,
6569
+ expectedRevision: session.revision,
6570
+ sessionId: session.sessionId
6571
+ });
6572
+ requeuedInPass.add(session.sessionId);
6573
+ continue;
6574
+ }
6575
+ if (session.phase === "stopping") {
6576
+ await completeStop(session, expectedLease);
6577
+ continue;
6578
+ }
6579
+ await options.repository.update({
6580
+ build: (state) => releaseBackgroundSessionLease(state),
6581
+ expectedLease,
6582
+ expectedRevision: session.revision,
6583
+ sessionId: session.sessionId
6584
+ });
6585
+ }
6586
+ };
6587
+ const expireLifetime = async () => {
6588
+ const now = options.clock.now();
6589
+ const cutoff = Date.parse(now) - options.config.sessionLifetimeMs;
6590
+ for (const session of await options.repository.list()) {
6591
+ if (isBackgroundSessionTerminalPhase(session.phase)) continue;
6592
+ if (Date.parse(session.createdAt) > cutoff) continue;
6593
+ const nextState = requestBackgroundSessionStop(session, {
6594
+ now,
6595
+ reason: "background session lifetime exceeded"
6596
+ });
6597
+ const stored = await options.repository.update({
6598
+ build: () => nextState,
6599
+ expectedRevision: session.revision,
6600
+ sessionId: session.sessionId
6601
+ });
6602
+ if (stored?.phase === "stopped") {
6603
+ counters.stopped += 1;
6604
+ await enqueueDelivery(stored.sessionId, "stopped", stopNotice(stored), stored);
6605
+ } else stepControllers.get(session.sessionId)?.abort(/* @__PURE__ */ new Error("background session lifetime exceeded"));
6606
+ }
6607
+ };
6608
+ const stopStoppingSessions = async () => {
6609
+ for (const session of await options.repository.list()) {
6610
+ if (session.phase !== "stopping") continue;
6611
+ if (inFlight.has(session.sessionId)) {
6612
+ stepControllers.get(session.sessionId)?.abort(/* @__PURE__ */ new Error("background session stop requested"));
6613
+ continue;
6614
+ }
6615
+ const expectedLease = session.lease ? {
6616
+ kind: "held",
6617
+ owner: session.lease.owner,
6618
+ epoch: session.lease.epoch
6619
+ } : { kind: "absent" };
6620
+ await completeStop(session, expectedLease);
6621
+ }
6622
+ };
6623
+ const completeStop = async (state, expectedLease) => {
6624
+ const stopped = await options.repository.update({
6625
+ build: (current) => completeBackgroundSessionStop(current, { now: options.clock.now() }),
6626
+ expectedLease,
6627
+ expectedRevision: state.revision,
6628
+ sessionId: state.sessionId
6629
+ });
6630
+ if (stopped) {
6631
+ counters.stopped += 1;
6632
+ await enqueueDelivery(stopped.sessionId, "stopped", stopNotice(stopped), stopped);
6633
+ }
6634
+ };
6635
+ const startDueSessions = async () => {
6636
+ const now = options.clock.now();
6637
+ for (const session of await options.repository.list()) {
6638
+ if (inFlight.size >= options.config.maxConcurrentSessions) break;
6639
+ if (inFlight.has(session.sessionId)) continue;
6640
+ if (!isBackgroundSessionDue(session, now)) continue;
6641
+ if (session.lease !== void 0 && !isBackgroundSessionLeaseExpired(session, now)) continue;
6642
+ const step = runStep(session).finally(() => {
6643
+ inFlight.delete(session.sessionId);
6644
+ });
6645
+ inFlight.set(session.sessionId, step);
6646
+ step.catch((error) => {
6647
+ options.onError?.(error);
6648
+ });
6649
+ }
6650
+ };
6651
+ const runStep = async (session) => {
6652
+ const now = options.clock.now();
6653
+ const stepCount = session.stepCount + 1;
6654
+ const wakeText = requeuedInPass.has(session.sessionId) ? interruptedStepWakeText(session) : buildWakeText(session);
6655
+ requeuedInPass.delete(session.sessionId);
6656
+ const lease = {
6657
+ epoch: (session.lease?.epoch ?? 0) + 1,
6658
+ expiresAt: toIso(Date.parse(now) + options.config.leaseMs),
6659
+ owner
6660
+ };
6661
+ const claimed = await options.repository.update({
6662
+ build: (state) => claimBackgroundSession(state, {
6663
+ lease,
6664
+ now,
6665
+ stepRunId: `bg-step:${session.sessionId}:${stepCount}`,
6666
+ wakeText
6667
+ }),
6668
+ expectedLease: { kind: "absent-or-stale" },
6669
+ expectedRevision: session.revision,
6670
+ now,
6671
+ sessionId: session.sessionId
6672
+ });
6673
+ if (!claimed) return;
6674
+ counters.started += 1;
6675
+ const controller = new AbortController();
6676
+ stepControllers.set(session.sessionId, controller);
6677
+ let outcome;
6678
+ try {
6679
+ let settled = false;
6680
+ const renewal = (async () => {
6681
+ while (!settled) {
6682
+ await Effect.runPromise(options.sleep(options.config.leaseRenewalIntervalMs)).catch(() => void 0);
6683
+ if (settled) break;
6684
+ try {
6685
+ const current = await options.repository.get(session.sessionId);
6686
+ if (!current || current.lease === void 0 || current.lease.owner !== owner || current.lease.epoch !== lease.epoch) {
6687
+ controller.abort(/* @__PURE__ */ new Error("background session lease was lost"));
6688
+ break;
6689
+ }
6690
+ if (!await options.repository.update({
6691
+ build: (state) => renewBackgroundSessionLease(state, {
6692
+ expiresAt: toIso(Date.parse(options.clock.now()) + options.config.leaseMs),
6693
+ epoch: lease.epoch,
6694
+ owner
6695
+ }),
6696
+ expectedLease: {
6697
+ kind: "held",
6698
+ owner,
6699
+ epoch: lease.epoch
6700
+ },
6701
+ expectedRevision: current.revision,
6702
+ sessionId: session.sessionId
6703
+ })) controller.abort(/* @__PURE__ */ new Error("background session lease renewal was denied"));
6704
+ } catch {
6705
+ controller.abort(/* @__PURE__ */ new Error("background session lease renewal failed"));
6706
+ }
6707
+ }
6708
+ })();
6709
+ outcome = await options.runStep({
6710
+ session: claimed,
6711
+ signal: controller.signal,
6712
+ wakeText
6713
+ }).then((result) => ({
6714
+ ok: true,
6715
+ result
6716
+ }), (error) => ({
6717
+ error,
6718
+ ok: false
6719
+ }));
6720
+ settled = true;
6721
+ renewal.catch(() => void 0);
6722
+ } finally {
6723
+ stepControllers.delete(session.sessionId);
6724
+ }
6725
+ try {
6726
+ await commitStep(claimed, outcome, lease);
6727
+ } catch (error) {
6728
+ options.onError?.(error);
6729
+ await requeueAfterFailedCommit(session.sessionId, lease, error);
6730
+ }
6731
+ };
6732
+ const requeueAfterFailedCommit = async (sessionId, lease, error) => {
6733
+ try {
6734
+ const current = await options.repository.get(sessionId);
6735
+ if (!current || current.phase !== "running") return;
6736
+ await options.repository.update({
6737
+ build: (state) => requeueInterruptedBackgroundSessionStep(state, {
6738
+ now: options.clock.now(),
6739
+ wakeText: `步骤结果提交失败(${errorMessageOf(error)}),将重试`
6740
+ }),
6741
+ expectedLease: {
6742
+ kind: "held",
6743
+ owner: lease.owner,
6744
+ epoch: lease.epoch
6745
+ },
6746
+ expectedRevision: current.revision,
6747
+ sessionId
6748
+ });
6749
+ } catch (commitError) {
6750
+ options.onError?.(commitError);
6751
+ }
6752
+ };
6753
+ const commitStep = async (claimed, outcome, lease) => {
6754
+ const now = options.clock.now();
6755
+ const current = await options.repository.get(claimed.sessionId);
6756
+ if (!current) return;
6757
+ const expectedLease = {
6758
+ kind: "held",
6759
+ owner: lease.owner,
6760
+ epoch: lease.epoch
6761
+ };
6762
+ if (current.phase === "waiting" || current.phase === "input-required") {
6763
+ const text = outcome.ok ? outcome.result.finalText : "";
6764
+ await options.repository.update({
6765
+ build: (state) => releaseBackgroundSessionLease(state),
6766
+ expectedLease,
6767
+ expectedRevision: current.revision,
6768
+ sessionId: current.sessionId
6769
+ });
6770
+ if (text.trim() !== "") await enqueueDelivery(current.sessionId, "progress", text, current);
6771
+ return;
6772
+ }
6773
+ if (current.phase === "stopping") {
6774
+ await completeStop(current, expectedLease);
6775
+ return;
6776
+ }
6777
+ if (current.phase !== "running") return;
6778
+ if (outcome.ok) {
6779
+ const completed = await options.repository.update({
6780
+ build: (state) => completeBackgroundSessionStep(state, {
6781
+ now,
6782
+ stepRunId: outcome.result.runId,
6783
+ text: outcome.result.finalText
6784
+ }),
6785
+ expectedLease,
6786
+ expectedRevision: current.revision,
6787
+ sessionId: current.sessionId
6788
+ });
6789
+ if (completed) {
6790
+ counters.completed += 1;
6791
+ await enqueueDelivery(completed.sessionId, "final", completed.result?.text ?? "", completed);
6792
+ }
6793
+ return;
6794
+ }
6795
+ const errorMessage = errorMessageOf(outcome.error);
6796
+ if (isFencedOperationError(outcome.error)) {
6797
+ const parked = await options.repository.update({
6798
+ build: (state) => parkBackgroundSessionForReconciliation(state, {
6799
+ now,
6800
+ reason: `step failed on a fenced operation: ${errorMessage}`
6801
+ }),
6802
+ expectedLease,
6803
+ expectedRevision: current.revision,
6804
+ sessionId: current.sessionId
6805
+ });
6806
+ if (parked) await enqueueDelivery(parked.sessionId, "reconciliation", `后台会话「${parked.displayName}」需要人工对账:${parked.reconciliationNote ?? errorMessage}`, parked);
6807
+ return;
6808
+ }
6809
+ if (isRetryableStepError(outcome.error) && current.consecutiveFailures + 1 < options.config.maxConsecutiveFailures) {
6810
+ const backoff = options.config.retryBackoffMs * 2 ** current.consecutiveFailures;
6811
+ await options.repository.update({
6812
+ build: (state) => failBackgroundSessionStep(state, {
6813
+ errorMessage,
6814
+ now,
6815
+ retryable: true,
6816
+ wakeAt: toIso(Date.parse(now) + backoff)
6817
+ }),
6818
+ expectedLease,
6819
+ expectedRevision: current.revision,
6820
+ sessionId: current.sessionId
6821
+ });
6822
+ return;
6823
+ }
6824
+ const failed = await options.repository.update({
6825
+ build: (state) => failBackgroundSessionStep(state, {
6826
+ errorMessage,
6827
+ now,
6828
+ retryable: false
6829
+ }),
6830
+ expectedLease,
6831
+ expectedRevision: current.revision,
6832
+ sessionId: current.sessionId
6833
+ });
6834
+ if (failed) {
6835
+ counters.failed += 1;
6836
+ await enqueueDelivery(failed.sessionId, "failed", `后台会话「${failed.displayName}」失败:${failed.errorMessage ?? errorMessage}`, failed);
6837
+ }
6838
+ };
6839
+ const drainDeliveries = async () => {
6840
+ const pending = await options.deliveries.pending();
6841
+ for (const record of pending) try {
6842
+ const { providerMessageId } = await options.deliver(record);
6843
+ if (await options.deliveries.markDelivered(record.deliveryId, providerMessageId)) counters.deliveriesDelivered += 1;
6844
+ } catch (error) {
6845
+ options.onError?.(error);
6846
+ }
6847
+ };
6848
+ const enqueueDelivery = async (sessionId, kind, text, session) => {
6849
+ if (text.trim() === "") return;
6850
+ const deliveryId = kind === "progress" ? progressDeliveryId(sessionId, session.stepCount) : terminalDeliveryId(sessionId, kind);
6851
+ await options.deliveries.enqueue({
6852
+ createdAt: options.clock.now(),
6853
+ deliveryId,
6854
+ kind,
6855
+ sessionId,
6856
+ text
6857
+ });
6858
+ };
6859
+ const buildWakeText = (session) => {
6860
+ if (session.wakeCount === 0) return `你在一个后台会话中开始工作。任务:\n${session.prompt}\n\n继续工作直到给出最终结果;如果必须等待外部变化或用户输入,调用 background.wait。`;
6861
+ const parts = [`后台会话第 ${session.stepCount + 1} 步。任务:\n${session.prompt}`, "继续先前的工作(历史在会话记录中)。"];
6862
+ if (session.pendingInput.length > 0) parts.push(`用户新的输入:\n${session.pendingInput.join("\n---\n")}`);
6863
+ parts.push("完成后给出最终结果;需要等待时调用 background.wait。");
6864
+ return parts.join("\n\n");
6865
+ };
6866
+ const interruptedStepWakeText = (session) => `你的上一步在后台会话中被守护进程重启打断,未产生确定的工具副作用(副作用由工具账本保护)。继续先前的工作(历史在会话记录中)。` + (session.pendingInput.length > 0 ? `\n\n用户新的输入:\n${session.pendingInput.join("\n---\n")}` : "");
6867
+ const tick = () => Effect.promise(() => supervisionPass());
6868
+ const loop = createPeriodicEffectLoop({
6869
+ intervalMs: options.config.intervalMs,
6870
+ onError: (error) => {
6871
+ options.onError?.(error);
6872
+ },
6873
+ run: tick,
6874
+ sleep: options.sleep
6875
+ });
6876
+ const statusOf = () => Object.freeze({
6877
+ capacity: options.config.maxConcurrentSessions,
6878
+ counters: Object.freeze({ ...counters }),
6879
+ inFlightSteps: inFlight.size,
6880
+ ...oldestDueAt === void 0 ? {} : { oldestDueAt },
6881
+ owner,
6882
+ phaseCounts: snapshot,
6883
+ reconciliationCount: snapshot["reconciliation-required"],
6884
+ repositoryHealthy,
6885
+ running: loop.running()
6886
+ });
6887
+ return {
6888
+ recover: tick,
6889
+ start: () => Effect.sync(() => loop.start()),
6890
+ status: statusOf,
6891
+ stop: () => Effect.promise(async () => {
6892
+ for (const controller of stepControllers.values()) controller.abort(/* @__PURE__ */ new Error("background session supervisor is stopping"));
6893
+ await Promise.allSettled(inFlight.values());
6894
+ await loop.stop();
6895
+ }),
6896
+ tick
6897
+ };
6898
+ }
6899
+ function isFencedOperationError(error) {
6900
+ const message = errorMessageOf(error).toLowerCase();
6901
+ return message.includes("fenced") || message.includes("reconciliation-required");
6902
+ }
6903
+ function isRetryableStepError(error) {
6904
+ if (!(error instanceof Error)) return false;
6905
+ if (error.name === "AgentRunCancelled") return true;
6906
+ if (error.name === "AgentHarnessBusy" || error.name === "AgentInstanceBusy") return true;
6907
+ return false;
6908
+ }
6909
+ function errorMessageOf(error) {
6910
+ return error instanceof Error ? error.message : String(error);
6911
+ }
6912
+ function toIso(timeMs) {
6913
+ return new Date(timeMs).toISOString();
6914
+ }
6915
+ function stopNotice(session) {
6916
+ return `后台会话「${session.displayName}」已停止。${session.cancellation ? `原因:${session.cancellation.reason}` : ""}`.trim();
6917
+ }
6918
+ function emptyPhaseCounts() {
6919
+ return Object.freeze({
6920
+ completed: 0,
6921
+ failed: 0,
6922
+ "input-required": 0,
6923
+ queued: 0,
6924
+ "reconciliation-required": 0,
6925
+ running: 0,
6926
+ stopped: 0,
6927
+ stopping: 0,
6928
+ waiting: 0
6929
+ });
6930
+ }
6931
+ //#endregion
6932
+ //#region src/application/background-session/background-session-tools.ts
6933
+ function createBackgroundSessionHostTools(options) {
6934
+ const contracts = createBackgroundSessionToolContracts();
6935
+ const executors = new Map(contracts.map((contract) => [contract.id, createExecutor(contract, options)]));
6936
+ return contracts.map((contract) => Object.freeze({
6937
+ ...contract,
6938
+ createExecutor: () => ({ execute: (input, context) => asToolInputRejection$1(() => executors.get(contract.id)(input, context)) }),
6939
+ replayCompleted: (input, completedResult, context) => asToolInputRejection$1(() => replayCompleted(contract.id, input, completedResult, context, options))
6940
+ }));
6941
+ }
6942
+ function createExecutor(contract, options) {
6943
+ switch (contract.id) {
6944
+ case "background.start": return (input, context) => {
6945
+ const { prompt, displayName } = readObject(input, ["prompt", "displayName"]);
6946
+ if (typeof prompt !== "string" || prompt.trim() === "") throw new BackgroundSessionCallerDenied("background.start requires a non-empty prompt");
6947
+ if (displayName !== void 0 && typeof displayName !== "string") throw new BackgroundSessionCallerDenied("background.start displayName must be a string");
6948
+ const sessionId = options.createSessionId();
6949
+ return options.service.start({
6950
+ authority: buildAuthority(options.definition, context, sessionId),
6951
+ context,
6952
+ sessionId,
6953
+ ...displayName === void 0 ? {} : { displayName },
6954
+ prompt
6955
+ });
6956
+ };
6957
+ case "background.wait": return (input, context) => {
6958
+ const { delayMs, reason, until } = readObject(input, [
6959
+ "delayMs",
6960
+ "reason",
6961
+ "until"
6962
+ ]);
6963
+ return options.service.wait({
6964
+ context,
6965
+ ...delayMs === void 0 ? {} : { delayMs: readInteger(delayMs, "delayMs") },
6966
+ ...reason === void 0 ? {} : { reason: readString(reason, "reason") },
6967
+ ...until === void 0 ? {} : { until: readString(until, "until") }
6968
+ });
6969
+ };
6970
+ case "background.list": return async (input, context) => {
6971
+ const { limit, phase } = readObject(input, ["limit", "phase"]);
6972
+ return { sessions: await options.service.list({
6973
+ context,
6974
+ ...limit === void 0 ? {} : { limit: readInteger(limit, "limit") },
6975
+ ...phase === void 0 ? {} : { phase: readPhase(phase) }
6976
+ }) };
6977
+ };
6978
+ case "background.status": return (input, context) => {
6979
+ const { sessionId } = readObject(input, ["sessionId"]);
6980
+ return options.service.status({
6981
+ context,
6982
+ sessionId: readString(sessionId, "sessionId")
6983
+ });
6984
+ };
6985
+ case "background.send": return (input, context) => {
6986
+ const { message, sessionId } = readObject(input, ["message", "sessionId"]);
6987
+ return options.service.send({
6988
+ context,
6989
+ message: readString(message, "message"),
6990
+ sessionId: readString(sessionId, "sessionId")
6991
+ });
6992
+ };
6993
+ case "background.stop": return (input, context) => {
6994
+ const { reason, sessionId } = readObject(input, ["reason", "sessionId"]);
6995
+ return options.service.stop({
6996
+ context,
6997
+ ...reason === void 0 ? {} : { reason: readString(reason, "reason") },
6998
+ sessionId: readString(sessionId, "sessionId")
6999
+ });
7000
+ };
7001
+ default: throw new BackgroundSessionCallerDenied(`unknown background tool: ${contract.id}`);
7002
+ }
7003
+ }
7004
+ function replayCompleted(toolId, input, completedResult, context, options) {
7005
+ switch (toolId) {
7006
+ case "background.start": {
7007
+ const sessionId = readReplayedSessionId(completedResult);
7008
+ return options.service.status({
7009
+ context,
7010
+ sessionId
7011
+ });
7012
+ }
7013
+ case "background.wait": return completedResult;
7014
+ case "background.list": return completedResult;
7015
+ case "background.status": {
7016
+ const sessionId = readReplayedSessionId(input);
7017
+ return options.service.status({
7018
+ context,
7019
+ sessionId
7020
+ });
7021
+ }
7022
+ case "background.send": {
7023
+ const sessionId = readReplayedSessionId(input);
7024
+ return options.service.status({
7025
+ context,
7026
+ sessionId
7027
+ });
7028
+ }
7029
+ case "background.stop": {
7030
+ const sessionId = readReplayedSessionId(input);
7031
+ return options.service.status({
7032
+ context,
7033
+ sessionId
7034
+ });
7035
+ }
7036
+ default: return completedResult;
7037
+ }
7038
+ }
7039
+ function buildAuthority(definition, context, sessionId) {
7040
+ return Object.freeze({
7041
+ agentId: definition.agentId,
7042
+ memoryScopes: definition.memory.scopes,
7043
+ policyEpoch: context.policyEpoch,
7044
+ profileRevision: definition.profileRevision,
7045
+ ...definition.projectSpaceId === void 0 ? {} : { projectSpaceId: definition.projectSpaceId },
7046
+ sessionKey: createBackgroundSessionKey(sessionId),
7047
+ toolGrantRevision: definition.toolGrantSet.revision
7048
+ });
7049
+ }
7050
+ function readObject(input, allowed) {
7051
+ if (input === null || typeof input !== "object" || Array.isArray(input)) throw new BackgroundSessionCallerDenied("background tool input must be an object");
7052
+ const record = input;
7053
+ const unknown = Object.keys(record).find((key) => !allowed.includes(key));
7054
+ if (unknown) throw new BackgroundSessionCallerDenied(`field is not allowed: ${unknown}`);
7055
+ return record;
7056
+ }
7057
+ function readString(value, name) {
7058
+ if (typeof value !== "string" || value.trim() === "") throw new BackgroundSessionCallerDenied(`${name} must be a non-empty string`);
7059
+ return value;
7060
+ }
7061
+ function readInteger(value, name) {
7062
+ if (!Number.isSafeInteger(value) || value < 1) throw new BackgroundSessionCallerDenied(`${name} must be a positive integer`);
7063
+ return value;
7064
+ }
7065
+ function readPhase(value) {
7066
+ const phases = [
7067
+ "queued",
7068
+ "running",
7069
+ "waiting",
7070
+ "input-required",
7071
+ "stopping",
7072
+ "stopped",
7073
+ "completed",
7074
+ "failed",
7075
+ "reconciliation-required"
7076
+ ];
7077
+ if (typeof value !== "string" || !phases.includes(value)) throw new BackgroundSessionCallerDenied(`phase must be one of ${phases.join(", ")}`);
7078
+ return value;
7079
+ }
7080
+ function readReplayedSessionId(value) {
7081
+ if (value === null || typeof value !== "object" || Array.isArray(value)) throw new BackgroundSessionCallerDenied("replayed background tool result is invalid");
7082
+ return readString(value.sessionId, "sessionId");
7083
+ }
7084
+ async function asToolInputRejection$1(operation) {
7085
+ try {
7086
+ return await operation();
7087
+ } catch (error) {
7088
+ if (error instanceof BackgroundSessionCallerDenied || error instanceof BackgroundSessionTransitionDenied) throw new RivusToolInputRejected(error.message);
7089
+ throw error;
7090
+ }
7091
+ }
7092
+ //#endregion
7093
+ //#region src/infrastructure/persistence/jsonl-snapshot-store.ts
7094
+ var JsonlSnapshotStoreCorrupted = class extends Error {
7095
+ name = "JsonlSnapshotStoreCorrupted";
7096
+ };
7097
+ async function loadJsonlSnapshotStore(options) {
7098
+ const raw = await readPersistenceFile(options.filePath);
7099
+ if (raw === void 0) return [];
7100
+ const lines = raw.split("\n");
7101
+ const latest = /* @__PURE__ */ new Map();
7102
+ let lineCount = 0;
7103
+ for (let index = 0; index < lines.length; index += 1) {
7104
+ const line = lines[index] ?? "";
7105
+ if (!line.trim()) continue;
7106
+ lineCount += 1;
7107
+ let parsed;
7108
+ try {
7109
+ parsed = JSON.parse(line);
7110
+ } catch {
7111
+ if (index === lines.length - 1) {
7112
+ await truncateAtLine(options.filePath, lines, index);
7113
+ break;
7114
+ }
7115
+ throw new JsonlSnapshotStoreCorrupted(`${options.errorLabel} JSONL at line ${index + 1} is not valid JSON`);
7116
+ }
7117
+ if (!isRecord$4(parsed) || parsed.version !== options.version) throw new JsonlSnapshotStoreCorrupted(`unsupported ${options.errorLabel} version at line ${index + 1}`);
7118
+ if (isRecord$4(parsed.snapshot)) {
7119
+ if (!Array.isArray(parsed.snapshot.records)) throw new JsonlSnapshotStoreCorrupted(`invalid ${options.errorLabel} snapshot at line ${index + 1}`);
7120
+ latest.clear();
7121
+ for (const value of parsed.snapshot.records) {
7122
+ if (!options.isRecord(value)) throw new JsonlSnapshotStoreCorrupted(`invalid ${options.errorLabel} snapshot at line ${index + 1}`);
7123
+ latest.set(options.keyOf(value), structuredClone(value));
7124
+ }
7125
+ continue;
7126
+ }
7127
+ if (!options.isRecord(parsed.record)) throw new JsonlSnapshotStoreCorrupted(`invalid ${options.errorLabel} record at line ${index + 1}`);
7128
+ const record = parsed.record;
7129
+ const previous = latest.get(options.keyOf(record));
7130
+ const invalid = options.validateSequence(previous, record, index + 1);
7131
+ if (invalid) throw new JsonlSnapshotStoreCorrupted(`invalid ${options.errorLabel} ${invalid} at line ${index + 1}`);
7132
+ latest.set(options.keyOf(record), structuredClone(record));
7133
+ }
7134
+ if (lineCount >= options.compactThreshold) await writeJsonlSnapshot(options.filePath, options.version, [...latest.values()]);
7135
+ return [...latest.values()];
7136
+ }
7137
+ async function appendJsonlRecord(filePath, version, record) {
7138
+ await mkdir(dirname(filePath), { recursive: true });
7139
+ await appendFile(filePath, `${JSON.stringify({
7140
+ record,
7141
+ version
7142
+ })}\n`, "utf8");
7143
+ }
7144
+ async function writeJsonlSnapshot(filePath, version, records) {
7145
+ await mkdir(dirname(filePath), { recursive: true });
7146
+ await writeFile(filePath, `${JSON.stringify({
7147
+ snapshot: { records },
7148
+ version
7149
+ })}\n`, "utf8");
7150
+ }
7151
+ async function truncateAtLine(filePath, lines, lineIndex) {
7152
+ let offset = 0;
7153
+ for (let index = 0; index < lineIndex; index += 1) offset += (lines[index] ?? "").length + 1;
7154
+ await truncate(filePath, offset);
7155
+ }
7156
+ //#endregion
7157
+ //#region src/infrastructure/persistence/jsonl-background-session-repository.ts
7158
+ const BACKGROUND_SESSION_JSONL_VERSION = 1;
7159
+ async function openJsonlBackgroundSessionRepository(options) {
7160
+ return createBackgroundSessionRepository({
7161
+ initial: await loadJsonlSnapshotStore({
7162
+ compactThreshold: options.compactThreshold ?? 5e3,
7163
+ errorLabel: "background session",
7164
+ filePath: options.filePath,
7165
+ isRecord: isBackgroundSessionState,
7166
+ keyOf: (record) => record.sessionId,
7167
+ validateSequence: validateSessionSequence,
7168
+ version: 1
7169
+ }),
7170
+ persist: (record) => appendJsonlRecord(options.filePath, 1, record)
7171
+ });
7172
+ }
7173
+ function validateSessionSequence(previous, record, _lineNumber) {
7174
+ if (previous === void 0) {
7175
+ if (record.revision !== 1 || record.phase !== "queued") return "first record";
7176
+ return;
7177
+ }
7178
+ if (record.revision !== previous.revision + 1) return "revision";
7179
+ return isValidBackgroundSessionTransition(previous, record);
7180
+ }
7181
+ function isBackgroundSessionState(value) {
7182
+ if (!isRecord$4(value)) return false;
7183
+ const phases = [
7184
+ "queued",
7185
+ "running",
7186
+ "waiting",
7187
+ "input-required",
7188
+ "stopping",
7189
+ "stopped",
7190
+ "completed",
7191
+ "failed",
7192
+ "reconciliation-required"
7193
+ ];
7194
+ if (typeof value.sessionId !== "string" || value.sessionId.trim() === "") return false;
7195
+ if (typeof value.displayName !== "string") return false;
7196
+ if (!phases.includes(value.phase)) return false;
7197
+ if (!Number.isInteger(value.revision) || value.revision < 1) return false;
7198
+ if (typeof value.parentRunId !== "string" || value.parentRunId.trim() === "") return false;
7199
+ if (typeof value.sourceMessageId !== "string" || value.sourceMessageId.trim() === "") return false;
7200
+ if (!isRecord$4(value.origin)) return false;
7201
+ const origin = value.origin;
7202
+ if (typeof origin.endpointId !== "string" || origin.endpointId.trim() === "") return false;
7203
+ if (typeof origin.tenantKey !== "string") return false;
7204
+ if (!Array.isArray(origin.allowedActorOpenIds) || origin.allowedActorOpenIds.some((id) => typeof id !== "string")) return false;
7205
+ if (origin.conversationId !== void 0 && typeof origin.conversationId !== "string") return false;
7206
+ if (origin.memory !== void 0 && !isRecord$4(origin.memory)) return false;
7207
+ if (!isRecord$4(value.authority)) return false;
7208
+ const authority = value.authority;
7209
+ if (typeof authority.agentId !== "string" || authority.agentId.trim() === "") return false;
7210
+ if (typeof authority.profileRevision !== "string" || authority.profileRevision.trim() === "") return false;
7211
+ if (typeof authority.toolGrantRevision !== "string" || authority.toolGrantRevision.trim() === "") return false;
7212
+ if (!Number.isInteger(authority.policyEpoch) || authority.policyEpoch < 0) return false;
7213
+ if (!Array.isArray(authority.memoryScopes) || authority.memoryScopes.some((scope) => typeof scope !== "string")) return false;
7214
+ if (typeof authority.sessionKey !== "string" || authority.sessionKey.trim() === "") return false;
7215
+ if (authority.projectSpaceId !== void 0 && typeof authority.projectSpaceId !== "string") return false;
7216
+ if (typeof value.prompt !== "string") return false;
7217
+ if (!Number.isInteger(value.stepCount) || value.stepCount < 0) return false;
7218
+ if (!Number.isInteger(value.wakeCount) || value.wakeCount < 0) return false;
7219
+ if (!Number.isInteger(value.consecutiveFailures) || value.consecutiveFailures < 0) return false;
7220
+ if (!Array.isArray(value.pendingInput) || value.pendingInput.some((entry) => typeof entry !== "string")) return false;
7221
+ if (value.currentStepRunId !== void 0 && typeof value.currentStepRunId !== "string") return false;
7222
+ if (value.lastWakeText !== void 0 && typeof value.lastWakeText !== "string") return false;
7223
+ if (value.wakeAt !== void 0 && typeof value.wakeAt !== "string") return false;
7224
+ if (value.errorMessage !== void 0 && typeof value.errorMessage !== "string") return false;
7225
+ if (value.reconciliationNote !== void 0 && typeof value.reconciliationNote !== "string") return false;
7226
+ if (typeof value.createdAt !== "string" || !isIso(value.createdAt)) return false;
7227
+ if (typeof value.updatedAt !== "string" || !isIso(value.updatedAt)) return false;
7228
+ if (value.lease !== void 0 && !isLease(value.lease)) return false;
7229
+ if (value.cancellation !== void 0) {
7230
+ if (!isRecord$4(value.cancellation)) return false;
7231
+ if (typeof value.cancellation.reason !== "string" || !isIso(value.cancellation.requestedAt)) return false;
7232
+ }
7233
+ if (value.result !== void 0) {
7234
+ if (!isRecord$4(value.result)) return false;
7235
+ if (typeof value.result.text !== "string" || typeof value.result.stepRunId !== "string" || !isIso(value.result.completedAt)) return false;
7236
+ }
7237
+ return true;
7238
+ }
7239
+ function isLease(value) {
7240
+ if (!isRecord$4(value)) return false;
7241
+ return typeof value.owner === "string" && value.owner.trim() !== "" && Number.isInteger(value.epoch) && value.epoch >= 0 && isIso(value.expiresAt);
7242
+ }
7243
+ function isIso(value) {
7244
+ return typeof value === "string" && Number.isFinite(Date.parse(value));
7245
+ }
7246
+ //#endregion
7247
+ //#region src/infrastructure/persistence/jsonl-background-session-delivery-store.ts
7248
+ const BACKGROUND_SESSION_DELIVERY_JSONL_VERSION = 1;
7249
+ async function openJsonlBackgroundSessionDeliveryStore(options) {
7250
+ return createBackgroundSessionDeliveryStore({
7251
+ initial: await loadJsonlSnapshotStore({
7252
+ compactThreshold: options.compactThreshold ?? 2e3,
7253
+ errorLabel: "background session delivery",
7254
+ filePath: options.filePath,
7255
+ isRecord: isDeliveryRecord,
7256
+ keyOf: (record) => record.deliveryId,
7257
+ validateSequence: validateDeliverySequence,
7258
+ version: 1
7259
+ }),
7260
+ persist: (record) => appendJsonlRecord(options.filePath, 1, record)
7261
+ });
7262
+ }
7263
+ function validateDeliverySequence(previous, record, _lineNumber) {
7264
+ if (previous === void 0) return record.revision === 1 && record.state === "pending" ? void 0 : "first record";
7265
+ if (record.revision !== previous.revision + 1) return "revision";
7266
+ return previous.state === "pending" && record.state === "delivered" ? void 0 : "transition";
7267
+ }
7268
+ function isDeliveryRecord(value) {
7269
+ if (!isRecord$4(value)) return false;
7270
+ if (typeof value.deliveryId !== "string" || value.deliveryId.trim() === "" || typeof value.sessionId !== "string" || value.sessionId.trim() === "") return false;
7271
+ if (typeof value.kind !== "string" || ![
7272
+ "progress",
7273
+ "final",
7274
+ "stopped",
7275
+ "failed",
7276
+ "reconciliation"
7277
+ ].includes(value.kind)) return false;
7278
+ if (typeof value.text !== "string") return false;
7279
+ if (value.state !== "pending" && value.state !== "delivered") return false;
7280
+ if (!Number.isInteger(value.revision) || value.revision < 1) return false;
7281
+ if (value.providerMessageId !== void 0 && typeof value.providerMessageId !== "string") return false;
7282
+ return typeof value.createdAt === "string" && Number.isFinite(Date.parse(value.createdAt));
7283
+ }
7284
+ //#endregion
7285
+ //#region src/infrastructure/feishu/feishu-interactive-card-send.ts
7286
+ function sendFeishuInteractiveCard(client, request, errorMessage) {
7287
+ return Effect.gen(function* () {
7288
+ const response = yield* client.request(request, errorMessage);
7289
+ const providerMessageId = readMessageId(response.body.data);
7290
+ if (!providerMessageId) return yield* Effect.fail(new FeishuOpenApiError(response.status, response.body.code, "Feishu send response missing message_id"));
7291
+ return Object.freeze({ providerMessageId });
7292
+ });
7293
+ }
7294
+ function readMessageId(data) {
7295
+ if (data === null || typeof data !== "object" || Array.isArray(data)) return void 0;
7296
+ const value = data.message_id;
7297
+ return typeof value === "string" && value.trim() !== "" ? value : void 0;
7298
+ }
7299
+ //#endregion
7300
+ //#region src/infrastructure/feishu/feishu-background-session-delivery.ts
7301
+ function createConfiguredFeishuBackgroundSessionDelivery(options) {
7302
+ const baseUrl = options.config.feishu.baseUrl.replace(/\/$/, "");
7303
+ return { deliver: (input) => Effect.runPromise(sendFeishuInteractiveCard(options.client, {
7304
+ body: {
7305
+ content: JSON.stringify(createBackgroundSessionCard(input)),
7306
+ msg_type: "interactive",
7307
+ receive_id: input.chatId,
7308
+ uuid: deliveryUuid$1(input.deliveryId)
7309
+ },
7310
+ method: "POST",
7311
+ url: `${baseUrl}/open-apis/im/v1/messages?receive_id_type=chat_id`
7312
+ }, "Feishu background session delivery failed")) };
7313
+ }
7314
+ function createBackgroundSessionCard(input) {
7315
+ const title = cardTitle(input.kind);
7316
+ const headerTemplate = cardHeaderTemplate(input.kind);
7317
+ return {
7318
+ body: { elements: [
7319
+ {
7320
+ content: `**${escapeCardText(title)}** · ${escapeCardText(input.displayName)}`,
7321
+ tag: "markdown"
7322
+ },
7323
+ {
7324
+ content: input.text,
7325
+ tag: "markdown"
7326
+ },
7327
+ {
7328
+ content: `会话 ${escapeCardText(input.sessionId)} · _由 Rivus 后台会话生成_`,
7329
+ tag: "markdown"
7330
+ }
7331
+ ] },
7332
+ config: { update_multi: true },
7333
+ header: {
7334
+ template: headerTemplate,
7335
+ title: {
7336
+ content: title,
7337
+ tag: "plain_text"
7338
+ }
7339
+ },
7340
+ schema: "2.0"
7341
+ };
7342
+ }
7343
+ function cardTitle(kind) {
7344
+ switch (kind) {
7345
+ case "progress": return "后台会话进展";
7346
+ case "final": return "后台会话完成";
7347
+ case "failed": return "后台会话失败";
7348
+ case "stopped": return "后台会话已停止";
7349
+ case "reconciliation": return "后台会话需对账";
7350
+ }
7351
+ }
7352
+ function cardHeaderTemplate(kind) {
7353
+ switch (kind) {
7354
+ case "final": return "green";
7355
+ case "failed":
7356
+ case "reconciliation": return "red";
7357
+ case "stopped": return "orange";
7358
+ case "progress": return "blue";
7359
+ }
7360
+ }
7361
+ function escapeCardText(value) {
7362
+ return value.replace(/([*_~`|<>])/g, "\\$1");
7363
+ }
7364
+ function deliveryUuid$1(deliveryId) {
7365
+ return `rivus-${createHash("sha256").update(`background-session:${deliveryId}`).digest("hex").slice(0, 32)}`;
7366
+ }
7367
+ //#endregion
5884
7368
  //#region src/application/memory/rivus-memory-tool.ts
5885
7369
  function createRivusMemoryTool(memory) {
5886
7370
  const handles = Array.isArray(memory) ? [...memory] : [memory];
@@ -7051,21 +8535,16 @@ function createConfiguredFeishuTextReplySender(options) {
7051
8535
  //#region src/infrastructure/feishu/feishu-automation-card-sender.ts
7052
8536
  function createConfiguredFeishuAutomationCardSender(options) {
7053
8537
  const baseUrl = options.config.feishu.baseUrl.replace(/\/$/, "");
7054
- return { send: (input) => Effect.gen(function* () {
7055
- const response = yield* options.client.request({
7056
- body: {
7057
- content: JSON.stringify(createAutomationCard(input.markdown)),
7058
- msg_type: "interactive",
7059
- receive_id: input.receiveId,
7060
- uuid: deliveryUuid(input.idempotencyKey)
7061
- },
7062
- method: "POST",
7063
- url: `${baseUrl}/open-apis/im/v1/messages?receive_id_type=${encodeURIComponent(input.receiveIdType)}`
7064
- }, "Feishu send failed");
7065
- const providerMessageId = readMessageId(response.body.data);
7066
- if (!providerMessageId) return yield* Effect.fail(new FeishuOpenApiError(response.status, response.body.code, "Feishu send response missing message_id"));
7067
- return Object.freeze({ providerMessageId });
7068
- }) };
8538
+ return { send: (input) => sendFeishuInteractiveCard(options.client, {
8539
+ body: {
8540
+ content: JSON.stringify(createAutomationCard(input.markdown)),
8541
+ msg_type: "interactive",
8542
+ receive_id: input.receiveId,
8543
+ uuid: deliveryUuid(input.idempotencyKey)
8544
+ },
8545
+ method: "POST",
8546
+ url: `${baseUrl}/open-apis/im/v1/messages?receive_id_type=${encodeURIComponent(input.receiveIdType)}`
8547
+ }, "Feishu send failed") };
7069
8548
  }
7070
8549
  function createAutomationCard(markdown) {
7071
8550
  const presentation = splitPresentation(markdown);
@@ -7104,11 +8583,6 @@ function splitPresentation(markdown) {
7104
8583
  function deliveryUuid(idempotencyKey) {
7105
8584
  return `rivus-${createHash("sha256").update(idempotencyKey).digest("hex").slice(0, 32)}`;
7106
8585
  }
7107
- function readMessageId(data) {
7108
- if (data === null || typeof data !== "object" || Array.isArray(data)) return void 0;
7109
- const value = data.message_id;
7110
- return typeof value === "string" && value.trim() !== "" ? value : void 0;
7111
- }
7112
8586
  //#endregion
7113
8587
  //#region src/application/interaction/human-interaction-repository.ts
7114
8588
  var HumanInteractionRepositoryError = class extends Error {
@@ -7462,4 +8936,4 @@ function validateDecisionInput(input) {
7462
8936
  if (input.recommendedOptionId && !optionIds.includes(input.recommendedOptionId)) throw new Error("recommended user decision option must be available");
7463
8937
  }
7464
8938
  //#endregion
7465
- export { AgentContextBudgetExceeded, AgentEventHandlerFailed, AgentEventLogStoreError, AgentEventSinkFailed, AgentHarnessBusy, AgentInstanceBusy, AgentInstanceConflict, AgentLoopFailed, AgentMemoryError, AgentRunCancelled, AgentRuntimeDisposed, AutomationMandateError, CardPresentationTransitionDenied, CompactionError, DEFAULT_CARD_STREAM_LEASE_MS, DelegationDenied, DeliveryOutboxError, FeishuCardPresentationNotFound, FeishuCardTargetNotFound, FeishuCardTargetRegistryStoreError, FeishuCotProtocolError, FeishuEndpointCredentialError, FeishuOpenApiError, FeishuTenantAccessTokenError, HumanInteractionRepositoryError, HumanInteractionTransitionDenied, InvalidFeishuCardAction, InvalidFeishuMessageContent, InvalidFeishuSessionReference, InvalidInvocationAuthority, InvalidProjectSkillCatalog, InvalidRecoveryAction, InvalidRivusEndpointBinding, InvalidRivusPlugin, InvalidRivusProjectSpace, InvalidStableJson, InvalidToolInput, InvalidWorkspaceRoot, LangfuseTelemetryConfigError, MEMORY_SCOPES, OpenClawEnvImportError, PluginStateConflict, RIVUS_MEMORY_TOOL_ID, RIVUS_MEMORY_TOOL_PLUGIN_ID, RIVUS_MEMORY_TOOL_VERSION, RIVUS_PLUGIN_API_VERSION, RivusDaemonConfigError, RivusDeploymentAutomationReadinessError, RivusDeploymentDaemonLifecycleError, RivusDeploymentManifestError, RivusDeploymentReadinessError, RivusPluginConformanceError, RivusPluginLoadError, RivusToolInputRejected, SessionSchedulerCapacityExceeded, SessionSchedulerDisposed, ToolInvocationDenied, UnsupportedFeishuCardAction, UnsupportedFeishuMessage, WorkspaceInstructionsSourceError, acceptsCardPresentationProgress, activeCardPresentation, assembleAgentContext, assertRivusPluginConforms, commitAutomationOutcome, createAgentCommandFromFeishuCardAction, createAgentCommandFromFeishuMessage, createAgentConversationMessages, createAgentDomainEventHandler, createAgentDomainEventSink, createAgentDomainEventSinkFromCallback, createAgentHarness, createAgentHarnessClient, createAgentHarnessPooledRuntime, createAgentInstanceRegistry, createAgentLoopFromCallback, createAgentLoopModelExecutionEnd, createAgentLoopModelExecutionStart, createAgentLoopPromptTransformer, createAgentLoopSkillExecutionEnd, createAgentLoopSkillExecutionStart, createAgentLoopTextDelta, createAgentLoopThinkingDelta, createAgentLoopToolExecutionEnd, createAgentLoopToolExecutionStart, createAgentLoopToolExecutionUpdate, createAgentMemoryService, createAgentRunUpdateHandler, createAgentRuntime, createAgentRuntimePool, createAgentTranscriptMessages, createAgentTranscriptTurn, createAgentsMdInstructionsProvider, createAsyncIterableAgentLoop, createAutomationMandateStore, createCoalescingFeishuPublisher, createCompactionService, createCompositeRivusDaemonTransport, createConfiguredFeishuAutomationCardSender, createConfiguredFeishuCardKitPublisher, createConfiguredFeishuCardKitTargetCreator, createConfiguredFeishuCardRolloverRuntime, createConfiguredFeishuHumanInteractionPresenter, createConfiguredFeishuOpenApiClient, createConfiguredFeishuTextReplySender, createConfiguredRivusDaemonBootstrap, createConfiguredRivusDeploymentDaemon, createDailyAutomationSchedule, createDefaultAgentHarness, createDefaultAgentHarnessClient, createDefaultAgentHarnessClientFromCallback, createDefaultAgentHarnessClientFromTextCallback, createDefaultAgentHarnessFromCallback, createDefaultAgentHarnessFromTextCallback, createDefaultAgentRuntime, createDefaultAgentRuntimeFromCallback, createDefaultAgentRuntimeFromTextCallback, createDelegationService, createDeliveryOutbox, createEventAgentLoop, createFakeRivusPlugin, createFeishuAgentDaemon, createFeishuAgentRunCard, createFeishuAgentRuntime, createFeishuCardActionCallbackResponse, createFeishuCardActionErrorResponse, createFeishuCardDeliveryLedger, createFeishuCardDeliveryReconciler, createFeishuCardKitOpenApiClient, createFeishuCardKitOpenApiTargetCreator, createFeishuCardKitPublisher, createFeishuCardPresentationStore, createFeishuCardRollover, createFeishuCardRolloverSupervisor, createFeishuCardTargetPreparation, createFeishuConversationId, createFeishuCotPublisher, createFeishuDeploymentEndpoint, createFeishuEventHandlers, createFeishuHumanInteractionCard, createFeishuHumanInteractionPresenter, createFeishuInboxRepository, createFeishuMessageQueue, createFeishuMessageWorker, createFeishuOpenApiClient, createFeishuPeriodicFlush, createFeishuPresentationPreparation, createFeishuSessionKey, createFeishuStreamProjector, createFeishuTenantAccessTokenProvider, createFeishuWebSocketDaemon, createFeishuWorkerLoop, createFixedClock, createHumanInteractionEndpointRegistry, createHumanInteractionService, createHumanInteractionToolApprovalGateway, createInMemoryFeishuCardTargetRegistry, createInMemoryHumanInteractionRepository, createInvocationAuthority, createJsonFetchRequest, createJsonFileFeishuCardTargetRegistry, createJsonlAgentEventLog, createJsonlHumanInteractionRepository, createLangfuseAgentTelemetry, createLazyFeishuWebSocketEventDispatcher, createMemoryNamespace, createOpenTelemetryAgentEventSink, createOpenTelemetryAgentTelemetry, createPiAgentLoop, createPiSdkAgentLoop, createPiSessionRegistry, createPluginStateStore, createProjectMemoryPromptPreparer, createRateLimitedFeishuPublisher, createRecoveryAction, createRecoveryControl, createRivusAgentHost, createRivusDaemonProcess, createRivusDaemonShutdownController, createRivusDaemonStatusHttpServer, createRivusDaemonStatusReporter, createRivusDeploymentCliProcess, createRivusDeploymentDaemon, createRivusEnvFromOpenClawConfig, createRivusMemoryTool, createRivusMemoryToolContract, createRivusMemoryToolDescriptor, createRivusPluginCatalog, createRoutedHumanInteractionToolApprovalService, createScheduledAutomation, createSequenceRunIds, createSessionScheduler, createSubagentCoordinator, createSystemClock, createTelemetryContentRedactor, createTestClock, createTextAgentLoop, createTextAgentLoopFromCallback, createToolBroker, createToolInputDigest, createToolOperationLedger, createUuidRunIds, createWorkspaceRootHandle, describeFeishuMessageIntake, evolveAgentRun, formatRivusEnvFile, initialAgentRunState, intersectToolIds, isAgentToolExecutionEvent, isAssistantTextDeltaEvent, isAssistantThinkingDeltaEvent, isCardPresentationHandoffDue, isTerminalAgentDomainEvent, isTerminalAgentRunPhase, loadNodeRivusPluginModule, loadRivusDaemonConfig, loadRivusDeployment, loadRivusDeploymentManifest, normalizeStableJson, openJsonAutomationTickRepository, openJsonlAgentMemoryService, openJsonlFeishuCardDeliveryLedger, openJsonlFeishuInboxRepository, openJsonlRecoveryControl, openJsonlToolOperationLedger, replayAgentHistory, replayAgentTranscript, requiresToolApproval, resolveFeishuEndpointCredentials, resolveLangfuseTelemetryConfig, resolveRivusAgentDefinition, resolveRivusProjectSpace, restoreAgentHistory, restoreConfiguredRivusDaemonBootstrap, restrictMemoryScopesForAudience, runRivusDaemonCli, shouldAcceptFeishuEndpointMessage, transitionHumanInteraction, validateProjectSkillCatalog, validateProjectSkillCommand, validateRivusDeploymentManifest };
8939
+ export { AgentContextBudgetExceeded, AgentEventHandlerFailed, AgentEventLogStoreError, AgentEventSinkFailed, AgentHarnessBusy, AgentInstanceBusy, AgentInstanceConflict, AgentLoopFailed, AgentMemoryError, AgentRunCancelled, AgentRuntimeDisposed, AutomationMandateError, BACKGROUND_SESSION_DELIVERY_JSONL_VERSION, BACKGROUND_SESSION_JSONL_VERSION, BACKGROUND_SESSION_SESSION_KEY_PREFIX, BACKGROUND_SESSION_START_TOOL_ID, BACKGROUND_SESSION_TOOL_IDS, BACKGROUND_SESSION_TOOL_PLUGIN_ID, BACKGROUND_SESSION_TOOL_VERSION, BackgroundSessionCallerDenied, BackgroundSessionDeliveryConflict, BackgroundSessionRepositoryConflict, BackgroundSessionRepositoryCorrupted, BackgroundSessionTransitionDenied, CardPresentationTransitionDenied, CompactionError, DEFAULT_BACKGROUND_SESSION_LEASE_MS, DEFAULT_BACKGROUND_SESSION_LEASE_RENEWAL_INTERVAL_MS, DEFAULT_BACKGROUND_SESSION_LIFETIME_MS, DEFAULT_BACKGROUND_SESSION_MAX_CONCURRENT_SESSIONS, DEFAULT_BACKGROUND_SESSION_MAX_CONSECUTIVE_FAILURES, DEFAULT_BACKGROUND_SESSION_RETRY_BACKOFF_MS, DEFAULT_BACKGROUND_SESSION_STEP_TIMEOUT_MS, DEFAULT_BACKGROUND_SESSION_SUPERVISOR_INTERVAL_MS, DEFAULT_CARD_STREAM_LEASE_MS, DelegationDenied, DeliveryOutboxError, FeishuCardPresentationNotFound, FeishuCardTargetNotFound, FeishuCardTargetRegistryStoreError, FeishuCotProtocolError, FeishuEndpointCredentialError, FeishuOpenApiError, FeishuTenantAccessTokenError, HumanInteractionRepositoryError, HumanInteractionTransitionDenied, InvalidFeishuCardAction, InvalidFeishuMessageContent, InvalidFeishuSessionReference, InvalidInvocationAuthority, InvalidProjectSkillCatalog, InvalidRecoveryAction, InvalidRivusEndpointBinding, InvalidRivusPlugin, InvalidRivusProjectSpace, InvalidStableJson, InvalidToolInput, InvalidWorkspaceRoot, LangfuseTelemetryConfigError, MEMORY_SCOPES, OpenClawEnvImportError, PluginStateConflict, RIVUS_MEMORY_TOOL_ID, RIVUS_MEMORY_TOOL_PLUGIN_ID, RIVUS_MEMORY_TOOL_VERSION, RIVUS_PLUGIN_API_VERSION, RivusDaemonConfigError, RivusDeploymentAutomationReadinessError, RivusDeploymentDaemonLifecycleError, RivusDeploymentManifestError, RivusDeploymentReadinessError, RivusPluginConformanceError, RivusPluginLoadError, RivusToolInputRejected, SessionSchedulerCapacityExceeded, SessionSchedulerDisposed, ToolInvocationDenied, UnsupportedFeishuCardAction, UnsupportedFeishuMessage, WorkspaceInstructionsSourceError, acceptsCardPresentationProgress, activeCardPresentation, appendBackgroundSessionInput, assembleAgentContext, assertRivusPluginConforms, backgroundSessionToolIds, claimBackgroundSession, commitAutomationOutcome, completeBackgroundSessionStep, completeBackgroundSessionStop, createAgentCommandFromFeishuCardAction, createAgentCommandFromFeishuMessage, createAgentConversationMessages, createAgentDomainEventHandler, createAgentDomainEventSink, createAgentDomainEventSinkFromCallback, createAgentHarness, createAgentHarnessClient, createAgentHarnessPooledRuntime, createAgentInstanceRegistry, createAgentLoopFromCallback, createAgentLoopModelExecutionEnd, createAgentLoopModelExecutionStart, createAgentLoopPromptTransformer, createAgentLoopSkillExecutionEnd, createAgentLoopSkillExecutionStart, createAgentLoopTextDelta, createAgentLoopThinkingDelta, createAgentLoopToolExecutionEnd, createAgentLoopToolExecutionStart, createAgentLoopToolExecutionUpdate, createAgentMemoryService, createAgentRunUpdateHandler, createAgentRuntime, createAgentRuntimePool, createAgentTranscriptMessages, createAgentTranscriptTurn, createAgentsMdInstructionsProvider, createAsyncIterableAgentLoop, createAutomationMandateStore, createBackgroundSession, createBackgroundSessionCard, createBackgroundSessionDeliveryStore, createBackgroundSessionHostTools, createBackgroundSessionKey, createBackgroundSessionRepository, createBackgroundSessionService, createBackgroundSessionStepSourceMessageId, createBackgroundSessionSupervisor, createBackgroundSessionToolContracts, createCoalescingFeishuPublisher, createCompactionService, createCompositeRivusDaemonTransport, createConfiguredFeishuAutomationCardSender, createConfiguredFeishuBackgroundSessionDelivery, createConfiguredFeishuCardKitPublisher, createConfiguredFeishuCardKitTargetCreator, createConfiguredFeishuCardRolloverRuntime, createConfiguredFeishuHumanInteractionPresenter, createConfiguredFeishuOpenApiClient, createConfiguredFeishuTextReplySender, createConfiguredRivusDaemonBootstrap, createConfiguredRivusDeploymentDaemon, createDailyAutomationSchedule, createDefaultAgentHarness, createDefaultAgentHarnessClient, createDefaultAgentHarnessClientFromCallback, createDefaultAgentHarnessClientFromTextCallback, createDefaultAgentHarnessFromCallback, createDefaultAgentHarnessFromTextCallback, createDefaultAgentRuntime, createDefaultAgentRuntimeFromCallback, createDefaultAgentRuntimeFromTextCallback, createDelegationService, createDeliveryOutbox, createEventAgentLoop, createFakeRivusPlugin, createFeishuAgentDaemon, createFeishuAgentRunCard, createFeishuAgentRuntime, createFeishuCardActionCallbackResponse, createFeishuCardActionErrorResponse, createFeishuCardDeliveryLedger, createFeishuCardDeliveryReconciler, createFeishuCardKitOpenApiClient, createFeishuCardKitOpenApiTargetCreator, createFeishuCardKitPublisher, createFeishuCardPresentationStore, createFeishuCardRollover, createFeishuCardRolloverSupervisor, createFeishuCardTargetPreparation, createFeishuConversationId, createFeishuCotPublisher, createFeishuDeploymentEndpoint, createFeishuEventHandlers, createFeishuHumanInteractionCard, createFeishuHumanInteractionPresenter, createFeishuInboxRepository, createFeishuMessageQueue, createFeishuMessageWorker, createFeishuOpenApiClient, createFeishuPeriodicFlush, createFeishuPresentationPreparation, createFeishuSessionKey, createFeishuStreamProjector, createFeishuTenantAccessTokenProvider, createFeishuWebSocketDaemon, createFeishuWorkerLoop, createFixedClock, createHumanInteractionEndpointRegistry, createHumanInteractionService, createHumanInteractionToolApprovalGateway, createInMemoryFeishuCardTargetRegistry, createInMemoryHumanInteractionRepository, createInvocationAuthority, createJsonFetchRequest, createJsonFileFeishuCardTargetRegistry, createJsonlAgentEventLog, createJsonlHumanInteractionRepository, createLangfuseAgentTelemetry, createLazyFeishuWebSocketEventDispatcher, createMemoryNamespace, createOpenTelemetryAgentEventSink, createOpenTelemetryAgentTelemetry, createPiAgentLoop, createPiSdkAgentLoop, createPiSessionRegistry, createPluginStateStore, createProjectMemoryPromptPreparer, createRateLimitedFeishuPublisher, createRecoveryAction, createRecoveryControl, createRivusAgentHost, createRivusDaemonProcess, createRivusDaemonShutdownController, createRivusDaemonStatusHttpServer, createRivusDaemonStatusReporter, createRivusDeploymentCliProcess, createRivusDeploymentDaemon, createRivusEnvFromOpenClawConfig, createRivusMemoryTool, createRivusMemoryToolContract, createRivusMemoryToolDescriptor, createRivusPluginCatalog, createRoutedHumanInteractionToolApprovalService, createScheduledAutomation, createSequenceRunIds, createSessionScheduler, createSubagentCoordinator, createSystemClock, createTelemetryContentRedactor, createTestClock, createTextAgentLoop, createTextAgentLoopFromCallback, createToolBroker, createToolInputDigest, createToolOperationLedger, createUuidRunIds, createWorkspaceRootHandle, describeFeishuMessageIntake, evolveAgentRun, extendBackgroundSessionDefinition, failBackgroundSessionStep, formatRivusEnvFile, initialAgentRunState, intersectToolIds, isAgentToolExecutionEvent, isAssistantTextDeltaEvent, isAssistantThinkingDeltaEvent, isBackgroundSessionDue, isBackgroundSessionLeaseExpired, isBackgroundSessionState, isBackgroundSessionTerminalPhase, isBackgroundSessionToolId, isCardPresentationHandoffDue, isTerminalAgentDomainEvent, isTerminalAgentRunPhase, loadNodeRivusPluginModule, loadRivusDaemonConfig, loadRivusDeployment, loadRivusDeploymentManifest, narrowBackgroundSessionDefinition, normalizeStableJson, openJsonAutomationTickRepository, openJsonlAgentMemoryService, openJsonlBackgroundSessionDeliveryStore, openJsonlBackgroundSessionRepository, openJsonlFeishuCardDeliveryLedger, openJsonlFeishuInboxRepository, openJsonlRecoveryControl, openJsonlToolOperationLedger, parkBackgroundSessionForReconciliation, progressDeliveryId, releaseBackgroundSessionLease, renewBackgroundSessionLease, replayAgentHistory, replayAgentTranscript, requestBackgroundSessionStop, requeueInterruptedBackgroundSessionStep, requiresToolApproval, resolveBackgroundSessionReconciliation, resolveBackgroundSessionSupervisorIntervalMs, resolveFeishuEndpointCredentials, resolveLangfuseTelemetryConfig, resolveRivusAgentDefinition, resolveRivusProjectSpace, restoreAgentHistory, restoreConfiguredRivusDaemonBootstrap, restrictMemoryScopesForAudience, runRivusDaemonCli, sessionIdFromSessionKey, shouldAcceptFeishuEndpointMessage, suspendBackgroundSession, terminalDeliveryId, transitionHumanInteraction, validateProjectSkillCatalog, validateProjectSkillCommand, validateRivusDeploymentManifest };