@jmanuelcorral/openteam 0.27.1 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.opencode/openteam.example.json +7 -1
- package/README.es.md +19 -1
- package/README.md +25 -1
- package/dist/certificates/graph-release-certificate.json +2 -2
- package/dist/certificates/graph-shadow-certificate.json +2 -2
- package/dist/certificates/opencode-2.0.5/graph-release-certificate.json +2 -2
- package/dist/certificates/opencode-2.0.5/graph-shadow-certificate.json +2 -2
- package/dist/cli.js +1609 -248
- package/dist/config/errors.d.ts.map +1 -1
- package/dist/config/schema.d.ts +18 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/console/agentView.d.ts +13 -0
- package/dist/console/agentView.d.ts.map +1 -0
- package/dist/console/assets.d.ts.map +1 -1
- package/dist/console/inspector.d.ts.map +1 -1
- package/dist/console/refresh.d.ts +1 -1
- package/dist/console/refresh.d.ts.map +1 -1
- package/dist/console/render.d.ts +1 -0
- package/dist/console/render.d.ts.map +1 -1
- package/dist/graph/schema.d.ts +6 -0
- package/dist/graph/schema.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1207 -403
- package/dist/lifecycle/contracts.d.ts +2 -2
- package/dist/lifecycle/contracts.d.ts.map +1 -1
- package/dist/lifecycle/schema.d.ts +6 -0
- package/dist/lifecycle/schema.d.ts.map +1 -1
- package/dist/local/concurrency.d.ts +1 -1
- package/dist/local/concurrency.d.ts.map +1 -1
- package/dist/messages/agentView.d.ts +77 -0
- package/dist/messages/agentView.d.ts.map +1 -0
- package/dist/messages/consoleDetail.d.ts +9 -0
- package/dist/messages/consoleDetail.d.ts.map +1 -1
- package/dist/messages/orchestration.d.ts +26 -0
- package/dist/messages/orchestration.d.ts.map +1 -1
- package/dist/opencodeArtifacts/orchestratorAgent.d.ts.map +1 -1
- package/dist/orchestrator/coordinator.d.ts +13 -1
- package/dist/orchestrator/coordinator.d.ts.map +1 -1
- package/dist/orchestrator/outputContract.d.ts +3 -0
- package/dist/orchestrator/outputContract.d.ts.map +1 -1
- package/dist/orchestrator/reportDelivery.d.ts +13 -0
- package/dist/orchestrator/reportDelivery.d.ts.map +1 -0
- package/dist/orchestrator/subsessions.d.ts +5 -0
- package/dist/orchestrator/subsessions.d.ts.map +1 -1
- package/dist/orchestrator/taskEffort.d.ts +39 -0
- package/dist/orchestrator/taskEffort.d.ts.map +1 -0
- package/dist/plugin/capture.d.ts +3 -0
- package/dist/plugin/capture.d.ts.map +1 -1
- package/dist/plugin/nativeHost.d.ts.map +1 -1
- package/dist/plugin/nativeHostContext.d.ts +1 -1
- package/dist/plugin/nativeHostContext.d.ts.map +1 -1
- package/dist/plugin/nativeSessions.d.ts +9 -0
- package/dist/plugin/nativeSessions.d.ts.map +1 -1
- package/dist/plugin/orchestrateTool.d.ts +6 -0
- package/dist/plugin/orchestrateTool.d.ts.map +1 -1
- package/dist/plugin/reportTool.d.ts +4 -0
- package/dist/plugin/reportTool.d.ts.map +1 -0
- package/dist/plugin/runtimeContext.d.ts +14 -0
- package/dist/plugin/runtimeContext.d.ts.map +1 -1
- package/dist/plugin/toolcalls.d.ts +9 -1
- package/dist/plugin/toolcalls.d.ts.map +1 -1
- package/dist/storage/scopedArtifacts.d.ts +7 -0
- package/dist/storage/scopedArtifacts.d.ts.map +1 -0
- package/dist/telemetry/aggregate.d.ts +7 -0
- package/dist/telemetry/aggregate.d.ts.map +1 -1
- package/dist/telemetry/events.d.ts +68 -2
- package/dist/telemetry/events.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ import { exec, execFile as execFile4 } from "node:child_process";
|
|
|
7
7
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
8
8
|
import { mkdir as mkdir5, readFile as readFile6, writeFile as writeFile2 } from "node:fs/promises";
|
|
9
9
|
import { createRequire as createRequire2 } from "node:module";
|
|
10
|
-
import { dirname as
|
|
10
|
+
import { dirname as dirname12, resolve as resolve19 } from "node:path";
|
|
11
11
|
import { promisify as promisify3 } from "node:util";
|
|
12
12
|
import {
|
|
13
13
|
confirm as clackConfirm,
|
|
@@ -577,6 +577,15 @@ function migrateConfig(raw) {
|
|
|
577
577
|
var consoleDetailMessages = {
|
|
578
578
|
runtimeStateCleanupFailed: "The Console runtime state could not be published and its staging file could not be removed.",
|
|
579
579
|
requestFailed: "The local opencode request failed.",
|
|
580
|
+
usageUnavailable: "Unavailable / partial",
|
|
581
|
+
usageCaution: "The host did not report trustworthy usage for every message. Counters are not confirmed totals; no token rate or real savings can be inferred.",
|
|
582
|
+
timingUnknown: "Unknown",
|
|
583
|
+
estimatedCost: "Estimated cost",
|
|
584
|
+
estimatedBaseline: "Estimated baseline",
|
|
585
|
+
estimatedSavings: "Estimated savings",
|
|
586
|
+
estimatedInput: "Estimated tokens in",
|
|
587
|
+
estimatedOutput: "Estimated tokens out",
|
|
588
|
+
estimatesNotUsage: "Routing estimates are separate from host-reported usage; they are not measured spend or proven savings.",
|
|
580
589
|
nativeToolFailed: "The native tool execution failed.",
|
|
581
590
|
follow: "Follow new activity",
|
|
582
591
|
metadataOnly: "Lifecycle and telemetry stay metadata-only.",
|
|
@@ -832,7 +841,13 @@ var OrchestratorConfigSchema = z2.object({
|
|
|
832
841
|
roles: OrchestratorRolesSchema,
|
|
833
842
|
primary: AgentExecutionPolicySchema.optional(),
|
|
834
843
|
maxRetries: z2.number().int().min(0).optional(),
|
|
835
|
-
maxModelsPerNode: z2.number().int().positive().optional()
|
|
844
|
+
maxModelsPerNode: z2.number().int().positive().optional(),
|
|
845
|
+
taskBudget: z2.object({
|
|
846
|
+
maxBatches: z2.number().int().min(1).max(1000).optional(),
|
|
847
|
+
maxAttempts: z2.number().int().min(1).max(1e4).optional(),
|
|
848
|
+
maxDurationMs: z2.number().int().min(1000).max(86400000).optional(),
|
|
849
|
+
maxDepth: z2.number().int().min(0).max(32).optional()
|
|
850
|
+
}).strict().optional()
|
|
836
851
|
}).strict();
|
|
837
852
|
var defaultFrontierModel = {
|
|
838
853
|
providerID: "google",
|
|
@@ -1497,6 +1512,32 @@ function withReportedModelSlots(runtime, reported, aliases) {
|
|
|
1497
1512
|
}
|
|
1498
1513
|
|
|
1499
1514
|
// src/messages/orchestration.ts
|
|
1515
|
+
var reportDeliveryMessages = {
|
|
1516
|
+
description: "Submit the active worker's substantive findings to its assigned durable report. No arbitrary paths or other sessions are accepted. This does not replace the coordinator's completion checks.",
|
|
1517
|
+
status: "Whether the assigned work is done or needs another bounded pass.",
|
|
1518
|
+
findings: "Concrete findings, changes, evidence and remaining work; at most 32768 characters.",
|
|
1519
|
+
assignmentConflict: "A report assignment is already active for this session.",
|
|
1520
|
+
noAssignment: "No active coordinator-owned report assignment exists for this session.",
|
|
1521
|
+
invalidReport: "Report delivery requires substantive findings and a valid done/continue status within 32768 characters.",
|
|
1522
|
+
unsafePath: "The private artifact path is unavailable, linked or outside the allowed boundary.",
|
|
1523
|
+
workspaceMismatch: "Orchestration directory must match the trusted host workspace; a model-authored directory cannot change report or session scope.",
|
|
1524
|
+
submitted: (path) => `Report persisted at ${path}. The coordinator will independently validate current, substantive completion.`
|
|
1525
|
+
};
|
|
1526
|
+
var taskEffortMessages = {
|
|
1527
|
+
cancelled: "Task execution was cancelled; no replacement attempt was dispatched.",
|
|
1528
|
+
createDeadline: "task-budget-exhausted: duration. Session creation did not settle before the deadline; no prompt was dispatched and retry is disabled.",
|
|
1529
|
+
ledgerInvalid: "The cumulative task-effort ledger is invalid or unavailable; orchestration is stopped rather than resetting its allowance.",
|
|
1530
|
+
exhausted: (reason) => `task-budget-exhausted: ${reason}. Keep existing work and reports. Another batch or worker cannot reset this task's allowance; a new root user turn starts a new task.`,
|
|
1531
|
+
summary: (batches, attempts, remainingMs, remainingBatches, remainingAttempts) => `Task effort: ${batches} batch(es), ${attempts} attempt(s), ${Math.max(0, Math.floor(remainingMs / 1000))}s remaining; ${remainingBatches} batch(es) and ${remainingAttempts} attempt(s) available.`
|
|
1532
|
+
};
|
|
1533
|
+
var executionPhaseMessages = {
|
|
1534
|
+
"model-request": "Model request",
|
|
1535
|
+
"tool-input": "Preparing tool input",
|
|
1536
|
+
"tool-execution": "Executing a tool",
|
|
1537
|
+
"report-validation": "Validating durable report",
|
|
1538
|
+
idle: "Session idle",
|
|
1539
|
+
unknown: "Session phase unavailable"
|
|
1540
|
+
};
|
|
1500
1541
|
var HOST_SESSION_REQUIRED = "Orchestration requires a nonempty host ToolContext sessionID.";
|
|
1501
1542
|
var PARENT_OVERRIDE_IGNORED = "parentSessionID override ignored: the trusted host ToolContext session owns this orchestration and its children. Programmatic callers must supply their parent as the ToolContext sessionID.";
|
|
1502
1543
|
var PARENT_SESSION_DESCRIPTION = "Legacy parent reference. Omit it: the trusted host ToolContext session is the parent. A differing payload value is ignored with an advisory.";
|
|
@@ -2359,15 +2400,29 @@ var MessageEventSchema = EventBaseSchema.extend({
|
|
|
2359
2400
|
tokensReasoning: z5.number().int().min(0),
|
|
2360
2401
|
tokensCacheRead: z5.number().int().min(0),
|
|
2361
2402
|
tokensCacheWrite: z5.number().int().min(0),
|
|
2362
|
-
durationMs: z5.number().int().min(0)
|
|
2403
|
+
durationMs: z5.number().int().min(0),
|
|
2404
|
+
usageStatus: z5.enum(["reported", "missing", "zero-unverified"]).optional(),
|
|
2405
|
+
costStatus: z5.enum(["reported", "unavailable"]).optional(),
|
|
2406
|
+
finish: z5.enum([
|
|
2407
|
+
"stop",
|
|
2408
|
+
"length",
|
|
2409
|
+
"tool-calls",
|
|
2410
|
+
"content-filter",
|
|
2411
|
+
"error",
|
|
2412
|
+
"unknown"
|
|
2413
|
+
]).optional(),
|
|
2414
|
+
truncatedToolCall: z5.boolean().optional()
|
|
2363
2415
|
});
|
|
2364
2416
|
var ToolcallEventSchema = EventBaseSchema.extend({
|
|
2365
2417
|
type: z5.literal("toolcall"),
|
|
2366
2418
|
tool: z5.string().min(1),
|
|
2367
2419
|
callID: z5.string().min(1),
|
|
2368
2420
|
agent: z5.string().min(1).optional(),
|
|
2369
|
-
durationMs: z5.number().int().min(0),
|
|
2421
|
+
durationMs: z5.number().int().min(0).nullable(),
|
|
2370
2422
|
ok: z5.boolean(),
|
|
2423
|
+
executed: z5.boolean().optional(),
|
|
2424
|
+
providerExecuted: z5.boolean().optional(),
|
|
2425
|
+
failureKind: z5.enum(["input-invalid", "execution", "unknown"]).optional(),
|
|
2371
2426
|
title: z5.string().optional()
|
|
2372
2427
|
});
|
|
2373
2428
|
var MeetingEventSchema = EventBaseSchema.extend({
|
|
@@ -2397,7 +2452,15 @@ var ActivityEventSchema = EventBaseSchema.extend({
|
|
|
2397
2452
|
type: z5.literal("activity"),
|
|
2398
2453
|
kind: z5.enum(["route", "agent", "decision", "commit"]),
|
|
2399
2454
|
agent: z5.string().min(1).optional(),
|
|
2400
|
-
summary: z5.string().min(1)
|
|
2455
|
+
summary: z5.string().min(1),
|
|
2456
|
+
phase: z5.enum([
|
|
2457
|
+
"model-request",
|
|
2458
|
+
"tool-input",
|
|
2459
|
+
"tool-execution",
|
|
2460
|
+
"report-validation",
|
|
2461
|
+
"idle",
|
|
2462
|
+
"unknown"
|
|
2463
|
+
]).optional()
|
|
2401
2464
|
});
|
|
2402
2465
|
var SessionEndpointEventSchema = EventBaseSchema.extend({
|
|
2403
2466
|
type: z5.literal("session-endpoint"),
|
|
@@ -2860,11 +2923,17 @@ function reportHasSubstance(text) {
|
|
|
2860
2923
|
function roleReportPath(batchID, roleID) {
|
|
2861
2924
|
return `${ROLE_REPORTS_ROOT}/${reportPathSegment(batchID)}/${reportPathSegment(roleID)}.md`;
|
|
2862
2925
|
}
|
|
2863
|
-
function outputContractInstruction(reportPath) {
|
|
2926
|
+
function outputContractInstruction(reportPath, structuredReport) {
|
|
2864
2927
|
return [
|
|
2865
2928
|
"## Output contract (openteam)",
|
|
2866
2929
|
"",
|
|
2867
|
-
|
|
2930
|
+
...structuredReport ? [
|
|
2931
|
+
"Prefer `openteam-submit-report` with substantive `findings` and `status`",
|
|
2932
|
+
"(`done` or `continue`): openteam persists only your assigned report and",
|
|
2933
|
+
"confirms the write. Keep submissions concise; split large work into small",
|
|
2934
|
+
"tool calls. If that tool is unavailable, write your complete findings"
|
|
2935
|
+
] : ["Write your complete findings"],
|
|
2936
|
+
"to the report file below using the `write`",
|
|
2868
2937
|
"tool (create parent directories as needed), and keep it updated with",
|
|
2869
2938
|
"`edit` as you progress. This file is the ONLY channel your work reaches",
|
|
2870
2939
|
"the coordinator: anything you do not write there is discarded and lost,",
|
|
@@ -2907,9 +2976,33 @@ function composeSubsessionPrompt(input) {
|
|
|
2907
2976
|
].join(`
|
|
2908
2977
|
`) : "";
|
|
2909
2978
|
return {
|
|
2910
|
-
prompt: `${input.prompt}${handoff}
|
|
2979
|
+
prompt: `${input.prompt}${handoff}${input.truncated !== true ? "" : [
|
|
2980
|
+
"",
|
|
2981
|
+
"",
|
|
2982
|
+
"## Truncated tool-call recovery",
|
|
2983
|
+
"",
|
|
2984
|
+
"The previous response ended at the output limit and a tool call was invalid",
|
|
2985
|
+
"before execution. Use smaller, bounded tool calls and concise findings.",
|
|
2986
|
+
"Inspect the existing workspace and assigned report before continuing.",
|
|
2987
|
+
"Never repair and execute the malformed JSON. Produce a fresh, complete",
|
|
2988
|
+
"call only for work that is still necessary. Do not increase model limits",
|
|
2989
|
+
"or change the execution domain. This continuation uses the same pass budget."
|
|
2990
|
+
].join(`
|
|
2991
|
+
`)}${input.repair === undefined ? "" : [
|
|
2992
|
+
"",
|
|
2993
|
+
"",
|
|
2994
|
+
"## Report delivery repair",
|
|
2995
|
+
"",
|
|
2996
|
+
`Previous pass did not prove completion: ${input.repair}.`,
|
|
2997
|
+
"Continue the SAME goal and existing workspace, not a new orchestration.",
|
|
2998
|
+
"Read the assigned report and inspect the existing work first. Do not redo",
|
|
2999
|
+
"completed implementation merely because its delivery failed. Persist the",
|
|
3000
|
+
input.structuredReport === false ? "missing findings in the assigned report; do not just promise a report." : "missing findings with openteam-submit-report; do not just promise a report.",
|
|
3001
|
+
"This repair consumes the existing node pass allowance."
|
|
3002
|
+
].join(`
|
|
3003
|
+
`)}
|
|
2911
3004
|
|
|
2912
|
-
${outputContractInstruction(reportPath)}`,
|
|
3005
|
+
${outputContractInstruction(reportPath, input.structuredReport !== false)}`,
|
|
2913
3006
|
reportPath
|
|
2914
3007
|
};
|
|
2915
3008
|
}
|
|
@@ -3286,15 +3379,21 @@ function promptArgs(sessionID, req, signal) {
|
|
|
3286
3379
|
}
|
|
3287
3380
|
return args;
|
|
3288
3381
|
}
|
|
3289
|
-
async function withTimeout(promise, timeoutMs) {
|
|
3290
|
-
if (timeoutMs === undefined) {
|
|
3382
|
+
async function withTimeout(promise, timeoutMs, signal) {
|
|
3383
|
+
if (timeoutMs === undefined && signal === undefined) {
|
|
3291
3384
|
return { kind: "settled", value: await promise };
|
|
3292
3385
|
}
|
|
3293
3386
|
let timeoutID;
|
|
3387
|
+
let abortListener;
|
|
3294
3388
|
const timeout = new Promise((resolve) => {
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3389
|
+
if (timeoutMs !== undefined)
|
|
3390
|
+
timeoutID = setTimeout(() => {
|
|
3391
|
+
resolve({ kind: "timeout" });
|
|
3392
|
+
}, timeoutMs);
|
|
3393
|
+
abortListener = () => resolve({ kind: "aborted" });
|
|
3394
|
+
signal?.addEventListener("abort", abortListener, { once: true });
|
|
3395
|
+
if (signal?.aborted)
|
|
3396
|
+
abortListener();
|
|
3298
3397
|
});
|
|
3299
3398
|
try {
|
|
3300
3399
|
return await Promise.race([
|
|
@@ -3303,6 +3402,8 @@ async function withTimeout(promise, timeoutMs) {
|
|
|
3303
3402
|
]);
|
|
3304
3403
|
} finally {
|
|
3305
3404
|
clearTimeout(timeoutID);
|
|
3405
|
+
if (abortListener !== undefined)
|
|
3406
|
+
signal?.removeEventListener("abort", abortListener);
|
|
3306
3407
|
}
|
|
3307
3408
|
}
|
|
3308
3409
|
async function beforeDeadline(request, deadline, deps) {
|
|
@@ -3424,7 +3525,35 @@ async function confirmPromptRequestSettled(isSettled, deps, deadline) {
|
|
|
3424
3525
|
async function runSubsession(client, req, deps) {
|
|
3425
3526
|
let sessionID;
|
|
3426
3527
|
try {
|
|
3427
|
-
|
|
3528
|
+
deps.signal?.throwIfAborted();
|
|
3529
|
+
const createController = new AbortController;
|
|
3530
|
+
const createSignal = deps.signal === undefined ? createController.signal : AbortSignal.any([deps.signal, createController.signal]);
|
|
3531
|
+
const remaining = deps.deadlineAt === undefined ? undefined : Math.max(0, deps.deadlineAt - deps.now());
|
|
3532
|
+
if (remaining === 0)
|
|
3533
|
+
return {
|
|
3534
|
+
success: false,
|
|
3535
|
+
roleID: req.roleID,
|
|
3536
|
+
model: req.model,
|
|
3537
|
+
failureStage: "create",
|
|
3538
|
+
failureReason: taskEffortMessages.createDeadline,
|
|
3539
|
+
retrySafe: false
|
|
3540
|
+
};
|
|
3541
|
+
const createOutcome = await withTimeout(req.existingSessionID === undefined ? client.session.create(remaining === undefined && deps.signal === undefined ? createArgs(req) : { ...createArgs(req), signal: createSignal }) : Promise.resolve({
|
|
3542
|
+
data: { id: req.existingSessionID },
|
|
3543
|
+
error: undefined
|
|
3544
|
+
}), remaining, deps.signal);
|
|
3545
|
+
if (createOutcome.kind !== "settled") {
|
|
3546
|
+
createController.abort();
|
|
3547
|
+
return {
|
|
3548
|
+
success: false,
|
|
3549
|
+
roleID: req.roleID,
|
|
3550
|
+
model: req.model,
|
|
3551
|
+
failureStage: "create",
|
|
3552
|
+
failureReason: createOutcome.kind === "timeout" ? taskEffortMessages.createDeadline : taskEffortMessages.cancelled,
|
|
3553
|
+
retrySafe: false
|
|
3554
|
+
};
|
|
3555
|
+
}
|
|
3556
|
+
const created = createOutcome.value;
|
|
3428
3557
|
if (created.error !== undefined) {
|
|
3429
3558
|
const normalizedFailure = isNormalizedSessionFailure(created.error) ? created.error : undefined;
|
|
3430
3559
|
return {
|
|
@@ -3451,19 +3580,32 @@ async function runSubsession(client, req, deps) {
|
|
|
3451
3580
|
try {
|
|
3452
3581
|
await deps.onSessionCreated?.(sessionID);
|
|
3453
3582
|
} catch {}
|
|
3583
|
+
await deps.prepareSession?.(sessionID);
|
|
3584
|
+
deps.signal?.throwIfAborted();
|
|
3585
|
+
if (deps.deadlineAt !== undefined && deps.now() >= deps.deadlineAt)
|
|
3586
|
+
return {
|
|
3587
|
+
success: false,
|
|
3588
|
+
sessionID,
|
|
3589
|
+
roleID: req.roleID,
|
|
3590
|
+
model: req.model,
|
|
3591
|
+
failureStage: "create",
|
|
3592
|
+
failureReason: taskEffortMessages.createDeadline,
|
|
3593
|
+
retrySafe: false
|
|
3594
|
+
};
|
|
3454
3595
|
} catch (error) {
|
|
3455
3596
|
return {
|
|
3456
3597
|
success: false,
|
|
3457
3598
|
roleID: req.roleID,
|
|
3458
3599
|
model: req.model,
|
|
3459
3600
|
failureStage: "create",
|
|
3460
|
-
failureReason: errorReason(error),
|
|
3461
|
-
retrySafe: true
|
|
3601
|
+
failureReason: deps.signal?.aborted ? taskEffortMessages.cancelled : errorReason(error),
|
|
3602
|
+
retrySafe: deps.signal?.aborted !== true
|
|
3462
3603
|
};
|
|
3463
3604
|
}
|
|
3464
3605
|
const promptController = new AbortController;
|
|
3606
|
+
const promptSignal = deps.signal === undefined ? promptController.signal : AbortSignal.any([deps.signal, promptController.signal]);
|
|
3465
3607
|
let promptSettled = false;
|
|
3466
|
-
const promptPromise = client.session.prompt(promptArgs(sessionID, req,
|
|
3608
|
+
const promptPromise = client.session.prompt(promptArgs(sessionID, req, promptSignal)).then((value) => {
|
|
3467
3609
|
promptSettled = true;
|
|
3468
3610
|
return value;
|
|
3469
3611
|
}, (error) => {
|
|
@@ -3471,8 +3613,9 @@ async function runSubsession(client, req, deps) {
|
|
|
3471
3613
|
throw error;
|
|
3472
3614
|
});
|
|
3473
3615
|
try {
|
|
3474
|
-
const
|
|
3475
|
-
|
|
3616
|
+
const timeoutMs = deps.deadlineAt === undefined ? deps.timeoutMs : Math.min(deps.timeoutMs ?? Infinity, Math.max(0, deps.deadlineAt - deps.now()));
|
|
3617
|
+
const outcome = await withTimeout(promptPromise, timeoutMs, deps.signal);
|
|
3618
|
+
if (outcome.kind !== "settled") {
|
|
3476
3619
|
promptController.abort();
|
|
3477
3620
|
const stopDeadline = deps.now() + Math.max(0, deps.abortGraceMs);
|
|
3478
3621
|
const stopped = await confirmSessionStopped(client, sessionID, req.directory, deps, stopDeadline);
|
|
@@ -3483,8 +3626,8 @@ async function runSubsession(client, req, deps) {
|
|
|
3483
3626
|
roleID: req.roleID,
|
|
3484
3627
|
model: req.model,
|
|
3485
3628
|
failureStage: "prompt",
|
|
3486
|
-
failureReason: !stopped.confirmed ? promptStopUnconfirmed(stopped.cause) : requestSettled ? promptTimedOut(deps.timeoutMs ?? 0) : promptStopUnconfirmed("request-unsettled"),
|
|
3487
|
-
retrySafe: stopped.confirmed && requestSettled
|
|
3629
|
+
failureReason: !stopped.confirmed ? promptStopUnconfirmed(stopped.cause) : requestSettled ? deps.deadlineAt !== undefined && deps.now() >= deps.deadlineAt ? taskEffortMessages.exhausted("duration") : outcome.kind === "aborted" ? taskEffortMessages.cancelled : promptTimedOut(deps.timeoutMs ?? 0) : promptStopUnconfirmed("request-unsettled"),
|
|
3630
|
+
retrySafe: stopped.confirmed && requestSettled && outcome.kind !== "aborted" && (deps.deadlineAt === undefined || deps.now() < deps.deadlineAt)
|
|
3488
3631
|
};
|
|
3489
3632
|
}
|
|
3490
3633
|
const prompted = outcome.value;
|
|
@@ -3517,8 +3660,8 @@ async function runSubsession(client, req, deps) {
|
|
|
3517
3660
|
roleID: req.roleID,
|
|
3518
3661
|
model: req.model,
|
|
3519
3662
|
failureStage: "prompt",
|
|
3520
|
-
failureReason: stopped.confirmed ? errorReason(error) : promptStopUnconfirmed(stopped.cause),
|
|
3521
|
-
retrySafe: stopped.confirmed
|
|
3663
|
+
failureReason: stopped.confirmed ? deps.signal?.aborted ? taskEffortMessages.cancelled : errorReason(error) : promptStopUnconfirmed(stopped.cause),
|
|
3664
|
+
retrySafe: stopped.confirmed && deps.signal?.aborted !== true
|
|
3522
3665
|
};
|
|
3523
3666
|
}
|
|
3524
3667
|
}
|
|
@@ -3714,12 +3857,15 @@ var TelemetryFailureClassSchema = z7.enum([
|
|
|
3714
3857
|
"prompt-auth",
|
|
3715
3858
|
"prompt-content-filter",
|
|
3716
3859
|
"prompt-context-length",
|
|
3860
|
+
"prompt-output-truncated",
|
|
3861
|
+
"budget-exhausted",
|
|
3717
3862
|
"prompt-validation",
|
|
3718
3863
|
"prompt-connection",
|
|
3719
3864
|
"prompt-server",
|
|
3720
3865
|
"unknown"
|
|
3721
3866
|
]);
|
|
3722
3867
|
var FAILURE_CAUSE_RULES = [
|
|
3868
|
+
[["prompt-output-truncated"], "prompt-output-truncated"],
|
|
3723
3869
|
[
|
|
3724
3870
|
[
|
|
3725
3871
|
"rate limit",
|
|
@@ -3822,6 +3968,8 @@ function matchFailureCause(lowerReason) {
|
|
|
3822
3968
|
}
|
|
3823
3969
|
function classifyFailureForTelemetry(failureReason, failureStage) {
|
|
3824
3970
|
const lower = failureReason.toLowerCase();
|
|
3971
|
+
if (lower.startsWith("task-budget-exhausted:"))
|
|
3972
|
+
return "budget-exhausted";
|
|
3825
3973
|
if (TIMEOUT_NEEDLES.some((needle) => lower.includes(needle))) {
|
|
3826
3974
|
return "prompt-timeout";
|
|
3827
3975
|
}
|
|
@@ -3900,6 +4048,8 @@ async function recordLifecycle(lifecycle, event) {
|
|
|
3900
4048
|
await lifecycle.recorder.append(event);
|
|
3901
4049
|
}
|
|
3902
4050
|
function lifecycleFailureFor(subsession) {
|
|
4051
|
+
if (subsession.failureReason?.startsWith("task-budget-exhausted:"))
|
|
4052
|
+
return { class: "budget-exhausted", retryable: false };
|
|
3903
4053
|
const normalized = subsession.normalizedFailure;
|
|
3904
4054
|
if (normalized !== undefined) {
|
|
3905
4055
|
return {
|
|
@@ -3969,7 +4119,7 @@ function buildNodeBudgetExhaustedEvent(roleID, passCount, sessionID, ts) {
|
|
|
3969
4119
|
passCount
|
|
3970
4120
|
};
|
|
3971
4121
|
}
|
|
3972
|
-
async function runRoleTaskWithCorrelation(input, deps, correlation, batch, routed, handoff, reportBatchID, attemptLifecycle) {
|
|
4122
|
+
async function runRoleTaskWithCorrelation(input, deps, correlation, batch, routed, handoff, reportBatchID, attemptLifecycle, repair, truncated, existingSessionID) {
|
|
3973
4123
|
const role = roleFor(input);
|
|
3974
4124
|
if (routed.routeKind === "blocked") {
|
|
3975
4125
|
throw new Error(coordinatorRoutingBlocked(input.roleID, routed.blockReason));
|
|
@@ -3980,13 +4130,18 @@ async function runRoleTaskWithCorrelation(input, deps, correlation, batch, route
|
|
|
3980
4130
|
prompt: input.prompt,
|
|
3981
4131
|
roleID: input.roleID,
|
|
3982
4132
|
batchID: reportBatchID,
|
|
3983
|
-
handoff
|
|
4133
|
+
handoff,
|
|
4134
|
+
structuredReport: deps.reportDelivery !== undefined,
|
|
4135
|
+
...repair === undefined ? {} : { repair },
|
|
4136
|
+
...truncated === true ? { truncated: true } : {}
|
|
3984
4137
|
});
|
|
3985
4138
|
const request = {
|
|
3986
4139
|
roleID: input.roleID,
|
|
3987
4140
|
model: decision2.selected,
|
|
3988
4141
|
prompt: composed.prompt
|
|
3989
4142
|
};
|
|
4143
|
+
if (existingSessionID !== undefined)
|
|
4144
|
+
request.existingSessionID = existingSessionID;
|
|
3990
4145
|
if (input.parentSessionID !== undefined) {
|
|
3991
4146
|
request.parentSessionID = input.parentSessionID;
|
|
3992
4147
|
}
|
|
@@ -4004,11 +4159,17 @@ async function runRoleTaskWithCorrelation(input, deps, correlation, batch, route
|
|
|
4004
4159
|
if (input.directory !== undefined) {
|
|
4005
4160
|
request.directory = input.directory;
|
|
4006
4161
|
}
|
|
4162
|
+
let reportLease;
|
|
4007
4163
|
const subsessionDeps = {
|
|
4008
4164
|
abortGraceMs: deps.abortGraceMs,
|
|
4009
4165
|
statusPollMs: deps.statusPollMs,
|
|
4010
4166
|
now: deps.now,
|
|
4011
4167
|
delay: deps.delay,
|
|
4168
|
+
prepareSession: async (sessionID) => {
|
|
4169
|
+
if (deps.taskEffort !== undefined)
|
|
4170
|
+
deps.taskEffort.ledger.bindChild(deps.taskEffort.ref, sessionID);
|
|
4171
|
+
reportLease = deps.reportDelivery?.open(sessionID, reportBatchID, input.roleID);
|
|
4172
|
+
},
|
|
4012
4173
|
...deps.timeoutMs === undefined ? {} : { timeoutMs: deps.timeoutMs },
|
|
4013
4174
|
...attemptLifecycle === undefined ? {} : {
|
|
4014
4175
|
onSessionCreated: (sessionID) => recordLifecycle(attemptLifecycle.lifecycle, {
|
|
@@ -4053,27 +4214,66 @@ async function runRoleTaskWithCorrelation(input, deps, correlation, batch, route
|
|
|
4053
4214
|
}
|
|
4054
4215
|
let release;
|
|
4055
4216
|
let queueObservation;
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
const
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
const acquisition = await limiter.acquire(poolKey, priority);
|
|
4066
|
-
release = acquisition.release;
|
|
4067
|
-
waitedMs = acquisition.waitedMs;
|
|
4068
|
-
}
|
|
4069
|
-
queueObservation = {
|
|
4070
|
-
runtimeId,
|
|
4071
|
-
waitedMs,
|
|
4072
|
-
activeCount: limiter.activeCount(poolKey),
|
|
4073
|
-
queuedCount: limiter.queuedCount(poolKey)
|
|
4217
|
+
const admission = deps.taskEffort?.ledger.check(deps.taskEffort.ref);
|
|
4218
|
+
async function denied(reason) {
|
|
4219
|
+
const subsession = {
|
|
4220
|
+
roleID: input.roleID,
|
|
4221
|
+
model: decision2.selected,
|
|
4222
|
+
success: false,
|
|
4223
|
+
failureStage: "create",
|
|
4224
|
+
retrySafe: false,
|
|
4225
|
+
failureReason: reason
|
|
4074
4226
|
};
|
|
4227
|
+
const record = buildRecord(input, decision2, subsession, deps, correlation.decisionID, correlation.batchID);
|
|
4228
|
+
await safeEmit(deps.sink, correlatedCostRecordToRouteEvent(record));
|
|
4229
|
+
return { decision: decision2, subsession, record, reportPath: composed.reportPath };
|
|
4075
4230
|
}
|
|
4231
|
+
if (admission?.ok === false)
|
|
4232
|
+
return denied(taskEffortMessages.exhausted(admission.reason));
|
|
4233
|
+
if (deps.signal?.aborted)
|
|
4234
|
+
return denied(taskEffortMessages.cancelled);
|
|
4235
|
+
const queueController = new AbortController;
|
|
4236
|
+
const queueSignal = deps.signal === undefined ? queueController.signal : AbortSignal.any([deps.signal, queueController.signal]);
|
|
4237
|
+
const queueDeadline = admission?.ok === true ? setTimeout(() => queueController.abort(), admission.remainingMs) : undefined;
|
|
4076
4238
|
try {
|
|
4239
|
+
if (runtimeId !== undefined && deps.runtimeLimiter !== undefined) {
|
|
4240
|
+
const limiter = deps.runtimeLimiter;
|
|
4241
|
+
const priority = priorityForRole(role);
|
|
4242
|
+
const dispatchRuntime = configuredRuntime(runtimeId, input.config) ?? { id: runtimeId };
|
|
4243
|
+
const aliases = localModelAliases(decision2.selected.providerID, input.availableModels);
|
|
4244
|
+
const poolKey = slotPoolKey(withReportedModelSlots(dispatchRuntime, deps.reportedModelSlots?.(runtimeId), aliases), aliases.get(decision2.selected.modelID) ?? decision2.selected.modelID);
|
|
4245
|
+
release = limiter.tryAcquire(poolKey, priority);
|
|
4246
|
+
let waitedMs = 0;
|
|
4247
|
+
if (release === undefined) {
|
|
4248
|
+
let acquisition;
|
|
4249
|
+
try {
|
|
4250
|
+
acquisition = await limiter.acquire(poolKey, priority, queueSignal);
|
|
4251
|
+
} catch (error) {
|
|
4252
|
+
if (!queueSignal.aborted)
|
|
4253
|
+
throw error;
|
|
4254
|
+
return denied(queueController.signal.aborted ? taskEffortMessages.exhausted("duration") : taskEffortMessages.cancelled);
|
|
4255
|
+
}
|
|
4256
|
+
release = acquisition.release;
|
|
4257
|
+
waitedMs = acquisition.waitedMs;
|
|
4258
|
+
}
|
|
4259
|
+
queueObservation = {
|
|
4260
|
+
runtimeId,
|
|
4261
|
+
waitedMs,
|
|
4262
|
+
activeCount: limiter.activeCount(poolKey),
|
|
4263
|
+
queuedCount: limiter.queuedCount(poolKey)
|
|
4264
|
+
};
|
|
4265
|
+
}
|
|
4266
|
+
clearTimeout(queueDeadline);
|
|
4267
|
+
const effort = deps.taskEffort?.ledger.attempt(deps.taskEffort.ref);
|
|
4268
|
+
if (effort?.ok === false) {
|
|
4269
|
+
return denied(taskEffortMessages.exhausted(effort.reason));
|
|
4270
|
+
}
|
|
4271
|
+
if (effort?.ok === true) {
|
|
4272
|
+
subsessionDeps.timeoutMs = Math.min(subsessionDeps.timeoutMs ?? Infinity, effort.remainingMs);
|
|
4273
|
+
subsessionDeps.deadlineAt = deps.now() + effort.remainingMs;
|
|
4274
|
+
}
|
|
4275
|
+
if (deps.signal !== undefined)
|
|
4276
|
+
subsessionDeps.signal = deps.signal;
|
|
4077
4277
|
if (attemptLifecycle !== undefined) {
|
|
4078
4278
|
await recordLifecycle(attemptLifecycle.lifecycle, {
|
|
4079
4279
|
type: "attempt.started",
|
|
@@ -4101,8 +4301,17 @@ async function runRoleTaskWithCorrelation(input, deps, correlation, batch, route
|
|
|
4101
4301
|
await safeEmit(deps.sink, buildQueueEvent(queueObservation, sessionID, deps.now(), queueCorrelation));
|
|
4102
4302
|
}
|
|
4103
4303
|
}
|
|
4104
|
-
|
|
4304
|
+
const reportSubmitted = await reportLease?.close();
|
|
4305
|
+
return {
|
|
4306
|
+
decision: decision2,
|
|
4307
|
+
subsession,
|
|
4308
|
+
record,
|
|
4309
|
+
reportPath: composed.reportPath,
|
|
4310
|
+
...reportSubmitted === undefined ? {} : { reportSubmitted }
|
|
4311
|
+
};
|
|
4105
4312
|
} finally {
|
|
4313
|
+
clearTimeout(queueDeadline);
|
|
4314
|
+
await reportLease?.close();
|
|
4106
4315
|
release?.();
|
|
4107
4316
|
}
|
|
4108
4317
|
}
|
|
@@ -4214,15 +4423,19 @@ async function assessCurrentAttemptReport(input, before, result, deps) {
|
|
|
4214
4423
|
done: false
|
|
4215
4424
|
};
|
|
4216
4425
|
}
|
|
4217
|
-
if (after === before) {
|
|
4426
|
+
if (after === before && result.reportSubmitted !== true) {
|
|
4218
4427
|
return {
|
|
4219
4428
|
result: withFailure(gated, REPORT_STALE_REASON, "report"),
|
|
4220
4429
|
done: false
|
|
4221
4430
|
};
|
|
4222
4431
|
}
|
|
4432
|
+
const done = parseReportStatus(after) === "done" && reportHasSubstance(after);
|
|
4223
4433
|
return {
|
|
4224
4434
|
result: gated,
|
|
4225
|
-
done
|
|
4435
|
+
done,
|
|
4436
|
+
...!done ? {
|
|
4437
|
+
repairReason: !reportHasSubstance(after) ? "report-without-substance" : parseReportStatus(after) === "continue" ? "report-continue" : "report-status-missing"
|
|
4438
|
+
} : {}
|
|
4226
4439
|
};
|
|
4227
4440
|
}
|
|
4228
4441
|
function failedPassDisposition(subsession) {
|
|
@@ -4233,6 +4446,8 @@ function failedPassDisposition(subsession) {
|
|
|
4233
4446
|
if (subsession.failureStage === "report")
|
|
4234
4447
|
return "retry-incomplete";
|
|
4235
4448
|
if (subsession.normalizedFailure !== undefined) {
|
|
4449
|
+
if (subsession.normalizedFailure.failureClass === "prompt-output-truncated")
|
|
4450
|
+
return "retry-incomplete";
|
|
4236
4451
|
return subsession.normalizedFailure.retryable ? "retry-transport" : "terminal";
|
|
4237
4452
|
}
|
|
4238
4453
|
const failureReason = subsession.failureReason ?? "";
|
|
@@ -4332,6 +4547,7 @@ async function runNodeWithIteration(input, deps, correlation, batch, lifecycle)
|
|
|
4332
4547
|
let totalPasses = 0;
|
|
4333
4548
|
let spend = { usd: 0, frontierTokens: 0 };
|
|
4334
4549
|
let lastResult;
|
|
4550
|
+
let reportRepairReason;
|
|
4335
4551
|
let escalationReason;
|
|
4336
4552
|
const reportBatchID = correlation.batchID ?? correlation.decisionID;
|
|
4337
4553
|
modelLoop:
|
|
@@ -4404,14 +4620,19 @@ async function runNodeWithIteration(input, deps, correlation, batch, lifecycle)
|
|
|
4404
4620
|
retryIndex: pass - 1,
|
|
4405
4621
|
selectionCause: lifecycleSelectionCause(totalPasses, modelIndex, retryReason, escalationReason)
|
|
4406
4622
|
};
|
|
4407
|
-
let result = await runRoleTaskWithCorrelation(input, deps, attemptCorrelation, batch, attemptDecision, modelIndex > 0, reportBatchID, attemptLifecycle);
|
|
4623
|
+
let result = await runRoleTaskWithCorrelation(input, deps, attemptCorrelation, batch, attemptDecision, modelIndex > 0, reportBatchID, attemptLifecycle, reportRepairReason, lastResult?.subsession.normalizedFailure?.failureClass === "prompt-output-truncated", pass > 1 && reportRepairReason !== undefined && (lastResult?.subsession.success || lastResult?.subsession.failureStage === "report") && lastResult?.subsession.retrySafe !== false ? lastResult?.subsession.sessionID : undefined);
|
|
4408
4624
|
totalPasses += 1;
|
|
4409
4625
|
spend = {
|
|
4410
4626
|
usd: attemptDecision.estimatedCostUSD === null ? spend.usd : spend.usd + attemptDecision.estimatedCostUSD,
|
|
4411
4627
|
frontierTokens: spend.frontierTokens + (attemptDecision.routeKind === "frontier" ? (input.task.estimatedInputTokens ?? 0) + (input.task.estimatedOutputTokens ?? 0) : 0)
|
|
4412
4628
|
};
|
|
4629
|
+
if (result.subsession.sessionID !== undefined)
|
|
4630
|
+
await deps.sessionPhase?.(result.subsession.sessionID, "report-validation");
|
|
4413
4631
|
const assessment = await assessCurrentAttemptReport(input, before, result, deps);
|
|
4632
|
+
if (result.subsession.sessionID !== undefined)
|
|
4633
|
+
await deps.sessionPhase?.(result.subsession.sessionID, "idle");
|
|
4414
4634
|
result = assessment.result;
|
|
4635
|
+
reportRepairReason = assessment.repairReason ?? (result.subsession.failureStage === "report" ? result.subsession.failureReason : undefined);
|
|
4415
4636
|
lastResult = result;
|
|
4416
4637
|
if (assessment.done) {
|
|
4417
4638
|
await recordAttemptTerminal(attemptLifecycle, result, "none", true);
|
|
@@ -4497,13 +4718,28 @@ async function runRoleTasks(inputs, deps, options = {}) {
|
|
|
4497
4718
|
});
|
|
4498
4719
|
}
|
|
4499
4720
|
}
|
|
4500
|
-
const
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4721
|
+
const waveController = deps.taskEffort === undefined ? undefined : new AbortController;
|
|
4722
|
+
const waveDeps = waveController === undefined ? deps : {
|
|
4723
|
+
...deps,
|
|
4724
|
+
signal: deps.signal === undefined ? waveController.signal : AbortSignal.any([deps.signal, waveController.signal])
|
|
4725
|
+
};
|
|
4726
|
+
const waveTasks = runnable.map(async (input) => {
|
|
4727
|
+
try {
|
|
4728
|
+
const correlation = correlationByRole.get(input.roleID);
|
|
4729
|
+
if (correlation === undefined) {
|
|
4730
|
+
throw new Error(`missing correlation for ${input.roleID}`);
|
|
4731
|
+
}
|
|
4732
|
+
return await runNodeWithIteration(input, waveDeps, correlation, batch, lifecycle);
|
|
4733
|
+
} catch (error) {
|
|
4734
|
+
waveController?.abort();
|
|
4735
|
+
throw error;
|
|
4504
4736
|
}
|
|
4505
|
-
|
|
4506
|
-
|
|
4737
|
+
});
|
|
4738
|
+
const waveResults = waveController === undefined ? await Promise.all(waveTasks) : (await Promise.allSettled(waveTasks)).map((outcome) => {
|
|
4739
|
+
if (outcome.status === "rejected")
|
|
4740
|
+
throw outcome.reason;
|
|
4741
|
+
return outcome.value;
|
|
4742
|
+
});
|
|
4507
4743
|
for (const result of waveResults) {
|
|
4508
4744
|
allResults.push(result);
|
|
4509
4745
|
if (result.subsession.success) {
|
|
@@ -5720,6 +5956,11 @@ function applyRoute(session2, event) {
|
|
|
5720
5956
|
}
|
|
5721
5957
|
function applyMessage(session2, event) {
|
|
5722
5958
|
session2.messageCount += 1;
|
|
5959
|
+
const unknownUsage = event.usageStatus === undefined ? event.tokensIn + event.tokensOut + event.tokensReasoning + event.tokensCacheRead + event.tokensCacheWrite === 0 : event.usageStatus !== "reported";
|
|
5960
|
+
if (unknownUsage)
|
|
5961
|
+
session2.unavailableUsageMessages = (session2.unavailableUsageMessages ?? 0) + 1;
|
|
5962
|
+
if (event.costStatus === "unavailable" || event.costStatus === undefined && unknownUsage && event.costUSD === 0)
|
|
5963
|
+
session2.unavailableCostMessages = (session2.unavailableCostMessages ?? 0) + 1;
|
|
5723
5964
|
session2.realCostUSD += event.costUSD;
|
|
5724
5965
|
session2.tokensIn += event.tokensIn;
|
|
5725
5966
|
session2.tokensOut += event.tokensOut;
|
|
@@ -5731,7 +5972,9 @@ function applyMessage(session2, event) {
|
|
|
5731
5972
|
}
|
|
5732
5973
|
function applyToolUsage(stats, event) {
|
|
5733
5974
|
stats.count += 1;
|
|
5734
|
-
stats.totalDurationMs += event.durationMs;
|
|
5975
|
+
stats.totalDurationMs += event.durationMs ?? 0;
|
|
5976
|
+
if (event.durationMs === null)
|
|
5977
|
+
stats.unknownDurationCount = (stats.unknownDurationCount ?? 0) + 1;
|
|
5735
5978
|
if (event.ok) {
|
|
5736
5979
|
stats.ok += 1;
|
|
5737
5980
|
} else {
|
|
@@ -5774,6 +6017,8 @@ function mergeTool(target, source) {
|
|
|
5774
6017
|
target.ok += source.ok;
|
|
5775
6018
|
target.failed += source.failed;
|
|
5776
6019
|
target.totalDurationMs += source.totalDurationMs;
|
|
6020
|
+
if (source.unknownDurationCount !== undefined)
|
|
6021
|
+
target.unknownDurationCount = (target.unknownDurationCount ?? 0) + source.unknownDurationCount;
|
|
5777
6022
|
}
|
|
5778
6023
|
function accumulateTotals(totals, session2) {
|
|
5779
6024
|
totals.sessions += 1;
|
|
@@ -5784,6 +6029,10 @@ function accumulateTotals(totals, session2) {
|
|
|
5784
6029
|
totals.estimatedSavingsUSD = addEstimate(totals.estimatedSavingsUSD, session2.estimatedSavingsUSD);
|
|
5785
6030
|
totals.realCostUSD += session2.realCostUSD;
|
|
5786
6031
|
totals.messageCount += session2.messageCount;
|
|
6032
|
+
if (session2.unavailableUsageMessages !== undefined)
|
|
6033
|
+
totals.unavailableUsageMessages = (totals.unavailableUsageMessages ?? 0) + session2.unavailableUsageMessages;
|
|
6034
|
+
if (session2.unavailableCostMessages !== undefined)
|
|
6035
|
+
totals.unavailableCostMessages = (totals.unavailableCostMessages ?? 0) + session2.unavailableCostMessages;
|
|
5787
6036
|
totals.tokensIn += session2.tokensIn;
|
|
5788
6037
|
totals.tokensOut += session2.tokensOut;
|
|
5789
6038
|
totals.tokensReasoning += session2.tokensReasoning;
|
|
@@ -5850,6 +6099,7 @@ function aggregateEvents(events) {
|
|
|
5850
6099
|
const decisions = [];
|
|
5851
6100
|
const meetings = [];
|
|
5852
6101
|
const activity = [];
|
|
6102
|
+
const calls = new Map;
|
|
5853
6103
|
const sessionFor = (sessionID, ts) => {
|
|
5854
6104
|
const existing = sessions.get(sessionID);
|
|
5855
6105
|
if (existing === undefined) {
|
|
@@ -5870,7 +6120,13 @@ function aggregateEvents(events) {
|
|
|
5870
6120
|
applyMessage(sessionFor(event.sessionID, event.ts), event);
|
|
5871
6121
|
break;
|
|
5872
6122
|
case "toolcall":
|
|
5873
|
-
|
|
6123
|
+
{
|
|
6124
|
+
const key = `${event.sessionID}\x00${event.callID}`;
|
|
6125
|
+
const previous = calls.get(key);
|
|
6126
|
+
if (previous === undefined || previous.ok && !event.ok || previous.ok === event.ok && (event.durationMs ?? -1) > (previous.durationMs ?? -1)) {
|
|
6127
|
+
calls.set(key, event);
|
|
6128
|
+
}
|
|
6129
|
+
}
|
|
5874
6130
|
break;
|
|
5875
6131
|
case "session-endpoint":
|
|
5876
6132
|
applyEndpoint(sessionFor(event.sessionID, event.ts), event);
|
|
@@ -5883,9 +6139,19 @@ function aggregateEvents(events) {
|
|
|
5883
6139
|
break;
|
|
5884
6140
|
case "activity":
|
|
5885
6141
|
activity.push(toActivity(event));
|
|
6142
|
+
if (event.phase !== undefined) {
|
|
6143
|
+
const session2 = sessionFor(event.sessionID, event.ts);
|
|
6144
|
+
if (event.ts >= (session2.phaseAt ?? -Infinity)) {
|
|
6145
|
+
session2.phase = event.phase;
|
|
6146
|
+
session2.phaseAt = event.ts;
|
|
6147
|
+
}
|
|
6148
|
+
}
|
|
5886
6149
|
break;
|
|
5887
6150
|
}
|
|
5888
6151
|
}
|
|
6152
|
+
for (const event of calls.values()) {
|
|
6153
|
+
applyToolcall(sessionFor(event.sessionID, event.ts), event);
|
|
6154
|
+
}
|
|
5889
6155
|
const totals = {
|
|
5890
6156
|
sessions: 0,
|
|
5891
6157
|
routeCount: 0,
|
|
@@ -6176,8 +6442,15 @@ var KNOWN_CONFIG_KEYS_BY_PATH = new Map([
|
|
|
6176
6442
|
["graph.worktrees", ["enabled"]],
|
|
6177
6443
|
["lifecycle", ["root", "retention"]],
|
|
6178
6444
|
["lifecycle.retention", ["maxTerminalRuns", "maxAgeDays", "maxBytes"]],
|
|
6179
|
-
[
|
|
6445
|
+
[
|
|
6446
|
+
"orchestrator",
|
|
6447
|
+
["roles", "primary", "maxRetries", "maxModelsPerNode", "taskBudget"]
|
|
6448
|
+
],
|
|
6180
6449
|
["orchestrator.primary", ["executionMode", "model", "fallbacks"]],
|
|
6450
|
+
[
|
|
6451
|
+
"orchestrator.taskBudget",
|
|
6452
|
+
["maxBatches", "maxAttempts", "maxDurationMs", "maxDepth"]
|
|
6453
|
+
],
|
|
6181
6454
|
["orchestrator.primary.fallbacks[]", MODEL_REF_KEYS]
|
|
6182
6455
|
]);
|
|
6183
6456
|
function isUnrecognizedKeysIssue(issue) {
|
|
@@ -7466,6 +7739,488 @@ async function handleLifecycleHistoryRoute(request, response, url, deps) {
|
|
|
7466
7739
|
return true;
|
|
7467
7740
|
}
|
|
7468
7741
|
|
|
7742
|
+
// src/messages/agentView.ts
|
|
7743
|
+
var agentViewMessages = {
|
|
7744
|
+
title: "Agent workspace",
|
|
7745
|
+
graph: "Graph",
|
|
7746
|
+
chronology: "Chronology",
|
|
7747
|
+
filters: "Filters",
|
|
7748
|
+
search: "Search operations",
|
|
7749
|
+
searchHint: "Alias, role, model or operation ID",
|
|
7750
|
+
allRoles: "All roles",
|
|
7751
|
+
allStates: "All states",
|
|
7752
|
+
role: "Role",
|
|
7753
|
+
state: "State",
|
|
7754
|
+
matches: "Matching operations",
|
|
7755
|
+
noMatches: "No operations match these filters.",
|
|
7756
|
+
filterNote: "Filtered operations stay dimmed to preserve context.",
|
|
7757
|
+
hierarchy: "Hierarchy",
|
|
7758
|
+
dependency: "Prerequisite",
|
|
7759
|
+
legend: "Solid: parent/child. Dashed: prerequisite. Neither implies model activity.",
|
|
7760
|
+
inspector: "Operation inspector",
|
|
7761
|
+
root: "Select coordinator",
|
|
7762
|
+
isolate: "Isolate hierarchy branch",
|
|
7763
|
+
clearIsolation: "Show all branches",
|
|
7764
|
+
selectedFiltered: "The selected operation is outside the current filters.",
|
|
7765
|
+
zoomIn: "Zoom in",
|
|
7766
|
+
zoomOut: "Zoom out",
|
|
7767
|
+
fit: "Fit graph",
|
|
7768
|
+
reset: "Reset view",
|
|
7769
|
+
canvas: "Agent graph. Select an operation with Enter or Space. Arrow keys pan the canvas; plus and minus zoom.",
|
|
7770
|
+
play: "Play recorded events",
|
|
7771
|
+
pause: "Pause replay",
|
|
7772
|
+
previous: "Previous event",
|
|
7773
|
+
next: "Next event",
|
|
7774
|
+
speed: "Events per second",
|
|
7775
|
+
replayNote: "Replay uses recorded event prefixes. Current conversations and telemetry are never shown at historical cursors.",
|
|
7776
|
+
noEvents: "No recorded events at this cursor.",
|
|
7777
|
+
eventWindow: "Showing the most recent 1,000 events in this prefix. Use the cursor to inspect earlier history.",
|
|
7778
|
+
attempts: "Attempts",
|
|
7779
|
+
failures: "Failed attempts",
|
|
7780
|
+
noModel: "Model not recorded",
|
|
7781
|
+
noSession: "No session created",
|
|
7782
|
+
phase: "Observed phase",
|
|
7783
|
+
phaseUnknown: "Session phase unavailable",
|
|
7784
|
+
historicalMetrics: "Live phase and usage are unavailable in historical replay.",
|
|
7785
|
+
usage: "Reported input / output tokens",
|
|
7786
|
+
usageUnavailable: "Usage unavailable / partial",
|
|
7787
|
+
cost: "Reported cost",
|
|
7788
|
+
costUnavailable: "Cost unavailable / partial",
|
|
7789
|
+
tools: "Tool calls / failures",
|
|
7790
|
+
noTools: "No tool outcomes observed",
|
|
7791
|
+
related: "Related batches",
|
|
7792
|
+
relatedNote: "Same task, or a batch whose root session is this operation's child session. Outcomes remain independent.",
|
|
7793
|
+
relatedFailed: "Related failed batches",
|
|
7794
|
+
missing: "Unresolved references",
|
|
7795
|
+
states: {
|
|
7796
|
+
waiting: "Waiting",
|
|
7797
|
+
selected: "Selected",
|
|
7798
|
+
queued: "Queued",
|
|
7799
|
+
running: "Running",
|
|
7800
|
+
succeeded: "Succeeded",
|
|
7801
|
+
failed: "Failed",
|
|
7802
|
+
blocked: "Blocked",
|
|
7803
|
+
cancelled: "Cancelled",
|
|
7804
|
+
interrupted: "Interrupted",
|
|
7805
|
+
unknown: "Unknown"
|
|
7806
|
+
},
|
|
7807
|
+
events: {
|
|
7808
|
+
"run.started": "Batch started",
|
|
7809
|
+
"operation.queued": "Operation queued",
|
|
7810
|
+
"attempt.model-selected": "Model selected",
|
|
7811
|
+
"attempt.queued": "Attempt queued",
|
|
7812
|
+
"attempt.started": "Attempt started",
|
|
7813
|
+
"session.created": "Session created",
|
|
7814
|
+
"attempt.terminal": "Attempt finished",
|
|
7815
|
+
"operation.terminal": "Operation finished",
|
|
7816
|
+
"run.terminal": "Batch finished"
|
|
7817
|
+
}
|
|
7818
|
+
};
|
|
7819
|
+
|
|
7820
|
+
// src/console/agentView.ts
|
|
7821
|
+
function layoutAgentOperations(operations) {
|
|
7822
|
+
const byID = new Map(operations.map((operation) => [operation.operationID, operation]));
|
|
7823
|
+
const rows = new Map;
|
|
7824
|
+
const nodes = [];
|
|
7825
|
+
let width = 256;
|
|
7826
|
+
let height = 152;
|
|
7827
|
+
for (const operation of byID.values()) {
|
|
7828
|
+
const seen = new Set([operation.operationID]);
|
|
7829
|
+
let parent = operation.parentOperationID;
|
|
7830
|
+
let depth = 0;
|
|
7831
|
+
while (parent !== undefined && byID.has(parent) && !seen.has(parent)) {
|
|
7832
|
+
seen.add(parent);
|
|
7833
|
+
depth++;
|
|
7834
|
+
parent = byID.get(parent)?.parentOperationID;
|
|
7835
|
+
}
|
|
7836
|
+
const row = rows.get(depth) ?? 0;
|
|
7837
|
+
rows.set(depth, row + 1);
|
|
7838
|
+
const x = 28 + depth * 268;
|
|
7839
|
+
const y = 28 + row * 148;
|
|
7840
|
+
nodes.push({ id: operation.operationID, x, y });
|
|
7841
|
+
width = Math.max(width, x + 256);
|
|
7842
|
+
height = Math.max(height, y + 144);
|
|
7843
|
+
}
|
|
7844
|
+
return { nodes, width, height };
|
|
7845
|
+
}
|
|
7846
|
+
var AGENT_VIEW_CLIENT_JS = `
|
|
7847
|
+
var layoutAgentOperations=${layoutAgentOperations.toString()};
|
|
7848
|
+
function createAgentViewer(host,options){
|
|
7849
|
+
var msg=${JSON.stringify(agentViewMessages)},phases=${JSON.stringify(executionPhaseMessages)};
|
|
7850
|
+
var source=null,selected=null,isolated=null,run=null,mode='graph',playing=false,playTimer=null,pendingCursor=null;
|
|
7851
|
+
var scale=1,offsetX=24,offsetY=24,positioned=false,drag=null,summaries=new Map((document.__consoleTelemetry||[]).map(function(item){return [item.sessionID,item]})),nodes=new Map(),layout=null;
|
|
7852
|
+
var metricsKey='',relatedKey='';
|
|
7853
|
+
var namespace='http://www.w3.org/2000/svg',byID=new Map(),tree=null,filtered=new Set(),openDetails=new Map();
|
|
7854
|
+
function element(tag,text,className){var node=document.createElement(tag);if(text!==undefined){node.textContent=text}if(className){node.className=className}return node}
|
|
7855
|
+
function button(label,action,marker){
|
|
7856
|
+
var node=element('button',label);node.type='button';node.setAttribute('aria-label',label);
|
|
7857
|
+
if(marker){node.setAttribute('data-agent-'+marker,'')}
|
|
7858
|
+
node.addEventListener('click',action);return node;
|
|
7859
|
+
}
|
|
7860
|
+
function svgElement(tag,attributes,text){
|
|
7861
|
+
var node=document.createElementNS(namespace,tag);
|
|
7862
|
+
Object.keys(attributes||{}).forEach(function(key){node.setAttribute(key,String(attributes[key]))});
|
|
7863
|
+
if(text!==undefined){node.textContent=text}return node;
|
|
7864
|
+
}
|
|
7865
|
+
function label(text,input){var node=element('label',text);node.appendChild(input);return node}
|
|
7866
|
+
function option(select,value,text){var node=element('option',text);node.value=value;select.appendChild(node)}
|
|
7867
|
+
var shell=element('section',undefined,'av-workspace');shell.setAttribute('aria-label',msg.title);
|
|
7868
|
+
var tools=element('div',undefined,'av-toolbar');
|
|
7869
|
+
var graphButton=button(msg.graph,function(){setMode('graph')},'graph');
|
|
7870
|
+
var chronologyButton=button(msg.chronology,function(){setMode('chronology')},'chronology');
|
|
7871
|
+
tools.append(graphButton,chronologyButton);
|
|
7872
|
+
tools.appendChild(button(msg.previous,function(){pause();seek(Math.max(0,source.cursor-1),true)},'previous'));
|
|
7873
|
+
var playButton=button(msg.play,togglePlayback,'play');tools.appendChild(playButton);
|
|
7874
|
+
tools.appendChild(button(msg.next,function(){pause();seek(Math.min(source.head,source.cursor+1),true)},'next'));
|
|
7875
|
+
var speed=element('select');speed.setAttribute('aria-label',msg.speed);
|
|
7876
|
+
[1,2,5].forEach(function(value){option(speed,String(value),String(value))});
|
|
7877
|
+
tools.appendChild(label(msg.speed,speed));
|
|
7878
|
+
var count=element('span',undefined,'av-count');count.setAttribute('role','status');tools.appendChild(count);
|
|
7879
|
+
shell.appendChild(tools);
|
|
7880
|
+
var body=element('div',undefined,'av-body'),filters=element('aside',undefined,'av-filters');
|
|
7881
|
+
filters.appendChild(element('h3',msg.filters));
|
|
7882
|
+
var search=element('input');search.type='search';search.placeholder=msg.searchHint;search.setAttribute('data-agent-search','');
|
|
7883
|
+
filters.appendChild(label(msg.search,search));
|
|
7884
|
+
var role=element('select');role.setAttribute('data-agent-role','');option(role,'',msg.allRoles);
|
|
7885
|
+
filters.appendChild(label(msg.role,role));
|
|
7886
|
+
var status=element('select');status.setAttribute('data-agent-state','');option(status,'',msg.allStates);
|
|
7887
|
+
Object.keys(msg.states).forEach(function(key){option(status,key,msg.states[key])});
|
|
7888
|
+
filters.appendChild(label(msg.state,status));
|
|
7889
|
+
var isolate=button(msg.isolate,function(){isolated=isolated?null:selected;applyFilters()},'isolate');
|
|
7890
|
+
filters.appendChild(isolate);
|
|
7891
|
+
filters.appendChild(button(msg.root,function(){select(source.rootOperationID)},'root'));
|
|
7892
|
+
filters.appendChild(element('p',msg.filterNote));
|
|
7893
|
+
var legend=element('div',undefined,'av-legend');legend.appendChild(element('p',msg.hierarchy,'av-solid'));
|
|
7894
|
+
legend.appendChild(element('p',msg.dependency,'av-dashed'));legend.appendChild(element('p',msg.legend));filters.appendChild(legend);
|
|
7895
|
+
var unresolved=element('p');unresolved.setAttribute('data-agent-unresolved','');filters.appendChild(unresolved);
|
|
7896
|
+
body.appendChild(filters);
|
|
7897
|
+
var center=element('div',undefined,'av-center');
|
|
7898
|
+
var canvas=element('div',undefined,'av-canvas');
|
|
7899
|
+
var zoomTools=element('div',undefined,'av-zoom');
|
|
7900
|
+
zoomTools.append(button(msg.zoomIn,function(){zoom(1.2)},'zoom-in'),button(msg.zoomOut,function(){zoom(1/1.2)},'zoom-out'),
|
|
7901
|
+
button(msg.fit,fit,'fit'),button(msg.reset,function(){scale=1;offsetX=24;offsetY=24;transform()},'reset'));
|
|
7902
|
+
canvas.appendChild(zoomTools);
|
|
7903
|
+
var svg=svgElement('svg',{'class':'av-graph','role':'group','aria-label':msg.canvas,tabindex:0});
|
|
7904
|
+
var viewport=svgElement('g',{'class':'av-viewport'});svg.appendChild(viewport);canvas.appendChild(svg);
|
|
7905
|
+
center.appendChild(canvas);
|
|
7906
|
+
var chronology=element('ol',undefined,'av-chronology');chronology.hidden=true;chronology.setAttribute('aria-label',msg.chronology);
|
|
7907
|
+
center.appendChild(chronology);
|
|
7908
|
+
var empty=element('p',msg.noMatches,'av-empty');empty.hidden=true;center.appendChild(empty);
|
|
7909
|
+
body.appendChild(center);
|
|
7910
|
+
var inspector=element('aside',undefined,'av-inspector');
|
|
7911
|
+
inspector.setAttribute('aria-label',msg.inspector);inspector.appendChild(element('h3',msg.inspector));
|
|
7912
|
+
var notice=element('p',msg.selectedFiltered);notice.hidden=true;inspector.appendChild(notice);
|
|
7913
|
+
var metrics=element('div',undefined,'av-metrics');metrics.setAttribute('data-agent-metrics','');inspector.appendChild(metrics);
|
|
7914
|
+
var inspectorTree=element('div');inspectorTree.setAttribute('data-agent-inspector-tree','');inspector.appendChild(inspectorTree);
|
|
7915
|
+
var related=element('section',undefined,'av-related');inspector.appendChild(related);
|
|
7916
|
+
body.appendChild(inspector);shell.appendChild(body);
|
|
7917
|
+
var replayNote=element('p',msg.replayNote,'av-replay-note');shell.appendChild(replayNote);
|
|
7918
|
+
host.replaceChildren(shell);
|
|
7919
|
+
host.classList.add('av-host');
|
|
7920
|
+
function setMode(value){
|
|
7921
|
+
mode=value;canvas.hidden=value!=='graph';chronology.hidden=value!=='chronology';
|
|
7922
|
+
graphButton.setAttribute('aria-pressed',String(value==='graph'));chronologyButton.setAttribute('aria-pressed',String(value==='chronology'));
|
|
7923
|
+
if(value==='graph'&&!positioned){fit()}
|
|
7924
|
+
}
|
|
7925
|
+
function transform(){
|
|
7926
|
+
viewport.setAttribute('transform','translate('+offsetX+' '+offsetY+') scale('+scale+')');
|
|
7927
|
+
svg.setAttribute('data-agent-scale',String(scale));
|
|
7928
|
+
}
|
|
7929
|
+
function fit(){
|
|
7930
|
+
if(!layout){return}
|
|
7931
|
+
var bounds=svg.getBoundingClientRect();if(!bounds.width||!bounds.height){return}
|
|
7932
|
+
scale=Math.max(.06,Math.min(1.25,(bounds.width-48)/layout.width,(bounds.height-92)/layout.height));
|
|
7933
|
+
offsetX=(bounds.width-layout.width*scale)/2;offsetY=60;positioned=true;transform();
|
|
7934
|
+
}
|
|
7935
|
+
function zoom(factor,x,y){
|
|
7936
|
+
var bounds=svg.getBoundingClientRect(),cx=x===undefined?bounds.width/2:x,cy=y===undefined?bounds.height/2:y;
|
|
7937
|
+
var next=Math.max(.06,Math.min(3,scale*factor));
|
|
7938
|
+
offsetX=cx-(cx-offsetX)*next/scale;offsetY=cy-(cy-offsetY)*next/scale;scale=next;positioned=true;transform();
|
|
7939
|
+
}
|
|
7940
|
+
svg.addEventListener('wheel',function(event){
|
|
7941
|
+
if(!event.ctrlKey&&!event.metaKey){return}
|
|
7942
|
+
event.preventDefault();var bounds=svg.getBoundingClientRect();zoom(event.deltaY>0?1/1.15:1.15,event.clientX-bounds.left,event.clientY-bounds.top);
|
|
7943
|
+
},{passive:false});
|
|
7944
|
+
svg.addEventListener('pointerdown',function(event){
|
|
7945
|
+
if(event.button!==0||event.target.closest('[data-agent-operation]')){return}
|
|
7946
|
+
drag={x:event.clientX,y:event.clientY,left:offsetX,top:offsetY,id:event.pointerId};
|
|
7947
|
+
svg.setPointerCapture(event.pointerId);
|
|
7948
|
+
});
|
|
7949
|
+
svg.addEventListener('pointermove',function(event){
|
|
7950
|
+
if(!drag||event.pointerId!==drag.id){return}
|
|
7951
|
+
offsetX=drag.left+event.clientX-drag.x;offsetY=drag.top+event.clientY-drag.y;positioned=true;transform();
|
|
7952
|
+
});
|
|
7953
|
+
function endDrag(){drag=null}
|
|
7954
|
+
svg.addEventListener('pointerup',endDrag);svg.addEventListener('pointercancel',endDrag);svg.addEventListener('lostpointercapture',endDrag);
|
|
7955
|
+
svg.addEventListener('keydown',function(event){
|
|
7956
|
+
if(event.key==='+'||event.key==='='){event.preventDefault();zoom(1.2)}
|
|
7957
|
+
else if(event.key==='-'){event.preventDefault();zoom(1/1.2)}
|
|
7958
|
+
else if(['ArrowLeft','ArrowRight','ArrowUp','ArrowDown'].includes(event.key)){
|
|
7959
|
+
event.preventDefault();offsetX+=event.key==='ArrowLeft'?40:event.key==='ArrowRight'?-40:0;
|
|
7960
|
+
offsetY+=event.key==='ArrowUp'?40:event.key==='ArrowDown'?-40:0;positioned=true;transform();
|
|
7961
|
+
}
|
|
7962
|
+
});
|
|
7963
|
+
function lastAttempt(operation){var attempts=operation.attempts||[];return attempts[attempts.length-1]}
|
|
7964
|
+
function phaseFor(operation){
|
|
7965
|
+
if(operation.state!=='running'){return msg.states[operation.state]||msg.states.unknown}
|
|
7966
|
+
if(!options.isLive()){return msg.phaseUnknown}
|
|
7967
|
+
var attempt=lastAttempt(operation),summary=summaries.get(attempt&&attempt.sessionID||options.rootSessionID(operation.operationID));
|
|
7968
|
+
return summary&&phases[summary.phase]||msg.phaseUnknown;
|
|
7969
|
+
}
|
|
7970
|
+
function appendMetric(name,value){var row=element('p');row.append(element('span',name),element('strong',String(value)));metrics.appendChild(row)}
|
|
7971
|
+
function updateMetrics(){
|
|
7972
|
+
if(!source){return}
|
|
7973
|
+
nodes.forEach(function(node,id){var phase=phaseFor(byID.get(id));if(node.phase.textContent!==phase){node.phase.textContent=phase}});
|
|
7974
|
+
var operation=byID.get(selected),attempt=operation&&lastAttempt(operation);
|
|
7975
|
+
var session=attempt&&attempt.sessionID||options.rootSessionID(operation&&operation.operationID),summary=summaries.get(session);
|
|
7976
|
+
var key=JSON.stringify([source.runID,selected,options.isLive(),operation&&phaseFor(operation),summary]);
|
|
7977
|
+
if(metricsKey===key){return}metricsKey=key;
|
|
7978
|
+
metrics.replaceChildren();
|
|
7979
|
+
if(!options.isLive()){metrics.appendChild(element('p',msg.historicalMetrics));return}
|
|
7980
|
+
if(!operation){return}
|
|
7981
|
+
appendMetric(msg.phase,phaseFor(operation));
|
|
7982
|
+
var hasUsage=summary&&summary.messageCount>0&&!(summary.unavailableUsageMessages>0);
|
|
7983
|
+
appendMetric(msg.usage,hasUsage?summary.tokensIn+' / '+summary.tokensOut:msg.usageUnavailable);
|
|
7984
|
+
appendMetric(msg.cost,summary&&summary.messageCount>0&&!(summary.unavailableCostMessages>0)?'$'+summary.realCostUSD.toFixed(5):msg.costUnavailable);
|
|
7985
|
+
appendMetric(msg.tools,summary&&summary.toolcalls.count?summary.toolcalls.count+' / '+summary.toolcalls.failed:msg.noTools);
|
|
7986
|
+
}
|
|
7987
|
+
function updateRelated(){
|
|
7988
|
+
if(!source){return}
|
|
7989
|
+
var current=(options.runs()||[]).find(function(item){return item.runID===source.runID});
|
|
7990
|
+
var operation=byID.get(selected),sessions=new Set((operation&&operation.attempts||[]).map(function(attempt){return attempt.sessionID}).filter(Boolean));
|
|
7991
|
+
var others=(options.isLive()?options.runs():[]).filter(function(item){return item.runID!==source.runID&&
|
|
7992
|
+
(current&&item.rootTaskID===current.rootTaskID||item.rootSessionID&&sessions.has(item.rootSessionID))});
|
|
7993
|
+
var key=JSON.stringify([source.runID,selected,others]);if(relatedKey===key){return}relatedKey=key;
|
|
7994
|
+
related.replaceChildren();
|
|
7995
|
+
if(!others.length){return}
|
|
7996
|
+
related.appendChild(element('h4',msg.related));related.appendChild(element('p',msg.relatedNote));
|
|
7997
|
+
var failed=others.filter(function(item){return item.terminalOutcome==='failed'}).length;
|
|
7998
|
+
if(failed){related.appendChild(element('p',msg.relatedFailed+': '+failed,'av-warning'))}
|
|
7999
|
+
others.forEach(function(item){
|
|
8000
|
+
var link=element('a',item.runID+' · '+(msg.states[item.terminalOutcome]||msg.states.unknown));
|
|
8001
|
+
var url=new URL(window.location.href);url.searchParams.set('run',item.runID);url.searchParams.delete('cursor');link.href=url.href;
|
|
8002
|
+
link.setAttribute('data-agent-related-run',item.runID);link.setAttribute('data-state',item.terminalOutcome||'unknown');related.appendChild(link);
|
|
8003
|
+
});
|
|
8004
|
+
}
|
|
8005
|
+
function select(id,quiet){
|
|
8006
|
+
if(!byID.has(id)){selected=null;shell.removeAttribute('data-agent-selected');updateMetrics();updateRelated();return}
|
|
8007
|
+
selected=id;shell.setAttribute('data-agent-selected',id);
|
|
8008
|
+
nodes.forEach(function(node,key){node.group.setAttribute('aria-pressed',String(key===id))});
|
|
8009
|
+
inspectorTree.querySelectorAll('.lct-operation-card').forEach(function(card){
|
|
8010
|
+
card.hidden=card.parentElement.getAttribute('data-lifecycle-operation-id')!==id;
|
|
8011
|
+
});
|
|
8012
|
+
notice.hidden=!filtered.has(id);
|
|
8013
|
+
inspector.scrollTop=quiet?inspector.scrollTop:0;
|
|
8014
|
+
updateMetrics();updateRelated();
|
|
8015
|
+
if(!quiet){document.dispatchEvent(new CustomEvent('console-conversation-selection'))}
|
|
8016
|
+
}
|
|
8017
|
+
function applyFilters(){
|
|
8018
|
+
if(!source){return}
|
|
8019
|
+
var term=search.value.trim().toLowerCase(),branch=null;
|
|
8020
|
+
if(isolated&&byID.has(isolated)){
|
|
8021
|
+
branch=new Set([isolated]);var parent=byID.get(isolated).parentOperationID;
|
|
8022
|
+
while(parent&&byID.has(parent)&&!branch.has(parent)){branch.add(parent);parent=byID.get(parent).parentOperationID}
|
|
8023
|
+
var descend=new Set([isolated]),changed=true;
|
|
8024
|
+
while(changed){changed=false;byID.forEach(function(op,id){if(descend.has(op.parentOperationID)&&!descend.has(id)){descend.add(id);changed=true}})}
|
|
8025
|
+
descend.forEach(function(id){branch.add(id)});
|
|
8026
|
+
}
|
|
8027
|
+
filtered=new Set();
|
|
8028
|
+
byID.forEach(function(op,id){
|
|
8029
|
+
var models=(op.attempts||[]).map(function(a){return a.model?a.model.providerID+'/'+a.model.modelID:''}).join(' ');
|
|
8030
|
+
var match=(!term||[id,op.agentID||'',op.roleID,models].join(' ').toLowerCase().includes(term))&&
|
|
8031
|
+
(!role.value||op.roleID===role.value)&&(!status.value||op.state===status.value)&&(!branch||branch.has(id));
|
|
8032
|
+
if(!match){filtered.add(id)}
|
|
8033
|
+
var node=nodes.get(id);if(node){node.group.setAttribute('data-filtered',String(!match));node.group.setAttribute('tabindex',match?'0':'-1')}
|
|
8034
|
+
});
|
|
8035
|
+
viewport.querySelectorAll('[data-edge-from]').forEach(function(edge){
|
|
8036
|
+
edge.setAttribute('data-filtered',String(filtered.has(edge.getAttribute('data-edge-from'))||filtered.has(edge.getAttribute('data-edge-to'))));
|
|
8037
|
+
});
|
|
8038
|
+
chronology.querySelectorAll('[data-event-operation]').forEach(function(row){row.hidden=filtered.has(row.getAttribute('data-event-operation'))});
|
|
8039
|
+
count.textContent=msg.matches+': '+(byID.size-filtered.size)+' / '+byID.size;
|
|
8040
|
+
empty.hidden=filtered.size!==byID.size||byID.size===0;
|
|
8041
|
+
notice.hidden=!filtered.has(selected);isolate.textContent=isolated?msg.clearIsolation:msg.isolate;
|
|
8042
|
+
isolate.setAttribute('aria-pressed',String(!!isolated));
|
|
8043
|
+
}
|
|
8044
|
+
search.addEventListener('input',applyFilters);role.addEventListener('change',applyFilters);status.addEventListener('change',applyFilters);
|
|
8045
|
+
function buildGraph(){
|
|
8046
|
+
var focus=document.activeElement&&document.activeElement.getAttribute('data-agent-operation');
|
|
8047
|
+
viewport.replaceChildren();nodes.clear();layout=layoutAgentOperations(Array.from(byID.values()));
|
|
8048
|
+
var positions=new Map(layout.nodes.map(function(node){return [node.id,node]}));
|
|
8049
|
+
var defs=svgElement('defs'),marker=svgElement('marker',{id:'agent-dependency-arrow',viewBox:'0 0 8 8',refX:7,refY:4,markerWidth:6,markerHeight:6,orient:'auto'});
|
|
8050
|
+
marker.appendChild(svgElement('path',{d:'M0 0 L8 4 L0 8 Z',fill:'#8a777e'}));defs.appendChild(marker);viewport.appendChild(defs);
|
|
8051
|
+
var missing=0;
|
|
8052
|
+
function edge(from,to,kind){
|
|
8053
|
+
var a=positions.get(from),b=positions.get(to);if(!a||!b){missing++;return}
|
|
8054
|
+
var x1=a.x+228,y1=a.y+56,x2=b.x,y2=b.y+56,middle=(x1+x2)/2;
|
|
8055
|
+
var path=svgElement('path',{'class':'av-edge','data-kind':kind,'data-edge-from':from,'data-edge-to':to,
|
|
8056
|
+
d:'M'+x1+' '+y1+' C'+middle+' '+y1+' '+middle+' '+y2+' '+x2+' '+y2});
|
|
8057
|
+
if(kind==='dependency'){path.setAttribute('marker-end','url(#agent-dependency-arrow)')}
|
|
8058
|
+
path.appendChild(svgElement('title',{},(kind==='hierarchy'?msg.hierarchy:msg.dependency)+': '+from+' -> '+to));viewport.appendChild(path);
|
|
8059
|
+
}
|
|
8060
|
+
byID.forEach(function(operation){
|
|
8061
|
+
if(operation.parentOperationID){edge(operation.parentOperationID,operation.operationID,'hierarchy')}
|
|
8062
|
+
(operation.dependsOnOperationIDs||[]).forEach(function(id){edge(id,operation.operationID,'dependency')});
|
|
8063
|
+
});
|
|
8064
|
+
unresolved.textContent=msg.missing+': '+missing;unresolved.hidden=missing===0;
|
|
8065
|
+
layout.nodes.forEach(function(position){
|
|
8066
|
+
var operation=byID.get(position.id),attempt=lastAttempt(operation),identity=operation.agentID||operation.roleID;
|
|
8067
|
+
var group=svgElement('g',{'class':'av-node',transform:'translate('+position.x+' '+position.y+')','data-agent-operation':position.id,
|
|
8068
|
+
'data-state':operation.state,role:'button',tabindex:0,'aria-label':identity+' · '+operation.roleID+' · '+(msg.states[operation.state]||msg.states.unknown)});
|
|
8069
|
+
group.appendChild(svgElement('rect',{width:228,height:120,rx:12}));
|
|
8070
|
+
group.appendChild(svgElement('title',{},identity+' · '+position.id));
|
|
8071
|
+
group.appendChild(svgElement('text',{x:14,y:23,'class':'av-role'},operation.roleID.slice(0,31)));
|
|
8072
|
+
group.appendChild(svgElement('text',{x:14,y:45,'class':'av-name'},identity.slice(0,28)));
|
|
8073
|
+
var model=attempt&&attempt.model?attempt.model.providerID+'/'+attempt.model.modelID:msg.noModel;
|
|
8074
|
+
group.appendChild(svgElement('text',{x:14,y:64,'class':'av-model'},model.slice(0,32)));
|
|
8075
|
+
var phase=svgElement('text',{x:14,y:84,'class':'av-phase'},phaseFor(operation));group.appendChild(phase);
|
|
8076
|
+
var failures=(operation.attempts||[]).filter(function(a){return ['failed','interrupted','cancelled'].includes(a.state)}).length;
|
|
8077
|
+
group.appendChild(svgElement('text',{x:14,y:105,'class':'av-attempts'},msg.attempts+': '+operation.attempts.length+' · '+msg.failures+': '+failures));
|
|
8078
|
+
group.addEventListener('click',function(){select(position.id)});
|
|
8079
|
+
group.addEventListener('keydown',function(event){if(event.key==='Enter'||event.key===' '){event.preventDefault();select(position.id)}});
|
|
8080
|
+
nodes.set(position.id,{group:group,phase:phase});viewport.appendChild(group);
|
|
8081
|
+
});
|
|
8082
|
+
transform();if(!positioned){fit()}
|
|
8083
|
+
if(focus&&nodes.has(focus)){nodes.get(focus).group.focus({preventScroll:true})}
|
|
8084
|
+
}
|
|
8085
|
+
function buildChronology(){
|
|
8086
|
+
var top=chronology.scrollTop;chronology.replaceChildren();var events=source.timeline||[];
|
|
8087
|
+
if(!events.length){chronology.appendChild(element('li',msg.noEvents))}
|
|
8088
|
+
if(events.length>1000){chronology.appendChild(element('li',msg.eventWindow))}
|
|
8089
|
+
events.slice(-1000).forEach(function(event){
|
|
8090
|
+
var id=event.operationID||event.root&&event.root.operationID||source.rootOperationID,op=byID.get(id);
|
|
8091
|
+
var row=element('li');row.setAttribute('data-event-operation',id);row.setAttribute('data-event-seq',String(event.seq));
|
|
8092
|
+
var item=button('',function(){pause();select(id);seek(event.seq+1,true)});
|
|
8093
|
+
item.appendChild(element('time',new Date(event.at).toISOString()));
|
|
8094
|
+
item.appendChild(element('strong',msg.events[event.type]||event.type));
|
|
8095
|
+
item.appendChild(element('span',(op&&(op.agentID||op.roleID)||id)+(event.outcome?' · '+(msg.states[event.outcome]||event.outcome):'')));
|
|
8096
|
+
row.appendChild(item);chronology.appendChild(row);
|
|
8097
|
+
});chronology.scrollTop=top;
|
|
8098
|
+
}
|
|
8099
|
+
function seek(cursor,push){pendingCursor=cursor;options.seek(cursor,push)}
|
|
8100
|
+
function pause(){playing=false;clearTimeout(playTimer);playTimer=null;playButton.textContent=msg.play;playButton.setAttribute('aria-label',msg.play);playButton.setAttribute('aria-pressed','false')}
|
|
8101
|
+
function tick(){
|
|
8102
|
+
if(!playing||!source){return}
|
|
8103
|
+
if(document.hidden||!shell.isConnected){pause();return}
|
|
8104
|
+
if(pendingCursor===null||source.cursor===pendingCursor){
|
|
8105
|
+
if(source.cursor>=source.head){pause();return}
|
|
8106
|
+
seek(source.cursor+1,false);
|
|
8107
|
+
}
|
|
8108
|
+
playTimer=setTimeout(tick,1000/Number(speed.value));
|
|
8109
|
+
}
|
|
8110
|
+
function togglePlayback(){
|
|
8111
|
+
if(playing){pause();return}if(!source||source.head===0){return}
|
|
8112
|
+
playing=true;playButton.textContent=msg.pause;playButton.setAttribute('aria-label',msg.pause);playButton.setAttribute('aria-pressed','true');
|
|
8113
|
+
seek(source.cursor>=source.head?0:source.cursor,true);playTimer=setTimeout(tick,1000/Number(speed.value));
|
|
8114
|
+
}
|
|
8115
|
+
function rememberDetails(){
|
|
8116
|
+
if(!tree){return}
|
|
8117
|
+
tree.querySelectorAll('[data-lifecycle-operation-id]').forEach(function(article){
|
|
8118
|
+
var card=article.querySelector('.lct-operation-card');if(!card){return}
|
|
8119
|
+
card.querySelectorAll('details:not(.lc-conversation details)').forEach(function(detail,index){
|
|
8120
|
+
openDetails.set(article.getAttribute('data-lifecycle-operation-id')+':'+index,detail.open);
|
|
8121
|
+
});
|
|
8122
|
+
});
|
|
8123
|
+
}
|
|
8124
|
+
function update(projection,nextTree){
|
|
8125
|
+
var changedRun=run!==projection.runID;
|
|
8126
|
+
if(changedRun){pause();selected=projection.rootOperationID;isolated=null;positioned=false;openDetails.clear()}
|
|
8127
|
+
else{rememberDetails()}
|
|
8128
|
+
run=projection.runID;source=projection;
|
|
8129
|
+
byID=new Map((projection.operations||[]).map(function(op){return [op.operationID,op]}));
|
|
8130
|
+
if(!byID.has(selected)){selected=byID.has(projection.rootOperationID)?projection.rootOperationID:byID.keys().next().value}
|
|
8131
|
+
var oldRole=role.value;role.replaceChildren();option(role,'',msg.allRoles);
|
|
8132
|
+
Array.from(new Set(Array.from(byID.values()).map(function(op){return op.roleID}))).sort().forEach(function(value){option(role,value,value)});
|
|
8133
|
+
if(Array.from(role.options).some(function(item){return item.value===oldRole})){role.value=oldRole}
|
|
8134
|
+
var top=inspector.scrollTop;tree=nextTree;inspectorTree.replaceChildren(tree);
|
|
8135
|
+
tree.querySelectorAll('[data-lifecycle-operation-id]').forEach(function(article){
|
|
8136
|
+
var card=article.querySelector('.lct-operation-card');if(!card){return}
|
|
8137
|
+
card.querySelectorAll('details').forEach(function(detail,index){
|
|
8138
|
+
var saved=openDetails.get(article.getAttribute('data-lifecycle-operation-id')+':'+index);if(saved!==undefined){detail.open=saved}
|
|
8139
|
+
});
|
|
8140
|
+
});
|
|
8141
|
+
isolate.disabled=byID.size===0;
|
|
8142
|
+
buildGraph();buildChronology();applyFilters();select(selected,true);setMode(mode);inspector.scrollTop=changedRun?0:top;
|
|
8143
|
+
}
|
|
8144
|
+
function onTelemetry(event){
|
|
8145
|
+
summaries=new Map((event.detail&&event.detail.sessions||[]).map(function(item){return [item.sessionID,item]}));
|
|
8146
|
+
if(shell.isConnected){updateMetrics()}
|
|
8147
|
+
}
|
|
8148
|
+
function onVisibility(){if(document.hidden){pause()}}
|
|
8149
|
+
document.addEventListener('console-telemetry',onTelemetry);
|
|
8150
|
+
document.addEventListener('visibilitychange',onVisibility);
|
|
8151
|
+
window.addEventListener('pagehide',pause);
|
|
8152
|
+
return {update:update,pause:pause,connected:function(){return shell.isConnected},refresh:function(){updateMetrics();updateRelated();if(!positioned&&mode==='graph'){fit()}},
|
|
8153
|
+
dispose:function(){pause();document.removeEventListener('console-telemetry',onTelemetry);document.removeEventListener('visibilitychange',onVisibility);
|
|
8154
|
+
window.removeEventListener('pagehide',pause);host.classList.remove('av-host')}};
|
|
8155
|
+
}
|
|
8156
|
+
`;
|
|
8157
|
+
var AGENT_VIEW_STYLE = `
|
|
8158
|
+
#screen-tree:has(.av-workspace){max-width:none}
|
|
8159
|
+
.av-host{max-height:none;padding:0;overflow:visible}
|
|
8160
|
+
.av-workspace{--av-bg:#121012;--av-text:#f3edef;--av-muted:#b7aab0;--av-line:#3b3036;--av-accent:#c9184c;--cp-bg:#121012;--cp-surface:#1d181c;--cp-surface-soft:#262026;--cp-text:#f3edef;--cp-text-muted:#b7aab0;--cp-border:#3b3036;--cp-border-strong:#79646d;--cp-accent:#f47b9e;--cp-success:#77c491;--cp-danger:#ff8699;color:var(--av-text);background:var(--av-bg);border:1px solid var(--av-line);border-radius:14px;overflow:hidden}
|
|
8161
|
+
.av-workspace [hidden]{display:none!important}
|
|
8162
|
+
.av-workspace button,.av-workspace input,.av-workspace select{font:inherit;color:inherit;background:#211b20;border:1px solid var(--av-line);border-radius:7px;padding:6px 9px}
|
|
8163
|
+
.av-workspace button:hover,.av-workspace button[aria-pressed="true"]{border-color:#ee7399;color:#ffa2be}
|
|
8164
|
+
.av-workspace :focus-visible{outline:2px solid #ec5282;outline-offset:3px}
|
|
8165
|
+
.av-toolbar{display:flex;align-items:center;gap:7px;flex-wrap:wrap;padding:12px;border-bottom:1px solid var(--av-line);font-size:12px}
|
|
8166
|
+
.av-toolbar label{display:flex;align-items:center;gap:6px}.av-count{margin-left:auto;color:var(--av-muted)}
|
|
8167
|
+
.av-body{display:grid;grid-template-columns:180px minmax(300px,1fr) minmax(280px,360px);height:min(78vh,860px);min-height:520px}
|
|
8168
|
+
.av-filters{padding:16px 12px;border-right:1px solid var(--av-line);overflow:auto;font-size:12px}
|
|
8169
|
+
.av-filters h3,.av-inspector>h3{color:var(--av-text);font-size:12px;letter-spacing:.06em;text-transform:uppercase;margin-bottom:14px}
|
|
8170
|
+
.av-filters label{display:grid;gap:6px;margin-bottom:14px;color:var(--av-muted)}
|
|
8171
|
+
.av-filters input,.av-filters select{width:100%;min-width:0;color:var(--av-text)}
|
|
8172
|
+
.av-filters>button{display:block;width:100%;margin:9px 0;font-size:12px;text-align:left}
|
|
8173
|
+
.av-filters p,.av-related p{margin:10px 0;color:var(--av-muted);line-height:1.5;font-size:11px}
|
|
8174
|
+
.av-legend{margin-top:24px;border-top:1px solid var(--av-line);padding-top:8px}
|
|
8175
|
+
.av-solid:before,.av-dashed:before{content:"";display:inline-block;width:24px;border-top:2px solid #b7aab0;margin-right:7px;vertical-align:middle}.av-dashed:before{border-top-style:dashed}
|
|
8176
|
+
.av-center{position:relative;min-width:0;background:#fdfbf6;color:#30272d}
|
|
8177
|
+
.av-canvas{position:relative;height:100%;min-height:380px;overflow:hidden;background-image:radial-gradient(#e3d9db .8px,transparent .8px);background-size:20px 20px}
|
|
8178
|
+
.av-zoom{position:absolute;display:flex;gap:5px;top:12px;left:12px;z-index:2;flex-wrap:wrap}
|
|
8179
|
+
.av-zoom button{background:#fdfbf6;color:#342c30;border-color:#d6c5cb;font-size:11px;box-shadow:0 1px 3px #0001}
|
|
8180
|
+
.av-zoom button:hover{color:#a50e3c}
|
|
8181
|
+
.av-graph{width:100%;height:100%;display:block;cursor:grab;touch-action:none}
|
|
8182
|
+
.av-node{cursor:pointer;outline:none}.av-node rect{fill:#fffdf9;stroke:#d2c5ca;stroke-width:1.5}
|
|
8183
|
+
.av-node:hover rect,.av-node:focus-visible rect{stroke:#69434f;stroke-width:2}
|
|
8184
|
+
.av-node[aria-pressed="true"] rect{stroke:#c9184c;stroke-width:2.5}
|
|
8185
|
+
.av-node[data-state="failed"] rect,.av-node[data-state="interrupted"] rect{fill:#fff0f1;stroke:#bf3150}
|
|
8186
|
+
.av-node[data-state="succeeded"] rect{fill:#f4faf3;stroke:#79a186}
|
|
8187
|
+
.av-node text{fill:#362b31;font:11px var(--font-sans);pointer-events:none}
|
|
8188
|
+
.av-node .av-role{fill:#755f69;font-size:10px;letter-spacing:.04em}
|
|
8189
|
+
.av-node .av-name{font-size:16px;font-weight:650}
|
|
8190
|
+
.av-node .av-model,.av-node .av-attempts{fill:#6d5a63;font-size:10px;font-family:var(--font-mono)}
|
|
8191
|
+
.av-node .av-phase{fill:#9d234b;font-size:11px}
|
|
8192
|
+
.av-node[data-filtered="true"]{opacity:.22}
|
|
8193
|
+
.av-edge{fill:none;stroke:#a6969c;stroke-width:1.5}
|
|
8194
|
+
.av-edge[data-kind="dependency"]{stroke:#bd5776;stroke-dasharray:5 5}
|
|
8195
|
+
.av-edge[data-filtered="true"]{opacity:.12}
|
|
8196
|
+
.av-empty{position:absolute;bottom:18px;left:18px;right:18px;background:#fdfbf6;padding:10px;border:1px solid #d6c5cb;border-radius:7px;font-size:12px}
|
|
8197
|
+
.av-inspector{overflow:auto;min-width:0;padding:16px 14px;border-left:1px solid var(--av-line);overflow-anchor:none}
|
|
8198
|
+
.av-inspector .lct-tree,.av-inspector .lct-operation{min-width:0;margin:0;padding:0;max-width:100%}
|
|
8199
|
+
.av-inspector .lct-operation-children{margin:0;padding:0;border:0}
|
|
8200
|
+
.av-inspector .lct-operation-card{border-left-width:3px;box-shadow:none;border-radius:8px;padding:12px}
|
|
8201
|
+
.av-inspector .lct-operation-meta,.av-inspector .lct-attempt-meta{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
|
|
8202
|
+
.av-inspector .lct-operation-head,.av-inspector .lct-attempt-head{flex-wrap:wrap}
|
|
8203
|
+
.av-inspector .lct-session{display:block}.av-inspector code,.av-inspector dd{overflow-wrap:anywhere;word-break:break-word}
|
|
8204
|
+
.av-inspector .lc-conversation{padding:9px}.av-inspector .lc-conversation pre{padding:8px;font-size:11px}
|
|
8205
|
+
.av-inspector .lct-attempt{padding:10px;min-width:0}
|
|
8206
|
+
.av-inspector .lct-times{display:block;font-size:10px}
|
|
8207
|
+
.av-inspector .lct-unlinked>h4,.av-inspector .lct-unlinked>p,.av-inspector .lct-no-attempts{font-size:11px}
|
|
8208
|
+
.av-metrics{margin-bottom:14px;font-size:11px;border-bottom:1px solid var(--av-line);padding-bottom:10px}
|
|
8209
|
+
.av-metrics p{display:flex;flex-wrap:wrap;gap:3px 8px;justify-content:space-between;margin:5px 0}.av-metrics span{color:var(--av-muted)}
|
|
8210
|
+
.av-related{margin-top:18px}.av-related a{display:block;color:#f59fba;overflow-wrap:anywhere;font-size:11px;margin:8px 0}
|
|
8211
|
+
.av-related a[data-state="failed"],.av-warning{color:#ff8699!important}
|
|
8212
|
+
.av-chronology{list-style:none;margin:0;padding:18px;height:100%;overflow:auto}
|
|
8213
|
+
.av-chronology li{border-left:2px solid #d2c5ca;padding:0 0 12px 16px}
|
|
8214
|
+
.av-chronology button{display:grid;gap:7px;text-align:left;width:100%;background:#fffdf9;color:#30272d;border-color:#d2c5ca;padding:12px}
|
|
8215
|
+
.av-chronology button:hover{border-color:#c9184c;color:#9d234b}
|
|
8216
|
+
.av-chronology time{font:10px var(--font-mono);color:#725e68}.av-chronology span{font-size:11px;overflow-wrap:anywhere}
|
|
8217
|
+
.av-replay-note{padding:10px 14px;margin:0;border-top:1px solid var(--av-line);color:var(--av-muted);font-size:11px}
|
|
8218
|
+
@media(max-width:1280px){.av-body{grid-template-columns:145px minmax(250px,1fr) 300px}.av-toolbar{gap:5px}}
|
|
8219
|
+
@media(max-width:1050px){.av-body{grid-template-columns:minmax(250px,1fr) 300px}.av-filters{grid-column:1/-1;display:flex;flex-wrap:wrap;gap:10px;align-items:center;border-bottom:1px solid var(--av-line);max-height:150px}.av-filters label{width:150px;margin:0}.av-filters>button{width:auto}.av-filters h3,.av-filters>p,.av-legend{display:none}.av-body{height:auto}.av-center,.av-inspector{height:620px}}
|
|
8220
|
+
@media(max-width:740px){.av-body{display:block}.av-center{height:430px}.av-inspector{height:auto;max-height:650px;border-left:0;border-top:1px solid var(--av-line)}.av-count{width:100%;margin:0}.av-filters{max-height:none}.av-toolbar{font-size:11px}}
|
|
8221
|
+
@media(prefers-reduced-motion:reduce){.av-workspace *{animation:none!important;transition:none!important}}
|
|
8222
|
+
`;
|
|
8223
|
+
|
|
7469
8224
|
// src/console/inspector.ts
|
|
7470
8225
|
var CONVERSATION_CLIENT_JS = `
|
|
7471
8226
|
function wireConversationInspector(){
|
|
@@ -7708,7 +8463,9 @@ function wireConversationInspector(){
|
|
|
7708
8463
|
});
|
|
7709
8464
|
document.addEventListener('conversation-tree-replacing',function(){
|
|
7710
8465
|
var scroll=document.querySelector('.scroll'),tree=mount&&mount.querySelector('[data-lifecycle-tree-mount]');
|
|
7711
|
-
|
|
8466
|
+
var inspector=mount&&mount.querySelector('.av-inspector');
|
|
8467
|
+
retained={focus:document.activeElement,scroll:scroll,scrollTop:scroll&&scroll.scrollTop,treeTop:tree&&tree.scrollTop,
|
|
8468
|
+
inspector:inspector,inspectorTop:inspector&&inspector.scrollTop,positions:[]};
|
|
7712
8469
|
records.forEach(function(record){
|
|
7713
8470
|
[record.body].concat(Array.from(record.panel.querySelectorAll('pre'))).forEach(function(node){
|
|
7714
8471
|
retained.positions.push([node,node.scrollTop,node.scrollLeft]);
|
|
@@ -7723,6 +8480,7 @@ function wireConversationInspector(){
|
|
|
7723
8480
|
var tree=mount&&mount.querySelector('[data-lifecycle-tree-mount]');
|
|
7724
8481
|
if(tree&&retained.treeTop!==null){tree.scrollTop=retained.treeTop}
|
|
7725
8482
|
if(retained.scroll){retained.scroll.scrollTop=retained.scrollTop}
|
|
8483
|
+
if(retained.inspector&&retained.inspector.isConnected){retained.inspector.scrollTop=retained.inspectorTop}
|
|
7726
8484
|
if(retained.focus&&retained.focus.isConnected&&retained.focus!==document.activeElement&&
|
|
7727
8485
|
(!document.activeElement||document.activeElement===document.body||document.activeElement===document.documentElement)){
|
|
7728
8486
|
retained.focus.focus({preventScroll:true});
|
|
@@ -7877,6 +8635,8 @@ var CONSOLE_REFRESH_JS = `
|
|
|
7877
8635
|
if(viewStopped||viewRequest!==controller||!result){return}
|
|
7878
8636
|
if(typeof result.data.routing!=='string'||typeof result.data.logs!=='string'){return}
|
|
7879
8637
|
latestView=result.data;viewRevision=result.revision;
|
|
8638
|
+
document.__consoleTelemetry=latestView.sessionSummaries||[];
|
|
8639
|
+
document.dispatchEvent(new CustomEvent('console-telemetry',{detail:{sessions:latestView.sessionSummaries||[]}}));
|
|
7880
8640
|
var updated=document.querySelector('.token-chip b');
|
|
7881
8641
|
if(updated&&typeof latestView.updatedAt==='string'){updated.textContent=latestView.updatedAt}
|
|
7882
8642
|
if(Number.isInteger(latestView.refreshMs)&&latestView.refreshMs>=250&&latestView.refreshMs!==ms){
|
|
@@ -8515,6 +9275,7 @@ var LIFECYCLE_THEME_BOOT = `
|
|
|
8515
9275
|
})();
|
|
8516
9276
|
`;
|
|
8517
9277
|
var LIFECYCLE_CLIENT_JS = `
|
|
9278
|
+
${AGENT_VIEW_CLIENT_JS}
|
|
8518
9279
|
function wireLifecycleTimeline(){
|
|
8519
9280
|
var mount=document.getElementById('lifecycle-timeline-mount');
|
|
8520
9281
|
if(!mount){return}
|
|
@@ -8553,6 +9314,11 @@ function wireLifecycleTimeline(){
|
|
|
8553
9314
|
lastSseHead:new Map()
|
|
8554
9315
|
};
|
|
8555
9316
|
var projectionKey='';
|
|
9317
|
+
var agentViewer=null,agentRuns=[],agentRootOperationID=null;
|
|
9318
|
+
function clearAgentViewer(){
|
|
9319
|
+
if(agentViewer){agentViewer.dispose();agentViewer=null}
|
|
9320
|
+
var note=mount.querySelector('[data-agent-degraded]');if(note){note.remove()}
|
|
9321
|
+
}
|
|
8556
9322
|
var committedRun=mount.getAttribute('data-lifecycle-run')||null,committedCursor=urlCursor();
|
|
8557
9323
|
|
|
8558
9324
|
function invalidateConversation(){
|
|
@@ -8687,6 +9453,7 @@ function wireLifecycleTimeline(){
|
|
|
8687
9453
|
if(sliderWired||!slider){return}
|
|
8688
9454
|
sliderWired=true;
|
|
8689
9455
|
slider.addEventListener('input',function(){
|
|
9456
|
+
if(agentViewer){agentViewer.pause()}
|
|
8690
9457
|
var c=parseInt(slider.value,10);
|
|
8691
9458
|
if(!scrubInProgress){
|
|
8692
9459
|
history.pushState(null,'',window.location.href);
|
|
@@ -8829,6 +9596,7 @@ function wireLifecycleTimeline(){
|
|
|
8829
9596
|
function renderView(d,requestedCursor){
|
|
8830
9597
|
ensureViewControls();
|
|
8831
9598
|
state.runID=d.selection.runID;
|
|
9599
|
+
agentRuns=d.runs||[];
|
|
8832
9600
|
state.head=d.selection.head;
|
|
8833
9601
|
state.cursor=d.selection.cursor;
|
|
8834
9602
|
state.followLive=requestedCursor===null;
|
|
@@ -8905,6 +9673,7 @@ function wireLifecycleTimeline(){
|
|
|
8905
9673
|
}
|
|
8906
9674
|
|
|
8907
9675
|
function renderLegacy(d){
|
|
9676
|
+
clearAgentViewer();
|
|
8908
9677
|
ensureViewControls();
|
|
8909
9678
|
state.runID=d.selection.runID;
|
|
8910
9679
|
state.head=0;
|
|
@@ -8943,19 +9712,37 @@ function wireLifecycleTimeline(){
|
|
|
8943
9712
|
|
|
8944
9713
|
function renderProjection(proj,recording){
|
|
8945
9714
|
if(!proj||!treeMountEl){return}
|
|
9715
|
+
agentRootOperationID=proj.rootOperationID;
|
|
8946
9716
|
var degraded=recording&&recording.state==='degraded';
|
|
8947
9717
|
var option=runSelect&&Array.from(runSelect.options).find(function(o){return o.value===proj.runID});
|
|
8948
9718
|
var key=JSON.stringify([proj.runID,proj.cursor,proj.rootOperationID,proj.operations,degraded,option&&option.getAttribute('data-run-session')]);
|
|
8949
|
-
if(key===projectionKey){return}
|
|
9719
|
+
if(key===projectionKey){if(agentViewer){agentViewer.refresh()}return}
|
|
8950
9720
|
projectionKey=key;
|
|
8951
9721
|
document.dispatchEvent(new CustomEvent('conversation-tree-replacing'));
|
|
8952
|
-
|
|
9722
|
+
if(!agentViewer||!agentViewer.connected()){
|
|
9723
|
+
if(agentViewer){agentViewer.dispose()}
|
|
9724
|
+
agentViewer=createAgentViewer(treeMountEl,{
|
|
9725
|
+
isLive:function(){return state.followLive},
|
|
9726
|
+
runs:function(){return agentRuns},
|
|
9727
|
+
rootSessionID:function(id){
|
|
9728
|
+
if(id!==agentRootOperationID){return undefined}
|
|
9729
|
+
var option=runSelect&&Array.from(runSelect.options).find(function(o){return o.value===state.runID});
|
|
9730
|
+
return option&&option.getAttribute('data-run-session')||undefined;
|
|
9731
|
+
},
|
|
9732
|
+
seek:function(cursor,push){
|
|
9733
|
+
if(push){pushUrl(state.runID,cursor)}else{replaceUrl(state.runID,cursor)}
|
|
9734
|
+
navigateFromUrl(false);
|
|
9735
|
+
}
|
|
9736
|
+
});
|
|
9737
|
+
}
|
|
9738
|
+
var priorNote=mount.querySelector('[data-agent-degraded]');if(priorNote){priorNote.remove()}
|
|
8953
9739
|
if(degraded){
|
|
8954
9740
|
var note=makeElement('div','lc-partial-note',message('partial-tail'));
|
|
9741
|
+
note.setAttribute('data-agent-degraded','');
|
|
8955
9742
|
note.setAttribute('role','status');
|
|
8956
|
-
treeMountEl.
|
|
9743
|
+
treeMountEl.before(note);
|
|
8957
9744
|
}
|
|
8958
|
-
|
|
9745
|
+
agentViewer.update(proj,buildOperationTree(proj));
|
|
8959
9746
|
}
|
|
8960
9747
|
|
|
8961
9748
|
function makeElement(tag,className,text){
|
|
@@ -9288,6 +10075,7 @@ function wireLifecycleTimeline(){
|
|
|
9288
10075
|
}
|
|
9289
10076
|
|
|
9290
10077
|
function showError(){
|
|
10078
|
+
clearAgentViewer();
|
|
9291
10079
|
invalidateConversation();
|
|
9292
10080
|
projectionKey='';
|
|
9293
10081
|
mount.setAttribute('data-lifecycle-state','error');
|
|
@@ -9304,6 +10092,7 @@ function wireLifecycleTimeline(){
|
|
|
9304
10092
|
}
|
|
9305
10093
|
|
|
9306
10094
|
function showApiError(err){
|
|
10095
|
+
clearAgentViewer();
|
|
9307
10096
|
projectionKey='';
|
|
9308
10097
|
mount.setAttribute('data-lifecycle-state','error');
|
|
9309
10098
|
updateScreenCopy('unavailable',false,null);
|
|
@@ -9320,6 +10109,7 @@ function wireLifecycleTimeline(){
|
|
|
9320
10109
|
}
|
|
9321
10110
|
|
|
9322
10111
|
function showDisabled(d){
|
|
10112
|
+
clearAgentViewer();
|
|
9323
10113
|
projectionKey='';
|
|
9324
10114
|
mount.setAttribute('data-lifecycle-state','disabled');
|
|
9325
10115
|
updateScreenCopy('unavailable',false,null);
|
|
@@ -9337,6 +10127,7 @@ function wireLifecycleTimeline(){
|
|
|
9337
10127
|
}
|
|
9338
10128
|
|
|
9339
10129
|
function showEmpty(){
|
|
10130
|
+
clearAgentViewer();
|
|
9340
10131
|
projectionKey='';
|
|
9341
10132
|
mount.setAttribute('data-lifecycle-state','empty');
|
|
9342
10133
|
updateScreenCopy('empty',false,null);
|
|
@@ -9355,6 +10146,7 @@ function wireLifecycleTimeline(){
|
|
|
9355
10146
|
// --- Run selector change ---
|
|
9356
10147
|
if(runSelect){
|
|
9357
10148
|
runSelect.addEventListener('change',function(){
|
|
10149
|
+
if(agentViewer){agentViewer.pause()}
|
|
9358
10150
|
var newRun=runSelect.value;
|
|
9359
10151
|
pushUrl(newRun,null); // committed selection → traversable entry
|
|
9360
10152
|
navigateFromUrl(false);
|
|
@@ -9369,6 +10161,7 @@ function wireLifecycleTimeline(){
|
|
|
9369
10161
|
// --- Live / Return to live ---
|
|
9370
10162
|
if(liveBtn){
|
|
9371
10163
|
liveBtn.addEventListener('click',function(){
|
|
10164
|
+
if(agentViewer){agentViewer.pause()}
|
|
9372
10165
|
pushUrl(state.explicitRun,null); // return-to-live preserves automatic run selection
|
|
9373
10166
|
navigateFromUrl(false);
|
|
9374
10167
|
});
|
|
@@ -9393,6 +10186,7 @@ function wireLifecycleTimeline(){
|
|
|
9393
10186
|
|
|
9394
10187
|
// --- Browser back/forward ---
|
|
9395
10188
|
window.addEventListener('popstate',function(){
|
|
10189
|
+
if(agentViewer){agentViewer.pause()}
|
|
9396
10190
|
navigateFromUrl(false);
|
|
9397
10191
|
});
|
|
9398
10192
|
|
|
@@ -9447,7 +10241,11 @@ function ms(value) {
|
|
|
9447
10241
|
return value >= 1000 ? `${(value / 1000).toFixed(2)}s` : `${Math.round(value)}ms`;
|
|
9448
10242
|
}
|
|
9449
10243
|
function avgMs(stats) {
|
|
9450
|
-
|
|
10244
|
+
const known = stats.count - (stats.unknownDurationCount ?? 0);
|
|
10245
|
+
return stats.count === 0 ? "—" : known === 0 ? consoleDetailMessages.timingUnknown : ms(stats.totalDurationMs / known);
|
|
10246
|
+
}
|
|
10247
|
+
function measured(value, unavailable) {
|
|
10248
|
+
return (unavailable ?? 0) === 0 ? String(value) : `<span title="${escapeHtml(consoleDetailMessages.usageCaution)}">${escapeHtml(consoleDetailMessages.usageUnavailable)}</span>`;
|
|
9451
10249
|
}
|
|
9452
10250
|
function agentModel(agent) {
|
|
9453
10251
|
return agent.model === undefined ? "inherits default" : `${agent.model.providerID}/${agent.model.modelID}`;
|
|
@@ -9462,15 +10260,16 @@ function summaryPanel(cost) {
|
|
|
9462
10260
|
return [
|
|
9463
10261
|
'<section class="panel" id="panel-summary">',
|
|
9464
10262
|
"<h2>Routing summary</h2>",
|
|
10263
|
+
`<p class="muted">${escapeHtml(consoleDetailMessages.estimatesNotUsage)}</p>`,
|
|
9465
10264
|
'<div class="grid">',
|
|
9466
10265
|
`<div class="stat"><span class="k">Decisions</span><span class="v">${cost.count}</span></div>`,
|
|
9467
10266
|
`<div class="stat"><span class="k">Local</span><span class="v">${cost.localCount}</span></div>`,
|
|
9468
10267
|
`<div class="stat"><span class="k">Frontier</span><span class="v">${cost.frontierCount}</span></div>`,
|
|
9469
|
-
`<div class="stat"><span class="k"
|
|
9470
|
-
`<div class="stat"><span class="k"
|
|
9471
|
-
`<div class="stat"><span class="k"
|
|
9472
|
-
`<div class="stat"><span class="k"
|
|
9473
|
-
`<div class="stat"><span class="k"
|
|
10268
|
+
`<div class="stat"><span class="k">${escapeHtml(consoleDetailMessages.estimatedCost)}</span><span class="v">${usd(cost.totalEstimatedUSD)}</span></div>`,
|
|
10269
|
+
`<div class="stat"><span class="k">${escapeHtml(consoleDetailMessages.estimatedBaseline)}</span><span class="v">${usd(cost.totalBaselineUSD)}</span></div>`,
|
|
10270
|
+
`<div class="stat"><span class="k">${escapeHtml(consoleDetailMessages.estimatedSavings)}</span><span class="v good">${usd(cost.totalSavingsUSD)} (${pct(cost.savingsPct)})</span></div>`,
|
|
10271
|
+
`<div class="stat"><span class="k">${escapeHtml(consoleDetailMessages.estimatedInput)}</span><span class="v">${cost.tokensIn}</span></div>`,
|
|
10272
|
+
`<div class="stat"><span class="k">${escapeHtml(consoleDetailMessages.estimatedOutput)}</span><span class="v">${cost.tokensOut}</span></div>`,
|
|
9474
10273
|
"</div>",
|
|
9475
10274
|
"</section>"
|
|
9476
10275
|
].join("");
|
|
@@ -9585,12 +10384,12 @@ function totalsPanel(totals) {
|
|
|
9585
10384
|
'<div class="grid">',
|
|
9586
10385
|
`<div class="stat"><span class="k">Sessions</span><span class="v">${totals.sessions}</span></div>`,
|
|
9587
10386
|
`<div class="stat"><span class="k">Messages</span><span class="v">${totals.messageCount}</span></div>`,
|
|
9588
|
-
`<div class="stat"><span class="k">Real cost</span><span class="v">${usd(totals.realCostUSD)}</span></div>`,
|
|
10387
|
+
`<div class="stat"><span class="k">Real cost</span><span class="v">${measured(usd(totals.realCostUSD), totals.unavailableCostMessages)}</span></div>`,
|
|
9589
10388
|
`<div class="stat"><span class="k">Est. savings</span><span class="v good">${usd(totals.estimatedSavingsUSD)}</span></div>`,
|
|
9590
|
-
`<div class="stat"><span class="k">Tokens in</span><span class="v">${totals.tokensIn}</span></div>`,
|
|
9591
|
-
`<div class="stat"><span class="k">Tokens out</span><span class="v">${totals.tokensOut}</span></div>`,
|
|
9592
|
-
`<div class="stat"><span class="k">Reasoning</span><span class="v">${totals.tokensReasoning}</span></div>`,
|
|
9593
|
-
`<div class="stat"><span class="k">Cache r/w</span><span class="v">${totals.tokensCacheRead}/${totals.tokensCacheWrite}</span></div>`,
|
|
10389
|
+
`<div class="stat"><span class="k">Tokens in</span><span class="v">${measured(totals.tokensIn, totals.unavailableUsageMessages)}</span></div>`,
|
|
10390
|
+
`<div class="stat"><span class="k">Tokens out</span><span class="v">${measured(totals.tokensOut, totals.unavailableUsageMessages)}</span></div>`,
|
|
10391
|
+
`<div class="stat"><span class="k">Reasoning</span><span class="v">${measured(totals.tokensReasoning, totals.unavailableUsageMessages)}</span></div>`,
|
|
10392
|
+
`<div class="stat"><span class="k">Cache r/w</span><span class="v">${measured(`${totals.tokensCacheRead}/${totals.tokensCacheWrite}`, totals.unavailableUsageMessages)}</span></div>`,
|
|
9594
10393
|
`<div class="stat"><span class="k">Toolcalls</span><span class="v">${t.count} <span class="good">${t.ok}✓</span> <span class="frontier">${t.failed}✗</span></span></div>`,
|
|
9595
10394
|
`<div class="stat"><span class="k">Avg tool dur.</span><span class="v">${avgMs(t)}</span></div>`,
|
|
9596
10395
|
"</div>",
|
|
@@ -9613,8 +10412,8 @@ function sessionRow(session2) {
|
|
|
9613
10412
|
`<td>${sessionNameHtml(session2.sessionID, sessionName(session2))}<br>${observedTimeHtml(session2)}<br><code>${escapeHtml(session2.sessionID)}</code></td>`,
|
|
9614
10413
|
`<td>${models}</td>`,
|
|
9615
10414
|
`<td><span class="local">${session2.localCount}</span>/<span class="frontier">${session2.frontierCount}</span></td>`,
|
|
9616
|
-
`<td>${usd(session2.realCostUSD)}</td>`,
|
|
9617
|
-
`<td>${session2.tokensIn}/${session2.tokensOut}</td>`,
|
|
10415
|
+
`<td>${measured(usd(session2.realCostUSD), session2.unavailableCostMessages)}</td>`,
|
|
10416
|
+
`<td>${measured(`${session2.tokensIn}/${session2.tokensOut}`, session2.unavailableUsageMessages)}</td>`,
|
|
9618
10417
|
`<td>${session2.toolcalls.count} (${avgMs(session2.toolcalls)})</td>`,
|
|
9619
10418
|
"</tr>"
|
|
9620
10419
|
].join("");
|
|
@@ -9751,8 +10550,8 @@ function sessionHeaderPanel(tab) {
|
|
|
9751
10550
|
`<div class="stat"><span class="k">Endpoint</span><span class="v">${endpoint}</span></div>`,
|
|
9752
10551
|
dir,
|
|
9753
10552
|
title,
|
|
9754
|
-
`<div class="stat"><span class="k">Real cost</span><span class="v">${usd(s.realCostUSD)}</span></div>`,
|
|
9755
|
-
`<div class="stat"><span class="k">Tokens in/out</span><span class="v">${s.tokensIn}/${s.tokensOut}</span></div>`,
|
|
10553
|
+
`<div class="stat"><span class="k">Real cost</span><span class="v">${measured(usd(s.realCostUSD), s.unavailableCostMessages)}</span></div>`,
|
|
10554
|
+
`<div class="stat"><span class="k">Tokens in/out</span><span class="v">${measured(`${s.tokensIn}/${s.tokensOut}`, s.unavailableUsageMessages)}</span></div>`,
|
|
9756
10555
|
`<div class="stat"><span class="k">Local/Frontier</span><span class="v"><span class="local">${s.localCount}</span>/<span class="frontier">${s.frontierCount}</span></span></div>`,
|
|
9757
10556
|
`<div class="stat"><span class="k">Toolcalls</span><span class="v">${s.toolcalls.count} (${avgMs(s.toolcalls)})</span></div>`,
|
|
9758
10557
|
"</div>",
|
|
@@ -10653,7 +11452,7 @@ function renderConsoleHtml(state, options = {}) {
|
|
|
10653
11452
|
'<meta name="viewport" content="width=device-width,initial-scale=1">',
|
|
10654
11453
|
"<title>openteam console</title>",
|
|
10655
11454
|
lifecycleEnabled ? `<script>${LIFECYCLE_THEME_BOOT}</script>` : "",
|
|
10656
|
-
`<style>${CONSOLE_STYLE}${CONVERSATION_STYLE}${graphOptionProvided ? GRAPH_STYLE : ""}${lifecycleEnabled ? LIFECYCLE_STYLE : ""}</style>`,
|
|
11455
|
+
`<style>${CONSOLE_STYLE}${CONVERSATION_STYLE}${graphOptionProvided ? GRAPH_STYLE : ""}${lifecycleEnabled ? LIFECYCLE_STYLE + AGENT_VIEW_STYLE : ""}</style>`,
|
|
10657
11456
|
"</head>",
|
|
10658
11457
|
"<body>",
|
|
10659
11458
|
'<div class="app">',
|
|
@@ -10683,6 +11482,7 @@ function renderConsoleUpdate(state, options = {}) {
|
|
|
10683
11482
|
routing: routingScreenBody(state),
|
|
10684
11483
|
logs: logsScreenBody(state, options.terminalEnabled === true, options.ptyEnabled === true),
|
|
10685
11484
|
sessionCount: state.sessionsDetail.length,
|
|
11485
|
+
sessionSummaries: state.sessions,
|
|
10686
11486
|
...options.graphView ? {
|
|
10687
11487
|
tree: treeGraphPanel(options.graphView.projection, options.drilldownEnabled === true, false, options.graphView.mode ?? "active")
|
|
10688
11488
|
} : {}
|
|
@@ -12618,6 +13418,7 @@ var lifecycleFailureSchema = z13.object({
|
|
|
12618
13418
|
"prompt-auth",
|
|
12619
13419
|
"prompt-content-filter",
|
|
12620
13420
|
"prompt-context-length",
|
|
13421
|
+
"prompt-output-truncated",
|
|
12621
13422
|
"prompt-validation",
|
|
12622
13423
|
"prompt-connection",
|
|
12623
13424
|
"prompt-server",
|
|
@@ -13662,6 +14463,8 @@ var NodeFailureClassSchema = z17.enum([
|
|
|
13662
14463
|
"prompt-auth",
|
|
13663
14464
|
"prompt-content-filter",
|
|
13664
14465
|
"prompt-context-length",
|
|
14466
|
+
"prompt-output-truncated",
|
|
14467
|
+
"budget-exhausted",
|
|
13665
14468
|
"prompt-validation",
|
|
13666
14469
|
"prompt-connection",
|
|
13667
14470
|
"prompt-server",
|
|
@@ -18170,7 +18973,15 @@ function buildOrchestratorAgent(model, options = {}) {
|
|
|
18170
18973
|
" `title` is optional and only for readability.",
|
|
18171
18974
|
"- `parentSessionID` (optional): the current session, so that the subsessions",
|
|
18172
18975
|
" link as children.",
|
|
18173
|
-
"- `directory` (optional):
|
|
18976
|
+
"- `directory` (optional): omit it to use the trusted host workspace. A different",
|
|
18977
|
+
" directory is rejected; this argument cannot authorize another workspace.",
|
|
18978
|
+
"",
|
|
18979
|
+
"Related and nested batches share a cumulative task budget, not a fresh allowance",
|
|
18980
|
+
"per call. On `task-budget-exhausted`, stop delegation and summarize preserved",
|
|
18981
|
+
"work and remaining tasks. Never create another batch/session or edit effort",
|
|
18982
|
+
"state to reset that allowance. Only a genuinely new root user turn starts a new task.",
|
|
18983
|
+
"Workers should use `openteam-submit-report` for their assigned report, retaining",
|
|
18984
|
+
"operator permission checks. Do not broaden file or shell permissions to deliver it.",
|
|
18174
18985
|
"",
|
|
18175
18986
|
"The tool returns a per-role summary: selected model, success or",
|
|
18176
18987
|
"failure, the created session, and — for each role — a `report` file path",
|
|
@@ -21747,7 +22558,7 @@ var nativeHostMessages = {
|
|
|
21747
22558
|
// package.json
|
|
21748
22559
|
var package_default = {
|
|
21749
22560
|
name: "@jmanuelcorral/openteam",
|
|
21750
|
-
version: "0.
|
|
22561
|
+
version: "0.28.0",
|
|
21751
22562
|
packageManager: "bun@1.3.14",
|
|
21752
22563
|
description: "Cost-aware, local-first routing plugin for opencode with cheapest-capable frontier fallback and multi-agent orchestration.",
|
|
21753
22564
|
license: "MIT",
|
|
@@ -27872,7 +28683,7 @@ function planStartupHygieneMigration(exists) {
|
|
|
27872
28683
|
|
|
27873
28684
|
// src/index.ts
|
|
27874
28685
|
import { readFile as readFile5 } from "node:fs/promises";
|
|
27875
|
-
import { basename as basename4, dirname as
|
|
28686
|
+
import { basename as basename4, dirname as dirname11, resolve as resolve18 } from "node:path";
|
|
27876
28687
|
|
|
27877
28688
|
// src/graph/certificate.ts
|
|
27878
28689
|
import { z as z29 } from "zod";
|
|
@@ -29042,17 +29853,31 @@ function createRuntimeConcurrencyLimiter(options) {
|
|
|
29042
29853
|
}
|
|
29043
29854
|
return {
|
|
29044
29855
|
tryAcquire,
|
|
29045
|
-
acquire(runtimeId, priority = "worker") {
|
|
29856
|
+
async acquire(runtimeId, priority = "worker", signal) {
|
|
29857
|
+
signal?.throwIfAborted();
|
|
29046
29858
|
const immediate = tryAcquire(runtimeId, priority);
|
|
29047
29859
|
if (immediate !== undefined) {
|
|
29048
29860
|
return Promise.resolve({ release: immediate, waitedMs: 0 });
|
|
29049
29861
|
}
|
|
29050
29862
|
const state = stateFor(runtimeId);
|
|
29051
29863
|
const queuedAt = options.now();
|
|
29052
|
-
return new Promise((resolve13) => {
|
|
29053
|
-
|
|
29864
|
+
return new Promise((resolve13, reject) => {
|
|
29865
|
+
const waiter = (release) => {
|
|
29866
|
+
signal?.removeEventListener("abort", cancel2);
|
|
29054
29867
|
resolve13({ release, waitedMs: options.now() - queuedAt });
|
|
29055
|
-
}
|
|
29868
|
+
};
|
|
29869
|
+
function cancel2() {
|
|
29870
|
+
const index = state.queues[priority].indexOf(waiter);
|
|
29871
|
+
if (index < 0)
|
|
29872
|
+
return;
|
|
29873
|
+
state.queues[priority].splice(index, 1);
|
|
29874
|
+
signal?.removeEventListener("abort", cancel2);
|
|
29875
|
+
reject(signal?.reason);
|
|
29876
|
+
}
|
|
29877
|
+
state.queues[priority].push(waiter);
|
|
29878
|
+
signal?.addEventListener("abort", cancel2, { once: true });
|
|
29879
|
+
if (signal?.aborted)
|
|
29880
|
+
cancel2();
|
|
29056
29881
|
});
|
|
29057
29882
|
},
|
|
29058
29883
|
activeCount(runtimeId) {
|
|
@@ -29093,6 +29918,192 @@ var readReportArtifact = async (reportPath) => {
|
|
|
29093
29918
|
}
|
|
29094
29919
|
};
|
|
29095
29920
|
|
|
29921
|
+
// src/orchestrator/reportDelivery.ts
|
|
29922
|
+
import { z as z30 } from "zod";
|
|
29923
|
+
var Submission = z30.object({
|
|
29924
|
+
status: z30.enum(["done", "continue"]),
|
|
29925
|
+
findings: z30.string().min(1).max(32768)
|
|
29926
|
+
}).strict();
|
|
29927
|
+
function createReportDelivery(deps) {
|
|
29928
|
+
const active = new Map;
|
|
29929
|
+
return {
|
|
29930
|
+
open(sessionID, batchID, roleID) {
|
|
29931
|
+
if (active.has(sessionID))
|
|
29932
|
+
throw new Error(reportDeliveryMessages.assignmentConflict);
|
|
29933
|
+
const lease = {
|
|
29934
|
+
path: roleReportPath(batchID, roleID),
|
|
29935
|
+
open: true,
|
|
29936
|
+
submitted: false,
|
|
29937
|
+
pending: Promise.resolve()
|
|
29938
|
+
};
|
|
29939
|
+
active.set(sessionID, lease);
|
|
29940
|
+
return {
|
|
29941
|
+
async close() {
|
|
29942
|
+
lease.open = false;
|
|
29943
|
+
await lease.pending;
|
|
29944
|
+
if (active.get(sessionID) === lease)
|
|
29945
|
+
active.delete(sessionID);
|
|
29946
|
+
return lease.submitted;
|
|
29947
|
+
}
|
|
29948
|
+
};
|
|
29949
|
+
},
|
|
29950
|
+
path(sessionID) {
|
|
29951
|
+
const lease = active.get(sessionID);
|
|
29952
|
+
if (lease?.open !== true)
|
|
29953
|
+
throw new Error(reportDeliveryMessages.noAssignment);
|
|
29954
|
+
return lease.path;
|
|
29955
|
+
},
|
|
29956
|
+
async submit(sessionID, input) {
|
|
29957
|
+
const payload = Submission.safeParse(input);
|
|
29958
|
+
if (!payload.success || !reportHasSubstance(payload.data.findings))
|
|
29959
|
+
throw new Error(reportDeliveryMessages.invalidReport);
|
|
29960
|
+
const lease = active.get(sessionID);
|
|
29961
|
+
if (lease?.open !== true)
|
|
29962
|
+
throw new Error(reportDeliveryMessages.noAssignment);
|
|
29963
|
+
const content = `${payload.data.findings.trim()}
|
|
29964
|
+
|
|
29965
|
+
openteam-status: ${payload.data.status}
|
|
29966
|
+
`;
|
|
29967
|
+
if (parseReportStatus(content) !== payload.data.status)
|
|
29968
|
+
throw new Error(reportDeliveryMessages.invalidReport);
|
|
29969
|
+
const write = lease.pending.then(async () => {
|
|
29970
|
+
if (!lease.open)
|
|
29971
|
+
throw new Error(reportDeliveryMessages.noAssignment);
|
|
29972
|
+
await deps.write(lease.path, content);
|
|
29973
|
+
lease.submitted = true;
|
|
29974
|
+
});
|
|
29975
|
+
lease.pending = write.then(() => {}, () => {});
|
|
29976
|
+
await write;
|
|
29977
|
+
return lease.path;
|
|
29978
|
+
}
|
|
29979
|
+
};
|
|
29980
|
+
}
|
|
29981
|
+
|
|
29982
|
+
// src/orchestrator/taskEffort.ts
|
|
29983
|
+
import { z as z31 } from "zod";
|
|
29984
|
+
var Binding = z31.object({
|
|
29985
|
+
taskID: z31.string().regex(/^[a-f0-9]{64}$/),
|
|
29986
|
+
depth: z31.number().int().min(0).max(128),
|
|
29987
|
+
worker: z31.boolean()
|
|
29988
|
+
}).strict();
|
|
29989
|
+
var Record = z31.object({
|
|
29990
|
+
v: z31.literal(1),
|
|
29991
|
+
startedAt: z31.number().finite(),
|
|
29992
|
+
batches: z31.number().int().min(0),
|
|
29993
|
+
attempts: z31.number().int().min(0),
|
|
29994
|
+
maxBatches: z31.number().int().positive(),
|
|
29995
|
+
maxAttempts: z31.number().int().positive(),
|
|
29996
|
+
maxDurationMs: z31.number().int().positive(),
|
|
29997
|
+
maxDepth: z31.number().int().min(0)
|
|
29998
|
+
}).strict();
|
|
29999
|
+
function decode(schema, raw) {
|
|
30000
|
+
let value;
|
|
30001
|
+
try {
|
|
30002
|
+
value = JSON.parse(raw ?? "null");
|
|
30003
|
+
} catch {
|
|
30004
|
+
throw new Error(taskEffortMessages.ledgerInvalid);
|
|
30005
|
+
}
|
|
30006
|
+
const parsed = schema.safeParse(value);
|
|
30007
|
+
if (!parsed.success)
|
|
30008
|
+
throw new Error(taskEffortMessages.ledgerInvalid);
|
|
30009
|
+
return parsed.data;
|
|
30010
|
+
}
|
|
30011
|
+
function createTaskEffort(deps) {
|
|
30012
|
+
const limits = {
|
|
30013
|
+
maxBatches: deps.limits?.maxBatches ?? 8,
|
|
30014
|
+
maxAttempts: deps.limits?.maxAttempts ?? 32,
|
|
30015
|
+
maxDurationMs: deps.limits?.maxDurationMs ?? 7200000,
|
|
30016
|
+
maxDepth: deps.limits?.maxDepth ?? 3
|
|
30017
|
+
};
|
|
30018
|
+
const bindingPath = (sessionID) => `sessions/${sha256Hex(sessionID)}.json`;
|
|
30019
|
+
const taskPath = (taskID) => `tasks/${taskID}.json`;
|
|
30020
|
+
function initialize(sessionID, messageID) {
|
|
30021
|
+
const taskID = sha256Hex(`${sessionID}\x00${messageID}`);
|
|
30022
|
+
deps.store.update(taskPath(taskID), (previous) => {
|
|
30023
|
+
if (previous !== undefined) {
|
|
30024
|
+
decode(Record, previous);
|
|
30025
|
+
return previous;
|
|
30026
|
+
}
|
|
30027
|
+
return JSON.stringify({
|
|
30028
|
+
v: 1,
|
|
30029
|
+
startedAt: deps.now(),
|
|
30030
|
+
batches: 0,
|
|
30031
|
+
attempts: 0,
|
|
30032
|
+
...limits
|
|
30033
|
+
});
|
|
30034
|
+
});
|
|
30035
|
+
const binding = { taskID, depth: 0, worker: false };
|
|
30036
|
+
deps.store.write(bindingPath(sessionID), JSON.stringify(binding));
|
|
30037
|
+
return binding;
|
|
30038
|
+
}
|
|
30039
|
+
function bindChild(parent, sessionID) {
|
|
30040
|
+
if (parent.depth >= 128)
|
|
30041
|
+
throw new Error(taskEffortMessages.ledgerInvalid);
|
|
30042
|
+
deps.store.write(bindingPath(sessionID), JSON.stringify({
|
|
30043
|
+
taskID: parent.taskID,
|
|
30044
|
+
depth: parent.depth + 1,
|
|
30045
|
+
worker: true
|
|
30046
|
+
}));
|
|
30047
|
+
}
|
|
30048
|
+
async function forSession(sessionID, ancestors = new Set) {
|
|
30049
|
+
if (ancestors.has(sessionID) || ancestors.size >= 128)
|
|
30050
|
+
throw new Error(taskEffortMessages.ledgerInvalid);
|
|
30051
|
+
const stored = deps.store.read(bindingPath(sessionID));
|
|
30052
|
+
if (stored !== undefined)
|
|
30053
|
+
return decode(Binding, stored);
|
|
30054
|
+
ancestors.add(sessionID);
|
|
30055
|
+
const parentID = await deps.parentSession?.(sessionID);
|
|
30056
|
+
if (parentID !== undefined) {
|
|
30057
|
+
const parent = await forSession(parentID, ancestors);
|
|
30058
|
+
bindChild(parent, sessionID);
|
|
30059
|
+
return { taskID: parent.taskID, depth: parent.depth + 1 };
|
|
30060
|
+
}
|
|
30061
|
+
return initialize(sessionID, "restored-session");
|
|
30062
|
+
}
|
|
30063
|
+
function consume(ref, kind) {
|
|
30064
|
+
let result = { ok: false, reason: "duration" };
|
|
30065
|
+
deps.store.update(taskPath(ref.taskID), (raw) => {
|
|
30066
|
+
const record3 = decode(Record, raw);
|
|
30067
|
+
const remainingMs = Math.min(record3.maxDurationMs, limits.maxDurationMs) - Math.max(0, deps.now() - record3.startedAt);
|
|
30068
|
+
const reason = ref.depth > Math.min(record3.maxDepth, limits.maxDepth) ? "depth" : remainingMs <= 0 ? "duration" : kind === "batches" && record3.batches >= Math.min(record3.maxBatches, limits.maxBatches) ? "batches" : kind === "attempts" && record3.attempts >= Math.min(record3.maxAttempts, limits.maxAttempts) ? "attempts" : undefined;
|
|
30069
|
+
if (reason !== undefined)
|
|
30070
|
+
result = { ok: false, reason };
|
|
30071
|
+
else {
|
|
30072
|
+
if (kind !== "check")
|
|
30073
|
+
record3[kind] += 1;
|
|
30074
|
+
result = {
|
|
30075
|
+
ok: true,
|
|
30076
|
+
remainingMs,
|
|
30077
|
+
batches: record3.batches,
|
|
30078
|
+
attempts: record3.attempts,
|
|
30079
|
+
remainingBatches: Math.max(0, Math.min(record3.maxBatches, limits.maxBatches) - record3.batches),
|
|
30080
|
+
remainingAttempts: Math.max(0, Math.min(record3.maxAttempts, limits.maxAttempts) - record3.attempts)
|
|
30081
|
+
};
|
|
30082
|
+
}
|
|
30083
|
+
return JSON.stringify(record3);
|
|
30084
|
+
});
|
|
30085
|
+
return result;
|
|
30086
|
+
}
|
|
30087
|
+
return {
|
|
30088
|
+
async userTurn(sessionID, messageID) {
|
|
30089
|
+
const stored = deps.store.read(bindingPath(sessionID));
|
|
30090
|
+
if (stored !== undefined && decode(Binding, stored).worker)
|
|
30091
|
+
return;
|
|
30092
|
+
const parentID = await deps.parentSession?.(sessionID);
|
|
30093
|
+
if (parentID !== undefined) {
|
|
30094
|
+
bindChild(await forSession(parentID), sessionID);
|
|
30095
|
+
return;
|
|
30096
|
+
}
|
|
30097
|
+
initialize(sessionID, messageID);
|
|
30098
|
+
},
|
|
30099
|
+
forSession,
|
|
30100
|
+
bindChild,
|
|
30101
|
+
batch: (ref) => consume(ref, "batches"),
|
|
30102
|
+
attempt: (ref) => consume(ref, "attempts"),
|
|
30103
|
+
check: (ref) => consume(ref, "check")
|
|
30104
|
+
};
|
|
30105
|
+
}
|
|
30106
|
+
|
|
29096
30107
|
// src/plugin/availability.ts
|
|
29097
30108
|
function modelKey4(model) {
|
|
29098
30109
|
return `${model.providerID}/${model.modelID}`;
|
|
@@ -29338,7 +30349,7 @@ function createAvailabilityCache(options) {
|
|
|
29338
30349
|
|
|
29339
30350
|
// src/plugin/capture.ts
|
|
29340
30351
|
function nonNeg(value) {
|
|
29341
|
-
return typeof value === "number" && value >= 0 ? Math.trunc(value) : 0;
|
|
30352
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.trunc(value) : 0;
|
|
29342
30353
|
}
|
|
29343
30354
|
function messageEventFrom(info, now) {
|
|
29344
30355
|
if (info.role !== "assistant") {
|
|
@@ -29352,6 +30363,17 @@ function messageEventFrom(info, now) {
|
|
|
29352
30363
|
}
|
|
29353
30364
|
const created = info.time.created ?? info.time.completed;
|
|
29354
30365
|
const durationMs = Math.max(0, Math.trunc(info.time.completed - created));
|
|
30366
|
+
const counters = [info.tokens?.input, info.tokens?.output];
|
|
30367
|
+
const hasUsage = counters.every((value) => typeof value === "number" && Number.isFinite(value) && value >= 0);
|
|
30368
|
+
const zeroUsage = [
|
|
30369
|
+
info.tokens?.input,
|
|
30370
|
+
info.tokens?.output,
|
|
30371
|
+
info.tokens?.reasoning,
|
|
30372
|
+
info.tokens?.cache?.read,
|
|
30373
|
+
info.tokens?.cache?.write
|
|
30374
|
+
].every((value) => value === undefined || value === 0);
|
|
30375
|
+
const usageStatus = !hasUsage ? "missing" : zeroUsage && info.hasGeneratedOutput !== false ? "zero-unverified" : "reported";
|
|
30376
|
+
const hasCost = typeof info.cost === "number" && Number.isFinite(info.cost) && info.cost >= 0;
|
|
29355
30377
|
const event = {
|
|
29356
30378
|
v: EVENT_SCHEMA_VERSION,
|
|
29357
30379
|
type: "message",
|
|
@@ -29359,7 +30381,11 @@ function messageEventFrom(info, now) {
|
|
|
29359
30381
|
sessionID: info.sessionID,
|
|
29360
30382
|
providerID: info.providerID,
|
|
29361
30383
|
modelID: info.modelID,
|
|
29362
|
-
costUSD:
|
|
30384
|
+
costUSD: hasCost ? info.cost ?? 0 : 0,
|
|
30385
|
+
usageStatus,
|
|
30386
|
+
costStatus: hasCost && (info.cost !== 0 || usageStatus === "reported") ? "reported" : "unavailable",
|
|
30387
|
+
...info.finish === undefined ? {} : { finish: finishReason(info.finish) },
|
|
30388
|
+
...info.truncatedToolCall === true ? { truncatedToolCall: true } : {},
|
|
29363
30389
|
tokensIn: nonNeg(info.tokens?.input),
|
|
29364
30390
|
tokensOut: nonNeg(info.tokens?.output),
|
|
29365
30391
|
tokensReasoning: nonNeg(info.tokens?.reasoning),
|
|
@@ -29370,6 +30396,18 @@ function messageEventFrom(info, now) {
|
|
|
29370
30396
|
if (info.mode !== undefined) {
|
|
29371
30397
|
event.mode = info.mode;
|
|
29372
30398
|
}
|
|
30399
|
+
function finishReason(value) {
|
|
30400
|
+
switch (value) {
|
|
30401
|
+
case "stop":
|
|
30402
|
+
case "length":
|
|
30403
|
+
case "tool-calls":
|
|
30404
|
+
case "content-filter":
|
|
30405
|
+
case "error":
|
|
30406
|
+
return value;
|
|
30407
|
+
default:
|
|
30408
|
+
return "unknown";
|
|
30409
|
+
}
|
|
30410
|
+
}
|
|
29373
30411
|
if (info.id !== undefined) {
|
|
29374
30412
|
event.messageID = info.id;
|
|
29375
30413
|
}
|
|
@@ -30099,36 +31137,36 @@ function formatResponse(response) {
|
|
|
30099
31137
|
}
|
|
30100
31138
|
|
|
30101
31139
|
// src/plugin/reportRunSchema.ts
|
|
30102
|
-
import { z as
|
|
31140
|
+
import { z as z33 } from "zod";
|
|
30103
31141
|
|
|
30104
31142
|
// src/plugin/graphShadowIngress.ts
|
|
30105
|
-
import { z as
|
|
31143
|
+
import { z as z32 } from "zod";
|
|
30106
31144
|
var LEGACY_EXECUTION_TRACE_VERSION = 1;
|
|
30107
|
-
var LegacyExecutionStatusSchema =
|
|
31145
|
+
var LegacyExecutionStatusSchema = z32.enum([
|
|
30108
31146
|
"completed",
|
|
30109
31147
|
"failed",
|
|
30110
31148
|
"cancelled"
|
|
30111
31149
|
]);
|
|
30112
|
-
var LegacyReviewOutcomeSchema =
|
|
31150
|
+
var LegacyReviewOutcomeSchema = z32.enum([
|
|
30113
31151
|
"approved",
|
|
30114
31152
|
"rejected",
|
|
30115
31153
|
"inconclusive"
|
|
30116
31154
|
]);
|
|
30117
|
-
var LegacyTraceNodeV1Schema =
|
|
31155
|
+
var LegacyTraceNodeV1Schema = z32.object({
|
|
30118
31156
|
id: NodeIDSchema,
|
|
30119
31157
|
role: NodeRoleSchema,
|
|
30120
|
-
model:
|
|
30121
|
-
sessionRef:
|
|
31158
|
+
model: z32.string().min(1),
|
|
31159
|
+
sessionRef: z32.string().min(1).optional(),
|
|
30122
31160
|
errorClass: ErrorClassSchema.optional()
|
|
30123
31161
|
}).strict();
|
|
30124
|
-
var LegacyExecutionTraceV1Schema =
|
|
30125
|
-
version:
|
|
31162
|
+
var LegacyExecutionTraceV1Schema = z32.object({
|
|
31163
|
+
version: z32.literal(LEGACY_EXECUTION_TRACE_VERSION),
|
|
30126
31164
|
runID: NodeIDSchema,
|
|
30127
31165
|
status: LegacyExecutionStatusSchema,
|
|
30128
31166
|
outcome: LegacyReviewOutcomeSchema,
|
|
30129
|
-
fixes:
|
|
30130
|
-
nodes:
|
|
30131
|
-
parentSessionRef:
|
|
31167
|
+
fixes: z32.number().int().nonnegative(),
|
|
31168
|
+
nodes: z32.array(LegacyTraceNodeV1Schema).min(1),
|
|
31169
|
+
parentSessionRef: z32.string().min(1).optional()
|
|
30132
31170
|
}).strict();
|
|
30133
31171
|
function gateReason2(gate) {
|
|
30134
31172
|
if (gate === undefined || gate.mode === "off") {
|
|
@@ -30199,20 +31237,20 @@ function parseLegacyExecutionTrace(input) {
|
|
|
30199
31237
|
}
|
|
30200
31238
|
|
|
30201
31239
|
// src/plugin/reportRunSchema.ts
|
|
30202
|
-
var ReportRunNodeSchema =
|
|
31240
|
+
var ReportRunNodeSchema = z33.object({
|
|
30203
31241
|
id: NodeIDSchema,
|
|
30204
31242
|
role: NodeRoleSchema,
|
|
30205
|
-
model:
|
|
30206
|
-
ok:
|
|
30207
|
-
sessionRef:
|
|
31243
|
+
model: z33.string().min(1),
|
|
31244
|
+
ok: z33.boolean(),
|
|
31245
|
+
sessionRef: z33.string().min(1).optional(),
|
|
30208
31246
|
errorClass: ErrorClassSchema.optional()
|
|
30209
31247
|
}).strict();
|
|
30210
|
-
var ReportRunPayloadSchema =
|
|
31248
|
+
var ReportRunPayloadSchema = z33.object({
|
|
30211
31249
|
runID: NodeIDSchema,
|
|
30212
31250
|
status: LegacyExecutionStatusSchema,
|
|
30213
|
-
fixes:
|
|
30214
|
-
nodes:
|
|
30215
|
-
parentSessionRef:
|
|
31251
|
+
fixes: z33.number().int().nonnegative(),
|
|
31252
|
+
nodes: z33.array(ReportRunNodeSchema).min(1),
|
|
31253
|
+
parentSessionRef: z33.string().min(1).optional()
|
|
30216
31254
|
}).strict();
|
|
30217
31255
|
|
|
30218
31256
|
// src/orchestrator/graphShadow.ts
|
|
@@ -30714,7 +31752,7 @@ async function handleReportRun(args, observe, tracker) {
|
|
|
30714
31752
|
}
|
|
30715
31753
|
|
|
30716
31754
|
// src/plugin/modelResidency.ts
|
|
30717
|
-
import { z as
|
|
31755
|
+
import { z as z34 } from "zod";
|
|
30718
31756
|
|
|
30719
31757
|
// src/local/lemonadeRequestGuard.ts
|
|
30720
31758
|
var inferencePaths = new Set([
|
|
@@ -31085,7 +32123,7 @@ function createModelResidencyGuard(config, options) {
|
|
|
31085
32123
|
throw failure2("identity", model.providerID);
|
|
31086
32124
|
fetch2 = installed.fetch;
|
|
31087
32125
|
}
|
|
31088
|
-
const configuredHeaders =
|
|
32126
|
+
const configuredHeaders = z34.record(z34.string(), z34.string()).safeParse(provider?.options?.headers ?? {});
|
|
31089
32127
|
if (!configuredHeaders.success)
|
|
31090
32128
|
throw failure2("configuration", model.providerID);
|
|
31091
32129
|
const headers = new Headers(configuredHeaders.data);
|
|
@@ -31313,62 +32351,62 @@ ${lines.join(`
|
|
|
31313
32351
|
}
|
|
31314
32352
|
|
|
31315
32353
|
// src/memory/types.ts
|
|
31316
|
-
import { z as
|
|
32354
|
+
import { z as z35 } from "zod";
|
|
31317
32355
|
var SHARED_OWNER_KEY = "*";
|
|
31318
|
-
var OwnerKeySchema =
|
|
31319
|
-
var MemoryKindSchema =
|
|
31320
|
-
var MemoryBaseSchema =
|
|
31321
|
-
id:
|
|
32356
|
+
var OwnerKeySchema = z35.string().min(1);
|
|
32357
|
+
var MemoryKindSchema = z35.enum(["fact", "preference", "entity"]);
|
|
32358
|
+
var MemoryBaseSchema = z35.object({
|
|
32359
|
+
id: z35.string().min(1),
|
|
31322
32360
|
ownerKey: OwnerKeySchema,
|
|
31323
|
-
confidence:
|
|
31324
|
-
validFrom:
|
|
31325
|
-
validUntil:
|
|
31326
|
-
createdAt:
|
|
31327
|
-
invalidatedAt:
|
|
31328
|
-
sourceHash:
|
|
31329
|
-
supersededBy:
|
|
32361
|
+
confidence: z35.number().min(0).max(1),
|
|
32362
|
+
validFrom: z35.number().finite(),
|
|
32363
|
+
validUntil: z35.number().finite().nullable().default(null),
|
|
32364
|
+
createdAt: z35.number().finite(),
|
|
32365
|
+
invalidatedAt: z35.number().finite().nullable().default(null),
|
|
32366
|
+
sourceHash: z35.string().min(1),
|
|
32367
|
+
supersededBy: z35.string().min(1).nullable().default(null)
|
|
31330
32368
|
}).strict();
|
|
31331
32369
|
var FactSchema = MemoryBaseSchema.extend({
|
|
31332
|
-
kind:
|
|
31333
|
-
subject:
|
|
31334
|
-
predicate:
|
|
31335
|
-
object:
|
|
31336
|
-
category:
|
|
32370
|
+
kind: z35.literal("fact"),
|
|
32371
|
+
subject: z35.string().min(1),
|
|
32372
|
+
predicate: z35.string().min(1),
|
|
32373
|
+
object: z35.string().min(1),
|
|
32374
|
+
category: z35.string().min(1).nullable().default(null)
|
|
31337
32375
|
});
|
|
31338
32376
|
var PreferenceSchema = MemoryBaseSchema.extend({
|
|
31339
|
-
kind:
|
|
31340
|
-
category:
|
|
31341
|
-
preference:
|
|
31342
|
-
context:
|
|
31343
|
-
lastAccessedAt:
|
|
31344
|
-
accessCount:
|
|
32377
|
+
kind: z35.literal("preference"),
|
|
32378
|
+
category: z35.string().min(1),
|
|
32379
|
+
preference: z35.string().min(1),
|
|
32380
|
+
context: z35.string().min(1).nullable().default(null),
|
|
32381
|
+
lastAccessedAt: z35.number().finite().nullable().default(null),
|
|
32382
|
+
accessCount: z35.number().int().min(0).default(0)
|
|
31345
32383
|
});
|
|
31346
32384
|
var EntitySchema = MemoryBaseSchema.extend({
|
|
31347
|
-
kind:
|
|
31348
|
-
canonicalName:
|
|
31349
|
-
type:
|
|
31350
|
-
aliases:
|
|
32385
|
+
kind: z35.literal("entity"),
|
|
32386
|
+
canonicalName: z35.string().min(1),
|
|
32387
|
+
type: z35.string().min(1),
|
|
32388
|
+
aliases: z35.array(z35.string().min(1)).default([])
|
|
31351
32389
|
});
|
|
31352
32390
|
var RelationSchema = MemoryBaseSchema.extend({
|
|
31353
|
-
kind:
|
|
31354
|
-
from:
|
|
31355
|
-
to:
|
|
31356
|
-
predicate:
|
|
31357
|
-
annotation:
|
|
32391
|
+
kind: z35.literal("relation"),
|
|
32392
|
+
from: z35.string().min(1),
|
|
32393
|
+
to: z35.string().min(1),
|
|
32394
|
+
predicate: z35.string().min(1),
|
|
32395
|
+
annotation: z35.string().min(1).nullable().default(null)
|
|
31358
32396
|
});
|
|
31359
|
-
var MemoryRecordSchema =
|
|
32397
|
+
var MemoryRecordSchema = z35.discriminatedUnion("kind", [
|
|
31360
32398
|
FactSchema,
|
|
31361
32399
|
PreferenceSchema,
|
|
31362
32400
|
EntitySchema,
|
|
31363
32401
|
RelationSchema
|
|
31364
32402
|
]);
|
|
31365
|
-
var RecallQuerySchema =
|
|
32403
|
+
var RecallQuerySchema = z35.object({
|
|
31366
32404
|
ownerKey: OwnerKeySchema,
|
|
31367
|
-
kinds:
|
|
31368
|
-
asOf:
|
|
31369
|
-
limit:
|
|
31370
|
-
minSimilarity:
|
|
31371
|
-
includeShared:
|
|
32405
|
+
kinds: z35.array(MemoryKindSchema).default(["fact", "preference", "entity"]),
|
|
32406
|
+
asOf: z35.number().finite().nullable().default(null),
|
|
32407
|
+
limit: z35.number().int().positive().default(8),
|
|
32408
|
+
minSimilarity: z35.number().min(0).max(1).default(0.2),
|
|
32409
|
+
includeShared: z35.boolean().default(true)
|
|
31372
32410
|
}).strict();
|
|
31373
32411
|
|
|
31374
32412
|
// src/memory/rank.ts
|
|
@@ -31939,42 +32977,42 @@ function buildMemoryInjector(deps, policy) {
|
|
|
31939
32977
|
|
|
31940
32978
|
// src/plugin/memoryTool.ts
|
|
31941
32979
|
import { tool as tool5 } from "@opencode-ai/plugin";
|
|
31942
|
-
import { z as
|
|
32980
|
+
import { z as z37 } from "zod";
|
|
31943
32981
|
|
|
31944
32982
|
// src/memory/extract.ts
|
|
31945
|
-
import { z as
|
|
32983
|
+
import { z as z36 } from "zod";
|
|
31946
32984
|
var REDACTED = "[redacted]";
|
|
31947
|
-
var RawFactSchema =
|
|
31948
|
-
subject:
|
|
31949
|
-
predicate:
|
|
31950
|
-
object:
|
|
31951
|
-
category:
|
|
31952
|
-
confidence:
|
|
32985
|
+
var RawFactSchema = z36.object({
|
|
32986
|
+
subject: z36.string().min(1),
|
|
32987
|
+
predicate: z36.string().min(1),
|
|
32988
|
+
object: z36.string().min(1),
|
|
32989
|
+
category: z36.string().min(1).nullable().optional(),
|
|
32990
|
+
confidence: z36.number().min(0).max(1).optional()
|
|
31953
32991
|
});
|
|
31954
|
-
var RawPreferenceSchema =
|
|
31955
|
-
category:
|
|
31956
|
-
preference:
|
|
31957
|
-
context:
|
|
31958
|
-
confidence:
|
|
32992
|
+
var RawPreferenceSchema = z36.object({
|
|
32993
|
+
category: z36.string().min(1),
|
|
32994
|
+
preference: z36.string().min(1),
|
|
32995
|
+
context: z36.string().min(1).nullable().optional(),
|
|
32996
|
+
confidence: z36.number().min(0).max(1).optional()
|
|
31959
32997
|
});
|
|
31960
|
-
var RawEntitySchema =
|
|
31961
|
-
canonicalName:
|
|
31962
|
-
type:
|
|
31963
|
-
aliases:
|
|
31964
|
-
confidence:
|
|
32998
|
+
var RawEntitySchema = z36.object({
|
|
32999
|
+
canonicalName: z36.string().min(1),
|
|
33000
|
+
type: z36.string().min(1),
|
|
33001
|
+
aliases: z36.array(z36.string().min(1)).optional(),
|
|
33002
|
+
confidence: z36.number().min(0).max(1).optional()
|
|
31965
33003
|
});
|
|
31966
|
-
var RawRelationSchema =
|
|
31967
|
-
from:
|
|
31968
|
-
to:
|
|
31969
|
-
predicate:
|
|
31970
|
-
annotation:
|
|
31971
|
-
confidence:
|
|
33004
|
+
var RawRelationSchema = z36.object({
|
|
33005
|
+
from: z36.string().min(1),
|
|
33006
|
+
to: z36.string().min(1),
|
|
33007
|
+
predicate: z36.string().min(1),
|
|
33008
|
+
annotation: z36.string().min(1).nullable().optional(),
|
|
33009
|
+
confidence: z36.number().min(0).max(1).optional()
|
|
31972
33010
|
}).strict();
|
|
31973
|
-
var RawExtractionSchema =
|
|
31974
|
-
facts:
|
|
31975
|
-
preferences:
|
|
31976
|
-
entities:
|
|
31977
|
-
relations:
|
|
33011
|
+
var RawExtractionSchema = z36.object({
|
|
33012
|
+
facts: z36.array(RawFactSchema).default([]),
|
|
33013
|
+
preferences: z36.array(RawPreferenceSchema).default([]),
|
|
33014
|
+
entities: z36.array(RawEntitySchema).default([]),
|
|
33015
|
+
relations: z36.array(RawRelationSchema).default([])
|
|
31978
33016
|
});
|
|
31979
33017
|
var DEFAULT_CONFIDENCE = 0.6;
|
|
31980
33018
|
var SYSTEM_PROMPT = [
|
|
@@ -32228,13 +33266,13 @@ var memoryToolMessages = {
|
|
|
32228
33266
|
|
|
32229
33267
|
// src/plugin/memoryTool.ts
|
|
32230
33268
|
var SCRIBE_ROLE_ID = "scribe";
|
|
32231
|
-
var MemoryMessageSchema =
|
|
32232
|
-
role:
|
|
32233
|
-
content:
|
|
33269
|
+
var MemoryMessageSchema = z37.object({
|
|
33270
|
+
role: z37.enum(["system", "user", "assistant"]).describe(memoryToolMessages.messageRoleDescription),
|
|
33271
|
+
content: z37.string().min(1).describe(memoryToolMessages.messageContentDescription)
|
|
32234
33272
|
}).strict();
|
|
32235
|
-
var MemoryWritePayloadSchema =
|
|
32236
|
-
messages:
|
|
32237
|
-
roleID:
|
|
33273
|
+
var MemoryWritePayloadSchema = z37.object({
|
|
33274
|
+
messages: z37.array(MemoryMessageSchema).min(1).describe(memoryToolMessages.messagesDescription),
|
|
33275
|
+
roleID: z37.string().min(1).default(SCRIBE_ROLE_ID).describe(memoryToolMessages.roleIDDescription)
|
|
32238
33276
|
}).strict();
|
|
32239
33277
|
function createMemoryTool(deps) {
|
|
32240
33278
|
return tool5({
|
|
@@ -32418,7 +33456,7 @@ import { Session as Session2 } from "@opencode/schema/session";
|
|
|
32418
33456
|
import { Tool as Tool2 } from "@opencode/schema/tool";
|
|
32419
33457
|
import { tool as legacyTool } from "@opencode-ai/plugin/tool";
|
|
32420
33458
|
import { Clock, Effect, Option, Stream } from "effect";
|
|
32421
|
-
import { z as
|
|
33459
|
+
import { z as z39 } from "zod";
|
|
32422
33460
|
|
|
32423
33461
|
// src/plugin/nativeHostContext.ts
|
|
32424
33462
|
import {
|
|
@@ -32480,7 +33518,7 @@ function nativeConfiguredInventory(models, config) {
|
|
|
32480
33518
|
|
|
32481
33519
|
// src/plugin/nativeResidency.ts
|
|
32482
33520
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
32483
|
-
import { z as
|
|
33521
|
+
import { z as z38 } from "zod";
|
|
32484
33522
|
var NATIVE_RESIDENCY_PROVIDER_PACKAGE = "aisdk:@ai-sdk/openai-compatible@2.0.75";
|
|
32485
33523
|
var NATIVE_ADMISSION_HEADER = "x-openteam-local-admission";
|
|
32486
33524
|
var MAX_ADMISSIONS = 2048;
|
|
@@ -32558,7 +33596,7 @@ function createNativeModelResidencyGuard(config, options) {
|
|
|
32558
33596
|
});
|
|
32559
33597
|
}
|
|
32560
33598
|
function target(model, send, baseURL) {
|
|
32561
|
-
const headers = new Headers(
|
|
33599
|
+
const headers = new Headers(z38.record(z38.string(), z38.string()).parse(model.headers ?? {}));
|
|
32562
33600
|
if (typeof model.settings?.apiKey === "string" && !headers.has("authorization"))
|
|
32563
33601
|
headers.set("authorization", `Bearer ${model.settings.apiKey}`);
|
|
32564
33602
|
return {
|
|
@@ -32596,7 +33634,7 @@ function createNativeModelResidencyGuard(config, options) {
|
|
|
32596
33634
|
localTargets.set(key(ref), target(model, guardedFetch(binding, options.fetch), binding.baseURL));
|
|
32597
33635
|
return model;
|
|
32598
33636
|
} catch (error) {
|
|
32599
|
-
if (!(error instanceof ModelResidencyError) && !(error instanceof
|
|
33637
|
+
if (!(error instanceof ModelResidencyError) && !(error instanceof z38.ZodError))
|
|
32600
33638
|
throw error;
|
|
32601
33639
|
(options.warn ?? console.warn)(modelResidencyMessages.providerDisabled(model.providerID, residentRuntimes.find((runtime) => runtime.defaultModel.providerID === model.providerID)?.kind === "llama-swap" ? "llama-swap" : "Lemonade"));
|
|
32602
33640
|
return { ...model, enabled: false };
|
|
@@ -32753,6 +33791,10 @@ function nativeAssistantResponse(sessionID, message2) {
|
|
|
32753
33791
|
...message2.cost === undefined ? {} : { cost: message2.cost },
|
|
32754
33792
|
...message2.tokens === undefined ? {} : { tokens: message2.tokens },
|
|
32755
33793
|
...message2.error === undefined ? {} : { error: message2.error },
|
|
33794
|
+
...message2.finish === undefined ? {} : { finish: message2.finish },
|
|
33795
|
+
...message2.rawFinish === undefined ? {} : { rawFinish: message2.rawFinish },
|
|
33796
|
+
hasGeneratedOutput: message2.content.some((part) => part.type === "tool" || part.text.length > 0),
|
|
33797
|
+
truncatedToolCall: message2.finish === "length" && message2.content.some((part) => part.type === "tool" && part.executed === false && part.state.status === "error" && part.state.error.type === "tool.input-json"),
|
|
32756
33798
|
time: {
|
|
32757
33799
|
created: DateTime.toEpochMillis(message2.time.created),
|
|
32758
33800
|
...message2.time.completed === undefined ? {} : { completed: DateTime.toEpochMillis(message2.time.completed) }
|
|
@@ -32779,7 +33821,8 @@ function createNativeSessionClient(deps) {
|
|
|
32779
33821
|
}
|
|
32780
33822
|
return {
|
|
32781
33823
|
async create(args) {
|
|
32782
|
-
const
|
|
33824
|
+
const parentSignal = deps.signal?.();
|
|
33825
|
+
const signal = parentSignal === undefined ? args.signal : args.signal === undefined ? parentSignal : AbortSignal.any([parentSignal, args.signal]);
|
|
32783
33826
|
signal?.throwIfAborted();
|
|
32784
33827
|
assertDirectory(args.query?.directory);
|
|
32785
33828
|
if (args.body?.parentID === undefined)
|
|
@@ -32789,7 +33832,7 @@ function createNativeSessionClient(deps) {
|
|
|
32789
33832
|
const child = await deps.run(deps.sessions().create({
|
|
32790
33833
|
parentID,
|
|
32791
33834
|
...args.body.title === undefined ? {} : { title: args.body.title }
|
|
32792
|
-
}));
|
|
33835
|
+
}), signal === undefined ? undefined : { signal });
|
|
32793
33836
|
if (!sameNativeWorkspace(child.location, location))
|
|
32794
33837
|
throw new Error(nativeHostMessages.workspaceMismatch);
|
|
32795
33838
|
if (child.parentID !== parentID)
|
|
@@ -32828,6 +33871,11 @@ function createNativeSessionClient(deps) {
|
|
|
32828
33871
|
const assistant = [...messages].reverse().find((message2) => message2.type === "assistant");
|
|
32829
33872
|
if (final.outcome === "interrupted")
|
|
32830
33873
|
throw new Error(nativeHostMessages.executionInterrupted);
|
|
33874
|
+
if (assistant?.time.completed !== undefined) {
|
|
33875
|
+
const response = nativeAssistantResponse(sessionID, assistant);
|
|
33876
|
+
if (response.info.truncatedToolCall)
|
|
33877
|
+
return { data: response, error: undefined };
|
|
33878
|
+
}
|
|
32831
33879
|
if (final.outcome !== "succeeded" || assistant?.error !== undefined)
|
|
32832
33880
|
throw new Error(nativeHostMessages.executionFailed);
|
|
32833
33881
|
if (assistant?.time.completed === undefined)
|
|
@@ -32867,8 +33915,8 @@ function createNativeSessionClient(deps) {
|
|
|
32867
33915
|
}
|
|
32868
33916
|
|
|
32869
33917
|
// src/plugin/nativeHost.ts
|
|
32870
|
-
var executionEvent =
|
|
32871
|
-
type:
|
|
33918
|
+
var executionEvent = z39.preprocess(only(["type", "location", "data"]), z39.object({
|
|
33919
|
+
type: z39.enum([
|
|
32872
33920
|
"session.created",
|
|
32873
33921
|
"session.deleted",
|
|
32874
33922
|
"session.execution.started",
|
|
@@ -32876,15 +33924,30 @@ var executionEvent = z37.preprocess(only(["type", "location", "data"]), z37.obje
|
|
|
32876
33924
|
"session.execution.failed",
|
|
32877
33925
|
"session.execution.interrupted",
|
|
32878
33926
|
"session.step.ended",
|
|
32879
|
-
"session.step.
|
|
33927
|
+
"session.step.started",
|
|
33928
|
+
"session.step.failed",
|
|
33929
|
+
"session.tool.input.started",
|
|
33930
|
+
"session.tool.success",
|
|
33931
|
+
"session.tool.failed"
|
|
32880
33932
|
]),
|
|
32881
|
-
location:
|
|
32882
|
-
directory:
|
|
32883
|
-
workspaceID:
|
|
33933
|
+
location: z39.preprocess(only(["directory", "workspaceID"]), z39.object({
|
|
33934
|
+
directory: z39.string(),
|
|
33935
|
+
workspaceID: z39.string().optional()
|
|
32884
33936
|
}).strict()).optional(),
|
|
32885
|
-
data:
|
|
32886
|
-
sessionID
|
|
32887
|
-
assistantMessageID
|
|
33937
|
+
data: z39.preprocess(only([
|
|
33938
|
+
"sessionID",
|
|
33939
|
+
"assistantMessageID",
|
|
33940
|
+
"id",
|
|
33941
|
+
"name",
|
|
33942
|
+
"executed",
|
|
33943
|
+
"error"
|
|
33944
|
+
]), z39.object({
|
|
33945
|
+
sessionID: z39.string(),
|
|
33946
|
+
assistantMessageID: z39.string().optional(),
|
|
33947
|
+
id: z39.string().optional(),
|
|
33948
|
+
name: z39.string().optional(),
|
|
33949
|
+
executed: z39.boolean().optional(),
|
|
33950
|
+
error: z39.preprocess(only(["type"]), z39.object({ type: z39.string() }).strict()).optional()
|
|
32888
33951
|
}).strict())
|
|
32889
33952
|
}).strict());
|
|
32890
33953
|
var nativeBindings = Effect.fn("openteam.nativeBindings")(function* () {
|
|
@@ -32939,6 +34002,15 @@ function createNativePluginEffect(factory) {
|
|
|
32939
34002
|
let config;
|
|
32940
34003
|
let residency;
|
|
32941
34004
|
const systemPrompts = new Map;
|
|
34005
|
+
const toolNames = new Map;
|
|
34006
|
+
const rememberTool = (sessionID, callID, name) => {
|
|
34007
|
+
toolNames.set(`${sessionID}\x00${callID}`, name);
|
|
34008
|
+
if (toolNames.size > 8192) {
|
|
34009
|
+
const oldest = toolNames.keys().next().value;
|
|
34010
|
+
if (oldest !== undefined)
|
|
34011
|
+
toolNames.delete(oldest);
|
|
34012
|
+
}
|
|
34013
|
+
};
|
|
32942
34014
|
const toolSignals = new AsyncLocalStorage;
|
|
32943
34015
|
const remember = (next) => {
|
|
32944
34016
|
bindings = { ...bindings, ...next };
|
|
@@ -32993,6 +34065,12 @@ function createNativePluginEffect(factory) {
|
|
|
32993
34065
|
directory,
|
|
32994
34066
|
worktree: ctx.location.project.directory,
|
|
32995
34067
|
client,
|
|
34068
|
+
toolOutcomesFromEvents: true,
|
|
34069
|
+
parentSession: async (sessionID) => {
|
|
34070
|
+
const info = await run(requiredBindings().sessions.get(Session2.ID.make(sessionID)));
|
|
34071
|
+
assertWorkspace(info.location);
|
|
34072
|
+
return info.parentID;
|
|
34073
|
+
},
|
|
32996
34074
|
exec: nativeExec(directory),
|
|
32997
34075
|
serverUrl: () => {
|
|
32998
34076
|
const url = bindings?.server?.urls().find((value) => {
|
|
@@ -33037,6 +34115,7 @@ function createNativePluginEffect(factory) {
|
|
|
33037
34115
|
yield* Effect.addFinalizer(() => Effect.promise(async () => {
|
|
33038
34116
|
guard.dispose();
|
|
33039
34117
|
systemPrompts.clear();
|
|
34118
|
+
toolNames.clear();
|
|
33040
34119
|
await hooks.dispose?.();
|
|
33041
34120
|
}));
|
|
33042
34121
|
yield* ctx.provider.transform(guard.providers);
|
|
@@ -33169,7 +34248,10 @@ function createNativePluginEffect(factory) {
|
|
|
33169
34248
|
});
|
|
33170
34249
|
}
|
|
33171
34250
|
});
|
|
33172
|
-
yield* ctx.tool.hook("execute.before", (event) => Effect.promise(() =>
|
|
34251
|
+
yield* ctx.tool.hook("execute.before", (event) => Effect.promise(() => {
|
|
34252
|
+
rememberTool(event.sessionID, event.id, event.tool);
|
|
34253
|
+
return hooks["tool.execute.before"]?.({ tool: event.tool, sessionID: event.sessionID, callID: event.id }, { args: event.input }) ?? Promise.resolve();
|
|
34254
|
+
}));
|
|
33173
34255
|
yield* ctx.tool.hook("execute.after", (event) => Effect.promise(() => hooks["tool.execute.after"]?.({
|
|
33174
34256
|
tool: event.tool,
|
|
33175
34257
|
sessionID: event.sessionID,
|
|
@@ -33196,9 +34278,62 @@ function createNativePluginEffect(factory) {
|
|
|
33196
34278
|
if (value.type === "session.deleted") {
|
|
33197
34279
|
guard.finished(sessionID);
|
|
33198
34280
|
systemPrompts.delete(sessionID);
|
|
34281
|
+
for (const key2 of toolNames.keys()) {
|
|
34282
|
+
if (key2.startsWith(`${sessionID}\x00`))
|
|
34283
|
+
toolNames.delete(key2);
|
|
34284
|
+
}
|
|
33199
34285
|
}
|
|
33200
34286
|
let mapped;
|
|
33201
|
-
if (value.type === "session.
|
|
34287
|
+
if (value.type === "session.tool.input.started") {
|
|
34288
|
+
if (value.data.id !== undefined && value.data.name !== undefined)
|
|
34289
|
+
rememberTool(sessionID, value.data.id, value.data.name);
|
|
34290
|
+
await hooks.event?.({
|
|
34291
|
+
event: {
|
|
34292
|
+
type: "openteam.session.phase",
|
|
34293
|
+
properties: { sessionID, phase: "tool-input" }
|
|
34294
|
+
}
|
|
34295
|
+
});
|
|
34296
|
+
return;
|
|
34297
|
+
} else if (value.type === "session.step.started") {
|
|
34298
|
+
mapped = {
|
|
34299
|
+
type: "openteam.session.phase",
|
|
34300
|
+
properties: { sessionID, phase: "model-request" }
|
|
34301
|
+
};
|
|
34302
|
+
} else if (value.type === "session.tool.success" || value.type === "session.tool.failed") {
|
|
34303
|
+
if (value.data.id === undefined)
|
|
34304
|
+
return;
|
|
34305
|
+
const key2 = `${sessionID}\x00${value.data.id}`;
|
|
34306
|
+
let name = toolNames.get(key2);
|
|
34307
|
+
if (name === undefined && bindings !== undefined) {
|
|
34308
|
+
const messages = await run(bindings.sessions.messages({
|
|
34309
|
+
sessionID: Session2.ID.make(sessionID),
|
|
34310
|
+
limit: 100
|
|
34311
|
+
}));
|
|
34312
|
+
const message2 = messages.find((candidate) => candidate.id === value.data.assistantMessageID);
|
|
34313
|
+
if (message2?.type === "assistant") {
|
|
34314
|
+
const part = message2.content.find((candidate) => candidate.type === "tool" && candidate.id === value.data.id);
|
|
34315
|
+
if (part?.type === "tool")
|
|
34316
|
+
name = part.name;
|
|
34317
|
+
}
|
|
34318
|
+
}
|
|
34319
|
+
const ok2 = value.type === "session.tool.success";
|
|
34320
|
+
const inputFailure = value.data.error?.type === "tool.input-json" || value.data.error?.type === "tool.input-schema";
|
|
34321
|
+
const executionReached = ok2 || value.data.error?.type === "tool.execution";
|
|
34322
|
+
mapped = {
|
|
34323
|
+
type: "openteam.tool.completed",
|
|
34324
|
+
properties: {
|
|
34325
|
+
sessionID,
|
|
34326
|
+
callID: value.data.id,
|
|
34327
|
+
tool: name ?? "unknown",
|
|
34328
|
+
ok: ok2,
|
|
34329
|
+
...inputFailure ? { executed: false } : executionReached ? { executed: true } : {},
|
|
34330
|
+
...value.data.executed === undefined ? {} : { providerExecuted: value.data.executed },
|
|
34331
|
+
...!ok2 ? {
|
|
34332
|
+
failureKind: inputFailure ? "input-invalid" : executionReached ? "execution" : "unknown"
|
|
34333
|
+
} : {}
|
|
34334
|
+
}
|
|
34335
|
+
};
|
|
34336
|
+
} else if (value.type === "session.created" || value.type === "session.deleted") {
|
|
33202
34337
|
mapped = {
|
|
33203
34338
|
type: value.type,
|
|
33204
34339
|
properties: { info: { id: sessionID } }
|
|
@@ -33239,12 +34374,13 @@ function createNativePluginEffect(factory) {
|
|
|
33239
34374
|
}
|
|
33240
34375
|
|
|
33241
34376
|
// src/plugin/orchestrateTool.ts
|
|
34377
|
+
import { resolve as resolve16 } from "node:path";
|
|
33242
34378
|
import { tool as tool6 } from "@opencode-ai/plugin";
|
|
33243
|
-
import { z as
|
|
34379
|
+
import { z as z40 } from "zod";
|
|
33244
34380
|
var _pluginWarnedRoles = new Set;
|
|
33245
34381
|
var EMPTY_ROLE_ID_SET = new Set;
|
|
33246
34382
|
var SAFE_ROLE_ID = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;
|
|
33247
|
-
var RoleIDSchema =
|
|
34383
|
+
var RoleIDSchema = z40.string().min(1).superRefine((roleID, ctx) => {
|
|
33248
34384
|
if (!SAFE_ROLE_ID.test(roleID)) {
|
|
33249
34385
|
ctx.addIssue({
|
|
33250
34386
|
code: "custom",
|
|
@@ -33252,16 +34388,16 @@ var RoleIDSchema = z38.string().min(1).superRefine((roleID, ctx) => {
|
|
|
33252
34388
|
});
|
|
33253
34389
|
}
|
|
33254
34390
|
});
|
|
33255
|
-
var RoleAssignmentSchema =
|
|
34391
|
+
var RoleAssignmentSchema = z40.object({
|
|
33256
34392
|
roleID: RoleIDSchema.describe("Role identifier from the roster"),
|
|
33257
|
-
prompt:
|
|
33258
|
-
title:
|
|
33259
|
-
dependsOn:
|
|
34393
|
+
prompt: z40.string().min(1).describe("Work prompt for this role"),
|
|
34394
|
+
title: z40.string().min(1).optional().describe("Human-readable title"),
|
|
34395
|
+
dependsOn: z40.array(RoleIDSchema).optional().describe("Role IDs this assignment depends on (DAG edges)")
|
|
33260
34396
|
}).strict();
|
|
33261
|
-
var OrchestratePayloadSchema =
|
|
33262
|
-
assignments:
|
|
33263
|
-
parentSessionID:
|
|
33264
|
-
directory:
|
|
34397
|
+
var OrchestratePayloadSchema = z40.object({
|
|
34398
|
+
assignments: z40.array(RoleAssignmentSchema).min(1).describe("Role assignments to distribute"),
|
|
34399
|
+
parentSessionID: z40.string().min(1).optional().describe(PARENT_SESSION_DESCRIPTION),
|
|
34400
|
+
directory: z40.string().min(1).optional().describe("Working directory override")
|
|
33265
34401
|
}).strict();
|
|
33266
34402
|
function validateAssignmentDependencies(assignments) {
|
|
33267
34403
|
const ids = new Set;
|
|
@@ -33446,8 +34582,15 @@ function adaptSdkClient(sdk, orchestratedModelOwnership) {
|
|
|
33446
34582
|
if (result.error !== undefined) {
|
|
33447
34583
|
out.error = normalizeSdkSessionFailure(result.error, "prompt");
|
|
33448
34584
|
} else {
|
|
34585
|
+
const info = isRecord8(result.data) ? nestedRecord2(result.data, "info") : undefined;
|
|
33449
34586
|
const nestedFailure = nestedAssistantFailure(result.data);
|
|
33450
|
-
if (
|
|
34587
|
+
if (info?.finish === "length" && info.truncatedToolCall === true) {
|
|
34588
|
+
out.error = {
|
|
34589
|
+
kind: "normalized-session-failure",
|
|
34590
|
+
failureClass: "prompt-output-truncated",
|
|
34591
|
+
retryable: true
|
|
34592
|
+
};
|
|
34593
|
+
} else if (nestedFailure !== undefined) {
|
|
33451
34594
|
out.error = normalizeSdkSessionFailure(nestedFailure, "prompt");
|
|
33452
34595
|
} else if (result.data !== undefined) {
|
|
33453
34596
|
out.data = result.data;
|
|
@@ -33607,7 +34750,10 @@ function mapTelemetryFailureClassToErrorClass(cls) {
|
|
|
33607
34750
|
case "prompt-rate-limited":
|
|
33608
34751
|
case "prompt-connection":
|
|
33609
34752
|
case "prompt-server":
|
|
34753
|
+
case "prompt-output-truncated":
|
|
33610
34754
|
return "transient";
|
|
34755
|
+
case "budget-exhausted":
|
|
34756
|
+
return "permanent";
|
|
33611
34757
|
case "create-rejected":
|
|
33612
34758
|
case "create-no-id":
|
|
33613
34759
|
case "prompt-rejected":
|
|
@@ -33890,8 +35036,16 @@ function createOrchestrateTool(deps) {
|
|
|
33890
35036
|
}
|
|
33891
35037
|
const parentOverrideIgnored = parsed.data.parentSessionID !== undefined && parsed.data.parentSessionID !== context.sessionID;
|
|
33892
35038
|
parsed.data.parentSessionID = context.sessionID;
|
|
33893
|
-
if (
|
|
33894
|
-
|
|
35039
|
+
if (deps.workspaceDirectory !== undefined) {
|
|
35040
|
+
const workspace = resolve16(deps.workspaceDirectory);
|
|
35041
|
+
if (resolve16(workspace, parsed.data.directory ?? ".") !== workspace)
|
|
35042
|
+
return reportDeliveryMessages.workspaceMismatch;
|
|
35043
|
+
parsed.data.directory = workspace;
|
|
35044
|
+
} else if (parsed.data.directory === undefined) {
|
|
35045
|
+
const directory = context.directory;
|
|
35046
|
+
if (directory !== undefined)
|
|
35047
|
+
parsed.data.directory = directory;
|
|
35048
|
+
}
|
|
33895
35049
|
const depError = validateAssignmentDependencies(parsed.data.assignments);
|
|
33896
35050
|
if (depError !== undefined) {
|
|
33897
35051
|
return dependencyValidationError(depError.code, depError.detail);
|
|
@@ -33914,6 +35068,14 @@ function createOrchestrateTool(deps) {
|
|
|
33914
35068
|
return missingAgentDefinition(agentName, input.roleID);
|
|
33915
35069
|
}
|
|
33916
35070
|
}
|
|
35071
|
+
const taskRef = await deps.taskEffort?.forSession(context.sessionID);
|
|
35072
|
+
if (taskRef !== undefined && deps.taskEffort !== undefined) {
|
|
35073
|
+
const effort2 = deps.taskEffort.batch(taskRef);
|
|
35074
|
+
if (!effort2.ok)
|
|
35075
|
+
return taskEffortMessages.exhausted(effort2.reason);
|
|
35076
|
+
for (const input of inputs)
|
|
35077
|
+
input.taskID = taskRef.taskID;
|
|
35078
|
+
}
|
|
33917
35079
|
const batchID = deps.newDecisionID();
|
|
33918
35080
|
if (deps.lifecycleRecorder !== undefined) {
|
|
33919
35081
|
const rootOperationID = operationID(batchID, "openteam");
|
|
@@ -33923,7 +35085,7 @@ function createOrchestrateTool(deps) {
|
|
|
33923
35085
|
executionAuthority: "coordinator",
|
|
33924
35086
|
root: {
|
|
33925
35087
|
operationID: rootOperationID,
|
|
33926
|
-
taskID: batchID,
|
|
35088
|
+
taskID: taskRef?.taskID ?? batchID,
|
|
33927
35089
|
kind: "coordinator",
|
|
33928
35090
|
roleID: "openteam",
|
|
33929
35091
|
agentID: context.agent,
|
|
@@ -33948,6 +35110,12 @@ function createOrchestrateTool(deps) {
|
|
|
33948
35110
|
reportedModelSlots: deps.reportedModelSlots,
|
|
33949
35111
|
readReportArtifact: deps.readReportArtifact,
|
|
33950
35112
|
reportArtifactExists: deps.reportArtifactExists,
|
|
35113
|
+
...deps.reportDelivery === undefined ? {} : { reportDelivery: deps.reportDelivery },
|
|
35114
|
+
...deps.sessionPhase === undefined ? {} : { sessionPhase: deps.sessionPhase },
|
|
35115
|
+
signal: context.abort,
|
|
35116
|
+
...deps.taskEffort === undefined || taskRef === undefined ? {} : {
|
|
35117
|
+
taskEffort: { ledger: deps.taskEffort, ref: taskRef }
|
|
35118
|
+
},
|
|
33951
35119
|
abortGraceMs: deps.abortGraceMs,
|
|
33952
35120
|
statusPollMs: deps.statusPollMs,
|
|
33953
35121
|
delay: deps.delay,
|
|
@@ -33965,10 +35133,15 @@ function createOrchestrateTool(deps) {
|
|
|
33965
35133
|
lifecycleStatus = activeLifecycleRecorder?.status() ?? lifecycleStatus;
|
|
33966
35134
|
const projected = projectResults(batch.results, batch.cancelled);
|
|
33967
35135
|
const shadowResult = await runShadowProducer(deps, parsed.data, batch);
|
|
35136
|
+
const effort = taskRef === undefined ? undefined : deps.taskEffort?.check(taskRef);
|
|
35137
|
+
const effortSummary = effort === undefined ? "" : `
|
|
35138
|
+
|
|
35139
|
+
${effort.ok ? taskEffortMessages.summary(effort.batches, effort.attempts, effort.remainingMs, effort.remainingBatches, effort.remainingAttempts) : taskEffortMessages.exhausted(effort.reason)}`;
|
|
33968
35140
|
const base = formatResult(projected) + (parentOverrideIgnored ? `
|
|
33969
35141
|
|
|
33970
|
-
${PARENT_OVERRIDE_IGNORED}` : "");
|
|
33971
|
-
const
|
|
35142
|
+
${PARENT_OVERRIDE_IGNORED}` : "") + effortSummary;
|
|
35143
|
+
const exhausted = effort?.ok === false || effort?.ok === true && (effort.remainingBatches === 0 || effort.remainingAttempts === 0);
|
|
35144
|
+
const advisory = exhausted ? undefined : singleAssignmentAdvisory(parsed.data.assignments.length, assignableRoleIDs(deps.config).length);
|
|
33972
35145
|
const withAdvisory = advisory === undefined ? base : `${base}
|
|
33973
35146
|
|
|
33974
35147
|
${advisory}`;
|
|
@@ -33999,7 +35172,7 @@ ${advisory}`;
|
|
|
33999
35172
|
|
|
34000
35173
|
// src/plugin/registerCastTool.ts
|
|
34001
35174
|
import { tool as tool7 } from "@opencode-ai/plugin";
|
|
34002
|
-
import { z as
|
|
35175
|
+
import { z as z41 } from "zod";
|
|
34003
35176
|
|
|
34004
35177
|
// src/messages/rosterSummary.ts
|
|
34005
35178
|
var ROSTER_SUMMARY_HEADING = "Registered team model policies";
|
|
@@ -34115,12 +35288,12 @@ function createTeamPreparation(deps) {
|
|
|
34115
35288
|
OpenTeamConfigSchema.parse(migrateConfig(baseRaw));
|
|
34116
35289
|
const overlay = overlayBefore === undefined ? undefined : parseConfigFileJson(DEFAULT_LOCAL_OVERLAY_PATH, overlayBefore);
|
|
34117
35290
|
const options = configOptionsFromPluginOptions(deps.options);
|
|
34118
|
-
const
|
|
35291
|
+
const resolve17 = (raw) => {
|
|
34119
35292
|
const config = validateConfigInput(TEAM_PREPARATION_CONFIG, mergeConfigInputs(mergeConfigInputs(raw, options), overlay));
|
|
34120
35293
|
assertEffectiveConfigModelDomains(config);
|
|
34121
35294
|
return config;
|
|
34122
35295
|
};
|
|
34123
|
-
const current =
|
|
35296
|
+
const current = resolve17(baseRaw);
|
|
34124
35297
|
const live = liveConfig ?? current;
|
|
34125
35298
|
if (resolveExecutionMode({
|
|
34126
35299
|
routerMode: current.router.executionMode,
|
|
@@ -34142,7 +35315,7 @@ function createTeamPreparation(deps) {
|
|
|
34142
35315
|
]))
|
|
34143
35316
|
}
|
|
34144
35317
|
});
|
|
34145
|
-
const effective =
|
|
35318
|
+
const effective = resolve17(candidate);
|
|
34146
35319
|
const requestedProfiles = new Set(roster.entries.filter((entry) => !isKnownNonWorkerRole(entry.roleID) && getRoleProfile(entry.roleID, live.orchestrator?.roles) === undefined).map((entry) => getRoleProfile(entry.roleID, effective.orchestrator?.roles)));
|
|
34147
35320
|
const additions = Object.fromEntries(Object.entries(effective.orchestrator?.roles ?? {}).filter(([key2, profile]) => requestedProfiles.has(profile) && !Object.hasOwn(live.orchestrator?.roles ?? {}, key2)));
|
|
34148
35321
|
const hasAdditions = Object.keys(additions).length > 0;
|
|
@@ -34228,13 +35401,13 @@ async function persistPreparedTeam(storage, files) {
|
|
|
34228
35401
|
}
|
|
34229
35402
|
|
|
34230
35403
|
// src/plugin/registerCastTool.ts
|
|
34231
|
-
var CastEntrySchema =
|
|
34232
|
-
roleID:
|
|
34233
|
-
agentName:
|
|
35404
|
+
var CastEntrySchema = z41.object({
|
|
35405
|
+
roleID: z41.string().min(1).describe("Stable role identifier, e.g. scribe or guardian"),
|
|
35406
|
+
agentName: z41.string().min(1).describe("Themed character name assigned to the role")
|
|
34234
35407
|
}).strict();
|
|
34235
|
-
var RegisterCastPayloadSchema =
|
|
34236
|
-
universe:
|
|
34237
|
-
entries:
|
|
35408
|
+
var RegisterCastPayloadSchema = z41.object({
|
|
35409
|
+
universe: z41.string().min(1).describe("Casting universe for this roster"),
|
|
35410
|
+
entries: z41.array(CastEntrySchema).min(1).describe("Role-to-name mappings")
|
|
34238
35411
|
}).strict();
|
|
34239
35412
|
function offendingFields(error) {
|
|
34240
35413
|
const fields = error.issues.flatMap((issue) => {
|
|
@@ -34354,7 +35527,7 @@ function createRegisterCastTool(deps) {
|
|
|
34354
35527
|
}
|
|
34355
35528
|
|
|
34356
35529
|
// src/plugin/reloadTool.ts
|
|
34357
|
-
import { resolve as
|
|
35530
|
+
import { resolve as resolve17 } from "node:path";
|
|
34358
35531
|
import { tool as tool8 } from "@opencode-ai/plugin/tool";
|
|
34359
35532
|
var WAIT_MS = 30000;
|
|
34360
35533
|
var SDK_TIMEOUT_MS = 5000;
|
|
@@ -34388,7 +35561,7 @@ function createReloadController(deps) {
|
|
|
34388
35561
|
return () => clearTimeout(timer);
|
|
34389
35562
|
}
|
|
34390
35563
|
};
|
|
34391
|
-
const directory =
|
|
35564
|
+
const directory = resolve17(deps.directory);
|
|
34392
35565
|
let pending;
|
|
34393
35566
|
let authorizing;
|
|
34394
35567
|
let closed = false;
|
|
@@ -34536,7 +35709,7 @@ function createReloadController(deps) {
|
|
|
34536
35709
|
const parsed = schema.safeParse(args);
|
|
34537
35710
|
if (!parsed.success)
|
|
34538
35711
|
return reloadMessages.invalid;
|
|
34539
|
-
if (context.agent !== "openteam" ||
|
|
35712
|
+
if (context.agent !== "openteam" || resolve17(context.directory) !== directory || context.sessionID.trim().length === 0)
|
|
34540
35713
|
return reloadMessages.denied;
|
|
34541
35714
|
if (parsed.data.action === "cancel") {
|
|
34542
35715
|
if ((pending?.sessionID ?? authorizing?.sessionID) !== context.sessionID)
|
|
@@ -34654,6 +35827,31 @@ function createReloadController(deps) {
|
|
|
34654
35827
|
};
|
|
34655
35828
|
}
|
|
34656
35829
|
|
|
35830
|
+
// src/plugin/reportTool.ts
|
|
35831
|
+
import { tool as tool9 } from "@opencode-ai/plugin";
|
|
35832
|
+
function createReportTool(delivery) {
|
|
35833
|
+
return tool9({
|
|
35834
|
+
description: reportDeliveryMessages.description,
|
|
35835
|
+
args: {
|
|
35836
|
+
status: tool9.schema.enum(["done", "continue"]).describe(reportDeliveryMessages.status),
|
|
35837
|
+
findings: tool9.schema.string().min(1).max(32768).describe(reportDeliveryMessages.findings)
|
|
35838
|
+
},
|
|
35839
|
+
async execute(args, context) {
|
|
35840
|
+
context.abort.throwIfAborted();
|
|
35841
|
+
const path4 = delivery.path(context.sessionID);
|
|
35842
|
+
await context.ask({
|
|
35843
|
+
permission: "openteam-submit-report",
|
|
35844
|
+
patterns: [path4],
|
|
35845
|
+
always: [],
|
|
35846
|
+
metadata: { reportPath: path4 }
|
|
35847
|
+
});
|
|
35848
|
+
context.abort.throwIfAborted();
|
|
35849
|
+
await delivery.submit(context.sessionID, args);
|
|
35850
|
+
return reportDeliveryMessages.submitted(path4);
|
|
35851
|
+
}
|
|
35852
|
+
});
|
|
35853
|
+
}
|
|
35854
|
+
|
|
34657
35855
|
// src/plugin/sessionTracker.ts
|
|
34658
35856
|
function createSessionTracker() {
|
|
34659
35857
|
const knownSessions = new Set;
|
|
@@ -34682,22 +35880,40 @@ function createSessionTracker() {
|
|
|
34682
35880
|
}
|
|
34683
35881
|
|
|
34684
35882
|
// src/plugin/toolcalls.ts
|
|
35883
|
+
var MAX_TRACKED_CALLS = 8192;
|
|
34685
35884
|
function key2(sessionID, callID) {
|
|
34686
35885
|
return `${sessionID}\x00${callID}`;
|
|
34687
35886
|
}
|
|
34688
35887
|
function createToolcallTracker(deps) {
|
|
34689
35888
|
const now = deps.now ?? Date.now;
|
|
34690
35889
|
const started = new Map;
|
|
35890
|
+
const completed = new Set;
|
|
34691
35891
|
return {
|
|
34692
35892
|
before(input) {
|
|
34693
|
-
|
|
35893
|
+
const mapKey = key2(input.sessionID, input.callID);
|
|
35894
|
+
if (completed.has(mapKey) || started.has(mapKey))
|
|
35895
|
+
return;
|
|
35896
|
+
started.set(mapKey, now());
|
|
35897
|
+
if (started.size > MAX_TRACKED_CALLS) {
|
|
35898
|
+
const oldest = started.keys().next().value;
|
|
35899
|
+
if (oldest !== undefined)
|
|
35900
|
+
started.delete(oldest);
|
|
35901
|
+
}
|
|
34694
35902
|
},
|
|
34695
35903
|
after(input) {
|
|
34696
35904
|
const mapKey = key2(input.sessionID, input.callID);
|
|
35905
|
+
if (completed.has(mapKey))
|
|
35906
|
+
return;
|
|
35907
|
+
completed.add(mapKey);
|
|
35908
|
+
if (completed.size > MAX_TRACKED_CALLS) {
|
|
35909
|
+
const oldest = completed.values().next().value;
|
|
35910
|
+
if (oldest !== undefined)
|
|
35911
|
+
completed.delete(oldest);
|
|
35912
|
+
}
|
|
34697
35913
|
const start = started.get(mapKey);
|
|
34698
35914
|
started.delete(mapKey);
|
|
34699
35915
|
const end = now();
|
|
34700
|
-
const durationMs = start === undefined ?
|
|
35916
|
+
const durationMs = input.durationMs !== undefined ? input.durationMs : start === undefined ? null : Math.max(0, Math.trunc(end - start));
|
|
34701
35917
|
const event = {
|
|
34702
35918
|
v: EVENT_SCHEMA_VERSION,
|
|
34703
35919
|
type: "toolcall",
|
|
@@ -34706,9 +35922,23 @@ function createToolcallTracker(deps) {
|
|
|
34706
35922
|
tool: input.tool,
|
|
34707
35923
|
callID: input.callID,
|
|
34708
35924
|
durationMs,
|
|
34709
|
-
ok: true
|
|
35925
|
+
ok: input.ok ?? true,
|
|
35926
|
+
...input.executed === undefined ? {} : { executed: input.executed },
|
|
35927
|
+
...input.providerExecuted === undefined ? {} : { providerExecuted: input.providerExecuted },
|
|
35928
|
+
...input.failureKind === undefined ? {} : { failureKind: input.failureKind }
|
|
34710
35929
|
};
|
|
34711
35930
|
return deps.sink.emit(event);
|
|
35931
|
+
},
|
|
35932
|
+
forgetSession(sessionID) {
|
|
35933
|
+
const prefix = `${sessionID}\x00`;
|
|
35934
|
+
for (const mapKey of started.keys()) {
|
|
35935
|
+
if (mapKey.startsWith(prefix))
|
|
35936
|
+
started.delete(mapKey);
|
|
35937
|
+
}
|
|
35938
|
+
for (const mapKey of completed) {
|
|
35939
|
+
if (mapKey.startsWith(prefix))
|
|
35940
|
+
completed.delete(mapKey);
|
|
35941
|
+
}
|
|
34712
35942
|
}
|
|
34713
35943
|
};
|
|
34714
35944
|
}
|
|
@@ -34896,6 +36126,61 @@ async function buildMemoryRuntimeFromConfig(config, deps, options = {}) {
|
|
|
34896
36126
|
}
|
|
34897
36127
|
}
|
|
34898
36128
|
|
|
36129
|
+
// src/storage/scopedArtifacts.ts
|
|
36130
|
+
import { lstatSync as lstatSync4, mkdirSync as mkdirSync4, realpathSync as realpathSync3 } from "node:fs";
|
|
36131
|
+
import { dirname as dirname10, join as join22 } from "node:path";
|
|
36132
|
+
function createScopedArtifactStore(directory, root) {
|
|
36133
|
+
function pathFor(name) {
|
|
36134
|
+
const workspace = realpathSync3(directory);
|
|
36135
|
+
const segments = [...splitVirtualPath(root), ...splitVirtualPath(name)];
|
|
36136
|
+
const filename = segments.pop();
|
|
36137
|
+
if (!filename)
|
|
36138
|
+
throw new Error(reportDeliveryMessages.unsafePath);
|
|
36139
|
+
let path4 = workspace;
|
|
36140
|
+
for (const segment of segments) {
|
|
36141
|
+
path4 = join22(path4, segment);
|
|
36142
|
+
try {
|
|
36143
|
+
mkdirSync4(path4, { mode: 448 });
|
|
36144
|
+
} catch (error) {
|
|
36145
|
+
if (!(typeof error === "object" && error !== null && ("code" in error) && error.code === "EEXIST"))
|
|
36146
|
+
throw error;
|
|
36147
|
+
}
|
|
36148
|
+
const stat4 = lstatSync4(path4);
|
|
36149
|
+
if (!stat4.isDirectory() || stat4.isSymbolicLink())
|
|
36150
|
+
throw new Error(reportDeliveryMessages.unsafePath);
|
|
36151
|
+
}
|
|
36152
|
+
const target = join22(path4, filename);
|
|
36153
|
+
try {
|
|
36154
|
+
const stat4 = lstatSync4(target);
|
|
36155
|
+
if (!stat4.isFile() || stat4.isSymbolicLink() || stat4.size > 1048576)
|
|
36156
|
+
throw new Error(reportDeliveryMessages.unsafePath);
|
|
36157
|
+
} catch (error) {
|
|
36158
|
+
if (!isMissingFsError(error))
|
|
36159
|
+
throw error;
|
|
36160
|
+
}
|
|
36161
|
+
return target;
|
|
36162
|
+
}
|
|
36163
|
+
return {
|
|
36164
|
+
read(name) {
|
|
36165
|
+
return readUtf8(pathFor(name));
|
|
36166
|
+
},
|
|
36167
|
+
write(name, content) {
|
|
36168
|
+
if (Buffer.byteLength(content, "utf8") > 1048576)
|
|
36169
|
+
throw new Error(reportDeliveryMessages.unsafePath);
|
|
36170
|
+
writeDurableAtomically(pathFor(name), content);
|
|
36171
|
+
},
|
|
36172
|
+
update(name, change) {
|
|
36173
|
+
const path4 = pathFor(name);
|
|
36174
|
+
withRunMutationLock(dirname10(path4), () => {
|
|
36175
|
+
const content = change(readUtf8(path4));
|
|
36176
|
+
if (Buffer.byteLength(content, "utf8") > 1048576)
|
|
36177
|
+
throw new Error(reportDeliveryMessages.unsafePath);
|
|
36178
|
+
writeDurableAtomically(path4, content);
|
|
36179
|
+
});
|
|
36180
|
+
}
|
|
36181
|
+
};
|
|
36182
|
+
}
|
|
36183
|
+
|
|
34899
36184
|
// src/telemetry/otelExporter.ts
|
|
34900
36185
|
var DEFAULT_SERVICE_NAME = "openteam";
|
|
34901
36186
|
function tracesUrl(ingestionEndpoint) {
|
|
@@ -35040,7 +36325,7 @@ var RELEASE_CERT_PATH = "artifacts/graph-release-certificate.json";
|
|
|
35040
36325
|
var SOAK_CERT_PATH = "artifacts/graph-soak-certificate.json";
|
|
35041
36326
|
async function readPackagedCertificate(path4) {
|
|
35042
36327
|
try {
|
|
35043
|
-
const hostDirectory = basename4(
|
|
36328
|
+
const hostDirectory = basename4(dirname11(path4)) === NATIVE_CERTIFICATE_DIRECTORY ? `${NATIVE_CERTIFICATE_DIRECTORY}/` : "";
|
|
35044
36329
|
return await readFile5(new URL(`./certificates/${hostDirectory}${basename4(path4)}`, import.meta.url), "utf8");
|
|
35045
36330
|
} catch {
|
|
35046
36331
|
return;
|
|
@@ -35165,8 +36450,8 @@ async function tryReadOpencodeVersion(serverUrl, fetchFn, client) {
|
|
|
35165
36450
|
}
|
|
35166
36451
|
var DEFAULT_OPENCODE_VERSION_BACKOFF_MS = [50, 250];
|
|
35167
36452
|
function defaultSleep(ms2) {
|
|
35168
|
-
return new Promise((
|
|
35169
|
-
setTimeout(
|
|
36453
|
+
return new Promise((resolve19) => {
|
|
36454
|
+
setTimeout(resolve19, ms2);
|
|
35170
36455
|
});
|
|
35171
36456
|
}
|
|
35172
36457
|
function createLazyOpencodeVersionReader(serverUrl, options = {}) {
|
|
@@ -35209,7 +36494,7 @@ function createLazyOpencodeVersionReader(serverUrl, options = {}) {
|
|
|
35209
36494
|
};
|
|
35210
36495
|
}
|
|
35211
36496
|
async function buildGateInput(config, storage, opencodeVersion, warn, packagedRead = readPackagedCertificate) {
|
|
35212
|
-
const hostPath = (path4) => isSupportedNativeOpencodeVersion(opencodeVersion) ? `${
|
|
36497
|
+
const hostPath = (path4) => isSupportedNativeOpencodeVersion(opencodeVersion) ? `${dirname11(path4)}/${NATIVE_CERTIFICATE_DIRECTORY}/${basename4(path4)}` : path4;
|
|
35213
36498
|
const shadow = await readAndParseCertificate(storage, hostPath(SHADOW_CERT_PATH), (raw) => parseShadowCertificate(raw, opencodeVersion), (cert) => shadowCertificateBindingDigest(cert.evidence), packagedRead);
|
|
35214
36499
|
const shadowDigest = shadow.status === "valid" ? shadow.digest : "0".repeat(64);
|
|
35215
36500
|
const release = await readAndParseCertificate(storage, hostPath(RELEASE_CERT_PATH), (raw) => parseReleaseCertificate(raw, opencodeVersion, shadowDigest), (cert) => cert.digest, packagedRead);
|
|
@@ -35418,7 +36703,7 @@ function createCliDeps(config, registry, telemetryPath, sessionsDir = DEFAULT_SE
|
|
|
35418
36703
|
telemetryPath,
|
|
35419
36704
|
opencodeConfigPaths: OPENCODE_CONFIG_CANDIDATES,
|
|
35420
36705
|
orchestratorAgentPath: ORCHESTRATOR_AGENT_PATH,
|
|
35421
|
-
agentDir:
|
|
36706
|
+
agentDir: dirname11(ORCHESTRATOR_AGENT_PATH),
|
|
35422
36707
|
cachePort: realCacheAdapter,
|
|
35423
36708
|
purge: createPluginPurgeRuntime(sessionsDir),
|
|
35424
36709
|
loadRosterForDoctor: () => readStoredRosterForDoctor(storage),
|
|
@@ -35569,6 +36854,24 @@ async function createPluginRuntime(ctx, rawOptions) {
|
|
|
35569
36854
|
return version === "unknown" ? undefined : version;
|
|
35570
36855
|
}, workspaceRoot);
|
|
35571
36856
|
const toolcalls = createToolcallTracker({ sink });
|
|
36857
|
+
const sessionPhase = async (sessionID, phase) => {
|
|
36858
|
+
try {
|
|
36859
|
+
await sink.emit({
|
|
36860
|
+
v: 1,
|
|
36861
|
+
type: "activity",
|
|
36862
|
+
ts: now(),
|
|
36863
|
+
sessionID,
|
|
36864
|
+
kind: "agent",
|
|
36865
|
+
summary: executionPhaseMessages[phase],
|
|
36866
|
+
phase
|
|
36867
|
+
});
|
|
36868
|
+
} catch (error) {
|
|
36869
|
+
logTelemetryError(error, diagnostics.warn("telemetry-write-failed", {
|
|
36870
|
+
persist: false,
|
|
36871
|
+
toast: false
|
|
36872
|
+
}));
|
|
36873
|
+
}
|
|
36874
|
+
};
|
|
35572
36875
|
const announcedSessions = new Set;
|
|
35573
36876
|
const announceEndpoint = (sessionID) => {
|
|
35574
36877
|
if (sessionID === undefined || announcedSessions.has(sessionID)) {
|
|
@@ -35689,6 +36992,18 @@ async function createPluginRuntime(ctx, rawOptions) {
|
|
|
35689
36992
|
},
|
|
35690
36993
|
now
|
|
35691
36994
|
});
|
|
36995
|
+
const reportStore = createScopedArtifactStore(ctx.directory, ROLE_REPORTS_ROOT);
|
|
36996
|
+
const taskEffort = createTaskEffort({
|
|
36997
|
+
store: createScopedArtifactStore(ctx.directory, ".opencode/openteam-local/effort"),
|
|
36998
|
+
now,
|
|
36999
|
+
...config.orchestrator?.taskBudget === undefined ? {} : { limits: config.orchestrator.taskBudget },
|
|
37000
|
+
...ctx.parentSession === undefined ? {} : { parentSession: ctx.parentSession }
|
|
37001
|
+
});
|
|
37002
|
+
const reportDelivery = createReportDelivery({
|
|
37003
|
+
write: async (path4, content) => {
|
|
37004
|
+
reportStore.write(path4.slice(ROLE_REPORTS_ROOT.length + 1), content);
|
|
37005
|
+
}
|
|
37006
|
+
});
|
|
35692
37007
|
const orchestrateTool = createOrchestrateTool({
|
|
35693
37008
|
client: orchestrateClient,
|
|
35694
37009
|
sink,
|
|
@@ -35709,11 +37024,15 @@ async function createPluginRuntime(ctx, rawOptions) {
|
|
|
35709
37024
|
capabilityProfiles,
|
|
35710
37025
|
reportArtifactExists,
|
|
35711
37026
|
readReportArtifact,
|
|
37027
|
+
reportDelivery,
|
|
37028
|
+
taskEffort,
|
|
37029
|
+
sessionPhase,
|
|
37030
|
+
workspaceDirectory: ctx.directory,
|
|
35712
37031
|
lifecycleRecorder,
|
|
35713
37032
|
abortGraceMs: DEFAULT_ABORT_GRACE_MS,
|
|
35714
37033
|
statusPollMs: DEFAULT_STATUS_POLL_MS,
|
|
35715
|
-
delay: (ms2) => new Promise((
|
|
35716
|
-
setTimeout(
|
|
37034
|
+
delay: (ms2) => new Promise((resolve19) => {
|
|
37035
|
+
setTimeout(resolve19, ms2);
|
|
35717
37036
|
}),
|
|
35718
37037
|
warn: diagnostics.warn("unknown-role")
|
|
35719
37038
|
});
|
|
@@ -35779,7 +37098,9 @@ async function createPluginRuntime(ctx, rawOptions) {
|
|
|
35779
37098
|
...hooks,
|
|
35780
37099
|
"chat.message": async (input, output) => {
|
|
35781
37100
|
reload.userTurn(input.sessionID);
|
|
37101
|
+
await taskEffort.userTurn(input.sessionID, input.messageID ?? output.message.id);
|
|
35782
37102
|
await hooks["chat.message"]?.(input, output);
|
|
37103
|
+
await sessionPhase(input.sessionID, "model-request");
|
|
35783
37104
|
announceEndpoint(input.sessionID);
|
|
35784
37105
|
},
|
|
35785
37106
|
dispose: async () => {
|
|
@@ -35793,18 +37114,44 @@ async function createPluginRuntime(ctx, rawOptions) {
|
|
|
35793
37114
|
"openteam-orchestrate": orchestrateTool,
|
|
35794
37115
|
"openteam-memory": memoryTool,
|
|
35795
37116
|
"openteam-register-cast": registerCastTool,
|
|
35796
|
-
"openteam-reload": reload.tool
|
|
37117
|
+
"openteam-reload": reload.tool,
|
|
37118
|
+
"openteam-submit-report": createReportTool(reportDelivery)
|
|
35797
37119
|
},
|
|
35798
37120
|
"tool.execute.before": async (input) => {
|
|
35799
37121
|
toolcalls.before(input);
|
|
37122
|
+
await sessionPhase(input.sessionID, "tool-execution");
|
|
35800
37123
|
},
|
|
35801
37124
|
"tool.execute.after": async (input) => {
|
|
35802
|
-
|
|
37125
|
+
if (ctx.toolOutcomesFromEvents !== true)
|
|
37126
|
+
await toolcalls.after(input);
|
|
35803
37127
|
if (input.tool === "openteam-reload")
|
|
35804
37128
|
reload.toolCompleted(input.sessionID);
|
|
35805
37129
|
},
|
|
35806
37130
|
event: async ({ event }) => {
|
|
35807
37131
|
reload.event(event);
|
|
37132
|
+
if (event.type === "openteam.tool.completed") {
|
|
37133
|
+
await toolcalls.after(event.properties);
|
|
37134
|
+
await sessionPhase(event.properties.sessionID, "unknown");
|
|
37135
|
+
} else if (event.type === "openteam.session.phase") {
|
|
37136
|
+
await sessionPhase(event.properties.sessionID, event.properties.phase);
|
|
37137
|
+
} else if (event.type === "session.idle") {
|
|
37138
|
+
if (typeof event.properties?.sessionID === "string")
|
|
37139
|
+
await sessionPhase(event.properties.sessionID, "idle");
|
|
37140
|
+
} else if (event.type === "message.part.updated") {
|
|
37141
|
+
const part = event.properties.part;
|
|
37142
|
+
if (part.type === "tool" && (part.state.status === "completed" || part.state.status === "error")) {
|
|
37143
|
+
await toolcalls.after({
|
|
37144
|
+
tool: part.tool,
|
|
37145
|
+
sessionID: part.sessionID,
|
|
37146
|
+
callID: part.callID,
|
|
37147
|
+
ok: part.state.status === "completed",
|
|
37148
|
+
durationMs: Math.max(0, Math.trunc(part.state.time.end - part.state.time.start)),
|
|
37149
|
+
...part.state.status === "error" ? { failureKind: "execution" } : {}
|
|
37150
|
+
});
|
|
37151
|
+
}
|
|
37152
|
+
} else if (event.type === "session.deleted") {
|
|
37153
|
+
toolcalls.forgetSession(event.properties.info.id);
|
|
37154
|
+
}
|
|
35808
37155
|
if (event.type === "session.created" || event.type === "session.idle") {
|
|
35809
37156
|
cache.refresh();
|
|
35810
37157
|
}
|
|
@@ -35821,6 +37168,7 @@ async function createPluginRuntime(ctx, rawOptions) {
|
|
|
35821
37168
|
announceEndpoint(message2.sessionID);
|
|
35822
37169
|
sessionTracker.trackSession(message2.sessionID);
|
|
35823
37170
|
sink.emit(message2);
|
|
37171
|
+
await sessionPhase(message2.sessionID, "unknown");
|
|
35824
37172
|
}
|
|
35825
37173
|
}
|
|
35826
37174
|
}
|
|
@@ -35830,6 +37178,19 @@ var server = (ctx, rawOptions) => createPluginRuntime({
|
|
|
35830
37178
|
directory: ctx.directory,
|
|
35831
37179
|
worktree: ctx.worktree,
|
|
35832
37180
|
client: ctx.client,
|
|
37181
|
+
...typeof ctx.client.session?.get !== "function" ? {} : {
|
|
37182
|
+
parentSession: async (sessionID) => {
|
|
37183
|
+
const response = await ctx.client.session.get({
|
|
37184
|
+
path: { id: sessionID },
|
|
37185
|
+
query: { directory: ctx.directory }
|
|
37186
|
+
});
|
|
37187
|
+
if (response.error !== undefined || response.data === undefined)
|
|
37188
|
+
throw new Error(nativeHostMessages.missingBindings);
|
|
37189
|
+
if (resolve18(response.data.directory) !== resolve18(ctx.directory))
|
|
37190
|
+
throw new Error(nativeHostMessages.workspaceMismatch);
|
|
37191
|
+
return response.data.parentID;
|
|
37192
|
+
}
|
|
37193
|
+
},
|
|
35833
37194
|
exec: createShellExec(ctx.$),
|
|
35834
37195
|
serverUrl: () => ctx.serverUrl,
|
|
35835
37196
|
...ctx.client.config?.providers === undefined ? {} : {
|
|
@@ -36456,7 +37817,7 @@ function createGitLastCommit(exec) {
|
|
|
36456
37817
|
// src/cli.ts
|
|
36457
37818
|
var execFileAsync3 = promisify3(execFile4);
|
|
36458
37819
|
var execAsync = promisify3(exec);
|
|
36459
|
-
var AGENT_DIR =
|
|
37820
|
+
var AGENT_DIR = dirname12(ORCHESTRATOR_AGENT_PATH);
|
|
36460
37821
|
var storage = createFsStorageProvider(process.cwd());
|
|
36461
37822
|
var CLI_LIFECYCLE_WRITER_IDENTITY = {
|
|
36462
37823
|
processID: process.pid,
|
|
@@ -36543,7 +37904,7 @@ async function readConfigFile(path4, resolution) {
|
|
|
36543
37904
|
return storage.read(path4);
|
|
36544
37905
|
}
|
|
36545
37906
|
try {
|
|
36546
|
-
return await readFile6(
|
|
37907
|
+
return await readFile6(resolve19(path4), "utf8");
|
|
36547
37908
|
} catch (error) {
|
|
36548
37909
|
throw new Error(`[openteam] config file named by --config could not be read: ${path4} (${describeFileReadError(error)})`);
|
|
36549
37910
|
}
|
|
@@ -36566,8 +37927,8 @@ async function saveConfig(config, path4, resolution = { explicit: false }) {
|
|
|
36566
37927
|
return;
|
|
36567
37928
|
}
|
|
36568
37929
|
const contents = serializeOpenTeamConfig(config);
|
|
36569
|
-
const diskPath =
|
|
36570
|
-
await mkdir5(
|
|
37930
|
+
const diskPath = resolve19(path4);
|
|
37931
|
+
await mkdir5(dirname12(diskPath), { recursive: true });
|
|
36571
37932
|
await writeFile2(diskPath, contents, "utf8");
|
|
36572
37933
|
}
|
|
36573
37934
|
function parseConfigSelection(argv) {
|
|
@@ -36612,8 +37973,8 @@ async function openBrowser(url) {
|
|
|
36612
37973
|
}
|
|
36613
37974
|
}
|
|
36614
37975
|
function waitForSignal() {
|
|
36615
|
-
return new Promise((
|
|
36616
|
-
const done = () =>
|
|
37976
|
+
return new Promise((resolve20) => {
|
|
37977
|
+
const done = () => resolve20();
|
|
36617
37978
|
process.once("SIGINT", done);
|
|
36618
37979
|
process.once("SIGTERM", done);
|
|
36619
37980
|
});
|
|
@@ -36814,7 +38175,7 @@ async function main() {
|
|
|
36814
38175
|
workspaceRoot,
|
|
36815
38176
|
configuredRoot: initialConsoleConfig.lifecycle?.root ?? DEFAULT_LIFECYCLE_ROOT
|
|
36816
38177
|
});
|
|
36817
|
-
const legacyGraphRoot =
|
|
38178
|
+
const legacyGraphRoot = resolve19(workspaceRoot, initialConsoleConfig.graph?.journalRoot ?? DEFAULT_GRAPH_JOURNAL_ROOT);
|
|
36818
38179
|
const lifecycleAvailability = initialConsoleConfig.console.graphView?.enabled === true ? "enabled" : "history-disabled";
|
|
36819
38180
|
const lifecycleHistoryReader = createLifecycleHistoryProvider({
|
|
36820
38181
|
lifecycleRoot,
|