@nylorun/runtime 0.42.0-beta → 0.43.0-beta
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 +22 -0
- package/dist/api/components.d.ts +43 -0
- package/dist/harness-api/record.js +20 -0
- package/dist/management-openapi.json +3 -2
- package/dist/openapi.json +29 -6
- package/dist/store/postgres/drizzle/0045_session_queue_delivery.sql +2 -0
- package/dist/store/postgres/drizzle/meta/_journal.json +7 -0
- package/dist/store/postgres/schema.d.ts +19 -1
- package/dist/store/postgres/schema.js +11 -2
- package/dist/tenant/commands.d.ts +19 -3
- package/dist/tenant/commands.js +55 -6
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.43.0-beta
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- c649f33: A message can steer a running turn (D85). `delivery: "steer"` on a `message` command, behind the
|
|
8
|
+
optional Host feature `steer`: to a busy agent session it waits in the session queue marked
|
|
9
|
+
`steer`, and our engine takes it into the running turn before its next step, after the tool
|
|
10
|
+
results, through a new effect kind, `inputs`, which core answers in the transaction that journals
|
|
11
|
+
it (Harness API 5, `harness-api/v5.4.json`). Each taken message's `command.message` is written
|
|
12
|
+
under the running turn, then `queue.taken` with the `step`. The queued answer and
|
|
13
|
+
`message.queued` say which delivery applied; a workflow session queues. A steer the turn doesn't
|
|
14
|
+
take starts the next turn like any queued message, and D76's defaults never choose steer.
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- Pin core to the tested release.
|
|
19
|
+
- Pin harness to the tested release.
|
|
20
|
+
- Updated dependencies [c649f33]
|
|
21
|
+
- Updated dependencies
|
|
22
|
+
- @nylorun/core@0.37.0-beta
|
|
23
|
+
- @nylorun/harness@0.34.0-beta
|
|
24
|
+
|
|
3
25
|
## 0.42.0-beta
|
|
4
26
|
|
|
5
27
|
### Minor Changes
|
package/dist/api/components.d.ts
CHANGED
|
@@ -2214,6 +2214,7 @@ export declare const SessionCommand: z.ZodUnion<readonly [z.ZodUnion<readonly [z
|
|
|
2214
2214
|
delivery: z.ZodOptional<z.ZodEnum<{
|
|
2215
2215
|
queue: "queue";
|
|
2216
2216
|
reject: "reject";
|
|
2217
|
+
steer: "steer";
|
|
2217
2218
|
}>>;
|
|
2218
2219
|
content: z.ZodString;
|
|
2219
2220
|
}, z.core.$strict>, z.ZodObject<{
|
|
@@ -2225,6 +2226,7 @@ export declare const SessionCommand: z.ZodUnion<readonly [z.ZodUnion<readonly [z
|
|
|
2225
2226
|
delivery: z.ZodOptional<z.ZodEnum<{
|
|
2226
2227
|
queue: "queue";
|
|
2227
2228
|
reject: "reject";
|
|
2229
|
+
steer: "steer";
|
|
2228
2230
|
}>>;
|
|
2229
2231
|
data: z.ZodType<import("@nylorun/core/define").JsonValue, unknown, z.core.$ZodTypeInternals<import("@nylorun/core/define").JsonValue, unknown>>;
|
|
2230
2232
|
}, z.core.$strict>, z.ZodObject<{
|
|
@@ -2236,6 +2238,7 @@ export declare const SessionCommand: z.ZodUnion<readonly [z.ZodUnion<readonly [z
|
|
|
2236
2238
|
delivery: z.ZodOptional<z.ZodEnum<{
|
|
2237
2239
|
queue: "queue";
|
|
2238
2240
|
reject: "reject";
|
|
2241
|
+
steer: "steer";
|
|
2239
2242
|
}>>;
|
|
2240
2243
|
parts: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
2241
2244
|
type: z.ZodLiteral<"text">;
|
|
@@ -2273,6 +2276,10 @@ export declare const QueuedResponse: z.ZodObject<{
|
|
|
2273
2276
|
status: z.ZodLiteral<"queued">;
|
|
2274
2277
|
queuedMessageId: z.ZodString;
|
|
2275
2278
|
position: z.ZodNumber;
|
|
2279
|
+
delivery: z.ZodOptional<z.ZodEnum<{
|
|
2280
|
+
queue: "queue";
|
|
2281
|
+
steer: "steer";
|
|
2282
|
+
}>>;
|
|
2276
2283
|
cursor: z.ZodNullable<z.ZodString>;
|
|
2277
2284
|
requestId: z.ZodString;
|
|
2278
2285
|
}, z.core.$strip>;
|
|
@@ -3309,6 +3316,7 @@ export declare const SessionEvent: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
3309
3316
|
delivery: z.ZodOptional<z.ZodEnum<{
|
|
3310
3317
|
queue: "queue";
|
|
3311
3318
|
reject: "reject";
|
|
3319
|
+
steer: "steer";
|
|
3312
3320
|
}>>;
|
|
3313
3321
|
queuedMessageId: z.ZodOptional<z.ZodString>;
|
|
3314
3322
|
cause: z.ZodOptional<z.ZodObject<{
|
|
@@ -4431,6 +4439,10 @@ export declare const SessionEvent: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
4431
4439
|
queuedMessageId: z.ZodString;
|
|
4432
4440
|
position: z.ZodNumber;
|
|
4433
4441
|
requestId: z.ZodString;
|
|
4442
|
+
delivery: z.ZodOptional<z.ZodEnum<{
|
|
4443
|
+
queue: "queue";
|
|
4444
|
+
steer: "steer";
|
|
4445
|
+
}>>;
|
|
4434
4446
|
}, z.core.$loose>;
|
|
4435
4447
|
}, z.core.$strip> | z.ZodObject<{
|
|
4436
4448
|
schema: z.ZodLiteral<"nylorun.event/2">;
|
|
@@ -4904,6 +4916,7 @@ export declare const SessionEvent: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
4904
4916
|
payload: z.ZodObject<{
|
|
4905
4917
|
turnId: z.ZodString;
|
|
4906
4918
|
queuedMessageIds: z.ZodArray<z.ZodString>;
|
|
4919
|
+
step: z.ZodOptional<z.ZodNumber>;
|
|
4907
4920
|
}, z.core.$loose>;
|
|
4908
4921
|
}, z.core.$strip> | z.ZodObject<{
|
|
4909
4922
|
schema: z.ZodLiteral<"nylorun.event/2">;
|
|
@@ -6388,6 +6401,7 @@ export declare const SessionEvent: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
6388
6401
|
delivery: z.ZodOptional<z.ZodEnum<{
|
|
6389
6402
|
queue: "queue";
|
|
6390
6403
|
reject: "reject";
|
|
6404
|
+
steer: "steer";
|
|
6391
6405
|
}>>;
|
|
6392
6406
|
queuedMessageId: z.ZodOptional<z.ZodString>;
|
|
6393
6407
|
cause: z.ZodOptional<z.ZodObject<{
|
|
@@ -7510,6 +7524,10 @@ export declare const SessionEvent: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
7510
7524
|
queuedMessageId: z.ZodString;
|
|
7511
7525
|
position: z.ZodNumber;
|
|
7512
7526
|
requestId: z.ZodString;
|
|
7527
|
+
delivery: z.ZodOptional<z.ZodEnum<{
|
|
7528
|
+
queue: "queue";
|
|
7529
|
+
steer: "steer";
|
|
7530
|
+
}>>;
|
|
7513
7531
|
}, z.core.$loose>;
|
|
7514
7532
|
}, z.core.$strip> | z.ZodObject<{
|
|
7515
7533
|
schema: z.ZodLiteral<"nylorun.event/2">;
|
|
@@ -7983,6 +8001,7 @@ export declare const SessionEvent: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
7983
8001
|
payload: z.ZodObject<{
|
|
7984
8002
|
turnId: z.ZodString;
|
|
7985
8003
|
queuedMessageIds: z.ZodArray<z.ZodString>;
|
|
8004
|
+
step: z.ZodOptional<z.ZodNumber>;
|
|
7986
8005
|
}, z.core.$loose>;
|
|
7987
8006
|
}, z.core.$strip> | z.ZodObject<{
|
|
7988
8007
|
schema: z.ZodLiteral<"nylorun.event/2">;
|
|
@@ -9470,6 +9489,7 @@ export declare const SessionItemsResponse: z.ZodObject<{
|
|
|
9470
9489
|
delivery: z.ZodOptional<z.ZodEnum<{
|
|
9471
9490
|
queue: "queue";
|
|
9472
9491
|
reject: "reject";
|
|
9492
|
+
steer: "steer";
|
|
9473
9493
|
}>>;
|
|
9474
9494
|
queuedMessageId: z.ZodOptional<z.ZodString>;
|
|
9475
9495
|
cause: z.ZodOptional<z.ZodObject<{
|
|
@@ -10592,6 +10612,10 @@ export declare const SessionItemsResponse: z.ZodObject<{
|
|
|
10592
10612
|
queuedMessageId: z.ZodString;
|
|
10593
10613
|
position: z.ZodNumber;
|
|
10594
10614
|
requestId: z.ZodString;
|
|
10615
|
+
delivery: z.ZodOptional<z.ZodEnum<{
|
|
10616
|
+
queue: "queue";
|
|
10617
|
+
steer: "steer";
|
|
10618
|
+
}>>;
|
|
10595
10619
|
}, z.core.$loose>;
|
|
10596
10620
|
}, z.core.$strip> | z.ZodObject<{
|
|
10597
10621
|
schema: z.ZodLiteral<"nylorun.event/2">;
|
|
@@ -11065,6 +11089,7 @@ export declare const SessionItemsResponse: z.ZodObject<{
|
|
|
11065
11089
|
payload: z.ZodObject<{
|
|
11066
11090
|
turnId: z.ZodString;
|
|
11067
11091
|
queuedMessageIds: z.ZodArray<z.ZodString>;
|
|
11092
|
+
step: z.ZodOptional<z.ZodNumber>;
|
|
11068
11093
|
}, z.core.$loose>;
|
|
11069
11094
|
}, z.core.$strip> | z.ZodObject<{
|
|
11070
11095
|
schema: z.ZodLiteral<"nylorun.event/2">;
|
|
@@ -12549,6 +12574,7 @@ export declare const SessionItemsResponse: z.ZodObject<{
|
|
|
12549
12574
|
delivery: z.ZodOptional<z.ZodEnum<{
|
|
12550
12575
|
queue: "queue";
|
|
12551
12576
|
reject: "reject";
|
|
12577
|
+
steer: "steer";
|
|
12552
12578
|
}>>;
|
|
12553
12579
|
queuedMessageId: z.ZodOptional<z.ZodString>;
|
|
12554
12580
|
cause: z.ZodOptional<z.ZodObject<{
|
|
@@ -13671,6 +13697,10 @@ export declare const SessionItemsResponse: z.ZodObject<{
|
|
|
13671
13697
|
queuedMessageId: z.ZodString;
|
|
13672
13698
|
position: z.ZodNumber;
|
|
13673
13699
|
requestId: z.ZodString;
|
|
13700
|
+
delivery: z.ZodOptional<z.ZodEnum<{
|
|
13701
|
+
queue: "queue";
|
|
13702
|
+
steer: "steer";
|
|
13703
|
+
}>>;
|
|
13674
13704
|
}, z.core.$loose>;
|
|
13675
13705
|
}, z.core.$strip> | z.ZodObject<{
|
|
13676
13706
|
schema: z.ZodLiteral<"nylorun.event/2">;
|
|
@@ -14144,6 +14174,7 @@ export declare const SessionItemsResponse: z.ZodObject<{
|
|
|
14144
14174
|
payload: z.ZodObject<{
|
|
14145
14175
|
turnId: z.ZodString;
|
|
14146
14176
|
queuedMessageIds: z.ZodArray<z.ZodString>;
|
|
14177
|
+
step: z.ZodOptional<z.ZodNumber>;
|
|
14147
14178
|
}, z.core.$loose>;
|
|
14148
14179
|
}, z.core.$strip> | z.ZodObject<{
|
|
14149
14180
|
schema: z.ZodLiteral<"nylorun.event/2">;
|
|
@@ -16546,6 +16577,7 @@ export declare const HistoryPage: z.ZodObject<{
|
|
|
16546
16577
|
delivery: z.ZodOptional<z.ZodEnum<{
|
|
16547
16578
|
queue: "queue";
|
|
16548
16579
|
reject: "reject";
|
|
16580
|
+
steer: "steer";
|
|
16549
16581
|
}>>;
|
|
16550
16582
|
queuedMessageId: z.ZodOptional<z.ZodString>;
|
|
16551
16583
|
cause: z.ZodOptional<z.ZodObject<{
|
|
@@ -17668,6 +17700,10 @@ export declare const HistoryPage: z.ZodObject<{
|
|
|
17668
17700
|
queuedMessageId: z.ZodString;
|
|
17669
17701
|
position: z.ZodNumber;
|
|
17670
17702
|
requestId: z.ZodString;
|
|
17703
|
+
delivery: z.ZodOptional<z.ZodEnum<{
|
|
17704
|
+
queue: "queue";
|
|
17705
|
+
steer: "steer";
|
|
17706
|
+
}>>;
|
|
17671
17707
|
}, z.core.$loose>;
|
|
17672
17708
|
}, z.core.$strip> | z.ZodObject<{
|
|
17673
17709
|
schema: z.ZodLiteral<"nylorun.event/2">;
|
|
@@ -18141,6 +18177,7 @@ export declare const HistoryPage: z.ZodObject<{
|
|
|
18141
18177
|
payload: z.ZodObject<{
|
|
18142
18178
|
turnId: z.ZodString;
|
|
18143
18179
|
queuedMessageIds: z.ZodArray<z.ZodString>;
|
|
18180
|
+
step: z.ZodOptional<z.ZodNumber>;
|
|
18144
18181
|
}, z.core.$loose>;
|
|
18145
18182
|
}, z.core.$strip> | z.ZodObject<{
|
|
18146
18183
|
schema: z.ZodLiteral<"nylorun.event/2">;
|
|
@@ -19625,6 +19662,7 @@ export declare const HistoryPage: z.ZodObject<{
|
|
|
19625
19662
|
delivery: z.ZodOptional<z.ZodEnum<{
|
|
19626
19663
|
queue: "queue";
|
|
19627
19664
|
reject: "reject";
|
|
19665
|
+
steer: "steer";
|
|
19628
19666
|
}>>;
|
|
19629
19667
|
queuedMessageId: z.ZodOptional<z.ZodString>;
|
|
19630
19668
|
cause: z.ZodOptional<z.ZodObject<{
|
|
@@ -20747,6 +20785,10 @@ export declare const HistoryPage: z.ZodObject<{
|
|
|
20747
20785
|
queuedMessageId: z.ZodString;
|
|
20748
20786
|
position: z.ZodNumber;
|
|
20749
20787
|
requestId: z.ZodString;
|
|
20788
|
+
delivery: z.ZodOptional<z.ZodEnum<{
|
|
20789
|
+
queue: "queue";
|
|
20790
|
+
steer: "steer";
|
|
20791
|
+
}>>;
|
|
20750
20792
|
}, z.core.$loose>;
|
|
20751
20793
|
}, z.core.$strip> | z.ZodObject<{
|
|
20752
20794
|
schema: z.ZodLiteral<"nylorun.event/2">;
|
|
@@ -21220,6 +21262,7 @@ export declare const HistoryPage: z.ZodObject<{
|
|
|
21220
21262
|
payload: z.ZodObject<{
|
|
21221
21263
|
turnId: z.ZodString;
|
|
21222
21264
|
queuedMessageIds: z.ZodArray<z.ZodString>;
|
|
21265
|
+
step: z.ZodOptional<z.ZodNumber>;
|
|
21223
21266
|
}, z.core.$loose>;
|
|
21224
21267
|
}, z.core.$strip> | z.ZodObject<{
|
|
21225
21268
|
schema: z.ZodLiteral<"nylorun.event/2">;
|
|
@@ -28,6 +28,7 @@ import { sessionSandboxSpec } from "../sandbox/share.js";
|
|
|
28
28
|
import { readRuntimeLimits } from "../tenant/runtime-limits.js";
|
|
29
29
|
import { checkEntry } from "../record/index.js";
|
|
30
30
|
import { turnManifestOf } from "../tenant/session.js";
|
|
31
|
+
import { takeSteeredMessages } from "../tenant/commands.js";
|
|
31
32
|
import { isEnabledIn, manifestFor, mcpToolIn } from "../mcp/snapshot.js";
|
|
32
33
|
import { findServer } from "../mcp/pool.js";
|
|
33
34
|
import { isHttpToolCall } from "../gates/http-tool.js";
|
|
@@ -127,6 +128,25 @@ export async function recordIntent(scope, effect, requestHash) {
|
|
|
127
128
|
await t.put("effects", request.effectId, row);
|
|
128
129
|
return { status: "execute", traceparent: row.traceparent };
|
|
129
130
|
}
|
|
131
|
+
if (request.kind === "inputs") {
|
|
132
|
+
// The messages steered into the running turn (D85), taken before a step: journaled with
|
|
133
|
+
// what was taken, empty or not, so a replay takes the same messages at the same step.
|
|
134
|
+
const step = Number(request.input?.step);
|
|
135
|
+
const events = await takeSteeredMessages(t, s, s.id, Number.isInteger(step) && step > 0 ? step : 1);
|
|
136
|
+
if (events.length > 0)
|
|
137
|
+
await t.put("sessions", s.id, s);
|
|
138
|
+
const outcome = { value: { events } };
|
|
139
|
+
const at = new Date().toISOString();
|
|
140
|
+
await t.put("effects", request.effectId, {
|
|
141
|
+
request,
|
|
142
|
+
requestHash,
|
|
143
|
+
status: "completed",
|
|
144
|
+
outcome,
|
|
145
|
+
startedAt: at,
|
|
146
|
+
settledAt: at,
|
|
147
|
+
});
|
|
148
|
+
return { status: "completed", outcome };
|
|
149
|
+
}
|
|
130
150
|
if (request.kind === "delegation") {
|
|
131
151
|
// Lifecycle points of an agent used as a tool: journaled once, so replays never re-emit.
|
|
132
152
|
const outcome = { value: null };
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"openapi": "3.2.0",
|
|
3
3
|
"info": {
|
|
4
4
|
"title": "Nylorun Management API",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.43.0-beta",
|
|
6
6
|
"x-nylorun-protocol": {
|
|
7
7
|
"min": 16,
|
|
8
8
|
"max": 18,
|
|
@@ -43,7 +43,8 @@
|
|
|
43
43
|
"agent-model",
|
|
44
44
|
"secret-routing",
|
|
45
45
|
"remove-tools",
|
|
46
|
-
"agent-triggers"
|
|
46
|
+
"agent-triggers",
|
|
47
|
+
"steer"
|
|
47
48
|
]
|
|
48
49
|
},
|
|
49
50
|
"description": "For operators: the Tenant's models, vaults, signing keys, settings and application keys, at `/v1/tenant/*` on the Tenant's URL, through `@nylorun/admin`. Every operation takes a management key, acting as itself: never for a subject and never from a browser. Management keys are issued only on the Tenant's machine (`nylorun tenant keys put <id> --management`) or from `NYLORUN_MANAGEMENT_KEY_FILE`."
|
package/dist/openapi.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"openapi": "3.2.0",
|
|
3
3
|
"info": {
|
|
4
4
|
"title": "Nylorun Runtime API",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.43.0-beta",
|
|
6
6
|
"x-nylorun-protocol": {
|
|
7
7
|
"min": 16,
|
|
8
8
|
"max": 18,
|
|
@@ -43,7 +43,8 @@
|
|
|
43
43
|
"agent-model",
|
|
44
44
|
"secret-routing",
|
|
45
45
|
"remove-tools",
|
|
46
|
-
"agent-triggers"
|
|
46
|
+
"agent-triggers",
|
|
47
|
+
"steer"
|
|
47
48
|
]
|
|
48
49
|
},
|
|
49
50
|
"description": "For developers: agent manifests, Agents, sessions (with AG-UI and A2A) and artifacts, through `@nylorun/agents`. Every Tenant serves it on its one URL, beside the Management API (`/openapi/management.json`). Every request sends `Nylorun-Protocol`. Who may call each operation is its `security` and its `x-nylorun-credentials` and `x-nylorun-scopes` (the subject scopes that reach it) fields: an application key (servers) or a trusted issuer's token (browsers and apps)."
|
|
@@ -6336,6 +6337,13 @@
|
|
|
6336
6337
|
"type": "integer",
|
|
6337
6338
|
"exclusiveMinimum": 0
|
|
6338
6339
|
},
|
|
6340
|
+
"delivery": {
|
|
6341
|
+
"type": "string",
|
|
6342
|
+
"enum": [
|
|
6343
|
+
"queue",
|
|
6344
|
+
"steer"
|
|
6345
|
+
]
|
|
6346
|
+
},
|
|
6339
6347
|
"cursor": {
|
|
6340
6348
|
"type": [
|
|
6341
6349
|
"string",
|
|
@@ -6788,7 +6796,8 @@
|
|
|
6788
6796
|
"type": "string",
|
|
6789
6797
|
"enum": [
|
|
6790
6798
|
"queue",
|
|
6791
|
-
"reject"
|
|
6799
|
+
"reject",
|
|
6800
|
+
"steer"
|
|
6792
6801
|
]
|
|
6793
6802
|
},
|
|
6794
6803
|
"content": {
|
|
@@ -7116,7 +7125,8 @@
|
|
|
7116
7125
|
"type": "string",
|
|
7117
7126
|
"enum": [
|
|
7118
7127
|
"queue",
|
|
7119
|
-
"reject"
|
|
7128
|
+
"reject",
|
|
7129
|
+
"steer"
|
|
7120
7130
|
]
|
|
7121
7131
|
},
|
|
7122
7132
|
"data": {
|
|
@@ -7443,7 +7453,8 @@
|
|
|
7443
7453
|
"type": "string",
|
|
7444
7454
|
"enum": [
|
|
7445
7455
|
"queue",
|
|
7446
|
-
"reject"
|
|
7456
|
+
"reject",
|
|
7457
|
+
"steer"
|
|
7447
7458
|
]
|
|
7448
7459
|
},
|
|
7449
7460
|
"parts": {
|
|
@@ -9700,7 +9711,8 @@
|
|
|
9700
9711
|
"type": "string",
|
|
9701
9712
|
"enum": [
|
|
9702
9713
|
"queue",
|
|
9703
|
-
"reject"
|
|
9714
|
+
"reject",
|
|
9715
|
+
"steer"
|
|
9704
9716
|
]
|
|
9705
9717
|
},
|
|
9706
9718
|
"queuedMessageId": {
|
|
@@ -11856,6 +11868,13 @@
|
|
|
11856
11868
|
},
|
|
11857
11869
|
"requestId": {
|
|
11858
11870
|
"type": "string"
|
|
11871
|
+
},
|
|
11872
|
+
"delivery": {
|
|
11873
|
+
"type": "string",
|
|
11874
|
+
"enum": [
|
|
11875
|
+
"queue",
|
|
11876
|
+
"steer"
|
|
11877
|
+
]
|
|
11859
11878
|
}
|
|
11860
11879
|
},
|
|
11861
11880
|
"required": [
|
|
@@ -12057,6 +12076,10 @@
|
|
|
12057
12076
|
"type": "string"
|
|
12058
12077
|
},
|
|
12059
12078
|
"minItems": 1
|
|
12079
|
+
},
|
|
12080
|
+
"step": {
|
|
12081
|
+
"type": "integer",
|
|
12082
|
+
"exclusiveMinimum": 0
|
|
12060
12083
|
}
|
|
12061
12084
|
},
|
|
12062
12085
|
"required": [
|
|
@@ -316,6 +316,13 @@
|
|
|
316
316
|
"when": 1793548858191,
|
|
317
317
|
"tag": "0044_agent_triggers_origin_backfill",
|
|
318
318
|
"breakpoints": true
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
"idx": 45,
|
|
322
|
+
"version": "7",
|
|
323
|
+
"when": 1793954783377,
|
|
324
|
+
"tag": "0045_session_queue_delivery",
|
|
325
|
+
"breakpoints": true
|
|
319
326
|
}
|
|
320
327
|
]
|
|
321
328
|
}
|
|
@@ -4484,7 +4484,8 @@ export declare const turns: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
|
4484
4484
|
}>;
|
|
4485
4485
|
/**
|
|
4486
4486
|
* Each session's queue (protocol 17, D76): messages that arrived while its turn ran or waited, in
|
|
4487
|
-
* order (`seq`), until a turn takes them
|
|
4487
|
+
* order (`seq`), until a turn takes them: the next turn, or the running one before a step for a
|
|
4488
|
+
* steered message (D85). A row holds the command as sent, the turn input its
|
|
4488
4489
|
* message gives the engine (file parts pinned when it was queued), and who sent it.
|
|
4489
4490
|
*/
|
|
4490
4491
|
export declare const sessionQueue: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
@@ -4679,6 +4680,23 @@ export declare const sessionQueue: import("drizzle-orm/pg-core").PgTableWithColu
|
|
|
4679
4680
|
}, {}, {
|
|
4680
4681
|
pgColumnBuilderBrand: 'PgCustomColumnBuilderBrand';
|
|
4681
4682
|
}>;
|
|
4683
|
+
delivery: import("drizzle-orm/pg-core").PgColumn<{
|
|
4684
|
+
name: "delivery";
|
|
4685
|
+
tableName: "session_queue";
|
|
4686
|
+
dataType: "string";
|
|
4687
|
+
columnType: "PgText";
|
|
4688
|
+
data: "queue" | "steer";
|
|
4689
|
+
driverParam: string;
|
|
4690
|
+
notNull: true;
|
|
4691
|
+
hasDefault: true;
|
|
4692
|
+
isPrimaryKey: false;
|
|
4693
|
+
isAutoincrement: false;
|
|
4694
|
+
hasRuntimeDefault: false;
|
|
4695
|
+
enumValues: ["queue", "steer"];
|
|
4696
|
+
baseColumn: never;
|
|
4697
|
+
identity: undefined;
|
|
4698
|
+
generated: undefined;
|
|
4699
|
+
}, {}, {}>;
|
|
4682
4700
|
};
|
|
4683
4701
|
dialect: 'pg';
|
|
4684
4702
|
}>;
|
|
@@ -560,7 +560,8 @@ export const turns = nylorun.table("turns", {
|
|
|
560
560
|
]);
|
|
561
561
|
/**
|
|
562
562
|
* Each session's queue (protocol 17, D76): messages that arrived while its turn ran or waited, in
|
|
563
|
-
* order (`seq`), until a turn takes them
|
|
563
|
+
* order (`seq`), until a turn takes them: the next turn, or the running one before a step for a
|
|
564
|
+
* steered message (D85). A row holds the command as sent, the turn input its
|
|
564
565
|
* message gives the engine (file parts pinned when it was queued), and who sent it.
|
|
565
566
|
*/
|
|
566
567
|
export const sessionQueue = nylorun.table("session_queue", {
|
|
@@ -580,7 +581,15 @@ export const sessionQueue = nylorun.table("session_queue", {
|
|
|
580
581
|
/** What sent it when not a client (track T4): a trigger's run, or the session's own wake. */
|
|
581
582
|
cause: jsonText(),
|
|
582
583
|
createdAt: textC().notNull(),
|
|
583
|
-
|
|
584
|
+
/**
|
|
585
|
+
* `steer` (D85): the running turn may take it before a step (the `inputs` effect); `queue`:
|
|
586
|
+
* it waits for the turn to end. Either starts the next turn if the running one didn't take it.
|
|
587
|
+
*/
|
|
588
|
+
delivery: text({ enum: ["queue", "steer"] }).notNull().default("queue"),
|
|
589
|
+
}, (t) => [
|
|
590
|
+
uniqueIndex("session_queue_order").on(t.sessionId, t.seq),
|
|
591
|
+
check("session_queue_delivery_check", sql `${t.delivery} IN ('queue', 'steer')`),
|
|
592
|
+
]);
|
|
584
593
|
/**
|
|
585
594
|
* The Tool Gate's keyed MCP calls (F4.1 G3): one row per call, written by the gates service
|
|
586
595
|
* before it calls the server and given the answer after. A re-send whose row has an answer
|
|
@@ -37,7 +37,10 @@ export interface MessageCause {
|
|
|
37
37
|
triggerId: string;
|
|
38
38
|
runId: string;
|
|
39
39
|
}
|
|
40
|
-
/**
|
|
40
|
+
/**
|
|
41
|
+
* How a message was taken: it started a turn, or waits in the session's queue, marked with the
|
|
42
|
+
* delivery that applied (D85): `steer` when the running turn may take it before a step.
|
|
43
|
+
*/
|
|
41
44
|
export type MessageAnswer = {
|
|
42
45
|
status: "accepted";
|
|
43
46
|
turnId: string;
|
|
@@ -47,15 +50,28 @@ export type MessageAnswer = {
|
|
|
47
50
|
queuedMessageId: string;
|
|
48
51
|
position: number;
|
|
49
52
|
cursor: string;
|
|
53
|
+
delivery: "queue" | "steer";
|
|
50
54
|
};
|
|
51
55
|
/**
|
|
52
56
|
* Takes a resolved message on session `s` (locked) in transaction `t`: it starts a turn when the
|
|
53
57
|
* session takes messages and none wait, else it waits in the queue behind them (protocol 17), and
|
|
54
58
|
* an idle session whose queue was left waiting (its Agent was unavailable when the last turn
|
|
55
59
|
* ended) starts a turn with all of them, this one last. Past `sessionQueuedMessages` it is
|
|
56
|
-
* `429 queue_full`. `waiting` is the queue's length, read under the session's lock.
|
|
60
|
+
* `429 queue_full`. `waiting` is the queue's length, read under the session's lock. `asked`
|
|
61
|
+
* `steer` (D85) marks a waiting message so the running turn may take it before a step; a
|
|
62
|
+
* workflow session can't, so it waits as `queue`.
|
|
63
|
+
*/
|
|
64
|
+
export declare function acceptMessage(ctx: TenantContext, t: Tx, s: Session, id: string, message: TurnMessage, waiting?: number, asked?: "queue" | "steer"): Promise<MessageAnswer>;
|
|
65
|
+
/**
|
|
66
|
+
* Takes the messages steered into session `s`'s running turn (D85), before step `step`: the
|
|
67
|
+
* `inputs` effect, in the transaction that journals it (`harness-api/record.ts`). Only `steer`
|
|
68
|
+
* rows whose turn request (variant, `removeTools`) is the running turn's join it; the rest wait
|
|
69
|
+
* for the turn's end. Writes each one's `command.message` under the turn, then one `queue.taken`
|
|
70
|
+
* with the step, adds their file artifacts to the session's, and returns their inputs (each as its
|
|
71
|
+
* message gave it, which the engine reads as a user message) in order. A workflow session takes
|
|
72
|
+
* none.
|
|
57
73
|
*/
|
|
58
|
-
export declare function
|
|
74
|
+
export declare function takeSteeredMessages(t: Tx, s: Session, id: string, step: number): Promise<unknown[]>;
|
|
59
75
|
/** Who checks a queued message's turn start: core, since the sender's grants were checked when it was queued. */
|
|
60
76
|
export declare const QUEUE_SCOPE: AuthScope;
|
|
61
77
|
/**
|
package/dist/tenant/commands.js
CHANGED
|
@@ -19,7 +19,10 @@
|
|
|
19
19
|
* (`session_queue`, `message.queued`) unless it asks `delivery: "reject"`, which is
|
|
20
20
|
* `409 session_busy`. A turn that ends takes every queued message in the same transaction
|
|
21
21
|
* (`startQueuedTurn`): client messages and queued ones start a turn through one door,
|
|
22
|
-
* `beginMessageTurn`, which writes each one's `command.message`.
|
|
22
|
+
* `beginMessageTurn`, which writes each one's `command.message`. A message that asks
|
|
23
|
+
* `delivery: "steer"` (D85) waits marked `steer`, and the running turn takes it before a step
|
|
24
|
+
* (`takeSteeredMessages`, the `inputs` effect); one it doesn't take starts the next turn like
|
|
25
|
+
* any other.
|
|
23
26
|
*/
|
|
24
27
|
import { randomUUID } from "node:crypto";
|
|
25
28
|
import { createDurableCheckpoint, createFlowCheckpoint, resumeFlowCheckpoint, } from "@nylorun/harness/run";
|
|
@@ -157,7 +160,7 @@ options = {}) {
|
|
|
157
160
|
// Every turn start on a sandbox: it exists, the token's grants reach it, and no other
|
|
158
161
|
// session's turn holds it. A queued message is checked when it is queued, too.
|
|
159
162
|
await checkAgentTurn(t, s, scope, ctx);
|
|
160
|
-
answer = await acceptMessage(ctx, t, s, id, await turnMessage(t, s, id, command, scope, options.trace), waiting);
|
|
163
|
+
answer = await acceptMessage(ctx, t, s, id, await turnMessage(t, s, id, command, scope, options.trace), waiting, delivery === "steer" ? "steer" : "queue");
|
|
161
164
|
}
|
|
162
165
|
else if (command.type === "approve" &&
|
|
163
166
|
(held = await heldCall(t, s, command.interactionId)) !== undefined) {
|
|
@@ -299,9 +302,11 @@ export const takesMessages = (s) => TAKES_MESSAGES.includes(s.status);
|
|
|
299
302
|
* session takes messages and none wait, else it waits in the queue behind them (protocol 17), and
|
|
300
303
|
* an idle session whose queue was left waiting (its Agent was unavailable when the last turn
|
|
301
304
|
* ended) starts a turn with all of them, this one last. Past `sessionQueuedMessages` it is
|
|
302
|
-
* `429 queue_full`. `waiting` is the queue's length, read under the session's lock.
|
|
305
|
+
* `429 queue_full`. `waiting` is the queue's length, read under the session's lock. `asked`
|
|
306
|
+
* `steer` (D85) marks a waiting message so the running turn may take it before a step; a
|
|
307
|
+
* workflow session can't, so it waits as `queue`.
|
|
303
308
|
*/
|
|
304
|
-
export async function acceptMessage(ctx, t, s, id, message, waiting) {
|
|
309
|
+
export async function acceptMessage(ctx, t, s, id, message, waiting, asked = "queue") {
|
|
305
310
|
const queued = waiting ?? (await t.countQueuedMessages(id));
|
|
306
311
|
const takes = takesMessages(s);
|
|
307
312
|
if (takes && queued === 0) {
|
|
@@ -313,6 +318,7 @@ export async function acceptMessage(ctx, t, s, id, message, waiting) {
|
|
|
313
318
|
if (queued >= sessionQueuedMessages)
|
|
314
319
|
fail(429, `Session ${id} already holds ${queued} queued messages, the Runtime limit sessionQueuedMessages (PUT /v1/tenant/limits); they start a turn when the running one ends.`, { code: "queue_full" });
|
|
315
320
|
const queuedMessageId = randomUUID();
|
|
321
|
+
const delivery = asked === "steer" && !isWorkflowManifest(s.manifest) ? "steer" : "queue";
|
|
316
322
|
await t.enqueueMessage({
|
|
317
323
|
id: queuedMessageId,
|
|
318
324
|
sessionId: id,
|
|
@@ -323,13 +329,56 @@ export async function acceptMessage(ctx, t, s, id, message, waiting) {
|
|
|
323
329
|
trace: message.trace ?? null,
|
|
324
330
|
cause: message.cause ?? null,
|
|
325
331
|
createdAt: new Date().toISOString(),
|
|
332
|
+
delivery,
|
|
326
333
|
});
|
|
327
334
|
const position = queued + 1;
|
|
328
|
-
const event = await t.event(id, s.activeTurnId, "message.queued", { queuedMessageId, position, requestId: message.command.requestId }, message.writer);
|
|
335
|
+
const event = await t.event(id, s.activeTurnId, "message.queued", { queuedMessageId, position, requestId: message.command.requestId, delivery }, message.writer);
|
|
329
336
|
const started = takes ? await startQueuedTurn(ctx, t, s, id) : undefined;
|
|
330
337
|
if (started?.taken.includes(queuedMessageId))
|
|
331
338
|
return { status: "accepted", turnId: started.turnId, cursor: started.cursor };
|
|
332
|
-
return { status: "queued", queuedMessageId, position, cursor: event.cursor };
|
|
339
|
+
return { status: "queued", queuedMessageId, position, cursor: event.cursor, delivery };
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Takes the messages steered into session `s`'s running turn (D85), before step `step`: the
|
|
343
|
+
* `inputs` effect, in the transaction that journals it (`harness-api/record.ts`). Only `steer`
|
|
344
|
+
* rows whose turn request (variant, `removeTools`) is the running turn's join it; the rest wait
|
|
345
|
+
* for the turn's end. Writes each one's `command.message` under the turn, then one `queue.taken`
|
|
346
|
+
* with the step, adds their file artifacts to the session's, and returns their inputs (each as its
|
|
347
|
+
* message gave it, which the engine reads as a user message) in order. A workflow session takes
|
|
348
|
+
* none.
|
|
349
|
+
*/
|
|
350
|
+
export async function takeSteeredMessages(t, s, id, step) {
|
|
351
|
+
const turnId = s.activeTurnId;
|
|
352
|
+
if (turnId === null || isWorkflowManifest(s.manifest))
|
|
353
|
+
return [];
|
|
354
|
+
const running = s.turnRequest?.turnId === turnId ? s.turnRequest : undefined;
|
|
355
|
+
if (running?.manifest !== undefined)
|
|
356
|
+
return [];
|
|
357
|
+
const runningTools = canonical([...new Set(running?.removeTools ?? [])].sort());
|
|
358
|
+
const rows = (await t.queuedMessages(id)).filter((row) => {
|
|
359
|
+
if (row.delivery !== "steer")
|
|
360
|
+
return false;
|
|
361
|
+
const request = turnManifestRequestOf(row.command);
|
|
362
|
+
if (request?.manifest !== undefined)
|
|
363
|
+
return false;
|
|
364
|
+
return canonical([...(request?.removeTools ?? [])].sort()) === runningTools;
|
|
365
|
+
});
|
|
366
|
+
if (rows.length === 0)
|
|
367
|
+
return [];
|
|
368
|
+
const taken = rows.map((row) => row.id);
|
|
369
|
+
await t.deleteQueuedMessages(taken);
|
|
370
|
+
const named = rows.flatMap((row) => row.fileArtifacts);
|
|
371
|
+
if (named.length > 0)
|
|
372
|
+
s.fileArtifacts = [...new Set([...(s.fileArtifacts ?? []), ...named])];
|
|
373
|
+
for (const row of rows)
|
|
374
|
+
await t.event(id, turnId, "command.message", {
|
|
375
|
+
...row.command,
|
|
376
|
+
queuedMessageId: row.id,
|
|
377
|
+
...(row.trace ? { trace: row.trace } : {}),
|
|
378
|
+
...(row.cause ? { cause: row.cause } : {}),
|
|
379
|
+
}, row.writer);
|
|
380
|
+
await t.event(id, turnId, "queue.taken", { turnId, queuedMessageIds: taken, step });
|
|
381
|
+
return rows.map((row) => row.input);
|
|
333
382
|
}
|
|
334
383
|
/**
|
|
335
384
|
* Resolves a message for a turn, now or when it leaves the queue: file parts name artifacts the
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const RUNTIME_VERSION = "0.
|
|
1
|
+
export declare const RUNTIME_VERSION = "0.43.0-beta";
|
package/dist/version.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// Kept in step with package.json by runtime/server/scripts/check-package.mjs, which runs in npm run check.
|
|
2
2
|
// release:prepare also rewrites this when it bumps @nylorun/runtime.
|
|
3
|
-
export const RUNTIME_VERSION = "0.
|
|
3
|
+
export const RUNTIME_VERSION = "0.43.0-beta";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nylorun/runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.43.0-beta",
|
|
4
4
|
"description": "Nylorun Runtime: the agent execution Host on Postgres, Restate and S2, and model providers.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -65,8 +65,8 @@
|
|
|
65
65
|
"@hono/node-server": "^2.1.5",
|
|
66
66
|
"@hono/zod-openapi": "^1.6.3",
|
|
67
67
|
"@modelcontextprotocol/sdk": "^1.32.1",
|
|
68
|
-
"@nylorun/core": "0.
|
|
69
|
-
"@nylorun/harness": "0.
|
|
68
|
+
"@nylorun/core": "0.37.0-beta",
|
|
69
|
+
"@nylorun/harness": "0.34.0-beta",
|
|
70
70
|
"@restatedev/restate-sdk": "1.17.3",
|
|
71
71
|
"@restatedev/restate-sdk-clients": "1.17.3",
|
|
72
72
|
"@s2-dev/streamstore": "0.28.0",
|