@openscout/protocol 0.2.63 → 0.2.82
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/LICENSE +202 -0
- package/README.md +103 -52
- package/dist/a2a.d.ts +224 -0
- package/dist/a2a.d.ts.map +1 -0
- package/dist/a2a.js +225 -0
- package/dist/activity.d.ts +70 -0
- package/dist/activity.d.ts.map +1 -0
- package/dist/activity.js +1 -0
- package/dist/actors.d.ts +7 -3
- package/dist/actors.d.ts.map +1 -0
- package/dist/actors.js +15 -1
- package/dist/agent-broker-feed.d.ts +84 -0
- package/dist/agent-broker-feed.d.ts.map +1 -0
- package/dist/agent-broker-feed.js +1 -0
- package/dist/agent-identity.d.ts +23 -0
- package/dist/agent-identity.d.ts.map +1 -0
- package/dist/agent-identity.js +122 -8
- package/dist/agent-runs.d.ts +191 -0
- package/dist/agent-runs.d.ts.map +1 -0
- package/dist/agent-runs.js +365 -0
- package/dist/assigned-roles.d.ts +205 -0
- package/dist/assigned-roles.d.ts.map +1 -0
- package/dist/assigned-roles.js +228 -0
- package/dist/broker-routes.d.ts +40 -0
- package/dist/broker-routes.d.ts.map +1 -0
- package/dist/broker-routes.js +56 -0
- package/dist/budget.d.ts +65 -0
- package/dist/budget.d.ts.map +1 -0
- package/dist/budget.js +19 -0
- package/dist/capability-matrix.d.ts +230 -0
- package/dist/capability-matrix.d.ts.map +1 -0
- package/dist/capability-matrix.js +304 -0
- package/dist/channel-identity.d.ts +40 -0
- package/dist/channel-identity.d.ts.map +1 -0
- package/dist/channel-identity.js +108 -0
- package/dist/collaboration.d.ts +45 -16
- package/dist/collaboration.d.ts.map +1 -0
- package/dist/collaboration.js +39 -23
- package/dist/common.d.ts +4 -3
- package/dist/common.d.ts.map +1 -0
- package/dist/conversations.d.ts +1 -0
- package/dist/conversations.d.ts.map +1 -0
- package/dist/cursor-transport.d.ts +22 -0
- package/dist/cursor-transport.d.ts.map +1 -0
- package/dist/cursor-transport.js +10 -0
- package/dist/debug-attach.d.ts +29 -0
- package/dist/debug-attach.d.ts.map +1 -0
- package/dist/debug-attach.js +6 -0
- package/dist/deliveries.d.ts +16 -2
- package/dist/deliveries.d.ts.map +1 -0
- package/dist/durable-actions.d.ts +94 -0
- package/dist/durable-actions.d.ts.map +1 -0
- package/dist/durable-actions.js +1 -0
- package/dist/events.d.ts +27 -1
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +14 -1
- package/dist/harness-feature-support.d.ts +76 -0
- package/dist/harness-feature-support.d.ts.map +1 -0
- package/dist/harness-feature-support.js +29 -0
- package/dist/host-integrations.d.ts +22 -0
- package/dist/host-integrations.d.ts.map +1 -0
- package/dist/host-integrations.js +64 -0
- package/dist/inbox.d.ts +50 -0
- package/dist/inbox.d.ts.map +1 -0
- package/dist/inbox.js +9 -0
- package/dist/index.d.ts +36 -2
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -2
- package/dist/invocations.d.ts +121 -0
- package/dist/invocations.d.ts.map +1 -0
- package/dist/invocations.js +201 -1
- package/dist/mesh.d.ts +98 -0
- package/dist/mesh.d.ts.map +1 -0
- package/dist/mesh.js +18 -1
- package/dist/messages.d.ts +3 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/native-interactions.d.ts +30 -0
- package/dist/native-interactions.d.ts.map +1 -0
- package/dist/native-interactions.js +51 -0
- package/dist/observed-status.d.ts +33 -0
- package/dist/observed-status.d.ts.map +1 -0
- package/dist/observed-status.js +6 -0
- package/dist/orchestrator-prompt.d.ts +10 -0
- package/dist/orchestrator-prompt.d.ts.map +1 -0
- package/dist/orchestrator-prompt.js +36 -0
- package/dist/permission-policy.d.ts +5 -0
- package/dist/permission-policy.d.ts.map +1 -0
- package/dist/permission-policy.js +15 -0
- package/dist/provisional-agent-names.d.ts +30 -0
- package/dist/provisional-agent-names.d.ts.map +1 -0
- package/dist/provisional-agent-names.js +224 -0
- package/dist/read-receipts.d.ts +12 -0
- package/dist/read-receipts.d.ts.map +1 -0
- package/dist/read-receipts.js +1 -0
- package/dist/relay-agent-card.d.ts +10 -0
- package/dist/relay-agent-card.d.ts.map +1 -0
- package/dist/rendezvous.d.ts +97 -0
- package/dist/rendezvous.d.ts.map +1 -0
- package/dist/rendezvous.js +35 -0
- package/dist/reserved-vocabulary.d.ts +21 -0
- package/dist/reserved-vocabulary.d.ts.map +1 -0
- package/dist/reserved-vocabulary.js +101 -0
- package/dist/route-aliases.d.ts +112 -0
- package/dist/route-aliases.d.ts.map +1 -0
- package/dist/route-aliases.js +1 -0
- package/dist/runtime-catalog-contract.d.ts +39 -0
- package/dist/runtime-catalog-contract.d.ts.map +1 -0
- package/dist/runtime-catalog-contract.js +17 -0
- package/dist/runtime-catalog.d.ts +11 -0
- package/dist/runtime-catalog.d.ts.map +1 -0
- package/dist/runtime-catalog.generated.d.ts +230 -0
- package/dist/runtime-catalog.generated.d.ts.map +1 -0
- package/dist/runtime-catalog.generated.js +299 -0
- package/dist/runtime-catalog.js +192 -0
- package/dist/runtime-execution.d.ts +161 -0
- package/dist/runtime-execution.d.ts.map +1 -0
- package/dist/runtime-execution.js +327 -0
- package/dist/runtime-profiles.d.ts +12 -0
- package/dist/runtime-profiles.d.ts.map +1 -0
- package/dist/runtime-profiles.js +20 -0
- package/dist/scout-agent-card.d.ts +10 -0
- package/dist/scout-agent-card.d.ts.map +1 -0
- package/dist/scout-composer.d.ts +27 -0
- package/dist/scout-composer.d.ts.map +1 -0
- package/dist/scout-composer.js +192 -0
- package/dist/scout-delivery.d.ts +101 -4
- package/dist/scout-delivery.d.ts.map +1 -0
- package/dist/scout-dispatch.d.ts +44 -3
- package/dist/scout-dispatch.d.ts.map +1 -0
- package/dist/scout-reply-context.d.ts +14 -0
- package/dist/scout-reply-context.d.ts.map +1 -0
- package/dist/scout-reply-context.js +1 -0
- package/dist/session-display-state.d.ts +132 -0
- package/dist/session-display-state.d.ts.map +1 -0
- package/dist/session-display-state.js +94 -0
- package/dist/terminal-host-topology.d.ts +119 -0
- package/dist/terminal-host-topology.d.ts.map +1 -0
- package/dist/terminal-host-topology.js +21 -0
- package/dist/terminal-sessions.d.ts +142 -0
- package/dist/terminal-sessions.d.ts.map +1 -0
- package/dist/terminal-sessions.js +81 -0
- package/dist/terminal-surface-id.d.ts +73 -0
- package/dist/terminal-surface-id.d.ts.map +1 -0
- package/dist/terminal-surface-id.js +162 -0
- package/dist/terminal-workspaces.d.ts +199 -0
- package/dist/terminal-workspaces.d.ts.map +1 -0
- package/dist/terminal-workspaces.js +287 -0
- package/dist/thread-events.d.ts +1 -0
- package/dist/thread-events.d.ts.map +1 -0
- package/dist/time.d.ts +16 -0
- package/dist/time.d.ts.map +1 -0
- package/dist/time.js +33 -0
- package/dist/transports.d.ts +1 -0
- package/dist/transports.d.ts.map +1 -0
- package/package.json +37 -9
- package/src/a2a.ts +471 -0
- package/src/activity.ts +113 -0
- package/src/actors.ts +42 -8
- package/src/agent-broker-feed.ts +102 -0
- package/src/agent-identity.ts +143 -8
- package/src/agent-runs.ts +675 -0
- package/src/assigned-roles.ts +437 -0
- package/src/broker-routes.ts +62 -0
- package/src/budget.ts +88 -0
- package/src/capability-matrix.ts +648 -0
- package/src/channel-identity.ts +147 -0
- package/src/collaboration.ts +78 -48
- package/src/common.ts +24 -5
- package/src/cursor-transport.ts +34 -0
- package/src/debug-attach.ts +38 -0
- package/src/deliveries.ts +16 -1
- package/src/durable-actions.ts +125 -0
- package/src/events.ts +31 -0
- package/src/harness-feature-support.ts +116 -0
- package/src/host-integrations.ts +104 -0
- package/src/inbox.ts +68 -0
- package/src/index.ts +35 -2
- package/src/invocations.ts +353 -0
- package/src/mesh.ts +130 -0
- package/src/messages.ts +2 -0
- package/src/native-interactions.ts +100 -0
- package/src/observed-status.ts +90 -0
- package/src/orchestrator-prompt.ts +47 -0
- package/src/permission-policy.ts +21 -0
- package/src/provisional-agent-names.ts +272 -0
- package/src/read-receipts.ts +12 -0
- package/src/relay-agent-card.ts +73 -63
- package/src/rendezvous.ts +154 -0
- package/src/reserved-vocabulary.ts +135 -0
- package/src/route-aliases.ts +130 -0
- package/src/runtime-catalog-contract.ts +60 -0
- package/src/runtime-catalog.generated.ts +300 -0
- package/src/runtime-catalog.md +21 -0
- package/src/runtime-catalog.ts +193 -0
- package/src/runtime-catalog.v1.json +81 -0
- package/src/runtime-execution.ts +545 -0
- package/src/runtime-profiles.ts +37 -0
- package/src/scout-agent-card.ts +10 -0
- package/src/scout-composer.ts +249 -0
- package/src/scout-delivery.ts +117 -4
- package/src/scout-dispatch.ts +34 -2
- package/src/scout-reply-context.ts +15 -0
- package/src/session-display-state.ts +202 -0
- package/src/terminal-host-topology.ts +132 -0
- package/src/terminal-sessions.ts +187 -0
- package/src/terminal-surface-id.ts +189 -0
- package/src/terminal-workspaces.ts +455 -0
- package/src/time.ts +49 -0
- package/dist/agent-address.d.ts +0 -1
- package/dist/agent-address.js +0 -1
- package/dist/agent-selectors.d.ts +0 -1
- package/dist/agent-selectors.js +0 -1
- package/src/agent-address.ts +0 -1
- package/src/agent-identity.test.ts +0 -435
- package/src/agent-selectors.ts +0 -1
- package/src/scout-agent-card.test.ts +0 -54
|
@@ -0,0 +1,675 @@
|
|
|
1
|
+
import type { AgentHarness } from "./actors.js";
|
|
2
|
+
import type { MetadataMap, ScoutId, VisibilityScope } from "./common.js";
|
|
3
|
+
import type {
|
|
4
|
+
FlightRecord,
|
|
5
|
+
Invocation,
|
|
6
|
+
InvocationExecutionPreference,
|
|
7
|
+
InvocationRequest,
|
|
8
|
+
} from "./invocations.js";
|
|
9
|
+
import {
|
|
10
|
+
normalizeScoutPermissionProfile,
|
|
11
|
+
type ScoutPermissionProfile,
|
|
12
|
+
} from "./permission-policy.js";
|
|
13
|
+
|
|
14
|
+
export const AGENT_RUN_STATES = [
|
|
15
|
+
"queued",
|
|
16
|
+
"waking",
|
|
17
|
+
"running",
|
|
18
|
+
"waiting",
|
|
19
|
+
"review",
|
|
20
|
+
"completed",
|
|
21
|
+
"failed",
|
|
22
|
+
"cancelled",
|
|
23
|
+
"unknown",
|
|
24
|
+
] as const;
|
|
25
|
+
|
|
26
|
+
export type AgentRunState = typeof AGENT_RUN_STATES[number];
|
|
27
|
+
|
|
28
|
+
export const AGENT_RUN_SOURCES = [
|
|
29
|
+
"ask",
|
|
30
|
+
"message",
|
|
31
|
+
"schedule",
|
|
32
|
+
"recipe",
|
|
33
|
+
"external_issue",
|
|
34
|
+
"manual",
|
|
35
|
+
"eval",
|
|
36
|
+
"unknown",
|
|
37
|
+
] as const;
|
|
38
|
+
|
|
39
|
+
export type AgentRunSource = typeof AGENT_RUN_SOURCES[number];
|
|
40
|
+
|
|
41
|
+
export const AGENT_RUN_REVIEW_STATES = [
|
|
42
|
+
"none",
|
|
43
|
+
"needed",
|
|
44
|
+
"blocked",
|
|
45
|
+
"approved",
|
|
46
|
+
"rejected",
|
|
47
|
+
] as const;
|
|
48
|
+
|
|
49
|
+
export type AgentRunReviewState = typeof AGENT_RUN_REVIEW_STATES[number];
|
|
50
|
+
|
|
51
|
+
export interface AgentRevisionSnapshot {
|
|
52
|
+
id?: ScoutId;
|
|
53
|
+
agentId?: ScoutId;
|
|
54
|
+
definitionId?: ScoutId;
|
|
55
|
+
revision?: number | string;
|
|
56
|
+
digest?: string;
|
|
57
|
+
displayName?: string;
|
|
58
|
+
runtime?: {
|
|
59
|
+
harness?: AgentHarness;
|
|
60
|
+
transport?: string;
|
|
61
|
+
model?: string;
|
|
62
|
+
reasoningEffort?: string;
|
|
63
|
+
session?: InvocationExecutionPreference["session"];
|
|
64
|
+
launchArgs?: string[];
|
|
65
|
+
};
|
|
66
|
+
permissions?: {
|
|
67
|
+
permissionProfile?: ScoutPermissionProfile | string;
|
|
68
|
+
sandbox?: string;
|
|
69
|
+
approvalPolicy?: string;
|
|
70
|
+
enforcementLevel?: string;
|
|
71
|
+
secretRefs?: string[];
|
|
72
|
+
};
|
|
73
|
+
workspace?: {
|
|
74
|
+
projectRoot?: string;
|
|
75
|
+
cwd?: string;
|
|
76
|
+
mode?: "shared" | "isolated" | "external_sandbox";
|
|
77
|
+
hooks?: string[];
|
|
78
|
+
};
|
|
79
|
+
provenance?: {
|
|
80
|
+
source?: "managed_agent" | "ad_hoc" | "imported" | "promotion";
|
|
81
|
+
sourceRef?: string;
|
|
82
|
+
parentRevisionId?: ScoutId;
|
|
83
|
+
};
|
|
84
|
+
metadata?: MetadataMap;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface AgentRunMetrics {
|
|
88
|
+
inputTokens?: number;
|
|
89
|
+
outputTokens?: number;
|
|
90
|
+
totalTokens?: number;
|
|
91
|
+
estimatedUsd?: number;
|
|
92
|
+
wallClockMs?: number;
|
|
93
|
+
toolCallCount?: number;
|
|
94
|
+
retryCount?: number;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface AgentRun {
|
|
98
|
+
id: ScoutId;
|
|
99
|
+
source: AgentRunSource;
|
|
100
|
+
requesterId: ScoutId;
|
|
101
|
+
agentId: ScoutId;
|
|
102
|
+
agentRevisionId?: ScoutId;
|
|
103
|
+
agentRevisionSnapshot?: AgentRevisionSnapshot;
|
|
104
|
+
aliasId?: ScoutId;
|
|
105
|
+
workId?: ScoutId;
|
|
106
|
+
collaborationRecordId?: ScoutId;
|
|
107
|
+
conversationId?: ScoutId;
|
|
108
|
+
messageId?: ScoutId;
|
|
109
|
+
invocationId?: ScoutId;
|
|
110
|
+
flightIds?: ScoutId[];
|
|
111
|
+
parentRunId?: ScoutId;
|
|
112
|
+
rootRunId?: ScoutId;
|
|
113
|
+
recipeId?: ScoutId;
|
|
114
|
+
attempt?: number;
|
|
115
|
+
idempotencyKey?: string;
|
|
116
|
+
state: AgentRunState;
|
|
117
|
+
reviewState?: AgentRunReviewState;
|
|
118
|
+
terminalReason?: string;
|
|
119
|
+
input: MetadataMap;
|
|
120
|
+
output?: MetadataMap;
|
|
121
|
+
artifactIds?: ScoutId[];
|
|
122
|
+
reviewTaskIds?: ScoutId[];
|
|
123
|
+
traceSessionIds?: ScoutId[];
|
|
124
|
+
createdAt: number;
|
|
125
|
+
startedAt?: number;
|
|
126
|
+
updatedAt: number;
|
|
127
|
+
completedAt?: number;
|
|
128
|
+
harness?: AgentHarness;
|
|
129
|
+
model?: string;
|
|
130
|
+
permissionProfile?: ScoutPermissionProfile;
|
|
131
|
+
metrics?: AgentRunMetrics;
|
|
132
|
+
metadata?: MetadataMap;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export type RunArtifactKind =
|
|
136
|
+
| "patch"
|
|
137
|
+
| "branch"
|
|
138
|
+
| "commit"
|
|
139
|
+
| "pull_request"
|
|
140
|
+
| "file"
|
|
141
|
+
| "report"
|
|
142
|
+
| "screenshot"
|
|
143
|
+
| "dataset_row"
|
|
144
|
+
| "log_bundle"
|
|
145
|
+
| "summary";
|
|
146
|
+
|
|
147
|
+
export interface RunArtifact {
|
|
148
|
+
id: ScoutId;
|
|
149
|
+
runId: ScoutId;
|
|
150
|
+
stepId?: ScoutId;
|
|
151
|
+
kind: RunArtifactKind;
|
|
152
|
+
title: string;
|
|
153
|
+
uri?: string;
|
|
154
|
+
resourceId?: ScoutId;
|
|
155
|
+
contentHash?: string;
|
|
156
|
+
reviewTaskId?: ScoutId;
|
|
157
|
+
createdAt: number;
|
|
158
|
+
createdById?: ScoutId;
|
|
159
|
+
metadata?: MetadataMap;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export type ReviewTaskKind =
|
|
163
|
+
| "permission"
|
|
164
|
+
| "output_review"
|
|
165
|
+
| "promotion"
|
|
166
|
+
| "retry_decision"
|
|
167
|
+
| "eval_label"
|
|
168
|
+
| "handoff";
|
|
169
|
+
|
|
170
|
+
export type ReviewTaskState =
|
|
171
|
+
| "open"
|
|
172
|
+
| "claimed"
|
|
173
|
+
| "approved"
|
|
174
|
+
| "rejected"
|
|
175
|
+
| "dismissed"
|
|
176
|
+
| "expired";
|
|
177
|
+
|
|
178
|
+
export interface ReviewTask {
|
|
179
|
+
id: ScoutId;
|
|
180
|
+
kind: ReviewTaskKind;
|
|
181
|
+
subject: {
|
|
182
|
+
runId?: ScoutId;
|
|
183
|
+
workId?: ScoutId;
|
|
184
|
+
stepId?: ScoutId;
|
|
185
|
+
artifactId?: ScoutId;
|
|
186
|
+
agentRevisionId?: ScoutId;
|
|
187
|
+
promotionId?: ScoutId;
|
|
188
|
+
traceRef?: {
|
|
189
|
+
sessionId: ScoutId;
|
|
190
|
+
turnId?: ScoutId;
|
|
191
|
+
blockId?: ScoutId;
|
|
192
|
+
version?: number;
|
|
193
|
+
};
|
|
194
|
+
};
|
|
195
|
+
assigneeId?: ScoutId;
|
|
196
|
+
groupId?: ScoutId;
|
|
197
|
+
state: ReviewTaskState;
|
|
198
|
+
risk?: "low" | "medium" | "high";
|
|
199
|
+
form?: MetadataMap;
|
|
200
|
+
decision?: MetadataMap;
|
|
201
|
+
createdAt: number;
|
|
202
|
+
claimedAt?: number;
|
|
203
|
+
completedAt?: number;
|
|
204
|
+
metadata?: MetadataMap;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export interface SavedRunView {
|
|
208
|
+
id: ScoutId;
|
|
209
|
+
name: string;
|
|
210
|
+
ownerId?: ScoutId;
|
|
211
|
+
visibility?: VisibilityScope;
|
|
212
|
+
filters: MetadataMap;
|
|
213
|
+
sort?: Array<{
|
|
214
|
+
field: string;
|
|
215
|
+
direction: "asc" | "desc";
|
|
216
|
+
}>;
|
|
217
|
+
createdAt: number;
|
|
218
|
+
updatedAt: number;
|
|
219
|
+
metadata?: MetadataMap;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export interface ProjectAgentRunFromInvocationFlightInput {
|
|
223
|
+
invocation: InvocationRequest;
|
|
224
|
+
flight?: FlightRecord;
|
|
225
|
+
now?: number;
|
|
226
|
+
source?: AgentRunSource;
|
|
227
|
+
reviewState?: AgentRunReviewState;
|
|
228
|
+
agentRevisionSnapshot?: AgentRevisionSnapshot;
|
|
229
|
+
reviewTaskIds?: ScoutId[];
|
|
230
|
+
artifactIds?: ScoutId[];
|
|
231
|
+
traceSessionIds?: ScoutId[];
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export interface ProjectAgentRunFromInvocationInput {
|
|
235
|
+
/** The merged invocation record, carrying its own execution status. */
|
|
236
|
+
invocation: Invocation;
|
|
237
|
+
now?: number;
|
|
238
|
+
source?: AgentRunSource;
|
|
239
|
+
reviewState?: AgentRunReviewState;
|
|
240
|
+
agentRevisionSnapshot?: AgentRevisionSnapshot;
|
|
241
|
+
reviewTaskIds?: ScoutId[];
|
|
242
|
+
artifactIds?: ScoutId[];
|
|
243
|
+
traceSessionIds?: ScoutId[];
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export function deriveProjectedAgentRunId(input: {
|
|
247
|
+
invocationId: ScoutId;
|
|
248
|
+
flightId?: ScoutId;
|
|
249
|
+
}): ScoutId {
|
|
250
|
+
const flightId = trimString(input.flightId);
|
|
251
|
+
if (flightId) {
|
|
252
|
+
return `run:flight:${flightId}`;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return `run:invocation:${input.invocationId}`;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export function projectAgentRunFromInvocationFlight(
|
|
259
|
+
input: ProjectAgentRunFromInvocationFlightInput,
|
|
260
|
+
): AgentRun {
|
|
261
|
+
const { invocation, flight } = input;
|
|
262
|
+
const agentRevisionSnapshot = input.agentRevisionSnapshot
|
|
263
|
+
?? metadataObject<AgentRevisionSnapshot>(invocation.metadata, "agentRevisionSnapshot");
|
|
264
|
+
const reviewTaskIds = uniqueIds(input.reviewTaskIds ?? metadataIdList(invocation.metadata, "reviewTaskIds"));
|
|
265
|
+
const artifactIds = uniqueIds(input.artifactIds ?? metadataIdList(invocation.metadata, "artifactIds"));
|
|
266
|
+
const traceSessionIds = uniqueIds(input.traceSessionIds ?? metadataIdList(invocation.metadata, "traceSessionIds"));
|
|
267
|
+
const reviewState = inferReviewState({
|
|
268
|
+
explicitReviewState: input.reviewState,
|
|
269
|
+
invocationMetadata: invocation.metadata,
|
|
270
|
+
flightMetadata: flight?.metadata,
|
|
271
|
+
reviewTaskIds,
|
|
272
|
+
});
|
|
273
|
+
const state = projectAgentRunState(flight?.state, reviewState);
|
|
274
|
+
const output = projectOutput(flight);
|
|
275
|
+
const metadata = projectMetadata({
|
|
276
|
+
invocationMetadata: invocation.metadata,
|
|
277
|
+
flightMetadata: flight?.metadata,
|
|
278
|
+
agentRevisionSnapshot,
|
|
279
|
+
});
|
|
280
|
+
const permissionProfile = inferPermissionProfile(invocation, agentRevisionSnapshot);
|
|
281
|
+
const harness = invocation.execution?.harness ?? agentRevisionSnapshot?.runtime?.harness;
|
|
282
|
+
const model = stringMetadata(invocation.metadata, "model")
|
|
283
|
+
?? stringMetadata(flight?.metadata, "model")
|
|
284
|
+
?? agentRevisionSnapshot?.runtime?.model;
|
|
285
|
+
const workId = inferWorkId(invocation);
|
|
286
|
+
const collaborationRecordId = inferCollaborationRecordId(invocation);
|
|
287
|
+
|
|
288
|
+
const run: AgentRun = {
|
|
289
|
+
id: deriveProjectedAgentRunId({
|
|
290
|
+
invocationId: invocation.id,
|
|
291
|
+
flightId: flight?.id,
|
|
292
|
+
}),
|
|
293
|
+
source: input.source ?? inferAgentRunSource(invocation),
|
|
294
|
+
requesterId: invocation.requesterId,
|
|
295
|
+
agentId: invocation.targetAgentId,
|
|
296
|
+
state,
|
|
297
|
+
input: projectInput(invocation),
|
|
298
|
+
createdAt: invocation.createdAt,
|
|
299
|
+
updatedAt: projectUpdatedAt(invocation, flight, input.now),
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
addOptional(run, "agentRevisionId", agentRevisionSnapshot?.id ?? stringMetadata(invocation.metadata, "agentRevisionId"));
|
|
303
|
+
addOptional(run, "agentRevisionSnapshot", agentRevisionSnapshot);
|
|
304
|
+
addOptional(run, "aliasId", stringMetadata(invocation.metadata, "aliasId"));
|
|
305
|
+
addOptional(run, "workId", workId);
|
|
306
|
+
addOptional(run, "collaborationRecordId", collaborationRecordId);
|
|
307
|
+
addOptional(run, "conversationId", invocation.conversationId);
|
|
308
|
+
addOptional(run, "messageId", invocation.messageId);
|
|
309
|
+
addOptional(run, "invocationId", invocation.id);
|
|
310
|
+
addOptional(run, "flightIds", flight ? [flight.id] : undefined);
|
|
311
|
+
addOptional(run, "parentRunId", stringMetadata(invocation.metadata, "parentRunId"));
|
|
312
|
+
addOptional(run, "rootRunId", stringMetadata(invocation.metadata, "rootRunId"));
|
|
313
|
+
addOptional(run, "recipeId", stringMetadata(invocation.metadata, "recipeId"));
|
|
314
|
+
addOptional(run, "attempt", numberMetadata(invocation.metadata, "attempt"));
|
|
315
|
+
addOptional(run, "idempotencyKey", stringMetadata(invocation.metadata, "idempotencyKey"));
|
|
316
|
+
addOptional(run, "reviewState", reviewState);
|
|
317
|
+
addOptional(run, "terminalReason", terminalReason(flight, state));
|
|
318
|
+
addOptional(run, "output", output);
|
|
319
|
+
addOptional(run, "artifactIds", artifactIds.length > 0 ? artifactIds : undefined);
|
|
320
|
+
addOptional(run, "reviewTaskIds", reviewTaskIds.length > 0 ? reviewTaskIds : undefined);
|
|
321
|
+
addOptional(run, "traceSessionIds", traceSessionIds.length > 0 ? traceSessionIds : undefined);
|
|
322
|
+
addOptional(run, "startedAt", flight?.startedAt);
|
|
323
|
+
addOptional(run, "completedAt", flight?.completedAt);
|
|
324
|
+
addOptional(run, "harness", harness);
|
|
325
|
+
addOptional(run, "model", model);
|
|
326
|
+
addOptional(run, "permissionProfile", permissionProfile);
|
|
327
|
+
addOptional(run, "metrics", inferMetrics(invocation.metadata, flight?.metadata));
|
|
328
|
+
addOptional(run, "metadata", metadata);
|
|
329
|
+
|
|
330
|
+
return run;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Project an AgentRun from the merged invocation record (Phase 3's single source
|
|
335
|
+
* of truth), where execution status lives on the invocation itself.
|
|
336
|
+
*
|
|
337
|
+
* Until the storage merge (PR B+) lands, this re-derives the flight view from the
|
|
338
|
+
* invocation's status subset and delegates to
|
|
339
|
+
* {@link projectAgentRunFromInvocationFlight}, so the two projectors stay
|
|
340
|
+
* behavior-identical and the stable `run:flight:<flightId>` id is preserved. A
|
|
341
|
+
* record with no durable flightId projects as an invocation-only run, exactly as
|
|
342
|
+
* the flight-based projector does when no flight is present.
|
|
343
|
+
*/
|
|
344
|
+
export function projectAgentRunFromInvocation(
|
|
345
|
+
input: ProjectAgentRunFromInvocationInput,
|
|
346
|
+
): AgentRun {
|
|
347
|
+
const { invocation } = input;
|
|
348
|
+
const flight: FlightRecord | undefined = invocation.flightId
|
|
349
|
+
? {
|
|
350
|
+
id: invocation.flightId,
|
|
351
|
+
invocationId: invocation.id,
|
|
352
|
+
requesterId: invocation.requesterId,
|
|
353
|
+
targetAgentId: invocation.targetAgentId,
|
|
354
|
+
state: invocation.state ?? "queued",
|
|
355
|
+
summary: invocation.summary,
|
|
356
|
+
output: invocation.output,
|
|
357
|
+
error: invocation.error,
|
|
358
|
+
startedAt: invocation.startedAt,
|
|
359
|
+
completedAt: invocation.completedAt,
|
|
360
|
+
labels: invocation.labels,
|
|
361
|
+
metadata: invocation.metadata,
|
|
362
|
+
}
|
|
363
|
+
: undefined;
|
|
364
|
+
|
|
365
|
+
return projectAgentRunFromInvocationFlight({
|
|
366
|
+
invocation,
|
|
367
|
+
flight,
|
|
368
|
+
now: input.now,
|
|
369
|
+
source: input.source,
|
|
370
|
+
reviewState: input.reviewState,
|
|
371
|
+
agentRevisionSnapshot: input.agentRevisionSnapshot,
|
|
372
|
+
reviewTaskIds: input.reviewTaskIds,
|
|
373
|
+
artifactIds: input.artifactIds,
|
|
374
|
+
traceSessionIds: input.traceSessionIds,
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export function projectAgentRunState(
|
|
379
|
+
flightState: FlightRecord["state"] | string | undefined,
|
|
380
|
+
reviewState?: AgentRunReviewState,
|
|
381
|
+
): AgentRunState {
|
|
382
|
+
if (flightState === "failed") {
|
|
383
|
+
return "failed";
|
|
384
|
+
}
|
|
385
|
+
if (flightState === "cancelled") {
|
|
386
|
+
return "cancelled";
|
|
387
|
+
}
|
|
388
|
+
if (flightState === "completed" && isBlockingReviewState(reviewState)) {
|
|
389
|
+
return "review";
|
|
390
|
+
}
|
|
391
|
+
if (isAgentRunState(flightState)) {
|
|
392
|
+
return flightState;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
return "unknown";
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
function projectInput(invocation: InvocationRequest): MetadataMap {
|
|
399
|
+
const projected: MetadataMap = {
|
|
400
|
+
action: invocation.action,
|
|
401
|
+
task: invocation.task,
|
|
402
|
+
targetAgentId: invocation.targetAgentId,
|
|
403
|
+
requesterNodeId: invocation.requesterNodeId,
|
|
404
|
+
ensureAwake: invocation.ensureAwake,
|
|
405
|
+
stream: invocation.stream,
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
addOptional(projected, "targetNodeId", invocation.targetNodeId);
|
|
409
|
+
addOptional(projected, "timeoutMs", invocation.timeoutMs);
|
|
410
|
+
addOptional(projected, "context", invocation.context);
|
|
411
|
+
addOptional(projected, "execution", invocation.execution);
|
|
412
|
+
addOptional(projected, "metadata", invocation.metadata);
|
|
413
|
+
|
|
414
|
+
return projected;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function projectOutput(flight: FlightRecord | undefined): MetadataMap | undefined {
|
|
418
|
+
if (!flight) {
|
|
419
|
+
return undefined;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
const output: MetadataMap = {};
|
|
423
|
+
addOptional(output, "summary", flight.summary);
|
|
424
|
+
addOptional(output, "text", flight.output);
|
|
425
|
+
addOptional(output, "error", flight.error);
|
|
426
|
+
addOptional(output, "metadata", flight.metadata);
|
|
427
|
+
|
|
428
|
+
return Object.keys(output).length > 0 ? output : undefined;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
function projectMetadata(input: {
|
|
432
|
+
invocationMetadata?: MetadataMap;
|
|
433
|
+
flightMetadata?: MetadataMap;
|
|
434
|
+
agentRevisionSnapshot?: AgentRevisionSnapshot;
|
|
435
|
+
}): MetadataMap | undefined {
|
|
436
|
+
const metadata: MetadataMap = {};
|
|
437
|
+
const rawSource = stringMetadata(input.invocationMetadata, "source");
|
|
438
|
+
|
|
439
|
+
addOptional(metadata, "rawSource", rawSource);
|
|
440
|
+
addOptional(metadata, "invocationMetadata", input.invocationMetadata);
|
|
441
|
+
addOptional(metadata, "flightMetadata", input.flightMetadata);
|
|
442
|
+
addOptional(metadata, "agentRevisionSnapshot", input.agentRevisionSnapshot);
|
|
443
|
+
|
|
444
|
+
return Object.keys(metadata).length > 0 ? metadata : undefined;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function projectUpdatedAt(
|
|
448
|
+
invocation: InvocationRequest,
|
|
449
|
+
flight: FlightRecord | undefined,
|
|
450
|
+
now: number | undefined,
|
|
451
|
+
): number {
|
|
452
|
+
if (flight?.completedAt !== undefined) {
|
|
453
|
+
return flight.completedAt;
|
|
454
|
+
}
|
|
455
|
+
if (now !== undefined) {
|
|
456
|
+
return now;
|
|
457
|
+
}
|
|
458
|
+
if (flight?.startedAt !== undefined) {
|
|
459
|
+
return flight.startedAt;
|
|
460
|
+
}
|
|
461
|
+
return invocation.createdAt;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
function inferAgentRunSource(invocation: InvocationRequest): AgentRunSource {
|
|
465
|
+
const explicit = stringMetadata(invocation.metadata, "agentRunSource")
|
|
466
|
+
?? stringMetadata(invocation.metadata, "runSource");
|
|
467
|
+
if (isAgentRunSource(explicit)) {
|
|
468
|
+
return explicit;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
const rawSource = stringMetadata(invocation.metadata, "source");
|
|
472
|
+
if (isAgentRunSource(rawSource)) {
|
|
473
|
+
return rawSource;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
switch (rawSource) {
|
|
477
|
+
case "collaboration-record":
|
|
478
|
+
return "ask";
|
|
479
|
+
case "broker-deliver":
|
|
480
|
+
return "message";
|
|
481
|
+
case "scout-app":
|
|
482
|
+
return invocation.messageId ? "message" : "manual";
|
|
483
|
+
case "scout-cli":
|
|
484
|
+
return invocation.messageId ? "message" : "ask";
|
|
485
|
+
default:
|
|
486
|
+
break;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
if (
|
|
490
|
+
invocation.collaborationRecordId
|
|
491
|
+
|| metadataObject(invocation.context, "collaboration")
|
|
492
|
+
|| stringMetadata(invocation.context, "collaborationRecordId")
|
|
493
|
+
) {
|
|
494
|
+
return "ask";
|
|
495
|
+
}
|
|
496
|
+
if (invocation.messageId || invocation.conversationId) {
|
|
497
|
+
return "message";
|
|
498
|
+
}
|
|
499
|
+
if (invocation.action === "wake") {
|
|
500
|
+
return "manual";
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
return "ask";
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
function inferReviewState(input: {
|
|
507
|
+
explicitReviewState?: AgentRunReviewState;
|
|
508
|
+
invocationMetadata?: MetadataMap;
|
|
509
|
+
flightMetadata?: MetadataMap;
|
|
510
|
+
reviewTaskIds: ScoutId[];
|
|
511
|
+
}): AgentRunReviewState | undefined {
|
|
512
|
+
if (input.explicitReviewState) {
|
|
513
|
+
return input.explicitReviewState;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
const metadataReviewState = stringMetadata(input.flightMetadata, "reviewState")
|
|
517
|
+
?? stringMetadata(input.invocationMetadata, "reviewState");
|
|
518
|
+
if (isAgentRunReviewState(metadataReviewState)) {
|
|
519
|
+
return metadataReviewState;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
if (
|
|
523
|
+
input.reviewTaskIds.length > 0
|
|
524
|
+
|| booleanMetadata(input.flightMetadata, "reviewNeeded")
|
|
525
|
+
|| booleanMetadata(input.flightMetadata, "needsReview")
|
|
526
|
+
|| booleanMetadata(input.flightMetadata, "requiresReview")
|
|
527
|
+
|| booleanMetadata(input.invocationMetadata, "reviewNeeded")
|
|
528
|
+
|| booleanMetadata(input.invocationMetadata, "needsReview")
|
|
529
|
+
|| booleanMetadata(input.invocationMetadata, "requiresReview")
|
|
530
|
+
) {
|
|
531
|
+
return "needed";
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
return undefined;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
function inferPermissionProfile(
|
|
538
|
+
invocation: InvocationRequest,
|
|
539
|
+
agentRevisionSnapshot: AgentRevisionSnapshot | undefined,
|
|
540
|
+
): ScoutPermissionProfile | undefined {
|
|
541
|
+
return invocation.execution?.permissionProfile
|
|
542
|
+
?? normalizeScoutPermissionProfile(stringMetadata(invocation.metadata, "permissionProfile"))
|
|
543
|
+
?? normalizeScoutPermissionProfile(agentRevisionSnapshot?.permissions?.permissionProfile);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
function inferMetrics(
|
|
547
|
+
invocationMetadata: MetadataMap | undefined,
|
|
548
|
+
flightMetadata: MetadataMap | undefined,
|
|
549
|
+
): AgentRunMetrics | undefined {
|
|
550
|
+
const metrics = metadataObject(flightMetadata, "metrics")
|
|
551
|
+
?? metadataObject(invocationMetadata, "metrics");
|
|
552
|
+
if (!metrics) {
|
|
553
|
+
return undefined;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
const projected: AgentRunMetrics = {};
|
|
557
|
+
addOptional(projected, "inputTokens", numberMetadata(metrics, "inputTokens"));
|
|
558
|
+
addOptional(projected, "outputTokens", numberMetadata(metrics, "outputTokens"));
|
|
559
|
+
addOptional(projected, "totalTokens", numberMetadata(metrics, "totalTokens"));
|
|
560
|
+
addOptional(projected, "estimatedUsd", numberMetadata(metrics, "estimatedUsd"));
|
|
561
|
+
addOptional(projected, "wallClockMs", numberMetadata(metrics, "wallClockMs"));
|
|
562
|
+
addOptional(projected, "toolCallCount", numberMetadata(metrics, "toolCallCount"));
|
|
563
|
+
addOptional(projected, "retryCount", numberMetadata(metrics, "retryCount"));
|
|
564
|
+
|
|
565
|
+
return Object.keys(projected).length > 0 ? projected : undefined;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
function inferWorkId(invocation: InvocationRequest): ScoutId | undefined {
|
|
569
|
+
return stringMetadata(invocation.metadata, "workId")
|
|
570
|
+
?? stringMetadata(invocation.context, "workId")
|
|
571
|
+
?? inferCollaborationWorkId(invocation);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
function inferCollaborationRecordId(invocation: InvocationRequest): ScoutId | undefined {
|
|
575
|
+
return invocation.collaborationRecordId
|
|
576
|
+
?? stringMetadata(invocation.metadata, "collaborationRecordId")
|
|
577
|
+
?? stringMetadata(invocation.context, "collaborationRecordId")
|
|
578
|
+
?? stringMetadata(metadataObject(invocation.context, "collaboration"), "recordId");
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
function inferCollaborationWorkId(invocation: InvocationRequest): ScoutId | undefined {
|
|
582
|
+
const collaboration = metadataObject(invocation.context, "collaboration");
|
|
583
|
+
const collaborationKind = stringMetadata(invocation.metadata, "collaborationRecordKind")
|
|
584
|
+
?? stringMetadata(invocation.context, "collaborationRecordKind")
|
|
585
|
+
?? stringMetadata(collaboration, "kind")
|
|
586
|
+
?? stringMetadata(collaboration, "recordKind");
|
|
587
|
+
if (collaborationKind !== "work_item") {
|
|
588
|
+
return undefined;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
return invocation.collaborationRecordId
|
|
592
|
+
?? stringMetadata(invocation.metadata, "collaborationRecordId")
|
|
593
|
+
?? stringMetadata(invocation.context, "collaborationRecordId")
|
|
594
|
+
?? stringMetadata(collaboration, "recordId");
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
function terminalReason(
|
|
598
|
+
flight: FlightRecord | undefined,
|
|
599
|
+
state: AgentRunState,
|
|
600
|
+
): string | undefined {
|
|
601
|
+
if (!flight || (state !== "failed" && state !== "cancelled")) {
|
|
602
|
+
return undefined;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
return trimString(flight.error) ?? trimString(flight.summary);
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
function isBlockingReviewState(state: AgentRunReviewState | undefined): boolean {
|
|
609
|
+
return state === "needed" || state === "blocked";
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
function isAgentRunState(value: unknown): value is AgentRunState {
|
|
613
|
+
return typeof value === "string" && AGENT_RUN_STATES.includes(value as AgentRunState);
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
function isAgentRunSource(value: unknown): value is AgentRunSource {
|
|
617
|
+
return typeof value === "string" && AGENT_RUN_SOURCES.includes(value as AgentRunSource);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
function isAgentRunReviewState(value: unknown): value is AgentRunReviewState {
|
|
621
|
+
return typeof value === "string" && AGENT_RUN_REVIEW_STATES.includes(value as AgentRunReviewState);
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
function metadataObject<T extends object = MetadataMap>(
|
|
625
|
+
metadata: MetadataMap | undefined,
|
|
626
|
+
key: string,
|
|
627
|
+
): T | undefined {
|
|
628
|
+
const value = metadata?.[key];
|
|
629
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value as T : undefined;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
function stringMetadata(metadata: MetadataMap | undefined, key: string): string | undefined {
|
|
633
|
+
const value = metadata?.[key];
|
|
634
|
+
return trimString(typeof value === "string" ? value : undefined);
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
function numberMetadata(metadata: MetadataMap | undefined, key: string): number | undefined {
|
|
638
|
+
const value = metadata?.[key];
|
|
639
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
function booleanMetadata(metadata: MetadataMap | undefined, key: string): boolean {
|
|
643
|
+
return metadata?.[key] === true;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
function metadataIdList(metadata: MetadataMap | undefined, key: string): ScoutId[] {
|
|
647
|
+
const value = metadata?.[key];
|
|
648
|
+
if (Array.isArray(value)) {
|
|
649
|
+
return value
|
|
650
|
+
.map((item) => trimString(typeof item === "string" ? item : undefined))
|
|
651
|
+
.filter((item): item is string => Boolean(item));
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
const single = trimString(typeof value === "string" ? value : undefined);
|
|
655
|
+
return single ? [single] : [];
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
function uniqueIds(ids: ScoutId[]): ScoutId[] {
|
|
659
|
+
return [...new Set(ids.map((id) => id.trim()).filter(Boolean))];
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
function trimString(value: string | undefined): string | undefined {
|
|
663
|
+
const trimmed = value?.trim();
|
|
664
|
+
return trimmed ? trimmed : undefined;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
function addOptional<T extends object, K extends keyof T>(
|
|
668
|
+
target: T,
|
|
669
|
+
key: K,
|
|
670
|
+
value: T[K] | undefined,
|
|
671
|
+
): void {
|
|
672
|
+
if (value !== undefined) {
|
|
673
|
+
target[key] = value;
|
|
674
|
+
}
|
|
675
|
+
}
|