@rynx-ai/daemon 0.1.11-beta.36 → 0.1.11-beta.38
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/db.js
CHANGED
|
@@ -100,6 +100,7 @@ function migrate(conn) {
|
|
|
100
100
|
status TEXT NOT NULL,
|
|
101
101
|
data TEXT NOT NULL,
|
|
102
102
|
created_by TEXT,
|
|
103
|
+
parent_tool_call_id TEXT,
|
|
103
104
|
created_at INTEGER NOT NULL,
|
|
104
105
|
UNIQUE(session_id, position)
|
|
105
106
|
);
|
|
@@ -370,6 +371,7 @@ function migrate(conn) {
|
|
|
370
371
|
addColumnIfMissing(conn, "session_message_operations", "response_id", "TEXT");
|
|
371
372
|
addColumnIfMissing(conn, "session_message_operations", "message_item_id", "TEXT");
|
|
372
373
|
addColumnIfMissing(conn, "session_message_operations", "execution_snapshot", "TEXT");
|
|
374
|
+
addColumnIfMissing(conn, "session_items", "parent_tool_call_id", "TEXT");
|
|
373
375
|
addColumnIfMissing(conn, "session_portal_tickets", "grant_handle", "TEXT");
|
|
374
376
|
addColumnIfMissing(conn, "session_portal_tickets", "embed_origin", "TEXT");
|
|
375
377
|
addColumnIfMissing(conn, "session_portal_grants", "grant_handle", "TEXT");
|
package/dist/plugin-host-rpc.js
CHANGED
|
@@ -558,6 +558,7 @@ export class PluginHostRpc {
|
|
|
558
558
|
return result;
|
|
559
559
|
}
|
|
560
560
|
async pumpRun(run, generator) {
|
|
561
|
+
let terminalCompleted = false;
|
|
561
562
|
let terminalFailure;
|
|
562
563
|
try {
|
|
563
564
|
for await (const event of generator) {
|
|
@@ -588,6 +589,10 @@ export class PluginHostRpc {
|
|
|
588
589
|
terminalFailure = sessionRunFailure(event);
|
|
589
590
|
if (terminalFailure)
|
|
590
591
|
break;
|
|
592
|
+
if (sessionRunCompleted(event)) {
|
|
593
|
+
terminalCompleted = true;
|
|
594
|
+
break;
|
|
595
|
+
}
|
|
591
596
|
}
|
|
592
597
|
if (!this.disposed &&
|
|
593
598
|
this.activeRuns.get(run.runId) === run &&
|
|
@@ -602,7 +607,7 @@ export class PluginHostRpc {
|
|
|
602
607
|
},
|
|
603
608
|
});
|
|
604
609
|
}
|
|
605
|
-
else {
|
|
610
|
+
else if (terminalCompleted) {
|
|
606
611
|
await this.emit({
|
|
607
612
|
event: "session.run.completed",
|
|
608
613
|
payload: {
|
|
@@ -614,6 +619,20 @@ export class PluginHostRpc {
|
|
|
614
619
|
},
|
|
615
620
|
});
|
|
616
621
|
}
|
|
622
|
+
else {
|
|
623
|
+
await this.emit({
|
|
624
|
+
event: "session.run.failed",
|
|
625
|
+
payload: {
|
|
626
|
+
runId: run.runId,
|
|
627
|
+
sessionId: run.sessionId,
|
|
628
|
+
error: {
|
|
629
|
+
code: "RUNTIME_EVENT_STREAM_ENDED",
|
|
630
|
+
message: "Runtime event stream ended before a terminal response event",
|
|
631
|
+
retryable: true,
|
|
632
|
+
},
|
|
633
|
+
},
|
|
634
|
+
});
|
|
635
|
+
}
|
|
617
636
|
}
|
|
618
637
|
}
|
|
619
638
|
catch (error) {
|
|
@@ -1509,6 +1528,13 @@ function sessionEventResponseId(event) {
|
|
|
1509
1528
|
}
|
|
1510
1529
|
function sessionRunFailure(event) {
|
|
1511
1530
|
const input = jsonRecord(event);
|
|
1531
|
+
if (input?.type === "session.interrupted") {
|
|
1532
|
+
return {
|
|
1533
|
+
code: "RUNTIME_TURN_INTERRUPTED",
|
|
1534
|
+
message: "Runtime Turn was interrupted",
|
|
1535
|
+
retryable: false,
|
|
1536
|
+
};
|
|
1537
|
+
}
|
|
1512
1538
|
if (input?.type !== "response.failed")
|
|
1513
1539
|
return undefined;
|
|
1514
1540
|
const error = jsonRecord(input.error);
|
|
@@ -1524,6 +1550,9 @@ function sessionRunFailure(event) {
|
|
|
1524
1550
|
retryable: false,
|
|
1525
1551
|
};
|
|
1526
1552
|
}
|
|
1553
|
+
function sessionRunCompleted(event) {
|
|
1554
|
+
return jsonRecord(event)?.type === "response.completed";
|
|
1555
|
+
}
|
|
1527
1556
|
function sessionHostEvent(run, event, delivery) {
|
|
1528
1557
|
return {
|
|
1529
1558
|
event: "session.run.event",
|
|
@@ -194,10 +194,10 @@ export class SqliteSessionForkStore {
|
|
|
194
194
|
}
|
|
195
195
|
const insertItem = conn.prepare(`INSERT INTO session_items (
|
|
196
196
|
id, session_id, position, response_id, type, status,
|
|
197
|
-
data, created_by, created_at
|
|
197
|
+
data, created_by, parent_tool_call_id, created_at
|
|
198
198
|
) VALUES (
|
|
199
199
|
@id, @session_id, @position, @response_id, @type, @status,
|
|
200
|
-
@data, @created_by, @created_at
|
|
200
|
+
@data, @created_by, @parent_tool_call_id, @created_at
|
|
201
201
|
)`);
|
|
202
202
|
for (const item of clonedItems) {
|
|
203
203
|
insertItem.run({
|
|
@@ -209,6 +209,7 @@ export class SqliteSessionForkStore {
|
|
|
209
209
|
status: item.status,
|
|
210
210
|
data: JSON.stringify(item.data),
|
|
211
211
|
created_by: item.createdBy ?? null,
|
|
212
|
+
parent_tool_call_id: item.parentToolCallId ?? null,
|
|
212
213
|
created_at: item.createdAt,
|
|
213
214
|
});
|
|
214
215
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { SessionLogAppendError } from "@rynx-ai/core";
|
|
1
2
|
import { db } from "./db.js";
|
|
2
|
-
import { transaction } from "./sqlite.js";
|
|
3
|
+
import { hasSqlitePrimaryCode, SQLITE_CONSTRAINT, transaction } from "./sqlite.js";
|
|
3
4
|
function toItem(row) {
|
|
4
5
|
return {
|
|
5
6
|
id: row.id,
|
|
@@ -9,6 +10,9 @@ function toItem(row) {
|
|
|
9
10
|
status: row.status,
|
|
10
11
|
createdAt: row.created_at,
|
|
11
12
|
...(row.created_by ? { createdBy: row.created_by } : {}),
|
|
13
|
+
...(row.parent_tool_call_id
|
|
14
|
+
? { parentToolCallId: row.parent_tool_call_id }
|
|
15
|
+
: {}),
|
|
12
16
|
type: row.type,
|
|
13
17
|
data: JSON.parse(row.data),
|
|
14
18
|
};
|
|
@@ -19,8 +23,10 @@ export class SqliteSessionLogStore {
|
|
|
19
23
|
return [];
|
|
20
24
|
const conn = db();
|
|
21
25
|
const insert = conn.prepare(`INSERT INTO session_items
|
|
22
|
-
(id, session_id, position, response_id, type, status, data, created_by,
|
|
23
|
-
|
|
26
|
+
(id, session_id, position, response_id, type, status, data, created_by,
|
|
27
|
+
parent_tool_call_id, created_at)
|
|
28
|
+
VALUES (@id, @session_id, @position, @response_id, @type, @status, @data,
|
|
29
|
+
@created_by, @parent_tool_call_id, @created_at)`);
|
|
24
30
|
const maxStmt = conn.prepare("SELECT MAX(position) AS max FROM session_items WHERE session_id = ?");
|
|
25
31
|
const tx = transaction(conn, (batch) => {
|
|
26
32
|
const { max } = maxStmt.get(sessionId);
|
|
@@ -36,6 +42,7 @@ export class SqliteSessionLogStore {
|
|
|
36
42
|
status: stored.status,
|
|
37
43
|
data: JSON.stringify(stored.data),
|
|
38
44
|
created_by: stored.createdBy ?? null,
|
|
45
|
+
parent_tool_call_id: stored.parentToolCallId ?? null,
|
|
39
46
|
created_at: stored.createdAt,
|
|
40
47
|
});
|
|
41
48
|
const resourceIds = stored.type === "message" && stored.data.role === "user"
|
|
@@ -54,10 +61,14 @@ export class SqliteSessionLogStore {
|
|
|
54
61
|
const resource = conn.prepare(`SELECT state, message_item_id
|
|
55
62
|
FROM session_resources
|
|
56
63
|
WHERE id = ? AND session_id = ?`).get(resourceId, sessionId);
|
|
57
|
-
if (!resource
|
|
58
|
-
resource
|
|
59
|
-
|
|
60
|
-
|
|
64
|
+
if (!resource) {
|
|
65
|
+
throw new SessionLogAppendError(`Session resource ${resourceId} does not exist`, 422, "session_resource_missing");
|
|
66
|
+
}
|
|
67
|
+
if (resource.state === "uploading") {
|
|
68
|
+
throw new SessionLogAppendError(`Session resource ${resourceId} is still uploading`, 409, "session_resource_not_ready");
|
|
69
|
+
}
|
|
70
|
+
if (resource.message_item_id && resource.message_item_id !== stored.id) {
|
|
71
|
+
throw new SessionLogAppendError(`Session resource ${resourceId} is already committed to another item`, 422, "session_resource_already_committed");
|
|
61
72
|
}
|
|
62
73
|
conn.prepare(`UPDATE session_resources
|
|
63
74
|
SET state = 'committed', message_item_id = ?,
|
|
@@ -68,7 +79,17 @@ export class SqliteSessionLogStore {
|
|
|
68
79
|
return stored;
|
|
69
80
|
});
|
|
70
81
|
});
|
|
71
|
-
|
|
82
|
+
try {
|
|
83
|
+
return tx(items);
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
if (error instanceof SessionLogAppendError)
|
|
87
|
+
throw error;
|
|
88
|
+
if (hasSqlitePrimaryCode(error, SQLITE_CONSTRAINT)) {
|
|
89
|
+
throw new SessionLogAppendError(error instanceof Error ? error.message : "Session log constraint rejected the item", 422, "session_log_constraint", { cause: error });
|
|
90
|
+
}
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
72
93
|
}
|
|
73
94
|
async list(sessionId, opts = {}) {
|
|
74
95
|
const conn = db();
|
|
@@ -1008,7 +1008,7 @@ function invalid(message) {
|
|
|
1008
1008
|
return new MachineSessionServiceFailure("failed_precondition", message);
|
|
1009
1009
|
}
|
|
1010
1010
|
function unavailable(message) {
|
|
1011
|
-
return new MachineSessionServiceFailure("failed_precondition", message);
|
|
1011
|
+
return new MachineSessionServiceFailure("failed_precondition", message, undefined, undefined, true);
|
|
1012
1012
|
}
|
|
1013
1013
|
function conflict(message) {
|
|
1014
1014
|
return new MachineSessionServiceFailure("conflict", message);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rynx-ai/daemon",
|
|
3
|
-
"version": "0.1.11-beta.
|
|
3
|
+
"version": "0.1.11-beta.38",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/rynx-ai/rynx.git",
|
|
@@ -51,17 +51,17 @@
|
|
|
51
51
|
"tar": "^7.5.19",
|
|
52
52
|
"undici": "^7.28.0",
|
|
53
53
|
"ws": "^8.21.0",
|
|
54
|
-
"@rynx-ai/core": "0.1.11-beta.
|
|
55
|
-
"@rynx-ai/emulator": "0.1.11-beta.
|
|
56
|
-
"@rynx-ai/plugin-
|
|
57
|
-
"@rynx-ai/plugin-
|
|
58
|
-
"@rynx-ai/protocol": "0.1.11-beta.
|
|
59
|
-
"@rynx-ai/remote-runtime-client": "0.1.11-beta.
|
|
60
|
-
"@rynx-ai/server": "0.1.11-beta.
|
|
54
|
+
"@rynx-ai/core": "0.1.11-beta.38",
|
|
55
|
+
"@rynx-ai/emulator": "0.1.11-beta.38",
|
|
56
|
+
"@rynx-ai/plugin-runner": "0.1.11-beta.38",
|
|
57
|
+
"@rynx-ai/plugin-sdk": "0.1.11-beta.38",
|
|
58
|
+
"@rynx-ai/protocol": "0.1.11-beta.38",
|
|
59
|
+
"@rynx-ai/remote-runtime-client": "0.1.11-beta.38",
|
|
60
|
+
"@rynx-ai/server": "0.1.11-beta.38"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"@types/ws": "^8.18.1",
|
|
64
|
-
"@rynx-ai/plugin-channel-lark": "0.1.11-beta.
|
|
64
|
+
"@rynx-ai/plugin-channel-lark": "0.1.11-beta.38"
|
|
65
65
|
},
|
|
66
66
|
"scripts": {
|
|
67
67
|
"build": "rm -rf dist bundled-plugins && tsc -p tsconfig.json && chmod +x dist/index-daemon.js && node ../../scripts/stage-bundled-plugins.mjs",
|