@geminixiang/mikan 1.0.0-beta.20 → 1.0.0-beta.21
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 +34 -0
- package/README.md +18 -11
- package/dist/adapters/buffered-responder.d.ts +60 -0
- package/dist/adapters/buffered-responder.d.ts.map +1 -0
- package/dist/adapters/buffered-responder.js +201 -0
- package/dist/adapters/buffered-responder.js.map +1 -0
- package/dist/adapters/discord/context.d.ts.map +1 -1
- package/dist/adapters/discord/context.js +42 -177
- package/dist/adapters/discord/context.js.map +1 -1
- package/dist/adapters/github/bot.d.ts +14 -76
- package/dist/adapters/github/bot.d.ts.map +1 -1
- package/dist/adapters/github/bot.js +52 -443
- package/dist/adapters/github/bot.js.map +1 -1
- package/dist/adapters/github/client.d.ts +4 -0
- package/dist/adapters/github/client.d.ts.map +1 -1
- package/dist/adapters/github/client.js +5 -0
- package/dist/adapters/github/client.js.map +1 -1
- package/dist/adapters/github/context.d.ts.map +1 -1
- package/dist/adapters/github/context.js +32 -104
- package/dist/adapters/github/context.js.map +1 -1
- package/dist/adapters/github/github-ops.d.ts +90 -0
- package/dist/adapters/github/github-ops.d.ts.map +1 -0
- package/dist/adapters/github/github-ops.js +405 -0
- package/dist/adapters/github/github-ops.js.map +1 -0
- package/dist/adapters/github/repo.d.ts +2 -0
- package/dist/adapters/github/repo.d.ts.map +1 -1
- package/dist/adapters/github/repo.js +5 -0
- package/dist/adapters/github/repo.js.map +1 -1
- package/dist/adapters/github/tools/checks.d.ts.map +1 -1
- package/dist/adapters/github/tools/checks.js +6 -17
- package/dist/adapters/github/tools/checks.js.map +1 -1
- package/dist/adapters/github/tools/issue.d.ts.map +1 -1
- package/dist/adapters/github/tools/issue.js +6 -17
- package/dist/adapters/github/tools/issue.js.map +1 -1
- package/dist/adapters/github/tools/pr.d.ts.map +1 -1
- package/dist/adapters/github/tools/pr.js +6 -17
- package/dist/adapters/github/tools/pr.js.map +1 -1
- package/dist/adapters/github/tools/read.d.ts.map +1 -1
- package/dist/adapters/github/tools/read.js +6 -17
- package/dist/adapters/github/tools/read.js.map +1 -1
- package/dist/adapters/github/tools/review-reply.d.ts.map +1 -1
- package/dist/adapters/github/tools/review-reply.js +6 -17
- package/dist/adapters/github/tools/review-reply.js.map +1 -1
- package/dist/adapters/github/tools/sync.d.ts.map +1 -1
- package/dist/adapters/github/tools/sync.js +6 -17
- package/dist/adapters/github/tools/sync.js.map +1 -1
- package/dist/adapters/slack/bot.js +1 -1
- package/dist/adapters/slack/bot.js.map +1 -1
- package/dist/adapters/telegram/context.d.ts.map +1 -1
- package/dist/adapters/telegram/context.js +33 -151
- package/dist/adapters/telegram/context.js.map +1 -1
- package/dist/agent.d.ts +0 -1
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +28 -32
- package/dist/agent.js.map +1 -1
- package/dist/cli/arg-grammar.d.ts +25 -0
- package/dist/cli/arg-grammar.d.ts.map +1 -0
- package/dist/cli/arg-grammar.js +59 -0
- package/dist/cli/arg-grammar.js.map +1 -0
- package/dist/cli/boot.d.ts +16 -0
- package/dist/cli/boot.d.ts.map +1 -0
- package/dist/cli/boot.js +119 -0
- package/dist/cli/boot.js.map +1 -0
- package/dist/cli/ext.js +9 -11
- package/dist/cli/ext.js.map +1 -1
- package/dist/commands/extensions.js +2 -2
- package/dist/commands/extensions.js.map +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +5 -2
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/model.d.ts.map +1 -1
- package/dist/commands/model.js +8 -8
- package/dist/commands/model.js.map +1 -1
- package/dist/commands/sandbox.d.ts.map +1 -1
- package/dist/commands/sandbox.js +7 -5
- package/dist/commands/sandbox.js.map +1 -1
- package/dist/config.d.ts +0 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -41
- package/dist/config.js.map +1 -1
- package/dist/env-manifest.d.ts +35 -0
- package/dist/env-manifest.d.ts.map +1 -0
- package/dist/env-manifest.js +225 -0
- package/dist/env-manifest.js.map +1 -0
- package/dist/events.d.ts +0 -10
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +9 -82
- package/dist/events.js.map +1 -1
- package/dist/execution-resolver.d.ts +1 -0
- package/dist/execution-resolver.d.ts.map +1 -1
- package/dist/execution-resolver.js +33 -36
- package/dist/execution-resolver.js.map +1 -1
- package/dist/harness/event-format.d.ts +66 -0
- package/dist/harness/event-format.d.ts.map +1 -0
- package/dist/harness/event-format.js +112 -0
- package/dist/harness/event-format.js.map +1 -0
- package/dist/harness/extensions/loader.d.ts +9 -6
- package/dist/harness/extensions/loader.d.ts.map +1 -1
- package/dist/harness/extensions/loader.js +35 -50
- package/dist/harness/extensions/loader.js.map +1 -1
- package/dist/harness/extensions/types.d.ts +10 -14
- package/dist/harness/extensions/types.d.ts.map +1 -1
- package/dist/harness/extensions/types.js.map +1 -1
- package/dist/harness/index.d.ts +1 -0
- package/dist/harness/index.d.ts.map +1 -1
- package/dist/harness/index.js +1 -0
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/runner.d.ts +16 -0
- package/dist/harness/runner.d.ts.map +1 -1
- package/dist/harness/runner.js +27 -1
- package/dist/harness/runner.js.map +1 -1
- package/dist/harness/subagent-runner.d.ts +18 -1
- package/dist/harness/subagent-runner.d.ts.map +1 -1
- package/dist/harness/subagent-runner.js +62 -30
- package/dist/harness/subagent-runner.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/main.js +69 -121
- package/dist/main.js.map +1 -1
- package/dist/observability/instrument.js +6 -4
- package/dist/observability/instrument.js.map +1 -1
- package/dist/observability/sentry.d.ts.map +1 -1
- package/dist/observability/sentry.js +3 -2
- package/dist/observability/sentry.js.map +1 -1
- package/dist/runtime/conversation-runtime.js +13 -3
- package/dist/runtime/conversation-runtime.js.map +1 -1
- package/dist/runtime/types.d.ts +4 -0
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/types.js.map +1 -1
- package/dist/sandbox/cloudflare.d.ts +1 -0
- package/dist/sandbox/cloudflare.d.ts.map +1 -1
- package/dist/sandbox/cloudflare.js +4 -1
- package/dist/sandbox/cloudflare.js.map +1 -1
- package/dist/sandbox/container.d.ts +1 -0
- package/dist/sandbox/container.d.ts.map +1 -1
- package/dist/sandbox/container.js +4 -1
- package/dist/sandbox/container.js.map +1 -1
- package/dist/sandbox/firecracker.d.ts +1 -0
- package/dist/sandbox/firecracker.d.ts.map +1 -1
- package/dist/sandbox/firecracker.js +4 -1
- package/dist/sandbox/firecracker.js.map +1 -1
- package/dist/sandbox/gondolin-bootstrap.d.ts +26 -0
- package/dist/sandbox/gondolin-bootstrap.d.ts.map +1 -0
- package/dist/sandbox/gondolin-bootstrap.js +27 -0
- package/dist/sandbox/gondolin-bootstrap.js.map +1 -0
- package/dist/sandbox/gondolin-contract.d.ts +125 -0
- package/dist/sandbox/gondolin-contract.d.ts.map +1 -0
- package/dist/sandbox/gondolin-contract.js +155 -0
- package/dist/sandbox/gondolin-contract.js.map +1 -0
- package/dist/sandbox/gondolin-fleet.d.ts +1 -1
- package/dist/sandbox/gondolin-fleet.d.ts.map +1 -1
- package/dist/sandbox/gondolin-fleet.js +1 -1
- package/dist/sandbox/gondolin-fleet.js.map +1 -1
- package/dist/sandbox/gondolin-gateway.d.ts +1 -0
- package/dist/sandbox/gondolin-gateway.d.ts.map +1 -1
- package/dist/sandbox/gondolin-gateway.js +13 -6
- package/dist/sandbox/gondolin-gateway.js.map +1 -1
- package/dist/sandbox/gondolin-inventory.d.ts +2 -16
- package/dist/sandbox/gondolin-inventory.d.ts.map +1 -1
- package/dist/sandbox/gondolin-inventory.js +2 -12
- package/dist/sandbox/gondolin-inventory.js.map +1 -1
- package/dist/sandbox/gondolin-placement.d.ts +0 -2
- package/dist/sandbox/gondolin-placement.d.ts.map +1 -1
- package/dist/sandbox/gondolin-placement.js +0 -6
- package/dist/sandbox/gondolin-placement.js.map +1 -1
- package/dist/sandbox/gondolin-recovery.d.ts +33 -0
- package/dist/sandbox/gondolin-recovery.d.ts.map +1 -0
- package/dist/sandbox/gondolin-recovery.js +39 -0
- package/dist/sandbox/gondolin-recovery.js.map +1 -0
- package/dist/sandbox/gondolin-remote.d.ts +2 -5
- package/dist/sandbox/gondolin-remote.d.ts.map +1 -1
- package/dist/sandbox/gondolin-remote.js +12 -39
- package/dist/sandbox/gondolin-remote.js.map +1 -1
- package/dist/sandbox/gondolin-worker-client.d.ts +8 -12
- package/dist/sandbox/gondolin-worker-client.d.ts.map +1 -1
- package/dist/sandbox/gondolin-worker-client.js +13 -15
- package/dist/sandbox/gondolin-worker-client.js.map +1 -1
- package/dist/sandbox/gondolin-worker.d.ts +2 -40
- package/dist/sandbox/gondolin-worker.d.ts.map +1 -1
- package/dist/sandbox/gondolin-worker.js.map +1 -1
- package/dist/sandbox/gondolin.d.ts +1 -0
- package/dist/sandbox/gondolin.d.ts.map +1 -1
- package/dist/sandbox/gondolin.js +8 -4
- package/dist/sandbox/gondolin.js.map +1 -1
- package/dist/sandbox/host.d.ts +1 -0
- package/dist/sandbox/host.d.ts.map +1 -1
- package/dist/sandbox/host.js +3 -0
- package/dist/sandbox/host.js.map +1 -1
- package/dist/sandbox/index.d.ts +9 -1
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/index.js +14 -0
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/types.d.ts +5 -0
- package/dist/sandbox/types.d.ts.map +1 -1
- package/dist/sandbox/types.js.map +1 -1
- package/dist/sandbox/utils.d.ts +1 -0
- package/dist/sandbox/utils.d.ts.map +1 -1
- package/dist/sandbox/utils.js +5 -2
- package/dist/sandbox/utils.js.map +1 -1
- package/dist/sessions/chat-history-sync.d.ts +32 -0
- package/dist/sessions/chat-history-sync.d.ts.map +1 -0
- package/dist/sessions/{agent-memory-file-manager.js → chat-history-sync.js} +24 -83
- package/dist/sessions/chat-history-sync.js.map +1 -0
- package/dist/sessions/conversation-log.d.ts +13 -0
- package/dist/sessions/conversation-log.d.ts.map +1 -0
- package/dist/sessions/conversation-log.js +47 -0
- package/dist/sessions/conversation-log.js.map +1 -0
- package/dist/sessions/rotation.d.ts +2 -0
- package/dist/sessions/rotation.d.ts.map +1 -0
- package/dist/sessions/rotation.js +39 -0
- package/dist/sessions/rotation.js.map +1 -0
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js +4 -10
- package/dist/sessions/store.js.map +1 -1
- package/dist/sessions/types.d.ts +2 -2
- package/dist/sessions/types.d.ts.map +1 -1
- package/dist/sessions/types.js.map +1 -1
- package/dist/settings-mutation.d.ts +23 -0
- package/dist/settings-mutation.d.ts.map +1 -0
- package/dist/settings-mutation.js +42 -0
- package/dist/settings-mutation.js.map +1 -0
- package/dist/tools/event.d.ts.map +1 -1
- package/dist/tools/event.js +27 -46
- package/dist/tools/event.js.map +1 -1
- package/dist/tools/host-fn-tool.d.ts +21 -0
- package/dist/tools/host-fn-tool.d.ts.map +1 -0
- package/dist/tools/host-fn-tool.js +32 -0
- package/dist/tools/host-fn-tool.js.map +1 -0
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +1 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/react.d.ts.map +1 -1
- package/dist/tools/react.js +6 -17
- package/dist/tools/react.js.map +1 -1
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +7 -26
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/sandbox.d.ts.map +1 -1
- package/dist/tools/sandbox.js +5 -2
- package/dist/tools/sandbox.js.map +1 -1
- package/dist/tools/subagent-slots.d.ts +28 -0
- package/dist/tools/subagent-slots.d.ts.map +1 -0
- package/dist/tools/subagent-slots.js +57 -0
- package/dist/tools/subagent-slots.js.map +1 -0
- package/dist/tools/subagent.d.ts +7 -2
- package/dist/tools/subagent.d.ts.map +1 -1
- package/dist/tools/subagent.js +160 -111
- package/dist/tools/subagent.js.map +1 -1
- package/dist/tools/types.d.ts +10 -9
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js.map +1 -1
- package/dist/types.d.ts +5 -24
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/date.d.ts +1 -1
- package/dist/utils/date.js +1 -1
- package/dist/utils/date.js.map +1 -1
- package/dist/vault/disabled.d.ts.map +1 -1
- package/dist/vault/disabled.js +0 -1
- package/dist/vault/disabled.js.map +1 -1
- package/dist/vault/index.d.ts +0 -2
- package/dist/vault/index.d.ts.map +1 -1
- package/dist/vault/index.js +0 -10
- package/dist/vault/index.js.map +1 -1
- package/dist/vault/injection.d.ts +20 -0
- package/dist/vault/injection.d.ts.map +1 -0
- package/dist/vault/injection.js +27 -0
- package/dist/vault/injection.js.map +1 -0
- package/dist/vault/types.d.ts +0 -2
- package/dist/vault/types.d.ts.map +1 -1
- package/dist/vault/types.js.map +1 -1
- package/dist/web/admin/portal.d.ts +3 -3
- package/dist/web/admin/portal.d.ts.map +1 -1
- package/dist/web/admin/portal.js +41 -39
- package/dist/web/admin/portal.js.map +1 -1
- package/dist/web/admin/types.d.ts +3 -0
- package/dist/web/admin/types.d.ts.map +1 -1
- package/dist/web/admin/types.js.map +1 -1
- package/dist/web/agent-events/portal.d.ts.map +1 -1
- package/dist/web/agent-events/portal.js +2 -1
- package/dist/web/agent-events/portal.js.map +1 -1
- package/package.json +1 -1
- package/dist/sessions/agent-memory-file-manager.d.ts +0 -19
- package/dist/sessions/agent-memory-file-manager.d.ts.map +0 -1
- package/dist/sessions/agent-memory-file-manager.js.map +0 -1
- package/dist/vault/routing.d.ts +0 -4
- package/dist/vault/routing.d.ts.map +0 -1
- package/dist/vault/routing.js +0 -6
- package/dist/vault/routing.js.map +0 -1
|
@@ -2,6 +2,7 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
3
|
import { Kind, Type } from "@sinclair/typebox";
|
|
4
4
|
import { Value } from "@sinclair/typebox/value";
|
|
5
|
+
import * as log from "../log.js";
|
|
5
6
|
import { MikanAgentSession } from "./runner.js";
|
|
6
7
|
import { SessionStore } from "./session-store.js";
|
|
7
8
|
const subagentRunDepth = new AsyncLocalStorage();
|
|
@@ -43,6 +44,10 @@ function schemaOptions(node) {
|
|
|
43
44
|
* without it. Hydrate plain JSON Schema into real TypeBox schema nodes so
|
|
44
45
|
* validation runs instead of throwing; schemas built with TypeBox already
|
|
45
46
|
* carry Kind and pass through untouched.
|
|
47
|
+
*
|
|
48
|
+
* Unsupported keywords ($ref, not, patternProperties, if/then/else) degrade to
|
|
49
|
+
* a permissive Unknown — fail-open by design: outputSchema is advisory output
|
|
50
|
+
* validation, not a security boundary.
|
|
46
51
|
*/
|
|
47
52
|
function hydrateSchema(schema) {
|
|
48
53
|
if (isRecord(schema) && Kind in schema)
|
|
@@ -180,44 +185,67 @@ function assistantText(message) {
|
|
|
180
185
|
.map((part) => part.text)
|
|
181
186
|
.join("");
|
|
182
187
|
}
|
|
183
|
-
/**
|
|
188
|
+
/**
|
|
189
|
+
* Execute one non-recursive, fresh subagent run. Never rejects: every
|
|
190
|
+
* failure — including request validation — is a result with a terminal
|
|
191
|
+
* status, so batch callers (`tasks` / `dag`) can never orphan in-flight
|
|
192
|
+
* sibling runs on one bad request. The run's spend is reported through
|
|
193
|
+
* `onUsage` before the result is returned.
|
|
194
|
+
*/
|
|
184
195
|
export async function runSubagent(options) {
|
|
185
|
-
|
|
186
|
-
|
|
196
|
+
const result = await executeSubagentRun(options);
|
|
197
|
+
try {
|
|
198
|
+
await options.onUsage?.({ tokens: result.tokens, costUsd: result.costUsd });
|
|
187
199
|
}
|
|
200
|
+
catch (err) {
|
|
201
|
+
log.logWarning("Subagent onUsage listener failed", String(err));
|
|
202
|
+
}
|
|
203
|
+
return result;
|
|
204
|
+
}
|
|
205
|
+
async function executeSubagentRun(options) {
|
|
188
206
|
const { request } = options;
|
|
189
207
|
const runId = randomUUID();
|
|
190
208
|
const startedAt = Date.now();
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
: options.defaultModel
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
const task = formatTask(request.task, request.input);
|
|
197
|
-
const budget = resolveBudget(request.budget);
|
|
198
|
-
const session = new MikanAgentSession({
|
|
199
|
-
systemPrompt: buildSystemPrompt(request.systemPrompt, request.outputSchema),
|
|
200
|
-
model,
|
|
201
|
-
thinkingLevel: options.thinkingLevel,
|
|
202
|
-
tools,
|
|
203
|
-
models: options.models,
|
|
204
|
-
sessionStore: SessionStore.inMemory(options.workspaceDir),
|
|
205
|
-
settings: { compaction: { enabled: false } },
|
|
206
|
-
});
|
|
209
|
+
let modelSpec = request.model ?? {
|
|
210
|
+
provider: options.defaultModel.provider,
|
|
211
|
+
id: options.defaultModel.id,
|
|
212
|
+
};
|
|
213
|
+
let sessionRef;
|
|
207
214
|
let terminalSignal;
|
|
215
|
+
let timeout;
|
|
208
216
|
const abort = (reason) => {
|
|
209
217
|
if (terminalSignal)
|
|
210
218
|
return;
|
|
211
219
|
terminalSignal = reason;
|
|
212
|
-
|
|
220
|
+
sessionRef?.abort();
|
|
213
221
|
};
|
|
214
222
|
const onAbort = () => abort("cancelled");
|
|
215
|
-
request.signal?.addEventListener("abort", onAbort, { once: true });
|
|
216
|
-
if (request.signal?.aborted)
|
|
217
|
-
abort("cancelled");
|
|
218
|
-
const timeout = setTimeout(() => abort("timeout"), budget.maxDurationMs);
|
|
219
|
-
timeout?.unref();
|
|
220
223
|
try {
|
|
224
|
+
if ((subagentRunDepth.getStore() ?? 0) >= 1) {
|
|
225
|
+
throw new Error("Nested api.subagent.run calls are not allowed");
|
|
226
|
+
}
|
|
227
|
+
const model = request.model
|
|
228
|
+
? options.models.resolve(request.model.provider, request.model.id)
|
|
229
|
+
: options.defaultModel;
|
|
230
|
+
modelSpec = { provider: model.provider, id: model.id };
|
|
231
|
+
const tools = selectTools(request.tools, options.availableTools);
|
|
232
|
+
const task = formatTask(request.task, request.input);
|
|
233
|
+
const budget = resolveBudget(request.budget);
|
|
234
|
+
const session = new MikanAgentSession({
|
|
235
|
+
systemPrompt: buildSystemPrompt(request.systemPrompt, request.outputSchema),
|
|
236
|
+
model,
|
|
237
|
+
thinkingLevel: options.thinkingLevel,
|
|
238
|
+
tools,
|
|
239
|
+
models: options.models,
|
|
240
|
+
sessionStore: SessionStore.inMemory(options.workspaceDir),
|
|
241
|
+
settings: { compaction: { enabled: false } },
|
|
242
|
+
});
|
|
243
|
+
sessionRef = session;
|
|
244
|
+
request.signal?.addEventListener("abort", onAbort, { once: true });
|
|
245
|
+
if (request.signal?.aborted)
|
|
246
|
+
abort("cancelled");
|
|
247
|
+
timeout = setTimeout(() => abort("timeout"), budget.maxDurationMs);
|
|
248
|
+
timeout.unref();
|
|
221
249
|
if (!terminalSignal) {
|
|
222
250
|
await subagentRunDepth.run(1, () => session.prompt(task, {
|
|
223
251
|
budget: {
|
|
@@ -280,6 +308,9 @@ export async function runSubagent(options) {
|
|
|
280
308
|
output: parsed,
|
|
281
309
|
};
|
|
282
310
|
}
|
|
311
|
+
if (!text) {
|
|
312
|
+
return { ...base, status: "failed", error: "Subagent produced no text output" };
|
|
313
|
+
}
|
|
283
314
|
return {
|
|
284
315
|
...base,
|
|
285
316
|
status: "completed",
|
|
@@ -287,20 +318,21 @@ export async function runSubagent(options) {
|
|
|
287
318
|
};
|
|
288
319
|
}
|
|
289
320
|
catch (err) {
|
|
290
|
-
const stats =
|
|
321
|
+
const stats = sessionRef?.getLastRunStats();
|
|
291
322
|
return {
|
|
292
323
|
runId,
|
|
293
324
|
status: terminalSignal ?? "failed",
|
|
294
325
|
model: modelSpec,
|
|
295
|
-
turns: stats
|
|
296
|
-
tokens: stats
|
|
297
|
-
costUsd: stats
|
|
326
|
+
turns: stats?.llmCalls ?? 0,
|
|
327
|
+
tokens: stats?.tokens ?? 0,
|
|
328
|
+
costUsd: stats?.costUsd ?? 0,
|
|
298
329
|
durationMs: Date.now() - startedAt,
|
|
299
330
|
error: err instanceof Error ? err.message : String(err),
|
|
300
331
|
};
|
|
301
332
|
}
|
|
302
333
|
finally {
|
|
303
|
-
|
|
334
|
+
if (timeout)
|
|
335
|
+
clearTimeout(timeout);
|
|
304
336
|
request.signal?.removeEventListener("abort", onAbort);
|
|
305
337
|
}
|
|
306
338
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subagent-runner.js","sourceRoot":"","sources":["../../src/harness/subagent-runner.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { AgentMessage, AgentTool, ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type { Api, AssistantMessage, Model } from \"@earendil-works/pi-ai\";\nimport { Kind, Type, type TSchema } from \"@sinclair/typebox\";\nimport { Value } from \"@sinclair/typebox/value\";\nimport type { MikanModels } from \"./models.js\";\nimport { MikanAgentSession } from \"./runner.js\";\nimport { SessionStore } from \"./session-store.js\";\nimport type { SubagentRunOutput, SubagentRunRequest, SubagentRunResult } from \"./types.js\";\n\nconst subagentRunDepth = new AsyncLocalStorage<number>();\nconst DEFAULT_SYSTEM_PROMPT =\n \"You are a focused subagent. Complete only the assigned task and return the result directly.\";\nconst DEFAULT_SUBAGENT_BUDGET = {\n maxTurns: 8,\n maxCostUsd: 0.5,\n maxDurationMs: 2 * 60 * 1000,\n} as const;\n\nconst SCHEMA_STRUCTURAL_KEYS = new Set([\n \"type\",\n \"properties\",\n \"required\",\n \"items\",\n \"enum\",\n \"const\",\n \"anyOf\",\n \"oneOf\",\n \"allOf\",\n]);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction schemaOptions(node: Record<string, unknown>): Record<string, unknown> {\n const options: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(node)) {\n if (!SCHEMA_STRUCTURAL_KEYS.has(key)) options[key] = value;\n }\n if (isRecord(options.additionalProperties)) {\n options.additionalProperties = hydrateSchema(options.additionalProperties);\n }\n return options;\n}\n\n/**\n * outputSchema arrives over the subagent tool as plain JSON (tool-call\n * arguments never carry TypeBox's Kind symbol), but Value.Check dispatches\n * purely on schema[Kind] and throws ValueCheckUnknownTypeError for anything\n * without it. Hydrate plain JSON Schema into real TypeBox schema nodes so\n * validation runs instead of throwing; schemas built with TypeBox already\n * carry Kind and pass through untouched.\n */\nfunction hydrateSchema(schema: unknown): TSchema {\n if (isRecord(schema) && Kind in schema) return schema as TSchema;\n if (!isRecord(schema)) return Type.Unknown();\n\n if (Array.isArray(schema.enum)) {\n const literals = schema.enum.filter(\n (value): value is string | number | boolean =>\n typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\",\n );\n return literals.length > 0\n ? Type.Union(literals.map((value) => Type.Literal(value)))\n : Type.Unknown();\n }\n if (\"const\" in schema) {\n const value = schema.const;\n return typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\"\n ? Type.Literal(value)\n : Type.Unknown();\n }\n if (Array.isArray(schema.anyOf)) return Type.Union(schema.anyOf.map(hydrateSchema));\n if (Array.isArray(schema.oneOf)) return Type.Union(schema.oneOf.map(hydrateSchema));\n if (Array.isArray(schema.allOf)) return Type.Intersect(schema.allOf.map(hydrateSchema));\n\n const type = Array.isArray(schema.type)\n ? schema.type\n : (schema.type ?? (schema.properties ? \"object\" : schema.items ? \"array\" : undefined));\n if (Array.isArray(type)) {\n return Type.Union(type.map((variant) => hydrateSchema({ ...schema, type: variant })));\n }\n\n const options = schemaOptions(schema);\n switch (type) {\n case \"object\": {\n const properties = isRecord(schema.properties) ? schema.properties : {};\n const required = new Set(Array.isArray(schema.required) ? schema.required : []);\n const props: Record<string, TSchema> = {};\n for (const [key, value] of Object.entries(properties)) {\n const hydrated = hydrateSchema(value);\n props[key] = required.has(key) ? hydrated : Type.Optional(hydrated);\n }\n return Type.Object(props, options);\n }\n case \"array\":\n return Type.Array(\n schema.items !== undefined ? hydrateSchema(schema.items) : Type.Unknown(),\n options,\n );\n case \"string\":\n return Type.String(options);\n case \"number\":\n return Type.Number(options);\n case \"integer\":\n return Type.Integer(options);\n case \"boolean\":\n return Type.Boolean(options);\n case \"null\":\n return Type.Null(options);\n default:\n return Type.Unknown(options);\n }\n}\n\ninterface RunSubagentOptions<TOutputSchema extends TSchema | undefined = undefined> {\n request: SubagentRunRequest<TOutputSchema>;\n defaultModel: Model<Api>;\n thinkingLevel: ThinkingLevel;\n models: MikanModels;\n workspaceDir: string;\n availableTools: AgentTool[];\n}\n\nfunction resolveBudget(budget: RunSubagentOptions[\"request\"][\"budget\"]) {\n const resolved = { ...DEFAULT_SUBAGENT_BUDGET, ...budget };\n const positiveIntegerFields = [\n [\"maxTurns\", resolved.maxTurns],\n [\"maxTokens\", resolved.maxTokens],\n [\"maxDurationMs\", resolved.maxDurationMs],\n ] as const;\n for (const [name, value] of positiveIntegerFields) {\n if (value !== undefined && (!Number.isInteger(value) || value <= 0)) {\n throw new Error(`api.subagent.run budget.${name} must be a positive integer`);\n }\n }\n if (!Number.isFinite(resolved.maxCostUsd) || resolved.maxCostUsd < 0) {\n throw new Error(\"api.subagent.run budget.maxCostUsd must be a non-negative number\");\n }\n return resolved;\n}\n\nfunction selectTools(requested: string[] | undefined, available: AgentTool[]): AgentTool[] {\n if (!requested || requested.length === 0) return [];\n const byName = new Map<string, AgentTool>();\n for (const tool of available) {\n if (!byName.has(tool.name)) byName.set(tool.name, tool);\n }\n const selected: AgentTool[] = [];\n for (const name of new Set(requested)) {\n const tool = byName.get(name);\n if (!tool) throw new Error(`Unknown or unavailable subagent tool: ${name}`);\n selected.push(tool);\n }\n return selected;\n}\n\nfunction formatTask(task: string, input: unknown): string {\n const trimmed = task.trim();\n if (!trimmed) throw new Error(\"api.subagent.run requires a non-empty task\");\n if (input === undefined) return trimmed;\n let serialized: string | undefined;\n try {\n serialized = JSON.stringify(input, null, 2);\n } catch (err) {\n throw new Error(\n `api.subagent.run input must be JSON-serializable: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n if (serialized === undefined) {\n throw new Error(\"api.subagent.run input must be JSON-serializable\");\n }\n return `${trimmed}\\n\\nInput:\\n${serialized}`;\n}\n\nfunction buildSystemPrompt(base: string | undefined, outputSchema: TSchema | undefined): string {\n const prompt = base?.trim() || DEFAULT_SYSTEM_PROMPT;\n if (!outputSchema) return prompt;\n return [\n prompt,\n \"\",\n \"Return only one JSON value matching this JSON Schema. Do not use Markdown or code fences.\",\n JSON.stringify(outputSchema),\n ].join(\"\\n\");\n}\n\nfunction finalAssistant(messages: AgentMessage[]): AssistantMessage | undefined {\n for (let index = messages.length - 1; index >= 0; index--) {\n const message = messages[index];\n if (message.role === \"assistant\") return message;\n }\n return undefined;\n}\n\nfunction assistantText(message: AssistantMessage | undefined): string {\n if (!message) return \"\";\n return message.content\n .filter((part) => part.type === \"text\")\n .map((part) => part.text)\n .join(\"\");\n}\n\n/** Execute one non-recursive, fresh subagent run for an extension. */\nexport async function runSubagent<TOutputSchema extends TSchema | undefined = undefined>(\n options: RunSubagentOptions<TOutputSchema>,\n): Promise<SubagentRunResult<SubagentRunOutput<TOutputSchema>>> {\n if ((subagentRunDepth.getStore() ?? 0) >= 1) {\n throw new Error(\"Nested api.subagent.run calls are not allowed\");\n }\n\n const { request } = options;\n const runId = randomUUID();\n const startedAt = Date.now();\n const model = request.model\n ? options.models.resolve(request.model.provider, request.model.id)\n : options.defaultModel;\n const modelSpec = { provider: model.provider, id: model.id };\n const tools = selectTools(request.tools, options.availableTools);\n const task = formatTask(request.task, request.input);\n const budget = resolveBudget(request.budget);\n const session = new MikanAgentSession({\n systemPrompt: buildSystemPrompt(request.systemPrompt, request.outputSchema),\n model,\n thinkingLevel: options.thinkingLevel,\n tools,\n models: options.models,\n sessionStore: SessionStore.inMemory(options.workspaceDir),\n settings: { compaction: { enabled: false } },\n });\n\n let terminalSignal: \"cancelled\" | \"timeout\" | undefined;\n const abort = (reason: \"cancelled\" | \"timeout\") => {\n if (terminalSignal) return;\n terminalSignal = reason;\n session.abort();\n };\n const onAbort = () => abort(\"cancelled\");\n request.signal?.addEventListener(\"abort\", onAbort, { once: true });\n if (request.signal?.aborted) abort(\"cancelled\");\n const timeout = setTimeout(() => abort(\"timeout\"), budget.maxDurationMs);\n timeout?.unref();\n\n try {\n if (!terminalSignal) {\n await subagentRunDepth.run(1, () =>\n session.prompt(task, {\n budget: {\n maxLlmCalls: budget.maxTurns,\n maxTokens: budget.maxTokens,\n maxCostUsd: budget.maxCostUsd,\n maxDurationMs: budget.maxDurationMs,\n },\n }),\n );\n }\n\n const stats = session.getLastRunStats();\n const assistant = finalAssistant(session.messages);\n const text = assistantText(assistant);\n const base = {\n runId,\n model: modelSpec,\n turns: stats.llmCalls,\n tokens: stats.tokens,\n costUsd: stats.costUsd,\n durationMs: Date.now() - startedAt,\n ...(text ? { text } : {}),\n };\n\n if (terminalSignal) return { ...base, status: terminalSignal };\n if (stats.budgetExceededReason) {\n return {\n ...base,\n status: \"budget_exceeded\",\n error: stats.budgetExceededReason,\n };\n }\n if (assistant?.stopReason === \"error\") {\n return {\n ...base,\n status: \"failed\",\n error: assistant.errorMessage || \"Subagent failed\",\n };\n }\n if (!assistant) {\n return { ...base, status: \"failed\", error: \"Subagent produced no assistant response\" };\n }\n\n if (request.outputSchema) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return { ...base, status: \"invalid_output\", error: \"Subagent output is not valid JSON\" };\n }\n if (!Value.Check(hydrateSchema(request.outputSchema), parsed)) {\n return {\n ...base,\n status: \"invalid_output\",\n error: \"Subagent output does not match the requested schema\",\n };\n }\n return {\n ...base,\n status: \"completed\",\n output: parsed as SubagentRunOutput<TOutputSchema>,\n };\n }\n\n return {\n ...base,\n status: \"completed\",\n output: text as SubagentRunOutput<TOutputSchema>,\n };\n } catch (err) {\n const stats = session.getLastRunStats();\n return {\n runId,\n status: terminalSignal ?? \"failed\",\n model: modelSpec,\n turns: stats.llmCalls,\n tokens: stats.tokens,\n costUsd: stats.costUsd,\n durationMs: Date.now() - startedAt,\n error: err instanceof Error ? err.message : String(err),\n };\n } finally {\n clearTimeout(timeout);\n request.signal?.removeEventListener(\"abort\", onAbort);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"subagent-runner.js","sourceRoot":"","sources":["../../src/harness/subagent-runner.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { AgentMessage, AgentTool, ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type { Api, AssistantMessage, Model } from \"@earendil-works/pi-ai\";\nimport { Kind, Type, type TSchema } from \"@sinclair/typebox\";\nimport { Value } from \"@sinclair/typebox/value\";\nimport * as log from \"../log.js\";\nimport type { MikanModels } from \"./models.js\";\nimport { MikanAgentSession } from \"./runner.js\";\nimport { SessionStore } from \"./session-store.js\";\nimport type {\n SubagentModelSpec,\n SubagentRunOutput,\n SubagentRunRequest,\n SubagentRunResult,\n} from \"./types.js\";\n\nconst subagentRunDepth = new AsyncLocalStorage<number>();\nconst DEFAULT_SYSTEM_PROMPT =\n \"You are a focused subagent. Complete only the assigned task and return the result directly.\";\nconst DEFAULT_SUBAGENT_BUDGET = {\n maxTurns: 8,\n maxCostUsd: 0.5,\n maxDurationMs: 2 * 60 * 1000,\n} as const;\n\nconst SCHEMA_STRUCTURAL_KEYS = new Set([\n \"type\",\n \"properties\",\n \"required\",\n \"items\",\n \"enum\",\n \"const\",\n \"anyOf\",\n \"oneOf\",\n \"allOf\",\n]);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction schemaOptions(node: Record<string, unknown>): Record<string, unknown> {\n const options: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(node)) {\n if (!SCHEMA_STRUCTURAL_KEYS.has(key)) options[key] = value;\n }\n if (isRecord(options.additionalProperties)) {\n options.additionalProperties = hydrateSchema(options.additionalProperties);\n }\n return options;\n}\n\n/**\n * outputSchema arrives over the subagent tool as plain JSON (tool-call\n * arguments never carry TypeBox's Kind symbol), but Value.Check dispatches\n * purely on schema[Kind] and throws ValueCheckUnknownTypeError for anything\n * without it. Hydrate plain JSON Schema into real TypeBox schema nodes so\n * validation runs instead of throwing; schemas built with TypeBox already\n * carry Kind and pass through untouched.\n *\n * Unsupported keywords ($ref, not, patternProperties, if/then/else) degrade to\n * a permissive Unknown — fail-open by design: outputSchema is advisory output\n * validation, not a security boundary.\n */\nfunction hydrateSchema(schema: unknown): TSchema {\n if (isRecord(schema) && Kind in schema) return schema as TSchema;\n if (!isRecord(schema)) return Type.Unknown();\n\n if (Array.isArray(schema.enum)) {\n const literals = schema.enum.filter(\n (value): value is string | number | boolean =>\n typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\",\n );\n return literals.length > 0\n ? Type.Union(literals.map((value) => Type.Literal(value)))\n : Type.Unknown();\n }\n if (\"const\" in schema) {\n const value = schema.const;\n return typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\"\n ? Type.Literal(value)\n : Type.Unknown();\n }\n if (Array.isArray(schema.anyOf)) return Type.Union(schema.anyOf.map(hydrateSchema));\n if (Array.isArray(schema.oneOf)) return Type.Union(schema.oneOf.map(hydrateSchema));\n if (Array.isArray(schema.allOf)) return Type.Intersect(schema.allOf.map(hydrateSchema));\n\n const type = Array.isArray(schema.type)\n ? schema.type\n : (schema.type ?? (schema.properties ? \"object\" : schema.items ? \"array\" : undefined));\n if (Array.isArray(type)) {\n return Type.Union(type.map((variant) => hydrateSchema({ ...schema, type: variant })));\n }\n\n const options = schemaOptions(schema);\n switch (type) {\n case \"object\": {\n const properties = isRecord(schema.properties) ? schema.properties : {};\n const required = new Set(Array.isArray(schema.required) ? schema.required : []);\n const props: Record<string, TSchema> = {};\n for (const [key, value] of Object.entries(properties)) {\n const hydrated = hydrateSchema(value);\n props[key] = required.has(key) ? hydrated : Type.Optional(hydrated);\n }\n return Type.Object(props, options);\n }\n case \"array\":\n return Type.Array(\n schema.items !== undefined ? hydrateSchema(schema.items) : Type.Unknown(),\n options,\n );\n case \"string\":\n return Type.String(options);\n case \"number\":\n return Type.Number(options);\n case \"integer\":\n return Type.Integer(options);\n case \"boolean\":\n return Type.Boolean(options);\n case \"null\":\n return Type.Null(options);\n default:\n return Type.Unknown(options);\n }\n}\n\ninterface RunSubagentOptions<TOutputSchema extends TSchema | undefined = undefined> {\n request: SubagentRunRequest<TOutputSchema>;\n defaultModel: Model<Api>;\n thinkingLevel: ThinkingLevel;\n models: MikanModels;\n workspaceDir: string;\n availableTools: AgentTool[];\n /**\n * The one seam through which a run's spend reaches its initiator (e.g. the\n * parent session's budget). Called exactly once per run with the final\n * totals — on every terminal path, including never-reject failures —\n * before the result is returned. Errors thrown here are logged and\n * swallowed to preserve the never-reject contract.\n */\n onUsage?: (usage: { tokens: number; costUsd: number }) => void | Promise<void>;\n}\n\nfunction resolveBudget(budget: RunSubagentOptions[\"request\"][\"budget\"]) {\n const resolved = { ...DEFAULT_SUBAGENT_BUDGET, ...budget };\n const positiveIntegerFields = [\n [\"maxTurns\", resolved.maxTurns],\n [\"maxTokens\", resolved.maxTokens],\n [\"maxDurationMs\", resolved.maxDurationMs],\n ] as const;\n for (const [name, value] of positiveIntegerFields) {\n if (value !== undefined && (!Number.isInteger(value) || value <= 0)) {\n throw new Error(`api.subagent.run budget.${name} must be a positive integer`);\n }\n }\n if (!Number.isFinite(resolved.maxCostUsd) || resolved.maxCostUsd < 0) {\n throw new Error(\"api.subagent.run budget.maxCostUsd must be a non-negative number\");\n }\n return resolved;\n}\n\nfunction selectTools(requested: string[] | undefined, available: AgentTool[]): AgentTool[] {\n if (!requested || requested.length === 0) return [];\n const byName = new Map<string, AgentTool>();\n for (const tool of available) {\n if (!byName.has(tool.name)) byName.set(tool.name, tool);\n }\n const selected: AgentTool[] = [];\n for (const name of new Set(requested)) {\n const tool = byName.get(name);\n if (!tool) throw new Error(`Unknown or unavailable subagent tool: ${name}`);\n selected.push(tool);\n }\n return selected;\n}\n\nfunction formatTask(task: string, input: unknown): string {\n const trimmed = task.trim();\n if (!trimmed) throw new Error(\"api.subagent.run requires a non-empty task\");\n if (input === undefined) return trimmed;\n let serialized: string | undefined;\n try {\n serialized = JSON.stringify(input, null, 2);\n } catch (err) {\n throw new Error(\n `api.subagent.run input must be JSON-serializable: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n if (serialized === undefined) {\n throw new Error(\"api.subagent.run input must be JSON-serializable\");\n }\n return `${trimmed}\\n\\nInput:\\n${serialized}`;\n}\n\nfunction buildSystemPrompt(base: string | undefined, outputSchema: TSchema | undefined): string {\n const prompt = base?.trim() || DEFAULT_SYSTEM_PROMPT;\n if (!outputSchema) return prompt;\n return [\n prompt,\n \"\",\n \"Return only one JSON value matching this JSON Schema. Do not use Markdown or code fences.\",\n JSON.stringify(outputSchema),\n ].join(\"\\n\");\n}\n\nfunction finalAssistant(messages: AgentMessage[]): AssistantMessage | undefined {\n for (let index = messages.length - 1; index >= 0; index--) {\n const message = messages[index];\n if (message.role === \"assistant\") return message;\n }\n return undefined;\n}\n\nfunction assistantText(message: AssistantMessage | undefined): string {\n if (!message) return \"\";\n return message.content\n .filter((part) => part.type === \"text\")\n .map((part) => part.text)\n .join(\"\");\n}\n\n/**\n * Execute one non-recursive, fresh subagent run. Never rejects: every\n * failure — including request validation — is a result with a terminal\n * status, so batch callers (`tasks` / `dag`) can never orphan in-flight\n * sibling runs on one bad request. The run's spend is reported through\n * `onUsage` before the result is returned.\n */\nexport async function runSubagent<TOutputSchema extends TSchema | undefined = undefined>(\n options: RunSubagentOptions<TOutputSchema>,\n): Promise<SubagentRunResult<SubagentRunOutput<TOutputSchema>>> {\n const result = await executeSubagentRun(options);\n try {\n await options.onUsage?.({ tokens: result.tokens, costUsd: result.costUsd });\n } catch (err) {\n log.logWarning(\"Subagent onUsage listener failed\", String(err));\n }\n return result;\n}\n\nasync function executeSubagentRun<TOutputSchema extends TSchema | undefined = undefined>(\n options: RunSubagentOptions<TOutputSchema>,\n): Promise<SubagentRunResult<SubagentRunOutput<TOutputSchema>>> {\n const { request } = options;\n const runId = randomUUID();\n const startedAt = Date.now();\n let modelSpec: SubagentModelSpec = request.model ?? {\n provider: options.defaultModel.provider,\n id: options.defaultModel.id,\n };\n let sessionRef: MikanAgentSession | undefined;\n let terminalSignal: \"cancelled\" | \"timeout\" | undefined;\n let timeout: NodeJS.Timeout | undefined;\n const abort = (reason: \"cancelled\" | \"timeout\") => {\n if (terminalSignal) return;\n terminalSignal = reason;\n sessionRef?.abort();\n };\n const onAbort = () => abort(\"cancelled\");\n\n try {\n if ((subagentRunDepth.getStore() ?? 0) >= 1) {\n throw new Error(\"Nested api.subagent.run calls are not allowed\");\n }\n const model = request.model\n ? options.models.resolve(request.model.provider, request.model.id)\n : options.defaultModel;\n modelSpec = { provider: model.provider, id: model.id };\n const tools = selectTools(request.tools, options.availableTools);\n const task = formatTask(request.task, request.input);\n const budget = resolveBudget(request.budget);\n const session = new MikanAgentSession({\n systemPrompt: buildSystemPrompt(request.systemPrompt, request.outputSchema),\n model,\n thinkingLevel: options.thinkingLevel,\n tools,\n models: options.models,\n sessionStore: SessionStore.inMemory(options.workspaceDir),\n settings: { compaction: { enabled: false } },\n });\n sessionRef = session;\n\n request.signal?.addEventListener(\"abort\", onAbort, { once: true });\n if (request.signal?.aborted) abort(\"cancelled\");\n timeout = setTimeout(() => abort(\"timeout\"), budget.maxDurationMs);\n timeout.unref();\n\n if (!terminalSignal) {\n await subagentRunDepth.run(1, () =>\n session.prompt(task, {\n budget: {\n maxLlmCalls: budget.maxTurns,\n maxTokens: budget.maxTokens,\n maxCostUsd: budget.maxCostUsd,\n maxDurationMs: budget.maxDurationMs,\n },\n }),\n );\n }\n\n const stats = session.getLastRunStats();\n const assistant = finalAssistant(session.messages);\n const text = assistantText(assistant);\n const base = {\n runId,\n model: modelSpec,\n turns: stats.llmCalls,\n tokens: stats.tokens,\n costUsd: stats.costUsd,\n durationMs: Date.now() - startedAt,\n ...(text ? { text } : {}),\n };\n\n if (terminalSignal) return { ...base, status: terminalSignal };\n if (stats.budgetExceededReason) {\n return {\n ...base,\n status: \"budget_exceeded\",\n error: stats.budgetExceededReason,\n };\n }\n if (assistant?.stopReason === \"error\") {\n return {\n ...base,\n status: \"failed\",\n error: assistant.errorMessage || \"Subagent failed\",\n };\n }\n if (!assistant) {\n return { ...base, status: \"failed\", error: \"Subagent produced no assistant response\" };\n }\n\n if (request.outputSchema) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return { ...base, status: \"invalid_output\", error: \"Subagent output is not valid JSON\" };\n }\n if (!Value.Check(hydrateSchema(request.outputSchema), parsed)) {\n return {\n ...base,\n status: \"invalid_output\",\n error: \"Subagent output does not match the requested schema\",\n };\n }\n return {\n ...base,\n status: \"completed\",\n output: parsed as SubagentRunOutput<TOutputSchema>,\n };\n }\n\n if (!text) {\n return { ...base, status: \"failed\", error: \"Subagent produced no text output\" };\n }\n return {\n ...base,\n status: \"completed\",\n output: text as SubagentRunOutput<TOutputSchema>,\n };\n } catch (err) {\n const stats = sessionRef?.getLastRunStats();\n return {\n runId,\n status: terminalSignal ?? \"failed\",\n model: modelSpec,\n turns: stats?.llmCalls ?? 0,\n tokens: stats?.tokens ?? 0,\n costUsd: stats?.costUsd ?? 0,\n durationMs: Date.now() - startedAt,\n error: err instanceof Error ? err.message : String(err),\n };\n } finally {\n if (timeout) clearTimeout(timeout);\n request.signal?.removeEventListener(\"abort\", onAbort);\n }\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
export { defaultCommandHandlers, dispatchCommand } from "./commands/registry.js";
|
|
2
2
|
export * from "./harness/index.js";
|
|
3
3
|
export type { CommandContext, CommandHandler, CommandServices } from "./commands/types.js";
|
|
4
|
-
export * from "./sessions/
|
|
4
|
+
export * from "./sessions/chat-history-sync.js";
|
|
5
5
|
export * from "./sessions/metadata.js";
|
|
6
6
|
export * from "./sessions/policy.js";
|
|
7
7
|
export * from "./sessions/store.js";
|
|
8
8
|
export { createConversationRuntime, type RunSessionOptions, type ConversationRuntime, type ConversationRuntimeOptions, } from "./runtime/conversation-runtime.js";
|
|
9
9
|
export type { MessagingBot, ConversationContext, ConversationEvent, MessagingEventHandler, ChatAdapter, ConversationMessage, ConversationResponder, ChatToolResult, ConversationKind, MessagingInfo, RunningSession, } from "./adapter.js";
|
|
10
|
-
export { SandboxError, createExecutor, getSandboxAdapters, parseSandboxArg, validateSandbox, } from "./sandbox/index.js";
|
|
10
|
+
export { SandboxError, configureGondolinRuntime, createExecutor, getSandboxAdapters, parseSandboxArg, validateSandbox, type GondolinBootstrapOptions, } from "./sandbox/index.js";
|
|
11
11
|
export type { CloudflareSandboxConfig, ExecOptions, ExecResult, Executor, SandboxAdapter, SandboxConfig, } from "./sandbox/index.js";
|
|
12
12
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACjF,cAAc,oBAAoB,CAAC;AACnC,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3F,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACjF,cAAc,oBAAoB,CAAC;AACnC,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3F,cAAc,iCAAiC,CAAC;AAChD,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EACL,yBAAyB,EACzB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,0BAA0B,GAChC,MAAM,mCAAmC,CAAC;AAC3C,YAAY,EACV,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,WAAW,EACX,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,YAAY,EACZ,wBAAwB,EACxB,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,KAAK,wBAAwB,GAC9B,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,uBAAuB,EACvB,WAAW,EACX,UAAU,EACV,QAAQ,EACR,cAAc,EACd,aAAa,GACd,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export { defaultCommandHandlers, dispatchCommand } from "./commands/registry.js";
|
|
2
2
|
export * from "./harness/index.js";
|
|
3
|
-
export * from "./sessions/
|
|
3
|
+
export * from "./sessions/chat-history-sync.js";
|
|
4
4
|
export * from "./sessions/metadata.js";
|
|
5
5
|
export * from "./sessions/policy.js";
|
|
6
6
|
export * from "./sessions/store.js";
|
|
7
7
|
export { createConversationRuntime, } from "./runtime/conversation-runtime.js";
|
|
8
|
-
export { SandboxError, createExecutor, getSandboxAdapters, parseSandboxArg, validateSandbox, } from "./sandbox/index.js";
|
|
8
|
+
export { SandboxError, configureGondolinRuntime, createExecutor, getSandboxAdapters, parseSandboxArg, validateSandbox, } from "./sandbox/index.js";
|
|
9
9
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACjF,cAAc,oBAAoB,CAAC;AAEnC,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACjF,cAAc,oBAAoB,CAAC;AAEnC,cAAc,iCAAiC,CAAC;AAChD,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EACL,yBAAyB,GAI1B,MAAM,mCAAmC,CAAC;AAc3C,OAAO,EACL,YAAY,EACZ,wBAAwB,EACxB,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,eAAe,GAEhB,MAAM,oBAAoB,CAAC","sourcesContent":["export { defaultCommandHandlers, dispatchCommand } from \"./commands/registry.js\";\nexport * from \"./harness/index.js\";\nexport type { CommandContext, CommandHandler, CommandServices } from \"./commands/types.js\";\nexport * from \"./sessions/chat-history-sync.js\";\nexport * from \"./sessions/metadata.js\";\nexport * from \"./sessions/policy.js\";\nexport * from \"./sessions/store.js\";\nexport {\n createConversationRuntime,\n type RunSessionOptions,\n type ConversationRuntime,\n type ConversationRuntimeOptions,\n} from \"./runtime/conversation-runtime.js\";\nexport type {\n MessagingBot,\n ConversationContext,\n ConversationEvent,\n MessagingEventHandler,\n ChatAdapter,\n ConversationMessage,\n ConversationResponder,\n ChatToolResult,\n ConversationKind,\n MessagingInfo,\n RunningSession,\n} from \"./adapter.js\";\nexport {\n SandboxError,\n configureGondolinRuntime,\n createExecutor,\n getSandboxAdapters,\n parseSandboxArg,\n validateSandbox,\n type GondolinBootstrapOptions,\n} from \"./sandbox/index.js\";\nexport type {\n CloudflareSandboxConfig,\n ExecOptions,\n ExecResult,\n Executor,\n SandboxAdapter,\n SandboxConfig,\n} from \"./sandbox/index.js\";\n"]}
|
package/dist/main.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import "./observability/instrument.js";
|
|
3
|
-
import { join
|
|
3
|
+
import { join } from "path";
|
|
4
4
|
import { mkdirSync, statSync, writeFileSync } from "fs";
|
|
5
|
-
import { homedir } from "os";
|
|
6
5
|
import { fileURLToPath } from "url";
|
|
7
6
|
import { dirname, join as pathJoin } from "path";
|
|
8
7
|
import { DiscordMessagingBot } from "./adapters/discord/bot.js";
|
|
@@ -19,19 +18,21 @@ import { InMemoryAdminTokenStore } from "./web/admin/store.js";
|
|
|
19
18
|
import { InMemoryLinkTokenStore } from "./web/login/store.js";
|
|
20
19
|
import { InMemorySessionViewTokenStore } from "./web/session-view/store.js";
|
|
21
20
|
import { DockerContainerManager } from "./provisioner.js";
|
|
22
|
-
import { assertStateDirOutsideWorkspace, createGlobalSettingsFile, loadGlobalSettings, MissingGlobalSettingsError, } from "./config.js";
|
|
21
|
+
import { assertStateDirOutsideWorkspace, createGlobalSettingsFile, loadGlobalSettings, MissingGlobalSettingsError, resolveLinkBaseUrl, } from "./config.js";
|
|
23
22
|
import { configureHttpDispatcher, defaultAuthPath, defaultModelsJsonPath, parseHttpIdleTimeoutMs, } from "./harness/index.js";
|
|
24
23
|
import { existsSync, readFileSync } from "fs";
|
|
25
24
|
import { readEnv, setEnvAliases } from "./utils/env.js";
|
|
26
25
|
import { ensureDirExists, isRecord, readJsonFileIfExists } from "./utils/file-guards.js";
|
|
27
|
-
import { SandboxError,
|
|
28
|
-
import {
|
|
26
|
+
import { SandboxError, validateSandbox } from "./sandbox/index.js";
|
|
27
|
+
import { helpText, resolveBoot } from "./cli/boot.js";
|
|
28
|
+
import { envReport, noPlatformsMessage, platformIsActive } from "./env-manifest.js";
|
|
29
|
+
import { disconnectAllGondolinRuntimes, gondolinResources, stopIdleGondolinVms, sweepUnadoptedGondolinWorkers, } from "./sandbox/gondolin.js";
|
|
30
|
+
import { configureGondolinRuntime } from "./sandbox/gondolin-bootstrap.js";
|
|
29
31
|
import { gondolinInventory } from "./sandbox/gondolin-inventory.js";
|
|
30
32
|
import { gondolinFleet } from "./sandbox/gondolin-fleet.js";
|
|
31
33
|
import { gondolinGateway } from "./sandbox/gondolin-gateway.js";
|
|
32
34
|
import { gondolinJoin } from "./sandbox/gondolin-join.js";
|
|
33
35
|
import { checkWorkspaceExported } from "./sandbox/gondolin-nfs-advisory.js";
|
|
34
|
-
import { gondolinPlacements } from "./sandbox/gondolin-placement.js";
|
|
35
36
|
import { FileVaultManager } from "./vault/index.js";
|
|
36
37
|
import { runExtCommand } from "./cli/ext.js";
|
|
37
38
|
import { createConversationRuntime } from "./runtime/conversation-runtime.js";
|
|
@@ -63,61 +64,11 @@ const GITHUB_REPOS = readEnv("GITHUB_REPOS");
|
|
|
63
64
|
const GITHUB_POLL_INTERVAL = readEnv("GITHUB_POLL_INTERVAL");
|
|
64
65
|
const GOOGLE_APPLICATION_CREDENTIALS = readEnv("GOOGLE_APPLICATION_CREDENTIALS");
|
|
65
66
|
const GOOGLE_CLOUD_PROJECT = readEnv("GOOGLE_CLOUD_PROJECT");
|
|
66
|
-
|
|
67
|
+
// Externally-visible base URL of the link/OAuth server; the env read and
|
|
68
|
+
// trailing-slash normalization live in config.resolveLinkBaseUrl.
|
|
69
|
+
const LINK_BASE_URL = resolveLinkBaseUrl();
|
|
67
70
|
const LINK_PORT_RAW = readEnv("LINK_PORT");
|
|
68
|
-
const LINK_PORT = LINK_PORT_RAW ? parseInt(LINK_PORT_RAW, 10) :
|
|
69
|
-
function parseArgs() {
|
|
70
|
-
const args = process.argv.slice(2);
|
|
71
|
-
let sandbox = { type: "host" };
|
|
72
|
-
let workingDir;
|
|
73
|
-
let stateDirArg;
|
|
74
|
-
let downloadChannelId;
|
|
75
|
-
let showOnboard = false;
|
|
76
|
-
let showVersion = false;
|
|
77
|
-
let mintWorkerToken = false;
|
|
78
|
-
for (let i = 0; i < args.length; i++) {
|
|
79
|
-
const arg = args[i];
|
|
80
|
-
if (arg === "--version" || arg === "-v" || arg === "-V") {
|
|
81
|
-
showVersion = true;
|
|
82
|
-
}
|
|
83
|
-
else if (arg === "--onboard") {
|
|
84
|
-
showOnboard = true;
|
|
85
|
-
}
|
|
86
|
-
else if (arg === "--worker-token") {
|
|
87
|
-
mintWorkerToken = true;
|
|
88
|
-
}
|
|
89
|
-
else if (arg.startsWith("--sandbox=")) {
|
|
90
|
-
sandbox = parseSandboxArg(arg.slice("--sandbox=".length));
|
|
91
|
-
}
|
|
92
|
-
else if (arg === "--sandbox") {
|
|
93
|
-
sandbox = parseSandboxArg(args[++i] || "");
|
|
94
|
-
}
|
|
95
|
-
else if (arg.startsWith("--state-dir=")) {
|
|
96
|
-
stateDirArg = arg.slice("--state-dir=".length);
|
|
97
|
-
}
|
|
98
|
-
else if (arg === "--state-dir") {
|
|
99
|
-
stateDirArg = args[++i];
|
|
100
|
-
}
|
|
101
|
-
else if (arg.startsWith("--download=")) {
|
|
102
|
-
downloadChannelId = arg.slice("--download=".length);
|
|
103
|
-
}
|
|
104
|
-
else if (arg === "--download") {
|
|
105
|
-
downloadChannelId = args[++i];
|
|
106
|
-
}
|
|
107
|
-
else if (!arg.startsWith("-")) {
|
|
108
|
-
workingDir = arg;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
return {
|
|
112
|
-
workingDir: workingDir ? resolve(workingDir) : undefined,
|
|
113
|
-
stateDir: stateDirArg ? resolve(stateDirArg) : undefined,
|
|
114
|
-
sandbox,
|
|
115
|
-
downloadChannel: downloadChannelId,
|
|
116
|
-
showOnboard,
|
|
117
|
-
showVersion,
|
|
118
|
-
mintWorkerToken,
|
|
119
|
-
};
|
|
120
|
-
}
|
|
71
|
+
const LINK_PORT = LINK_PORT_RAW ? parseInt(LINK_PORT_RAW, 10) : LINK_BASE_URL ? 8181 : undefined;
|
|
121
72
|
const WORLD_WRITABLE_MODE = 0o002;
|
|
122
73
|
function ensureSecureStateDir(path) {
|
|
123
74
|
let stat;
|
|
@@ -173,31 +124,38 @@ function handleStartupError(error) {
|
|
|
173
124
|
console.error(String(error));
|
|
174
125
|
process.exit(1);
|
|
175
126
|
}
|
|
176
|
-
|
|
177
|
-
// bot-mode argument parsing (which requires a workspace dir and tokens).
|
|
178
|
-
if (process.argv[2] === "ext") {
|
|
179
|
-
const code = await runExtCommand(process.argv.slice(3));
|
|
180
|
-
process.exit(code);
|
|
181
|
-
}
|
|
182
|
-
let parsedArgs;
|
|
127
|
+
let plan;
|
|
183
128
|
try {
|
|
184
|
-
|
|
129
|
+
plan = resolveBoot();
|
|
185
130
|
}
|
|
186
131
|
catch (error) {
|
|
187
132
|
handleStartupError(error);
|
|
188
133
|
}
|
|
134
|
+
// `mikan ext …` manages extensions and exits; handle it before the normal
|
|
135
|
+
// bot-mode startup (which requires platform tokens).
|
|
136
|
+
if (plan.mode === "ext") {
|
|
137
|
+
const code = await runExtCommand(plan.extArgs ?? []);
|
|
138
|
+
process.exit(code);
|
|
139
|
+
}
|
|
189
140
|
// Global fetch: proxy support (HTTP_PROXY/HTTPS_PROXY/NO_PROXY) and idle
|
|
190
141
|
// timeouts so a stalled LLM stream errors out instead of hanging a session.
|
|
191
142
|
const httpIdleTimeoutMs = parseHttpIdleTimeoutMs(readEnv("HTTP_IDLE_TIMEOUT"));
|
|
192
143
|
configureHttpDispatcher(httpIdleTimeoutMs);
|
|
193
|
-
|
|
194
|
-
|
|
144
|
+
if (plan.mode === "help") {
|
|
145
|
+
console.log(helpText());
|
|
146
|
+
process.exit(0);
|
|
147
|
+
}
|
|
148
|
+
if (plan.mode === "env") {
|
|
149
|
+
console.log(envReport());
|
|
150
|
+
process.exit(0);
|
|
151
|
+
}
|
|
152
|
+
if (plan.mode === "version") {
|
|
195
153
|
console.log(getVersion());
|
|
196
154
|
process.exit(0);
|
|
197
155
|
}
|
|
198
156
|
// Handle --worker-token: mint a one-time join token for a dial-home worker
|
|
199
|
-
if (
|
|
200
|
-
const stateDir =
|
|
157
|
+
if (plan.mode === "worker-token") {
|
|
158
|
+
const stateDir = plan.stateDir;
|
|
201
159
|
setEnvAliases("STATE_DIR", stateDir);
|
|
202
160
|
ensureSecureStateDir(stateDir);
|
|
203
161
|
gondolinJoin.configure(join(stateDir, "gondolin-gateway"));
|
|
@@ -231,14 +189,14 @@ if (parsedArgs.mintWorkerToken) {
|
|
|
231
189
|
}
|
|
232
190
|
}
|
|
233
191
|
// Handle --onboard mode
|
|
234
|
-
if (
|
|
235
|
-
const stateDir =
|
|
192
|
+
if (plan.mode === "onboard") {
|
|
193
|
+
const stateDir = plan.stateDir;
|
|
236
194
|
setEnvAliases("STATE_DIR", stateDir);
|
|
237
195
|
ensureSecureStateDir(stateDir);
|
|
238
196
|
try {
|
|
239
197
|
const settingsPath = createGlobalSettingsFile(stateDir);
|
|
240
198
|
console.log(`Created global settings at ${settingsPath}`);
|
|
241
|
-
console.log(
|
|
199
|
+
console.log(`Review the file, then start mikan (workspace defaults to ${join(stateDir, "workspace")}).`);
|
|
242
200
|
process.exit(0);
|
|
243
201
|
}
|
|
244
202
|
catch (err) {
|
|
@@ -247,44 +205,36 @@ if (parsedArgs.showOnboard) {
|
|
|
247
205
|
}
|
|
248
206
|
}
|
|
249
207
|
// Handle --download mode (Slack only)
|
|
250
|
-
if (
|
|
208
|
+
if (plan.mode === "download" && plan.downloadChannel) {
|
|
251
209
|
if (!SLACK_BOT_TOKEN) {
|
|
252
210
|
console.error("Missing env: SLACK_BOT_TOKEN");
|
|
253
211
|
process.exit(1);
|
|
254
212
|
}
|
|
255
|
-
await downloadChannel(
|
|
213
|
+
await downloadChannel(plan.downloadChannel, SLACK_BOT_TOKEN);
|
|
256
214
|
process.exit(0);
|
|
257
215
|
}
|
|
258
|
-
// Normal bot mode -
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
console.error(" mikan --download <channel-id>");
|
|
263
|
-
process.exit(1);
|
|
264
|
-
}
|
|
265
|
-
const { workingDir, sandbox } = { workingDir: parsedArgs.workingDir, sandbox: parsedArgs.sandbox };
|
|
266
|
-
const stateDir = parsedArgs.stateDir ?? join(homedir(), ".mikan");
|
|
216
|
+
// Normal bot mode - working dir is optional and defaults under the state dir
|
|
217
|
+
const sandbox = plan.sandbox;
|
|
218
|
+
const stateDir = plan.stateDir;
|
|
219
|
+
const workingDir = plan.workingDir;
|
|
267
220
|
setEnvAliases("STATE_DIR", stateDir);
|
|
268
221
|
ensureSecureStateDir(stateDir);
|
|
222
|
+
if (!plan.workingDirExplicit) {
|
|
223
|
+
ensureDirExists(workingDir);
|
|
224
|
+
}
|
|
269
225
|
try {
|
|
270
226
|
assertStateDirOutsideWorkspace(stateDir, workingDir, sandbox.type);
|
|
271
227
|
}
|
|
272
228
|
catch (error) {
|
|
273
229
|
handleStartupError(error);
|
|
274
230
|
}
|
|
275
|
-
// Validate platform tokens
|
|
276
|
-
const hasSlack =
|
|
277
|
-
const hasTelegram =
|
|
278
|
-
const hasDiscord =
|
|
279
|
-
const hasGithub =
|
|
280
|
-
GITHUB_INSTALLATION_ID &&
|
|
281
|
-
(GITHUB_APP_PRIVATE_KEY || GITHUB_APP_PRIVATE_KEY_PATH));
|
|
231
|
+
// Validate platform tokens — activation rules live in the env manifest.
|
|
232
|
+
const hasSlack = platformIsActive("slack");
|
|
233
|
+
const hasTelegram = platformIsActive("telegram");
|
|
234
|
+
const hasDiscord = platformIsActive("discord");
|
|
235
|
+
const hasGithub = platformIsActive("github");
|
|
282
236
|
if (!hasSlack && !hasTelegram && !hasDiscord && !hasGithub) {
|
|
283
|
-
console.error(
|
|
284
|
-
" Slack: SLACK_APP_TOKEN + SLACK_BOT_TOKEN\n" +
|
|
285
|
-
" Telegram: TELEGRAM_BOT_TOKEN\n" +
|
|
286
|
-
" Discord: DISCORD_BOT_TOKEN\n" +
|
|
287
|
-
" GitHub: GITHUB_APP_ID + GITHUB_INSTALLATION_ID + GITHUB_APP_PRIVATE_KEY(_PATH)");
|
|
237
|
+
console.error(noPlatformsMessage());
|
|
288
238
|
process.exit(1);
|
|
289
239
|
}
|
|
290
240
|
try {
|
|
@@ -326,19 +276,17 @@ const provisioner = sandbox.type === "image"
|
|
|
326
276
|
})
|
|
327
277
|
: undefined;
|
|
328
278
|
if (sandbox.type === "gondolin") {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
handleStartupError(error);
|
|
341
|
-
}
|
|
279
|
+
try {
|
|
280
|
+
configureGondolinRuntime({
|
|
281
|
+
stateDir,
|
|
282
|
+
limits: sandboxLimits,
|
|
283
|
+
boostLimits: sandboxBoostLimits,
|
|
284
|
+
remote: sandboxSettings?.gondolin?.remote,
|
|
285
|
+
requireRemote: sandbox.profile === "remote",
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
catch (error) {
|
|
289
|
+
handleStartupError(error);
|
|
342
290
|
}
|
|
343
291
|
}
|
|
344
292
|
const resourceController = sandbox.type === "image"
|
|
@@ -364,8 +312,8 @@ setInterval(() => linkTokenStore.purge(), 5 * 60 * 1000).unref();
|
|
|
364
312
|
setInterval(() => sessionViewTokenStore.purge(), 5 * 60 * 1000).unref();
|
|
365
313
|
setInterval(() => adminTokenStore.purge(), 5 * 60 * 1000).unref();
|
|
366
314
|
function portalBaseUrl() {
|
|
367
|
-
if (
|
|
368
|
-
return
|
|
315
|
+
if (LINK_BASE_URL)
|
|
316
|
+
return LINK_BASE_URL;
|
|
369
317
|
if (LINK_PORT)
|
|
370
318
|
return `http://localhost:${LINK_PORT}`;
|
|
371
319
|
return undefined;
|
|
@@ -452,14 +400,14 @@ function buildPlatformToolPackFactories() {
|
|
|
452
400
|
if (!hasGithub)
|
|
453
401
|
return [];
|
|
454
402
|
const platformGithubOps = {
|
|
455
|
-
pushAndCreatePr: (conversationId, request) => requireGithubBot("github_pr").pushAndCreatePr(conversationId, request),
|
|
456
|
-
getChecks: (conversationId, branch) => requireGithubBot("github_checks").getChecks(conversationId, branch),
|
|
457
|
-
getJobLog: (conversationId, jobId) => requireGithubBot("github_checks").getJobLog(conversationId, jobId),
|
|
458
|
-
getBuildLog: (conversationId, buildId) => requireGithubBot("github_checks").getBuildLog(conversationId, buildId),
|
|
459
|
-
replyToReviewThread: (conversationId, commentId, body) => requireGithubBot("github_review_reply").replyToReviewThread(conversationId, commentId, body),
|
|
460
|
-
syncRepo: (conversationId, branch) => requireGithubBot("github_sync").syncRepo(conversationId, branch),
|
|
461
|
-
readGithub: (conversationId, request) => requireGithubBot("github_read").readGithub(conversationId, request),
|
|
462
|
-
manageIssue: (conversationId, request) => requireGithubBot("github_issue").manageIssue(conversationId, request),
|
|
403
|
+
pushAndCreatePr: (conversationId, request) => requireGithubBot("github_pr").ops.pushAndCreatePr(conversationId, request),
|
|
404
|
+
getChecks: (conversationId, branch) => requireGithubBot("github_checks").ops.getChecks(conversationId, branch),
|
|
405
|
+
getJobLog: (conversationId, jobId) => requireGithubBot("github_checks").ops.getJobLog(conversationId, jobId),
|
|
406
|
+
getBuildLog: (conversationId, buildId) => requireGithubBot("github_checks").ops.getBuildLog(conversationId, buildId),
|
|
407
|
+
replyToReviewThread: (conversationId, commentId, body) => requireGithubBot("github_review_reply").ops.replyToReviewThread(conversationId, commentId, body),
|
|
408
|
+
syncRepo: (conversationId, branch) => requireGithubBot("github_sync").ops.syncRepo(conversationId, branch),
|
|
409
|
+
readGithub: (conversationId, request) => requireGithubBot("github_read").ops.readGithub(conversationId, request),
|
|
410
|
+
manageIssue: (conversationId, request) => requireGithubBot("github_issue").ops.manageIssue(conversationId, request),
|
|
463
411
|
};
|
|
464
412
|
return [() => createGithubToolPack(platformGithubOps)];
|
|
465
413
|
}
|