@trigger.dev/sdk 4.6.0 → 4.6.2
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/commonjs/v3/ai.d.ts +22 -6
- package/dist/commonjs/v3/ai.js +89 -33
- package/dist/commonjs/v3/ai.js.map +1 -1
- package/dist/commonjs/v3/auth.js +8 -2
- package/dist/commonjs/v3/auth.js.map +1 -1
- package/dist/commonjs/v3/sessionTracing.d.ts +7 -0
- package/dist/commonjs/v3/sessionTracing.js +44 -0
- package/dist/commonjs/v3/sessionTracing.js.map +1 -0
- package/dist/commonjs/v3/sessions.js +31 -34
- package/dist/commonjs/v3/sessions.js.map +1 -1
- package/dist/commonjs/version.js +1 -1
- package/dist/esm/v3/ai.d.ts +22 -6
- package/dist/esm/v3/ai.js +89 -33
- package/dist/esm/v3/ai.js.map +1 -1
- package/dist/esm/v3/auth.js +8 -2
- package/dist/esm/v3/auth.js.map +1 -1
- package/dist/esm/v3/sessionTracing.d.ts +7 -0
- package/dist/esm/v3/sessionTracing.js +40 -0
- package/dist/esm/v3/sessionTracing.js.map +1 -0
- package/dist/esm/v3/sessions.js +31 -34
- package/dist/esm/v3/sessions.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/docs/cli-env-commands.mdx +114 -0
- package/docs/cli-projects-commands.mdx +62 -0
- package/docs/cli-runs-commands.mdx +94 -0
- package/package.json +2 -2
package/dist/esm/v3/ai.js
CHANGED
|
@@ -2,6 +2,7 @@ import { accessoryAttributes, apiClientManager, controlSubtype, generateJWT, get
|
|
|
2
2
|
// Runtime VALUES go through the ESM/CJS shim so the CJS build can `require`
|
|
3
3
|
// ESM-only `ai@7` (see ../imports/ai-runtime.ts).
|
|
4
4
|
import { trace } from "@opentelemetry/api";
|
|
5
|
+
import { traceSessionIdle } from "./sessionTracing.js";
|
|
5
6
|
import { tool as aiTool, convertToModelMessages, dynamicTool, generateId as generateMessageId, getToolName, isToolUIPart, jsonSchema, readUIMessageStream, streamText as aiStreamText, zodSchema, } from "../imports/ai-runtime.js";
|
|
6
7
|
import { createTranscriptShadow, defaultStorage, diffTranscript, fingerprintMessage, parseTranscriptRuntimeState, restoreModelLane, } from "./transcriptStorage.js";
|
|
7
8
|
let transcriptStorageOverride;
|
|
@@ -1087,7 +1088,7 @@ async function waitOnChatRoute(route, options) {
|
|
|
1087
1088
|
return tracer.startActiveSpan(options.spanName ?? `chat.${route}.wait()`, async (span) => {
|
|
1088
1089
|
const idleMs = (options.idleTimeoutInSeconds ?? 0) * 1000;
|
|
1089
1090
|
if (idleMs > 0) {
|
|
1090
|
-
const warm = await router.next(route, { timeoutMs: idleMs });
|
|
1091
|
+
const warm = await traceSessionIdle(session.id, idleMs / 1000, () => router.next(route, { timeoutMs: idleMs }));
|
|
1091
1092
|
if (warm) {
|
|
1092
1093
|
span.setAttribute("wait.resolved", "idle");
|
|
1093
1094
|
return { ok: true, output: warm.data, record: warm };
|
|
@@ -1141,10 +1142,6 @@ async function waitOnChatRoute(route, options) {
|
|
|
1141
1142
|
session: session.id,
|
|
1142
1143
|
io: "in",
|
|
1143
1144
|
route,
|
|
1144
|
-
...accessoryAttributes({
|
|
1145
|
-
items: [{ text: `${session.id}.in:${route}`, variant: "normal" }],
|
|
1146
|
-
style: "codepath",
|
|
1147
|
-
}),
|
|
1148
1145
|
},
|
|
1149
1146
|
});
|
|
1150
1147
|
}
|
|
@@ -1820,6 +1817,14 @@ const chatHandoverPartialKey = locals.create("chat.handoverPartial");
|
|
|
1820
1817
|
* @internal
|
|
1821
1818
|
*/
|
|
1822
1819
|
const chatHandoverMessageIdKey = locals.create("chat.handoverMessageId");
|
|
1820
|
+
/**
|
|
1821
|
+
* The model messages a turn-0 head-start splice contributed to the model lane,
|
|
1822
|
+
* keyed by the UI message id it was synthesized under. When the agent's response
|
|
1823
|
+
* completes that message under the same id, this is the run to replace: the UI
|
|
1824
|
+
* form alone converts to something else (its pending tool calls drop out, the
|
|
1825
|
+
* approval round was never on it), so it cannot locate the run itself.
|
|
1826
|
+
*/
|
|
1827
|
+
const chatHandoverSplicedRunKey = locals.create("chat.handoverSplicedRun");
|
|
1823
1828
|
/**
|
|
1824
1829
|
* Run-scoped slot indicating that the customer's step-1 head-start
|
|
1825
1830
|
* response is the FINAL turn response. When true, turn 0 runs through
|
|
@@ -1903,16 +1908,19 @@ function synthesizeHandoverUIMessage(partial, messageId) {
|
|
|
1903
1908
|
*/
|
|
1904
1909
|
function spliceHandoverPartial(modelMessages, uiMessages, signal) {
|
|
1905
1910
|
if (!signal.partialAssistantMessage || signal.partialAssistantMessage.length === 0) {
|
|
1906
|
-
return;
|
|
1911
|
+
return undefined;
|
|
1907
1912
|
}
|
|
1908
1913
|
// Skip if the hydrated chain already persisted the partial under this id.
|
|
1909
1914
|
const alreadyInChain = signal.messageId !== undefined && uiMessages.some((m) => m.id === signal.messageId);
|
|
1910
1915
|
if (alreadyInChain)
|
|
1911
|
-
return;
|
|
1912
|
-
|
|
1916
|
+
return undefined;
|
|
1917
|
+
const run = [...signal.partialAssistantMessage];
|
|
1918
|
+
modelMessages.push(...run);
|
|
1913
1919
|
const partialUI = synthesizeHandoverUIMessage(signal.partialAssistantMessage, signal.messageId);
|
|
1914
|
-
if (partialUI)
|
|
1915
|
-
|
|
1920
|
+
if (!partialUI)
|
|
1921
|
+
return undefined;
|
|
1922
|
+
uiMessages.push(partialUI);
|
|
1923
|
+
return { id: partialUI.id, run };
|
|
1916
1924
|
}
|
|
1917
1925
|
/**
|
|
1918
1926
|
* Per-turn background context queue. Messages added via `chat.backgroundWork.inject()`
|
|
@@ -3652,8 +3660,8 @@ function isActionTurn(value) {
|
|
|
3652
3660
|
* tail does not match the old message's conversion, nothing is changed and
|
|
3653
3661
|
* `false` is returned so the caller can fall back to a full reconversion.
|
|
3654
3662
|
*/
|
|
3655
|
-
async function replaceModelRun(lane, oldUi, newUi, tailAfter) {
|
|
3656
|
-
const oldRun = await toModelMessages([stripProviderMetadata(oldUi)]);
|
|
3663
|
+
async function replaceModelRun(lane, oldUi, newUi, tailAfter, knownOldRun) {
|
|
3664
|
+
const oldRun = knownOldRun ?? (await toModelMessages([stripProviderMetadata(oldUi)]));
|
|
3657
3665
|
const newRun = await toModelMessages([stripProviderMetadata(newUi)]);
|
|
3658
3666
|
// A message that converts to nothing (a pending tool call with no output yet,
|
|
3659
3667
|
// which `ignoreIncompleteToolCalls` drops) locates no run in the lane. Matching
|
|
@@ -4785,7 +4793,7 @@ function chatAgent(options) {
|
|
|
4785
4793
|
const preloadResult = await messagesInput.waitWithIdleTimeout({
|
|
4786
4794
|
idleTimeoutInSeconds: effectivePreloadIdleTimeout,
|
|
4787
4795
|
timeout: effectivePreloadTimeout,
|
|
4788
|
-
spanName: "
|
|
4796
|
+
spanName: "first message",
|
|
4789
4797
|
skipSuspend: exitAfterPreloadIdle,
|
|
4790
4798
|
onSuspend: onChatSuspend
|
|
4791
4799
|
? async () => {
|
|
@@ -4937,7 +4945,7 @@ function chatAgent(options) {
|
|
|
4937
4945
|
const continuationResult = await messagesInput.waitWithIdleTimeout({
|
|
4938
4946
|
idleTimeoutInSeconds: effectiveIdleTimeout,
|
|
4939
4947
|
timeout: effectiveTurnTimeout,
|
|
4940
|
-
spanName: "
|
|
4948
|
+
spanName: "first message (continuation)",
|
|
4941
4949
|
onSuspend: onChatSuspend
|
|
4942
4950
|
? async () => {
|
|
4943
4951
|
await tracer.startActiveSpan("onChatSuspend()", async () => {
|
|
@@ -5466,10 +5474,12 @@ function chatAgent(options) {
|
|
|
5466
5474
|
// `UIMessageStreamError: No tool invocation found`.
|
|
5467
5475
|
const pendingHandoverPartial = locals.get(chatHandoverPartialKey);
|
|
5468
5476
|
if (pendingHandoverPartial && pendingHandoverPartial.length > 0) {
|
|
5469
|
-
spliceHandoverPartial(accumulatedMessages, accumulatedUIMessages, {
|
|
5477
|
+
const spliced = spliceHandoverPartial(accumulatedMessages, accumulatedUIMessages, {
|
|
5470
5478
|
partialAssistantMessage: pendingHandoverPartial,
|
|
5471
5479
|
messageId: locals.get(chatHandoverMessageIdKey),
|
|
5472
5480
|
});
|
|
5481
|
+
if (spliced)
|
|
5482
|
+
locals.set(chatHandoverSplicedRunKey, spliced);
|
|
5473
5483
|
locals.set(chatHandoverPartialKey, []); // consume once
|
|
5474
5484
|
splicedHandoverPartial = true;
|
|
5475
5485
|
}
|
|
@@ -5814,6 +5824,7 @@ function chatAgent(options) {
|
|
|
5814
5824
|
// never reports final usage), which would block the turn loop
|
|
5815
5825
|
// from ever firing onTurnComplete / writeTurnComplete.
|
|
5816
5826
|
let turnUsage;
|
|
5827
|
+
let lastStepUsage;
|
|
5817
5828
|
if (runResult != null &&
|
|
5818
5829
|
typeof runResult.totalUsage?.then === "function") {
|
|
5819
5830
|
try {
|
|
@@ -5826,6 +5837,18 @@ function chatAgent(options) {
|
|
|
5826
5837
|
/* non-fatal — usage capture failed */
|
|
5827
5838
|
}
|
|
5828
5839
|
}
|
|
5840
|
+
const lastStepUsagePromise = runResult != null ? runResult.usage : undefined;
|
|
5841
|
+
if (typeof lastStepUsagePromise?.then === "function") {
|
|
5842
|
+
try {
|
|
5843
|
+
lastStepUsage = (await Promise.race([
|
|
5844
|
+
lastStepUsagePromise,
|
|
5845
|
+
new Promise((r) => setTimeout(() => r(undefined), 2_000)),
|
|
5846
|
+
]));
|
|
5847
|
+
}
|
|
5848
|
+
catch {
|
|
5849
|
+
/* non-fatal — usage capture failed */
|
|
5850
|
+
}
|
|
5851
|
+
}
|
|
5829
5852
|
if (turnUsage) {
|
|
5830
5853
|
cumulativeUsage = addUsage(cumulativeUsage, turnUsage);
|
|
5831
5854
|
previousTurnUsage = turnUsage;
|
|
@@ -5971,8 +5994,14 @@ function chatAgent(options) {
|
|
|
5971
5994
|
stripProviderMetadata(capturedResponseMessage),
|
|
5972
5995
|
]);
|
|
5973
5996
|
if (existingIdx !== -1) {
|
|
5997
|
+
const spliced = locals.get(chatHandoverSplicedRunKey);
|
|
5998
|
+
const splicedRun = spliced && previousAtIdx && spliced.id === previousAtIdx.id
|
|
5999
|
+
? spliced.run
|
|
6000
|
+
: undefined;
|
|
5974
6001
|
const ok = previousAtIdx !== undefined &&
|
|
5975
|
-
(await replaceModelRun(accumulatedMessages, previousAtIdx, capturedResponseMessage, steerTailThisTurn));
|
|
6002
|
+
(await replaceModelRun(accumulatedMessages, previousAtIdx, capturedResponseMessage, steerTailThisTurn, splicedRun));
|
|
6003
|
+
if (splicedRun)
|
|
6004
|
+
locals.set(chatHandoverSplicedRunKey, undefined);
|
|
5976
6005
|
if (!ok) {
|
|
5977
6006
|
logger.warn("chat.agent: replaced response not found at the model lane tail; reconverting the lane");
|
|
5978
6007
|
accumulatedMessages = await toModelMessages(accumulatedUIMessages);
|
|
@@ -6032,12 +6061,14 @@ function chatAgent(options) {
|
|
|
6032
6061
|
const outerCompaction = locals.get(chatAgentCompactionKey);
|
|
6033
6062
|
const innerCompactionState = locals.get(chatCompactionStateKey);
|
|
6034
6063
|
if (outerCompaction && !innerCompactionState && turnUsage && !wasStopped) {
|
|
6064
|
+
const contextUsage = lastStepUsage ?? turnUsage;
|
|
6035
6065
|
const shouldTrigger = await outerCompaction.shouldCompact({
|
|
6036
6066
|
messages: accumulatedMessages,
|
|
6037
|
-
totalTokens:
|
|
6038
|
-
inputTokens:
|
|
6039
|
-
outputTokens:
|
|
6040
|
-
usage:
|
|
6067
|
+
totalTokens: contextUsage.totalTokens,
|
|
6068
|
+
inputTokens: contextUsage.inputTokens,
|
|
6069
|
+
outputTokens: contextUsage.outputTokens,
|
|
6070
|
+
usage: contextUsage,
|
|
6071
|
+
turnUsage,
|
|
6041
6072
|
totalUsage: cumulativeUsage,
|
|
6042
6073
|
chatId: currentWirePayload.chatId,
|
|
6043
6074
|
turn,
|
|
@@ -6362,7 +6393,7 @@ function chatAgent(options) {
|
|
|
6362
6393
|
const next = await messagesInput.waitWithIdleTimeout({
|
|
6363
6394
|
idleTimeoutInSeconds: effectiveIdleTimeout,
|
|
6364
6395
|
timeout: effectiveTurnTimeout,
|
|
6365
|
-
spanName: "
|
|
6396
|
+
spanName: "next message",
|
|
6366
6397
|
onSuspend: onChatSuspend
|
|
6367
6398
|
? async () => {
|
|
6368
6399
|
await tracer.startActiveSpan("onChatSuspend()", async () => {
|
|
@@ -6699,7 +6730,7 @@ function chatAgent(options) {
|
|
|
6699
6730
|
const next = await messagesInput.waitWithIdleTimeout({
|
|
6700
6731
|
idleTimeoutInSeconds: effectiveIdleTimeout,
|
|
6701
6732
|
timeout: effectiveTurnTimeout,
|
|
6702
|
-
spanName: "
|
|
6733
|
+
spanName: "next message (after error)",
|
|
6703
6734
|
});
|
|
6704
6735
|
if (!next.ok) {
|
|
6705
6736
|
return; // Timed out — end run gracefully
|
|
@@ -7739,6 +7770,8 @@ class ChatMessageAccumulator {
|
|
|
7739
7770
|
modelMessages = [];
|
|
7740
7771
|
uiMessages = [];
|
|
7741
7772
|
_compaction;
|
|
7773
|
+
/** The run a spliced head-start partial contributed, until its response replaces it. */
|
|
7774
|
+
_handoverRun;
|
|
7742
7775
|
_pendingMessages;
|
|
7743
7776
|
_steeringQueue = [];
|
|
7744
7777
|
constructor(options) {
|
|
@@ -7782,7 +7815,7 @@ class ChatMessageAccumulator {
|
|
|
7782
7815
|
* `consumeHandover` for the wait+seed+apply convenience.
|
|
7783
7816
|
*/
|
|
7784
7817
|
applyHandover(signal) {
|
|
7785
|
-
spliceHandoverPartial(this.modelMessages, this.uiMessages, signal);
|
|
7818
|
+
this._handoverRun = spliceHandoverPartial(this.modelMessages, this.uiMessages, signal);
|
|
7786
7819
|
}
|
|
7787
7820
|
/**
|
|
7788
7821
|
* One-call `chat.headStart` handover for a custom-agent loop: waits for the
|
|
@@ -7825,8 +7858,13 @@ class ChatMessageAccumulator {
|
|
|
7825
7858
|
if (existingIdx !== -1) {
|
|
7826
7859
|
const previous = this.uiMessages[existingIdx];
|
|
7827
7860
|
this.uiMessages[existingIdx] = response;
|
|
7861
|
+
const handoverRun = this._handoverRun && this._handoverRun.id === previous.id
|
|
7862
|
+
? this._handoverRun.run
|
|
7863
|
+
: undefined;
|
|
7864
|
+
if (handoverRun)
|
|
7865
|
+
this._handoverRun = undefined;
|
|
7828
7866
|
try {
|
|
7829
|
-
if (!(await replaceModelRun(this.modelMessages, previous, response, 0))) {
|
|
7867
|
+
if (!(await replaceModelRun(this.modelMessages, previous, response, 0, handoverRun))) {
|
|
7830
7868
|
this.modelMessages = await toModelMessages(this.uiMessages.map((m) => stripProviderMetadata(m)));
|
|
7831
7869
|
}
|
|
7832
7870
|
}
|
|
@@ -7929,8 +7967,10 @@ class ChatMessageAccumulator {
|
|
|
7929
7967
|
}
|
|
7930
7968
|
/**
|
|
7931
7969
|
* Run outer-loop compaction if needed. Call after adding the response
|
|
7932
|
-
* and capturing usage.
|
|
7933
|
-
*
|
|
7970
|
+
* and capturing usage. Pass the LAST step's usage (`result.usage`), which is
|
|
7971
|
+
* the context the model held on its final call; `result.totalUsage` sums every
|
|
7972
|
+
* step of a tool-using turn and belongs in `context.turnUsage`. Applies
|
|
7973
|
+
* `compactModelMessages` and `compactUIMessages` callbacks if configured.
|
|
7934
7974
|
*
|
|
7935
7975
|
* @returns `true` if compaction was performed, `false` otherwise.
|
|
7936
7976
|
*/
|
|
@@ -7943,6 +7983,7 @@ class ChatMessageAccumulator {
|
|
|
7943
7983
|
inputTokens: usage.inputTokens,
|
|
7944
7984
|
outputTokens: usage.outputTokens,
|
|
7945
7985
|
usage,
|
|
7986
|
+
turnUsage: context?.turnUsage,
|
|
7946
7987
|
totalUsage: context?.totalUsage,
|
|
7947
7988
|
chatId: context?.chatId,
|
|
7948
7989
|
turn: context?.turn,
|
|
@@ -8175,8 +8216,8 @@ function createChatSession(payload, options) {
|
|
|
8175
8216
|
idleTimeoutInSeconds: sessionIdleTimeoutOpt ?? currentPayload.idleTimeoutInSeconds ?? 30,
|
|
8176
8217
|
timeout,
|
|
8177
8218
|
spanName: currentPayload.trigger === "preload"
|
|
8178
|
-
? "
|
|
8179
|
-
: "
|
|
8219
|
+
? "first message"
|
|
8220
|
+
: "first message (continuation)",
|
|
8180
8221
|
});
|
|
8181
8222
|
if (!result.ok || runSignal.aborted) {
|
|
8182
8223
|
stop.cleanup();
|
|
@@ -8213,7 +8254,7 @@ function createChatSession(payload, options) {
|
|
|
8213
8254
|
const next = await messagesInput.waitWithIdleTimeout({
|
|
8214
8255
|
idleTimeoutInSeconds,
|
|
8215
8256
|
timeout,
|
|
8216
|
-
spanName: "
|
|
8257
|
+
spanName: "next message",
|
|
8217
8258
|
});
|
|
8218
8259
|
if (!next.ok || runSignal.aborted) {
|
|
8219
8260
|
stop.cleanup();
|
|
@@ -8424,6 +8465,7 @@ function createChatSession(payload, options) {
|
|
|
8424
8465
|
// indefinitely, which would wedge the turn loop (same guard as
|
|
8425
8466
|
// chat.agent's turn loop).
|
|
8426
8467
|
let turnUsage;
|
|
8468
|
+
let lastStepUsage;
|
|
8427
8469
|
if (typeof source.totalUsage?.then === "function") {
|
|
8428
8470
|
try {
|
|
8429
8471
|
const usage = (await Promise.race([
|
|
@@ -8440,14 +8482,28 @@ function createChatSession(payload, options) {
|
|
|
8440
8482
|
/* non-fatal */
|
|
8441
8483
|
}
|
|
8442
8484
|
}
|
|
8485
|
+
const lastStepUsagePromise = source.usage;
|
|
8486
|
+
if (typeof lastStepUsagePromise?.then === "function") {
|
|
8487
|
+
try {
|
|
8488
|
+
lastStepUsage = (await Promise.race([
|
|
8489
|
+
lastStepUsagePromise,
|
|
8490
|
+
new Promise((r) => setTimeout(() => r(undefined), 2_000)),
|
|
8491
|
+
]));
|
|
8492
|
+
}
|
|
8493
|
+
catch {
|
|
8494
|
+
/* non-fatal */
|
|
8495
|
+
}
|
|
8496
|
+
}
|
|
8443
8497
|
// Outer-loop compaction (same logic as chat.agent)
|
|
8444
8498
|
if (sessionCompaction && turnUsage && !turnObj.stopped) {
|
|
8499
|
+
const contextUsage = lastStepUsage ?? turnUsage;
|
|
8445
8500
|
const shouldTrigger = await sessionCompaction.shouldCompact({
|
|
8446
8501
|
messages: accumulator.modelMessages,
|
|
8447
|
-
totalTokens:
|
|
8448
|
-
inputTokens:
|
|
8449
|
-
outputTokens:
|
|
8450
|
-
usage:
|
|
8502
|
+
totalTokens: contextUsage.totalTokens,
|
|
8503
|
+
inputTokens: contextUsage.inputTokens,
|
|
8504
|
+
outputTokens: contextUsage.outputTokens,
|
|
8505
|
+
usage: contextUsage,
|
|
8506
|
+
turnUsage,
|
|
8451
8507
|
totalUsage: cumulativeUsage,
|
|
8452
8508
|
chatId: currentPayload.chatId,
|
|
8453
8509
|
turn,
|