@geminixiang/mikan 1.0.0-beta.21 → 1.0.0-beta.23
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/CHANGELOG.md +55 -0
- package/README.md +12 -8
- package/dist/adapters/discord/bot.d.ts.map +1 -1
- package/dist/adapters/discord/bot.js +13 -14
- package/dist/adapters/discord/bot.js.map +1 -1
- package/dist/adapters/intake.d.ts.map +1 -1
- package/dist/adapters/intake.js +5 -0
- package/dist/adapters/intake.js.map +1 -1
- package/dist/adapters/slack/bot.d.ts.map +1 -1
- package/dist/adapters/slack/bot.js +13 -2
- package/dist/adapters/slack/bot.js.map +1 -1
- package/dist/adapters/slack/types.d.ts +2 -0
- package/dist/adapters/slack/types.d.ts.map +1 -1
- package/dist/adapters/slack/types.js.map +1 -1
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +34 -24
- package/dist/agent.js.map +1 -1
- package/dist/cli/boot.d.ts +1 -1
- package/dist/cli/boot.d.ts.map +1 -1
- package/dist/cli/boot.js +7 -15
- package/dist/cli/boot.js.map +1 -1
- package/dist/commands/login.js +2 -2
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/sandbox.d.ts.map +1 -1
- package/dist/commands/sandbox.js +4 -7
- package/dist/commands/sandbox.js.map +1 -1
- package/dist/commands/text.js +1 -1
- package/dist/commands/text.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +12 -39
- package/dist/config.js.map +1 -1
- package/dist/execution-resolver.d.ts +6 -8
- package/dist/execution-resolver.d.ts.map +1 -1
- package/dist/execution-resolver.js +73 -107
- package/dist/execution-resolver.js.map +1 -1
- package/dist/harness/index.d.ts +1 -1
- package/dist/harness/index.d.ts.map +1 -1
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/runner.d.ts +9 -6
- package/dist/harness/runner.d.ts.map +1 -1
- package/dist/harness/runner.js +42 -20
- package/dist/harness/runner.js.map +1 -1
- package/dist/harness/subagent-runner.d.ts +14 -13
- package/dist/harness/subagent-runner.d.ts.map +1 -1
- package/dist/harness/subagent-runner.js +116 -24
- package/dist/harness/subagent-runner.js.map +1 -1
- package/dist/harness/types.d.ts +14 -0
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/harness/usage.d.ts +6 -0
- package/dist/harness/usage.d.ts.map +1 -0
- package/dist/harness/usage.js +32 -0
- package/dist/harness/usage.js.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.js +19 -87
- package/dist/main.js.map +1 -1
- package/dist/runtime/conversation-runtime.d.ts.map +1 -1
- package/dist/runtime/conversation-runtime.js +23 -79
- package/dist/runtime/conversation-runtime.js.map +1 -1
- package/dist/runtime/session-lifecycle.d.ts +19 -0
- package/dist/runtime/session-lifecycle.d.ts.map +1 -0
- package/dist/runtime/session-lifecycle.js +76 -0
- package/dist/runtime/session-lifecycle.js.map +1 -0
- package/dist/runtime/types.d.ts +5 -0
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/types.js.map +1 -1
- package/dist/sandbox/agent-sandbox.d.ts +18 -0
- package/dist/sandbox/agent-sandbox.d.ts.map +1 -0
- package/dist/sandbox/agent-sandbox.js +234 -0
- package/dist/sandbox/agent-sandbox.js.map +1 -0
- package/dist/sandbox/cloudflare.d.ts.map +1 -1
- package/dist/sandbox/cloudflare.js +1 -0
- package/dist/sandbox/cloudflare.js.map +1 -1
- package/dist/sandbox/container.d.ts.map +1 -1
- package/dist/sandbox/container.js +1 -0
- package/dist/sandbox/container.js.map +1 -1
- package/dist/sandbox/host.d.ts.map +1 -1
- package/dist/sandbox/host.js +1 -0
- package/dist/sandbox/host.js.map +1 -1
- package/dist/sandbox/identity.d.ts +11 -16
- package/dist/sandbox/identity.d.ts.map +1 -1
- package/dist/sandbox/identity.js +32 -26
- package/dist/sandbox/identity.js.map +1 -1
- package/dist/sandbox/image.d.ts.map +1 -1
- package/dist/sandbox/image.js +1 -0
- package/dist/sandbox/image.js.map +1 -1
- package/dist/sandbox/index.d.ts +7 -7
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/index.js +13 -9
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/types.d.ts +17 -16
- package/dist/sandbox/types.d.ts.map +1 -1
- package/dist/sandbox/types.js.map +1 -1
- package/dist/sessions/session-key.d.ts +9 -0
- package/dist/sessions/session-key.d.ts.map +1 -1
- package/dist/sessions/session-key.js +50 -2
- package/dist/sessions/session-key.js.map +1 -1
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js +36 -8
- package/dist/sessions/store.js.map +1 -1
- package/dist/tools/sandbox.d.ts.map +1 -1
- package/dist/tools/sandbox.js +4 -5
- package/dist/tools/sandbox.js.map +1 -1
- package/dist/tools/subagent-slots.d.ts +3 -3
- package/dist/tools/subagent-slots.d.ts.map +1 -1
- package/dist/tools/subagent-slots.js +25 -10
- package/dist/tools/subagent-slots.js.map +1 -1
- package/dist/tools/subagent.d.ts +13 -2
- package/dist/tools/subagent.d.ts.map +1 -1
- package/dist/tools/subagent.js +16 -16
- package/dist/tools/subagent.js.map +1 -1
- package/dist/types.d.ts +14 -63
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/vault/injection.d.ts +4 -14
- package/dist/vault/injection.d.ts.map +1 -1
- package/dist/vault/injection.js +5 -2
- package/dist/vault/injection.js.map +1 -1
- package/dist/vault/policy.d.ts +3 -3
- package/dist/vault/policy.d.ts.map +1 -1
- package/dist/vault/policy.js +6 -4
- package/dist/vault/policy.js.map +1 -1
- package/dist/vault/types.d.ts +4 -0
- package/dist/vault/types.d.ts.map +1 -1
- package/dist/vault/types.js.map +1 -1
- package/dist/web/admin/portal.js +2 -2
- package/dist/web/admin/portal.js.map +1 -1
- package/dist/workspace-projection/index.d.ts +5 -0
- package/dist/workspace-projection/index.d.ts.map +1 -0
- package/dist/workspace-projection/index.js +71 -0
- package/dist/workspace-projection/index.js.map +1 -0
- package/dist/workspace-projection/types.d.ts +7 -0
- package/dist/workspace-projection/types.d.ts.map +1 -0
- package/dist/workspace-projection/types.js +2 -0
- package/dist/workspace-projection/types.js.map +1 -0
- package/package.json +3 -3
- package/dist/sandbox/firecracker.d.ts +0 -18
- package/dist/sandbox/firecracker.d.ts.map +0 -1
- package/dist/sandbox/firecracker.js +0 -221
- package/dist/sandbox/firecracker.js.map +0 -1
- package/dist/sandbox/gondolin-bootstrap.d.ts +0 -26
- package/dist/sandbox/gondolin-bootstrap.d.ts.map +0 -1
- package/dist/sandbox/gondolin-bootstrap.js +0 -27
- package/dist/sandbox/gondolin-bootstrap.js.map +0 -1
- package/dist/sandbox/gondolin-contract.d.ts +0 -125
- package/dist/sandbox/gondolin-contract.d.ts.map +0 -1
- package/dist/sandbox/gondolin-contract.js +0 -155
- package/dist/sandbox/gondolin-contract.js.map +0 -1
- package/dist/sandbox/gondolin-fleet.d.ts +0 -104
- package/dist/sandbox/gondolin-fleet.d.ts.map +0 -1
- package/dist/sandbox/gondolin-fleet.js +0 -330
- package/dist/sandbox/gondolin-fleet.js.map +0 -1
- package/dist/sandbox/gondolin-gateway.d.ts +0 -86
- package/dist/sandbox/gondolin-gateway.d.ts.map +0 -1
- package/dist/sandbox/gondolin-gateway.js +0 -407
- package/dist/sandbox/gondolin-gateway.js.map +0 -1
- package/dist/sandbox/gondolin-inventory.d.ts +0 -75
- package/dist/sandbox/gondolin-inventory.d.ts.map +0 -1
- package/dist/sandbox/gondolin-inventory.js +0 -257
- package/dist/sandbox/gondolin-inventory.js.map +0 -1
- package/dist/sandbox/gondolin-join.d.ts +0 -62
- package/dist/sandbox/gondolin-join.d.ts.map +0 -1
- package/dist/sandbox/gondolin-join.js +0 -261
- package/dist/sandbox/gondolin-join.js.map +0 -1
- package/dist/sandbox/gondolin-nfs-advisory.d.ts +0 -15
- package/dist/sandbox/gondolin-nfs-advisory.d.ts.map +0 -1
- package/dist/sandbox/gondolin-nfs-advisory.js +0 -60
- package/dist/sandbox/gondolin-nfs-advisory.js.map +0 -1
- package/dist/sandbox/gondolin-placement.d.ts +0 -30
- package/dist/sandbox/gondolin-placement.d.ts.map +0 -1
- package/dist/sandbox/gondolin-placement.js +0 -77
- package/dist/sandbox/gondolin-placement.js.map +0 -1
- package/dist/sandbox/gondolin-recovery.d.ts +0 -33
- package/dist/sandbox/gondolin-recovery.d.ts.map +0 -1
- package/dist/sandbox/gondolin-recovery.js +0 -39
- package/dist/sandbox/gondolin-recovery.js.map +0 -1
- package/dist/sandbox/gondolin-remote.d.ts +0 -70
- package/dist/sandbox/gondolin-remote.d.ts.map +0 -1
- package/dist/sandbox/gondolin-remote.js +0 -325
- package/dist/sandbox/gondolin-remote.js.map +0 -1
- package/dist/sandbox/gondolin-worker-client.d.ts +0 -135
- package/dist/sandbox/gondolin-worker-client.d.ts.map +0 -1
- package/dist/sandbox/gondolin-worker-client.js +0 -323
- package/dist/sandbox/gondolin-worker-client.js.map +0 -1
- package/dist/sandbox/gondolin-worker-main.d.ts +0 -2
- package/dist/sandbox/gondolin-worker-main.d.ts.map +0 -1
- package/dist/sandbox/gondolin-worker-main.js +0 -22
- package/dist/sandbox/gondolin-worker-main.js.map +0 -1
- package/dist/sandbox/gondolin-worker.d.ts +0 -17
- package/dist/sandbox/gondolin-worker.d.ts.map +0 -1
- package/dist/sandbox/gondolin-worker.js +0 -201
- package/dist/sandbox/gondolin-worker.js.map +0 -1
- package/dist/sandbox/gondolin.d.ts +0 -53
- package/dist/sandbox/gondolin.d.ts.map +0 -1
- package/dist/sandbox/gondolin.js +0 -429
- package/dist/sandbox/gondolin.js.map +0 -1
|
@@ -1,83 +1,56 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { ensureDirExists, isRecord, readJsonFileIfExists } from "./utils/file-guards.js";
|
|
1
|
+
import { posix } from "node:path";
|
|
2
|
+
import { loadGlobalSettings } from "./config.js";
|
|
4
3
|
import { DockerContainerManager } from "./provisioner.js";
|
|
5
|
-
import { createExecutor } from "./sandbox/index.js";
|
|
4
|
+
import { createExecutor, getSandboxCredentialCapabilities, } from "./sandbox/index.js";
|
|
6
5
|
import { reportUserFacingError } from "./observability/sentry.js";
|
|
7
6
|
import { normalizeSharedVaultName } from "./vault/index.js";
|
|
8
7
|
import { resolveVaultInjection } from "./vault/injection.js";
|
|
9
8
|
import { allowsAmbientDefaultSharedVault } from "./vault/policy.js";
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
12
|
-
export
|
|
13
|
-
const globalDefault = readGlobalWorkspaceMountMode();
|
|
14
|
-
if (!workspaceDir) {
|
|
15
|
-
return globalDefault;
|
|
16
|
-
}
|
|
17
|
-
const conversationDir = join(workspaceDir, conversationId);
|
|
18
|
-
try {
|
|
19
|
-
return (resolveConversationSettings(conversationDir).sandbox?.image?.workspaceMount ?? globalDefault);
|
|
20
|
-
}
|
|
21
|
-
catch (err) {
|
|
22
|
-
log.logWarning("Falling back while resolving conversation workspace mount", err instanceof Error ? err.message : String(err));
|
|
23
|
-
const raw = readConversationSettingsFallback(conversationSettingsPath(conversationDir));
|
|
24
|
-
return raw?.sandbox?.image?.workspaceMount ?? globalDefault;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
function readGlobalWorkspaceMountMode() {
|
|
28
|
-
try {
|
|
29
|
-
return loadGlobalSettings().sandbox?.image?.workspaceMount ?? "private";
|
|
30
|
-
}
|
|
31
|
-
catch (err) {
|
|
32
|
-
log.logWarning("Using default workspace mount because global settings could not be read", err instanceof Error ? err.message : String(err));
|
|
33
|
-
return "private";
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
function readConversationSettingsFallback(settingsPath) {
|
|
37
|
-
try {
|
|
38
|
-
return readJsonFileIfExists(settingsPath, (value) => isRecord(value), () => "Ignoring malformed conversation settings file while resolving workspace mount");
|
|
39
|
-
}
|
|
40
|
-
catch (err) {
|
|
41
|
-
log.logWarning("Ignoring malformed conversation settings fallback while resolving workspace mount", err instanceof Error ? err.message : String(err));
|
|
42
|
-
return undefined;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
9
|
+
import { credentialAuthorizationKey, legacyExactCredentialAuthorizationKey, runtimeResourceKey, scopeCloudflareSandboxId, } from "./sandbox/identity.js";
|
|
10
|
+
import { resolveWorkspaceProjection, readWorkspaceProjectionMode, } from "./workspace-projection/index.js";
|
|
11
|
+
export const readConversationWorkspaceMountMode = readWorkspaceProjectionMode;
|
|
45
12
|
export class ActorExecutionResolver {
|
|
46
|
-
constructor(baseConfig, vaultManager, provisioner, workspaceDir
|
|
13
|
+
constructor(baseConfig, vaultManager, provisioner, workspaceDir) {
|
|
47
14
|
this.baseConfig = baseConfig;
|
|
48
15
|
this.vaultManager = vaultManager;
|
|
49
16
|
this.provisioner = provisioner;
|
|
50
17
|
this.workspaceDir = workspaceDir;
|
|
51
|
-
this.hostWorkspacePath = hostWorkspacePath;
|
|
52
|
-
this.ensuredConversationDirs = new Set();
|
|
53
18
|
}
|
|
54
19
|
async resolve(context) {
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
20
|
+
const plan = this.resolvePlan(context);
|
|
21
|
+
return createExecutor(plan.sandboxConfig, plan.env, this.buildEnsureReadyCallback(plan, context.conversationId));
|
|
22
|
+
}
|
|
23
|
+
resolvePlan(context) {
|
|
24
|
+
const ids = { userId: context.userId, conversationId: context.conversationId };
|
|
25
|
+
const credentialKey = credentialAuthorizationKey(this.baseConfig, ids);
|
|
26
|
+
const legacyCredentialKey = legacyExactCredentialAuthorizationKey(this.baseConfig, ids);
|
|
27
|
+
const resourceKey = runtimeResourceKey(this.baseConfig, ids);
|
|
28
|
+
this.ensureDefaultSharedVault(credentialKey, legacyCredentialKey, context.trustModel);
|
|
29
|
+
const vault = this.vaultManager.resolve(credentialKey) ??
|
|
30
|
+
(legacyCredentialKey ? this.vaultManager.resolve(legacyCredentialKey) : undefined);
|
|
31
|
+
const capabilities = getSandboxCredentialCapabilities(this.baseConfig.type);
|
|
64
32
|
const injection = resolveVaultInjection({
|
|
65
33
|
vault,
|
|
34
|
+
capabilities,
|
|
66
35
|
sandboxType: this.baseConfig.type,
|
|
67
36
|
conversationId: context.conversationId,
|
|
68
37
|
});
|
|
69
|
-
const
|
|
70
|
-
return
|
|
38
|
+
const mounts = this.resolveMounts(context.conversationId, injection.mounts);
|
|
39
|
+
return {
|
|
40
|
+
credentialKey,
|
|
41
|
+
resourceKey,
|
|
42
|
+
sandboxConfig: this.resolveSandboxConfig(resourceKey, this.baseConfig.type === "agent-sandbox" ? injection.mounts : mounts),
|
|
43
|
+
env: injection.env,
|
|
44
|
+
mounts,
|
|
45
|
+
};
|
|
71
46
|
}
|
|
72
|
-
ensureDefaultSharedVault(
|
|
73
|
-
if (!allowsAmbientDefaultSharedVault({
|
|
74
|
-
trustModel,
|
|
75
|
-
sandboxType: this.baseConfig.type,
|
|
76
|
-
})) {
|
|
47
|
+
ensureDefaultSharedVault(credentialKey, legacyCredentialKey, trustModel) {
|
|
48
|
+
if (!allowsAmbientDefaultSharedVault({ trustModel, sandboxType: this.baseConfig.type }))
|
|
77
49
|
return;
|
|
78
|
-
|
|
79
|
-
|
|
50
|
+
if (this.vaultManager.hasEntry(credentialKey) ||
|
|
51
|
+
(legacyCredentialKey && this.vaultManager.hasEntry(legacyCredentialKey))) {
|
|
80
52
|
return;
|
|
53
|
+
}
|
|
81
54
|
let profile;
|
|
82
55
|
try {
|
|
83
56
|
profile = loadGlobalSettings().sandbox?.defaultSharedVault;
|
|
@@ -87,43 +60,40 @@ export class ActorExecutionResolver {
|
|
|
87
60
|
}
|
|
88
61
|
if (!profile || normalizeSharedVaultName(profile) !== profile)
|
|
89
62
|
return;
|
|
90
|
-
this.vaultManager.copySharedVaultTo(profile,
|
|
63
|
+
this.vaultManager.copySharedVaultTo(profile, credentialKey);
|
|
91
64
|
}
|
|
92
|
-
resolveSandboxConfig(
|
|
65
|
+
resolveSandboxConfig(resourceKey, mounts) {
|
|
93
66
|
if (this.baseConfig.type === "cloudflare") {
|
|
94
67
|
return {
|
|
95
68
|
type: "cloudflare",
|
|
96
|
-
sandboxId: scopeCloudflareSandboxId(this.baseConfig.sandboxId,
|
|
69
|
+
sandboxId: scopeCloudflareSandboxId(this.baseConfig.sandboxId, resourceKey),
|
|
97
70
|
};
|
|
98
71
|
}
|
|
99
|
-
if (this.baseConfig.type === "
|
|
72
|
+
if (this.baseConfig.type === "agent-sandbox") {
|
|
100
73
|
return {
|
|
101
74
|
...this.baseConfig,
|
|
102
|
-
|
|
103
|
-
mounts
|
|
104
|
-
instanceId: vaultKey,
|
|
105
|
-
resourceKey: vaultKey,
|
|
75
|
+
resourceKey,
|
|
76
|
+
mounts,
|
|
106
77
|
};
|
|
107
78
|
}
|
|
108
|
-
if (this.baseConfig.type !== "image")
|
|
79
|
+
if (this.baseConfig.type !== "image")
|
|
109
80
|
return this.baseConfig;
|
|
110
|
-
}
|
|
111
81
|
return {
|
|
112
82
|
type: "container",
|
|
113
|
-
container: DockerContainerManager.containerName(
|
|
83
|
+
container: DockerContainerManager.containerName(resourceKey),
|
|
114
84
|
};
|
|
115
85
|
}
|
|
116
|
-
buildEnsureReadyCallback(
|
|
117
|
-
if (this.baseConfig.type !== "image" ||
|
|
86
|
+
buildEnsureReadyCallback(plan, conversationId) {
|
|
87
|
+
if (this.baseConfig.type !== "image" || plan.sandboxConfig.type !== "container") {
|
|
118
88
|
return undefined;
|
|
119
89
|
}
|
|
120
90
|
return async () => {
|
|
121
|
-
const expected =
|
|
91
|
+
const expected = plan.sandboxConfig.type === "container" ? plan.sandboxConfig.container : "";
|
|
122
92
|
let actual;
|
|
123
93
|
try {
|
|
124
|
-
actual = await this.provisioner?.provision(
|
|
94
|
+
actual = await this.provisioner?.provision(plan.resourceKey, {
|
|
125
95
|
containerName: expected,
|
|
126
|
-
mounts:
|
|
96
|
+
mounts: plan.mounts,
|
|
127
97
|
conversationId,
|
|
128
98
|
});
|
|
129
99
|
}
|
|
@@ -135,49 +105,45 @@ export class ActorExecutionResolver {
|
|
|
135
105
|
severity: "error",
|
|
136
106
|
context: {
|
|
137
107
|
sandboxType: "image",
|
|
138
|
-
resolvedSandboxType: config.type,
|
|
139
108
|
conversationId,
|
|
140
|
-
|
|
109
|
+
credentialKey: plan.credentialKey,
|
|
110
|
+
resourceKey: plan.resourceKey,
|
|
141
111
|
expectedContainer: expected,
|
|
142
|
-
hasVault: Boolean(
|
|
112
|
+
hasVault: Boolean(plan.env || plan.mounts.length > 0),
|
|
143
113
|
},
|
|
144
114
|
});
|
|
145
115
|
throw err;
|
|
146
116
|
}
|
|
147
117
|
if (actual && actual !== expected) {
|
|
148
|
-
throw new Error(`Provisioner returned container "${actual}" for
|
|
118
|
+
throw new Error(`Provisioner returned container "${actual}" for resource key "${plan.resourceKey}", expected "${expected}"`);
|
|
149
119
|
}
|
|
150
120
|
};
|
|
151
121
|
}
|
|
152
|
-
/** Workspace layout overlaid by the vault's (already validated) credential mounts. */
|
|
153
122
|
resolveMounts(conversationId, vaultMounts) {
|
|
154
|
-
const
|
|
155
|
-
for (
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
if (readConversationWorkspaceMountMode(this.workspaceDir, conversationId) === "full") {
|
|
168
|
-
return [{ source: this.workspaceDir, target: "/workspace" }];
|
|
169
|
-
}
|
|
170
|
-
const conversationDir = join(this.workspaceDir, conversationId);
|
|
171
|
-
if (!this.ensuredConversationDirs.has(conversationId)) {
|
|
172
|
-
ensureDirExists(conversationDir);
|
|
173
|
-
this.ensuredConversationDirs.add(conversationId);
|
|
123
|
+
const workspaceMounts = resolveWorkspaceProjection(this.workspaceDir, conversationId).mounts;
|
|
124
|
+
for (let index = 0; index < vaultMounts.length; index += 1) {
|
|
125
|
+
const vaultMount = vaultMounts[index];
|
|
126
|
+
const workspaceCollision = workspaceMounts.find((workspaceMount) => targetsOverlap(workspaceMount.target, vaultMount.target));
|
|
127
|
+
if (workspaceCollision) {
|
|
128
|
+
throw new Error(`Vault mount target "${vaultMount.target}" overlaps protected workspace target "${workspaceCollision.target}"`);
|
|
129
|
+
}
|
|
130
|
+
const vaultCollision = vaultMounts
|
|
131
|
+
.slice(0, index)
|
|
132
|
+
.find((other) => targetsOverlap(other.target, vaultMount.target));
|
|
133
|
+
if (vaultCollision) {
|
|
134
|
+
throw new Error(`Vault mount target "${vaultMount.target}" overlaps vault target "${vaultCollision.target}"`);
|
|
135
|
+
}
|
|
174
136
|
}
|
|
175
|
-
return [
|
|
176
|
-
{ source: join(this.workspaceDir, "MEMORY.md"), target: "/workspace/MEMORY.md" },
|
|
177
|
-
{ source: join(this.workspaceDir, "skills"), target: "/workspace/skills" },
|
|
178
|
-
{ source: join(this.workspaceDir, "events"), target: "/workspace/events" },
|
|
179
|
-
{ source: conversationDir, target: `/workspace/${conversationId}` },
|
|
180
|
-
];
|
|
137
|
+
return [...workspaceMounts, ...vaultMounts];
|
|
181
138
|
}
|
|
182
139
|
}
|
|
140
|
+
function targetsOverlap(left, right) {
|
|
141
|
+
const a = normalizeMountTarget(left);
|
|
142
|
+
const b = normalizeMountTarget(right);
|
|
143
|
+
return a === b || a.startsWith(`${b}/`) || b.startsWith(`${a}/`);
|
|
144
|
+
}
|
|
145
|
+
function normalizeMountTarget(value) {
|
|
146
|
+
const normalized = posix.normalize(value);
|
|
147
|
+
return normalized.replace(/\/+$/, "") || "/";
|
|
148
|
+
}
|
|
183
149
|
//# sourceMappingURL=execution-resolver.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution-resolver.js","sourceRoot":"","sources":["../src/execution-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"path\";\nimport {\n conversationSettingsPath,\n loadGlobalSettings,\n resolveConversationSettings,\n} from \"./config.js\";\nimport { ensureDirExists, isRecord, readJsonFileIfExists } from \"./utils/file-guards.js\";\nimport { DockerContainerManager, type ContainerMount } from \"./provisioner.js\";\nimport { createExecutor, type Executor, type SandboxConfig } from \"./sandbox/index.js\";\nimport { reportUserFacingError } from \"./observability/sentry.js\";\nimport { normalizeSharedVaultName, type VaultManager } from \"./vault/index.js\";\nimport { resolveVaultInjection, type VaultInjection } from \"./vault/injection.js\";\nimport { allowsAmbientDefaultSharedVault } from \"./vault/policy.js\";\nimport { actorKey, scopeCloudflareSandboxId } from \"./sandbox/identity.js\";\nimport type { ResolvedVaultMount } from \"./vault/types.js\";\nimport * as log from \"./log.js\";\n\nexport type { ActorContext, ImageWorkspaceMountMode } from \"./types.js\";\nimport type { ActorContext, ImageWorkspaceMountMode } from \"./types.js\";\n\nexport function readConversationWorkspaceMountMode(\n workspaceDir: string | undefined,\n conversationId: string,\n): ImageWorkspaceMountMode {\n const globalDefault = readGlobalWorkspaceMountMode();\n if (!workspaceDir) {\n return globalDefault;\n }\n\n const conversationDir = join(workspaceDir, conversationId);\n try {\n return (\n resolveConversationSettings(conversationDir).sandbox?.image?.workspaceMount ?? globalDefault\n );\n } catch (err) {\n log.logWarning(\n \"Falling back while resolving conversation workspace mount\",\n err instanceof Error ? err.message : String(err),\n );\n const raw = readConversationSettingsFallback(conversationSettingsPath(conversationDir));\n return raw?.sandbox?.image?.workspaceMount ?? globalDefault;\n }\n}\n\nfunction readGlobalWorkspaceMountMode(): ImageWorkspaceMountMode {\n try {\n return loadGlobalSettings().sandbox?.image?.workspaceMount ?? \"private\";\n } catch (err) {\n log.logWarning(\n \"Using default workspace mount because global settings could not be read\",\n err instanceof Error ? err.message : String(err),\n );\n return \"private\";\n }\n}\n\nfunction readConversationSettingsFallback(\n settingsPath: string,\n): { sandbox?: { image?: { workspaceMount?: ImageWorkspaceMountMode } } } | undefined {\n try {\n return readJsonFileIfExists(\n settingsPath,\n (value): value is { sandbox?: { image?: { workspaceMount?: ImageWorkspaceMountMode } } } =>\n isRecord(value),\n () => \"Ignoring malformed conversation settings file while resolving workspace mount\",\n );\n } catch (err) {\n log.logWarning(\n \"Ignoring malformed conversation settings fallback while resolving workspace mount\",\n err instanceof Error ? err.message : String(err),\n );\n return undefined;\n }\n}\n\nexport class ActorExecutionResolver {\n private readonly ensuredConversationDirs = new Set<string>();\n\n constructor(\n private baseConfig: SandboxConfig,\n private vaultManager: VaultManager,\n private provisioner?: DockerContainerManager,\n private workspaceDir?: string,\n private hostWorkspacePath?: string,\n ) {}\n\n async resolve(context: ActorContext): Promise<Executor> {\n const vaultKey = actorKey(this.baseConfig, {\n userId: context.userId,\n conversationId: context.conversationId,\n });\n this.ensureDefaultSharedVault(vaultKey, context.trustModel);\n\n const vault = this.vaultManager.resolve(vaultKey);\n // The vault decides what it contributes (env, validated credential\n // mounts); this resolver only composes that with workspace layout and\n // per-actor config shaping.\n const injection = resolveVaultInjection({\n vault,\n sandboxType: this.baseConfig.type,\n conversationId: context.conversationId,\n });\n const config = this.resolveSandboxConfig(vaultKey, context.conversationId, injection);\n return createExecutor(\n config,\n injection.env,\n this.buildEnsureReadyCallback(vaultKey, context.conversationId, config, injection),\n );\n }\n\n private ensureDefaultSharedVault(vaultKey: string, trustModel: ActorContext[\"trustModel\"]): void {\n if (\n !allowsAmbientDefaultSharedVault({\n trustModel,\n sandboxType: this.baseConfig.type,\n })\n ) {\n return;\n }\n if (this.vaultManager.hasEntry(vaultKey)) return;\n\n let profile: string | undefined;\n try {\n profile = loadGlobalSettings().sandbox?.defaultSharedVault;\n } catch {\n return;\n }\n if (!profile || normalizeSharedVaultName(profile) !== profile) return;\n\n this.vaultManager.copySharedVaultTo(profile, vaultKey);\n }\n\n private resolveSandboxConfig(\n vaultKey: string,\n conversationId: string,\n injection: VaultInjection,\n ): SandboxConfig {\n if (this.baseConfig.type === \"cloudflare\") {\n return {\n type: \"cloudflare\",\n sandboxId: scopeCloudflareSandboxId(this.baseConfig.sandboxId, vaultKey),\n };\n }\n if (this.baseConfig.type === \"gondolin\") {\n return {\n ...this.baseConfig,\n workspacePath: this.hostWorkspacePath,\n mounts: this.resolveMounts(conversationId, injection.mounts),\n instanceId: vaultKey,\n resourceKey: vaultKey,\n };\n }\n if (this.baseConfig.type !== \"image\") {\n return this.baseConfig;\n }\n\n return {\n type: \"container\",\n container: DockerContainerManager.containerName(vaultKey),\n };\n }\n\n private buildEnsureReadyCallback(\n vaultKey: string,\n conversationId: string,\n config: SandboxConfig,\n injection: VaultInjection,\n ): (() => Promise<void>) | undefined {\n if (this.baseConfig.type !== \"image\" || config.type !== \"container\") {\n return undefined;\n }\n\n return async () => {\n const expected = config.container || DockerContainerManager.containerName(vaultKey);\n let actual: string | undefined;\n try {\n actual = await this.provisioner?.provision(vaultKey, {\n containerName: expected,\n mounts: this.resolveMounts(conversationId, injection.mounts),\n conversationId,\n });\n } catch (err) {\n reportUserFacingError(err, {\n domain: \"sandbox\",\n surface: \"sandbox_provision\",\n operation: \"ensure_image_container_ready\",\n severity: \"error\",\n context: {\n sandboxType: \"image\",\n resolvedSandboxType: config.type,\n conversationId,\n vaultKey,\n expectedContainer: expected,\n hasVault: Boolean(injection.env || injection.mounts.length > 0),\n },\n });\n throw err;\n }\n if (actual && actual !== expected) {\n throw new Error(\n `Provisioner returned container \"${actual}\" for container key \"${vaultKey}\", expected \"${expected}\"`,\n );\n }\n };\n }\n\n /** Workspace layout overlaid by the vault's (already validated) credential mounts. */\n private resolveMounts(\n conversationId: string,\n vaultMounts: ResolvedVaultMount[],\n ): ContainerMount[] {\n const mountsByTarget = new Map<string, ContainerMount>();\n for (const mount of this.buildWorkspaceMounts(conversationId)) {\n mountsByTarget.set(mount.target, mount);\n }\n for (const mount of vaultMounts) {\n mountsByTarget.set(mount.target, { source: mount.source, target: mount.target });\n }\n return [...mountsByTarget.values()];\n }\n\n private buildWorkspaceMounts(conversationId: string): ContainerMount[] {\n if (!this.workspaceDir) {\n return [];\n }\n\n if (readConversationWorkspaceMountMode(this.workspaceDir, conversationId) === \"full\") {\n return [{ source: this.workspaceDir, target: \"/workspace\" }];\n }\n\n const conversationDir = join(this.workspaceDir, conversationId);\n if (!this.ensuredConversationDirs.has(conversationId)) {\n ensureDirExists(conversationDir);\n this.ensuredConversationDirs.add(conversationId);\n }\n\n return [\n { source: join(this.workspaceDir, \"MEMORY.md\"), target: \"/workspace/MEMORY.md\" },\n { source: join(this.workspaceDir, \"skills\"), target: \"/workspace/skills\" },\n { source: join(this.workspaceDir, \"events\"), target: \"/workspace/events\" },\n { source: conversationDir, target: `/workspace/${conversationId}` },\n ];\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"execution-resolver.js","sourceRoot":"","sources":["../src/execution-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["import { posix } from \"node:path\";\nimport { loadGlobalSettings } from \"./config.js\";\nimport { DockerContainerManager, type ContainerMount } from \"./provisioner.js\";\nimport {\n createExecutor,\n getSandboxCredentialCapabilities,\n type Executor,\n type SandboxConfig,\n} from \"./sandbox/index.js\";\nimport { reportUserFacingError } from \"./observability/sentry.js\";\nimport { normalizeSharedVaultName, type VaultManager } from \"./vault/index.js\";\nimport { resolveVaultInjection } from \"./vault/injection.js\";\nimport { allowsAmbientDefaultSharedVault } from \"./vault/policy.js\";\nimport {\n credentialAuthorizationKey,\n legacyExactCredentialAuthorizationKey,\n runtimeResourceKey,\n scopeCloudflareSandboxId,\n} from \"./sandbox/identity.js\";\nimport {\n resolveWorkspaceProjection,\n readWorkspaceProjectionMode,\n} from \"./workspace-projection/index.js\";\n\nexport type { ActorContext } from \"./types.js\";\nimport type { ActorContext, ExecutionPlan } from \"./types.js\";\n\nexport const readConversationWorkspaceMountMode = readWorkspaceProjectionMode;\n\nexport class ActorExecutionResolver {\n constructor(\n private baseConfig: SandboxConfig,\n private vaultManager: VaultManager,\n private provisioner?: DockerContainerManager,\n private workspaceDir?: string,\n ) {}\n\n async resolve(context: ActorContext): Promise<Executor> {\n const plan = this.resolvePlan(context);\n return createExecutor(\n plan.sandboxConfig,\n plan.env,\n this.buildEnsureReadyCallback(plan, context.conversationId),\n );\n }\n\n private resolvePlan(context: ActorContext): ExecutionPlan {\n const ids = { userId: context.userId, conversationId: context.conversationId };\n const credentialKey = credentialAuthorizationKey(this.baseConfig, ids);\n const legacyCredentialKey = legacyExactCredentialAuthorizationKey(this.baseConfig, ids);\n const resourceKey = runtimeResourceKey(this.baseConfig, ids);\n this.ensureDefaultSharedVault(credentialKey, legacyCredentialKey, context.trustModel);\n\n const vault =\n this.vaultManager.resolve(credentialKey) ??\n (legacyCredentialKey ? this.vaultManager.resolve(legacyCredentialKey) : undefined);\n const capabilities = getSandboxCredentialCapabilities(this.baseConfig.type);\n const injection = resolveVaultInjection({\n vault,\n capabilities,\n sandboxType: this.baseConfig.type,\n conversationId: context.conversationId,\n });\n const mounts = this.resolveMounts(context.conversationId, injection.mounts);\n return {\n credentialKey,\n resourceKey,\n sandboxConfig: this.resolveSandboxConfig(\n resourceKey,\n this.baseConfig.type === \"agent-sandbox\" ? injection.mounts : mounts,\n ),\n env: injection.env,\n mounts,\n };\n }\n\n private ensureDefaultSharedVault(\n credentialKey: string,\n legacyCredentialKey: string | undefined,\n trustModel: ActorContext[\"trustModel\"],\n ): void {\n if (!allowsAmbientDefaultSharedVault({ trustModel, sandboxType: this.baseConfig.type })) return;\n if (\n this.vaultManager.hasEntry(credentialKey) ||\n (legacyCredentialKey && this.vaultManager.hasEntry(legacyCredentialKey))\n ) {\n return;\n }\n\n let profile: string | undefined;\n try {\n profile = loadGlobalSettings().sandbox?.defaultSharedVault;\n } catch {\n return;\n }\n if (!profile || normalizeSharedVaultName(profile) !== profile) return;\n this.vaultManager.copySharedVaultTo(profile, credentialKey);\n }\n\n private resolveSandboxConfig(resourceKey: string, mounts: ContainerMount[]): SandboxConfig {\n if (this.baseConfig.type === \"cloudflare\") {\n return {\n type: \"cloudflare\",\n sandboxId: scopeCloudflareSandboxId(this.baseConfig.sandboxId, resourceKey),\n };\n }\n if (this.baseConfig.type === \"agent-sandbox\") {\n return {\n ...this.baseConfig,\n resourceKey,\n mounts,\n };\n }\n if (this.baseConfig.type !== \"image\") return this.baseConfig;\n return {\n type: \"container\",\n container: DockerContainerManager.containerName(resourceKey),\n };\n }\n\n private buildEnsureReadyCallback(\n plan: ExecutionPlan,\n conversationId: string,\n ): (() => Promise<void>) | undefined {\n if (this.baseConfig.type !== \"image\" || plan.sandboxConfig.type !== \"container\") {\n return undefined;\n }\n\n return async () => {\n const expected = plan.sandboxConfig.type === \"container\" ? plan.sandboxConfig.container : \"\";\n let actual: string | undefined;\n try {\n actual = await this.provisioner?.provision(plan.resourceKey, {\n containerName: expected,\n mounts: plan.mounts,\n conversationId,\n });\n } catch (err) {\n reportUserFacingError(err, {\n domain: \"sandbox\",\n surface: \"sandbox_provision\",\n operation: \"ensure_image_container_ready\",\n severity: \"error\",\n context: {\n sandboxType: \"image\",\n conversationId,\n credentialKey: plan.credentialKey,\n resourceKey: plan.resourceKey,\n expectedContainer: expected,\n hasVault: Boolean(plan.env || plan.mounts.length > 0),\n },\n });\n throw err;\n }\n if (actual && actual !== expected) {\n throw new Error(\n `Provisioner returned container \"${actual}\" for resource key \"${plan.resourceKey}\", expected \"${expected}\"`,\n );\n }\n };\n }\n\n private resolveMounts(conversationId: string, vaultMounts: ContainerMount[]): ContainerMount[] {\n const workspaceMounts = resolveWorkspaceProjection(this.workspaceDir, conversationId).mounts;\n for (let index = 0; index < vaultMounts.length; index += 1) {\n const vaultMount = vaultMounts[index];\n const workspaceCollision = workspaceMounts.find((workspaceMount) =>\n targetsOverlap(workspaceMount.target, vaultMount.target),\n );\n if (workspaceCollision) {\n throw new Error(\n `Vault mount target \"${vaultMount.target}\" overlaps protected workspace target \"${workspaceCollision.target}\"`,\n );\n }\n\n const vaultCollision = vaultMounts\n .slice(0, index)\n .find((other) => targetsOverlap(other.target, vaultMount.target));\n if (vaultCollision) {\n throw new Error(\n `Vault mount target \"${vaultMount.target}\" overlaps vault target \"${vaultCollision.target}\"`,\n );\n }\n }\n return [...workspaceMounts, ...vaultMounts];\n }\n}\n\nfunction targetsOverlap(left: string, right: string): boolean {\n const a = normalizeMountTarget(left);\n const b = normalizeMountTarget(right);\n return a === b || a.startsWith(`${b}/`) || b.startsWith(`${a}/`);\n}\n\nfunction normalizeMountTarget(value: string): string {\n const normalized = posix.normalize(value);\n return normalized.replace(/\\/+$/, \"\") || \"/\";\n}\n"]}
|
package/dist/harness/index.d.ts
CHANGED
|
@@ -16,5 +16,5 @@ export { buildEventPayload, EventTypeSchema, parseEventPayload, type EventConver
|
|
|
16
16
|
export { ExtensionRegistry, parseCommandInput } from "./extensions/registry.js";
|
|
17
17
|
export { defaultExtensionDirs, extensionSlug, listInstalledExtensions, loadExtensions, validateExtension, type ExtensionValidation, type InstalledExtensionInfo, type LoadExtensionsOptions, type LoadExtensionsResult, } from "./extensions/loader.js";
|
|
18
18
|
export type { AgentErrorHookEvent, BeforeAgentStartHookEvent, BeforeAgentStartHookResult, BudgetExceededHookEvent, SubagentApi, ExtensionCommand, ExtensionCommandContext, ExtensionDisposer, ExtensionHostServices, ExtensionLoadError, ExtensionManifest, ExtensionScheduleInfo, ExtensionSchedulePayload, ExtensionScheduleSpec, ExtensionScheduleStore, LoadedExtension, MessageEndHookEvent, MikanExtensionActivate, MikanExtensionApi, MikanExtensionModule, MikanHookMap, MikanHookName, RunOrigin, SessionCompactHookEvent, ToolCallHookEvent, ToolCallHookResult, ToolResultHookEvent, ToolResultHookResult, TurnEndHookEvent, } from "./extensions/types.js";
|
|
19
|
-
export { type SubagentModelSpec, type SubagentRunBudget, type SubagentRunOutput, type SubagentRunRequest, type SubagentRunResult, type SubagentRunStatus, CURRENT_SESSION_VERSION, type BranchSummaryEntry, type CompactionEntry, type CustomEntry, type CustomMessageEntry, type SessionContext, type SessionEntry, type SessionFileEntry, type SessionHeader, type SessionInfoEntry, type SessionMessageEntry, } from "./types.js";
|
|
19
|
+
export { type SubagentModelSpec, type SubagentParentContext, type SubagentRunBudget, type SubagentRunOutput, type SubagentRunRequest, type SubagentRunResult, type SubagentRunStatus, type SubagentUsage, CURRENT_SESSION_VERSION, type BranchSummaryEntry, type CompactionEntry, type CustomEntry, type CustomMessageEntry, type SessionContext, type SessionEntry, type SessionFileEntry, type SessionHeader, type SessionInfoEntry, type SessionMessageEntry, } from "./types.js";
|
|
20
20
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/harness/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,EACL,4BAA4B,EAC5B,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,KAAK,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAChG,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AACnG,OAAO,EACL,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,GAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,eAAe,GACrB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EACtB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,aAAa,GACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,GAC1B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAChF,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,uBAAuB,EACvB,cAAc,EACd,iBAAiB,EACjB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,mBAAmB,EACnB,yBAAyB,EACzB,0BAA0B,EAC1B,uBAAuB,EACvB,WAAW,EACX,gBAAgB,EAChB,uBAAuB,EACvB,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,wBAAwB,EACxB,qBAAqB,EACrB,sBAAsB,EACtB,eAAe,EACf,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,YAAY,EACZ,aAAa,EACb,SAAS,EACT,uBAAuB,EACvB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,uBAAuB,EACvB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,GACzB,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/harness/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,EACL,4BAA4B,EAC5B,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,KAAK,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAChG,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AACnG,OAAO,EACL,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,GAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,eAAe,GACrB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EACtB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,aAAa,GACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,GAC1B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAChF,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,uBAAuB,EACvB,cAAc,EACd,iBAAiB,EACjB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,mBAAmB,EACnB,yBAAyB,EACzB,0BAA0B,EAC1B,uBAAuB,EACvB,WAAW,EACX,gBAAgB,EAChB,uBAAuB,EACvB,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,wBAAwB,EACxB,qBAAqB,EACrB,sBAAsB,EACtB,eAAe,EACf,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,YAAY,EACZ,aAAa,EACb,SAAS,EACT,uBAAuB,EACvB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,uBAAuB,EACvB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,GACzB,MAAM,YAAY,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/harness/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,EACL,4BAA4B,EAC5B,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAiC,MAAM,aAAa,CAAC;AAChG,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AACnG,OAAO,EACL,iBAAiB,GAMlB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,GAIjB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,GAKvB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,iBAAiB,GAQlB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAChF,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,uBAAuB,EACvB,cAAc,EACd,iBAAiB,GAKlB,MAAM,wBAAwB,CAAC;AAgChC,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/harness/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,EACL,4BAA4B,EAC5B,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAiC,MAAM,aAAa,CAAC;AAChG,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AACnG,OAAO,EACL,iBAAiB,GAMlB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,GAIjB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,GAKvB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,iBAAiB,GAQlB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAChF,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,uBAAuB,EACvB,cAAc,EACd,iBAAiB,GAKlB,MAAM,wBAAwB,CAAC;AAgChC,OAAO,EASL,uBAAuB,GAWxB,MAAM,YAAY,CAAC","sourcesContent":["/**\n * mikan agent harness.\n *\n * mikan's own harness engineering layer, built directly on pi-agent-core\n * (agent loop, compaction, context building) and pi-ai (providers, models,\n * auth). See `src/harness/README.md` for the architecture.\n */\nexport { FileCredentialStore, defaultAuthPath } from \"./auth.js\";\nexport {\n DEFAULT_HTTP_IDLE_TIMEOUT_MS,\n configureHttpDispatcher,\n parseHttpIdleTimeoutMs,\n} from \"./http.js\";\nexport { MikanModels, defaultModelsJsonPath, type CreateMikanModelsOptions } from \"./models.js\";\nexport { SessionStore, loadSessionFileEntries, parseSessionFileEntries } from \"./session-store.js\";\nexport {\n MikanAgentSession,\n type CompactionReason,\n type HarnessEvent,\n type HarnessEventListener,\n type MikanAgentSessionOptions,\n type PromptBlockedOutcome,\n} from \"./runner.js\";\nexport {\n formatSkillsForPrompt,\n loadSkillsFromDir,\n parseFrontmatter,\n type LoadSkillsResult,\n type MikanSkill,\n type SkillDiagnostic,\n} from \"./skills.js\";\nexport {\n DEFAULT_BUDGET_SETTINGS,\n DEFAULT_EVENT_BUDGET,\n DEFAULT_RETRY_SETTINGS,\n resolveHarnessSettings,\n type BudgetSettings,\n type CompactionSettings,\n type HarnessSettings,\n type RetrySettings,\n} from \"./settings.js\";\nexport {\n buildEventPayload,\n EventTypeSchema,\n parseEventPayload,\n type EventConversationKind,\n type EventFilePayload,\n type EventPayloadInput,\n type EventType,\n type ImmediateEventPayload,\n type OneShotEventPayload,\n type PeriodicEventPayload,\n} from \"./event-format.js\";\nexport { ExtensionRegistry, parseCommandInput } from \"./extensions/registry.js\";\nexport {\n defaultExtensionDirs,\n extensionSlug,\n listInstalledExtensions,\n loadExtensions,\n validateExtension,\n type ExtensionValidation,\n type InstalledExtensionInfo,\n type LoadExtensionsOptions,\n type LoadExtensionsResult,\n} from \"./extensions/loader.js\";\nexport type {\n AgentErrorHookEvent,\n BeforeAgentStartHookEvent,\n BeforeAgentStartHookResult,\n BudgetExceededHookEvent,\n SubagentApi,\n ExtensionCommand,\n ExtensionCommandContext,\n ExtensionDisposer,\n ExtensionHostServices,\n ExtensionLoadError,\n ExtensionManifest,\n ExtensionScheduleInfo,\n ExtensionSchedulePayload,\n ExtensionScheduleSpec,\n ExtensionScheduleStore,\n LoadedExtension,\n MessageEndHookEvent,\n MikanExtensionActivate,\n MikanExtensionApi,\n MikanExtensionModule,\n MikanHookMap,\n MikanHookName,\n RunOrigin,\n SessionCompactHookEvent,\n ToolCallHookEvent,\n ToolCallHookResult,\n ToolResultHookEvent,\n ToolResultHookResult,\n TurnEndHookEvent,\n} from \"./extensions/types.js\";\nexport {\n type SubagentModelSpec,\n type SubagentParentContext,\n type SubagentRunBudget,\n type SubagentRunOutput,\n type SubagentRunRequest,\n type SubagentRunResult,\n type SubagentRunStatus,\n type SubagentUsage,\n CURRENT_SESSION_VERSION,\n type BranchSummaryEntry,\n type CompactionEntry,\n type CustomEntry,\n type CustomMessageEntry,\n type SessionContext,\n type SessionEntry,\n type SessionFileEntry,\n type SessionHeader,\n type SessionInfoEntry,\n type SessionMessageEntry,\n} from \"./types.js\";\n"]}
|
package/dist/harness/runner.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ import type { RunOrigin } from "./extensions/types.js";
|
|
|
21
21
|
import type { MikanModels } from "./models.js";
|
|
22
22
|
import { resolveHarnessSettings, type BudgetSettings } from "./settings.js";
|
|
23
23
|
import type { SessionStore } from "./session-store.js";
|
|
24
|
+
import type { SubagentUsage } from "./types.js";
|
|
24
25
|
export type CompactionReason = "threshold" | "overflow" | "manual";
|
|
25
26
|
interface CompactionResultSummary {
|
|
26
27
|
summary: string;
|
|
@@ -83,6 +84,7 @@ export declare class MikanAgentSession {
|
|
|
83
84
|
private overflowRecoveryAttempted;
|
|
84
85
|
private retryAbortController;
|
|
85
86
|
private compactionAbortController;
|
|
87
|
+
private runActive;
|
|
86
88
|
private tally;
|
|
87
89
|
private runBudget;
|
|
88
90
|
private budgetExceededReason;
|
|
@@ -91,8 +93,11 @@ export declare class MikanAgentSession {
|
|
|
91
93
|
/** Conversation transcript currently held by the agent. */
|
|
92
94
|
get messages(): AgentMessage[];
|
|
93
95
|
get model(): Model<Api>;
|
|
96
|
+
/** Whether this session currently owns a prompt, including pre-model hooks. */
|
|
97
|
+
get isActiveRun(): boolean;
|
|
94
98
|
/** Resource totals and terminal budget state from the most recent prompt. */
|
|
95
99
|
getLastRunStats(): Readonly<{
|
|
100
|
+
usage: SubagentUsage;
|
|
96
101
|
tokens: number;
|
|
97
102
|
costUsd: number;
|
|
98
103
|
llmCalls: number;
|
|
@@ -104,13 +109,10 @@ export declare class MikanAgentSession {
|
|
|
104
109
|
* runs launched by a tool during the current prompt — into the run tally
|
|
105
110
|
* and enforce the run budget at the fold itself: a fold that lands over a
|
|
106
111
|
* resource ceiling aborts the run now instead of waiting for a next
|
|
107
|
-
* assistant message that may never come (and would be paid for).
|
|
108
|
-
*
|
|
112
|
+
* assistant message that may never come (and would be paid for). Complete
|
|
113
|
+
* usage is folded; external runs are not this session's turns.
|
|
109
114
|
*/
|
|
110
|
-
foldExternalUsage(usage:
|
|
111
|
-
tokens?: number;
|
|
112
|
-
costUsd?: number;
|
|
113
|
-
}): Promise<void>;
|
|
115
|
+
foldExternalUsage(usage: SubagentUsage): Promise<void>;
|
|
114
116
|
subscribe(listener: HarnessEventListener): () => void;
|
|
115
117
|
/** Replace the agent transcript from the persisted session tree. */
|
|
116
118
|
reloadFromSession(): number;
|
|
@@ -131,6 +133,7 @@ export declare class MikanAgentSession {
|
|
|
131
133
|
budget?: BudgetSettings;
|
|
132
134
|
origin?: RunOrigin;
|
|
133
135
|
}): Promise<PromptBlockedOutcome | undefined>;
|
|
136
|
+
private runPrompt;
|
|
134
137
|
/** Abort the active run, pending retry backoff, and in-flight compaction. */
|
|
135
138
|
abort(): void;
|
|
136
139
|
private ensureAuthConfigured;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/harness/runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EACL,KAAK,EAQL,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,SAAS,EAEd,KAAK,aAAa,EACnB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAEL,KAAK,GAAG,EAER,KAAK,YAAY,EACjB,KAAK,KAAK,EACX,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,KAAK,cAAc,EAAwB,MAAM,eAAe,CAAC;AAClG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/harness/runner.ts"],"names":[],"mappings":"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"}
|
package/dist/harness/runner.js
CHANGED
|
@@ -18,6 +18,7 @@ import { Agent, calculateContextTokens, compact, convertToLlm, estimateContextTo
|
|
|
18
18
|
import { isContextOverflow, } from "@earendil-works/pi-ai";
|
|
19
19
|
import * as log from "../log.js";
|
|
20
20
|
import { resolveHarnessSettings } from "./settings.js";
|
|
21
|
+
import { addSubagentUsage, copySubagentUsage, createEmptySubagentUsage } from "./usage.js";
|
|
21
22
|
// Transient provider failures worth retrying: overload/rate-limit responses,
|
|
22
23
|
// 5xx statuses, and network/stream interruptions.
|
|
23
24
|
const RETRYABLE_ERROR_PATTERN = /overloaded|provider.?returned.?error|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server.?error|internal.?error|network.?error|connection.?error|connection.?refused|connection.?lost|websocket.?closed|websocket.?error|other side closed|fetch failed|upstream.?connect|reset before headers|socket hang up|ended without|stream ended before message_stop|http2 request did not get a response|timed? out|timeout|terminated|retry delay/i;
|
|
@@ -43,7 +44,12 @@ export class MikanAgentSession {
|
|
|
43
44
|
this.listeners = new Set();
|
|
44
45
|
this.retryAttempt = 0;
|
|
45
46
|
this.overflowRecoveryAttempted = false;
|
|
46
|
-
this.
|
|
47
|
+
this.runActive = false;
|
|
48
|
+
this.tally = {
|
|
49
|
+
usage: createEmptySubagentUsage(),
|
|
50
|
+
llmCalls: 0,
|
|
51
|
+
startedAt: 0,
|
|
52
|
+
};
|
|
47
53
|
this.runBudget = {};
|
|
48
54
|
this.models = options.models;
|
|
49
55
|
this.sessionStore = options.sessionStore;
|
|
@@ -97,11 +103,16 @@ export class MikanAgentSession {
|
|
|
97
103
|
get model() {
|
|
98
104
|
return this.agent.state.model;
|
|
99
105
|
}
|
|
106
|
+
/** Whether this session currently owns a prompt, including pre-model hooks. */
|
|
107
|
+
get isActiveRun() {
|
|
108
|
+
return this.runActive;
|
|
109
|
+
}
|
|
100
110
|
/** Resource totals and terminal budget state from the most recent prompt. */
|
|
101
111
|
getLastRunStats() {
|
|
102
112
|
return {
|
|
103
|
-
|
|
104
|
-
|
|
113
|
+
usage: copySubagentUsage(this.tally.usage),
|
|
114
|
+
tokens: this.tally.usage.totalTokens,
|
|
115
|
+
costUsd: this.tally.usage.cost.total,
|
|
105
116
|
llmCalls: this.tally.llmCalls,
|
|
106
117
|
durationMs: this.tally.startedAt > 0 ? Date.now() - this.tally.startedAt : 0,
|
|
107
118
|
...(this.budgetExceededReason ? { budgetExceededReason: this.budgetExceededReason } : {}),
|
|
@@ -112,13 +123,12 @@ export class MikanAgentSession {
|
|
|
112
123
|
* runs launched by a tool during the current prompt — into the run tally
|
|
113
124
|
* and enforce the run budget at the fold itself: a fold that lands over a
|
|
114
125
|
* resource ceiling aborts the run now instead of waiting for a next
|
|
115
|
-
* assistant message that may never come (and would be paid for).
|
|
116
|
-
*
|
|
126
|
+
* assistant message that may never come (and would be paid for). Complete
|
|
127
|
+
* usage is folded; external runs are not this session's turns.
|
|
117
128
|
*/
|
|
118
129
|
async foldExternalUsage(usage) {
|
|
119
|
-
this.tally.
|
|
120
|
-
this.
|
|
121
|
-
if (this.budgetExceededReason || !this.agent.state.isStreaming)
|
|
130
|
+
addSubagentUsage(this.tally.usage, usage);
|
|
131
|
+
if (this.budgetExceededReason || !this.runActive)
|
|
122
132
|
return;
|
|
123
133
|
const reason = this.resourceOverBudgetReason();
|
|
124
134
|
if (reason)
|
|
@@ -149,16 +159,29 @@ export class MikanAgentSession {
|
|
|
149
159
|
* @param options.origin Platform provenance forwarded to extension hooks.
|
|
150
160
|
*/
|
|
151
161
|
async prompt(text, options) {
|
|
152
|
-
if (this.
|
|
162
|
+
if (this.runActive) {
|
|
153
163
|
throw new Error("Agent is already processing a prompt");
|
|
154
164
|
}
|
|
165
|
+
this.runActive = true;
|
|
166
|
+
try {
|
|
167
|
+
return await this.runPrompt(text, options);
|
|
168
|
+
}
|
|
169
|
+
finally {
|
|
170
|
+
this.runActive = false;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
async runPrompt(text, options) {
|
|
155
174
|
const model = this.agent.state.model;
|
|
156
175
|
await this.ensureAuthConfigured(model);
|
|
157
176
|
this.retryAttempt = 0;
|
|
158
177
|
this.overflowRecoveryAttempted = false;
|
|
159
178
|
this.runBudget = { ...this.settings.budget, ...options?.budget };
|
|
160
179
|
this.budgetExceededReason = undefined;
|
|
161
|
-
this.tally = {
|
|
180
|
+
this.tally = {
|
|
181
|
+
usage: createEmptySubagentUsage(),
|
|
182
|
+
llmCalls: 0,
|
|
183
|
+
startedAt: Date.now(),
|
|
184
|
+
};
|
|
162
185
|
this.runOrigin = options?.origin;
|
|
163
186
|
// A previous turn may have ended over the threshold (for example after an
|
|
164
187
|
// abort); compact before adding new context on top.
|
|
@@ -275,8 +298,7 @@ export class MikanAgentSession {
|
|
|
275
298
|
const usage = message.usage;
|
|
276
299
|
if (!usage)
|
|
277
300
|
return;
|
|
278
|
-
this.tally.
|
|
279
|
-
this.tally.costUsd += usage.cost?.total ?? 0;
|
|
301
|
+
addSubagentUsage(this.tally.usage, usage);
|
|
280
302
|
}
|
|
281
303
|
/** Compare the tally against the run budget; abort the run when a cap is exceeded. */
|
|
282
304
|
async enforceBudget(message) {
|
|
@@ -293,16 +315,16 @@ export class MikanAgentSession {
|
|
|
293
315
|
await this.emit({
|
|
294
316
|
type: "budget_exceeded",
|
|
295
317
|
reason,
|
|
296
|
-
tokens: this.tally.
|
|
297
|
-
costUsd: this.tally.
|
|
318
|
+
tokens: this.tally.usage.totalTokens,
|
|
319
|
+
costUsd: this.tally.usage.cost.total,
|
|
298
320
|
llmCalls: this.tally.llmCalls,
|
|
299
321
|
durationMs: Date.now() - this.tally.startedAt,
|
|
300
322
|
});
|
|
301
323
|
if (this.extensions?.hasHandlers("budget_exceeded")) {
|
|
302
324
|
await this.extensions.emit("budget_exceeded", {
|
|
303
325
|
reason,
|
|
304
|
-
tokens: this.tally.
|
|
305
|
-
costUsd: this.tally.
|
|
326
|
+
tokens: this.tally.usage.totalTokens,
|
|
327
|
+
costUsd: this.tally.usage.cost.total,
|
|
306
328
|
llmCalls: this.tally.llmCalls,
|
|
307
329
|
durationMs: Date.now() - this.tally.startedAt,
|
|
308
330
|
origin: this.runOrigin,
|
|
@@ -322,11 +344,11 @@ export class MikanAgentSession {
|
|
|
322
344
|
/** The message-independent budget checks, shared with external-spend folds. */
|
|
323
345
|
resourceOverBudgetReason() {
|
|
324
346
|
const { maxTokens, maxCostUsd, maxDurationMs } = this.runBudget;
|
|
325
|
-
if (maxTokens !== undefined && this.tally.
|
|
326
|
-
return `${this.tally.
|
|
347
|
+
if (maxTokens !== undefined && this.tally.usage.totalTokens >= maxTokens) {
|
|
348
|
+
return `${this.tally.usage.totalTokens} tokens >= ${maxTokens} limit`;
|
|
327
349
|
}
|
|
328
|
-
if (maxCostUsd !== undefined && this.tally.
|
|
329
|
-
return `cost ${this.tally.
|
|
350
|
+
if (maxCostUsd !== undefined && this.tally.usage.cost.total >= maxCostUsd) {
|
|
351
|
+
return `cost ${this.tally.usage.cost.total.toFixed(2)} USD >= ${maxCostUsd} USD limit`;
|
|
330
352
|
}
|
|
331
353
|
if (maxDurationMs !== undefined && Date.now() - this.tally.startedAt >= maxDurationMs) {
|
|
332
354
|
return `${Date.now() - this.tally.startedAt}ms >= ${maxDurationMs}ms limit`;
|