@evident-ai/cli 3.0.1-dev.223a670 → 3.0.1-dev.23d3337
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/index.js +59 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1059,6 +1059,10 @@ function finishOf(m) {
|
|
|
1059
1059
|
const infoFinish = m.info?.finish;
|
|
1060
1060
|
return typeof infoFinish === "string" ? infoFinish : void 0;
|
|
1061
1061
|
}
|
|
1062
|
+
function isAssistantInFlight(m) {
|
|
1063
|
+
if (completedOf(m) == null) return true;
|
|
1064
|
+
return finishOf(m) === "tool-calls";
|
|
1065
|
+
}
|
|
1062
1066
|
async function createOpenCodeSession(port, directory) {
|
|
1063
1067
|
const url = new URL(`${opencodeBase(port)}/session`);
|
|
1064
1068
|
if (directory && directory.trim()) {
|
|
@@ -1140,9 +1144,13 @@ function messageRunState(messages, userMessageId) {
|
|
|
1140
1144
|
if (!reply) return "unknown";
|
|
1141
1145
|
}
|
|
1142
1146
|
if (!reply) return "queued";
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1147
|
+
return isAssistantInFlight(reply) ? "running" : "done";
|
|
1148
|
+
}
|
|
1149
|
+
function hasRunningAssistantExcept(messages, exceptUserMessageId) {
|
|
1150
|
+
if (!messages || messages.length === 0) return false;
|
|
1151
|
+
return messages.some(
|
|
1152
|
+
(m) => roleOf(m) === "assistant" && parentIdOf(m) !== exceptUserMessageId && isAssistantInFlight(m)
|
|
1153
|
+
);
|
|
1146
1154
|
}
|
|
1147
1155
|
function opencodeMessageIdFor2(queuedMessageId) {
|
|
1148
1156
|
return opencodeMessageIdFor(queuedMessageId);
|
|
@@ -1552,6 +1560,7 @@ var DEFAULT_RETRY_POLICY = {
|
|
|
1552
1560
|
var DEFAULT_PAUSED_POLL_INTERVAL_MS = 2e3;
|
|
1553
1561
|
var DEFAULT_PAUSED_MAX_WAIT_MS = 10 * 60 * 1e3;
|
|
1554
1562
|
var DEFAULT_DISPATCH_CONFIRM_MS = 6e3;
|
|
1563
|
+
var DEFAULT_STUCK_QUEUED_MS = 6e4;
|
|
1555
1564
|
var ChannelAuthError = class extends Error {
|
|
1556
1565
|
constructor(message) {
|
|
1557
1566
|
super(message);
|
|
@@ -1587,6 +1596,7 @@ var ChannelDriver = class {
|
|
|
1587
1596
|
pausedPollIntervalMs;
|
|
1588
1597
|
pausedMaxWaitMs;
|
|
1589
1598
|
dispatchConfirmMs;
|
|
1599
|
+
stuckQueuedMs;
|
|
1590
1600
|
now;
|
|
1591
1601
|
/** Cache of conversationId → opencode sessionId. */
|
|
1592
1602
|
sessions = /* @__PURE__ */ new Map();
|
|
@@ -1629,6 +1639,7 @@ var ChannelDriver = class {
|
|
|
1629
1639
|
this.pausedPollIntervalMs = config2.pausedPollIntervalMs ?? DEFAULT_PAUSED_POLL_INTERVAL_MS;
|
|
1630
1640
|
this.pausedMaxWaitMs = config2.pausedMaxWaitMs ?? DEFAULT_PAUSED_MAX_WAIT_MS;
|
|
1631
1641
|
this.dispatchConfirmMs = config2.dispatchConfirmMs ?? DEFAULT_DISPATCH_CONFIRM_MS;
|
|
1642
|
+
this.stuckQueuedMs = config2.stuckQueuedMs ?? DEFAULT_STUCK_QUEUED_MS;
|
|
1632
1643
|
this.now = config2.now ?? (() => Date.now());
|
|
1633
1644
|
}
|
|
1634
1645
|
/** The IPv4-loopback base URL for the local `opencode serve`. */
|
|
@@ -1747,6 +1758,7 @@ var ChannelDriver = class {
|
|
|
1747
1758
|
this.dispatched.add(message.id);
|
|
1748
1759
|
this.registerInFlight(conv, sessionId, message, opencodeMessageId);
|
|
1749
1760
|
dispatched += 1;
|
|
1761
|
+
void this.postSignal(conv.id, message.id, "dispatched");
|
|
1750
1762
|
}
|
|
1751
1763
|
if (messages.length > 0 && dispatched === 0 && skippedAlreadyDispatched === messages.length) {
|
|
1752
1764
|
this.log({
|
|
@@ -1812,7 +1824,8 @@ var ChannelDriver = class {
|
|
|
1812
1824
|
dispatchedAt: now,
|
|
1813
1825
|
deadline: now + this.pausedMaxWaitMs,
|
|
1814
1826
|
started: false,
|
|
1815
|
-
done: false
|
|
1827
|
+
done: false,
|
|
1828
|
+
stuckReported: false
|
|
1816
1829
|
});
|
|
1817
1830
|
}
|
|
1818
1831
|
/**
|
|
@@ -1972,6 +1985,12 @@ var ChannelDriver = class {
|
|
|
1972
1985
|
await this.redispatchInFlight(sessionId, inFlight);
|
|
1973
1986
|
}
|
|
1974
1987
|
}
|
|
1988
|
+
if (state === "queued" && !inFlight.started && !inFlight.stuckReported && this.now() - inFlight.dispatchedAt >= this.stuckQueuedMs && !hasRunningAssistantExcept(messages, inFlight.opencodeMessageId)) {
|
|
1989
|
+
inFlight.stuckReported = true;
|
|
1990
|
+
void this.postSignal(conv.id, inFlight.evidentMessageId, "stuck_queued", {
|
|
1991
|
+
stuck_for_ms: this.now() - inFlight.dispatchedAt
|
|
1992
|
+
});
|
|
1993
|
+
}
|
|
1975
1994
|
if (this.now() >= inFlight.deadline) {
|
|
1976
1995
|
this.log({
|
|
1977
1996
|
level: "info",
|
|
@@ -2258,6 +2277,42 @@ var ChannelDriver = class {
|
|
|
2258
2277
|
)
|
|
2259
2278
|
);
|
|
2260
2279
|
}
|
|
2280
|
+
/**
|
|
2281
|
+
* Best-effort, SINGLE-ATTEMPT runner→server telemetry ping
|
|
2282
|
+
* (queued-followup-redrive). `POST .../messages/:id/signal {signal, ...extra}`
|
|
2283
|
+
* — the server records it via `log()` (no DB write, no notification). This is
|
|
2284
|
+
* fire-and-forget: it MUST NEVER throw into the drain or the watcher tick, and
|
|
2285
|
+
* MUST NOT use `callWithRetry` (a telemetry ping must not block the sequential
|
|
2286
|
+
* watcher tick — one attempt is enough). A failure is SWALLOWED but LOGGED with
|
|
2287
|
+
* context (no silent catch, per development-workflow).
|
|
2288
|
+
*/
|
|
2289
|
+
async postSignal(conversationId, messageId, signal, extra) {
|
|
2290
|
+
try {
|
|
2291
|
+
const res = await this.fetchImpl(
|
|
2292
|
+
`${this.apiUrl}/agents/${this.agentId}/threads/${conversationId}/messages/${messageId}/signal`,
|
|
2293
|
+
{
|
|
2294
|
+
method: "POST",
|
|
2295
|
+
headers: { Authorization: this.getAuthHeader(), "Content-Type": "application/json" },
|
|
2296
|
+
body: JSON.stringify({ signal, ...extra })
|
|
2297
|
+
}
|
|
2298
|
+
);
|
|
2299
|
+
if (!res.ok) {
|
|
2300
|
+
this.log({
|
|
2301
|
+
level: "error",
|
|
2302
|
+
message: `Signal '${signal}' for message ${messageId.slice(0, 8)} returned HTTP ${res.status} (telemetry-only, ignored)`,
|
|
2303
|
+
conversation_id: conversationId,
|
|
2304
|
+
message_id: messageId
|
|
2305
|
+
});
|
|
2306
|
+
}
|
|
2307
|
+
} catch (err) {
|
|
2308
|
+
this.log({
|
|
2309
|
+
level: "error",
|
|
2310
|
+
message: `Signal '${signal}' for message ${messageId.slice(0, 8)} failed (telemetry-only, ignored): ${err instanceof Error ? err.message : String(err)}`,
|
|
2311
|
+
conversation_id: conversationId,
|
|
2312
|
+
message_id: messageId
|
|
2313
|
+
});
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2261
2316
|
async persistSession(conversationId, sessionId) {
|
|
2262
2317
|
const res = await this.fetchImpl(
|
|
2263
2318
|
`${this.apiUrl}/agents/${this.agentId}/threads/${conversationId}`,
|