@sentry/junior 0.203.0 → 0.205.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/dist/agent-D4nu8MQV.js +17521 -0
- package/dist/agent-hooks-DXHpTJ4m.js +4042 -0
- package/dist/agent-runner-C04colea.js +678 -0
- package/dist/api/schema.d.ts +2736 -2639
- package/dist/api/schema.js +4 -169
- package/dist/api.d.ts +23 -17
- package/dist/api.js +3881 -5326
- package/dist/app-Cb776lL8.d.ts +247 -0
- package/dist/app.d.ts +4 -520
- package/dist/app.js +9524 -11875
- package/dist/auth-pause-state-C2P3guS1.js +168 -0
- package/dist/catalog-runtime-CXw3asJD.js +7 -0
- package/dist/checkpoint-CrViJ8Ps.js +2450 -0
- package/dist/cli/chat.d.ts +20 -0
- package/dist/cli/chat.js +229 -336
- package/dist/cli/check.d.ts +8 -0
- package/dist/cli/check.js +513 -806
- package/dist/cli/env.d.ts +13 -0
- package/dist/cli/env.js +63 -12
- package/dist/cli/init.d.ts +3 -0
- package/dist/cli/init.js +90 -159
- package/dist/cli/main.d.ts +6 -0
- package/dist/cli/main.js +43 -64
- package/dist/cli/plugins.d.ts +13 -0
- package/dist/cli/plugins.js +148 -227
- package/dist/cli/run.d.ts +16 -0
- package/dist/cli/run.js +52 -8
- package/dist/cli/snapshot-create.d.ts +4 -0
- package/dist/cli/snapshot-create.js +71 -125
- package/dist/cli/upgrade.d.ts +15 -0
- package/dist/cli/upgrade.js +232 -335
- package/dist/config-BOtJQ7Pc.js +941 -0
- package/dist/context-B45_WqVX.js +298 -0
- package/dist/conversation-privacy-BZRA6Pes.js +182 -0
- package/dist/conversation-work-C6y3T5Hx.js +51 -0
- package/dist/credential-sync-Bep34IB_.js +2661 -0
- package/dist/db-BeyXKJOI.d.ts +5 -0
- package/dist/destinations-BeBiJeEM.js +29 -0
- package/dist/execution-stats-B6lgWxCK.js +373 -0
- package/dist/executor-BlUhFL7_.js +721 -0
- package/dist/experimental-CIXf7Uye.js +46 -0
- package/dist/history-ClE4toxe.d.ts +32 -0
- package/dist/history-CqTuSAdI.js +441 -0
- package/dist/instrumentation.d.ts +3 -3
- package/dist/instrumentation.js +130 -176
- package/dist/job-queue-DLMqIK74.js +63 -0
- package/dist/logging-BMJzdDlP.js +1210 -0
- package/dist/model-profile-CZmVoGdX.js +49 -0
- package/dist/nitro.d.ts +31 -36
- package/dist/nitro.js +275 -456
- package/dist/oauth-callback-server-WwG5_Zgm.js +130 -0
- package/dist/oauth-relay-CdCnu80W.js +62 -0
- package/dist/package-discovery-7a9YqLhE.js +455 -0
- package/dist/pending-auth-CUbXq06G.js +185 -0
- package/dist/plugin-module-BKGOXca2.js +81 -0
- package/dist/plugins-BI9A1vKA.d.ts +95 -0
- package/dist/plugins-egKWjgue.js +99 -0
- package/dist/private-trace-result-BLvBjy_e.js +16 -0
- package/dist/profile-T0tXE4zu.js +861 -0
- package/dist/registry-BA0__8ai.js +1419 -0
- package/dist/reporting-schema-DosTN__Q.js +105 -0
- package/dist/resolve-bvD1ORdv.js +546 -0
- package/dist/rolldown-runtime-B4FMCO8f.js +28 -0
- package/dist/runner-BXYxfIUL.js +392 -0
- package/dist/sandbox-egress-signals-ngEPjSEW.js +46 -0
- package/dist/schema-Rn8-XEaN.js +1140 -0
- package/dist/sentry-CD3SdJl-.js +26 -0
- package/dist/skills-DJOlYdBs.js +316 -0
- package/dist/spawn-h0R1bTEo.js +29 -0
- package/dist/stats-3YZn-Swi.js +2648 -0
- package/dist/store-C5qxF2ac.d.ts +208 -0
- package/dist/task-queue-CoXwd2eq.js +136 -0
- package/dist/task-runner-B2_mJZj0.js +639 -0
- package/dist/thread-state-CqZ1m-es.js +431 -0
- package/dist/turn-execution-fI6PZ0iI.js +47 -0
- package/dist/turn-lifecycle-CcnwrOcp.js +54 -0
- package/dist/usage-B5SfMb3H.js +296 -0
- package/dist/usage-schema-CKaDkH_j.js +20 -0
- package/dist/validation-DfWcvhuS.js +40 -0
- package/dist/vercel-queue-DIkVcfK4.js +167 -0
- package/dist/vercel.d.ts +6 -6
- package/dist/vercel.js +14 -6
- package/dist/version-CnXZ614E.d.ts +5 -0
- package/dist/version-oD-oPrbO.js +8 -0
- package/dist/version.d.ts +2 -4
- package/dist/version.js +2 -6
- package/dist/web-authorization-Crbzlmzo.js +76 -0
- package/dist/web-input-BOuq3oKK.js +494 -0
- package/dist/work-B91LQKHr.js +509 -0
- package/dist/worker-BcRRTe6k.js +625 -0
- package/package.json +9 -9
- package/dist/agent-hooks-GB2VPTNA.js +0 -51
- package/dist/catalog-runtime-UBLIWD3O.js +0 -14
- package/dist/chunk-2LYHWMR4.js +0 -46
- package/dist/chunk-352OWAZH.js +0 -320
- package/dist/chunk-3Y47VMHV.js +0 -6
- package/dist/chunk-3YJSKOWF.js +0 -164
- package/dist/chunk-4KSSKTQ5.js +0 -229
- package/dist/chunk-4UO6FK4G.js +0 -64
- package/dist/chunk-5AHX53NQ.js +0 -717
- package/dist/chunk-5J3E5FWA.js +0 -700
- package/dist/chunk-5PDAG6O3.js +0 -206
- package/dist/chunk-6Y5B5PEX.js +0 -80
- package/dist/chunk-7GWQ5S5R.js +0 -2086
- package/dist/chunk-7H2VZTWN.js +0 -103
- package/dist/chunk-7NL7T6VU.js +0 -406
- package/dist/chunk-A5L27LE4.js +0 -387
- package/dist/chunk-ADIAWL34.js +0 -81
- package/dist/chunk-ASTEMBKJ.js +0 -519
- package/dist/chunk-CEMMLV5L.js +0 -98
- package/dist/chunk-CM5HNV2W.js +0 -131
- package/dist/chunk-CRTRBBRI.js +0 -105
- package/dist/chunk-DA2KGZZI.js +0 -13
- package/dist/chunk-DIB4GX3G.js +0 -8
- package/dist/chunk-DKIJ2RP5.js +0 -68
- package/dist/chunk-DWPN6SCH.js +0 -172
- package/dist/chunk-EDKUFGPL.js +0 -64
- package/dist/chunk-ENY6SKIU.js +0 -1228
- package/dist/chunk-F4MGCZOX.js +0 -2943
- package/dist/chunk-FA6POGLH.js +0 -70
- package/dist/chunk-FSUR7GTG.js +0 -20475
- package/dist/chunk-GKEOHJL5.js +0 -1856
- package/dist/chunk-GMCB6W5Y.js +0 -333
- package/dist/chunk-IE2VPG7O.js +0 -1135
- package/dist/chunk-IZ5B5IHQ.js +0 -3656
- package/dist/chunk-JAL3CH4G.js +0 -27
- package/dist/chunk-KIIEUXD3.js +0 -1764
- package/dist/chunk-KXU4NIL7.js +0 -692
- package/dist/chunk-MTM5IFCY.js +0 -1190
- package/dist/chunk-N7TMSOZH.js +0 -235
- package/dist/chunk-NCEBK6PH.js +0 -36
- package/dist/chunk-NHJU2ZAL.js +0 -56
- package/dist/chunk-P6KTRNVC.js +0 -321
- package/dist/chunk-PDO5BLNM.js +0 -22
- package/dist/chunk-PDRNLLFT.js +0 -3295
- package/dist/chunk-PEQXYSSE.js +0 -45
- package/dist/chunk-PKEX2AQX.js +0 -198
- package/dist/chunk-PSJCGIGO.js +0 -1163
- package/dist/chunk-PZUSUL55.js +0 -506
- package/dist/chunk-R45M4TUS.js +0 -37
- package/dist/chunk-RC745GGZ.js +0 -122
- package/dist/chunk-SP3QKZXJ.js +0 -820
- package/dist/chunk-TXKUKMVO.js +0 -417
- package/dist/chunk-UE4GPWSD.js +0 -931
- package/dist/chunk-UIE3R5XU.js +0 -17
- package/dist/chunk-UXPG6ZIN.js +0 -84
- package/dist/chunk-VFUK3X5B.js +0 -50
- package/dist/chunk-VNMJWREK.js +0 -787
- package/dist/chunk-VZ7CSOX2.js +0 -706
- package/dist/chunk-WCNQJKFT.js +0 -10
- package/dist/chunk-WDZR3QQM.js +0 -135
- package/dist/chunk-WLYVJCHV.js +0 -1433
- package/dist/chunk-WS7NAFTM.js +0 -1520
- package/dist/chunk-X6GDDWQH.js +0 -60
- package/dist/chunk-XPDEYNQI.js +0 -102
- package/dist/chunk-XRW44VGM.js +0 -58
- package/dist/chunk-Y2CM7HXH.js +0 -111
- package/dist/chunk-Y7X25LFY.js +0 -15
- package/dist/conversation-work-VIOQ5ZF3.js +0 -54
- package/dist/db-NGDJV7YH.js +0 -26
- package/dist/discovery-DWVDM7UK.js +0 -44
- package/dist/experimental-P5FZM4CU.js +0 -12
- package/dist/oauth-callback-server-YFY7YEGK.js +0 -243
- package/dist/oauth-relay-5XPVRPYB.js +0 -8
- package/dist/plugins-YTYJMMJF.js +0 -14
- package/dist/runner-ORTNSB2Q.js +0 -522
- package/dist/sandbox-egress-signals-FIL7EGPR.js +0 -73
- package/dist/sentry-MB3NL3IR.js +0 -42
- package/dist/skills-H376WQOH.js +0 -27
- package/dist/spawn-T43WHLOS.js +0 -42
- package/dist/task-runner-LBZWF32V.js +0 -36
- package/dist/validation-REJLRKI6.js +0 -17
- package/dist/work-3KJ3RE76.js +0 -51
- package/dist/worker-QFEBU72E.js +0 -24
package/dist/chunk-SP3QKZXJ.js
DELETED
|
@@ -1,820 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
coerceThreadConversationState,
|
|
3
|
-
getPersistedThreadState
|
|
4
|
-
} from "./chunk-ASTEMBKJ.js";
|
|
5
|
-
import {
|
|
6
|
-
recordTaskExecution
|
|
7
|
-
} from "./chunk-PZUSUL55.js";
|
|
8
|
-
import {
|
|
9
|
-
pluginTaskId,
|
|
10
|
-
pluginTaskParamsSchema,
|
|
11
|
-
sendVercelPluginTask
|
|
12
|
-
} from "./chunk-3YJSKOWF.js";
|
|
13
|
-
import {
|
|
14
|
-
getPiMessageRole,
|
|
15
|
-
getTurnRecord,
|
|
16
|
-
hydrateConversationMessages,
|
|
17
|
-
instructionTextForProjection,
|
|
18
|
-
isToolResultError,
|
|
19
|
-
isToolResultMessage,
|
|
20
|
-
normalizeToolNameFromResult,
|
|
21
|
-
stripRuntimeTurnContext
|
|
22
|
-
} from "./chunk-F4MGCZOX.js";
|
|
23
|
-
import {
|
|
24
|
-
createPluginConversationEvents,
|
|
25
|
-
createPluginEmbedder,
|
|
26
|
-
createPluginLogger,
|
|
27
|
-
createPluginModel,
|
|
28
|
-
createPluginState,
|
|
29
|
-
getPlugins,
|
|
30
|
-
readActorIdentity
|
|
31
|
-
} from "./chunk-IZ5B5IHQ.js";
|
|
32
|
-
import {
|
|
33
|
-
JUNIOR_THREAD_STATE_TTL_MS
|
|
34
|
-
} from "./chunk-3Y47VMHV.js";
|
|
35
|
-
import {
|
|
36
|
-
getConversationStore,
|
|
37
|
-
getDb
|
|
38
|
-
} from "./chunk-GKEOHJL5.js";
|
|
39
|
-
import {
|
|
40
|
-
getStateAdapter
|
|
41
|
-
} from "./chunk-P6KTRNVC.js";
|
|
42
|
-
import {
|
|
43
|
-
sameActorIdentity
|
|
44
|
-
} from "./chunk-7NL7T6VU.js";
|
|
45
|
-
import {
|
|
46
|
-
credentialSubjectSchema
|
|
47
|
-
} from "./chunk-CEMMLV5L.js";
|
|
48
|
-
import {
|
|
49
|
-
parseSlackMessageTs
|
|
50
|
-
} from "./chunk-N7TMSOZH.js";
|
|
51
|
-
|
|
52
|
-
// src/chat/plugins/task-runner.ts
|
|
53
|
-
import { pluginRunContextSchema } from "@sentry/junior-plugin-api";
|
|
54
|
-
|
|
55
|
-
// src/chat/services/turn-session-routing.ts
|
|
56
|
-
async function loadConversationChain(conversationId, conversationStore) {
|
|
57
|
-
const chain = [];
|
|
58
|
-
const seen = /* @__PURE__ */ new Set();
|
|
59
|
-
let cursor = conversationId;
|
|
60
|
-
while (cursor && !seen.has(cursor)) {
|
|
61
|
-
seen.add(cursor);
|
|
62
|
-
const conversation = await conversationStore.get({
|
|
63
|
-
conversationId: cursor
|
|
64
|
-
});
|
|
65
|
-
if (!conversation) {
|
|
66
|
-
break;
|
|
67
|
-
}
|
|
68
|
-
chain.push(conversation);
|
|
69
|
-
cursor = conversation.parentConversationId;
|
|
70
|
-
}
|
|
71
|
-
return chain;
|
|
72
|
-
}
|
|
73
|
-
function slackSourceForDestination(args) {
|
|
74
|
-
if (args.source?.kind !== "slack" || args.source.channelId !== args.destination.channelId) {
|
|
75
|
-
return void 0;
|
|
76
|
-
}
|
|
77
|
-
const threadTs = args.source.threadTs?.trim();
|
|
78
|
-
return {
|
|
79
|
-
kind: "slack",
|
|
80
|
-
visibility: args.source.visibility ?? "public",
|
|
81
|
-
teamId: args.source.teamId?.trim() || args.destination.teamId,
|
|
82
|
-
channelId: args.source.channelId,
|
|
83
|
-
...threadTs ? { threadTs } : void 0
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
async function resolveConversationRouting(args) {
|
|
87
|
-
const conversationStore = args.conversationStore ?? (await import("./db-NGDJV7YH.js")).getConversationStore();
|
|
88
|
-
const chain = await loadConversationChain(
|
|
89
|
-
args.conversationId,
|
|
90
|
-
conversationStore
|
|
91
|
-
);
|
|
92
|
-
let destination;
|
|
93
|
-
let source;
|
|
94
|
-
let location;
|
|
95
|
-
for (const conversation of chain) {
|
|
96
|
-
destination ??= conversation.destination;
|
|
97
|
-
source ??= conversation.sessionSource;
|
|
98
|
-
location ??= conversation.location;
|
|
99
|
-
if (destination && source) {
|
|
100
|
-
break;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
if (!destination) {
|
|
104
|
-
return void 0;
|
|
105
|
-
}
|
|
106
|
-
if (destination.platform === "slack") {
|
|
107
|
-
const slackSource = slackSourceForDestination({ destination, source });
|
|
108
|
-
return {
|
|
109
|
-
destination,
|
|
110
|
-
...location ? { location } : void 0,
|
|
111
|
-
...slackSource ? { source: slackSource } : void 0
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
return {
|
|
115
|
-
destination,
|
|
116
|
-
...location ? { location } : void 0,
|
|
117
|
-
...source ? { source } : void 0
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
async function resolveTurnSessionRouting(args) {
|
|
121
|
-
const routing = await resolveConversationRouting(args);
|
|
122
|
-
if (!routing?.destination || !routing.source) {
|
|
123
|
-
throw new Error(
|
|
124
|
-
`Conversation ${args.conversationId} is missing durable routing metadata`
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
return {
|
|
128
|
-
destination: routing.destination,
|
|
129
|
-
...routing.location ? { location: routing.location } : void 0,
|
|
130
|
-
source: routing.source
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// src/chat/agent-dispatch/store.ts
|
|
135
|
-
import { createHash } from "crypto";
|
|
136
|
-
import {
|
|
137
|
-
destinationSchema,
|
|
138
|
-
destinationVisibilitySchema,
|
|
139
|
-
isSlackDestination,
|
|
140
|
-
replyAttributionSchema,
|
|
141
|
-
sourceSchema
|
|
142
|
-
} from "@sentry/junior-plugin-api";
|
|
143
|
-
import { z } from "zod";
|
|
144
|
-
var DISPATCH_PREFIX = "junior:agent_dispatch";
|
|
145
|
-
var DISPATCH_LOCK_TTL_MS = 10 * 60 * 1e3;
|
|
146
|
-
var DISPATCH_MAILBOX_APPEND_INDEX_LOCK_TTL_MS = 1e4;
|
|
147
|
-
var DISPATCH_MAILBOX_APPEND_INDEX_MAX_LENGTH = 1e4;
|
|
148
|
-
var nonEmptyExactStringSchema = z.string().min(1).refine(
|
|
149
|
-
(value) => value === value.trim() && value.toLowerCase() !== "unknown"
|
|
150
|
-
);
|
|
151
|
-
var pendingDispatchMailboxAppendIndexSchema = z.array(
|
|
152
|
-
nonEmptyExactStringSchema
|
|
153
|
-
);
|
|
154
|
-
var dispatchStatusSchema = z.enum([
|
|
155
|
-
"pending",
|
|
156
|
-
"running",
|
|
157
|
-
"awaiting_resume",
|
|
158
|
-
"completed",
|
|
159
|
-
"failed",
|
|
160
|
-
"blocked"
|
|
161
|
-
]);
|
|
162
|
-
var dispatchActorSchema = z.object({
|
|
163
|
-
platform: z.literal("system"),
|
|
164
|
-
name: nonEmptyExactStringSchema
|
|
165
|
-
}).strict();
|
|
166
|
-
var dispatchRecordSchema = z.object({
|
|
167
|
-
actor: dispatchActorSchema,
|
|
168
|
-
createdAtMs: z.number().finite(),
|
|
169
|
-
credentialSubject: credentialSubjectSchema.optional(),
|
|
170
|
-
destination: destinationSchema,
|
|
171
|
-
destinationVisibility: destinationVisibilitySchema,
|
|
172
|
-
errorMessage: z.string().optional(),
|
|
173
|
-
id: nonEmptyExactStringSchema,
|
|
174
|
-
idempotencyKey: z.string().min(1),
|
|
175
|
-
input: z.string().min(1),
|
|
176
|
-
metadata: z.record(z.string(), z.string()).optional(),
|
|
177
|
-
plugin: nonEmptyExactStringSchema,
|
|
178
|
-
replyAttribution: replyAttributionSchema.optional(),
|
|
179
|
-
resultMessageTs: z.string().optional(),
|
|
180
|
-
source: sourceSchema,
|
|
181
|
-
status: dispatchStatusSchema,
|
|
182
|
-
updatedAtMs: z.number().finite()
|
|
183
|
-
}).strict().superRefine((record, ctx) => {
|
|
184
|
-
if (!isSlackDestination(record.destination)) {
|
|
185
|
-
ctx.addIssue({
|
|
186
|
-
code: z.ZodIssueCode.custom,
|
|
187
|
-
message: "Dispatch destination platform must be slack",
|
|
188
|
-
path: ["destination"]
|
|
189
|
-
});
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
const subject = record.credentialSubject;
|
|
193
|
-
if (!subject) {
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
if (subject.allowedWhen === "private-direct-conversation") {
|
|
197
|
-
if (!record.destination.channelId.startsWith("D")) {
|
|
198
|
-
ctx.addIssue({
|
|
199
|
-
code: z.ZodIssueCode.custom,
|
|
200
|
-
message: "Dispatch credentialSubject requires a private direct Slack destination",
|
|
201
|
-
path: ["credentialSubject"]
|
|
202
|
-
});
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
if (subject.binding.type !== "slack-direct-conversation" || subject.binding.teamId !== record.destination.teamId || subject.binding.channelId !== record.destination.channelId) {
|
|
206
|
-
ctx.addIssue({
|
|
207
|
-
code: z.ZodIssueCode.custom,
|
|
208
|
-
message: "Dispatch credentialSubject binding must match destination",
|
|
209
|
-
path: ["credentialSubject", "binding"]
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
if (subject.binding.type !== subject.allowedWhen || subject.binding.plugin !== record.plugin || subject.binding.taskId !== subject.taskId) {
|
|
215
|
-
ctx.addIssue({
|
|
216
|
-
code: z.ZodIssueCode.custom,
|
|
217
|
-
message: "Dispatch credentialSubject binding must match task",
|
|
218
|
-
path: ["credentialSubject", "binding"]
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
});
|
|
222
|
-
function getDispatchStorageKey(id) {
|
|
223
|
-
return `${DISPATCH_PREFIX}:record:${id}`;
|
|
224
|
-
}
|
|
225
|
-
function dispatchLockKey(id) {
|
|
226
|
-
return `${DISPATCH_PREFIX}:lock:${id}`;
|
|
227
|
-
}
|
|
228
|
-
function pendingDispatchMailboxAppendIndexKey() {
|
|
229
|
-
return `${DISPATCH_PREFIX}:incomplete`;
|
|
230
|
-
}
|
|
231
|
-
function pendingDispatchMailboxAppendIndexLockKey() {
|
|
232
|
-
return `${DISPATCH_PREFIX}:incomplete:lock`;
|
|
233
|
-
}
|
|
234
|
-
function normalizeMetadata(metadata) {
|
|
235
|
-
if (!metadata) {
|
|
236
|
-
return void 0;
|
|
237
|
-
}
|
|
238
|
-
const entries = Object.entries(metadata).filter(
|
|
239
|
-
(entry) => typeof entry[0] === "string" && typeof entry[1] === "string"
|
|
240
|
-
);
|
|
241
|
-
return entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
242
|
-
}
|
|
243
|
-
function buildDispatchId(plugin, idempotencyKey) {
|
|
244
|
-
const digest = createHash("sha256").update(plugin).update("\0").update(idempotencyKey).digest("hex").slice(0, 32);
|
|
245
|
-
return `dispatch_${digest}`;
|
|
246
|
-
}
|
|
247
|
-
function parseDispatchRecord(value) {
|
|
248
|
-
const parsed = dispatchRecordSchema.safeParse(value);
|
|
249
|
-
return parsed.success ? parsed.data : void 0;
|
|
250
|
-
}
|
|
251
|
-
function getDispatchConversationId(dispatch) {
|
|
252
|
-
return `agent-dispatch:${dispatch.id}`;
|
|
253
|
-
}
|
|
254
|
-
function getDispatchInputMessageId(dispatchId) {
|
|
255
|
-
return `agent-dispatch:${dispatchId}`;
|
|
256
|
-
}
|
|
257
|
-
function getDispatchTurnId(dispatchId) {
|
|
258
|
-
return `dispatch:${dispatchId}`;
|
|
259
|
-
}
|
|
260
|
-
function toDispatchProjection(record) {
|
|
261
|
-
return {
|
|
262
|
-
id: record.id,
|
|
263
|
-
status: record.status,
|
|
264
|
-
...record.resultMessageTs ? { resultMessageTs: record.resultMessageTs } : void 0,
|
|
265
|
-
...record.errorMessage ? { errorMessage: record.errorMessage } : void 0
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
function isTerminalDispatchStatus(status) {
|
|
269
|
-
return status === "completed" || status === "failed" || status === "blocked";
|
|
270
|
-
}
|
|
271
|
-
async function withDispatchLock(dispatchId, task) {
|
|
272
|
-
const state = getStateAdapter();
|
|
273
|
-
await state.connect();
|
|
274
|
-
const lock = await state.acquireLock(
|
|
275
|
-
dispatchLockKey(dispatchId),
|
|
276
|
-
DISPATCH_LOCK_TTL_MS
|
|
277
|
-
);
|
|
278
|
-
if (!lock) {
|
|
279
|
-
throw new Error(`Could not acquire dispatch lock for ${dispatchId}`);
|
|
280
|
-
}
|
|
281
|
-
try {
|
|
282
|
-
return await task(state);
|
|
283
|
-
} finally {
|
|
284
|
-
await state.releaseLock(lock);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
async function putRecord(state, record) {
|
|
288
|
-
const parsed = dispatchRecordSchema.safeParse(record);
|
|
289
|
-
if (!parsed.success) {
|
|
290
|
-
throw new Error(
|
|
291
|
-
`Dispatch record is invalid: ${parsed.error.issues.map((issue) => `${issue.path.join(".") || "<root>"} ${issue.message}`).join("; ")}`
|
|
292
|
-
);
|
|
293
|
-
}
|
|
294
|
-
const next = parsed.data;
|
|
295
|
-
await state.set(
|
|
296
|
-
getDispatchStorageKey(next.id),
|
|
297
|
-
next,
|
|
298
|
-
JUNIOR_THREAD_STATE_TTL_MS
|
|
299
|
-
);
|
|
300
|
-
}
|
|
301
|
-
async function updatePendingDispatchMailboxAppendIndex(state, update) {
|
|
302
|
-
const lock = await state.acquireLock(
|
|
303
|
-
pendingDispatchMailboxAppendIndexLockKey(),
|
|
304
|
-
DISPATCH_MAILBOX_APPEND_INDEX_LOCK_TTL_MS
|
|
305
|
-
);
|
|
306
|
-
if (!lock) {
|
|
307
|
-
throw new Error("Could not acquire dispatch mailbox append index lock");
|
|
308
|
-
}
|
|
309
|
-
try {
|
|
310
|
-
const stored = await state.get(pendingDispatchMailboxAppendIndexKey());
|
|
311
|
-
const ids = stored === void 0 || stored === null ? [] : pendingDispatchMailboxAppendIndexSchema.parse(stored);
|
|
312
|
-
const next = [...new Set(update([...new Set(ids)]))].slice(
|
|
313
|
-
-DISPATCH_MAILBOX_APPEND_INDEX_MAX_LENGTH
|
|
314
|
-
);
|
|
315
|
-
if (next.length === ids.length && next.every((id, index) => id === ids[index])) {
|
|
316
|
-
return;
|
|
317
|
-
}
|
|
318
|
-
await state.set(
|
|
319
|
-
pendingDispatchMailboxAppendIndexKey(),
|
|
320
|
-
next,
|
|
321
|
-
JUNIOR_THREAD_STATE_TTL_MS
|
|
322
|
-
);
|
|
323
|
-
} finally {
|
|
324
|
-
await state.releaseLock(lock);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
async function getDispatchRecord(id) {
|
|
328
|
-
const state = getStateAdapter();
|
|
329
|
-
await state.connect();
|
|
330
|
-
return parseDispatchRecord(await state.get(getDispatchStorageKey(id)));
|
|
331
|
-
}
|
|
332
|
-
async function createOrGetDispatch(args) {
|
|
333
|
-
const id = buildDispatchId(args.plugin, args.options.idempotencyKey);
|
|
334
|
-
return await withDispatchLock(id, async (state) => {
|
|
335
|
-
const existing = parseDispatchRecord(
|
|
336
|
-
await state.get(getDispatchStorageKey(id))
|
|
337
|
-
);
|
|
338
|
-
if (existing) {
|
|
339
|
-
return { record: existing, status: "already_exists" };
|
|
340
|
-
}
|
|
341
|
-
const metadata = normalizeMetadata(args.options.metadata);
|
|
342
|
-
const record = {
|
|
343
|
-
actor: { platform: "system", name: args.plugin },
|
|
344
|
-
createdAtMs: args.nowMs,
|
|
345
|
-
...args.options.credentialSubject ? { credentialSubject: args.options.credentialSubject } : void 0,
|
|
346
|
-
destination: args.options.destination,
|
|
347
|
-
destinationVisibility: args.options.destinationVisibility,
|
|
348
|
-
id,
|
|
349
|
-
idempotencyKey: args.options.idempotencyKey,
|
|
350
|
-
input: args.options.input,
|
|
351
|
-
...metadata ? { metadata } : void 0,
|
|
352
|
-
plugin: args.plugin,
|
|
353
|
-
...args.options.replyAttribution ? { replyAttribution: args.options.replyAttribution } : void 0,
|
|
354
|
-
status: "pending",
|
|
355
|
-
source: args.options.source,
|
|
356
|
-
updatedAtMs: args.nowMs
|
|
357
|
-
};
|
|
358
|
-
await updatePendingDispatchMailboxAppendIndex(
|
|
359
|
-
state,
|
|
360
|
-
(ids) => ids.includes(id) ? ids : [...ids, id]
|
|
361
|
-
);
|
|
362
|
-
await putRecord(state, record);
|
|
363
|
-
return { record, status: "created" };
|
|
364
|
-
});
|
|
365
|
-
}
|
|
366
|
-
async function transitionDispatch(id, transition) {
|
|
367
|
-
return await withDispatchLock(id, async (state) => {
|
|
368
|
-
const current = parseDispatchRecord(
|
|
369
|
-
await state.get(getDispatchStorageKey(id))
|
|
370
|
-
);
|
|
371
|
-
if (!current) {
|
|
372
|
-
return void 0;
|
|
373
|
-
}
|
|
374
|
-
const transitioned = transition(current);
|
|
375
|
-
if (transitioned === current) {
|
|
376
|
-
return current;
|
|
377
|
-
}
|
|
378
|
-
const next = {
|
|
379
|
-
...transitioned,
|
|
380
|
-
updatedAtMs: Date.now()
|
|
381
|
-
};
|
|
382
|
-
await putRecord(state, next);
|
|
383
|
-
return next;
|
|
384
|
-
});
|
|
385
|
-
}
|
|
386
|
-
async function markDispatchRunning(id) {
|
|
387
|
-
return await transitionDispatch(
|
|
388
|
-
id,
|
|
389
|
-
(record) => isTerminalDispatchStatus(record.status) ? record : { ...record, status: "running", errorMessage: void 0 }
|
|
390
|
-
);
|
|
391
|
-
}
|
|
392
|
-
async function markDispatchAwaitingResume(id) {
|
|
393
|
-
return await transitionDispatch(
|
|
394
|
-
id,
|
|
395
|
-
(record) => isTerminalDispatchStatus(record.status) ? record : {
|
|
396
|
-
...record,
|
|
397
|
-
status: "awaiting_resume"
|
|
398
|
-
}
|
|
399
|
-
);
|
|
400
|
-
}
|
|
401
|
-
async function recordEventTaskExecution(previous, next, status) {
|
|
402
|
-
if (!next || next.status !== status || previous?.status === status) return;
|
|
403
|
-
if (next.plugin !== "junior") return;
|
|
404
|
-
const eventTaskId = next.metadata?.eventTaskId;
|
|
405
|
-
if (!eventTaskId) return;
|
|
406
|
-
const conversationId = getDispatchConversationId(next);
|
|
407
|
-
const conversation = await getConversationStore().get({ conversationId });
|
|
408
|
-
await recordTaskExecution("event", eventTaskId, {
|
|
409
|
-
...conversation ? { conversationId } : void 0,
|
|
410
|
-
executionId: next.id,
|
|
411
|
-
nowMs: next.updatedAtMs,
|
|
412
|
-
status
|
|
413
|
-
});
|
|
414
|
-
}
|
|
415
|
-
async function markDispatchBlocked(id, errorMessage, resultMessageTs) {
|
|
416
|
-
const previous = await getDispatchRecord(id);
|
|
417
|
-
const next = await transitionDispatch(
|
|
418
|
-
id,
|
|
419
|
-
(record) => isTerminalDispatchStatus(record.status) ? record : {
|
|
420
|
-
...record,
|
|
421
|
-
errorMessage,
|
|
422
|
-
...resultMessageTs ? { resultMessageTs } : void 0,
|
|
423
|
-
status: "blocked"
|
|
424
|
-
}
|
|
425
|
-
);
|
|
426
|
-
await recordEventTaskExecution(previous, next, "blocked");
|
|
427
|
-
return next;
|
|
428
|
-
}
|
|
429
|
-
async function markDispatchCompleted(id, resultMessageTs) {
|
|
430
|
-
const previous = await getDispatchRecord(id);
|
|
431
|
-
const next = await transitionDispatch(
|
|
432
|
-
id,
|
|
433
|
-
(record) => isTerminalDispatchStatus(record.status) ? record : {
|
|
434
|
-
...record,
|
|
435
|
-
errorMessage: void 0,
|
|
436
|
-
...resultMessageTs ? { resultMessageTs } : void 0,
|
|
437
|
-
status: "completed"
|
|
438
|
-
}
|
|
439
|
-
);
|
|
440
|
-
await recordEventTaskExecution(previous, next, "completed");
|
|
441
|
-
return next;
|
|
442
|
-
}
|
|
443
|
-
async function markDispatchFailed(id, errorMessage, resultMessageTs) {
|
|
444
|
-
const previous = await getDispatchRecord(id);
|
|
445
|
-
const next = await transitionDispatch(
|
|
446
|
-
id,
|
|
447
|
-
(record) => isTerminalDispatchStatus(record.status) ? record : {
|
|
448
|
-
...record,
|
|
449
|
-
errorMessage,
|
|
450
|
-
...resultMessageTs ? { resultMessageTs } : void 0,
|
|
451
|
-
status: "failed"
|
|
452
|
-
}
|
|
453
|
-
);
|
|
454
|
-
await recordEventTaskExecution(previous, next, "failed");
|
|
455
|
-
return next;
|
|
456
|
-
}
|
|
457
|
-
async function confirmDispatchMailboxAppend(id) {
|
|
458
|
-
const state = getStateAdapter();
|
|
459
|
-
await state.connect();
|
|
460
|
-
await updatePendingDispatchMailboxAppendIndex(
|
|
461
|
-
state,
|
|
462
|
-
(ids) => ids.filter((candidate) => candidate !== id)
|
|
463
|
-
);
|
|
464
|
-
}
|
|
465
|
-
async function listPendingDispatchMailboxAppends() {
|
|
466
|
-
const state = getStateAdapter();
|
|
467
|
-
await state.connect();
|
|
468
|
-
const stored = await state.get(pendingDispatchMailboxAppendIndexKey());
|
|
469
|
-
return stored === void 0 || stored === null ? [] : [...new Set(pendingDispatchMailboxAppendIndexSchema.parse(stored))];
|
|
470
|
-
}
|
|
471
|
-
async function claimDispatchMailboxAppend(id) {
|
|
472
|
-
return await withDispatchLock(id, async (state) => {
|
|
473
|
-
return parseDispatchRecord(await state.get(getDispatchStorageKey(id)));
|
|
474
|
-
});
|
|
475
|
-
}
|
|
476
|
-
async function getPluginDispatchProjection(args) {
|
|
477
|
-
const record = await getDispatchRecord(args.id);
|
|
478
|
-
if (!record || record.plugin !== args.plugin) {
|
|
479
|
-
return void 0;
|
|
480
|
-
}
|
|
481
|
-
return toDispatchProjection(record);
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
// src/chat/plugins/task-runner.ts
|
|
485
|
-
var PLUGIN_TASK_LOCK_TTL_MS = 5 * 60 * 1e3;
|
|
486
|
-
function isRecord(value) {
|
|
487
|
-
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
488
|
-
}
|
|
489
|
-
function textPart(value) {
|
|
490
|
-
if (isRecord(value) && value.type === "text" && typeof value.text === "string") {
|
|
491
|
-
return value.text;
|
|
492
|
-
}
|
|
493
|
-
return void 0;
|
|
494
|
-
}
|
|
495
|
-
function messageText(message) {
|
|
496
|
-
const content = message.content;
|
|
497
|
-
if (typeof content === "string") {
|
|
498
|
-
return sanitizeText(content);
|
|
499
|
-
}
|
|
500
|
-
if (!Array.isArray(content)) {
|
|
501
|
-
return "";
|
|
502
|
-
}
|
|
503
|
-
return sanitizeText(content.map(textPart).filter(Boolean).join("\n"));
|
|
504
|
-
}
|
|
505
|
-
function toolResultText(message) {
|
|
506
|
-
const record = message;
|
|
507
|
-
const parts = [
|
|
508
|
-
messageText(message),
|
|
509
|
-
record.output,
|
|
510
|
-
record.result,
|
|
511
|
-
record.stdout,
|
|
512
|
-
record.stderr,
|
|
513
|
-
record.toolResult
|
|
514
|
-
].filter(
|
|
515
|
-
(value) => typeof value === "string" && value.length > 0
|
|
516
|
-
);
|
|
517
|
-
return sanitizeText(parts.join("\n"));
|
|
518
|
-
}
|
|
519
|
-
function sanitizeText(text) {
|
|
520
|
-
return text.replace(
|
|
521
|
-
/<data_base64>[\s\S]*?<\/data_base64>/g,
|
|
522
|
-
"<data_base64>[omitted]</data_base64>"
|
|
523
|
-
).replace(
|
|
524
|
-
/data:image\/[a-z0-9.+-]+;base64,[a-z0-9+/=]+/gi,
|
|
525
|
-
"[image data omitted]"
|
|
526
|
-
).replaceAll("\0", " ").trim();
|
|
527
|
-
}
|
|
528
|
-
function messageProvenance(provenance) {
|
|
529
|
-
return {
|
|
530
|
-
authority: provenance.authority,
|
|
531
|
-
...provenance.actor ? { actor: provenance.actor } : void 0
|
|
532
|
-
};
|
|
533
|
-
}
|
|
534
|
-
function runTranscriptEntry(message, provenance, runActor) {
|
|
535
|
-
const role = getPiMessageRole(message);
|
|
536
|
-
if (role === "user" || role === "assistant") {
|
|
537
|
-
const text2 = role === "user" ? instructionTextForProjection(messageText(message)) : messageText(message);
|
|
538
|
-
if (!text2) {
|
|
539
|
-
return void 0;
|
|
540
|
-
}
|
|
541
|
-
if (role === "assistant") {
|
|
542
|
-
return { type: "message", role, text: text2 };
|
|
543
|
-
}
|
|
544
|
-
return {
|
|
545
|
-
type: "message",
|
|
546
|
-
role,
|
|
547
|
-
text: text2,
|
|
548
|
-
provenance: messageProvenance(provenance),
|
|
549
|
-
isRunActor: sameActorIdentity(provenance.actor, runActor)
|
|
550
|
-
};
|
|
551
|
-
}
|
|
552
|
-
if (!isToolResultMessage(message)) {
|
|
553
|
-
return void 0;
|
|
554
|
-
}
|
|
555
|
-
const toolName = normalizeToolNameFromResult(message);
|
|
556
|
-
if (!toolName) {
|
|
557
|
-
return void 0;
|
|
558
|
-
}
|
|
559
|
-
const text = toolResultText(message);
|
|
560
|
-
return {
|
|
561
|
-
type: "toolResult",
|
|
562
|
-
toolName,
|
|
563
|
-
isError: isToolResultError(message),
|
|
564
|
-
...text ? { text } : void 0
|
|
565
|
-
};
|
|
566
|
-
}
|
|
567
|
-
function turnMessagesWithProvenance(record) {
|
|
568
|
-
const startIndex = record.turnStartMessageIndex ?? 0;
|
|
569
|
-
const messages = record.piMessages.slice(startIndex);
|
|
570
|
-
const provenance = record.piMessageProvenance.slice(startIndex);
|
|
571
|
-
const paired = [];
|
|
572
|
-
for (const [index, message] of messages.entries()) {
|
|
573
|
-
for (const stripped of stripRuntimeTurnContext([message])) {
|
|
574
|
-
paired.push({
|
|
575
|
-
message: stripped,
|
|
576
|
-
provenance: provenance[index] ?? { authority: "context" }
|
|
577
|
-
});
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
return paired;
|
|
581
|
-
}
|
|
582
|
-
function slackContextAuthor(location, message) {
|
|
583
|
-
const userId = message.author?.userId?.trim();
|
|
584
|
-
if (!userId) {
|
|
585
|
-
return void 0;
|
|
586
|
-
}
|
|
587
|
-
return {
|
|
588
|
-
platform: "slack",
|
|
589
|
-
teamId: location.teamId,
|
|
590
|
-
userId,
|
|
591
|
-
...message.author?.userName ? { userName: message.author.userName } : void 0,
|
|
592
|
-
...message.author?.fullName ? { fullName: message.author.fullName } : void 0
|
|
593
|
-
};
|
|
594
|
-
}
|
|
595
|
-
function slackTimestampMs(value) {
|
|
596
|
-
const timestamp = parseSlackMessageTs(value);
|
|
597
|
-
if (!timestamp) {
|
|
598
|
-
return void 0;
|
|
599
|
-
}
|
|
600
|
-
const timestampMs = Number(timestamp) * 1e3;
|
|
601
|
-
return Number.isFinite(timestampMs) ? timestampMs : void 0;
|
|
602
|
-
}
|
|
603
|
-
function conversationMessageTimestampMs(message) {
|
|
604
|
-
if (message.meta?.slackTs !== void 0) {
|
|
605
|
-
return slackTimestampMs(message.meta.slackTs);
|
|
606
|
-
}
|
|
607
|
-
return Number.isFinite(message.createdAtMs) ? message.createdAtMs : void 0;
|
|
608
|
-
}
|
|
609
|
-
function messageExistedAtRunCompletion(message, completedAtMs) {
|
|
610
|
-
const messageTimestampMs = conversationMessageTimestampMs(message);
|
|
611
|
-
return messageTimestampMs !== void 0 && messageTimestampMs <= completedAtMs;
|
|
612
|
-
}
|
|
613
|
-
async function loadConversationContextTranscriptEntries(record, location, visibility, runActor) {
|
|
614
|
-
if (location?.provider !== "slack" || visibility !== "public") {
|
|
615
|
-
return [];
|
|
616
|
-
}
|
|
617
|
-
const state = await getPersistedThreadState(record.conversationId);
|
|
618
|
-
const conversation = coerceThreadConversationState(state);
|
|
619
|
-
await hydrateConversationMessages({
|
|
620
|
-
conversation,
|
|
621
|
-
conversationId: record.conversationId
|
|
622
|
-
});
|
|
623
|
-
const entries = [];
|
|
624
|
-
for (const message of conversation.messages) {
|
|
625
|
-
if (message.role !== "user") {
|
|
626
|
-
continue;
|
|
627
|
-
}
|
|
628
|
-
if (!messageExistedAtRunCompletion(message, record.updatedAtMs)) {
|
|
629
|
-
continue;
|
|
630
|
-
}
|
|
631
|
-
const text = sanitizeText(message.text);
|
|
632
|
-
if (!text) {
|
|
633
|
-
continue;
|
|
634
|
-
}
|
|
635
|
-
const author = slackContextAuthor(location, message);
|
|
636
|
-
entries.push({
|
|
637
|
-
type: "message",
|
|
638
|
-
role: "user",
|
|
639
|
-
text,
|
|
640
|
-
provenance: {
|
|
641
|
-
authority: "context",
|
|
642
|
-
...author ? { actor: author } : void 0
|
|
643
|
-
},
|
|
644
|
-
isRunActor: sameActorIdentity(author, runActor)
|
|
645
|
-
});
|
|
646
|
-
}
|
|
647
|
-
return entries;
|
|
648
|
-
}
|
|
649
|
-
async function withPluginTaskLock(taskId, callback) {
|
|
650
|
-
const state = getStateAdapter();
|
|
651
|
-
await state.connect();
|
|
652
|
-
const lock = await state.acquireLock(
|
|
653
|
-
`plugin:task:${taskId}`,
|
|
654
|
-
PLUGIN_TASK_LOCK_TTL_MS
|
|
655
|
-
);
|
|
656
|
-
if (!lock) {
|
|
657
|
-
throw new Error(`Could not acquire plugin task lock for ${taskId}`);
|
|
658
|
-
}
|
|
659
|
-
try {
|
|
660
|
-
return await callback();
|
|
661
|
-
} finally {
|
|
662
|
-
await state.releaseLock(lock);
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
async function loadPluginRun(params) {
|
|
666
|
-
const record = await getTurnRecord(params.conversationId, params.sessionId);
|
|
667
|
-
if (!record) {
|
|
668
|
-
throw new Error("Completed plugin task session record is unavailable");
|
|
669
|
-
}
|
|
670
|
-
if (record.state !== "completed") {
|
|
671
|
-
throw new Error("Completed plugin task session record is not completed");
|
|
672
|
-
}
|
|
673
|
-
const conversationStore = getConversationStore();
|
|
674
|
-
const routing = await resolveConversationRouting({
|
|
675
|
-
conversationId: params.conversationId,
|
|
676
|
-
conversationStore
|
|
677
|
-
});
|
|
678
|
-
if (!routing) {
|
|
679
|
-
throw new Error(
|
|
680
|
-
`Conversation ${params.conversationId} is missing durable routing metadata`
|
|
681
|
-
);
|
|
682
|
-
}
|
|
683
|
-
const source = record.source ?? routing.source;
|
|
684
|
-
if (!source) {
|
|
685
|
-
throw new Error("Completed plugin task session record is missing Source");
|
|
686
|
-
}
|
|
687
|
-
const conversation = await conversationStore.get({
|
|
688
|
-
conversationId: params.conversationId
|
|
689
|
-
});
|
|
690
|
-
const runActor = record.actor ?? record.actors[0] ?? (record.dispatchId ? (await getDispatchRecord(record.dispatchId))?.actor : void 0);
|
|
691
|
-
const actorUser = runActor ? (await readActorIdentity(runActor))?.user : void 0;
|
|
692
|
-
const runEntries = turnMessagesWithProvenance(record).map(
|
|
693
|
-
({ message, provenance }) => runTranscriptEntry(message, provenance, runActor)
|
|
694
|
-
).filter((entry) => Boolean(entry));
|
|
695
|
-
const runMessageTexts = new Set(
|
|
696
|
-
runEntries.filter((entry) => entry.type === "message").map((entry) => entry.text)
|
|
697
|
-
);
|
|
698
|
-
const contextEntries = (await loadConversationContextTranscriptEntries(
|
|
699
|
-
record,
|
|
700
|
-
conversation?.location,
|
|
701
|
-
conversation?.visibility,
|
|
702
|
-
runActor
|
|
703
|
-
)).filter(
|
|
704
|
-
(entry) => entry.type !== "message" || !runMessageTexts.has(entry.text)
|
|
705
|
-
);
|
|
706
|
-
return pluginRunContextSchema.parse({
|
|
707
|
-
...actorUser ? { actorUserId: actorUser.id } : void 0,
|
|
708
|
-
completedAtMs: record.updatedAtMs,
|
|
709
|
-
conversationId: record.conversationId,
|
|
710
|
-
destination: routing.destination,
|
|
711
|
-
...routing.location ? { locationId: routing.location.id } : void 0,
|
|
712
|
-
// Read Actors from the full run record, not the shorter transcript.
|
|
713
|
-
// This includes every Actor that supplied an instruction.
|
|
714
|
-
actors: record.actors,
|
|
715
|
-
...runActor ? { actor: runActor } : void 0,
|
|
716
|
-
runId: record.turnId,
|
|
717
|
-
source,
|
|
718
|
-
transcript: [...contextEntries, ...runEntries]
|
|
719
|
-
});
|
|
720
|
-
}
|
|
721
|
-
function taskPluginContext(plugin, message, options = {}) {
|
|
722
|
-
const pluginName = plugin.manifest.name;
|
|
723
|
-
const sessionParams = pluginTaskParamsSchema.parse(message.params);
|
|
724
|
-
return {
|
|
725
|
-
db: getDb(),
|
|
726
|
-
embedder: createPluginEmbedder(pluginName, {
|
|
727
|
-
signal: options.signal
|
|
728
|
-
}),
|
|
729
|
-
events: createPluginConversationEvents({
|
|
730
|
-
conversationId: sessionParams.conversationId,
|
|
731
|
-
operationId: pluginTaskId(message),
|
|
732
|
-
plugin,
|
|
733
|
-
turnId: sessionParams.sessionId
|
|
734
|
-
}),
|
|
735
|
-
id: pluginTaskId(message),
|
|
736
|
-
log: createPluginLogger(pluginName),
|
|
737
|
-
model: createPluginModel(pluginName, plugin.model, {
|
|
738
|
-
signal: options.signal
|
|
739
|
-
}),
|
|
740
|
-
name: message.name,
|
|
741
|
-
plugin: { name: pluginName },
|
|
742
|
-
run: {
|
|
743
|
-
async load() {
|
|
744
|
-
return await loadPluginRun(sessionParams);
|
|
745
|
-
}
|
|
746
|
-
},
|
|
747
|
-
state: createPluginState(pluginName)
|
|
748
|
-
};
|
|
749
|
-
}
|
|
750
|
-
function findPluginTask(message) {
|
|
751
|
-
const plugin = getPlugins().find(
|
|
752
|
-
(candidate) => candidate.manifest.name === message.plugin
|
|
753
|
-
);
|
|
754
|
-
if (!plugin?.tasks || !Object.hasOwn(plugin.tasks, message.name)) {
|
|
755
|
-
return void 0;
|
|
756
|
-
}
|
|
757
|
-
const task = plugin.tasks[message.name];
|
|
758
|
-
return { plugin, task };
|
|
759
|
-
}
|
|
760
|
-
async function scheduleSessionCompletedPluginTasks(params, options = {}) {
|
|
761
|
-
const coreParams = pluginTaskParamsSchema.parse(params);
|
|
762
|
-
const taskRegistrations = getPlugins().flatMap(
|
|
763
|
-
(plugin) => Object.keys(plugin.tasks ?? {}).map((name) => ({ name, plugin }))
|
|
764
|
-
);
|
|
765
|
-
if (taskRegistrations.length === 0) {
|
|
766
|
-
return;
|
|
767
|
-
}
|
|
768
|
-
const record = await getTurnRecord(
|
|
769
|
-
coreParams.conversationId,
|
|
770
|
-
coreParams.sessionId
|
|
771
|
-
);
|
|
772
|
-
if (!record || record.state !== "completed") {
|
|
773
|
-
throw new Error("Completed plugin task session record is not ready");
|
|
774
|
-
}
|
|
775
|
-
const send = options.send ?? sendVercelPluginTask;
|
|
776
|
-
const messages = taskRegistrations.map(({ name, plugin }) => ({
|
|
777
|
-
name,
|
|
778
|
-
params: coreParams,
|
|
779
|
-
plugin: plugin.manifest.name
|
|
780
|
-
}));
|
|
781
|
-
await Promise.all(
|
|
782
|
-
messages.map(async (message) => {
|
|
783
|
-
await send(message);
|
|
784
|
-
})
|
|
785
|
-
);
|
|
786
|
-
}
|
|
787
|
-
async function processPluginTask(message, options = {}) {
|
|
788
|
-
await withPluginTaskLock(pluginTaskId(message), async () => {
|
|
789
|
-
const resolved = findPluginTask(message);
|
|
790
|
-
if (!resolved) {
|
|
791
|
-
throw new Error(
|
|
792
|
-
`Plugin task "${message.plugin}.${message.name}" is not registered`
|
|
793
|
-
);
|
|
794
|
-
}
|
|
795
|
-
await resolved.task.run(
|
|
796
|
-
taskPluginContext(resolved.plugin, message, options)
|
|
797
|
-
);
|
|
798
|
-
});
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
export {
|
|
802
|
-
getDispatchConversationId,
|
|
803
|
-
getDispatchInputMessageId,
|
|
804
|
-
getDispatchTurnId,
|
|
805
|
-
isTerminalDispatchStatus,
|
|
806
|
-
getDispatchRecord,
|
|
807
|
-
createOrGetDispatch,
|
|
808
|
-
markDispatchRunning,
|
|
809
|
-
markDispatchAwaitingResume,
|
|
810
|
-
markDispatchBlocked,
|
|
811
|
-
markDispatchCompleted,
|
|
812
|
-
markDispatchFailed,
|
|
813
|
-
confirmDispatchMailboxAppend,
|
|
814
|
-
listPendingDispatchMailboxAppends,
|
|
815
|
-
claimDispatchMailboxAppend,
|
|
816
|
-
getPluginDispatchProjection,
|
|
817
|
-
resolveTurnSessionRouting,
|
|
818
|
-
scheduleSessionCompletedPluginTasks,
|
|
819
|
-
processPluginTask
|
|
820
|
-
};
|