@rynx-ai/daemon 0.1.0 → 0.1.10-beta.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/dist/app-browser-host-supervisor.d.ts +97 -0
- package/dist/app-browser-host-supervisor.js +529 -0
- package/dist/browser-artifact-management.d.ts +20 -0
- package/dist/browser-artifact-management.js +61 -0
- package/dist/browser-cli-args.d.ts +20 -0
- package/dist/browser-cli-args.js +100 -0
- package/dist/browser-runner-session-context.d.ts +24 -0
- package/dist/browser-runner-session-context.js +113 -0
- package/dist/cdp-keyboard-input.d.ts +6 -0
- package/dist/cdp-keyboard-input.js +209 -0
- package/dist/channel-store.d.ts +0 -6
- package/dist/channel-store.js +2 -18
- package/dist/chrome-for-testing-release-resolver.d.ts +34 -0
- package/dist/chrome-for-testing-release-resolver.js +214 -0
- package/dist/chrome-for-testing-store.d.ts +85 -0
- package/dist/chrome-for-testing-store.js +836 -0
- package/dist/chrome-inspection-gateway.d.ts +58 -0
- package/dist/chrome-inspection-gateway.js +806 -0
- package/dist/chrome-inspection-manager.d.ts +94 -0
- package/dist/chrome-inspection-manager.js +573 -0
- package/dist/cli.js +478 -30
- package/dist/control-client.d.ts +122 -0
- package/dist/control-client.js +855 -0
- package/dist/control-deps.js +37 -6
- package/dist/control-endpoint.d.ts +14 -0
- package/dist/control-endpoint.js +124 -0
- package/dist/control-link-store.d.ts +16 -0
- package/dist/control-link-store.js +53 -0
- package/dist/daemon-build-status.d.ts +8 -0
- package/dist/daemon-build-status.js +18 -0
- package/dist/daemon-owner.d.ts +14 -0
- package/dist/daemon-owner.js +104 -0
- package/dist/daemon-server.d.ts +29 -2
- package/dist/daemon-server.js +1113 -26
- package/dist/db.js +196 -10
- package/dist/desktop-browser-host-client.d.ts +35 -0
- package/dist/desktop-browser-host-client.js +415 -0
- package/dist/direct-runtime-authenticator.d.ts +13 -0
- package/dist/direct-runtime-authenticator.js +132 -0
- package/dist/direct-runtime-config.d.ts +20 -0
- package/dist/direct-runtime-config.js +101 -0
- package/dist/embedded-browser-profile-cleanup.d.ts +58 -0
- package/dist/embedded-browser-profile-cleanup.js +338 -0
- package/dist/headless-browser-host.d.ts +14 -0
- package/dist/headless-browser-host.js +2173 -0
- package/dist/index-daemon.js +55 -5
- package/dist/installation-id.d.ts +33 -0
- package/dist/installation-id.js +692 -0
- package/dist/maintenance-management.d.ts +11 -0
- package/dist/maintenance-management.js +13 -0
- package/dist/migrations/cleanup-legacy-sessions.d.ts +0 -3
- package/dist/migrations/cleanup-legacy-sessions.js +10 -28
- package/dist/plugin-cli.d.ts +30 -0
- package/dist/plugin-cli.js +270 -0
- package/dist/plugin-host-rpc.d.ts +85 -0
- package/dist/plugin-host-rpc.js +878 -0
- package/dist/plugin-install-restart.d.ts +13 -0
- package/dist/plugin-install-restart.js +24 -0
- package/dist/plugin-installer.d.ts +71 -15
- package/dist/plugin-installer.js +521 -155
- package/dist/plugin-management-service.d.ts +58 -0
- package/dist/plugin-management-service.js +240 -0
- package/dist/plugin-package.d.ts +61 -0
- package/dist/plugin-package.js +732 -0
- package/dist/plugin-runtime-control.d.ts +2 -0
- package/dist/plugin-runtime-control.js +37 -0
- package/dist/plugin-store.d.ts +37 -8
- package/dist/plugin-store.js +80 -15
- package/dist/plugin-supervisor.d.ts +160 -0
- package/dist/plugin-supervisor.js +1143 -0
- package/dist/pm2.d.ts +3 -1
- package/dist/pm2.js +92 -18
- package/dist/provider-cli-service.d.ts +46 -0
- package/dist/provider-cli-service.js +510 -0
- package/dist/registry.d.ts +6 -19
- package/dist/registry.js +22 -87
- package/dist/remote-runtime-access-store.d.ts +62 -0
- package/dist/remote-runtime-access-store.js +393 -0
- package/dist/remote-runtime-admin.d.ts +35 -0
- package/dist/remote-runtime-admin.js +110 -0
- package/dist/remote-runtime-connection-manager.d.ts +103 -0
- package/dist/remote-runtime-connection-manager.js +1575 -0
- package/dist/remote-runtime-credential-store.d.ts +45 -0
- package/dist/remote-runtime-credential-store.js +639 -0
- package/dist/remote-runtime-target-control.d.ts +51 -0
- package/dist/remote-runtime-target-control.js +488 -0
- package/dist/remote-runtime-target-store.d.ts +56 -0
- package/dist/remote-runtime-target-store.js +326 -0
- package/dist/runtime-share-addresses.d.ts +21 -0
- package/dist/runtime-share-addresses.js +50 -0
- package/dist/session-browser-capability-store.d.ts +13 -0
- package/dist/session-browser-capability-store.js +58 -0
- package/dist/session-emulator-binding-store.d.ts +10 -0
- package/dist/session-emulator-binding-store.js +61 -0
- package/dist/session-launch-operations.d.ts +41 -0
- package/dist/session-launch-operations.js +124 -0
- package/dist/session-log-store.js +29 -0
- package/dist/session-meta-store.d.ts +3 -2
- package/dist/session-meta-store.js +59 -7
- package/dist/session-pending-message-store.d.ts +2 -0
- package/dist/session-pending-message-store.js +41 -0
- package/dist/session-resource-store.d.ts +32 -0
- package/dist/session-resource-store.js +700 -0
- package/dist/setup.d.ts +16 -0
- package/dist/setup.js +144 -5
- package/dist/skills-catalog.js +8 -4
- package/dist/update.d.ts +11 -2
- package/dist/update.js +0 -27
- package/package.json +23 -10
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { newSessionId } from "@rynx-ai/core";
|
|
2
|
+
import { db } from "./db.js";
|
|
3
|
+
import { createSessionMeta } from "./session-meta-store.js";
|
|
4
|
+
const MAX_ID_LENGTH = 512;
|
|
5
|
+
const SHA256_PATTERN = /^[a-fA-F0-9]{64}$/;
|
|
6
|
+
export class SessionLaunchOperationConflictError extends Error {
|
|
7
|
+
pluginId;
|
|
8
|
+
scopeId;
|
|
9
|
+
operationId;
|
|
10
|
+
code = "SESSION_LAUNCH_OPERATION_CONFLICT";
|
|
11
|
+
constructor(pluginId, scopeId, operationId) {
|
|
12
|
+
super(`session launch operation was reused with a different request: ${pluginId}/${scopeId}/${operationId}`);
|
|
13
|
+
this.pluginId = pluginId;
|
|
14
|
+
this.scopeId = scopeId;
|
|
15
|
+
this.operationId = operationId;
|
|
16
|
+
this.name = "SessionLaunchOperationConflictError";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export class SessionLaunchOperationTargetDeletedError extends Error {
|
|
20
|
+
pluginId;
|
|
21
|
+
scopeId;
|
|
22
|
+
operationId;
|
|
23
|
+
sessionId;
|
|
24
|
+
code = "SESSION_LAUNCH_OPERATION_TARGET_DELETED";
|
|
25
|
+
constructor(pluginId, scopeId, operationId, sessionId) {
|
|
26
|
+
super(`session launch operation target was deleted: ${pluginId}/${scopeId}/${operationId}`);
|
|
27
|
+
this.pluginId = pluginId;
|
|
28
|
+
this.scopeId = scopeId;
|
|
29
|
+
this.operationId = operationId;
|
|
30
|
+
this.sessionId = sessionId;
|
|
31
|
+
this.name = "SessionLaunchOperationTargetDeletedError";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Atomically allocate a persisted machine session for one plugin operation.
|
|
36
|
+
*
|
|
37
|
+
* The durable operation row is the idempotency boundary across runner crashes,
|
|
38
|
+
* daemon restarts, and remote lease re-delivery. It deliberately excludes any
|
|
39
|
+
* Workspace concept: `scopeId` and `operationId` are opaque to the daemon.
|
|
40
|
+
*/
|
|
41
|
+
export function ensurePluginSessionLaunch(input) {
|
|
42
|
+
const pluginId = requiredId(input.pluginId, "pluginId");
|
|
43
|
+
const scopeId = requiredId(input.scopeId, "scopeId");
|
|
44
|
+
const operationId = requiredId(input.operationId, "operationId");
|
|
45
|
+
const requestHash = requiredRequestHash(input.requestHash);
|
|
46
|
+
const ensure = db().transaction(() => {
|
|
47
|
+
const existing = readOperation(pluginId, scopeId, operationId);
|
|
48
|
+
if (existing) {
|
|
49
|
+
if (existing.request_hash !== requestHash) {
|
|
50
|
+
throw new SessionLaunchOperationConflictError(pluginId, scopeId, operationId);
|
|
51
|
+
}
|
|
52
|
+
if (existing.state === "deleted") {
|
|
53
|
+
return { disposition: "deleted", sessionId: existing.session_id };
|
|
54
|
+
}
|
|
55
|
+
if (!sessionExists(existing.session_id)) {
|
|
56
|
+
// Preserve the operation key even when an older deletion path removed
|
|
57
|
+
// the session without first marking its launch operation. Throwing from
|
|
58
|
+
// inside this transaction would roll the repair back, so return a
|
|
59
|
+
// sentinel and raise the typed error after the commit.
|
|
60
|
+
tombstoneOperations(existing.session_id, new Date().toISOString());
|
|
61
|
+
return { disposition: "deleted", sessionId: existing.session_id };
|
|
62
|
+
}
|
|
63
|
+
return { disposition: "replayed", sessionId: existing.session_id };
|
|
64
|
+
}
|
|
65
|
+
const now = new Date().toISOString();
|
|
66
|
+
let sessionId = newSessionId();
|
|
67
|
+
while (sessionExists(sessionId))
|
|
68
|
+
sessionId = newSessionId();
|
|
69
|
+
createSessionMeta({
|
|
70
|
+
...input.session,
|
|
71
|
+
id: sessionId,
|
|
72
|
+
source: `plugin:${pluginId}`,
|
|
73
|
+
createdAt: now,
|
|
74
|
+
updatedAt: now,
|
|
75
|
+
});
|
|
76
|
+
if (!sessionExists(sessionId)) {
|
|
77
|
+
throw new Error(`plugin session launch failed to persist session metadata: ${sessionId}`);
|
|
78
|
+
}
|
|
79
|
+
db()
|
|
80
|
+
.prepare(`INSERT INTO plugin_session_launch_operations
|
|
81
|
+
(plugin_id, scope_id, operation_id, request_hash, session_id, state,
|
|
82
|
+
created_at, updated_at, deleted_at)
|
|
83
|
+
VALUES (?, ?, ?, ?, ?, 'active', ?, ?, NULL)`)
|
|
84
|
+
.run(pluginId, scopeId, operationId, requestHash, sessionId, now, now);
|
|
85
|
+
return { disposition: "created", sessionId };
|
|
86
|
+
});
|
|
87
|
+
const result = ensure.immediate();
|
|
88
|
+
if (result.disposition === "deleted") {
|
|
89
|
+
throw new SessionLaunchOperationTargetDeletedError(pluginId, scopeId, operationId, result.sessionId);
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
function readOperation(pluginId, scopeId, operationId) {
|
|
94
|
+
return db()
|
|
95
|
+
.prepare(`SELECT request_hash, session_id, state
|
|
96
|
+
FROM plugin_session_launch_operations
|
|
97
|
+
WHERE plugin_id = ? AND scope_id = ? AND operation_id = ?`)
|
|
98
|
+
.get(pluginId, scopeId, operationId);
|
|
99
|
+
}
|
|
100
|
+
function sessionExists(sessionId) {
|
|
101
|
+
return Boolean(db().prepare("SELECT 1 FROM sessions WHERE id = ?").pluck().get(sessionId));
|
|
102
|
+
}
|
|
103
|
+
function tombstoneOperations(sessionId, now) {
|
|
104
|
+
return db()
|
|
105
|
+
.prepare(`UPDATE plugin_session_launch_operations
|
|
106
|
+
SET state = 'deleted', updated_at = ?, deleted_at = ?
|
|
107
|
+
WHERE session_id = ? AND state = 'active'`)
|
|
108
|
+
.run(now, now, sessionId).changes;
|
|
109
|
+
}
|
|
110
|
+
function requiredId(value, label) {
|
|
111
|
+
const normalized = value?.trim();
|
|
112
|
+
if (!normalized)
|
|
113
|
+
throw new Error(`${label} is required`);
|
|
114
|
+
if (normalized.length > MAX_ID_LENGTH)
|
|
115
|
+
throw new Error(`${label} is too long`);
|
|
116
|
+
return normalized;
|
|
117
|
+
}
|
|
118
|
+
function requiredRequestHash(value) {
|
|
119
|
+
const normalized = value?.trim();
|
|
120
|
+
if (!SHA256_PATTERN.test(normalized)) {
|
|
121
|
+
throw new Error("requestHash must be a SHA-256 hex digest");
|
|
122
|
+
}
|
|
123
|
+
return normalized.toLowerCase();
|
|
124
|
+
}
|
|
@@ -37,6 +37,35 @@ export class SqliteSessionLogStore {
|
|
|
37
37
|
created_by: stored.createdBy ?? null,
|
|
38
38
|
created_at: stored.createdAt,
|
|
39
39
|
});
|
|
40
|
+
if (stored.type === "message" && stored.data.role === "user") {
|
|
41
|
+
const resourceIds = stored.data.content.flatMap((part) => part.type === "input_image" ? [part.resourceId] : []);
|
|
42
|
+
const operationIds = new Set();
|
|
43
|
+
for (const resourceId of resourceIds) {
|
|
44
|
+
const resource = conn.prepare(`SELECT state, message_item_id
|
|
45
|
+
FROM session_resources
|
|
46
|
+
WHERE id = ? AND session_id = ?`).get(resourceId, sessionId);
|
|
47
|
+
if (!resource ||
|
|
48
|
+
resource.state === "uploading" ||
|
|
49
|
+
(resource.message_item_id && resource.message_item_id !== stored.id)) {
|
|
50
|
+
throw new Error(`Session image resource ${resourceId} is not committable`);
|
|
51
|
+
}
|
|
52
|
+
conn.prepare(`UPDATE session_resources
|
|
53
|
+
SET state = 'committed', message_item_id = ?,
|
|
54
|
+
committed_at = COALESCE(committed_at, ?)
|
|
55
|
+
WHERE id = ? AND session_id = ?`).run(stored.id, stored.createdAt, resourceId, sessionId);
|
|
56
|
+
const operation = conn.prepare(`SELECT client_message_id
|
|
57
|
+
FROM session_message_operation_resources
|
|
58
|
+
WHERE session_id = ? AND resource_id = ?`).get(sessionId, resourceId);
|
|
59
|
+
if (operation)
|
|
60
|
+
operationIds.add(operation.client_message_id);
|
|
61
|
+
}
|
|
62
|
+
for (const clientMessageId of operationIds) {
|
|
63
|
+
conn.prepare(`UPDATE session_message_operations
|
|
64
|
+
SET state = 'mirrored', error = NULL, updated_at = ?
|
|
65
|
+
WHERE session_id = ? AND client_message_id = ?
|
|
66
|
+
AND state IN ('injecting', 'injected', 'outcome_unknown')`).run(stored.createdAt, sessionId, clientMessageId);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
40
69
|
return stored;
|
|
41
70
|
});
|
|
42
71
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The unified machine-session record (SQLite) — one row per session regardless
|
|
3
3
|
* of origin (the web console AND every channel). Holds identity/meta (source /
|
|
4
|
-
* agent / inline config / model / title / …) so the **session list survives a
|
|
4
|
+
* provider / agent / inline config / model / title / …) so the **session list survives a
|
|
5
5
|
* daemon restart**; the transcript lives in `session_items` (see
|
|
6
6
|
* {@link import("./session-log-store.js")}). Runtime `status` is intentionally
|
|
7
7
|
* not stored — it is reconstructed as `idle` after a restart.
|
|
@@ -11,12 +11,13 @@
|
|
|
11
11
|
* via the `ChannelContext`, so a channel registers its sessions the same way the
|
|
12
12
|
* console does.
|
|
13
13
|
*/
|
|
14
|
-
import type
|
|
14
|
+
import { type MachineSessionRecord, type SessionRegistry } from "@rynx-ai/core";
|
|
15
15
|
/** Back-compat alias for the unified record. */
|
|
16
16
|
export type StoredSessionMeta = MachineSessionRecord;
|
|
17
17
|
export declare function listSessionMetas(): StoredSessionMeta[];
|
|
18
18
|
export declare function getSessionMeta(id: string): StoredSessionMeta | undefined;
|
|
19
19
|
export declare function createSessionMeta(meta: StoredSessionMeta): void;
|
|
20
|
+
export declare function updateSessionMeta(meta: StoredSessionMeta): void;
|
|
20
21
|
export declare function setSessionTitle(id: string, title: string): void;
|
|
21
22
|
export declare function removeSessionMeta(id: string): void;
|
|
22
23
|
/** {@link SessionRegistry} over the same `sessions` table — the form channels
|
|
@@ -1,5 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The unified machine-session record (SQLite) — one row per session regardless
|
|
3
|
+
* of origin (the web console AND every channel). Holds identity/meta (source /
|
|
4
|
+
* provider / agent / inline config / model / title / …) so the **session list survives a
|
|
5
|
+
* daemon restart**; the transcript lives in `session_items` (see
|
|
6
|
+
* {@link import("./session-log-store.js")}). Runtime `status` is intentionally
|
|
7
|
+
* not stored — it is reconstructed as `idle` after a restart.
|
|
8
|
+
*
|
|
9
|
+
* Exposes both the standalone functions the control-plane deps wire in and a
|
|
10
|
+
* {@link SessionRegistry} adapter ({@link sessionRegistry}) injected into channels
|
|
11
|
+
* via the `ChannelContext`, so a channel registers its sessions the same way the
|
|
12
|
+
* console does.
|
|
13
|
+
*/
|
|
14
|
+
import { normalizeSessionTitle, } from "@rynx-ai/core";
|
|
1
15
|
import { db } from "./db.js";
|
|
2
|
-
const COLS = "id, agent, config, model, reasoning_effort, title, source, created_at, updated_at";
|
|
16
|
+
const COLS = "id, provider, agent, config, model, reasoning_effort, title, source, created_at, updated_at";
|
|
3
17
|
export function listSessionMetas() {
|
|
4
18
|
return db()
|
|
5
19
|
.prepare(`SELECT ${COLS} FROM sessions ORDER BY created_at`)
|
|
@@ -13,27 +27,60 @@ export function getSessionMeta(id) {
|
|
|
13
27
|
export function createSessionMeta(meta) {
|
|
14
28
|
db()
|
|
15
29
|
.prepare(`INSERT OR IGNORE INTO sessions
|
|
16
|
-
(id, agent, config, model, reasoning_effort, title, source, created_at, updated_at)
|
|
17
|
-
VALUES (@id, @agent, @config, @model, @reasoning_effort, @title, @source, @created_at, @updated_at)`)
|
|
30
|
+
(id, provider, agent, config, model, reasoning_effort, title, source, created_at, updated_at)
|
|
31
|
+
VALUES (@id, @provider, @agent, @config, @model, @reasoning_effort, @title, @source, @created_at, @updated_at)`)
|
|
18
32
|
.run({
|
|
19
33
|
id: meta.id,
|
|
34
|
+
provider: meta.provider ?? null,
|
|
20
35
|
agent: meta.agent ?? null,
|
|
21
36
|
config: meta.config ? JSON.stringify(meta.config) : null,
|
|
22
37
|
model: meta.model ?? null,
|
|
23
38
|
reasoning_effort: meta.reasoningEffort ?? null,
|
|
24
|
-
title: meta.title ?? null,
|
|
39
|
+
title: normalizeSessionTitle(meta.title) ?? null,
|
|
25
40
|
source: meta.source,
|
|
26
41
|
created_at: meta.createdAt,
|
|
27
42
|
updated_at: meta.updatedAt ?? meta.createdAt,
|
|
28
43
|
});
|
|
29
44
|
}
|
|
45
|
+
export function updateSessionMeta(meta) {
|
|
46
|
+
db()
|
|
47
|
+
.prepare(`UPDATE sessions
|
|
48
|
+
SET provider = @provider,
|
|
49
|
+
agent = @agent,
|
|
50
|
+
config = @config,
|
|
51
|
+
model = @model,
|
|
52
|
+
reasoning_effort = @reasoning_effort,
|
|
53
|
+
title = @title,
|
|
54
|
+
source = @source,
|
|
55
|
+
updated_at = @updated_at
|
|
56
|
+
WHERE id = @id`)
|
|
57
|
+
.run({
|
|
58
|
+
id: meta.id,
|
|
59
|
+
provider: meta.provider ?? null,
|
|
60
|
+
agent: meta.agent ?? null,
|
|
61
|
+
config: meta.config ? JSON.stringify(meta.config) : null,
|
|
62
|
+
model: meta.model ?? null,
|
|
63
|
+
reasoning_effort: meta.reasoningEffort ?? null,
|
|
64
|
+
title: normalizeSessionTitle(meta.title) ?? null,
|
|
65
|
+
source: meta.source,
|
|
66
|
+
updated_at: meta.updatedAt ?? new Date().toISOString(),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
30
69
|
export function setSessionTitle(id, title) {
|
|
31
70
|
db()
|
|
32
71
|
.prepare("UPDATE sessions SET title = ?, updated_at = ? WHERE id = ?")
|
|
33
|
-
.run(title, new Date().toISOString(), id);
|
|
72
|
+
.run(normalizeSessionTitle(title), new Date().toISOString(), id);
|
|
34
73
|
}
|
|
35
74
|
export function removeSessionMeta(id) {
|
|
36
|
-
db().
|
|
75
|
+
db().transaction(() => {
|
|
76
|
+
const now = new Date().toISOString();
|
|
77
|
+
db()
|
|
78
|
+
.prepare(`UPDATE plugin_session_launch_operations
|
|
79
|
+
SET state = 'deleted', updated_at = ?, deleted_at = ?
|
|
80
|
+
WHERE session_id = ? AND state = 'active'`)
|
|
81
|
+
.run(now, now, id);
|
|
82
|
+
db().prepare("DELETE FROM sessions WHERE id = ?").run(id);
|
|
83
|
+
}).immediate();
|
|
37
84
|
}
|
|
38
85
|
/** {@link SessionRegistry} over the same `sessions` table — the form channels
|
|
39
86
|
* receive through their `ChannelContext`. */
|
|
@@ -47,11 +94,16 @@ export const sessionRegistry = {
|
|
|
47
94
|
function rowToMeta(row) {
|
|
48
95
|
return {
|
|
49
96
|
id: row.id,
|
|
97
|
+
provider: row.provider === "codex" || row.provider === "traex" || row.provider === "claude"
|
|
98
|
+
? row.provider
|
|
99
|
+
: undefined,
|
|
50
100
|
agent: row.agent ?? undefined,
|
|
51
101
|
config: row.config ? JSON.parse(row.config) : undefined,
|
|
52
102
|
model: row.model ?? undefined,
|
|
53
103
|
reasoningEffort: (row.reasoning_effort ?? undefined),
|
|
54
|
-
|
|
104
|
+
// Normalize on read as well so pre-boundary database rows cannot poison an
|
|
105
|
+
// entire Remote Session list page after upgrading the daemon.
|
|
106
|
+
title: normalizeSessionTitle(row.title ?? undefined),
|
|
55
107
|
source: row.source ?? "console",
|
|
56
108
|
createdAt: row.created_at,
|
|
57
109
|
updatedAt: row.updated_at ?? row.created_at,
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { db } from "./db.js";
|
|
2
|
+
export const sessionPendingMessageStore = {
|
|
3
|
+
put(message) {
|
|
4
|
+
const result = db()
|
|
5
|
+
.prepare(`INSERT OR IGNORE INTO session_pending_messages
|
|
6
|
+
(session_id, message, state, created_at)
|
|
7
|
+
VALUES (?, ?, 'queued', ?)`)
|
|
8
|
+
.run(message.sessionId, message.message, message.createdAt);
|
|
9
|
+
return result.changes === 1;
|
|
10
|
+
},
|
|
11
|
+
get(sessionId) {
|
|
12
|
+
const row = db()
|
|
13
|
+
.prepare(`SELECT session_id, message, state, created_at
|
|
14
|
+
FROM session_pending_messages WHERE session_id = ?`)
|
|
15
|
+
.get(sessionId);
|
|
16
|
+
return row ? fromRow(row) : undefined;
|
|
17
|
+
},
|
|
18
|
+
list() {
|
|
19
|
+
return db()
|
|
20
|
+
.prepare(`SELECT session_id, message, state, created_at
|
|
21
|
+
FROM session_pending_messages ORDER BY created_at`)
|
|
22
|
+
.all().map(fromRow);
|
|
23
|
+
},
|
|
24
|
+
markOutcomeUnknown(sessionId) {
|
|
25
|
+
db()
|
|
26
|
+
.prepare(`UPDATE session_pending_messages SET state = 'outcome_unknown'
|
|
27
|
+
WHERE session_id = ? AND state = 'queued'`)
|
|
28
|
+
.run(sessionId);
|
|
29
|
+
},
|
|
30
|
+
delete(sessionId) {
|
|
31
|
+
db().prepare("DELETE FROM session_pending_messages WHERE session_id = ?").run(sessionId);
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
function fromRow(row) {
|
|
35
|
+
return {
|
|
36
|
+
sessionId: row.session_id,
|
|
37
|
+
message: row.message,
|
|
38
|
+
state: row.state,
|
|
39
|
+
createdAt: row.created_at,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type UserContentPart } from "@rynx-ai/core";
|
|
2
|
+
import { type RemoteRuntimeSessionResourceDeleteParams, type RemoteRuntimeSessionResourceDeleteResult, type RemoteRuntimeSessionResourceGetParams, type RemoteRuntimeSessionResourceGetResult, type RemoteRuntimeSessionResourcePolicyResult, type RemoteRuntimeSessionResourceReadParams, type RemoteRuntimeSessionResourceReadResult, type RemoteRuntimeSessionResourceUploadBeginParams, type RemoteRuntimeSessionResourceUploadBeginResult, type RemoteRuntimeSessionResourceUploadChunkParams, type RemoteRuntimeSessionResourceUploadChunkResult, type RemoteRuntimeSessionResourceUploadCommitParams, type RemoteRuntimeSessionResourceUploadCommitResult } from "@rynx-ai/protocol/remote-runtime-rpc";
|
|
3
|
+
import { type MachineSessionPreparedInput, type MachineSessionResourcePort } from "@rynx-ai/server";
|
|
4
|
+
export declare class SqliteSessionResourceStore implements MachineSessionResourcePort {
|
|
5
|
+
private readonly root;
|
|
6
|
+
constructor(root?: string);
|
|
7
|
+
policy(_sessionId: string): RemoteRuntimeSessionResourcePolicyResult;
|
|
8
|
+
beginUpload(input: RemoteRuntimeSessionResourceUploadBeginParams): Promise<RemoteRuntimeSessionResourceUploadBeginResult>;
|
|
9
|
+
writeUploadChunk(input: RemoteRuntimeSessionResourceUploadChunkParams): Promise<RemoteRuntimeSessionResourceUploadChunkResult>;
|
|
10
|
+
commitUpload(input: RemoteRuntimeSessionResourceUploadCommitParams): Promise<RemoteRuntimeSessionResourceUploadCommitResult>;
|
|
11
|
+
getResource(input: RemoteRuntimeSessionResourceGetParams): Promise<RemoteRuntimeSessionResourceGetResult>;
|
|
12
|
+
readResource(input: RemoteRuntimeSessionResourceReadParams): Promise<RemoteRuntimeSessionResourceReadResult>;
|
|
13
|
+
deleteResource(input: RemoteRuntimeSessionResourceDeleteParams): Promise<RemoteRuntimeSessionResourceDeleteResult>;
|
|
14
|
+
prepareInput(sessionId: string, content: UserContentPart[], clientMessageId?: string): Promise<MachineSessionPreparedInput>;
|
|
15
|
+
markMessageInjecting(sessionId: string, clientMessageId: string): void;
|
|
16
|
+
markMessageInjected(sessionId: string, clientMessageId: string): void;
|
|
17
|
+
markMessageOutcomeUnknown(sessionId: string, clientMessageId: string, reason: string): void;
|
|
18
|
+
markMessageFailedNotStarted(sessionId: string, clientMessageId: string, reason: string): void;
|
|
19
|
+
deleteSession(sessionId: string): void;
|
|
20
|
+
private prepareMessageOperation;
|
|
21
|
+
private bindOperationResources;
|
|
22
|
+
private transitionOperation;
|
|
23
|
+
private finalizeUpload;
|
|
24
|
+
private reconcileUploadOffset;
|
|
25
|
+
private rowByUpload;
|
|
26
|
+
private requireUpload;
|
|
27
|
+
private requireResource;
|
|
28
|
+
private sessionDirectory;
|
|
29
|
+
private partialPath;
|
|
30
|
+
private finalPath;
|
|
31
|
+
private sweepExpiredStagedResources;
|
|
32
|
+
}
|