@jini-ai/daemon 0.5.1 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/dist/delegated-tool-bridge.js +12 -0
- package/dist/run-lifecycle.d.ts +1 -0
- package/dist/run-lifecycle.js +11 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
## 0.5.2 — 2026-10-06
|
|
2
|
+
|
|
3
|
+
- No slow-run notice while a delegated tool waits on a surface: the first `emitSurface` of a call suspends the notice and the call's end resumes it. Suspensions are counted, so with two calls in flight the first to finish does not re-arm the notice over the other's open form; `resume()` drops suspensions left by an ended run.
|
|
4
|
+
|
|
1
5
|
## 0.5.1 — 2026-10-05
|
|
2
6
|
|
|
3
7
|
- The `@jini-ai/db` peer range is `^0.2.0 || ^0.3.0` (daemon uses only db's kernel and store entries, which 0.3.0 leaves unchanged), so a host on db 0.3.0 installs without a peer conflict.
|
|
@@ -109,9 +109,19 @@ export function createDelegatedToolBridge(options) {
|
|
|
109
109
|
* screen, with no call left to answer it.
|
|
110
110
|
*/
|
|
111
111
|
let settled = false;
|
|
112
|
+
// A handler emits a surface mid-call because it is about to WAIT on the human (a form, a card).
|
|
113
|
+
// Nothing reaches the run's event stream while they answer, so the slow-run watchdog would read
|
|
114
|
+
// that silence as a stall and post "Still working…" over an open form — which then reappears
|
|
115
|
+
// once the form is answered. Suspended from the first surface until the call settles (the
|
|
116
|
+
// `finally` below); the watchdog re-arms then, so a genuine stall afterwards is still caught.
|
|
117
|
+
let slowRunSuspended = false;
|
|
112
118
|
const emitSurface = async (emission) => {
|
|
113
119
|
if (settled)
|
|
114
120
|
throw new Error(`emitSurface: tool call ${toolUseId} has already completed`);
|
|
121
|
+
if (!slowRunSuspended) {
|
|
122
|
+
slowRunSuspended = true;
|
|
123
|
+
lifecycle.suspendSlowRunNotice({ runId: runId });
|
|
124
|
+
}
|
|
115
125
|
// Cast because `RunAgentPayload` is a closed union and `channel` is deliberately an open
|
|
116
126
|
// string — a seam that only accepts channels this file already knows about is not a
|
|
117
127
|
// channel-neutral seam. This mirrors `@jini-ai/protocol`'s own posture of typing each
|
|
@@ -202,6 +212,8 @@ export function createDelegatedToolBridge(options) {
|
|
|
202
212
|
finally {
|
|
203
213
|
unsubscribeCancel();
|
|
204
214
|
invocation.signal?.removeEventListener('abort', abortFromTransport);
|
|
215
|
+
if (slowRunSuspended)
|
|
216
|
+
lifecycle.resumeSlowRunNotice({ runId: runId });
|
|
205
217
|
}
|
|
206
218
|
}
|
|
207
219
|
return { execute };
|
package/dist/run-lifecycle.d.ts
CHANGED
|
@@ -106,6 +106,7 @@ export interface RunLifecycle {
|
|
|
106
106
|
* on a run that never actually stalled. A driver that knows exactly why a run is quiet must say so
|
|
107
107
|
* rather than leaving the watchdog to guess from silence alone. No-op if `runId` is unknown,
|
|
108
108
|
* already terminal, or the slow-run notice is disabled kernel-wide (`slowRunThresholdMs: null`).
|
|
109
|
+
* Pairs nest: the notice stays suspended until every open suspension has been resumed.
|
|
109
110
|
*/
|
|
110
111
|
suspendSlowRunNotice(args: {
|
|
111
112
|
readonly runId: string;
|
package/dist/run-lifecycle.js
CHANGED
|
@@ -102,6 +102,7 @@ function rehydratedRunRecord(runId, entries) {
|
|
|
102
102
|
terminalEndEntry: endEntry,
|
|
103
103
|
watchdog: undefined,
|
|
104
104
|
slowRunWatchdog: undefined,
|
|
105
|
+
slowRunSuspensions: 0,
|
|
105
106
|
startPromise: undefined,
|
|
106
107
|
finishPromise: undefined,
|
|
107
108
|
retentionTimer: undefined,
|
|
@@ -290,6 +291,7 @@ function buildNewRunRecord(startInput, runId, now) {
|
|
|
290
291
|
terminalEndEntry: undefined,
|
|
291
292
|
watchdog: undefined,
|
|
292
293
|
slowRunWatchdog: undefined,
|
|
294
|
+
slowRunSuspensions: 0,
|
|
293
295
|
startPromise: undefined,
|
|
294
296
|
finishPromise: undefined,
|
|
295
297
|
retentionTimer: undefined,
|
|
@@ -748,7 +750,9 @@ export function createRunLifecycle(requiredArgs, optionalArgs = {}) {
|
|
|
748
750
|
// freshly-started one does. Without this, `finish()`'s `record.slowRunWatchdog?.cancel()` (which
|
|
749
751
|
// never fires again on its own — the underlying timer is one-shot) left the notice permanently
|
|
750
752
|
// dark for the rest of a resumed run's life, silently disabling a feature the run is otherwise
|
|
751
|
-
// still eligible for.
|
|
753
|
+
// still eligible for. Suspensions left open when the run ended can never be resumed (resume is a
|
|
754
|
+
// no-op on a terminal run), so they are dropped here or they would keep the notice dark forever.
|
|
755
|
+
record.slowRunSuspensions = 0;
|
|
752
756
|
armSlowRunWatchdogIfConfigured({ record: record, timeoutMs: slowRunThresholdMs, onTimeout: () => {
|
|
753
757
|
void handleSlowRunNotice(runId);
|
|
754
758
|
} });
|
|
@@ -762,12 +766,18 @@ export function createRunLifecycle(requiredArgs, optionalArgs = {}) {
|
|
|
762
766
|
const record = runs.get(runId);
|
|
763
767
|
if (!record || isTerminalRunState({ state: record.status.state }))
|
|
764
768
|
return;
|
|
769
|
+
record.slowRunSuspensions += 1;
|
|
765
770
|
record.slowRunWatchdog?.cancel({});
|
|
766
771
|
},
|
|
767
772
|
resumeSlowRunNotice({ runId }) {
|
|
768
773
|
const record = runs.get(runId);
|
|
769
774
|
if (!record || isTerminalRunState({ state: record.status.state }))
|
|
770
775
|
return;
|
|
776
|
+
// Re-arm only when the LAST open suspension closes (see `RunRecord.slowRunSuspensions`).
|
|
777
|
+
if (record.slowRunSuspensions > 0)
|
|
778
|
+
record.slowRunSuspensions -= 1;
|
|
779
|
+
if (record.slowRunSuspensions > 0)
|
|
780
|
+
return;
|
|
771
781
|
// Suspension cancels permanently. Resuming must create a new window, never revive that handle.
|
|
772
782
|
record.slowRunWatchdog?.cancel({});
|
|
773
783
|
armSlowRunWatchdogIfConfigured({ record, timeoutMs: slowRunThresholdMs, onTimeout: () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jini-ai/daemon",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "The stateful agent daemon runtime: run lifecycle, durable event-log port, the tool-execution boundary, agent executor, terminal sessions, and routines.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -118,8 +118,8 @@
|
|
|
118
118
|
"dependencies": {
|
|
119
119
|
"@jini-ai/agent-runtime": "^0.4.0",
|
|
120
120
|
"@jini-ai/core": "^0.4.1",
|
|
121
|
-
"@jini-ai/
|
|
122
|
-
"@jini-ai/
|
|
121
|
+
"@jini-ai/platform": "^0.5.1",
|
|
122
|
+
"@jini-ai/protocol": "^0.4.0"
|
|
123
123
|
},
|
|
124
124
|
"devDependencies": {
|
|
125
125
|
"@vitest/coverage-v8": "^2.1.9",
|
|
@@ -132,9 +132,9 @@
|
|
|
132
132
|
"@types/pg": "8.23.1",
|
|
133
133
|
"express": "^4.21.0",
|
|
134
134
|
"@types/express": "^4.17.21",
|
|
135
|
-
"@jini-ai/
|
|
135
|
+
"@jini-ai/db": "0.3.0",
|
|
136
136
|
"@jini-ai/http-kit": "0.4.0",
|
|
137
|
-
"@jini-ai/
|
|
137
|
+
"@jini-ai/chat": "0.5.3"
|
|
138
138
|
},
|
|
139
139
|
"peerDependencies": {
|
|
140
140
|
"node-pty": "^1.1.0",
|