@athenaintel/react 0.18.0 → 0.19.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/README.md +106 -4
- package/dist/SuperGroupingCard-BsWbHyV_.js +795 -0
- package/dist/SuperGroupingCard-BsWbHyV_.js.map +1 -0
- package/dist/SuperGroupingCard-CRRFUgjN.cjs +794 -0
- package/dist/SuperGroupingCard-CRRFUgjN.cjs.map +1 -0
- package/dist/chat/StatewireApprovalCard.d.ts +59 -2
- package/dist/chat/StatewireClientToolBridge.d.ts +3 -3
- package/dist/chat/StatewireQueuedMessages.d.ts +105 -6
- package/dist/chat/statewire-approval.d.ts +1 -1
- package/dist/chat/statewire-client-tools.d.ts +15 -21
- package/dist/chat/super-grouping/CollapsibleGroup.d.ts +52 -11
- package/dist/chat/super-grouping/SuperGroupingCard.d.ts +78 -21
- package/dist/chat/super-grouping/activity-timeline.d.ts +91 -0
- package/dist/chat/super-grouping/grouping-function.d.ts +13 -10
- package/dist/chat/super-grouping/index.d.ts +12 -0
- package/dist/chat/super-grouping/toolkit-map.d.ts +8 -1
- package/dist/chat/use-statewire-approval-request.d.ts +44 -0
- package/dist/chat-ui/header/conversation-history-panel.d.ts +11 -1
- package/dist/chat-ui/index.d.ts +7 -1
- package/dist/chat-ui/mentions/suggestions/shims.d.ts +0 -4
- package/dist/chat-ui/messages/runtime-message.d.ts +2 -3
- package/dist/chat-ui/messages/statewire-continue-run.d.ts +48 -7
- package/dist/chat-ui/messages/user-edit-composer.d.ts +5 -2
- package/dist/chat-ui/statewire.d.ts +19 -0
- package/dist/chat-ui/thread/chat-thread-shell.d.ts +7 -1
- package/dist/chat-ui/thread/statewire-history-edge.d.ts +52 -0
- package/dist/chat-ui-statewire.cjs +25 -0
- package/dist/chat-ui-statewire.cjs.map +1 -0
- package/dist/chat-ui-statewire.js +25 -0
- package/dist/chat-ui-statewire.js.map +1 -0
- package/dist/chat-ui.cjs +174 -357
- package/dist/chat-ui.cjs.map +1 -1
- package/dist/chat-ui.js +173 -355
- package/dist/chat-ui.js.map +1 -1
- package/dist/diagnostics/athena-diagnostics.d.ts +1 -1
- package/dist/diagnostics/errors.d.ts +4 -0
- package/dist/index.cjs +2222 -5183
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +21 -6
- package/dist/index.js +4193 -7151
- package/dist/index.js.map +1 -1
- package/dist/misc-tool-uis-B2e0Okkn.cjs +43 -0
- package/dist/misc-tool-uis-B2e0Okkn.cjs.map +1 -0
- package/dist/misc-tool-uis-gAiQw0Yl.js +44 -0
- package/dist/misc-tool-uis-gAiQw0Yl.js.map +1 -0
- package/dist/provider/AthenaProvider.d.ts +4 -2
- package/dist/provider/config.d.ts +9 -2
- package/dist/provider/statewire-window-context.d.ts +12 -0
- package/dist/runtime/statewire-auth-headers.d.ts +38 -0
- package/dist/runtime/statewire-lifecycle.d.ts +25 -0
- package/dist/runtime/statewire-session-key.d.ts +13 -0
- package/dist/runtime/useAthenaStatewireRuntime.d.ts +36 -5
- package/dist/statewire-continue-run-D34gS7_1.js +132 -0
- package/dist/statewire-continue-run-D34gS7_1.js.map +1 -0
- package/dist/statewire-continue-run-nE9VCKUh.cjs +131 -0
- package/dist/statewire-continue-run-nE9VCKUh.cjs.map +1 -0
- package/dist/statewire-history-edge-C8uyTEjX.cjs +1711 -0
- package/dist/statewire-history-edge-C8uyTEjX.cjs.map +1 -0
- package/dist/statewire-history-edge-CPohUKMt.js +1712 -0
- package/dist/statewire-history-edge-CPohUKMt.js.map +1 -0
- package/dist/styles.css +1 -1
- package/dist/super-grouping.cjs +22 -0
- package/dist/super-grouping.cjs.map +1 -0
- package/dist/super-grouping.js +22 -0
- package/dist/super-grouping.js.map +1 -0
- package/dist/threads/mint-thread-id.d.ts +8 -0
- package/dist/threads/statewire-thread-list.d.ts +20 -4
- package/dist/tool-fallback-DkQ3DLkn.js +4281 -0
- package/dist/tool-fallback-DkQ3DLkn.js.map +1 -0
- package/dist/tool-fallback-kfhpJQZa.cjs +4297 -0
- package/dist/tool-fallback-kfhpJQZa.cjs.map +1 -0
- package/dist/tools/index.d.ts +14 -0
- package/dist/tools/misc-tool-uis.d.ts +2 -0
- package/dist/tools/primitives.d.ts +41 -0
- package/dist/tools/tool-fallback.d.ts +78 -6
- package/dist/tools/tool-icons.d.ts +10 -0
- package/dist/tools/tool-uis.d.ts +1 -23
- package/dist/tools.cjs +41 -0
- package/dist/tools.cjs.map +1 -0
- package/dist/tools.js +41 -0
- package/dist/tools.js.map +1 -0
- package/dist/trash-2-B5OaNAL7.cjs +5096 -0
- package/dist/trash-2-B5OaNAL7.cjs.map +1 -0
- package/dist/trash-2-CCwSURL-.js +5081 -0
- package/dist/trash-2-CCwSURL-.js.map +1 -0
- package/dist/{use-rest-conversation-history-Dm0rdQgT.cjs → use-rest-conversation-history-Cm8qMRxp.cjs} +445 -5406
- package/dist/use-rest-conversation-history-Cm8qMRxp.cjs.map +1 -0
- package/dist/{use-rest-conversation-history-Bs5qn5G3.js → use-rest-conversation-history-veDZS-oL.js} +491 -5452
- package/dist/use-rest-conversation-history-veDZS-oL.js.map +1 -0
- package/dist/wrench-BEf72cyP.cjs +417 -0
- package/dist/wrench-BEf72cyP.cjs.map +1 -0
- package/dist/wrench-CbrOlVYm.js +418 -0
- package/dist/wrench-CbrOlVYm.js.map +1 -0
- package/dist/x-Dfd2NzK0.cjs +42 -0
- package/dist/x-Dfd2NzK0.cjs.map +1 -0
- package/dist/x-_DntAa_a.js +43 -0
- package/dist/x-_DntAa_a.js.map +1 -0
- package/package.json +29 -11
- package/dist/chat/super-grouping/tool-status-labels.d.ts +0 -1
- package/dist/use-rest-conversation-history-Bs5qn5G3.js.map +0 -1
- package/dist/use-rest-conversation-history-Dm0rdQgT.cjs.map +0 -1
|
@@ -0,0 +1,1711 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
3
|
+
const react = require("@assistant-ui/react");
|
|
4
|
+
const trash2 = require("./trash-2-B5OaNAL7.cjs");
|
|
5
|
+
const React = require("react");
|
|
6
|
+
require("@assistant-ui/tap");
|
|
7
|
+
require("statewire");
|
|
8
|
+
const reactStatewire = require("@assistant-ui/react-statewire");
|
|
9
|
+
const store = require("@assistant-ui/store");
|
|
10
|
+
const core = require("@assistant-ui/core");
|
|
11
|
+
const x = require("./x-Dfd2NzK0.cjs");
|
|
12
|
+
function isClientToolCallRequest(value) {
|
|
13
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
14
|
+
const candidate = value;
|
|
15
|
+
return typeof candidate.interrupt_id === "string" && candidate.interrupt_id.length > 0 && typeof candidate.tool_name === "string";
|
|
16
|
+
}
|
|
17
|
+
function hasClientToolInterruptSource(payload) {
|
|
18
|
+
return !!payload && typeof payload === "object" && !Array.isArray(payload) && payload.source === trash2.CLIENT_TOOL_INTERRUPT_SOURCE;
|
|
19
|
+
}
|
|
20
|
+
function isClientToolInterrupt(payload) {
|
|
21
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
const candidate = payload;
|
|
25
|
+
return candidate.source === trash2.CLIENT_TOOL_INTERRUPT_SOURCE && candidate.type === trash2.CLIENT_TOOL_INTERRUPT_SOURCE && typeof candidate.context === "object" && candidate.context !== null && Array.isArray(candidate.context.requests) && candidate.context.requests.length > 0 && candidate.context.requests.every(isClientToolCallRequest);
|
|
26
|
+
}
|
|
27
|
+
function clientToolCallArgs(request) {
|
|
28
|
+
const args = request.tool_args;
|
|
29
|
+
return args && typeof args === "object" && !Array.isArray(args) ? args : {};
|
|
30
|
+
}
|
|
31
|
+
function clientToolResultsResumeValue(results) {
|
|
32
|
+
return { client_tool_results: results };
|
|
33
|
+
}
|
|
34
|
+
function clientToolRunConfigEntries(tools) {
|
|
35
|
+
return tools.map(({ definition }) => ({
|
|
36
|
+
name: definition.name,
|
|
37
|
+
description: definition.description,
|
|
38
|
+
parameters: definition.parameters,
|
|
39
|
+
requires_write: definition.requiresWrite
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
function clientToolSuccessEnvelope(result) {
|
|
43
|
+
return {
|
|
44
|
+
status: trash2.CLIENT_TOOL_RESULT_STATUS_SUCCESS,
|
|
45
|
+
result: result === void 0 ? null : result
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function clientToolErrorEnvelope(error) {
|
|
49
|
+
const message = error instanceof Error ? error.message : typeof error === "string" ? error : "Client tool execution failed.";
|
|
50
|
+
return { status: trash2.CLIENT_TOOL_RESULT_STATUS_ERROR, error: message };
|
|
51
|
+
}
|
|
52
|
+
const DEFAULT_MAX_CACHED_CLIENT_TOOL_RESUMES = 128;
|
|
53
|
+
function createClientToolRequestTracker(options = {}) {
|
|
54
|
+
const maxCachedResumes = options.maxCachedResumes ?? DEFAULT_MAX_CACHED_CLIENT_TOOL_RESUMES;
|
|
55
|
+
const requests = /* @__PURE__ */ new Map();
|
|
56
|
+
const pruneCompletedRequests = (protectedRequestId) => {
|
|
57
|
+
let completedCount = 0;
|
|
58
|
+
for (const entry of requests.values()) {
|
|
59
|
+
if (entry.resumeValue !== void 0 || entry.settled === true) completedCount += 1;
|
|
60
|
+
}
|
|
61
|
+
if (completedCount <= maxCachedResumes) return;
|
|
62
|
+
for (const [requestId, entry] of requests) {
|
|
63
|
+
if (completedCount <= maxCachedResumes) break;
|
|
64
|
+
if (requestId === protectedRequestId || entry.resumeValue === void 0 && entry.settled !== true || entry.resumeOwner !== void 0) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
requests.delete(requestId);
|
|
68
|
+
completedCount -= 1;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
return {
|
|
72
|
+
claim(requestId) {
|
|
73
|
+
if (requests.has(requestId)) return false;
|
|
74
|
+
requests.set(requestId, { resumeAttemptCount: 0 });
|
|
75
|
+
return true;
|
|
76
|
+
},
|
|
77
|
+
release(requestId) {
|
|
78
|
+
requests.delete(requestId);
|
|
79
|
+
},
|
|
80
|
+
has(requestId) {
|
|
81
|
+
return requests.has(requestId);
|
|
82
|
+
},
|
|
83
|
+
cacheResume(requestId, value) {
|
|
84
|
+
const entry = requests.get(requestId) ?? { resumeAttemptCount: 0 };
|
|
85
|
+
entry.resumeValue = value;
|
|
86
|
+
entry.settled = false;
|
|
87
|
+
requests.delete(requestId);
|
|
88
|
+
requests.set(requestId, entry);
|
|
89
|
+
pruneCompletedRequests(requestId);
|
|
90
|
+
},
|
|
91
|
+
getCachedResume(requestId) {
|
|
92
|
+
const entry = requests.get(requestId);
|
|
93
|
+
if (!entry || entry.resumeValue === void 0) return void 0;
|
|
94
|
+
return {
|
|
95
|
+
value: entry.resumeValue,
|
|
96
|
+
attemptCount: entry.resumeAttemptCount
|
|
97
|
+
};
|
|
98
|
+
},
|
|
99
|
+
claimResumeReplay(requestId, owner) {
|
|
100
|
+
const entry = requests.get(requestId);
|
|
101
|
+
if (!entry || entry.resumeValue === void 0) return false;
|
|
102
|
+
if (entry.resumeOwner !== void 0 && entry.resumeOwner !== owner) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
entry.resumeOwner = owner;
|
|
106
|
+
return true;
|
|
107
|
+
},
|
|
108
|
+
releaseResumeReplay(requestId, owner) {
|
|
109
|
+
const entry = requests.get(requestId);
|
|
110
|
+
if ((entry == null ? void 0 : entry.resumeOwner) === owner) entry.resumeOwner = void 0;
|
|
111
|
+
pruneCompletedRequests();
|
|
112
|
+
},
|
|
113
|
+
settleResume(requestId) {
|
|
114
|
+
const entry = requests.get(requestId);
|
|
115
|
+
if (!entry) return;
|
|
116
|
+
entry.resumeValue = void 0;
|
|
117
|
+
entry.resumeOwner = void 0;
|
|
118
|
+
entry.settled = true;
|
|
119
|
+
requests.delete(requestId);
|
|
120
|
+
requests.set(requestId, entry);
|
|
121
|
+
pruneCompletedRequests(requestId);
|
|
122
|
+
},
|
|
123
|
+
takeResumeAttempt(requestId, attemptOptions) {
|
|
124
|
+
const entry = requests.get(requestId);
|
|
125
|
+
if (!entry || entry.resumeValue === void 0 || entry.resumeOwner !== attemptOptions.owner || entry.resumeAttemptCount >= attemptOptions.maxAttempts) {
|
|
126
|
+
return void 0;
|
|
127
|
+
}
|
|
128
|
+
entry.resumeAttemptCount += 1;
|
|
129
|
+
return {
|
|
130
|
+
value: entry.resumeValue,
|
|
131
|
+
attemptNumber: entry.resumeAttemptCount
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
function statewireRejectionPayload(error) {
|
|
137
|
+
const failure = error == null ? void 0 : error.failure;
|
|
138
|
+
if ((failure == null ? void 0 : failure.fate) !== "rejected") return null;
|
|
139
|
+
const payload = failure.payload;
|
|
140
|
+
if (typeof (payload == null ? void 0 : payload.status) !== "number") return null;
|
|
141
|
+
return { status: payload.status, detail: payload.detail };
|
|
142
|
+
}
|
|
143
|
+
function statewireRejectionDetailMessage(error) {
|
|
144
|
+
var _a;
|
|
145
|
+
const detail = (_a = statewireRejectionPayload(error)) == null ? void 0 : _a.detail;
|
|
146
|
+
if (typeof detail === "string") return detail.length > 0 ? detail : null;
|
|
147
|
+
if (detail === null || typeof detail !== "object" || Array.isArray(detail)) return null;
|
|
148
|
+
const message = detail.message;
|
|
149
|
+
return typeof message === "string" && message.length > 0 ? message : null;
|
|
150
|
+
}
|
|
151
|
+
function isLegacyThreadReadOnlyRejection(error) {
|
|
152
|
+
const payload = statewireRejectionPayload(error);
|
|
153
|
+
if ((payload == null ? void 0 : payload.status) !== 409) return false;
|
|
154
|
+
const detail = payload.detail;
|
|
155
|
+
return (detail == null ? void 0 : detail.code) === "legacy_thread_read_only";
|
|
156
|
+
}
|
|
157
|
+
function isStatewireChannelTeardown(error) {
|
|
158
|
+
var _a;
|
|
159
|
+
const cause = (_a = error == null ? void 0 : error.failure) == null ? void 0 : _a.cause;
|
|
160
|
+
return typeof cause === "string" && cause !== "server";
|
|
161
|
+
}
|
|
162
|
+
const sanitizeConnectionMessage = (message) => {
|
|
163
|
+
const printable = Array.from(message, (character) => {
|
|
164
|
+
const code = character.charCodeAt(0);
|
|
165
|
+
return code < 32 || code === 127 ? " " : character;
|
|
166
|
+
}).join("").replace(/\s+/g, " ").trim();
|
|
167
|
+
return printable ? printable.slice(0, 200) : void 0;
|
|
168
|
+
};
|
|
169
|
+
function projectDeepAgentConnection(connection) {
|
|
170
|
+
switch (connection.status) {
|
|
171
|
+
case "connected":
|
|
172
|
+
return { status: "connected", degraded: false };
|
|
173
|
+
case "connecting": {
|
|
174
|
+
const message = connection.message === void 0 ? void 0 : sanitizeConnectionMessage(connection.message);
|
|
175
|
+
return {
|
|
176
|
+
status: "connecting",
|
|
177
|
+
attempt: connection.attempt,
|
|
178
|
+
...connection.cause !== void 0 && { cause: connection.cause },
|
|
179
|
+
...connection.lastError !== void 0 && { lastError: connection.lastError },
|
|
180
|
+
...message !== void 0 && { message },
|
|
181
|
+
// A first dial is expected; a retry means the channel dropped.
|
|
182
|
+
degraded: connection.attempt > 0
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
case "disconnected": {
|
|
186
|
+
const message = connection.message === void 0 ? void 0 : sanitizeConnectionMessage(connection.message);
|
|
187
|
+
return {
|
|
188
|
+
status: "disconnected",
|
|
189
|
+
reason: connection.reason,
|
|
190
|
+
...message !== void 0 && { message },
|
|
191
|
+
// Parked (`deferred`) and quiet (`idle`) channels are healthy; only a
|
|
192
|
+
// terminal loss is degraded.
|
|
193
|
+
degraded: connection.reason === "gone"
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
default:
|
|
197
|
+
return unknownConnectionStatus(connection);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
function unknownConnectionStatus(connection) {
|
|
201
|
+
throw new Error(
|
|
202
|
+
`statewire: unknown connection status ${JSON.stringify(
|
|
203
|
+
connection.status
|
|
204
|
+
)}`
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
function isRecord(value) {
|
|
208
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
209
|
+
}
|
|
210
|
+
function isPendingInterrupt(request) {
|
|
211
|
+
return request.type === "interrupt" && !("response" in request);
|
|
212
|
+
}
|
|
213
|
+
function isApprovalCardInterrupt(request) {
|
|
214
|
+
if (!isPendingInterrupt(request)) return false;
|
|
215
|
+
return !hasClientToolInterruptSource(request.payload);
|
|
216
|
+
}
|
|
217
|
+
function asHitlApproval(value) {
|
|
218
|
+
if (!isRecord(value)) return null;
|
|
219
|
+
return value.type === "hitl" && value.source === "hitl_approval" && typeof value.message === "string" ? value : null;
|
|
220
|
+
}
|
|
221
|
+
const DEFAULT_INTERRUPT_PAUSED_MESSAGE = "The agent is paused and waiting for input.";
|
|
222
|
+
function readInterruptMessage(value, fallback = DEFAULT_INTERRUPT_PAUSED_MESSAGE) {
|
|
223
|
+
if (isRecord(value) && typeof value.message === "string" && value.message.length > 0) {
|
|
224
|
+
return value.message;
|
|
225
|
+
}
|
|
226
|
+
return fallback;
|
|
227
|
+
}
|
|
228
|
+
function pendingActionRequests(hitl) {
|
|
229
|
+
const context = hitl == null ? void 0 : hitl.context;
|
|
230
|
+
if (!context) return [];
|
|
231
|
+
const requests = Array.isArray(context.action_requests) ? context.action_requests.filter(isRecord) : context.tool_name && context.tool_args ? [{ name: context.tool_name, args: context.tool_args }] : [];
|
|
232
|
+
return requests.map((request) => ({
|
|
233
|
+
name: typeof request.name === "string" ? request.name : "tool",
|
|
234
|
+
args: isRecord(request.args) ? request.args : {},
|
|
235
|
+
...typeof request.tool_call_id === "string" && { toolCallId: request.tool_call_id },
|
|
236
|
+
...typeof request.interrupt_id === "string" && { interruptId: request.interrupt_id }
|
|
237
|
+
}));
|
|
238
|
+
}
|
|
239
|
+
function readAbandonedInputRequests(state) {
|
|
240
|
+
const abandoned = trash2.readDeepAgentStreamValues(state).abandonedInputRequests;
|
|
241
|
+
return Array.isArray(abandoned) ? abandoned : void 0;
|
|
242
|
+
}
|
|
243
|
+
function findAbandonedInterrupt(abandoned) {
|
|
244
|
+
return abandoned == null ? void 0 : abandoned.find(
|
|
245
|
+
(request) => isRecord(request) && request.type === "interrupt" && typeof request.id === "string"
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
const HITL_REJECT_REASON = "User rejected the action.";
|
|
249
|
+
const HITL_PENDING_RESUME_GRACE_MS = 15e3;
|
|
250
|
+
function hitlResumeApprove() {
|
|
251
|
+
return { action: "approve" };
|
|
252
|
+
}
|
|
253
|
+
function hitlResumeReject(reason = HITL_REJECT_REASON) {
|
|
254
|
+
return { action: "reject", reason };
|
|
255
|
+
}
|
|
256
|
+
function hitlResumeContinue() {
|
|
257
|
+
return { action: "continue" };
|
|
258
|
+
}
|
|
259
|
+
function useApprovalResumeLock(options) {
|
|
260
|
+
const { requestId, isRunning, sendResume, pendingResumeGraceMs } = options;
|
|
261
|
+
const [pending, setPending] = React.useState(false);
|
|
262
|
+
const prevRequestIdRef = React.useRef(requestId);
|
|
263
|
+
if (prevRequestIdRef.current !== requestId) {
|
|
264
|
+
prevRequestIdRef.current = requestId;
|
|
265
|
+
if (pending) setPending(false);
|
|
266
|
+
}
|
|
267
|
+
const sawResumeRunRef = React.useRef(false);
|
|
268
|
+
React.useEffect(() => {
|
|
269
|
+
if (!pending) {
|
|
270
|
+
sawResumeRunRef.current = false;
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
if (isRunning) {
|
|
274
|
+
sawResumeRunRef.current = true;
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
if (sawResumeRunRef.current) {
|
|
278
|
+
sawResumeRunRef.current = false;
|
|
279
|
+
setPending(false);
|
|
280
|
+
}
|
|
281
|
+
}, [pending, isRunning]);
|
|
282
|
+
React.useEffect(() => {
|
|
283
|
+
if (!pending || pendingResumeGraceMs === void 0) return;
|
|
284
|
+
const timer = setTimeout(() => {
|
|
285
|
+
if (!sawResumeRunRef.current) setPending(false);
|
|
286
|
+
}, pendingResumeGraceMs);
|
|
287
|
+
return () => clearTimeout(timer);
|
|
288
|
+
}, [pending, requestId, pendingResumeGraceMs]);
|
|
289
|
+
const sendResumeRef = React.useRef(sendResume);
|
|
290
|
+
sendResumeRef.current = sendResume;
|
|
291
|
+
const pendingRef = React.useRef(pending);
|
|
292
|
+
pendingRef.current = pending;
|
|
293
|
+
const resume = React.useCallback(
|
|
294
|
+
(value) => {
|
|
295
|
+
if (requestId === void 0 || pendingRef.current) return;
|
|
296
|
+
setPending(true);
|
|
297
|
+
pendingRef.current = true;
|
|
298
|
+
sendResumeRef.current(requestId, value);
|
|
299
|
+
},
|
|
300
|
+
[requestId]
|
|
301
|
+
);
|
|
302
|
+
return { pending, resume };
|
|
303
|
+
}
|
|
304
|
+
function queueEntryText(parts) {
|
|
305
|
+
return parts.flatMap(
|
|
306
|
+
(part) => part.type === "text" && typeof part.text === "string" ? [part.text] : []
|
|
307
|
+
).join("\n\n");
|
|
308
|
+
}
|
|
309
|
+
function isQueueEntryUnsettled(entry) {
|
|
310
|
+
return entry.meta === void 0;
|
|
311
|
+
}
|
|
312
|
+
function readPrioritizedQueueIds(raw) {
|
|
313
|
+
return Array.isArray(raw) ? raw.filter((id) => typeof id === "string") : [];
|
|
314
|
+
}
|
|
315
|
+
function queueLaneFlags(status) {
|
|
316
|
+
return {
|
|
317
|
+
isRunning: status === "running",
|
|
318
|
+
isContinuable: status === "stopped" || status === "error"
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
function buildStatewireQueueRows(options) {
|
|
322
|
+
const { queue, steerQueue, isContinuable } = options;
|
|
323
|
+
return [
|
|
324
|
+
...isContinuable ? steerQueue.map((item) => ({ item, lane: "steer" })) : [],
|
|
325
|
+
...queue.map((item) => ({ item, lane: "queue" }))
|
|
326
|
+
];
|
|
327
|
+
}
|
|
328
|
+
function showQueueRowSendNow(options) {
|
|
329
|
+
const { lane, index, isRunning, isContinuable } = options;
|
|
330
|
+
return lane === "queue" && (isContinuable || isRunning && index === 0);
|
|
331
|
+
}
|
|
332
|
+
function buildQueueEditCommand(options) {
|
|
333
|
+
const { item, lane, runId, text } = options;
|
|
334
|
+
if (!text.trim() || text === queueEntryText(item.parts) || runId === null) {
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
const message = {
|
|
338
|
+
id: item.id,
|
|
339
|
+
role: "user",
|
|
340
|
+
parts: [{ type: "text", text }, ...item.parts.filter((part) => part.type !== "text")],
|
|
341
|
+
...item.metadata === void 0 ? {} : { metadata: item.metadata }
|
|
342
|
+
};
|
|
343
|
+
return lane === "steer" ? { type: "run/steer", runId, message } : { type: "run/enqueue", runId, message };
|
|
344
|
+
}
|
|
345
|
+
const QUEUE_AUTO_CONTINUE_DELAY_MS = 2e3;
|
|
346
|
+
function userStopBlocksQueueAutoContinue(options) {
|
|
347
|
+
return options.marker === trash2.ATHENA_RUN_MARKER_CANCELLED && options.source !== trash2.ATHENA_STOP_SOURCE_POD_DRAIN;
|
|
348
|
+
}
|
|
349
|
+
function describeQueueSendFailure(failure) {
|
|
350
|
+
const message = "message" in failure && failure.message !== void 0 ? `: ${failure.message}` : "";
|
|
351
|
+
return `${failure.fate} (${failure.cause})${message}`;
|
|
352
|
+
}
|
|
353
|
+
function isFailedSendEntryRace(error) {
|
|
354
|
+
return error instanceof Error && error.message.startsWith("statewire: unknown failed");
|
|
355
|
+
}
|
|
356
|
+
function hasStatewireThreadExtras(extras) {
|
|
357
|
+
if (!extras || typeof extras !== "object") return false;
|
|
358
|
+
const candidate = extras;
|
|
359
|
+
return typeof candidate.sendCommand === "function" && Array.isArray(candidate.inputRequests) && typeof candidate.runs === "object" && candidate.runs !== null;
|
|
360
|
+
}
|
|
361
|
+
function isFailedSendEntry(value) {
|
|
362
|
+
var _a;
|
|
363
|
+
if (!value || typeof value !== "object") return false;
|
|
364
|
+
const entry = value;
|
|
365
|
+
return typeof entry.id === "string" && typeof ((_a = entry.sendFailure) == null ? void 0 : _a.fate) === "string";
|
|
366
|
+
}
|
|
367
|
+
function readStatewireFailedSendLane(extras) {
|
|
368
|
+
var _a;
|
|
369
|
+
if (!extras || typeof extras !== "object") return null;
|
|
370
|
+
const candidate = extras;
|
|
371
|
+
const failed = (_a = candidate.runs) == null ? void 0 : _a.failed;
|
|
372
|
+
if (!Array.isArray(failed) || typeof candidate.retryFailed !== "function") return null;
|
|
373
|
+
return {
|
|
374
|
+
failed: failed.filter(isFailedSendEntry),
|
|
375
|
+
retryFailed: candidate.retryFailed
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
function requireStatewireFailedActions(extras) {
|
|
379
|
+
if (!extras || typeof extras !== "object") {
|
|
380
|
+
throw new Error("Failed-send actions require a Statewire thread");
|
|
381
|
+
}
|
|
382
|
+
const candidate = extras;
|
|
383
|
+
if (typeof candidate.retryFailed !== "function" || typeof candidate.discardFailed !== "function") {
|
|
384
|
+
throw new Error("Failed-send actions require a Statewire thread");
|
|
385
|
+
}
|
|
386
|
+
return candidate;
|
|
387
|
+
}
|
|
388
|
+
const DEEP_AGENT_MAX_CHAINED_HISTORY_LOADS = 3;
|
|
389
|
+
function selectMessagesWindowLane(state) {
|
|
390
|
+
return typeof state === "object" && state !== null ? state[trash2.DEEP_AGENT_MESSAGES_WINDOW_STATE_KEY] : void 0;
|
|
391
|
+
}
|
|
392
|
+
function useDeepAgentMessagesWindow() {
|
|
393
|
+
const lane = reactStatewire.useStatewireState(selectMessagesWindowLane);
|
|
394
|
+
return React.useMemo(
|
|
395
|
+
() => trash2.readDeepAgentMessagesWindow({ [trash2.DEEP_AGENT_MESSAGES_WINDOW_STATE_KEY]: lane }),
|
|
396
|
+
[lane]
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
const everyMessageMounted = () => true;
|
|
400
|
+
const defaultNow = () => Date.now();
|
|
401
|
+
function useDeepAgentWindowSync({
|
|
402
|
+
messages,
|
|
403
|
+
toolOutputs,
|
|
404
|
+
nearTop = false,
|
|
405
|
+
nearTopEpoch = 0,
|
|
406
|
+
isMessageMounted = everyMessageMounted,
|
|
407
|
+
maxChainedLoads = DEEP_AGENT_MAX_CHAINED_HISTORY_LOADS,
|
|
408
|
+
onHistoryLoad,
|
|
409
|
+
onError,
|
|
410
|
+
now = defaultNow
|
|
411
|
+
}) {
|
|
412
|
+
const sendCommand = reactStatewire.useStatewireSendCommand();
|
|
413
|
+
const window = useDeepAgentMessagesWindow();
|
|
414
|
+
const [loading, setLoading] = React.useState(false);
|
|
415
|
+
const [requests, setRequests] = React.useState(0);
|
|
416
|
+
const [settledLoads, setSettledLoads] = React.useState(0);
|
|
417
|
+
const servedRequestsRef = React.useRef(0);
|
|
418
|
+
const inflightRef = React.useRef(null);
|
|
419
|
+
const chainRef = React.useRef({ epoch: 0, loads: 0 });
|
|
420
|
+
const aliveRef = React.useRef(true);
|
|
421
|
+
const windowRef = React.useRef(window);
|
|
422
|
+
windowRef.current = window;
|
|
423
|
+
const answeredRef = React.useRef(/* @__PURE__ */ new Map());
|
|
424
|
+
const onHistoryLoadRef = React.useRef(onHistoryLoad);
|
|
425
|
+
onHistoryLoadRef.current = onHistoryLoad;
|
|
426
|
+
const onErrorRef = React.useRef(onError);
|
|
427
|
+
onErrorRef.current = onError;
|
|
428
|
+
const nowRef = React.useRef(now);
|
|
429
|
+
nowRef.current = now;
|
|
430
|
+
React.useEffect(() => {
|
|
431
|
+
aliveRef.current = true;
|
|
432
|
+
return () => {
|
|
433
|
+
aliveRef.current = false;
|
|
434
|
+
};
|
|
435
|
+
}, []);
|
|
436
|
+
React.useEffect(() => {
|
|
437
|
+
if (window === null || window.start === 0 || inflightRef.current !== null) return;
|
|
438
|
+
const requested = requests !== servedRequestsRef.current;
|
|
439
|
+
if (requested) {
|
|
440
|
+
servedRequestsRef.current = requests;
|
|
441
|
+
chainRef.current = { epoch: nearTopEpoch, loads: 1 };
|
|
442
|
+
} else {
|
|
443
|
+
if (!nearTop) return;
|
|
444
|
+
if (chainRef.current.epoch !== nearTopEpoch) {
|
|
445
|
+
chainRef.current = { epoch: nearTopEpoch, loads: 0 };
|
|
446
|
+
}
|
|
447
|
+
if (chainRef.current.loads >= maxChainedLoads) return;
|
|
448
|
+
chainRef.current.loads += 1;
|
|
449
|
+
}
|
|
450
|
+
const command = trash2.buildHistoryLoadCommand({ window });
|
|
451
|
+
if (command === null) return;
|
|
452
|
+
inflightRef.current = command.beforeIndex;
|
|
453
|
+
setLoading(true);
|
|
454
|
+
const startedAt = nowRef.current();
|
|
455
|
+
Promise.resolve(sendCommand(command)).then((payload) => {
|
|
456
|
+
var _a;
|
|
457
|
+
(_a = onHistoryLoadRef.current) == null ? void 0 : _a.call(onHistoryLoadRef, {
|
|
458
|
+
beforeIndex: command.beforeIndex,
|
|
459
|
+
limit: command.limit,
|
|
460
|
+
result: trash2.readHistoryLoadResult(payload),
|
|
461
|
+
durationMs: Math.max(0, Math.round(nowRef.current() - startedAt))
|
|
462
|
+
});
|
|
463
|
+
}).catch((error) => {
|
|
464
|
+
var _a;
|
|
465
|
+
(_a = onErrorRef.current) == null ? void 0 : _a.call(onErrorRef, error, "history/load");
|
|
466
|
+
}).finally(() => {
|
|
467
|
+
var _a;
|
|
468
|
+
inflightRef.current = null;
|
|
469
|
+
if (!aliveRef.current) return;
|
|
470
|
+
setLoading(false);
|
|
471
|
+
if (((_a = windowRef.current) == null ? void 0 : _a.start) !== command.beforeIndex) {
|
|
472
|
+
setSettledLoads((count) => count + 1);
|
|
473
|
+
}
|
|
474
|
+
});
|
|
475
|
+
}, [nearTop, nearTopEpoch, requests, settledLoads, window, sendCommand, maxChainedLoads]);
|
|
476
|
+
React.useEffect(() => {
|
|
477
|
+
var _a;
|
|
478
|
+
if (window === null || toolOutputs === void 0) return;
|
|
479
|
+
for (const message of messages) {
|
|
480
|
+
if (!isMessageMounted(message.id)) continue;
|
|
481
|
+
for (const part of message.content) {
|
|
482
|
+
if (part.type !== "tool-call") continue;
|
|
483
|
+
const marker = trash2.readTruncatedToolOutputArtifact(part.artifact);
|
|
484
|
+
if (marker === null || toolOutputs.isPending(marker.messageId)) continue;
|
|
485
|
+
if (((_a = toolOutputs.entry(marker.messageId)) == null ? void 0 : _a.chars) === marker.chars) continue;
|
|
486
|
+
if (answeredRef.current.get(marker.messageId) === marker.chars) continue;
|
|
487
|
+
const { messageId, chars } = marker;
|
|
488
|
+
toolOutputs.markPending(messageId);
|
|
489
|
+
Promise.resolve(sendCommand(trash2.buildToolOutputCommand({ messageId }))).then((payload) => {
|
|
490
|
+
answeredRef.current.set(messageId, chars);
|
|
491
|
+
const result = trash2.readToolOutputResult(payload);
|
|
492
|
+
if (result === null) {
|
|
493
|
+
toolOutputs.clearPending(messageId);
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
toolOutputs.set(result.messageId, { content: result.content, chars });
|
|
497
|
+
}).catch((error) => {
|
|
498
|
+
var _a2;
|
|
499
|
+
answeredRef.current.set(messageId, chars);
|
|
500
|
+
toolOutputs.clearPending(messageId);
|
|
501
|
+
(_a2 = onErrorRef.current) == null ? void 0 : _a2.call(onErrorRef, error, "history/tool_output");
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}, [messages, isMessageMounted, window, sendCommand, toolOutputs]);
|
|
506
|
+
const loadOlder = React.useCallback(() => {
|
|
507
|
+
setRequests((count) => count + 1);
|
|
508
|
+
}, []);
|
|
509
|
+
return { window, olderCount: (window == null ? void 0 : window.start) ?? 0, loading, loadOlder };
|
|
510
|
+
}
|
|
511
|
+
function useDeepAgentThreadStatus() {
|
|
512
|
+
return store.useAuiState((s) => {
|
|
513
|
+
var _a;
|
|
514
|
+
const status = (_a = s.thread.extras) == null ? void 0 : _a.status;
|
|
515
|
+
if (status === void 0) {
|
|
516
|
+
throw new Error("useDeepAgentThreadStatus requires a statewire thread");
|
|
517
|
+
}
|
|
518
|
+
return status;
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
const MAX_STEPS_HINT = "Raise “Max steps” in the agent settings for longer runs.";
|
|
522
|
+
function describeTerminationReason(kind, reason) {
|
|
523
|
+
switch (kind) {
|
|
524
|
+
case "paused":
|
|
525
|
+
return {
|
|
526
|
+
title: "Paused by a server update",
|
|
527
|
+
detail: "Progress up to this point is saved — send a message to continue."
|
|
528
|
+
};
|
|
529
|
+
case "stopped":
|
|
530
|
+
switch (reason) {
|
|
531
|
+
case "transport_cancel":
|
|
532
|
+
return {
|
|
533
|
+
title: "Run cancelled",
|
|
534
|
+
detail: "Cancelled by a page reload, navigation, or closed view — not an explicit Stop. Send a follow-up to continue."
|
|
535
|
+
};
|
|
536
|
+
case "fence_lost":
|
|
537
|
+
return {
|
|
538
|
+
title: "Run superseded",
|
|
539
|
+
detail: "Another activation took over this thread."
|
|
540
|
+
};
|
|
541
|
+
case "instance_closed":
|
|
542
|
+
return {
|
|
543
|
+
title: "Run stopped",
|
|
544
|
+
detail: "The client that started it went away."
|
|
545
|
+
};
|
|
546
|
+
default:
|
|
547
|
+
return { title: "Conversation stopped", detail: void 0 };
|
|
548
|
+
}
|
|
549
|
+
case "failed":
|
|
550
|
+
switch (reason) {
|
|
551
|
+
case "recursion_limit":
|
|
552
|
+
return {
|
|
553
|
+
title: "Step limit reached",
|
|
554
|
+
detail: `The run was stopped before finishing; the work so far is saved. ${MAX_STEPS_HINT}`
|
|
555
|
+
};
|
|
556
|
+
case "abandoned":
|
|
557
|
+
return {
|
|
558
|
+
title: "Run stopped unexpectedly",
|
|
559
|
+
detail: "The server handling it went away mid-run (a crash, restart, or deploy). The work so far is saved."
|
|
560
|
+
};
|
|
561
|
+
default:
|
|
562
|
+
return { title: "Run failed", detail: void 0 };
|
|
563
|
+
}
|
|
564
|
+
case "handoff":
|
|
565
|
+
switch (reason) {
|
|
566
|
+
case "duplicate_call_guard":
|
|
567
|
+
return {
|
|
568
|
+
title: "Run ended by the runtime",
|
|
569
|
+
detail: "The same tool calls were repeating with identical arguments and no new progress, so the agent was asked to wrap up."
|
|
570
|
+
};
|
|
571
|
+
case "step_budget":
|
|
572
|
+
return {
|
|
573
|
+
title: "Run ended by the runtime",
|
|
574
|
+
detail: `The step budget ran out, so the agent was asked to wrap up. ${MAX_STEPS_HINT}`
|
|
575
|
+
};
|
|
576
|
+
default:
|
|
577
|
+
return {
|
|
578
|
+
title: "Run ended by the runtime",
|
|
579
|
+
detail: "The agent was asked to wrap up."
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
const SEVERITY = {
|
|
585
|
+
stopped: "info",
|
|
586
|
+
paused: "info",
|
|
587
|
+
failed: "error",
|
|
588
|
+
handoff: "warning"
|
|
589
|
+
};
|
|
590
|
+
function metadataOf(kwargs) {
|
|
591
|
+
const metadata = kwargs == null ? void 0 : kwargs.metadata;
|
|
592
|
+
return typeof metadata === "object" && metadata !== null ? metadata : void 0;
|
|
593
|
+
}
|
|
594
|
+
function readTerminationReason(kwargs) {
|
|
595
|
+
var _a;
|
|
596
|
+
const top = kwargs == null ? void 0 : kwargs[trash2.ATHENA_TERMINATION_REASON_KEY];
|
|
597
|
+
if (typeof top === "string") return top;
|
|
598
|
+
const mirrored = (_a = metadataOf(kwargs)) == null ? void 0 : _a[trash2.ATHENA_TERMINATION_REASON_KEY];
|
|
599
|
+
return typeof mirrored === "string" ? mirrored : void 0;
|
|
600
|
+
}
|
|
601
|
+
function readHandoff(kwargs) {
|
|
602
|
+
var _a;
|
|
603
|
+
return (kwargs == null ? void 0 : kwargs[trash2.ATHENA_HANDOFF_KEY]) === true || ((_a = metadataOf(kwargs)) == null ? void 0 : _a[trash2.ATHENA_HANDOFF_KEY]) === true;
|
|
604
|
+
}
|
|
605
|
+
function textOf(content) {
|
|
606
|
+
if (typeof content === "string") return content;
|
|
607
|
+
if (!Array.isArray(content)) return void 0;
|
|
608
|
+
const texts = content.map(
|
|
609
|
+
(block) => typeof block === "string" ? block : block && typeof block === "object" && block.type === "text" ? block.text : void 0
|
|
610
|
+
).filter((text) => typeof text === "string" && text.length > 0);
|
|
611
|
+
return texts.length > 0 ? texts.join("\n") : void 0;
|
|
612
|
+
}
|
|
613
|
+
function fromMarker(marker, source, reason) {
|
|
614
|
+
if (marker === trash2.ATHENA_RUN_MARKER_CANCELLED) {
|
|
615
|
+
const kind = source === trash2.ATHENA_STOP_SOURCE_POD_DRAIN ? "paused" : "stopped";
|
|
616
|
+
return {
|
|
617
|
+
kind,
|
|
618
|
+
reason: reason ?? (source === "unattributed" ? "unattributed_stop" : source),
|
|
619
|
+
silent: source === trash2.ATHENA_STOP_SOURCE_SEND_NOW
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
if (marker === trash2.ATHENA_RUN_MARKER_FAILED) {
|
|
623
|
+
return { kind: "failed", reason: reason ?? "error", silent: false };
|
|
624
|
+
}
|
|
625
|
+
return void 0;
|
|
626
|
+
}
|
|
627
|
+
function build(partial, text, isSoleSourceMessage) {
|
|
628
|
+
const description = describeTerminationReason(partial.kind, partial.reason);
|
|
629
|
+
return {
|
|
630
|
+
kind: partial.kind,
|
|
631
|
+
reason: partial.reason,
|
|
632
|
+
severity: SEVERITY[partial.kind],
|
|
633
|
+
title: description.title,
|
|
634
|
+
detail: description.detail,
|
|
635
|
+
text,
|
|
636
|
+
silent: partial.silent,
|
|
637
|
+
isSoleSourceMessage
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
function readRuntimeMessageFromSourceMessages(message) {
|
|
641
|
+
var _a;
|
|
642
|
+
const sources = core.getExternalStoreMessages(message);
|
|
643
|
+
for (const source of sources) {
|
|
644
|
+
if ((source == null ? void 0 : source.type) !== "ai") continue;
|
|
645
|
+
const kwargs = source.additional_kwargs;
|
|
646
|
+
const marker = kwargs == null ? void 0 : kwargs[trash2.ATHENA_RUN_MARKER_KEY];
|
|
647
|
+
const reason = readTerminationReason(kwargs);
|
|
648
|
+
const text = textOf(source.content);
|
|
649
|
+
if (typeof marker === "string") {
|
|
650
|
+
const markerSource = kwargs == null ? void 0 : kwargs[trash2.ATHENA_RUN_MARKER_SOURCE_KEY];
|
|
651
|
+
const partial = fromMarker(
|
|
652
|
+
marker,
|
|
653
|
+
typeof markerSource === "string" ? markerSource : void 0,
|
|
654
|
+
reason
|
|
655
|
+
);
|
|
656
|
+
if (partial) return build(partial, text, sources.length === 1);
|
|
657
|
+
}
|
|
658
|
+
if (readHandoff(kwargs)) {
|
|
659
|
+
return build({ kind: "handoff", reason, silent: false }, text, sources.length === 1);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
const custom = (_a = message.metadata) == null ? void 0 : _a.custom;
|
|
663
|
+
if (!custom) return void 0;
|
|
664
|
+
const parts = message.content;
|
|
665
|
+
const sole = Array.isArray(parts) ? parts.length <= 1 : true;
|
|
666
|
+
const joinedMarker = custom[trash2.ATHENA_RUN_MARKER_KEY];
|
|
667
|
+
const joinedReason = readTerminationReason({ metadata: custom });
|
|
668
|
+
if (typeof joinedMarker === "string") {
|
|
669
|
+
const joinedSource = custom[trash2.ATHENA_RUN_MARKER_SOURCE_KEY];
|
|
670
|
+
const partial = fromMarker(
|
|
671
|
+
joinedMarker,
|
|
672
|
+
typeof joinedSource === "string" ? joinedSource : void 0,
|
|
673
|
+
joinedReason
|
|
674
|
+
);
|
|
675
|
+
if (partial) return build(partial, void 0, sole);
|
|
676
|
+
}
|
|
677
|
+
if (custom[trash2.ATHENA_HANDOFF_KEY] === true) {
|
|
678
|
+
return build({ kind: "handoff", reason: joinedReason, silent: false }, void 0, sole);
|
|
679
|
+
}
|
|
680
|
+
return void 0;
|
|
681
|
+
}
|
|
682
|
+
function runtimeMessageMarkerText(message) {
|
|
683
|
+
var _a;
|
|
684
|
+
if (message.kind !== "failed" || message.detail) return void 0;
|
|
685
|
+
const text = (_a = message.text) == null ? void 0 : _a.replace(/^(?:⏹️|⏸️|⚠️|\s)+/u, "").trim();
|
|
686
|
+
if (!text || text === message.title) return void 0;
|
|
687
|
+
return text;
|
|
688
|
+
}
|
|
689
|
+
function readSoleRuntimeMessageKind(message) {
|
|
690
|
+
const found = readRuntimeMessageFromSourceMessages(message);
|
|
691
|
+
return (found == null ? void 0 : found.isSoleSourceMessage) ? found.kind : void 0;
|
|
692
|
+
}
|
|
693
|
+
const StatewireToolOutputsContext = React.createContext(null);
|
|
694
|
+
function useStatewireToolOutputs() {
|
|
695
|
+
return React.useContext(StatewireToolOutputsContext);
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* @license lucide-react v0.575.0 - ISC
|
|
699
|
+
*
|
|
700
|
+
* This source code is licensed under the ISC license.
|
|
701
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
702
|
+
*/
|
|
703
|
+
const __iconNode$7 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
|
|
704
|
+
const LoaderCircle = trash2.createLucideIcon("loader-circle", __iconNode$7);
|
|
705
|
+
/**
|
|
706
|
+
* @license lucide-react v0.575.0 - ISC
|
|
707
|
+
*
|
|
708
|
+
* This source code is licensed under the ISC license.
|
|
709
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
710
|
+
*/
|
|
711
|
+
const __iconNode$6 = [
|
|
712
|
+
["path", { d: "m15 9-6 6", key: "1uzhvr" }],
|
|
713
|
+
[
|
|
714
|
+
"path",
|
|
715
|
+
{
|
|
716
|
+
d: "M2.586 16.726A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2h6.624a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688a2 2 0 0 1-1.414.586H8.688a2 2 0 0 1-1.414-.586z",
|
|
717
|
+
key: "2d38gg"
|
|
718
|
+
}
|
|
719
|
+
],
|
|
720
|
+
["path", { d: "m9 9 6 6", key: "z0biqf" }]
|
|
721
|
+
];
|
|
722
|
+
const OctagonX = trash2.createLucideIcon("octagon-x", __iconNode$6);
|
|
723
|
+
/**
|
|
724
|
+
* @license lucide-react v0.575.0 - ISC
|
|
725
|
+
*
|
|
726
|
+
* This source code is licensed under the ISC license.
|
|
727
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
728
|
+
*/
|
|
729
|
+
const __iconNode$5 = [
|
|
730
|
+
[
|
|
731
|
+
"path",
|
|
732
|
+
{
|
|
733
|
+
d: "M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",
|
|
734
|
+
key: "1a8usu"
|
|
735
|
+
}
|
|
736
|
+
],
|
|
737
|
+
["path", { d: "m15 5 4 4", key: "1mk7zo" }]
|
|
738
|
+
];
|
|
739
|
+
const Pencil = trash2.createLucideIcon("pencil", __iconNode$5);
|
|
740
|
+
/**
|
|
741
|
+
* @license lucide-react v0.575.0 - ISC
|
|
742
|
+
*
|
|
743
|
+
* This source code is licensed under the ISC license.
|
|
744
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
745
|
+
*/
|
|
746
|
+
const __iconNode$4 = [
|
|
747
|
+
["path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8", key: "1357e3" }],
|
|
748
|
+
["path", { d: "M3 3v5h5", key: "1xhq8a" }]
|
|
749
|
+
];
|
|
750
|
+
const RotateCcw = trash2.createLucideIcon("rotate-ccw", __iconNode$4);
|
|
751
|
+
/**
|
|
752
|
+
* @license lucide-react v0.575.0 - ISC
|
|
753
|
+
*
|
|
754
|
+
* This source code is licensed under the ISC license.
|
|
755
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
756
|
+
*/
|
|
757
|
+
const __iconNode$3 = [
|
|
758
|
+
[
|
|
759
|
+
"path",
|
|
760
|
+
{
|
|
761
|
+
d: "M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z",
|
|
762
|
+
key: "1ffxy3"
|
|
763
|
+
}
|
|
764
|
+
],
|
|
765
|
+
["path", { d: "m21.854 2.147-10.94 10.939", key: "12cjpa" }]
|
|
766
|
+
];
|
|
767
|
+
const Send = trash2.createLucideIcon("send", __iconNode$3);
|
|
768
|
+
/**
|
|
769
|
+
* @license lucide-react v0.575.0 - ISC
|
|
770
|
+
*
|
|
771
|
+
* This source code is licensed under the ISC license.
|
|
772
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
773
|
+
*/
|
|
774
|
+
const __iconNode$2 = [
|
|
775
|
+
["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }]
|
|
776
|
+
];
|
|
777
|
+
const Square = trash2.createLucideIcon("square", __iconNode$2);
|
|
778
|
+
/**
|
|
779
|
+
* @license lucide-react v0.575.0 - ISC
|
|
780
|
+
*
|
|
781
|
+
* This source code is licensed under the ISC license.
|
|
782
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
783
|
+
*/
|
|
784
|
+
const __iconNode$1 = [
|
|
785
|
+
[
|
|
786
|
+
"path",
|
|
787
|
+
{
|
|
788
|
+
d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3",
|
|
789
|
+
key: "wmoenq"
|
|
790
|
+
}
|
|
791
|
+
],
|
|
792
|
+
["path", { d: "M12 9v4", key: "juzpu7" }],
|
|
793
|
+
["path", { d: "M12 17h.01", key: "p32p05" }]
|
|
794
|
+
];
|
|
795
|
+
const TriangleAlert = trash2.createLucideIcon("triangle-alert", __iconNode$1);
|
|
796
|
+
/**
|
|
797
|
+
* @license lucide-react v0.575.0 - ISC
|
|
798
|
+
*
|
|
799
|
+
* This source code is licensed under the ISC license.
|
|
800
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
801
|
+
*/
|
|
802
|
+
const __iconNode = [
|
|
803
|
+
[
|
|
804
|
+
"path",
|
|
805
|
+
{
|
|
806
|
+
d: "M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z",
|
|
807
|
+
key: "1xq2db"
|
|
808
|
+
}
|
|
809
|
+
]
|
|
810
|
+
];
|
|
811
|
+
const Zap = trash2.createLucideIcon("zap", __iconNode);
|
|
812
|
+
function r(e) {
|
|
813
|
+
var t, f, n = "";
|
|
814
|
+
if ("string" == typeof e || "number" == typeof e) n += e;
|
|
815
|
+
else if ("object" == typeof e) if (Array.isArray(e)) {
|
|
816
|
+
var o = e.length;
|
|
817
|
+
for (t = 0; t < o; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f);
|
|
818
|
+
} else for (f in e) e[f] && (n && (n += " "), n += f);
|
|
819
|
+
return n;
|
|
820
|
+
}
|
|
821
|
+
function clsx() {
|
|
822
|
+
for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
|
|
823
|
+
return n;
|
|
824
|
+
}
|
|
825
|
+
const falsyToString = (value) => typeof value === "boolean" ? `${value}` : value === 0 ? "0" : value;
|
|
826
|
+
const cx = clsx;
|
|
827
|
+
const cva = (base, config) => (props) => {
|
|
828
|
+
var _config_compoundVariants;
|
|
829
|
+
if ((config === null || config === void 0 ? void 0 : config.variants) == null) return cx(base, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);
|
|
830
|
+
const { variants, defaultVariants } = config;
|
|
831
|
+
const getVariantClassNames = Object.keys(variants).map((variant) => {
|
|
832
|
+
const variantProp = props === null || props === void 0 ? void 0 : props[variant];
|
|
833
|
+
const defaultVariantProp = defaultVariants === null || defaultVariants === void 0 ? void 0 : defaultVariants[variant];
|
|
834
|
+
if (variantProp === null) return null;
|
|
835
|
+
const variantKey = falsyToString(variantProp) || falsyToString(defaultVariantProp);
|
|
836
|
+
return variants[variant][variantKey];
|
|
837
|
+
});
|
|
838
|
+
const propsWithoutUndefined = props && Object.entries(props).reduce((acc, param) => {
|
|
839
|
+
let [key, value] = param;
|
|
840
|
+
if (value === void 0) {
|
|
841
|
+
return acc;
|
|
842
|
+
}
|
|
843
|
+
acc[key] = value;
|
|
844
|
+
return acc;
|
|
845
|
+
}, {});
|
|
846
|
+
const getCompoundVariantClassNames = config === null || config === void 0 ? void 0 : (_config_compoundVariants = config.compoundVariants) === null || _config_compoundVariants === void 0 ? void 0 : _config_compoundVariants.reduce((acc, param) => {
|
|
847
|
+
let { class: cvClass, className: cvClassName, ...compoundVariantOptions } = param;
|
|
848
|
+
return Object.entries(compoundVariantOptions).every((param2) => {
|
|
849
|
+
let [key, value] = param2;
|
|
850
|
+
return Array.isArray(value) ? value.includes({
|
|
851
|
+
...defaultVariants,
|
|
852
|
+
...propsWithoutUndefined
|
|
853
|
+
}[key]) : {
|
|
854
|
+
...defaultVariants,
|
|
855
|
+
...propsWithoutUndefined
|
|
856
|
+
}[key] === value;
|
|
857
|
+
}) ? [
|
|
858
|
+
...acc,
|
|
859
|
+
cvClass,
|
|
860
|
+
cvClassName
|
|
861
|
+
] : acc;
|
|
862
|
+
}, []);
|
|
863
|
+
return cx(base, getVariantClassNames, getCompoundVariantClassNames, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);
|
|
864
|
+
};
|
|
865
|
+
const buttonVariants = cva(
|
|
866
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
|
867
|
+
{
|
|
868
|
+
variants: {
|
|
869
|
+
variant: {
|
|
870
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
871
|
+
destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
872
|
+
outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
|
|
873
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
874
|
+
ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
875
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
876
|
+
},
|
|
877
|
+
size: {
|
|
878
|
+
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
879
|
+
xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
880
|
+
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
|
881
|
+
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
882
|
+
icon: "size-9",
|
|
883
|
+
"icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
|
|
884
|
+
"icon-sm": "size-8",
|
|
885
|
+
"icon-lg": "size-10"
|
|
886
|
+
}
|
|
887
|
+
},
|
|
888
|
+
defaultVariants: {
|
|
889
|
+
variant: "default",
|
|
890
|
+
size: "default"
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
);
|
|
894
|
+
function Button({
|
|
895
|
+
className,
|
|
896
|
+
variant = "default",
|
|
897
|
+
size = "default",
|
|
898
|
+
asChild = false,
|
|
899
|
+
...props
|
|
900
|
+
}) {
|
|
901
|
+
const Comp = asChild ? trash2.Slot : "button";
|
|
902
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
903
|
+
Comp,
|
|
904
|
+
{
|
|
905
|
+
"data-slot": "button",
|
|
906
|
+
"data-variant": variant,
|
|
907
|
+
"data-size": size,
|
|
908
|
+
className: trash2.cn(buttonVariants({ variant, size, className })),
|
|
909
|
+
...props
|
|
910
|
+
}
|
|
911
|
+
);
|
|
912
|
+
}
|
|
913
|
+
function useStatewireApprovalRequest(options = {}) {
|
|
914
|
+
var _a;
|
|
915
|
+
const {
|
|
916
|
+
interruptPredicate = isApprovalCardInterrupt,
|
|
917
|
+
pendingResumeGraceMs = HITL_PENDING_RESUME_GRACE_MS
|
|
918
|
+
} = options;
|
|
919
|
+
const sendCommand = reactStatewire.useStatewireSendCommand();
|
|
920
|
+
const request = (_a = reactStatewire.useStatewireRuns().inputRequests) == null ? void 0 : _a.find(interruptPredicate);
|
|
921
|
+
const requestId = request == null ? void 0 : request.id;
|
|
922
|
+
const abandoned = reactStatewire.useStatewireState(readAbandonedInputRequests);
|
|
923
|
+
const abandonedInterrupt = findAbandonedInterrupt(abandoned);
|
|
924
|
+
const hitl = asHitlApproval(request == null ? void 0 : request.payload);
|
|
925
|
+
const actionRequests = React.useMemo(() => pendingActionRequests(hitl), [hitl]);
|
|
926
|
+
const isRunning = react.useAuiState((s) => s.thread.isRunning);
|
|
927
|
+
const { pending, resume } = useApprovalResumeLock({
|
|
928
|
+
requestId,
|
|
929
|
+
isRunning,
|
|
930
|
+
pendingResumeGraceMs,
|
|
931
|
+
sendResume: (id, value) => sendCommand({
|
|
932
|
+
type: "run/input",
|
|
933
|
+
requestId: id,
|
|
934
|
+
response: { type: "resume", value }
|
|
935
|
+
})
|
|
936
|
+
});
|
|
937
|
+
return { request, requestId, hitl, actionRequests, abandonedInterrupt, pending, resume };
|
|
938
|
+
}
|
|
939
|
+
const StatewireApprovalCard = (props) => {
|
|
940
|
+
const extras = react.useAuiState((s) => s.thread.extras);
|
|
941
|
+
if (!hasStatewireThreadExtras(extras)) return null;
|
|
942
|
+
return /* @__PURE__ */ jsxRuntime.jsx(StatewireApprovalCardInner, { ...props });
|
|
943
|
+
};
|
|
944
|
+
const StatewireApprovalCardInner = ({
|
|
945
|
+
classNames,
|
|
946
|
+
fallbackMessage,
|
|
947
|
+
interruptPredicate,
|
|
948
|
+
pendingResumeGraceMs,
|
|
949
|
+
isHandledElsewhere,
|
|
950
|
+
renderDetails,
|
|
951
|
+
readOnly = false,
|
|
952
|
+
readOnlyNotice = "Waiting for someone with edit access to respond."
|
|
953
|
+
}) => {
|
|
954
|
+
var _a, _b, _c;
|
|
955
|
+
const { request, requestId, hitl, actionRequests, abandonedInterrupt, pending, resume } = useStatewireApprovalRequest({ interruptPredicate, pendingResumeGraceMs });
|
|
956
|
+
const [dismissedId, setDismissedId] = React.useState();
|
|
957
|
+
const [detailsOverride, setDetailsOverride] = React.useState();
|
|
958
|
+
const prevRequestIdRef = React.useRef(requestId);
|
|
959
|
+
if (prevRequestIdRef.current !== requestId) {
|
|
960
|
+
prevRequestIdRef.current = requestId;
|
|
961
|
+
if (detailsOverride !== void 0) setDetailsOverride(void 0);
|
|
962
|
+
}
|
|
963
|
+
if (!request) {
|
|
964
|
+
if (!abandonedInterrupt || abandonedInterrupt.id === dismissedId) return null;
|
|
965
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
966
|
+
"div",
|
|
967
|
+
{
|
|
968
|
+
className: trash2.cn(
|
|
969
|
+
"aui-approval-abandoned flex w-full items-center justify-between gap-3 rounded-xl border border-amber-300 bg-amber-50 px-3 py-2 text-amber-800 text-xs",
|
|
970
|
+
classNames == null ? void 0 : classNames.abandoned
|
|
971
|
+
),
|
|
972
|
+
children: [
|
|
973
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: "Approval was cancelled — the run moved on." }),
|
|
974
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
975
|
+
"button",
|
|
976
|
+
{
|
|
977
|
+
type: "button",
|
|
978
|
+
"aria-label": "Dismiss cancelled approval",
|
|
979
|
+
onClick: () => setDismissedId(abandonedInterrupt.id),
|
|
980
|
+
className: "shrink-0 rounded-md p-1 hover:bg-amber-100",
|
|
981
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(x.X, { className: "size-3.5" })
|
|
982
|
+
}
|
|
983
|
+
)
|
|
984
|
+
]
|
|
985
|
+
}
|
|
986
|
+
);
|
|
987
|
+
}
|
|
988
|
+
const context = { request, hitl, actionRequests };
|
|
989
|
+
if (isHandledElsewhere == null ? void 0 : isHandledElsewhere(context)) return null;
|
|
990
|
+
const message = readInterruptMessage(request.payload, fallbackMessage);
|
|
991
|
+
const toolName = ((_a = hitl == null ? void 0 : hitl.context) == null ? void 0 : _a.tool_name) ?? ((_b = hitl == null ? void 0 : hitl.context) == null ? void 0 : _b.tool_id);
|
|
992
|
+
const pendingCount = ((_c = hitl == null ? void 0 : hitl.context) == null ? void 0 : _c.pending_action_count) ?? 1;
|
|
993
|
+
const hasDetails = hitl !== null && actionRequests.length > 0;
|
|
994
|
+
const showDetails = hasDetails && (detailsOverride ?? actionRequests.length <= 1);
|
|
995
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
996
|
+
"section",
|
|
997
|
+
{
|
|
998
|
+
"aria-label": hitl ? "Approval required" : "Input required",
|
|
999
|
+
className: trash2.cn(
|
|
1000
|
+
"aui-approval-card w-full rounded-2xl border border-amber-300 bg-amber-50 px-4 py-3 text-amber-900",
|
|
1001
|
+
classNames == null ? void 0 : classNames.root
|
|
1002
|
+
),
|
|
1003
|
+
children: [
|
|
1004
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
|
|
1005
|
+
/* @__PURE__ */ jsxRuntime.jsx(TriangleAlert, { className: "mt-0.5 size-4 shrink-0" }),
|
|
1006
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
1007
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "flex items-center gap-2 font-semibold text-sm", children: [
|
|
1008
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: hitl ? "Approval required" : "Waiting for input" }),
|
|
1009
|
+
hitl && pendingCount > 1 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "shrink-0 font-normal text-amber-800 text-xs", children: [
|
|
1010
|
+
pendingCount,
|
|
1011
|
+
" tool calls"
|
|
1012
|
+
] }) : null
|
|
1013
|
+
] }),
|
|
1014
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "pt-1 text-amber-800 text-sm leading-snug", children: hitl && pendingCount === 1 && toolName ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1015
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: toolName }),
|
|
1016
|
+
" requires approval before it runs."
|
|
1017
|
+
] }) : message }),
|
|
1018
|
+
hasDetails ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1019
|
+
"button",
|
|
1020
|
+
{
|
|
1021
|
+
type: "button",
|
|
1022
|
+
onClick: () => setDetailsOverride(!showDetails),
|
|
1023
|
+
"aria-expanded": showDetails,
|
|
1024
|
+
className: "mt-2 flex items-center gap-1 rounded px-1 py-0.5 text-amber-800 text-xs transition-colors hover:text-amber-950",
|
|
1025
|
+
children: [
|
|
1026
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1027
|
+
trash2.ChevronDown,
|
|
1028
|
+
{
|
|
1029
|
+
className: trash2.cn("size-3 transition-transform", showDetails && "rotate-180")
|
|
1030
|
+
}
|
|
1031
|
+
),
|
|
1032
|
+
showDetails ? "Hide details" : "Review details"
|
|
1033
|
+
]
|
|
1034
|
+
}
|
|
1035
|
+
) : null,
|
|
1036
|
+
showDetails ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: trash2.cn("mt-2 flex flex-col gap-2", classNames == null ? void 0 : classNames.details), children: renderDetails ? renderDetails(context) : /* @__PURE__ */ jsxRuntime.jsx(DefaultApprovalDetails, { actionRequests }) }) : null
|
|
1037
|
+
] })
|
|
1038
|
+
] }),
|
|
1039
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: trash2.cn("flex flex-wrap items-center gap-2 pt-3", classNames == null ? void 0 : classNames.actions), children: readOnly ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-amber-800 text-sm", "data-testid": "statewire-approval-read-only", children: readOnlyNotice }) : hitl ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1040
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1041
|
+
Button,
|
|
1042
|
+
{
|
|
1043
|
+
size: "sm",
|
|
1044
|
+
disabled: pending,
|
|
1045
|
+
onClick: () => resume(hitlResumeApprove()),
|
|
1046
|
+
className: "bg-green-600 text-white hover:bg-green-700",
|
|
1047
|
+
children: [
|
|
1048
|
+
/* @__PURE__ */ jsxRuntime.jsx(x.Check, {}),
|
|
1049
|
+
"Approve"
|
|
1050
|
+
]
|
|
1051
|
+
}
|
|
1052
|
+
),
|
|
1053
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1054
|
+
Button,
|
|
1055
|
+
{
|
|
1056
|
+
size: "sm",
|
|
1057
|
+
variant: "outline",
|
|
1058
|
+
disabled: pending,
|
|
1059
|
+
onClick: () => resume(hitlResumeReject()),
|
|
1060
|
+
children: [
|
|
1061
|
+
/* @__PURE__ */ jsxRuntime.jsx(x.X, {}),
|
|
1062
|
+
"Reject"
|
|
1063
|
+
]
|
|
1064
|
+
}
|
|
1065
|
+
)
|
|
1066
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(Button, { size: "sm", disabled: pending, onClick: () => resume(hitlResumeContinue()), children: "Continue" }) })
|
|
1067
|
+
]
|
|
1068
|
+
}
|
|
1069
|
+
);
|
|
1070
|
+
};
|
|
1071
|
+
const DefaultApprovalDetails = ({
|
|
1072
|
+
actionRequests
|
|
1073
|
+
}) => /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: actionRequests.map((action, index) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1074
|
+
"div",
|
|
1075
|
+
{
|
|
1076
|
+
className: "rounded-lg bg-amber-100 p-2 text-amber-900 text-xs leading-relaxed",
|
|
1077
|
+
children: [
|
|
1078
|
+
actionRequests.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-mono font-semibold", children: action.name }) : null,
|
|
1079
|
+
Object.keys(action.args).length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "mt-1 max-h-32 overflow-auto whitespace-pre-wrap break-words rounded bg-white/60 p-1.5 font-mono text-[11px]", children: JSON.stringify(action.args, null, 2) }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-amber-800", children: "No arguments." })
|
|
1080
|
+
]
|
|
1081
|
+
},
|
|
1082
|
+
`${action.name}-${index}`
|
|
1083
|
+
)) });
|
|
1084
|
+
const EXIT_ANIMATION_MS = 200;
|
|
1085
|
+
const EXIT_RESET_MS = 2500;
|
|
1086
|
+
const ContinuePill = ({ onClick, ariaLabel, dataTestId }) => {
|
|
1087
|
+
const [isExiting, setIsExiting] = React.useState(false);
|
|
1088
|
+
const onClickRef = React.useRef(onClick);
|
|
1089
|
+
const pendingOnClickRef = React.useRef(onClick);
|
|
1090
|
+
onClickRef.current = onClick;
|
|
1091
|
+
React.useEffect(() => {
|
|
1092
|
+
if (!isExiting) return;
|
|
1093
|
+
const dispatchTimer = setTimeout(
|
|
1094
|
+
() => pendingOnClickRef.current(),
|
|
1095
|
+
EXIT_ANIMATION_MS
|
|
1096
|
+
);
|
|
1097
|
+
const resetTimer = setTimeout(() => setIsExiting(false), EXIT_RESET_MS);
|
|
1098
|
+
return () => {
|
|
1099
|
+
clearTimeout(dispatchTimer);
|
|
1100
|
+
clearTimeout(resetTimer);
|
|
1101
|
+
};
|
|
1102
|
+
}, [isExiting]);
|
|
1103
|
+
const handleClick = () => {
|
|
1104
|
+
if (isExiting) return;
|
|
1105
|
+
pendingOnClickRef.current = onClickRef.current;
|
|
1106
|
+
setIsExiting(true);
|
|
1107
|
+
};
|
|
1108
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1109
|
+
"button",
|
|
1110
|
+
{
|
|
1111
|
+
type: "button",
|
|
1112
|
+
onClick: handleClick,
|
|
1113
|
+
disabled: isExiting,
|
|
1114
|
+
className: trash2.cn(
|
|
1115
|
+
"group inline-flex items-center gap-1.5 rounded-full bg-primary px-3.5 py-1 text-xs font-medium text-primary-foreground shadow-sm",
|
|
1116
|
+
"transition-all duration-200 ease-out",
|
|
1117
|
+
"hover:bg-primary/90 hover:shadow-md active:scale-95",
|
|
1118
|
+
"animate-in fade-in slide-in-from-bottom-1",
|
|
1119
|
+
isExiting && "pointer-events-none scale-90 opacity-0"
|
|
1120
|
+
),
|
|
1121
|
+
"aria-label": ariaLabel,
|
|
1122
|
+
"data-testid": dataTestId,
|
|
1123
|
+
children: [
|
|
1124
|
+
/* @__PURE__ */ jsxRuntime.jsx(trash2.Play, { className: "size-3 fill-current transition-transform duration-200 ease-out group-hover:translate-x-0.5" }),
|
|
1125
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Continue" })
|
|
1126
|
+
]
|
|
1127
|
+
}
|
|
1128
|
+
);
|
|
1129
|
+
};
|
|
1130
|
+
const StatewireQueuedMessages = (props) => {
|
|
1131
|
+
const extras = react.useAuiState((s) => s.thread.extras);
|
|
1132
|
+
if (!hasStatewireThreadExtras(extras)) return null;
|
|
1133
|
+
return /* @__PURE__ */ jsxRuntime.jsx(StatewireQueuedMessagesInner, { ...props });
|
|
1134
|
+
};
|
|
1135
|
+
const StatewireQueuedMessagesInner = ({
|
|
1136
|
+
classNames,
|
|
1137
|
+
autoContinue = false,
|
|
1138
|
+
threadId = null,
|
|
1139
|
+
onEvent,
|
|
1140
|
+
renderContent,
|
|
1141
|
+
renderEditor
|
|
1142
|
+
}) => {
|
|
1143
|
+
var _a;
|
|
1144
|
+
const runs = reactStatewire.useStatewireRuns();
|
|
1145
|
+
const { queue, steerQueue, runId } = runs;
|
|
1146
|
+
const failed = runs.failed ?? [];
|
|
1147
|
+
const rawPrioritizedQueueIds = reactStatewire.useStatewireState(
|
|
1148
|
+
(state) => trash2.readDeepAgentStreamValues(state).prioritizedQueueIds
|
|
1149
|
+
);
|
|
1150
|
+
const prioritizedQueueIds = React.useMemo(
|
|
1151
|
+
() => new Set(readPrioritizedQueueIds(rawPrioritizedQueueIds)),
|
|
1152
|
+
[rawPrioritizedQueueIds]
|
|
1153
|
+
);
|
|
1154
|
+
const status = useDeepAgentThreadStatus();
|
|
1155
|
+
const { isRunning, isContinuable } = queueLaneFlags(status);
|
|
1156
|
+
const aui = react.useAui();
|
|
1157
|
+
const sendCommand = reactStatewire.useStatewireSendCommand();
|
|
1158
|
+
const listId = React.useId();
|
|
1159
|
+
const [expanded, setExpanded] = React.useState(true);
|
|
1160
|
+
const [editingId, setEditingId] = React.useState(null);
|
|
1161
|
+
const [editingText, setEditingText] = React.useState("");
|
|
1162
|
+
const autoContinueAttemptsRef = React.useRef(/* @__PURE__ */ new Set());
|
|
1163
|
+
const onEventRef = React.useRef(onEvent);
|
|
1164
|
+
onEventRef.current = onEvent;
|
|
1165
|
+
const rows = buildStatewireQueueRows({ queue, steerQueue, isContinuable });
|
|
1166
|
+
const queueHeadId = ((_a = queue[0]) == null ? void 0 : _a.id) ?? null;
|
|
1167
|
+
const autoContinueOptions = autoContinue === true ? {} : autoContinue || null;
|
|
1168
|
+
const saveEdit = (item, lane, text) => {
|
|
1169
|
+
setEditingId(null);
|
|
1170
|
+
setEditingText("");
|
|
1171
|
+
const command = buildQueueEditCommand({ item, lane, runId, text });
|
|
1172
|
+
if (command !== null) sendCommand(command);
|
|
1173
|
+
};
|
|
1174
|
+
const runFailedSendAction = ({
|
|
1175
|
+
action,
|
|
1176
|
+
messageId,
|
|
1177
|
+
run
|
|
1178
|
+
}) => {
|
|
1179
|
+
try {
|
|
1180
|
+
run(requireStatewireFailedActions(aui.thread().getState().extras));
|
|
1181
|
+
} catch (error) {
|
|
1182
|
+
if (!(error instanceof Error) || !isFailedSendEntryRace(error)) throw error;
|
|
1183
|
+
onEvent == null ? void 0 : onEvent({
|
|
1184
|
+
type: "failed-send-action-raced",
|
|
1185
|
+
threadId,
|
|
1186
|
+
messageId,
|
|
1187
|
+
action,
|
|
1188
|
+
error: error.message
|
|
1189
|
+
});
|
|
1190
|
+
}
|
|
1191
|
+
};
|
|
1192
|
+
if (rows.length === 0 && failed.length === 0) return null;
|
|
1193
|
+
const renderRowContent = (context) => renderContent ? renderContent(context) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "min-w-0 flex-1 whitespace-pre-wrap break-words text-foreground text-xs", children: context.text || "Queued attachment" });
|
|
1194
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1195
|
+
"section",
|
|
1196
|
+
{
|
|
1197
|
+
"aria-label": "Queued messages",
|
|
1198
|
+
className: trash2.cn(
|
|
1199
|
+
"aui-statewire-queue w-full rounded-xl border border-border/70 bg-muted/30 px-2 py-1.5",
|
|
1200
|
+
classNames == null ? void 0 : classNames.root
|
|
1201
|
+
),
|
|
1202
|
+
children: [
|
|
1203
|
+
autoContinueOptions ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1204
|
+
QueueAutoContinue,
|
|
1205
|
+
{
|
|
1206
|
+
delayMs: autoContinueOptions.delayMs ?? QUEUE_AUTO_CONTINUE_DELAY_MS,
|
|
1207
|
+
queueHeadId,
|
|
1208
|
+
isContinuable,
|
|
1209
|
+
status,
|
|
1210
|
+
threadId,
|
|
1211
|
+
editing: editingId !== null,
|
|
1212
|
+
attemptsRef: autoContinueAttemptsRef,
|
|
1213
|
+
onEventRef
|
|
1214
|
+
}
|
|
1215
|
+
) : null,
|
|
1216
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
1217
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1218
|
+
"button",
|
|
1219
|
+
{
|
|
1220
|
+
type: "button",
|
|
1221
|
+
onClick: () => setExpanded((value) => !value),
|
|
1222
|
+
"aria-expanded": expanded,
|
|
1223
|
+
"aria-controls": listId,
|
|
1224
|
+
className: "flex items-center gap-1 rounded px-1 py-1 font-medium text-muted-foreground text-xs hover:text-foreground",
|
|
1225
|
+
children: [
|
|
1226
|
+
expanded ? /* @__PURE__ */ jsxRuntime.jsx(trash2.ChevronDown, { className: "size-3.5" }) : /* @__PURE__ */ jsxRuntime.jsx(x.ChevronRight, { className: "size-3.5" }),
|
|
1227
|
+
rows.length + failed.length,
|
|
1228
|
+
" queued"
|
|
1229
|
+
]
|
|
1230
|
+
}
|
|
1231
|
+
),
|
|
1232
|
+
isContinuable && queueHeadId !== null ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1233
|
+
ContinuePill,
|
|
1234
|
+
{
|
|
1235
|
+
ariaLabel: "Continue with queued messages",
|
|
1236
|
+
onClick: () => aui.composer.queueItem({ id: queueHeadId }).move({ lane: "steer" })
|
|
1237
|
+
}
|
|
1238
|
+
) : null
|
|
1239
|
+
] }),
|
|
1240
|
+
expanded ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1241
|
+
"ul",
|
|
1242
|
+
{
|
|
1243
|
+
id: listId,
|
|
1244
|
+
className: trash2.cn("max-h-40 overflow-y-auto", classNames == null ? void 0 : classNames.list),
|
|
1245
|
+
"data-testid": "athena-statewire-queue",
|
|
1246
|
+
children: [
|
|
1247
|
+
rows.map(({ item, lane }, index) => {
|
|
1248
|
+
const text = queueEntryText(item.parts);
|
|
1249
|
+
const isUnsettled = isQueueEntryUnsettled(item);
|
|
1250
|
+
const isEditing = editingId === item.id;
|
|
1251
|
+
const showSendNow = !isUnsettled && showQueueRowSendNow({ lane, index, isRunning, isContinuable });
|
|
1252
|
+
const showPrioritize = !isUnsettled && lane === "queue" && isRunning && runId !== null;
|
|
1253
|
+
const isPrioritized = prioritizedQueueIds.has(item.id);
|
|
1254
|
+
const editorContext = {
|
|
1255
|
+
value: editingText,
|
|
1256
|
+
onChange: setEditingText,
|
|
1257
|
+
onSave: (next) => saveEdit(item, lane, next),
|
|
1258
|
+
onCancel: () => {
|
|
1259
|
+
setEditingId(null);
|
|
1260
|
+
setEditingText("");
|
|
1261
|
+
}
|
|
1262
|
+
};
|
|
1263
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1264
|
+
"li",
|
|
1265
|
+
{
|
|
1266
|
+
className: "group flex items-start gap-2 rounded-md px-1 py-1.5 hover:bg-background",
|
|
1267
|
+
children: [
|
|
1268
|
+
isUnsettled ? /* @__PURE__ */ jsxRuntime.jsx(LoaderCircle, { className: "mt-0.5 size-3.5 shrink-0 animate-spin text-muted-foreground/60" }) : /* @__PURE__ */ jsxRuntime.jsx(x.Circle, { className: "mt-0.5 size-3.5 shrink-0 text-muted-foreground/40" }),
|
|
1269
|
+
isEditing ? renderEditor ? renderEditor(editorContext) : /* @__PURE__ */ jsxRuntime.jsx(DefaultQueueEditor, { ...editorContext }) : renderRowContent({ text, index, item }),
|
|
1270
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1271
|
+
"div",
|
|
1272
|
+
{
|
|
1273
|
+
className: trash2.cn("flex shrink-0 items-center gap-1", isEditing && "hidden"),
|
|
1274
|
+
"data-testid": "statewire-queue-row-actions",
|
|
1275
|
+
children: [
|
|
1276
|
+
isUnsettled ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1277
|
+
"span",
|
|
1278
|
+
{
|
|
1279
|
+
className: "px-1 text-[10px] text-muted-foreground",
|
|
1280
|
+
"data-testid": "statewire-queued-message-sending",
|
|
1281
|
+
children: "Sending…"
|
|
1282
|
+
}
|
|
1283
|
+
) : null,
|
|
1284
|
+
showSendNow ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1285
|
+
"button",
|
|
1286
|
+
{
|
|
1287
|
+
type: "button",
|
|
1288
|
+
"aria-label": "Send now",
|
|
1289
|
+
onClick: () => aui.composer.queueItem({ id: item.id }).move({ lane: "steer" }),
|
|
1290
|
+
className: "inline-flex items-center gap-1 rounded-full border border-primary/30 px-2 py-1 font-medium text-[10px] text-primary hover:bg-primary/5",
|
|
1291
|
+
children: [
|
|
1292
|
+
/* @__PURE__ */ jsxRuntime.jsx(Send, { className: "size-2.5" }),
|
|
1293
|
+
"Send now"
|
|
1294
|
+
]
|
|
1295
|
+
}
|
|
1296
|
+
) : null,
|
|
1297
|
+
showPrioritize ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1298
|
+
"button",
|
|
1299
|
+
{
|
|
1300
|
+
type: "button",
|
|
1301
|
+
"aria-label": isPrioritized ? "Remove priority" : "Prioritize",
|
|
1302
|
+
"aria-pressed": isPrioritized,
|
|
1303
|
+
title: isPrioritized ? "Remove priority" : "Prioritize this message. Delivered as soon as the current step ends.",
|
|
1304
|
+
onClick: () => {
|
|
1305
|
+
if (runId === null) return;
|
|
1306
|
+
sendCommand({
|
|
1307
|
+
type: "run/prioritize",
|
|
1308
|
+
runId,
|
|
1309
|
+
messageId: item.id,
|
|
1310
|
+
priority: !isPrioritized
|
|
1311
|
+
});
|
|
1312
|
+
},
|
|
1313
|
+
className: trash2.cn(
|
|
1314
|
+
"rounded p-1 transition-colors",
|
|
1315
|
+
isPrioritized ? "text-amber-500 hover:text-amber-600" : "text-muted-foreground hover:text-amber-500"
|
|
1316
|
+
),
|
|
1317
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Zap, { className: "size-3" })
|
|
1318
|
+
}
|
|
1319
|
+
) : null,
|
|
1320
|
+
!isUnsettled ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1321
|
+
"button",
|
|
1322
|
+
{
|
|
1323
|
+
type: "button",
|
|
1324
|
+
"aria-label": "Edit queued message",
|
|
1325
|
+
onClick: () => {
|
|
1326
|
+
setEditingId(item.id);
|
|
1327
|
+
setEditingText(text);
|
|
1328
|
+
},
|
|
1329
|
+
className: "rounded p-1 text-muted-foreground transition-colors hover:text-primary",
|
|
1330
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Pencil, { className: "size-3" })
|
|
1331
|
+
}
|
|
1332
|
+
) : null,
|
|
1333
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1334
|
+
"button",
|
|
1335
|
+
{
|
|
1336
|
+
type: "button",
|
|
1337
|
+
"aria-label": "Remove queued message",
|
|
1338
|
+
onClick: () => aui.composer.queueItem({ id: item.id }).remove(),
|
|
1339
|
+
className: trash2.cn(
|
|
1340
|
+
"rounded p-1 text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive",
|
|
1341
|
+
!showSendNow && "opacity-0 focus-visible:opacity-100 group-hover:opacity-100"
|
|
1342
|
+
),
|
|
1343
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(trash2.Trash2, { className: "size-3" })
|
|
1344
|
+
}
|
|
1345
|
+
)
|
|
1346
|
+
]
|
|
1347
|
+
}
|
|
1348
|
+
)
|
|
1349
|
+
]
|
|
1350
|
+
},
|
|
1351
|
+
item.id
|
|
1352
|
+
);
|
|
1353
|
+
}),
|
|
1354
|
+
failed.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1355
|
+
"li",
|
|
1356
|
+
{
|
|
1357
|
+
className: "group flex items-start gap-2 rounded-md px-1 py-1.5 hover:bg-background",
|
|
1358
|
+
children: [
|
|
1359
|
+
/* @__PURE__ */ jsxRuntime.jsx(trash2.CircleAlert, { className: "mt-0.5 size-3.5 shrink-0 text-destructive" }),
|
|
1360
|
+
renderRowContent({
|
|
1361
|
+
text: queueEntryText(item.parts),
|
|
1362
|
+
index: rows.length + index,
|
|
1363
|
+
item
|
|
1364
|
+
}),
|
|
1365
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1366
|
+
"div",
|
|
1367
|
+
{
|
|
1368
|
+
className: "flex shrink-0 items-center gap-1",
|
|
1369
|
+
"data-testid": "statewire-queue-row-actions",
|
|
1370
|
+
children: [
|
|
1371
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1372
|
+
"span",
|
|
1373
|
+
{
|
|
1374
|
+
className: "px-1 text-[10px] text-destructive",
|
|
1375
|
+
title: describeQueueSendFailure(item.sendFailure),
|
|
1376
|
+
children: "Failed to send"
|
|
1377
|
+
}
|
|
1378
|
+
),
|
|
1379
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1380
|
+
"button",
|
|
1381
|
+
{
|
|
1382
|
+
type: "button",
|
|
1383
|
+
"aria-label": "Retry failed message",
|
|
1384
|
+
onClick: () => runFailedSendAction({
|
|
1385
|
+
action: "retry",
|
|
1386
|
+
messageId: item.id,
|
|
1387
|
+
run: (actions) => actions.retryFailed(item.id)
|
|
1388
|
+
}),
|
|
1389
|
+
className: "inline-flex items-center gap-1 rounded-full border border-primary/30 px-2 py-1 font-medium text-[10px] text-primary hover:bg-primary/5",
|
|
1390
|
+
children: [
|
|
1391
|
+
/* @__PURE__ */ jsxRuntime.jsx(RotateCcw, { className: "size-2.5" }),
|
|
1392
|
+
"Retry"
|
|
1393
|
+
]
|
|
1394
|
+
}
|
|
1395
|
+
),
|
|
1396
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1397
|
+
"button",
|
|
1398
|
+
{
|
|
1399
|
+
type: "button",
|
|
1400
|
+
"aria-label": "Discard failed message",
|
|
1401
|
+
onClick: () => runFailedSendAction({
|
|
1402
|
+
action: "discard",
|
|
1403
|
+
messageId: item.id,
|
|
1404
|
+
run: (actions) => actions.discardFailed(item.id)
|
|
1405
|
+
}),
|
|
1406
|
+
className: "rounded p-1 text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive",
|
|
1407
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(trash2.Trash2, { className: "size-3" })
|
|
1408
|
+
}
|
|
1409
|
+
)
|
|
1410
|
+
]
|
|
1411
|
+
}
|
|
1412
|
+
)
|
|
1413
|
+
]
|
|
1414
|
+
},
|
|
1415
|
+
item.id
|
|
1416
|
+
))
|
|
1417
|
+
]
|
|
1418
|
+
}
|
|
1419
|
+
) : null
|
|
1420
|
+
]
|
|
1421
|
+
}
|
|
1422
|
+
);
|
|
1423
|
+
};
|
|
1424
|
+
const QueueAutoContinue = ({ delayMs, queueHeadId, isContinuable, status, threadId, editing, attemptsRef, onEventRef }) => {
|
|
1425
|
+
const aui = react.useAui();
|
|
1426
|
+
const lastMessageMarker = react.useAuiState((s) => {
|
|
1427
|
+
var _a;
|
|
1428
|
+
const last = s.thread.messages.at(-1);
|
|
1429
|
+
return last ? (_a = trash2.readRunMarkerFromSourceMessages(last)) == null ? void 0 : _a.marker : void 0;
|
|
1430
|
+
});
|
|
1431
|
+
const lastMessageMarkerSource = react.useAuiState((s) => {
|
|
1432
|
+
var _a;
|
|
1433
|
+
const last = s.thread.messages.at(-1);
|
|
1434
|
+
return last ? (_a = trash2.readRunMarkerFromSourceMessages(last)) == null ? void 0 : _a.source : void 0;
|
|
1435
|
+
});
|
|
1436
|
+
const userStopBlocks = userStopBlocksQueueAutoContinue({
|
|
1437
|
+
marker: lastMessageMarker,
|
|
1438
|
+
source: lastMessageMarkerSource
|
|
1439
|
+
});
|
|
1440
|
+
React.useEffect(() => {
|
|
1441
|
+
if (!isContinuable || queueHeadId === null || userStopBlocks) return;
|
|
1442
|
+
if (editing) return;
|
|
1443
|
+
const attemptKey = `${threadId ?? "unknown"}:${queueHeadId}`;
|
|
1444
|
+
if (attemptsRef.current.has(attemptKey)) return;
|
|
1445
|
+
const timeoutId = setTimeout(() => {
|
|
1446
|
+
var _a;
|
|
1447
|
+
attemptsRef.current.add(attemptKey);
|
|
1448
|
+
(_a = onEventRef.current) == null ? void 0 : _a.call(onEventRef, { type: "auto-continued", threadId, status, headEntryId: queueHeadId });
|
|
1449
|
+
aui.composer.queueItem({ id: queueHeadId }).move({ lane: "steer" });
|
|
1450
|
+
}, delayMs);
|
|
1451
|
+
return () => clearTimeout(timeoutId);
|
|
1452
|
+
}, [
|
|
1453
|
+
attemptsRef,
|
|
1454
|
+
aui,
|
|
1455
|
+
delayMs,
|
|
1456
|
+
editing,
|
|
1457
|
+
isContinuable,
|
|
1458
|
+
onEventRef,
|
|
1459
|
+
queueHeadId,
|
|
1460
|
+
status,
|
|
1461
|
+
threadId,
|
|
1462
|
+
userStopBlocks
|
|
1463
|
+
]);
|
|
1464
|
+
return null;
|
|
1465
|
+
};
|
|
1466
|
+
const DefaultQueueEditor = ({
|
|
1467
|
+
value,
|
|
1468
|
+
onChange,
|
|
1469
|
+
onSave,
|
|
1470
|
+
onCancel
|
|
1471
|
+
}) => {
|
|
1472
|
+
const canSave = value.trim().length > 0;
|
|
1473
|
+
const handleKeyDown = (event) => {
|
|
1474
|
+
if (event.key === "Enter" && !event.shiftKey) {
|
|
1475
|
+
event.preventDefault();
|
|
1476
|
+
if (canSave) onSave(value);
|
|
1477
|
+
} else if (event.key === "Escape") {
|
|
1478
|
+
event.preventDefault();
|
|
1479
|
+
onCancel();
|
|
1480
|
+
}
|
|
1481
|
+
};
|
|
1482
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 items-start gap-1", children: [
|
|
1483
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1484
|
+
"textarea",
|
|
1485
|
+
{
|
|
1486
|
+
autoFocus: true,
|
|
1487
|
+
"aria-label": "Edit message",
|
|
1488
|
+
value,
|
|
1489
|
+
onChange: (event) => onChange(event.target.value),
|
|
1490
|
+
onKeyDown: handleKeyDown,
|
|
1491
|
+
rows: Math.min(6, Math.max(1, value.split("\n").length)),
|
|
1492
|
+
className: "min-w-0 flex-1 resize-none rounded-md border border-border bg-background px-2 py-1 text-foreground text-xs outline-none focus-visible:ring-2 focus-visible:ring-ring/50"
|
|
1493
|
+
}
|
|
1494
|
+
),
|
|
1495
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1496
|
+
"button",
|
|
1497
|
+
{
|
|
1498
|
+
type: "button",
|
|
1499
|
+
"aria-label": "Save edit",
|
|
1500
|
+
disabled: !canSave,
|
|
1501
|
+
onClick: () => onSave(value),
|
|
1502
|
+
className: trash2.cn(
|
|
1503
|
+
"rounded p-1 text-primary transition-colors hover:bg-primary/10",
|
|
1504
|
+
!canSave && "cursor-not-allowed opacity-40"
|
|
1505
|
+
),
|
|
1506
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(x.Check, { className: "size-3.5" })
|
|
1507
|
+
}
|
|
1508
|
+
),
|
|
1509
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1510
|
+
"button",
|
|
1511
|
+
{
|
|
1512
|
+
type: "button",
|
|
1513
|
+
"aria-label": "Cancel edit",
|
|
1514
|
+
onClick: onCancel,
|
|
1515
|
+
className: "rounded p-1 text-muted-foreground transition-colors hover:bg-muted",
|
|
1516
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(x.X, { className: "size-3.5" })
|
|
1517
|
+
}
|
|
1518
|
+
)
|
|
1519
|
+
] });
|
|
1520
|
+
};
|
|
1521
|
+
const SEVERITY_CLASS = {
|
|
1522
|
+
info: "border-border bg-muted/40 text-muted-foreground",
|
|
1523
|
+
warning: "border-amber-200 bg-amber-50 text-amber-900",
|
|
1524
|
+
error: "border-red-200 bg-red-50 text-red-800"
|
|
1525
|
+
};
|
|
1526
|
+
const KIND_ICON = {
|
|
1527
|
+
stopped: Square,
|
|
1528
|
+
paused: trash2.Pause,
|
|
1529
|
+
failed: OctagonX,
|
|
1530
|
+
handoff: TriangleAlert
|
|
1531
|
+
};
|
|
1532
|
+
const RuntimeMessageCard = ({
|
|
1533
|
+
message,
|
|
1534
|
+
action,
|
|
1535
|
+
className,
|
|
1536
|
+
...rest
|
|
1537
|
+
}) => {
|
|
1538
|
+
if (message.silent) return null;
|
|
1539
|
+
const Icon = KIND_ICON[message.kind];
|
|
1540
|
+
const markerText = runtimeMessageMarkerText(message);
|
|
1541
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1542
|
+
"div",
|
|
1543
|
+
{
|
|
1544
|
+
...rest,
|
|
1545
|
+
role: "status",
|
|
1546
|
+
"data-runtime-message-kind": message.kind,
|
|
1547
|
+
"data-runtime-message-reason": message.reason,
|
|
1548
|
+
className: trash2.cn(
|
|
1549
|
+
"my-2 flex w-full items-start gap-2 rounded-lg border px-3 py-2 text-sm",
|
|
1550
|
+
SEVERITY_CLASS[message.severity],
|
|
1551
|
+
className
|
|
1552
|
+
),
|
|
1553
|
+
children: [
|
|
1554
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "mt-0.5 size-4 shrink-0", "aria-hidden": "true" }),
|
|
1555
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
|
|
1556
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: message.title }),
|
|
1557
|
+
message.detail ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs opacity-90", children: message.detail }) : null,
|
|
1558
|
+
markerText ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs opacity-90", children: markerText }) : null
|
|
1559
|
+
] }),
|
|
1560
|
+
action
|
|
1561
|
+
]
|
|
1562
|
+
}
|
|
1563
|
+
);
|
|
1564
|
+
};
|
|
1565
|
+
const THREAD_VIEWPORT_ATTR = "data-aui-thread-viewport";
|
|
1566
|
+
const HISTORY_EDGE_NEAR_MARGIN_PX = 1500;
|
|
1567
|
+
const HistoryEdgeRow = ({
|
|
1568
|
+
olderCount,
|
|
1569
|
+
loading,
|
|
1570
|
+
onLoadOlder,
|
|
1571
|
+
className,
|
|
1572
|
+
rowRef
|
|
1573
|
+
}) => {
|
|
1574
|
+
if (olderCount <= 0) return null;
|
|
1575
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1576
|
+
"div",
|
|
1577
|
+
{
|
|
1578
|
+
ref: rowRef,
|
|
1579
|
+
"data-testid": "thread-history-edge",
|
|
1580
|
+
className: trash2.cn(
|
|
1581
|
+
"flex w-full max-w-(--thread-max-width) items-center justify-center py-1 text-xs text-muted-foreground",
|
|
1582
|
+
className
|
|
1583
|
+
),
|
|
1584
|
+
children: loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { "data-testid": "thread-history-edge-loading", children: "Loading earlier messages…" }) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1585
|
+
"button",
|
|
1586
|
+
{
|
|
1587
|
+
type: "button",
|
|
1588
|
+
"data-testid": "thread-history-edge-load",
|
|
1589
|
+
onClick: onLoadOlder,
|
|
1590
|
+
className: "rounded-lg px-2.5 py-1 text-xs font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
|
|
1591
|
+
children: [
|
|
1592
|
+
olderCount.toLocaleString(),
|
|
1593
|
+
" earlier ",
|
|
1594
|
+
olderCount === 1 ? "message" : "messages"
|
|
1595
|
+
]
|
|
1596
|
+
}
|
|
1597
|
+
)
|
|
1598
|
+
}
|
|
1599
|
+
);
|
|
1600
|
+
};
|
|
1601
|
+
const StatewireHistoryEdge = ({
|
|
1602
|
+
toolOutputs: toolOutputsProp,
|
|
1603
|
+
className,
|
|
1604
|
+
onHistoryLoad
|
|
1605
|
+
}) => {
|
|
1606
|
+
var _a;
|
|
1607
|
+
const providerToolOutputs = useStatewireToolOutputs();
|
|
1608
|
+
const toolOutputs = toolOutputsProp ?? providerToolOutputs ?? void 0;
|
|
1609
|
+
const messages = react.useAuiState((s) => s.thread.messages);
|
|
1610
|
+
const [nearTop, setNearTop] = React.useState(false);
|
|
1611
|
+
const [nearTopEpoch, setNearTopEpoch] = React.useState(0);
|
|
1612
|
+
const nearTopRef = React.useRef(false);
|
|
1613
|
+
const [rowEl, setRowEl] = React.useState(null);
|
|
1614
|
+
const { olderCount, loading, loadOlder } = useDeepAgentWindowSync({
|
|
1615
|
+
messages,
|
|
1616
|
+
toolOutputs,
|
|
1617
|
+
nearTop,
|
|
1618
|
+
nearTopEpoch,
|
|
1619
|
+
onHistoryLoad,
|
|
1620
|
+
onError: (error, command) => {
|
|
1621
|
+
if (error instanceof Error && isStatewireChannelTeardown(error)) return;
|
|
1622
|
+
console.warn(`[StatewireHistoryEdge] ${command} failed:`, error);
|
|
1623
|
+
}
|
|
1624
|
+
});
|
|
1625
|
+
React.useEffect(() => {
|
|
1626
|
+
if (!rowEl || olderCount <= 0 || typeof IntersectionObserver === "undefined") return;
|
|
1627
|
+
const observer = new IntersectionObserver(
|
|
1628
|
+
(entries) => {
|
|
1629
|
+
for (const entry of entries) {
|
|
1630
|
+
const near = entry.isIntersecting;
|
|
1631
|
+
if (nearTopRef.current === near) continue;
|
|
1632
|
+
nearTopRef.current = near;
|
|
1633
|
+
setNearTop(near);
|
|
1634
|
+
if (near) setNearTopEpoch((epoch) => epoch + 1);
|
|
1635
|
+
}
|
|
1636
|
+
},
|
|
1637
|
+
{
|
|
1638
|
+
root: rowEl.closest(`[${THREAD_VIEWPORT_ATTR}]`),
|
|
1639
|
+
rootMargin: `${HISTORY_EDGE_NEAR_MARGIN_PX}px 0px`
|
|
1640
|
+
}
|
|
1641
|
+
);
|
|
1642
|
+
observer.observe(rowEl);
|
|
1643
|
+
return () => {
|
|
1644
|
+
observer.disconnect();
|
|
1645
|
+
nearTopRef.current = false;
|
|
1646
|
+
setNearTop(false);
|
|
1647
|
+
};
|
|
1648
|
+
}, [rowEl, olderCount]);
|
|
1649
|
+
const shapeRef = React.useRef(
|
|
1650
|
+
null
|
|
1651
|
+
);
|
|
1652
|
+
const firstId = (_a = messages[0]) == null ? void 0 : _a.id;
|
|
1653
|
+
const length = messages.length;
|
|
1654
|
+
React.useLayoutEffect(() => {
|
|
1655
|
+
const viewport = (rowEl == null ? void 0 : rowEl.closest(`[${THREAD_VIEWPORT_ATTR}]`)) ?? null;
|
|
1656
|
+
const prev = shapeRef.current;
|
|
1657
|
+
const prepended = viewport !== null && prev !== null && prev.firstId !== void 0 && firstId !== prev.firstId && length > prev.length;
|
|
1658
|
+
if (prepended) viewport.scrollTop += viewport.scrollHeight - prev.scrollHeight;
|
|
1659
|
+
shapeRef.current = loading || prepended || prev === null ? { firstId, length, scrollHeight: (viewport == null ? void 0 : viewport.scrollHeight) ?? 0 } : { firstId, length, scrollHeight: prev.scrollHeight };
|
|
1660
|
+
});
|
|
1661
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1662
|
+
HistoryEdgeRow,
|
|
1663
|
+
{
|
|
1664
|
+
rowRef: setRowEl,
|
|
1665
|
+
olderCount,
|
|
1666
|
+
loading,
|
|
1667
|
+
onLoadOlder: loadOlder,
|
|
1668
|
+
className
|
|
1669
|
+
}
|
|
1670
|
+
);
|
|
1671
|
+
};
|
|
1672
|
+
exports.Button = Button;
|
|
1673
|
+
exports.ContinuePill = ContinuePill;
|
|
1674
|
+
exports.HISTORY_EDGE_NEAR_MARGIN_PX = HISTORY_EDGE_NEAR_MARGIN_PX;
|
|
1675
|
+
exports.HITL_PENDING_RESUME_GRACE_MS = HITL_PENDING_RESUME_GRACE_MS;
|
|
1676
|
+
exports.HistoryEdgeRow = HistoryEdgeRow;
|
|
1677
|
+
exports.LoaderCircle = LoaderCircle;
|
|
1678
|
+
exports.Pencil = Pencil;
|
|
1679
|
+
exports.RuntimeMessageCard = RuntimeMessageCard;
|
|
1680
|
+
exports.Square = Square;
|
|
1681
|
+
exports.StatewireApprovalCard = StatewireApprovalCard;
|
|
1682
|
+
exports.StatewireHistoryEdge = StatewireHistoryEdge;
|
|
1683
|
+
exports.StatewireQueuedMessages = StatewireQueuedMessages;
|
|
1684
|
+
exports.StatewireToolOutputsContext = StatewireToolOutputsContext;
|
|
1685
|
+
exports.THREAD_VIEWPORT_ATTR = THREAD_VIEWPORT_ATTR;
|
|
1686
|
+
exports.TriangleAlert = TriangleAlert;
|
|
1687
|
+
exports.Zap = Zap;
|
|
1688
|
+
exports.asHitlApproval = asHitlApproval;
|
|
1689
|
+
exports.buttonVariants = buttonVariants;
|
|
1690
|
+
exports.clientToolCallArgs = clientToolCallArgs;
|
|
1691
|
+
exports.clientToolErrorEnvelope = clientToolErrorEnvelope;
|
|
1692
|
+
exports.clientToolResultsResumeValue = clientToolResultsResumeValue;
|
|
1693
|
+
exports.clientToolRunConfigEntries = clientToolRunConfigEntries;
|
|
1694
|
+
exports.clientToolSuccessEnvelope = clientToolSuccessEnvelope;
|
|
1695
|
+
exports.createClientToolRequestTracker = createClientToolRequestTracker;
|
|
1696
|
+
exports.hasStatewireThreadExtras = hasStatewireThreadExtras;
|
|
1697
|
+
exports.isClientToolInterrupt = isClientToolInterrupt;
|
|
1698
|
+
exports.isLegacyThreadReadOnlyRejection = isLegacyThreadReadOnlyRejection;
|
|
1699
|
+
exports.isPendingInterrupt = isPendingInterrupt;
|
|
1700
|
+
exports.isStatewireChannelTeardown = isStatewireChannelTeardown;
|
|
1701
|
+
exports.projectDeepAgentConnection = projectDeepAgentConnection;
|
|
1702
|
+
exports.readInterruptMessage = readInterruptMessage;
|
|
1703
|
+
exports.readRuntimeMessageFromSourceMessages = readRuntimeMessageFromSourceMessages;
|
|
1704
|
+
exports.readSoleRuntimeMessageKind = readSoleRuntimeMessageKind;
|
|
1705
|
+
exports.readStatewireFailedSendLane = readStatewireFailedSendLane;
|
|
1706
|
+
exports.statewireRejectionDetailMessage = statewireRejectionDetailMessage;
|
|
1707
|
+
exports.statewireRejectionPayload = statewireRejectionPayload;
|
|
1708
|
+
exports.useDeepAgentThreadStatus = useDeepAgentThreadStatus;
|
|
1709
|
+
exports.useStatewireApprovalRequest = useStatewireApprovalRequest;
|
|
1710
|
+
exports.useStatewireToolOutputs = useStatewireToolOutputs;
|
|
1711
|
+
//# sourceMappingURL=statewire-history-edge-C8uyTEjX.cjs.map
|