@mono-agent/agent-app 0.19.1 → 0.20.1
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/README.md +307 -32
- package/dist/acp-bridge.d.ts.map +1 -1
- package/dist/acp-bridge.js +113 -54
- package/dist/acp-bridge.js.map +1 -1
- package/dist/acp-session-store.d.ts +12 -0
- package/dist/acp-session-store.d.ts.map +1 -0
- package/dist/acp-session-store.js +74 -0
- package/dist/acp-session-store.js.map +1 -0
- package/dist/agent-artifact-paths.d.ts +8 -0
- package/dist/agent-artifact-paths.d.ts.map +1 -0
- package/dist/agent-artifact-paths.js +11 -0
- package/dist/agent-artifact-paths.js.map +1 -0
- package/dist/agent-root-coordinator.d.ts +101 -0
- package/dist/agent-root-coordinator.d.ts.map +1 -0
- package/dist/agent-root-coordinator.js +470 -0
- package/dist/agent-root-coordinator.js.map +1 -0
- package/dist/app-controller-channels.d.ts +13 -1
- package/dist/app-controller-channels.d.ts.map +1 -1
- package/dist/app-controller-channels.js +152 -20
- package/dist/app-controller-channels.js.map +1 -1
- package/dist/app-controller-continuation.d.ts +2 -0
- package/dist/app-controller-continuation.d.ts.map +1 -1
- package/dist/app-controller-continuation.js.map +1 -1
- package/dist/app-controller-lifecycle.d.ts +5 -0
- package/dist/app-controller-lifecycle.d.ts.map +1 -1
- package/dist/app-controller-lifecycle.js +24 -5
- package/dist/app-controller-lifecycle.js.map +1 -1
- package/dist/app-controller-maintenance.d.ts +4 -0
- package/dist/app-controller-maintenance.d.ts.map +1 -1
- package/dist/app-controller-maintenance.js +34 -2
- package/dist/app-controller-maintenance.js.map +1 -1
- package/dist/app-controller-memory.d.ts +2 -0
- package/dist/app-controller-memory.d.ts.map +1 -1
- package/dist/app-controller-memory.js +6 -3
- package/dist/app-controller-memory.js.map +1 -1
- package/dist/app-controller-process-jobs.d.ts +49 -0
- package/dist/app-controller-process-jobs.d.ts.map +1 -0
- package/dist/app-controller-process-jobs.js +294 -0
- package/dist/app-controller-process-jobs.js.map +1 -0
- package/dist/app-controller-responder.d.ts +17 -0
- package/dist/app-controller-responder.d.ts.map +1 -1
- package/dist/app-controller-responder.js +164 -13
- package/dist/app-controller-responder.js.map +1 -1
- package/dist/app-controller-traceability.d.ts +8 -0
- package/dist/app-controller-traceability.d.ts.map +1 -1
- package/dist/app-controller-traceability.js +22 -1
- package/dist/app-controller-traceability.js.map +1 -1
- package/dist/app-controller-types.d.ts +1 -1
- package/dist/app-controller-types.d.ts.map +1 -1
- package/dist/app-controller-utils.d.ts +8 -0
- package/dist/app-controller-utils.d.ts.map +1 -1
- package/dist/app-controller-utils.js +24 -1
- package/dist/app-controller-utils.js.map +1 -1
- package/dist/app-controller.d.ts +45 -1
- package/dist/app-controller.d.ts.map +1 -1
- package/dist/app-controller.js +135 -39
- package/dist/app-controller.js.map +1 -1
- package/dist/background-log-maintenance.d.ts +85 -2
- package/dist/background-log-maintenance.d.ts.map +1 -1
- package/dist/background-log-maintenance.js +407 -136
- package/dist/background-log-maintenance.js.map +1 -1
- package/dist/background-runtime.d.ts.map +1 -1
- package/dist/background-runtime.js +22 -41
- package/dist/background-runtime.js.map +1 -1
- package/dist/background.d.ts +18 -26
- package/dist/background.d.ts.map +1 -1
- package/dist/background.js +105 -138
- package/dist/background.js.map +1 -1
- package/dist/channel-drivers/cron.d.ts +12 -1
- package/dist/channel-drivers/cron.d.ts.map +1 -1
- package/dist/channel-drivers/cron.js +121 -18
- package/dist/channel-drivers/cron.js.map +1 -1
- package/dist/channel-drivers/native-notify.d.ts +3 -0
- package/dist/channel-drivers/native-notify.d.ts.map +1 -1
- package/dist/channel-drivers/native-notify.js +2 -1
- package/dist/channel-drivers/native-notify.js.map +1 -1
- package/dist/channel-drivers/slack.d.ts.map +1 -1
- package/dist/channel-drivers/slack.js +41 -4
- package/dist/channel-drivers/slack.js.map +1 -1
- package/dist/channel-drivers/telegram.d.ts.map +1 -1
- package/dist/channel-drivers/telegram.js +46 -3
- package/dist/channel-drivers/telegram.js.map +1 -1
- package/dist/channel-drivers/tui.d.ts +13 -2
- package/dist/channel-drivers/tui.d.ts.map +1 -1
- package/dist/channel-drivers/tui.js +112 -3
- package/dist/channel-drivers/tui.js.map +1 -1
- package/dist/channels.d.ts +1 -1
- package/dist/channels.d.ts.map +1 -1
- package/dist/channels.js +4 -2
- package/dist/channels.js.map +1 -1
- package/dist/cli-args.d.ts +15 -1
- package/dist/cli-args.d.ts.map +1 -1
- package/dist/cli-args.js +82 -12
- package/dist/cli-args.js.map +1 -1
- package/dist/cli-background-command.d.ts +9 -2
- package/dist/cli-background-command.d.ts.map +1 -1
- package/dist/cli-background-command.js +179 -66
- package/dist/cli-background-command.js.map +1 -1
- package/dist/cli-commands.d.ts.map +1 -1
- package/dist/cli-commands.js +50 -12
- package/dist/cli-commands.js.map +1 -1
- package/dist/cli-help.d.ts.map +1 -1
- package/dist/cli-help.js +21 -1
- package/dist/cli-help.js.map +1 -1
- package/dist/config-reference.d.ts.map +1 -1
- package/dist/config-reference.js +105 -2
- package/dist/config-reference.js.map +1 -1
- package/dist/configured-agent.d.ts +64 -21
- package/dist/configured-agent.d.ts.map +1 -1
- package/dist/configured-agent.js +840 -156
- package/dist/configured-agent.js.map +1 -1
- package/dist/conversation-state-roots.d.ts +59 -0
- package/dist/conversation-state-roots.d.ts.map +1 -0
- package/dist/conversation-state-roots.js +248 -0
- package/dist/conversation-state-roots.js.map +1 -0
- package/dist/cron-control-store.d.ts +91 -0
- package/dist/cron-control-store.d.ts.map +1 -0
- package/dist/cron-control-store.js +1251 -0
- package/dist/cron-control-store.js.map +1 -0
- package/dist/cron-operator-service.d.ts +54 -0
- package/dist/cron-operator-service.d.ts.map +1 -0
- package/dist/cron-operator-service.js +352 -0
- package/dist/cron-operator-service.js.map +1 -0
- package/dist/doctor-session-history.d.ts +9 -0
- package/dist/doctor-session-history.d.ts.map +1 -0
- package/dist/doctor-session-history.js +313 -0
- package/dist/doctor-session-history.js.map +1 -0
- package/dist/doctor.d.ts +2 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +356 -9
- package/dist/doctor.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/interaction-bridge.d.ts +1 -0
- package/dist/interaction-bridge.d.ts.map +1 -1
- package/dist/interaction-bridge.js +54 -6
- package/dist/interaction-bridge.js.map +1 -1
- package/dist/jobs-command.d.ts +17 -0
- package/dist/jobs-command.d.ts.map +1 -0
- package/dist/jobs-command.js +207 -0
- package/dist/jobs-command.js.map +1 -0
- package/dist/launchd-lifecycle-lock.d.ts +36 -0
- package/dist/launchd-lifecycle-lock.d.ts.map +1 -0
- package/dist/launchd-lifecycle-lock.js +124 -0
- package/dist/launchd-lifecycle-lock.js.map +1 -0
- package/dist/launchd-log-monitor-status.d.ts +7 -0
- package/dist/launchd-log-monitor-status.d.ts.map +1 -0
- package/dist/launchd-log-monitor-status.js +224 -0
- package/dist/launchd-log-monitor-status.js.map +1 -0
- package/dist/launchd-logs.d.ts +9 -1
- package/dist/launchd-logs.d.ts.map +1 -1
- package/dist/launchd-logs.js +69 -16
- package/dist/launchd-logs.js.map +1 -1
- package/dist/launchd-maintenance-command.d.ts +10 -0
- package/dist/launchd-maintenance-command.d.ts.map +1 -0
- package/dist/launchd-maintenance-command.js +2 -0
- package/dist/launchd-maintenance-command.js.map +1 -0
- package/dist/launchd-maintenance-entry.d.ts +30 -0
- package/dist/launchd-maintenance-entry.d.ts.map +1 -0
- package/dist/launchd-maintenance-entry.js +206 -0
- package/dist/launchd-maintenance-entry.js.map +1 -0
- package/dist/launchd-maintenance-gate.d.ts +28 -0
- package/dist/launchd-maintenance-gate.d.ts.map +1 -0
- package/dist/launchd-maintenance-gate.js +80 -0
- package/dist/launchd-maintenance-gate.js.map +1 -0
- package/dist/launchd-private-files.d.ts +3 -0
- package/dist/launchd-private-files.d.ts.map +1 -0
- package/dist/launchd-private-files.js +58 -0
- package/dist/launchd-private-files.js.map +1 -0
- package/dist/launchd.d.ts +56 -2
- package/dist/launchd.d.ts.map +1 -1
- package/dist/launchd.js +210 -5
- package/dist/launchd.js.map +1 -1
- package/dist/local-configuration.d.ts.map +1 -1
- package/dist/local-configuration.js +34 -7
- package/dist/local-configuration.js.map +1 -1
- package/dist/managed-launchd-maintenance-environment.d.ts +3 -0
- package/dist/managed-launchd-maintenance-environment.d.ts.map +1 -0
- package/dist/managed-launchd-maintenance-environment.js +12 -0
- package/dist/managed-launchd-maintenance-environment.js.map +1 -0
- package/dist/managed-runtime-launch-proof.d.ts +11 -0
- package/dist/managed-runtime-launch-proof.d.ts.map +1 -0
- package/dist/managed-runtime-launch-proof.js +59 -0
- package/dist/managed-runtime-launch-proof.js.map +1 -0
- package/dist/managed-runtime-maintenance-entry.d.ts +10 -0
- package/dist/managed-runtime-maintenance-entry.d.ts.map +1 -0
- package/dist/managed-runtime-maintenance-entry.js +244 -0
- package/dist/managed-runtime-maintenance-entry.js.map +1 -0
- package/dist/managed-web-logs.d.ts +29 -11
- package/dist/managed-web-logs.d.ts.map +1 -1
- package/dist/managed-web-logs.js +244 -121
- package/dist/managed-web-logs.js.map +1 -1
- package/dist/managed-web-maintenance-environment.d.ts +6 -0
- package/dist/managed-web-maintenance-environment.d.ts.map +1 -0
- package/dist/managed-web-maintenance-environment.js +19 -0
- package/dist/managed-web-maintenance-environment.js.map +1 -0
- package/dist/mcp-apps.d.ts +37 -0
- package/dist/mcp-apps.d.ts.map +1 -0
- package/dist/mcp-apps.js +1753 -0
- package/dist/mcp-apps.js.map +1 -0
- package/dist/memory-command.d.ts +12 -0
- package/dist/memory-command.d.ts.map +1 -1
- package/dist/memory-command.js +510 -1
- package/dist/memory-command.js.map +1 -1
- package/dist/modules/known-tools.d.ts +1 -1
- package/dist/modules/known-tools.d.ts.map +1 -1
- package/dist/modules/known-tools.js +2 -0
- package/dist/modules/known-tools.js.map +1 -1
- package/dist/posted-reply-history.d.ts.map +1 -1
- package/dist/posted-reply-history.js +12 -0
- package/dist/posted-reply-history.js.map +1 -1
- package/dist/proactive-notify.d.ts +4 -1
- package/dist/proactive-notify.d.ts.map +1 -1
- package/dist/proactive-notify.js +43 -5
- package/dist/proactive-notify.js.map +1 -1
- package/dist/process-jobs-config.d.ts +84 -0
- package/dist/process-jobs-config.d.ts.map +1 -0
- package/dist/process-jobs-config.js +427 -0
- package/dist/process-jobs-config.js.map +1 -0
- package/dist/process-jobs-context.d.ts +24 -0
- package/dist/process-jobs-context.d.ts.map +1 -0
- package/dist/process-jobs-context.js +135 -0
- package/dist/process-jobs-context.js.map +1 -0
- package/dist/process-jobs-protection.d.ts +33 -0
- package/dist/process-jobs-protection.d.ts.map +1 -0
- package/dist/process-jobs-protection.js +74 -0
- package/dist/process-jobs-protection.js.map +1 -0
- package/dist/process-jobs-root-registry.d.ts +115 -0
- package/dist/process-jobs-root-registry.d.ts.map +1 -0
- package/dist/process-jobs-root-registry.js +978 -0
- package/dist/process-jobs-root-registry.js.map +1 -0
- package/dist/process-jobs-runtime.d.ts +38 -0
- package/dist/process-jobs-runtime.d.ts.map +1 -0
- package/dist/process-jobs-runtime.js +178 -0
- package/dist/process-jobs-runtime.js.map +1 -0
- package/dist/process-jobs-service.d.ts +70 -0
- package/dist/process-jobs-service.d.ts.map +1 -0
- package/dist/process-jobs-service.js +1989 -0
- package/dist/process-jobs-service.js.map +1 -0
- package/dist/process-jobs-store.d.ts +151 -0
- package/dist/process-jobs-store.d.ts.map +1 -0
- package/dist/process-jobs-store.js +1290 -0
- package/dist/process-jobs-store.js.map +1 -0
- package/dist/reply-artifacts.d.ts +65 -0
- package/dist/reply-artifacts.d.ts.map +1 -0
- package/dist/reply-artifacts.js +1147 -0
- package/dist/reply-artifacts.js.map +1 -0
- package/dist/reply-part-budget.d.ts +16 -0
- package/dist/reply-part-budget.d.ts.map +1 -0
- package/dist/reply-part-budget.js +57 -0
- package/dist/reply-part-budget.js.map +1 -0
- package/dist/request-model-override.d.ts +19 -0
- package/dist/request-model-override.d.ts.map +1 -1
- package/dist/request-model-override.js +54 -1
- package/dist/request-model-override.js.map +1 -1
- package/dist/request-scoped-mcp.d.ts +31 -0
- package/dist/request-scoped-mcp.d.ts.map +1 -0
- package/dist/request-scoped-mcp.js +197 -0
- package/dist/request-scoped-mcp.js.map +1 -0
- package/dist/run-history.d.ts.map +1 -1
- package/dist/run-history.js +50 -254
- package/dist/run-history.js.map +1 -1
- package/dist/runtime-option-extensions.d.ts +23 -0
- package/dist/runtime-option-extensions.d.ts.map +1 -1
- package/dist/runtime-option-extensions.js +55 -0
- package/dist/runtime-option-extensions.js.map +1 -1
- package/dist/runtime-routes.d.ts +7 -1
- package/dist/runtime-routes.d.ts.map +1 -1
- package/dist/runtime-routes.js +25 -0
- package/dist/runtime-routes.js.map +1 -1
- package/dist/secure-file-replace.d.ts +3 -0
- package/dist/secure-file-replace.d.ts.map +1 -1
- package/dist/secure-file-replace.js +31 -7
- package/dist/secure-file-replace.js.map +1 -1
- package/dist/session-history.d.ts +146 -0
- package/dist/session-history.d.ts.map +1 -0
- package/dist/session-history.js +347 -0
- package/dist/session-history.js.map +1 -0
- package/dist/sessions.d.ts +45 -2
- package/dist/sessions.d.ts.map +1 -1
- package/dist/sessions.js +849 -30
- package/dist/sessions.js.map +1 -1
- package/dist/web-command.d.ts +12 -11
- package/dist/web-command.d.ts.map +1 -1
- package/dist/web-command.js +554 -80
- package/dist/web-command.js.map +1 -1
- package/dist/web-log-maintenance-command.d.ts +7 -0
- package/dist/web-log-maintenance-command.d.ts.map +1 -0
- package/dist/web-log-maintenance-command.js +21 -0
- package/dist/web-log-maintenance-command.js.map +1 -0
- package/dist/web-log-maintenance-status.d.ts +26 -0
- package/dist/web-log-maintenance-status.d.ts.map +1 -0
- package/dist/web-log-maintenance-status.js +171 -0
- package/dist/web-log-maintenance-status.js.map +1 -0
- package/dist/web-log-maintenance.d.ts +32 -0
- package/dist/web-log-maintenance.d.ts.map +1 -0
- package/dist/web-log-maintenance.js +163 -0
- package/dist/web-log-maintenance.js.map +1 -0
- package/dist/web-maintenance-paths.d.ts +12 -0
- package/dist/web-maintenance-paths.d.ts.map +1 -0
- package/dist/web-maintenance-paths.js +24 -0
- package/dist/web-maintenance-paths.js.map +1 -0
- package/dist/wizard/prompts.d.ts.map +1 -1
- package/dist/wizard/prompts.js +1 -0
- package/dist/wizard/prompts.js.map +1 -1
- package/dist/wizard/run.js +1 -1
- package/dist/wizard/run.js.map +1 -1
- package/package.json +15 -15
- package/schema/mono-agent.config.schema.json +106 -1
- package/skills/mono-agent-composer/references/config-blueprint.md +27 -2
- package/skills/mono-agent-composer/references/discovery-questions.md +2 -2
- package/skills/mono-agent-composer/references/feature-coverage.md +6 -4
- package/skills/mono-agent-composer/references/package-map.md +19 -3
- package/skills/mono-agent-composer/references/playbooks.md +3 -3
- package/skills/mono-agent-composer/references/validation.md +4 -2
package/dist/configured-agent.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAgentHarness, createAgentResponder, createDurableHistoryStore, createToolPolicy, loadToolPolicyFromJsonFileSync, renderSkillIndexSection, } from "@mono-agent/agent-harness";
|
|
1
|
+
import { createAgentHarness, createAgentResponder, acquireToolHistoryWriter, createDurableHistoryStore, createToolPolicy, loadToolPolicyFromJsonFileSync, renderSkillIndexSection, ToolHistoryReader, toolHistoryLogicalConversationId, } from "@mono-agent/agent-harness";
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { resolve as resolvePath } from "node:path";
|
|
@@ -6,11 +6,17 @@ import { setToolActivityPathRoots } from "@mono-agent/agent-contracts";
|
|
|
6
6
|
import { resolveSupermemoryContainer } from "@mono-agent/config";
|
|
7
7
|
import { createCompositeRunRecorder, createJsonlRunRecorder } from "@mono-agent/observability";
|
|
8
8
|
import { createPhoenixRunExporter } from "@mono-agent/observability/otel";
|
|
9
|
-
import { assertExecutionModeCompatible, createMonoRuntime, createPiOAuthApiKeyResolver, defaultExecutionModeForModel, describeMonoRuntimeSupport, modelReferenceKey, monoRuntimeSupportsSessionResume, parseMonoRuntimeModelReference, runtimeOptionsForLocalProvider, } from "@mono-agent/runtime-adapter";
|
|
9
|
+
import { assertExecutionModeCompatible, createMonoRuntime, createPiOAuthApiKeyResolver, createSrtSandboxEngine, defaultExecutionModeForModel, describeMonoRuntimeSupport, modelReferenceKey, monoRuntimeSupportsSessionResume, parseMonoRuntimeModelReference, runtimeOptionsForLocalProvider, mergeSandboxPolicies, } from "@mono-agent/runtime-adapter";
|
|
10
|
+
import { agentArtifactDerivedRoots } from "./agent-artifact-paths.js";
|
|
11
|
+
import { acquireAgentRootOwnership, assertAgentRootLeaseOutsideWorkspace, releaseAgentRootOwnershipWhenIdle, } from "./agent-root-coordinator.js";
|
|
10
12
|
import { resolveMemoryRecallSettings } from "./memory-recall.js";
|
|
11
13
|
import { BUILTIN_TOOL_NAMES, canonicalToolName, isAllowAllTools } from "./modules/known-tools.js";
|
|
12
14
|
import { createSharedMemoryRecallRuntimeExtension, isSharedRecallStore, MemoryRetrievalService, } from "./memory-retrieval.js";
|
|
13
|
-
import { composeRuntimeOptionExtensions } from "./runtime-option-extensions.js";
|
|
15
|
+
import { clearSessionsSandboxPolicy, composeRuntimeOptionExtensions, createClearSessionsRuntimeExtension, } from "./runtime-option-extensions.js";
|
|
16
|
+
import { configuredRuntimeFallbackModels, runtimeUsesFallbackRouter, } from "./runtime-routes.js";
|
|
17
|
+
import { resolveProcessJobsProtectionPosture, } from "./process-jobs-protection.js";
|
|
18
|
+
import { createProcessJobsRuntimeExtension, processJobsSandboxPolicy, PROCESS_JOBS_PI_NATIVE_REQUIRED_ERROR, PROCESS_JOBS_PROTECTION_UNAVAILABLE_ERROR, } from "./process-jobs-runtime.js";
|
|
19
|
+
import { attestProcessJobsRootRegistrySnapshot, loadProcessJobsRootRegistryProtection, processJobsProtectionPolicyRoots, registerProcessJobsRoot, } from "./process-jobs-root-registry.js";
|
|
14
20
|
import { isReadSkillDenied } from "./skill-registry.js";
|
|
15
21
|
import { loadSupermemoryPlugin } from "./supermemory-plugin.js";
|
|
16
22
|
/**
|
|
@@ -148,10 +154,22 @@ function recorderCompositionDeps(config, options, internalHooks = {}) {
|
|
|
148
154
|
export function createConfiguredAgentRuntime(input) {
|
|
149
155
|
const config = isRuntimeOptions(input) ? input.config : input;
|
|
150
156
|
const options = isRuntimeOptions(input) ? input : undefined;
|
|
157
|
+
return wrapOwnedConfiguredRuntime(createConfiguredAgentRuntimeBase(config, options), config, options?.cwd, options?.sandboxEngine);
|
|
158
|
+
}
|
|
159
|
+
/** @internal App/harness seam; callers are already inside the shared root/request choke point. */
|
|
160
|
+
export function createConfiguredAgentRuntimeForApp(input, internal = {}) {
|
|
161
|
+
const config = isRuntimeOptions(input) ? input.config : input;
|
|
162
|
+
const options = isRuntimeOptions(input) ? input : undefined;
|
|
163
|
+
return createConfiguredAgentRuntimeBase(config, options, internal.suppressSandboxEngine === true);
|
|
164
|
+
}
|
|
165
|
+
function createConfiguredAgentRuntimeBase(config, options, suppressSandboxEngine = false) {
|
|
151
166
|
const fallback = fallbackChainForConfig(config, options);
|
|
167
|
+
const sandboxEngine = suppressSandboxEngine
|
|
168
|
+
? undefined
|
|
169
|
+
: configuredSandboxEngine(config, options?.model ?? config.runtime.model, options?.sandboxEngine);
|
|
152
170
|
const runtimeOptions = {
|
|
153
171
|
...runtimeHostOptionsForConfig(config),
|
|
154
|
-
...(
|
|
172
|
+
...(sandboxEngine === undefined ? {} : { sandboxEngine }),
|
|
155
173
|
...fallback,
|
|
156
174
|
...(fallback.fallbackChain === undefined
|
|
157
175
|
? {}
|
|
@@ -175,6 +193,107 @@ export function createConfiguredAgentRuntime(input) {
|
|
|
175
193
|
};
|
|
176
194
|
return createMonoRuntime(runtimeOptions);
|
|
177
195
|
}
|
|
196
|
+
function configuredSandboxEngine(config, primaryModel, explicit) {
|
|
197
|
+
if (explicit !== undefined)
|
|
198
|
+
return explicit;
|
|
199
|
+
return [primaryModel, ...configuredRuntimeFallbackModels(config.runtime)]
|
|
200
|
+
.some((model) => model.sdk === "pi")
|
|
201
|
+
? createSrtSandboxEngine()
|
|
202
|
+
: undefined;
|
|
203
|
+
}
|
|
204
|
+
function wrapOwnedConfiguredRuntime(runtime, config, agentRoot, configuredSandboxEngine) {
|
|
205
|
+
let security;
|
|
206
|
+
let disposed = false;
|
|
207
|
+
const loadSecurity = async () => {
|
|
208
|
+
const ownership = await acquireAgentRootOwnership(agentRoot);
|
|
209
|
+
try {
|
|
210
|
+
assertAgentRootLeaseOutsideWorkspace(ownership, config.runtime.workspace);
|
|
211
|
+
return { ownership };
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
await releaseAgentRootOwnershipWhenIdle(ownership).catch(() => undefined);
|
|
215
|
+
throw error;
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
const secured = () => (security ??= loadSecurity());
|
|
219
|
+
const releaseOwnership = async () => {
|
|
220
|
+
const current = security;
|
|
221
|
+
security = undefined;
|
|
222
|
+
if (current === undefined)
|
|
223
|
+
return;
|
|
224
|
+
const { ownership } = await current.catch(() => ({ ownership: undefined }));
|
|
225
|
+
if (ownership !== undefined) {
|
|
226
|
+
await releaseAgentRootOwnershipWhenIdle(ownership);
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
return {
|
|
230
|
+
async run(systemPrompt, runOptions) {
|
|
231
|
+
if (disposed)
|
|
232
|
+
throw new Error("Configured runtime has been disposed.");
|
|
233
|
+
const { ownership } = await secured();
|
|
234
|
+
const registry = await loadProcessJobsRootRegistryProtection(ownership.agentRoot, config.runtime.workspace);
|
|
235
|
+
ownership.coordinator.synchronizeGeneration(registry.generation);
|
|
236
|
+
const boundary = await attestProcessJobsRootRegistrySnapshot(registry, config.runtime.workspace);
|
|
237
|
+
if (disposed)
|
|
238
|
+
throw new Error("Configured runtime has been disposed.");
|
|
239
|
+
const lease = ownership.coordinator.acquireRequestLease(boundary.generation);
|
|
240
|
+
try {
|
|
241
|
+
const attested = await attestProcessJobsRootRegistrySnapshot(boundary, config.runtime.workspace);
|
|
242
|
+
const protectedRoots = processJobsProtectionPolicyRoots(attested);
|
|
243
|
+
let effectiveOptions = runOptions;
|
|
244
|
+
if (protectedRoots.length > 0) {
|
|
245
|
+
if (!configuredRoutesOnlyPiNative(config, runOptions.model)) {
|
|
246
|
+
throw new Error(PROCESS_JOBS_PI_NATIVE_REQUIRED_ERROR);
|
|
247
|
+
}
|
|
248
|
+
if (runOptions.model.sdk !== "pi")
|
|
249
|
+
throw new Error(PROCESS_JOBS_PI_NATIVE_REQUIRED_ERROR);
|
|
250
|
+
const sandboxEngine = runOptions.sandboxEngine
|
|
251
|
+
?? configuredSandboxEngine
|
|
252
|
+
?? createSrtSandboxEngine();
|
|
253
|
+
if (!await sandboxEngine.isAvailable().catch(() => false)) {
|
|
254
|
+
throw new Error(PROCESS_JOBS_PROTECTION_UNAVAILABLE_ERROR);
|
|
255
|
+
}
|
|
256
|
+
const sandboxPolicy = mergeSandboxPolicies(runOptions.sandboxPolicy, processJobsSandboxPolicy({ coreConfig: config, protectedRoots }));
|
|
257
|
+
if (sandboxPolicy === undefined) {
|
|
258
|
+
throw new Error(PROCESS_JOBS_PROTECTION_UNAVAILABLE_ERROR);
|
|
259
|
+
}
|
|
260
|
+
effectiveOptions = {
|
|
261
|
+
...runOptions,
|
|
262
|
+
sandboxPolicy,
|
|
263
|
+
sandboxEngine,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
return await runtime.run(systemPrompt, effectiveOptions);
|
|
267
|
+
}
|
|
268
|
+
finally {
|
|
269
|
+
lease.releaseAfterSettlement();
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
...(runtime.configureTools === undefined
|
|
273
|
+
? {}
|
|
274
|
+
: { configureTools: runtime.configureTools.bind(runtime) }),
|
|
275
|
+
...(runtime.syncSession === undefined ? {} : { syncSession: runtime.syncSession.bind(runtime) }),
|
|
276
|
+
...(runtime.refreshSession === undefined ? {} : { refreshSession: runtime.refreshSession.bind(runtime) }),
|
|
277
|
+
...(runtime.retireDurableSession === undefined
|
|
278
|
+
? {}
|
|
279
|
+
: { retireDurableSession: runtime.retireDurableSession.bind(runtime) }),
|
|
280
|
+
...(runtime.disposeSession === undefined ? {} : { disposeSession: runtime.disposeSession.bind(runtime) }),
|
|
281
|
+
...(runtime.invalidateSession === undefined
|
|
282
|
+
? {}
|
|
283
|
+
: { invalidateSession: runtime.invalidateSession.bind(runtime) }),
|
|
284
|
+
async disposeAllSessions() {
|
|
285
|
+
if (disposed)
|
|
286
|
+
return;
|
|
287
|
+
disposed = true;
|
|
288
|
+
try {
|
|
289
|
+
await runtime.disposeAllSessions?.();
|
|
290
|
+
}
|
|
291
|
+
finally {
|
|
292
|
+
await releaseOwnership();
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
};
|
|
296
|
+
}
|
|
178
297
|
/**
|
|
179
298
|
* Narrow the loaded MCP servers to the ones a profile names.
|
|
180
299
|
*
|
|
@@ -327,6 +446,11 @@ function subagentsRuntimeOptions(config, deps) {
|
|
|
327
446
|
const childSystemPrompt = childSkills === undefined
|
|
328
447
|
? request.systemPrompt
|
|
329
448
|
: `${request.systemPrompt}\n\n${renderSkillIndexSection(childSkills)}`;
|
|
449
|
+
if (childModel.sdk !== "pi"
|
|
450
|
+
&& (deps.processJobsProtectionPosture.requiresPiNative
|
|
451
|
+
|| sandboxPolicyCarriesProtectedRoots(request.sandboxPolicy))) {
|
|
452
|
+
throw new Error(PROCESS_JOBS_PI_NATIVE_REQUIRED_ERROR);
|
|
453
|
+
}
|
|
330
454
|
return await runtime.run(childSystemPrompt, {
|
|
331
455
|
model: childModel,
|
|
332
456
|
executionMode: childExecutionMode,
|
|
@@ -446,6 +570,27 @@ function fallbackChainForConfig(config, options) {
|
|
|
446
570
|
],
|
|
447
571
|
};
|
|
448
572
|
}
|
|
573
|
+
function configuredRoutesOnlyPiNative(config, primary) {
|
|
574
|
+
try {
|
|
575
|
+
const fallback = fallbackChainForConfig(config, { config, model: primary });
|
|
576
|
+
const routes = fallback.fallbackChain?.map((entry) => entry.model) ?? [primary];
|
|
577
|
+
return routes.length > 0 && routes.every((model) => model.sdk === "pi");
|
|
578
|
+
}
|
|
579
|
+
catch {
|
|
580
|
+
return false;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
function sandboxPolicyCarriesProtectedRoots(policy) {
|
|
584
|
+
if (policy === undefined || policy === null || typeof policy !== "object")
|
|
585
|
+
return false;
|
|
586
|
+
try {
|
|
587
|
+
const roots = policy.protectedRoots;
|
|
588
|
+
return roots !== undefined && (!Array.isArray(roots) || roots.length > 0);
|
|
589
|
+
}
|
|
590
|
+
catch {
|
|
591
|
+
return true;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
449
594
|
let memoryBujoModule;
|
|
450
595
|
let memorySearchModule;
|
|
451
596
|
const loadMemoryBujoModule = async () => (memoryBujoModule ??= await import("@mono-agent/memory/bujo"));
|
|
@@ -455,156 +600,581 @@ export async function createConfiguredAgentHarness(options) {
|
|
|
455
600
|
}
|
|
456
601
|
async function createConfiguredAgentHarnessInternal(options, internalHooks = {}) {
|
|
457
602
|
const config = options.config;
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
603
|
+
const ownership = await acquireAgentRootOwnership(options.cwd ?? process.cwd());
|
|
604
|
+
const agentRoot = ownership.agentRoot;
|
|
605
|
+
let ownershipTransferred = false;
|
|
606
|
+
try {
|
|
607
|
+
assertAgentRootLeaseOutsideWorkspace(ownership, config.runtime.workspace);
|
|
608
|
+
const loadedProcessJobsRegistry = internalHooks.processJobs?.registry
|
|
609
|
+
?? (internalHooks.bootstrapProcessJobs?.stateDir === undefined
|
|
610
|
+
? await loadProcessJobsRootRegistryProtection(ownership.agentRoot, config.runtime.workspace)
|
|
611
|
+
: (await registerProcessJobsRoot({
|
|
612
|
+
agentRoot: ownership.agentRoot,
|
|
613
|
+
workspace: config.runtime.workspace,
|
|
614
|
+
stateDir: internalHooks.bootstrapProcessJobs.stateDir,
|
|
615
|
+
coordinator: ownership.coordinator,
|
|
616
|
+
})).snapshot);
|
|
617
|
+
const processJobsRegistry = loadedProcessJobsRegistry.kind === "failed"
|
|
618
|
+
? loadedProcessJobsRegistry
|
|
619
|
+
: await attestProcessJobsRootRegistrySnapshot(loadedProcessJobsRegistry, config.runtime.workspace);
|
|
620
|
+
ownership.coordinator.synchronizeGeneration(processJobsRegistry.generation);
|
|
621
|
+
const processJobsProtectionPosture = internalHooks.processJobs?.protectionPosture
|
|
622
|
+
?? resolveProcessJobsProtectionPosture({
|
|
623
|
+
settings: internalHooks.bootstrapProcessJobs?.settings
|
|
624
|
+
?? { enabled: false, unsafeAllowUnprotectedState: false },
|
|
625
|
+
registry: processJobsRegistry,
|
|
626
|
+
coreConfig: config,
|
|
627
|
+
});
|
|
628
|
+
const processJobsProtectedRoots = processJobsProtectionPolicyRoots(processJobsRegistry);
|
|
629
|
+
const artifactDerivedRoots = agentArtifactDerivedRoots(config.artifacts.dir);
|
|
630
|
+
// Chat activity lines are formatted deep in the streaming layer, which has no
|
|
631
|
+
// per-message workspace to hand down. Without this the root falls back to
|
|
632
|
+
// `process.cwd()` — for a service-managed agent, whatever directory the
|
|
633
|
+
// supervisor started it in — and tool previews expose the full machine layout.
|
|
634
|
+
setToolActivityPathRoots({ workspaceRoot: config.runtime.workspace, homeDir: homedir() });
|
|
635
|
+
const model = options.model ?? config.runtime.model;
|
|
636
|
+
const executionMode = options.executionMode ?? config.runtime.executionMode;
|
|
637
|
+
const fallbackModels = configuredRuntimeFallbackModels(config.runtime);
|
|
638
|
+
const sandboxEngine = processJobsProtectionPosture.suppressSyntheticSandbox
|
|
639
|
+
? undefined
|
|
640
|
+
: configuredSandboxEngine(config, model, options.sandboxEngine);
|
|
641
|
+
const harnessSandboxPolicy = processJobsProtectionPosture.suppressSyntheticSandbox
|
|
642
|
+
? config.sandbox
|
|
643
|
+
: processJobsProtectedRoots.length === 0
|
|
644
|
+
? config.sandbox
|
|
645
|
+
: processJobsSandboxPolicy({ coreConfig: config, protectedRoots: processJobsProtectedRoots });
|
|
646
|
+
const runtime = options.runtime ?? createConfiguredAgentRuntimeForApp({
|
|
647
|
+
config,
|
|
648
|
+
cwd: agentRoot,
|
|
649
|
+
model,
|
|
650
|
+
executionMode,
|
|
651
|
+
...(sandboxEngine === undefined ? {} : { sandboxEngine }),
|
|
652
|
+
}, {
|
|
653
|
+
suppressSandboxEngine: processJobsProtectionPosture.suppressSyntheticSandbox,
|
|
654
|
+
});
|
|
655
|
+
const clearSessionsBoundaryOptions = {
|
|
656
|
+
cwd: agentRoot,
|
|
657
|
+
workspace: config.runtime.workspace,
|
|
658
|
+
baseModel: model,
|
|
659
|
+
fallbackModels,
|
|
660
|
+
...(harnessSandboxPolicy === undefined ? {} : { sandboxPolicy: harnessSandboxPolicy }),
|
|
661
|
+
...(processJobsProtectionPosture.suppressSyntheticSandbox
|
|
662
|
+
? { suppressSyntheticSandbox: true }
|
|
663
|
+
: {}),
|
|
664
|
+
};
|
|
665
|
+
const routedClearSessionsPolicy = runtimeUsesFallbackRouter(config.runtime)
|
|
666
|
+
? clearSessionsSandboxPolicy(clearSessionsBoundaryOptions)
|
|
667
|
+
: undefined;
|
|
668
|
+
// Request policy is still attested and applied per turn below. Configure the
|
|
669
|
+
// same stable engine/policy into the routed ToolContext so Pi filesystem
|
|
670
|
+
// builtins resolve their native boundary there; per-route-native projection
|
|
671
|
+
// clears both fields from every non-Pi attempt.
|
|
672
|
+
runtime.configureTools?.({
|
|
673
|
+
workspace: config.runtime.workspace,
|
|
674
|
+
...(sandboxEngine === undefined ? {} : { sandboxEngine }),
|
|
675
|
+
...(routedClearSessionsPolicy === undefined ? {} : { sandboxPolicy: routedClearSessionsPolicy }),
|
|
676
|
+
});
|
|
677
|
+
// The memory LLM must NOT ride the channel `runtime`: that runtime carries the
|
|
678
|
+
// channel fallback chain whose primary is `config.runtime.model`, and the
|
|
679
|
+
// fallback router overrides each run's per-call `model` — so reusing it would
|
|
680
|
+
// execute memory capture on `config.runtime.model` instead of
|
|
681
|
+
// `config.memory.llm.model`. createConfiguredMemory builds the memory LLM its own
|
|
682
|
+
// fallback-free runtime when no `memoryRuntime` is injected.
|
|
683
|
+
const configuredMemory = options.memory ?? (await createConfiguredMemoryInternal(config, { cwd: agentRoot }, processJobsProtectionPosture));
|
|
684
|
+
const memory = configuredMemoryForHarness(config, configuredMemory);
|
|
685
|
+
const memoryRecall = resolveMemoryRecallSettings(config) === undefined
|
|
686
|
+
|| !(memory instanceof MemoryRetrievalService)
|
|
687
|
+
? undefined
|
|
688
|
+
: createSharedMemoryRecallRuntimeExtension(memory, {
|
|
689
|
+
...(options.onMemoryRecallUnavailable === undefined
|
|
690
|
+
? {}
|
|
691
|
+
: { onUnavailable: options.onMemoryRecallUnavailable }),
|
|
692
|
+
});
|
|
693
|
+
const composedRuntimeOptionsForRequest = composeRuntimeOptionExtensions([
|
|
694
|
+
memoryRecall,
|
|
695
|
+
options.runtimeOptionsForRequest,
|
|
696
|
+
], {
|
|
697
|
+
// The app-owned, read-only MemoryRecall endpoint is part of every configured
|
|
698
|
+
// memory tier. Preserve only this exact extension under an authenticated
|
|
699
|
+
// request override; arbitrary caller/action MCP extensions remain excluded.
|
|
700
|
+
preserveMcpServersUnderOverride: memoryRecall === undefined ? [] : [memoryRecall],
|
|
701
|
+
});
|
|
702
|
+
const clearSessionsRuntimeOptionsForRequest = createClearSessionsRuntimeExtension(composedRuntimeOptionsForRequest, clearSessionsBoundaryOptions);
|
|
703
|
+
const runtimeOptionsForRequest = createProcessJobsRuntimeExtension({
|
|
704
|
+
next: clearSessionsRuntimeOptionsForRequest,
|
|
705
|
+
ownership,
|
|
706
|
+
registry: processJobsRegistry,
|
|
707
|
+
service: internalHooks.processJobs?.service,
|
|
708
|
+
coreConfig: config,
|
|
709
|
+
baseModel: model,
|
|
710
|
+
channelId: internalHooks.processJobs?.channelId,
|
|
711
|
+
sandboxEngine,
|
|
712
|
+
protectionPosture: processJobsProtectionPosture,
|
|
713
|
+
routesOnlyPiNative: internalHooks.processJobs?.routesOnlyPiNative
|
|
714
|
+
?? (() => configuredRoutesOnlyPiNative(config, model)),
|
|
715
|
+
});
|
|
716
|
+
const subagents = subagentsRuntimeOptions(config, {
|
|
717
|
+
runtime,
|
|
718
|
+
baseModel: model,
|
|
719
|
+
baseExecutionMode: executionMode,
|
|
720
|
+
processJobsProtectionPosture,
|
|
721
|
+
...(options.runtimeForModel === undefined ? {} : { runtimeForModel: options.runtimeForModel }),
|
|
722
|
+
});
|
|
723
|
+
const runtimeOptions = mergeStaticRuntimeOptions(runtimeOptionsForLocalProvider(model, config.providers?.local), configRuntimeFlags(config), sandboxEngine === undefined ? undefined : { sandboxEngine }, subagents, options.runtimeOptions);
|
|
724
|
+
const sessionOptions = {
|
|
725
|
+
mode: config.runtime.session.mode,
|
|
726
|
+
idleTimeoutMs: config.runtime.session.idleTimeoutMs,
|
|
727
|
+
// Any fallback makes the logical run stateless. A provider-owned session
|
|
728
|
+
// cannot safely cross the route boundary, even when both bridges happen to
|
|
729
|
+
// expose resume support. History replay remains available to every attempt.
|
|
730
|
+
supportsResume: hasConfiguredFallback(config)
|
|
731
|
+
? false
|
|
732
|
+
: supportsSessionResume(model, executionMode),
|
|
733
|
+
...(config.runtime.session.isolateProactive === undefined
|
|
734
|
+
? {}
|
|
735
|
+
: { isolateProactive: config.runtime.session.isolateProactive }),
|
|
736
|
+
...(options.onSessionEvent === undefined ? {} : { onSessionEvent: options.onSessionEvent }),
|
|
737
|
+
};
|
|
738
|
+
const piSessionsRoot = config.providers?.piNative?.piSessionsRoot;
|
|
739
|
+
const retireDurableSession = runtime.retireDurableSession?.bind(runtime);
|
|
740
|
+
const historyRoot = artifactDerivedRoots.history;
|
|
741
|
+
const baseHistoryStore = options.historyStore ?? createDurableHistoryStore({
|
|
742
|
+
root: historyRoot,
|
|
743
|
+
maxMessages: DEFAULT_HISTORY_MAX_MESSAGES,
|
|
744
|
+
...(piSessionsRoot === undefined || retireDurableSession === undefined
|
|
486
745
|
? {}
|
|
487
|
-
: {
|
|
746
|
+
: {
|
|
747
|
+
retireProviderSession: async (providerSessionId) => {
|
|
748
|
+
await retireDurableSession(providerSessionId, piSessionsRoot);
|
|
749
|
+
},
|
|
750
|
+
}),
|
|
488
751
|
});
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
//
|
|
494
|
-
//
|
|
495
|
-
//
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
},
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
752
|
+
const historyStore = internalHooks.wrapHistoryStore?.(baseHistoryStore) ?? baseHistoryStore;
|
|
753
|
+
const rollover = internalHooks.sessionRollover ?? config.runtime.session.rollover;
|
|
754
|
+
// Conversation history and managed-tool history are distinct contracts. A
|
|
755
|
+
// caller-supplied message store remains the sole message-history owner, while
|
|
756
|
+
// the configured app keeps its independent lifecycle sidecar and
|
|
757
|
+
// SessionHistory capability. Acquisition stays lazy so tool-free runs do not
|
|
758
|
+
// create either the sidecar or its owner database.
|
|
759
|
+
const toolHistory = lazyConfiguredToolHistory({
|
|
760
|
+
root: historyRoot,
|
|
761
|
+
artifactRoot: resolvePath(config.artifacts.dir, "tool-output"),
|
|
762
|
+
rollover,
|
|
763
|
+
...(options.onToolHistoryWarning === undefined
|
|
764
|
+
? {}
|
|
765
|
+
: { onWarning: options.onToolHistoryWarning }),
|
|
766
|
+
});
|
|
767
|
+
try {
|
|
768
|
+
const harness = createAgentHarness({
|
|
769
|
+
identityPath: config.context.identityPath,
|
|
770
|
+
...(config.context.soulPath === undefined ? {} : { soulPath: config.context.soulPath }),
|
|
771
|
+
...(config.context.skillsRoot === undefined ? {} : { skillsRoot: config.context.skillsRoot }),
|
|
772
|
+
...(config.context.skillMaxBytes === undefined ? {} : { skillMaxBytes: config.context.skillMaxBytes }),
|
|
773
|
+
...(config.context.skillDisclosure === undefined ? {} : { skillDisclosure: config.context.skillDisclosure }),
|
|
774
|
+
selectedSkills: config.context.selectedSkills,
|
|
775
|
+
runtime,
|
|
776
|
+
model,
|
|
777
|
+
executionMode,
|
|
778
|
+
cwd: config.runtime.workspace,
|
|
779
|
+
...(config.runtime.effort === undefined ? {} : { effort: config.runtime.effort }),
|
|
780
|
+
...(config.runtime.maxTurns === undefined ? {} : { maxTurns: config.runtime.maxTurns }),
|
|
781
|
+
...(config.providers?.piNative?.piSessionsRoot === undefined
|
|
782
|
+
? {}
|
|
783
|
+
: { piSessionsRoot: config.providers.piNative.piSessionsRoot }),
|
|
784
|
+
session: sessionOptions,
|
|
785
|
+
...(config.concurrency?.maxConcurrentRuns === undefined && config.concurrency?.maxPendingRuns === undefined
|
|
786
|
+
? {}
|
|
787
|
+
: {
|
|
788
|
+
concurrency: {
|
|
789
|
+
...(config.concurrency?.maxConcurrentRuns === undefined
|
|
790
|
+
? {}
|
|
791
|
+
: { maxConcurrentRuns: config.concurrency.maxConcurrentRuns }),
|
|
792
|
+
...(config.concurrency?.maxPendingRuns === undefined
|
|
793
|
+
? {}
|
|
794
|
+
: { maxPendingRuns: config.concurrency.maxPendingRuns }),
|
|
795
|
+
},
|
|
796
|
+
}),
|
|
797
|
+
runtimeOptions,
|
|
798
|
+
...(runtimeOptionsForRequest === undefined
|
|
799
|
+
? {}
|
|
800
|
+
: { runtimeOptionsForRequest }),
|
|
801
|
+
...(config.tools.mcpRequestContextServers === undefined
|
|
802
|
+
? {}
|
|
803
|
+
: {
|
|
804
|
+
mcpRequestContext: {
|
|
805
|
+
serverNames: config.tools.mcpRequestContextServers,
|
|
806
|
+
runOutputRoot: artifactDerivedRoots.outbound,
|
|
807
|
+
...(options.progressCapabilityIssuer === undefined
|
|
808
|
+
? {}
|
|
809
|
+
: { progressCapabilityIssuer: options.progressCapabilityIssuer }),
|
|
810
|
+
},
|
|
811
|
+
}),
|
|
812
|
+
...(config.tools.continuationServers === undefined || options.continuationCapabilityIssuer === undefined
|
|
813
|
+
? {}
|
|
814
|
+
: {
|
|
815
|
+
continuationContext: {
|
|
816
|
+
serverNames: config.tools.continuationServers,
|
|
817
|
+
capabilityIssuer: options.continuationCapabilityIssuer,
|
|
818
|
+
},
|
|
819
|
+
}),
|
|
820
|
+
...(options.runtimeForModel === undefined ? {} : { runtimeForModel: options.runtimeForModel }),
|
|
821
|
+
...(memory === undefined ? {} : { memory }),
|
|
822
|
+
memoryWriteMode: config.memory?.writeMode ?? "disabled",
|
|
823
|
+
...(options.onMemoryWarning === undefined ? {} : { onMemoryWarning: options.onMemoryWarning }),
|
|
824
|
+
historyStore,
|
|
825
|
+
toolHistory,
|
|
826
|
+
...(options.turnHistoryEnricher === undefined ? {} : { turnHistoryEnricher: options.turnHistoryEnricher }),
|
|
827
|
+
// Inbound channel attachments are saved here (under the artifacts dir, which
|
|
828
|
+
// sits inside a sandbox-readable root) so the agent can open them by path.
|
|
829
|
+
attachmentsDir: artifactDerivedRoots.attachments,
|
|
830
|
+
toolPolicy: createToolPolicy(toolPolicyInput(config)),
|
|
831
|
+
...(harnessSandboxPolicy === undefined ? {} : { sandboxPolicy: harnessSandboxPolicy }),
|
|
832
|
+
recorderFactory: ({ runId, conversationId, userInput, source, sourceDetail, isolated }) => composeRunRecorder(recorderCompositionDeps(config, options, internalHooks), {
|
|
833
|
+
runId,
|
|
834
|
+
conversationId,
|
|
835
|
+
runKind: "channel",
|
|
836
|
+
...(isolated === undefined ? {} : { isolated }),
|
|
837
|
+
...(userInput === undefined ? {} : { userInput }),
|
|
838
|
+
...(source === undefined ? {} : { source }),
|
|
839
|
+
...(sourceDetail === undefined ? {} : { sourceDetail }),
|
|
840
|
+
}),
|
|
841
|
+
...(options.createRunId === undefined ? {} : { createRunId: options.createRunId }),
|
|
842
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
843
|
+
});
|
|
844
|
+
ownershipTransferred = true;
|
|
845
|
+
return harnessWithAgentRootOwnership(harness, ownership);
|
|
846
|
+
}
|
|
847
|
+
catch (error) {
|
|
848
|
+
await toolHistory?.release?.().catch(() => undefined);
|
|
849
|
+
throw error;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
finally {
|
|
853
|
+
if (!ownershipTransferred) {
|
|
854
|
+
await releaseAgentRootOwnershipWhenIdle(ownership).catch(() => undefined);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
function harnessWithAgentRootOwnership(harness, ownership) {
|
|
859
|
+
let disposePromise;
|
|
860
|
+
return {
|
|
861
|
+
run: harness.run.bind(harness),
|
|
862
|
+
...(harness.submit === undefined ? {} : { submit: harness.submit.bind(harness) }),
|
|
863
|
+
...(harness.offerLiveInput === undefined
|
|
564
864
|
? {}
|
|
565
|
-
: {
|
|
566
|
-
...(
|
|
865
|
+
: { offerLiveInput: harness.offerLiveInput.bind(harness) }),
|
|
866
|
+
...(harness.cancel === undefined ? {} : { cancel: harness.cancel.bind(harness) }),
|
|
867
|
+
...(harness.resetConversation === undefined
|
|
567
868
|
? {}
|
|
568
|
-
: {
|
|
569
|
-
|
|
570
|
-
serverNames: config.tools.mcpRequestContextServers,
|
|
571
|
-
runOutputRoot: resolvePath(config.artifacts.dir, "outbound"),
|
|
572
|
-
...(options.progressCapabilityIssuer === undefined
|
|
573
|
-
? {}
|
|
574
|
-
: { progressCapabilityIssuer: options.progressCapabilityIssuer }),
|
|
575
|
-
},
|
|
576
|
-
}),
|
|
577
|
-
...(config.tools.continuationServers === undefined || options.continuationCapabilityIssuer === undefined
|
|
869
|
+
: { resetConversation: harness.resetConversation.bind(harness) }),
|
|
870
|
+
...(harness.appendVerbatimTurn === undefined
|
|
578
871
|
? {}
|
|
579
|
-
: {
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
872
|
+
: { appendVerbatimTurn: harness.appendVerbatimTurn.bind(harness) }),
|
|
873
|
+
dispose: () => {
|
|
874
|
+
disposePromise ??= Promise.resolve()
|
|
875
|
+
.then(async () => await harness.dispose?.())
|
|
876
|
+
.finally(async () => {
|
|
877
|
+
await releaseAgentRootOwnershipWhenIdle(ownership);
|
|
878
|
+
});
|
|
879
|
+
return disposePromise;
|
|
880
|
+
},
|
|
881
|
+
};
|
|
882
|
+
}
|
|
883
|
+
const TOOL_HISTORY_ACQUISITION_FAILURE_BACKOFF_MS = 30_000;
|
|
884
|
+
const TOOL_HISTORY_ACQUISITION_FAILURE_BACKOFF_MAX_MS = 5 * 60_000;
|
|
885
|
+
export function lazyConfiguredToolHistory(options) {
|
|
886
|
+
const failureBackoffMs = options.acquisitionFailureBackoffMs
|
|
887
|
+
?? TOOL_HISTORY_ACQUISITION_FAILURE_BACKOFF_MS;
|
|
888
|
+
if (!Number.isSafeInteger(failureBackoffMs) || failureBackoffMs < 1) {
|
|
889
|
+
throw new TypeError("tool history acquisition failure backoff must be a positive integer.");
|
|
890
|
+
}
|
|
891
|
+
const failureBackoffMaxMs = options.acquisitionFailureBackoffMaxMs
|
|
892
|
+
?? Math.max(TOOL_HISTORY_ACQUISITION_FAILURE_BACKOFF_MAX_MS, failureBackoffMs);
|
|
893
|
+
if (!Number.isSafeInteger(failureBackoffMaxMs)
|
|
894
|
+
|| failureBackoffMaxMs < failureBackoffMs) {
|
|
895
|
+
throw new TypeError("tool history acquisition failure backoff maximum must be an integer at least as large as the initial backoff.");
|
|
896
|
+
}
|
|
897
|
+
const now = options.now ?? Date.now;
|
|
898
|
+
let sharedAttempt;
|
|
899
|
+
let latestTurnGeneration = 0;
|
|
900
|
+
const turnStates = new Map();
|
|
901
|
+
let resetTail = Promise.resolve();
|
|
902
|
+
let retirementTail = Promise.resolve();
|
|
903
|
+
let acquisitionOutage = false;
|
|
904
|
+
let consecutiveAcquisitionFailures = 0;
|
|
905
|
+
const reader = new ToolHistoryReader(options.root);
|
|
906
|
+
const warn = (message) => {
|
|
907
|
+
try {
|
|
908
|
+
options.onWarning?.(message);
|
|
909
|
+
}
|
|
910
|
+
catch { /* diagnostics are best-effort */ }
|
|
911
|
+
};
|
|
912
|
+
const turnKey = (conversationId, runId) => JSON.stringify([conversationId, runId]);
|
|
913
|
+
const stateFor = (conversationId, runId) => {
|
|
914
|
+
const key = turnKey(conversationId, runId);
|
|
915
|
+
const existing = turnStates.get(key);
|
|
916
|
+
if (existing !== undefined)
|
|
917
|
+
return existing;
|
|
918
|
+
const state = { generation: ++latestTurnGeneration };
|
|
919
|
+
if (sharedAttempt?.failed === true
|
|
920
|
+
&& sharedAttempt.retryAtMs !== undefined
|
|
921
|
+
&& now() < sharedAttempt.retryAtMs) {
|
|
922
|
+
state.attempt = sharedAttempt;
|
|
923
|
+
}
|
|
924
|
+
turnStates.set(key, state);
|
|
925
|
+
return state;
|
|
926
|
+
};
|
|
927
|
+
const failedPromise = (code) => {
|
|
928
|
+
const error = Object.assign(new Error("Tool history writer became unavailable; a fresh boundary must reacquire it."), { code });
|
|
929
|
+
const failure = Promise.reject(error);
|
|
930
|
+
void failure.catch(() => undefined);
|
|
931
|
+
return failure;
|
|
932
|
+
};
|
|
933
|
+
const nextFailureBackoffMs = () => {
|
|
934
|
+
let backoffMs = failureBackoffMs;
|
|
935
|
+
for (let index = 0; index < consecutiveAcquisitionFailures && backoffMs < failureBackoffMaxMs; index += 1) {
|
|
936
|
+
backoffMs = backoffMs > Math.floor(failureBackoffMaxMs / 2)
|
|
937
|
+
? failureBackoffMaxMs
|
|
938
|
+
: Math.min(failureBackoffMaxMs, backoffMs * 2);
|
|
939
|
+
}
|
|
940
|
+
consecutiveAcquisitionFailures += 1;
|
|
941
|
+
return backoffMs;
|
|
942
|
+
};
|
|
943
|
+
const retire = (attempt) => {
|
|
944
|
+
if (attempt.retired || attempt.handle === undefined)
|
|
945
|
+
return;
|
|
946
|
+
attempt.retired = true;
|
|
947
|
+
retirementTail = retirementTail.then(async () => {
|
|
948
|
+
try {
|
|
949
|
+
await attempt.handle?.release();
|
|
950
|
+
}
|
|
951
|
+
catch { /* replacement acquisition must remain armed */ }
|
|
952
|
+
});
|
|
953
|
+
};
|
|
954
|
+
const latchExistingTurns = (attempt, failure) => {
|
|
955
|
+
const failedThrough = latestTurnGeneration;
|
|
956
|
+
for (const state of turnStates.values()) {
|
|
957
|
+
if (state.generation > failedThrough)
|
|
958
|
+
continue;
|
|
959
|
+
if (state.attempt === undefined || state.attempt === attempt)
|
|
960
|
+
state.failure = failure;
|
|
961
|
+
}
|
|
962
|
+
};
|
|
963
|
+
const invalidate = (attempt, code) => {
|
|
964
|
+
if (attempt.failed)
|
|
965
|
+
return attempt.failurePromise ?? attempt.promise;
|
|
966
|
+
const failure = failedPromise(code);
|
|
967
|
+
attempt.failed = true;
|
|
968
|
+
attempt.failurePromise = failure;
|
|
969
|
+
attempt.retryAtMs = now() + nextFailureBackoffMs();
|
|
970
|
+
latchExistingTurns(attempt, failure);
|
|
971
|
+
retire(attempt);
|
|
972
|
+
if (sharedAttempt === attempt) {
|
|
973
|
+
sharedAttempt = {
|
|
974
|
+
promise: failure,
|
|
975
|
+
failurePromise: failure,
|
|
976
|
+
failed: true,
|
|
977
|
+
retryAtMs: attempt.retryAtMs,
|
|
978
|
+
retired: true,
|
|
979
|
+
};
|
|
980
|
+
}
|
|
981
|
+
acquisitionOutage = true;
|
|
982
|
+
return failure;
|
|
983
|
+
};
|
|
984
|
+
const startAttempt = () => {
|
|
985
|
+
const acquisition = retirementTail.then(async () => await (options.acquireWriter ?? acquireToolHistoryWriter)({
|
|
986
|
+
root: options.root,
|
|
987
|
+
artifactRoot: options.artifactRoot,
|
|
988
|
+
...(options.onWarning === undefined ? {} : { onWarning: options.onWarning }),
|
|
989
|
+
}));
|
|
990
|
+
const attempt = {
|
|
991
|
+
promise: acquisition,
|
|
992
|
+
failed: false,
|
|
993
|
+
retired: false,
|
|
994
|
+
};
|
|
995
|
+
attempt.promise = acquisition.then((handle) => {
|
|
996
|
+
attempt.handle = handle;
|
|
997
|
+
consecutiveAcquisitionFailures = 0;
|
|
998
|
+
if (acquisitionOutage) {
|
|
999
|
+
warn("Tool history writer acquisition recovered; lifecycle persistence resumed.");
|
|
1000
|
+
}
|
|
1001
|
+
acquisitionOutage = false;
|
|
1002
|
+
return handle;
|
|
1003
|
+
}).catch((error) => {
|
|
1004
|
+
attempt.failed = true;
|
|
1005
|
+
attempt.failurePromise = attempt.promise;
|
|
1006
|
+
const retryBackoffMs = nextFailureBackoffMs();
|
|
1007
|
+
attempt.retryAtMs = now() + retryBackoffMs;
|
|
1008
|
+
latchExistingTurns(attempt, attempt.promise);
|
|
1009
|
+
if (!acquisitionOutage) {
|
|
1010
|
+
acquisitionOutage = true;
|
|
1011
|
+
warn(`Tool history writer acquisition failed (${toolHistoryAcquisitionErrorCode(error)}); new turns fail fast for ${String(retryBackoffMs)} ms and repeated failures back off to ${String(failureBackoffMaxMs)} ms, while explicit reset may retry immediately.`);
|
|
1012
|
+
}
|
|
1013
|
+
throw error;
|
|
1014
|
+
});
|
|
1015
|
+
void attempt.promise.catch(() => undefined);
|
|
1016
|
+
sharedAttempt = attempt;
|
|
1017
|
+
return attempt;
|
|
1018
|
+
};
|
|
1019
|
+
const selectAttempt = (bypassFailureBackoff) => {
|
|
1020
|
+
if (sharedAttempt !== undefined) {
|
|
1021
|
+
if (sharedAttempt.handle?.writer.isClosed === true) {
|
|
1022
|
+
invalidate(sharedAttempt, "history_writer_closed");
|
|
1023
|
+
}
|
|
1024
|
+
const withinFailureBackoff = sharedAttempt.retryAtMs !== undefined
|
|
1025
|
+
&& now() < sharedAttempt.retryAtMs;
|
|
1026
|
+
if (!sharedAttempt.failed
|
|
1027
|
+
|| (!bypassFailureBackoff && withinFailureBackoff)) {
|
|
1028
|
+
return sharedAttempt;
|
|
1029
|
+
}
|
|
1030
|
+
sharedAttempt = undefined;
|
|
1031
|
+
}
|
|
1032
|
+
return startAttempt();
|
|
1033
|
+
};
|
|
1034
|
+
const acquireForTurn = async (state) => {
|
|
1035
|
+
if (state.failure !== undefined)
|
|
1036
|
+
return await state.failure;
|
|
1037
|
+
state.attempt ??= selectAttempt(false);
|
|
1038
|
+
const handle = await state.attempt.promise;
|
|
1039
|
+
if (handle.writer.isClosed) {
|
|
1040
|
+
state.failure = invalidate(state.attempt, "history_writer_closed");
|
|
1041
|
+
return await state.failure;
|
|
1042
|
+
}
|
|
1043
|
+
return handle;
|
|
1044
|
+
};
|
|
1045
|
+
const writer = {
|
|
1046
|
+
createSink(binding) {
|
|
1047
|
+
const state = stateFor(binding.conversationId, binding.runId);
|
|
1048
|
+
return async (event) => {
|
|
1049
|
+
const handle = await acquireForTurn(state);
|
|
1050
|
+
try {
|
|
1051
|
+
const result = await handle.writer.persist(binding, event);
|
|
1052
|
+
const terminalCode = terminalToolHistoryWriterFailureCode(result, handle);
|
|
1053
|
+
if (terminalCode !== undefined && state.attempt !== undefined) {
|
|
1054
|
+
state.failure = invalidate(state.attempt, terminalCode);
|
|
1055
|
+
}
|
|
1056
|
+
return result;
|
|
1057
|
+
}
|
|
1058
|
+
catch (error) {
|
|
1059
|
+
const terminalCode = terminalToolHistoryWriterFailureCode(error, handle);
|
|
1060
|
+
if (terminalCode !== undefined && state.attempt !== undefined) {
|
|
1061
|
+
state.failure = invalidate(state.attempt, terminalCode);
|
|
1062
|
+
}
|
|
1063
|
+
throw error;
|
|
1064
|
+
}
|
|
1065
|
+
};
|
|
1066
|
+
},
|
|
1067
|
+
async finishRun(binding, status, failureKind) {
|
|
1068
|
+
const key = turnKey(binding.conversationId, binding.runId);
|
|
1069
|
+
const state = turnStates.get(key);
|
|
1070
|
+
try {
|
|
1071
|
+
if (state?.attempt === undefined || state.failure !== undefined)
|
|
1072
|
+
return;
|
|
1073
|
+
const handle = await state.attempt.promise.catch(() => undefined);
|
|
1074
|
+
try {
|
|
1075
|
+
await handle?.writer.finishRun(binding, status, failureKind);
|
|
1076
|
+
}
|
|
1077
|
+
catch (error) {
|
|
1078
|
+
if (handle === undefined)
|
|
1079
|
+
return;
|
|
1080
|
+
const terminalCode = terminalToolHistoryWriterFailureCode(error, handle);
|
|
1081
|
+
if (terminalCode === undefined)
|
|
1082
|
+
throw error;
|
|
1083
|
+
invalidate(state.attempt, terminalCode);
|
|
1084
|
+
return;
|
|
1085
|
+
}
|
|
1086
|
+
const terminalCode = handle === undefined
|
|
1087
|
+
? undefined
|
|
1088
|
+
: terminalToolHistoryWriterFailureCode(undefined, handle);
|
|
1089
|
+
if (terminalCode !== undefined)
|
|
1090
|
+
invalidate(state.attempt, terminalCode);
|
|
1091
|
+
}
|
|
1092
|
+
finally {
|
|
1093
|
+
turnStates.delete(key);
|
|
1094
|
+
}
|
|
1095
|
+
},
|
|
1096
|
+
async resetConversation(logicalConversationId) {
|
|
1097
|
+
const reset = resetTail.then(async () => {
|
|
1098
|
+
if (!await reader.exists())
|
|
1099
|
+
return;
|
|
1100
|
+
// Reset is serialized and host-explicit, so it may bypass only the
|
|
1101
|
+
// progressive post-failure cooldown. It still reuses a healthy/pending handle
|
|
1102
|
+
// and every fresh acquisition keeps the full restart-handoff ceiling.
|
|
1103
|
+
const observedAttempt = sharedAttempt;
|
|
1104
|
+
if (observedAttempt !== undefined && !observedAttempt.failed) {
|
|
1105
|
+
await observedAttempt.promise.catch(() => undefined);
|
|
1106
|
+
}
|
|
1107
|
+
let recoveryRetriesRemaining = 1;
|
|
1108
|
+
for (;;) {
|
|
1109
|
+
const attempt = selectAttempt(true);
|
|
1110
|
+
const handle = await attempt.promise;
|
|
1111
|
+
try {
|
|
1112
|
+
await handle.writer.resetConversation(logicalConversationId);
|
|
1113
|
+
}
|
|
1114
|
+
catch (error) {
|
|
1115
|
+
const terminalCode = reportedToolHistoryWriterFailureCode(error);
|
|
1116
|
+
if (terminalCode === undefined) {
|
|
1117
|
+
if (handle.writer.isClosed)
|
|
1118
|
+
invalidate(attempt, "history_writer_closed");
|
|
1119
|
+
throw error;
|
|
1120
|
+
}
|
|
1121
|
+
invalidate(attempt, terminalCode);
|
|
1122
|
+
if (recoveryRetriesRemaining === 0)
|
|
1123
|
+
throw error;
|
|
1124
|
+
recoveryRetriesRemaining -= 1;
|
|
1125
|
+
continue;
|
|
1126
|
+
}
|
|
1127
|
+
const terminalCode = terminalToolHistoryWriterFailureCode(undefined, handle);
|
|
1128
|
+
if (terminalCode !== undefined)
|
|
1129
|
+
invalidate(attempt, terminalCode);
|
|
1130
|
+
// A resolved reset was acknowledged only after its transaction
|
|
1131
|
+
// committed. Retire a concurrently closed handle, but never open a
|
|
1132
|
+
// second destructive reset window for an operation that succeeded.
|
|
1133
|
+
return;
|
|
1134
|
+
}
|
|
1135
|
+
});
|
|
1136
|
+
resetTail = reset.then(() => undefined, () => undefined);
|
|
1137
|
+
await reset;
|
|
1138
|
+
},
|
|
1139
|
+
};
|
|
1140
|
+
return {
|
|
1141
|
+
writer,
|
|
1142
|
+
reader,
|
|
1143
|
+
logicalConversationId: (conversationId) => toolHistoryLogicalConversationId(conversationId, options.rollover),
|
|
1144
|
+
async release() {
|
|
1145
|
+
const attempt = sharedAttempt;
|
|
1146
|
+
sharedAttempt = undefined;
|
|
1147
|
+
if (attempt !== undefined) {
|
|
1148
|
+
await attempt.promise.catch(() => undefined);
|
|
1149
|
+
retire(attempt);
|
|
1150
|
+
}
|
|
1151
|
+
await retirementTail;
|
|
1152
|
+
},
|
|
1153
|
+
};
|
|
1154
|
+
}
|
|
1155
|
+
function terminalToolHistoryWriterFailureCode(value, handle) {
|
|
1156
|
+
return reportedToolHistoryWriterFailureCode(value)
|
|
1157
|
+
?? (handle.writer.isClosed ? "history_writer_closed" : undefined);
|
|
1158
|
+
}
|
|
1159
|
+
function reportedToolHistoryWriterFailureCode(value) {
|
|
1160
|
+
const candidate = typeof value === "object" && value !== null
|
|
1161
|
+
? "errorCode" in value
|
|
1162
|
+
? value.errorCode
|
|
1163
|
+
: "code" in value
|
|
1164
|
+
? value.code
|
|
1165
|
+
: undefined
|
|
1166
|
+
: undefined;
|
|
1167
|
+
if (candidate === "history_writer_closed")
|
|
1168
|
+
return candidate;
|
|
1169
|
+
return undefined;
|
|
1170
|
+
}
|
|
1171
|
+
function toolHistoryAcquisitionErrorCode(error) {
|
|
1172
|
+
const candidate = typeof error === "object" && error !== null && "code" in error
|
|
1173
|
+
? error.code
|
|
1174
|
+
: undefined;
|
|
1175
|
+
return typeof candidate === "string" && /^history_[a-z0-9_]+$/u.test(candidate)
|
|
1176
|
+
? candidate
|
|
1177
|
+
: "history_writer_unavailable";
|
|
608
1178
|
}
|
|
609
1179
|
function configuredMemoryForHarness(config, memory) {
|
|
610
1180
|
if (memory instanceof MemoryRetrievalService || config.memory === undefined || !isSharedRecallStore(memory)) {
|
|
@@ -654,6 +1224,13 @@ function supportsSessionResume(model, executionMode) {
|
|
|
654
1224
|
// provider default (30s). The harness degrades recall to empty on timeout.
|
|
655
1225
|
const DEFAULT_EMBEDDINGS_TIMEOUT_MS = 10_000;
|
|
656
1226
|
export async function createConfiguredMemory(config, deps = {}) {
|
|
1227
|
+
return await createConfiguredMemoryInternal(config, deps);
|
|
1228
|
+
}
|
|
1229
|
+
/** @internal App-only unsafe authority; deliberately absent from the package root. */
|
|
1230
|
+
export async function createConfiguredMemoryForApp(config, deps, protectionPosture) {
|
|
1231
|
+
return await createConfiguredMemoryInternal(config, deps, protectionPosture);
|
|
1232
|
+
}
|
|
1233
|
+
async function createConfiguredMemoryInternal(config, deps, protectionPosture) {
|
|
657
1234
|
if (config.memory === undefined) {
|
|
658
1235
|
return undefined;
|
|
659
1236
|
}
|
|
@@ -705,7 +1282,7 @@ export async function createConfiguredMemory(config, deps = {}) {
|
|
|
705
1282
|
throw new Error(`memory.embeddings.apiKeyEnv ${embeddingsConfig.apiKeyEnv} is declared but has no resolved value; ` +
|
|
706
1283
|
`set ${embeddingsConfig.apiKeyEnv} before starting managed memory.`);
|
|
707
1284
|
}
|
|
708
|
-
const embeddings = search.createCircuitBreakerEmbeddingProvider(search.createEmbeddingProvider({
|
|
1285
|
+
const embeddings = wrapOwnedDirectEmbeddingProvider(search.createCircuitBreakerEmbeddingProvider(search.createEmbeddingProvider({
|
|
709
1286
|
provider: embeddingsConfig?.provider ?? "ollama",
|
|
710
1287
|
model: embeddingsConfig?.model ?? "nomic-embed-text:v1.5",
|
|
711
1288
|
...(embeddingsConfig?.endpoint !== undefined && { endpoint: embeddingsConfig.endpoint }),
|
|
@@ -718,7 +1295,7 @@ export async function createConfiguredMemory(config, deps = {}) {
|
|
|
718
1295
|
...(embeddingsConfig?.circuitBreaker?.cooldownMs !== undefined && {
|
|
719
1296
|
cooldownMs: embeddingsConfig.circuitBreaker.cooldownMs,
|
|
720
1297
|
}),
|
|
721
|
-
});
|
|
1298
|
+
}), config, deps.cwd ?? process.cwd(), protectionPosture);
|
|
722
1299
|
const dim = embeddingsConfig?.dim ?? 768;
|
|
723
1300
|
if (mode === "journal") {
|
|
724
1301
|
if (embeddingsConfig === undefined) {
|
|
@@ -746,7 +1323,7 @@ export async function createConfiguredMemory(config, deps = {}) {
|
|
|
746
1323
|
const recording = deps.observability === undefined
|
|
747
1324
|
? undefined
|
|
748
1325
|
: recorderCompositionDeps(config, deps.observability);
|
|
749
|
-
const llm = configuredMemoryLlm(bujo, config, llmConfig, deps.memoryRuntime, recording);
|
|
1326
|
+
const llm = configuredMemoryLlm(bujo, config, llmConfig, deps.memoryRuntime, recording, deps.cwd ?? process.cwd(), protectionPosture);
|
|
750
1327
|
if (llm === undefined) {
|
|
751
1328
|
throw new Error("memory.mode 'bujo' could not construct the required memory.llm.");
|
|
752
1329
|
}
|
|
@@ -773,16 +1350,16 @@ function configuredMemoryLlm(bujo, config, llmConfig,
|
|
|
773
1350
|
// Explicit memory-LLM runtime (tests). MUST be fallback-chain-free — see the
|
|
774
1351
|
// `memoryRuntime` doc on createConfiguredMemory. When undefined the memory LLM
|
|
775
1352
|
// builds its own fallback-free runtime so the per-call memory model is primary.
|
|
776
|
-
memoryRuntimeOverride, recording) {
|
|
1353
|
+
memoryRuntimeOverride, recording, agentRoot, protectionPosture) {
|
|
777
1354
|
if (llmConfig === undefined) {
|
|
778
1355
|
return undefined;
|
|
779
1356
|
}
|
|
780
1357
|
if (llmConfig.provider === "ollama") {
|
|
781
1358
|
// The ollama memory LLM does not ride `runtime.run`, so it is not recorded.
|
|
782
|
-
return bujo.createOllamaLlm({
|
|
1359
|
+
return wrapOwnedDirectMemoryLlm(bujo.createOllamaLlm({
|
|
783
1360
|
model: llmConfig.model,
|
|
784
1361
|
...(llmConfig.endpoint !== undefined && { endpoint: llmConfig.endpoint }),
|
|
785
|
-
});
|
|
1362
|
+
}), config, agentRoot, protectionPosture);
|
|
786
1363
|
}
|
|
787
1364
|
const model = parseMonoRuntimeModelReference(llmConfig.model);
|
|
788
1365
|
const executionMode = llmConfig.executionMode ?? defaultExecutionModeForModel(model);
|
|
@@ -795,7 +1372,7 @@ memoryRuntimeOverride, recording) {
|
|
|
795
1372
|
// channel runtime (which carries the fallback chain whose primary is
|
|
796
1373
|
// `config.runtime.model`) is intentionally NOT reused — see the `memoryRuntime`
|
|
797
1374
|
// doc on createConfiguredMemory.
|
|
798
|
-
const runtime = memoryRuntimeOverride ?? createMonoRuntime(runtimeHostOptionsForConfig(config));
|
|
1375
|
+
const runtime = wrapPerRunOwnedConfiguredRuntime(memoryRuntimeOverride ?? createMonoRuntime(runtimeHostOptionsForConfig(config)), config, agentRoot, protectionPosture);
|
|
799
1376
|
return createAgentHostMemoryLlm({
|
|
800
1377
|
runtime,
|
|
801
1378
|
model,
|
|
@@ -812,6 +1389,113 @@ memoryRuntimeOverride, recording) {
|
|
|
812
1389
|
: {}),
|
|
813
1390
|
});
|
|
814
1391
|
}
|
|
1392
|
+
/**
|
|
1393
|
+
* Memory completion is a model-running surface even when no channel harness is
|
|
1394
|
+
* present. Acquire the canonical-root owner and protection generation for the
|
|
1395
|
+
* exact duration of the provider call; release follows actual runtime
|
|
1396
|
+
* settlement, never its abort signal.
|
|
1397
|
+
*/
|
|
1398
|
+
function wrapPerRunOwnedConfiguredRuntime(runtime, config, agentRoot, protectionPosture) {
|
|
1399
|
+
return {
|
|
1400
|
+
...runtime,
|
|
1401
|
+
async run(systemPrompt, runOptions) {
|
|
1402
|
+
const ownership = await acquireAgentRootOwnership(agentRoot);
|
|
1403
|
+
let requestLease;
|
|
1404
|
+
try {
|
|
1405
|
+
assertAgentRootLeaseOutsideWorkspace(ownership, config.runtime.workspace);
|
|
1406
|
+
const loaded = await loadProcessJobsRootRegistryProtection(ownership.agentRoot, config.runtime.workspace);
|
|
1407
|
+
ownership.coordinator.synchronizeGeneration(loaded.generation);
|
|
1408
|
+
const boundary = await attestProcessJobsRootRegistrySnapshot(loaded, config.runtime.workspace);
|
|
1409
|
+
requestLease = ownership.coordinator.acquireRequestLease(boundary.generation);
|
|
1410
|
+
const attested = await attestProcessJobsRootRegistrySnapshot(boundary, config.runtime.workspace);
|
|
1411
|
+
const protectedRoots = processJobsProtectionPolicyRoots(attested);
|
|
1412
|
+
let effectiveOptions = runOptions;
|
|
1413
|
+
if (protectedRoots.length > 0) {
|
|
1414
|
+
if (runOptions.model.sdk !== "pi")
|
|
1415
|
+
throw new Error(PROCESS_JOBS_PI_NATIVE_REQUIRED_ERROR);
|
|
1416
|
+
if (protectionPosture?.suppressSyntheticSandbox !== true) {
|
|
1417
|
+
const sandboxEngine = runOptions.sandboxEngine ?? createSrtSandboxEngine();
|
|
1418
|
+
if (!await sandboxEngine.isAvailable().catch(() => false)) {
|
|
1419
|
+
throw new Error(PROCESS_JOBS_PROTECTION_UNAVAILABLE_ERROR);
|
|
1420
|
+
}
|
|
1421
|
+
const sandboxPolicy = mergeSandboxPolicies(runOptions.sandboxPolicy, processJobsSandboxPolicy({ coreConfig: config, protectedRoots }));
|
|
1422
|
+
if (sandboxPolicy === undefined) {
|
|
1423
|
+
throw new Error(PROCESS_JOBS_PROTECTION_UNAVAILABLE_ERROR);
|
|
1424
|
+
}
|
|
1425
|
+
effectiveOptions = {
|
|
1426
|
+
...runOptions,
|
|
1427
|
+
sandboxPolicy,
|
|
1428
|
+
sandboxEngine,
|
|
1429
|
+
};
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
return await runtime.run(systemPrompt, effectiveOptions);
|
|
1433
|
+
}
|
|
1434
|
+
finally {
|
|
1435
|
+
requestLease?.releaseAfterSettlement();
|
|
1436
|
+
await releaseAgentRootOwnershipWhenIdle(ownership);
|
|
1437
|
+
}
|
|
1438
|
+
},
|
|
1439
|
+
};
|
|
1440
|
+
}
|
|
1441
|
+
function wrapOwnedDirectMemoryLlm(llm, config, agentRoot, protectionPosture) {
|
|
1442
|
+
return {
|
|
1443
|
+
...llm,
|
|
1444
|
+
async complete(prompt, options) {
|
|
1445
|
+
const ownership = await acquireAgentRootOwnership(agentRoot);
|
|
1446
|
+
let requestLease;
|
|
1447
|
+
try {
|
|
1448
|
+
assertAgentRootLeaseOutsideWorkspace(ownership, config.runtime.workspace);
|
|
1449
|
+
const loaded = await loadProcessJobsRootRegistryProtection(ownership.agentRoot, config.runtime.workspace);
|
|
1450
|
+
ownership.coordinator.synchronizeGeneration(loaded.generation);
|
|
1451
|
+
const boundary = await attestProcessJobsRootRegistrySnapshot(loaded, config.runtime.workspace);
|
|
1452
|
+
requestLease = ownership.coordinator.acquireRequestLease(boundary.generation);
|
|
1453
|
+
const attested = await attestProcessJobsRootRegistrySnapshot(boundary, config.runtime.workspace);
|
|
1454
|
+
if (processJobsProtectionPolicyRoots(attested).length > 0
|
|
1455
|
+
&& protectionPosture?.suppressSyntheticSandbox !== true) {
|
|
1456
|
+
throw new Error(PROCESS_JOBS_PI_NATIVE_REQUIRED_ERROR);
|
|
1457
|
+
}
|
|
1458
|
+
return await llm.complete(prompt, options);
|
|
1459
|
+
}
|
|
1460
|
+
finally {
|
|
1461
|
+
requestLease?.releaseAfterSettlement();
|
|
1462
|
+
await releaseAgentRootOwnershipWhenIdle(ownership);
|
|
1463
|
+
}
|
|
1464
|
+
},
|
|
1465
|
+
};
|
|
1466
|
+
}
|
|
1467
|
+
/**
|
|
1468
|
+
* Configured embedding providers execute outside the channel harness. Hold the
|
|
1469
|
+
* same canonical-root owner and generation lease through the true embed()
|
|
1470
|
+
* settlement, and reject the non-Pi provider before invocation whenever a
|
|
1471
|
+
* retained process-job root makes native SRT confinement mandatory.
|
|
1472
|
+
*/
|
|
1473
|
+
function wrapOwnedDirectEmbeddingProvider(provider, config, agentRoot, protectionPosture) {
|
|
1474
|
+
return {
|
|
1475
|
+
...provider,
|
|
1476
|
+
async embed(texts) {
|
|
1477
|
+
const ownership = await acquireAgentRootOwnership(agentRoot);
|
|
1478
|
+
let requestLease;
|
|
1479
|
+
try {
|
|
1480
|
+
assertAgentRootLeaseOutsideWorkspace(ownership, config.runtime.workspace);
|
|
1481
|
+
const loaded = await loadProcessJobsRootRegistryProtection(ownership.agentRoot, config.runtime.workspace);
|
|
1482
|
+
ownership.coordinator.synchronizeGeneration(loaded.generation);
|
|
1483
|
+
const boundary = await attestProcessJobsRootRegistrySnapshot(loaded, config.runtime.workspace);
|
|
1484
|
+
requestLease = ownership.coordinator.acquireRequestLease(boundary.generation);
|
|
1485
|
+
const attested = await attestProcessJobsRootRegistrySnapshot(boundary, config.runtime.workspace);
|
|
1486
|
+
if (processJobsProtectionPolicyRoots(attested).length > 0
|
|
1487
|
+
&& protectionPosture?.suppressSyntheticSandbox !== true) {
|
|
1488
|
+
throw new Error(PROCESS_JOBS_PI_NATIVE_REQUIRED_ERROR);
|
|
1489
|
+
}
|
|
1490
|
+
return await provider.embed(texts);
|
|
1491
|
+
}
|
|
1492
|
+
finally {
|
|
1493
|
+
requestLease?.releaseAfterSettlement();
|
|
1494
|
+
await releaseAgentRootOwnershipWhenIdle(ownership);
|
|
1495
|
+
}
|
|
1496
|
+
},
|
|
1497
|
+
};
|
|
1498
|
+
}
|
|
815
1499
|
const MEMORY_LLM_SYSTEM_PROMPT = [
|
|
816
1500
|
"You are the private memory maintenance LLM for mono-agent.",
|
|
817
1501
|
"Return only the requested JSON or plain text.",
|