@rynx-ai/daemon 0.1.11-beta.3 → 0.1.11-beta.30
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/bundled-plugins/plugins/lark/.rynx-plugin/plugin.json +0 -12
- package/bundled-plugins/plugins/lark/dist/cli-mirror/mirror-index.js +3 -1
- package/bundled-plugins/plugins/lark/dist/host-adapters.d.ts +3 -3
- package/bundled-plugins/plugins/lark/dist/host-adapters.js +24 -18
- package/bundled-plugins/plugins/lark/dist/lark.js +18 -12
- package/bundled-plugins/plugins/lark/dist/runtime.js +6046 -6018
- package/bundled-plugins/plugins/lark/dist/settings.js +6006 -5987
- package/bundled-plugins/plugins/lark/package.json +1 -1
- package/bundled-plugins/plugins/lark/ui/assets/index-CGUVAMsv.css +1 -0
- package/bundled-plugins/plugins/lark/ui/index.html +2 -2
- package/dist/agent-file.js +0 -1
- package/dist/browser-artifact-management.js +4 -1
- package/dist/chrome-for-testing-runtime.js +4 -3
- package/dist/chrome-for-testing-store.js +29 -7
- package/dist/control-deps.d.ts +6 -2
- package/dist/control-deps.js +87 -4
- package/dist/control-link-store.js +4 -3
- package/dist/daemon-owner.js +4 -7
- package/dist/daemon-server.js +25 -14
- package/dist/db.d.ts +2 -2
- package/dist/db.js +133 -21
- package/dist/lifecycle.d.ts +1 -0
- package/dist/lifecycle.js +3 -0
- package/dist/migrations/cleanup-legacy-sessions.js +4 -3
- package/dist/plugin-cli.d.ts +10 -0
- package/dist/plugin-cli.js +19 -2
- package/dist/plugin-host-rpc.d.ts +31 -9
- package/dist/plugin-host-rpc.js +428 -80
- package/dist/plugin-installer.js +3 -2
- package/dist/plugin-management-service.js +0 -2
- package/dist/plugin-marketplace.js +2 -1
- package/dist/plugin-store.js +2 -4
- package/dist/plugin-supervisor.js +0 -4
- package/dist/remote-runtime-access-store.d.ts +2 -2
- package/dist/remote-runtime-access-store.js +6 -9
- package/dist/remote-runtime-connection-manager.js +1 -1
- package/dist/remote-runtime-target-store.d.ts +2 -2
- package/dist/remote-runtime-target-store.js +6 -6
- package/dist/session-emulator-binding-store.js +4 -6
- package/dist/session-fork-store.d.ts +1 -0
- package/dist/session-fork-store.js +82 -28
- package/dist/session-launch-operations.js +6 -5
- package/dist/session-log-store.d.ts +1 -0
- package/dist/session-log-store.js +19 -16
- package/dist/session-meta-store.d.ts +5 -0
- package/dist/session-meta-store.js +25 -2
- package/dist/session-portal-grant-store.d.ts +29 -0
- package/dist/session-portal-grant-store.js +85 -0
- package/dist/session-resource-store.d.ts +20 -6
- package/dist/session-resource-store.js +364 -68
- package/dist/setup-service.d.ts +1 -0
- package/dist/setup-service.js +1 -0
- package/dist/skills-catalog.d.ts +11 -2
- package/dist/skills-catalog.js +317 -10
- package/dist/sqlite.d.ts +22 -0
- package/dist/sqlite.js +57 -0
- package/dist/system-dependencies.d.ts +22 -0
- package/dist/system-dependencies.js +79 -0
- package/package.json +15 -12
- package/bundled-plugins/plugins/lark/ui/assets/index-B2dhMlMU.css +0 -1
- /package/bundled-plugins/plugins/lark/ui/assets/{index-D9N-AkLX.js → index-D8Amoe6a.js} +0 -0
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { normalizeSessionTitle, resolvedExecutionSnapshotSchema, sessionWorkspaceSnapshotSchema, } from "@rynx-ai/core";
|
|
15
15
|
import { db } from "./db.js";
|
|
16
|
+
import { transaction } from "./sqlite.js";
|
|
16
17
|
const COLS = "id, workspace, execution, title, forked_from_session_id, source, created_at, updated_at";
|
|
17
18
|
export function listSessionMetas() {
|
|
18
19
|
return db()
|
|
@@ -46,10 +47,15 @@ export function createSessionMeta(meta) {
|
|
|
46
47
|
export function setSessionTitle(id, title) {
|
|
47
48
|
db()
|
|
48
49
|
.prepare("UPDATE sessions SET title = ?, updated_at = ? WHERE id = ?")
|
|
49
|
-
.run(normalizeSessionTitle(title), new Date().toISOString(), id);
|
|
50
|
+
.run(normalizeSessionTitle(title) ?? null, new Date().toISOString(), id);
|
|
51
|
+
}
|
|
52
|
+
export function setSessionExecution(id, execution) {
|
|
53
|
+
db()
|
|
54
|
+
.prepare("UPDATE sessions SET execution = ?, updated_at = ? WHERE id = ?")
|
|
55
|
+
.run(JSON.stringify(resolvedExecutionSnapshotSchema.parse(execution)), new Date().toISOString(), id);
|
|
50
56
|
}
|
|
51
57
|
export function removeSessionMeta(id) {
|
|
52
|
-
db()
|
|
58
|
+
transaction(db(), () => {
|
|
53
59
|
const now = new Date().toISOString();
|
|
54
60
|
db()
|
|
55
61
|
.prepare(`UPDATE plugin_session_launch_operations
|
|
@@ -70,8 +76,25 @@ export const sessionRegistry = {
|
|
|
70
76
|
get: getSessionMeta,
|
|
71
77
|
list: listSessionMetas,
|
|
72
78
|
setTitle: setSessionTitle,
|
|
79
|
+
setExecution: setSessionExecution,
|
|
73
80
|
remove: removeSessionMeta,
|
|
74
81
|
};
|
|
82
|
+
/** Generic plugin-principal ownership, including descendants forked from a
|
|
83
|
+
* plugin-created Session. Portal authorization calls this on every request so
|
|
84
|
+
* a grant cannot cross into console or another plugin's Sessions. */
|
|
85
|
+
export function sessionBelongsToPlugin(pluginId, sessionId) {
|
|
86
|
+
const seen = new Set();
|
|
87
|
+
let current = sessionRegistry.get(sessionId);
|
|
88
|
+
while (current && !seen.has(current.id)) {
|
|
89
|
+
if (current.source === `plugin:${pluginId}`)
|
|
90
|
+
return true;
|
|
91
|
+
seen.add(current.id);
|
|
92
|
+
current = current.forkedFromSessionId
|
|
93
|
+
? sessionRegistry.get(current.forkedFromSessionId)
|
|
94
|
+
: undefined;
|
|
95
|
+
}
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
75
98
|
function rowToMeta(row) {
|
|
76
99
|
return {
|
|
77
100
|
id: row.id,
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type SessionPortalScope = "plugin_sessions" | "single_session";
|
|
2
|
+
export type SessionPortalAccess = "read_only" | "read_write";
|
|
3
|
+
export interface SessionPortalAuthorization {
|
|
4
|
+
portalId: string;
|
|
5
|
+
pluginId: string;
|
|
6
|
+
scope: SessionPortalScope;
|
|
7
|
+
access: SessionPortalAccess;
|
|
8
|
+
sessionId?: string;
|
|
9
|
+
expiresAt: string;
|
|
10
|
+
}
|
|
11
|
+
/** Issue a browser handoff into the native Session workbench. The Host knows
|
|
12
|
+
* only the generic Session scope and access level; product/user policy stays in
|
|
13
|
+
* the plugin that asks for the ticket. */
|
|
14
|
+
export declare function issueSessionPortalTicket(input: {
|
|
15
|
+
pluginId: string;
|
|
16
|
+
scope: SessionPortalScope;
|
|
17
|
+
access: SessionPortalAccess;
|
|
18
|
+
sessionId?: string;
|
|
19
|
+
now?: Date;
|
|
20
|
+
}): {
|
|
21
|
+
path: string;
|
|
22
|
+
expiresAt: string;
|
|
23
|
+
};
|
|
24
|
+
/** Atomically consume a one-use ticket and mint a fixed-lifetime browser grant. */
|
|
25
|
+
export declare function redeemSessionPortalTicket(ticket: string, now?: Date): (SessionPortalAuthorization & {
|
|
26
|
+
secret: string;
|
|
27
|
+
}) | undefined;
|
|
28
|
+
export declare function authorizeSessionPortalGrant(portalId: string, secret: string, now?: Date): SessionPortalAuthorization | undefined;
|
|
29
|
+
export declare function pruneSessionPortalAuthorization(now?: Date): void;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { createHash, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
|
|
2
|
+
import { db } from "./db.js";
|
|
3
|
+
import { transaction } from "./sqlite.js";
|
|
4
|
+
const TICKET_TTL_MS = 5 * 60 * 1_000;
|
|
5
|
+
const GRANT_TTL_MS = 30 * 60 * 1_000;
|
|
6
|
+
/** Issue a browser handoff into the native Session workbench. The Host knows
|
|
7
|
+
* only the generic Session scope and access level; product/user policy stays in
|
|
8
|
+
* the plugin that asks for the ticket. */
|
|
9
|
+
export function issueSessionPortalTicket(input) {
|
|
10
|
+
if ((input.scope === "single_session") !== Boolean(input.sessionId)) {
|
|
11
|
+
throw new Error("single_session Portal tickets require exactly one Session id");
|
|
12
|
+
}
|
|
13
|
+
const now = input.now ?? new Date();
|
|
14
|
+
const expiresAt = new Date(now.getTime() + TICKET_TTL_MS).toISOString();
|
|
15
|
+
const ticket = randomToken();
|
|
16
|
+
pruneSessionPortalAuthorization(now);
|
|
17
|
+
db().prepare(`INSERT INTO session_portal_tickets
|
|
18
|
+
(ticket_hash, plugin_id, scope, access, session_id, created_at, expires_at, used_at)
|
|
19
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, NULL)`).run(hash(ticket), input.pluginId, input.scope, input.access, input.sessionId ?? null, now.toISOString(), expiresAt);
|
|
20
|
+
return {
|
|
21
|
+
path: `/session-portal/redeem#ticket=${encodeURIComponent(ticket)}`,
|
|
22
|
+
expiresAt,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/** Atomically consume a one-use ticket and mint a fixed-lifetime browser grant. */
|
|
26
|
+
export function redeemSessionPortalTicket(ticket, now = new Date()) {
|
|
27
|
+
const connection = db();
|
|
28
|
+
return transaction(connection, () => {
|
|
29
|
+
const ticketHash = hash(ticket);
|
|
30
|
+
const row = connection.prepare(`SELECT plugin_id, scope, access, session_id, expires_at, used_at
|
|
31
|
+
FROM session_portal_tickets
|
|
32
|
+
WHERE ticket_hash = ?`).get(ticketHash);
|
|
33
|
+
if (!row || row.used_at !== null || row.expires_at <= now.toISOString())
|
|
34
|
+
return undefined;
|
|
35
|
+
const consumed = connection.prepare(`UPDATE session_portal_tickets SET used_at = ?
|
|
36
|
+
WHERE ticket_hash = ? AND used_at IS NULL AND expires_at > ?`).run(now.toISOString(), ticketHash, now.toISOString());
|
|
37
|
+
if (consumed.changes !== 1)
|
|
38
|
+
return undefined;
|
|
39
|
+
const portalId = randomUUID();
|
|
40
|
+
const secret = randomToken();
|
|
41
|
+
const expiresAt = new Date(now.getTime() + GRANT_TTL_MS).toISOString();
|
|
42
|
+
connection.prepare(`INSERT INTO session_portal_grants
|
|
43
|
+
(portal_id, secret_hash, plugin_id, scope, access, session_id, created_at, expires_at, revoked_at)
|
|
44
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL)`).run(portalId, hash(secret), row.plugin_id, row.scope, row.access, row.session_id, now.toISOString(), expiresAt);
|
|
45
|
+
return {
|
|
46
|
+
portalId,
|
|
47
|
+
secret,
|
|
48
|
+
pluginId: row.plugin_id,
|
|
49
|
+
scope: row.scope,
|
|
50
|
+
access: row.access,
|
|
51
|
+
...(row.session_id ? { sessionId: row.session_id } : {}),
|
|
52
|
+
expiresAt,
|
|
53
|
+
};
|
|
54
|
+
})();
|
|
55
|
+
}
|
|
56
|
+
export function authorizeSessionPortalGrant(portalId, secret, now = new Date()) {
|
|
57
|
+
const row = db().prepare(`SELECT portal_id, secret_hash, plugin_id, scope, access, session_id, expires_at, revoked_at
|
|
58
|
+
FROM session_portal_grants
|
|
59
|
+
WHERE portal_id = ?`).get(portalId);
|
|
60
|
+
if (!row || row.revoked_at !== null || row.expires_at <= now.toISOString())
|
|
61
|
+
return undefined;
|
|
62
|
+
const actual = Buffer.from(hash(secret), "hex");
|
|
63
|
+
const expected = Buffer.from(row.secret_hash, "hex");
|
|
64
|
+
if (actual.length !== expected.length || !timingSafeEqual(actual, expected))
|
|
65
|
+
return undefined;
|
|
66
|
+
return {
|
|
67
|
+
portalId: row.portal_id,
|
|
68
|
+
pluginId: row.plugin_id,
|
|
69
|
+
scope: row.scope,
|
|
70
|
+
access: row.access,
|
|
71
|
+
...(row.session_id ? { sessionId: row.session_id } : {}),
|
|
72
|
+
expiresAt: row.expires_at,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export function pruneSessionPortalAuthorization(now = new Date()) {
|
|
76
|
+
const connection = db();
|
|
77
|
+
connection.prepare("DELETE FROM session_portal_tickets WHERE expires_at <= ? OR used_at IS NOT NULL").run(now.toISOString());
|
|
78
|
+
connection.prepare("DELETE FROM session_portal_grants WHERE expires_at <= ? OR revoked_at IS NOT NULL").run(now.toISOString());
|
|
79
|
+
}
|
|
80
|
+
function randomToken() {
|
|
81
|
+
return randomBytes(32).toString("base64url");
|
|
82
|
+
}
|
|
83
|
+
function hash(value) {
|
|
84
|
+
return createHash("sha256").update(value, "utf8").digest("hex");
|
|
85
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type UserContentPart } from "@rynx-ai/core";
|
|
1
|
+
import { type SessionImageFileReference, type UserContentPart } from "@rynx-ai/core";
|
|
2
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";
|
|
3
|
+
import { type MachineSessionPreparedInput, type MachineSessionResourcePort, type MachineSessionRunExecutionSelection, type MachineSessionRunExecutionSnapshot } from "@rynx-ai/server";
|
|
4
4
|
export declare class SqliteSessionResourceStore implements MachineSessionResourcePort {
|
|
5
5
|
private readonly root;
|
|
6
6
|
constructor(root?: string);
|
|
@@ -9,18 +9,32 @@ export declare class SqliteSessionResourceStore implements MachineSessionResourc
|
|
|
9
9
|
writeUploadChunk(input: RemoteRuntimeSessionResourceUploadChunkParams): Promise<RemoteRuntimeSessionResourceUploadChunkResult>;
|
|
10
10
|
commitUpload(input: RemoteRuntimeSessionResourceUploadCommitParams): Promise<RemoteRuntimeSessionResourceUploadCommitResult>;
|
|
11
11
|
getResource(input: RemoteRuntimeSessionResourceGetParams): Promise<RemoteRuntimeSessionResourceGetResult>;
|
|
12
|
+
resolveCommittedLocalPath(sessionId: string, resourceId: string): string;
|
|
12
13
|
readResource(input: RemoteRuntimeSessionResourceReadParams): Promise<RemoteRuntimeSessionResourceReadResult>;
|
|
13
14
|
deleteResource(input: RemoteRuntimeSessionResourceDeleteParams): Promise<RemoteRuntimeSessionResourceDeleteResult>;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
materializeGeneratedImage(input: {
|
|
16
|
+
sessionId: string;
|
|
17
|
+
sourceId: string;
|
|
18
|
+
result: string;
|
|
19
|
+
}): Promise<SessionImageFileReference>;
|
|
20
|
+
prepareInput(sessionId: string, content: UserContentPart[], clientMessageId?: string, operationExecution?: {
|
|
21
|
+
selection: MachineSessionRunExecutionSelection;
|
|
22
|
+
snapshot: MachineSessionRunExecutionSnapshot;
|
|
23
|
+
}): Promise<MachineSessionPreparedInput>;
|
|
24
|
+
markMessageInjecting(sessionId: string, clientMessageId: string, identity?: {
|
|
25
|
+
responseId: string;
|
|
26
|
+
messageItemId: string;
|
|
27
|
+
}): void;
|
|
28
|
+
markMessageInjected(sessionId: string, clientMessageId: string, identity?: {
|
|
29
|
+
responseId: string;
|
|
30
|
+
}): void;
|
|
17
31
|
markMessageOutcomeUnknown(sessionId: string, clientMessageId: string, reason: string): void;
|
|
18
32
|
markMessageFailedNotStarted(sessionId: string, clientMessageId: string, reason: string): void;
|
|
19
33
|
deleteSession(sessionId: string): void;
|
|
20
34
|
private prepareMessageOperation;
|
|
21
35
|
private bindOperationResources;
|
|
22
36
|
private transitionOperation;
|
|
23
|
-
private
|
|
37
|
+
private finalizeStoredFile;
|
|
24
38
|
private reconcileUploadOffset;
|
|
25
39
|
private rowByUpload;
|
|
26
40
|
private requireUpload;
|