@rynx-ai/plugin-channel-lark 0.1.10 → 0.1.11-beta.10
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/.rynx-plugin/plugin.json +25 -0
- package/dist/cli-mirror/mirror-index.d.ts +4 -2
- package/dist/cli-mirror/mirror-index.js +10 -2
- package/dist/host-adapters.d.ts +26 -13
- package/dist/host-adapters.js +146 -44
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -3
- package/dist/lark-config-store.d.ts +30 -0
- package/dist/lark-config-store.js +135 -0
- package/dist/lark-runtime-state-store.d.ts +18 -0
- package/dist/lark-runtime-state-store.js +95 -0
- package/dist/lark-setup.d.ts +27 -5
- package/dist/lark-setup.js +24 -7
- package/dist/lark.d.ts +9 -2
- package/dist/lark.js +45 -80
- package/dist/runtime.d.ts +5 -8
- package/dist/runtime.js +131312 -141
- package/dist/settings.d.ts +7 -0
- package/dist/{runtime.mjs → settings.js} +6631 -10535
- package/package.json +27 -10
- package/ui/assets/index-CGUVAMsv.css +1 -0
- package/ui/assets/index-D8Amoe6a.js +201 -0
- package/ui/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- package/ui/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- package/ui/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- package/ui/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- package/ui/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/ui/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/ui/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- package/ui/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
- package/ui/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
- package/ui/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/ui/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/ui/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
- package/ui/index.html +13 -0
- package/rynx-plugin.json +0 -42
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "lark",
|
|
4
|
+
"version": "0.1.11",
|
|
5
|
+
"displayName": "Lark",
|
|
6
|
+
"description": "Lark and Feishu channel integration managed by the plugin.",
|
|
7
|
+
"apiRange": "^1.0.0",
|
|
8
|
+
"runtime": {
|
|
9
|
+
"entry": "./dist/runtime.js"
|
|
10
|
+
},
|
|
11
|
+
"channels": [
|
|
12
|
+
{
|
|
13
|
+
"id": "lark",
|
|
14
|
+
"displayName": "Lark"
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
"settings": {
|
|
18
|
+
"ui": {
|
|
19
|
+
"entry": "./ui/index.html"
|
|
20
|
+
},
|
|
21
|
+
"background": {
|
|
22
|
+
"entry": "./dist/settings.js"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CodexSessionStore, ConversationSessionStore } from "@rynx-ai/core";
|
|
1
|
+
import type { CodexSessionStore, ConversationSessionStore, SessionRegistry } from "@rynx-ai/core";
|
|
2
2
|
import type { LarkConversationDirectory } from "../lark-conversation-directory.js";
|
|
3
3
|
/**
|
|
4
4
|
* Resolves a Codex thread id (the rollout-file UUID) back to the Feishu
|
|
@@ -32,10 +32,12 @@ export declare class CodexMirrorIndex {
|
|
|
32
32
|
private readonly codexSessionStore;
|
|
33
33
|
private readonly conversationSessionStore;
|
|
34
34
|
private readonly conversationDirectory;
|
|
35
|
-
|
|
35
|
+
private readonly sessionRegistry;
|
|
36
|
+
constructor({ codexSessionStore, conversationSessionStore, conversationDirectory, sessionRegistry, }: {
|
|
36
37
|
codexSessionStore: Pick<CodexSessionStore, "listAll" | "findByCodexSessionId">;
|
|
37
38
|
conversationSessionStore: Pick<ConversationSessionStore, "findKeyBySessionId">;
|
|
38
39
|
conversationDirectory: Pick<LarkConversationDirectory, "get">;
|
|
40
|
+
sessionRegistry: Pick<SessionRegistry, "get">;
|
|
39
41
|
});
|
|
40
42
|
/** codexSessionId → the full send target, or null when the thread isn't
|
|
41
43
|
* bound, its session isn't routed, or the conversation was never recorded. */
|
|
@@ -2,10 +2,12 @@ export class CodexMirrorIndex {
|
|
|
2
2
|
codexSessionStore;
|
|
3
3
|
conversationSessionStore;
|
|
4
4
|
conversationDirectory;
|
|
5
|
-
|
|
5
|
+
sessionRegistry;
|
|
6
|
+
constructor({ codexSessionStore, conversationSessionStore, conversationDirectory, sessionRegistry, }) {
|
|
6
7
|
this.codexSessionStore = codexSessionStore;
|
|
7
8
|
this.conversationSessionStore = conversationSessionStore;
|
|
8
9
|
this.conversationDirectory = conversationDirectory;
|
|
10
|
+
this.sessionRegistry = sessionRegistry;
|
|
9
11
|
}
|
|
10
12
|
/** codexSessionId → the full send target, or null when the thread isn't
|
|
11
13
|
* bound, its session isn't routed, or the conversation was never recorded. */
|
|
@@ -22,6 +24,10 @@ export class CodexMirrorIndex {
|
|
|
22
24
|
if (!directory) {
|
|
23
25
|
return null;
|
|
24
26
|
}
|
|
27
|
+
const session = this.sessionRegistry.get(record.localThreadId);
|
|
28
|
+
if (!session) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
25
31
|
return {
|
|
26
32
|
codexSessionId,
|
|
27
33
|
localThreadId: record.localThreadId,
|
|
@@ -29,7 +35,9 @@ export class CodexMirrorIndex {
|
|
|
29
35
|
chatId: directory.chatId,
|
|
30
36
|
threadId: directory.threadId,
|
|
31
37
|
participants: directory.participants ?? [],
|
|
32
|
-
model
|
|
38
|
+
// A null model means the provider CLI owns model selection. The mirror
|
|
39
|
+
// still needs a stable string label for transcript normalization.
|
|
40
|
+
model: session.execution.model ?? session.execution.provider,
|
|
33
41
|
};
|
|
34
42
|
}
|
|
35
43
|
/** All Codex threads currently bound to a Feishu conversation (those whose
|
package/dist/host-adapters.d.ts
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
|
-
import { type AgentCapabilities, type AgentRuntimeId, type CapabilityResult, type
|
|
1
|
+
import { type AgentCapabilities, type AgentRuntimeId, type CapabilityResult, type ConversationSessionRecord, type ConversationStreamRequest, type ModelListResponse, type SessionExecution, type SessionEvent, type ThreadGoal } from "@rynx-ai/core";
|
|
2
2
|
import type { PluginAgentSummary, PluginHostClient, PluginResolvedSessionExecution, PluginSessionExecutionSnapshot } from "@rynx-ai/plugin-sdk";
|
|
3
3
|
import { FileLarkActiveSessionStore } from "./lark-session-store.js";
|
|
4
|
-
type LarkConversationRuntime
|
|
4
|
+
import type { LarkConversationRuntime } from "./lark.js";
|
|
5
|
+
interface HostSessionLaunchMeta {
|
|
6
|
+
sourceSessionId?: string;
|
|
7
|
+
agent?: string;
|
|
8
|
+
provider?: AgentRuntimeId;
|
|
9
|
+
model?: string;
|
|
10
|
+
reasoningEffort?: string;
|
|
11
|
+
}
|
|
5
12
|
/** Slow consumers fail the run instead of retaining an unbounded event stream. */
|
|
6
13
|
export declare const LARK_RUN_EVENT_QUEUE_MAX_ITEMS = 256;
|
|
7
14
|
export declare const LARK_RUN_EVENT_QUEUE_MAX_BYTES: number;
|
|
8
15
|
/**
|
|
9
|
-
* ConversationRuntime-shaped adapter backed exclusively by
|
|
10
|
-
*
|
|
16
|
+
* ConversationRuntime-shaped adapter backed exclusively by the typed Host API.
|
|
17
|
+
* The plugin never receives the daemon's runtime, abort controller,
|
|
11
18
|
* steer controller, or session bus.
|
|
12
19
|
*/
|
|
13
20
|
export declare class HostConversationRuntime implements LarkConversationRuntime {
|
|
@@ -16,12 +23,12 @@ export declare class HostConversationRuntime implements LarkConversationRuntime
|
|
|
16
23
|
runLive(input: ConversationStreamRequest): Promise<{
|
|
17
24
|
provider: "codex" | "traex" | "claude";
|
|
18
25
|
threadId: string;
|
|
19
|
-
model: string;
|
|
26
|
+
model: string | null;
|
|
20
27
|
authSource: "codex_cli" | "traex_cli" | "claude_cli";
|
|
21
28
|
generator: AsyncGenerator<SessionEvent, any, any>;
|
|
22
29
|
}>;
|
|
23
30
|
}
|
|
24
|
-
/** Agent command adapter used by /models
|
|
31
|
+
/** Agent command adapter used by /models and /goal. Session fork is a Core RPC. */
|
|
25
32
|
export declare class HostAgentCapabilities implements AgentCapabilities {
|
|
26
33
|
private readonly host;
|
|
27
34
|
constructor(host: PluginHostClient);
|
|
@@ -29,7 +36,6 @@ export declare class HostAgentCapabilities implements AgentCapabilities {
|
|
|
29
36
|
getGoal(sessionId: string): Promise<CapabilityResult<ThreadGoal | null>>;
|
|
30
37
|
setGoal(sessionId: string, objective: string): Promise<CapabilityResult>;
|
|
31
38
|
clearGoal(sessionId: string): Promise<CapabilityResult>;
|
|
32
|
-
forkSession(fromSessionId: string, toSessionId: string): Promise<CapabilityResult>;
|
|
33
39
|
}
|
|
34
40
|
/** Narrow agent catalog + first-turn execution resolver backed by Host RPC. */
|
|
35
41
|
export declare class HostAgentCatalog {
|
|
@@ -46,10 +52,14 @@ export declare class HostAgentCatalog {
|
|
|
46
52
|
export declare class HostSessionProvisioner {
|
|
47
53
|
private readonly host;
|
|
48
54
|
readonly instanceId: string;
|
|
55
|
+
private readonly resolvedExecutions;
|
|
49
56
|
constructor(host: PluginHostClient, instanceId: string);
|
|
50
|
-
provision(operationId: string): Promise<string>;
|
|
57
|
+
provision(operationId: string, session?: HostSessionLaunchMeta): Promise<string>;
|
|
58
|
+
takeExecution(sessionId: string): SessionExecution | undefined;
|
|
59
|
+
existingExecution(sessionId: string): Promise<SessionExecution | undefined>;
|
|
51
60
|
allocationOperationId(sessionKey: string, previousSessionId?: string): string;
|
|
52
61
|
forkOperationId(fromSessionId: string, newSessionKey: string): string;
|
|
62
|
+
fork(operationId: string, sourceSessionId: string, title?: string): Promise<string>;
|
|
53
63
|
setTitle(sessionId: string, title: string): Promise<void>;
|
|
54
64
|
}
|
|
55
65
|
/**
|
|
@@ -61,6 +71,7 @@ export declare class HostSessionProvisioner {
|
|
|
61
71
|
export declare class HostProvisionedLarkSessionStore extends FileLarkActiveSessionStore {
|
|
62
72
|
private readonly operation;
|
|
63
73
|
private mutationTail;
|
|
74
|
+
private readonly instanceDefaultAgent?;
|
|
64
75
|
constructor(options: {
|
|
65
76
|
filePath: string;
|
|
66
77
|
provisioner: HostSessionProvisioner;
|
|
@@ -69,12 +80,14 @@ export declare class HostProvisionedLarkSessionStore extends FileLarkActiveSessi
|
|
|
69
80
|
});
|
|
70
81
|
private readonly provisioner;
|
|
71
82
|
ensure(sessionKey: string): Promise<import("@rynx-ai/core").EnsureSessionResult>;
|
|
72
|
-
set(sessionKey: string, sessionId: string, cwd?: string): Promise<
|
|
83
|
+
set(sessionKey: string, sessionId: string, cwd?: string): Promise<ConversationSessionRecord>;
|
|
84
|
+
get(sessionKey: string): Promise<ConversationSessionRecord | null>;
|
|
73
85
|
rotate(sessionKey: string): Promise<import("@rynx-ai/core").RotateSessionResult>;
|
|
74
|
-
bindCwd(sessionKey: string, cwd: string): Promise<
|
|
75
|
-
applySettings(sessionKey: string, settings: Parameters<FileLarkActiveSessionStore["applySettings"]>[1]): Promise<
|
|
76
|
-
setAgent(sessionKey: string, agentName: string): Promise<
|
|
77
|
-
freeze(sessionKey: string, execution: Parameters<FileLarkActiveSessionStore["freeze"]>[1]): Promise<
|
|
86
|
+
bindCwd(sessionKey: string, cwd: string): Promise<ConversationSessionRecord>;
|
|
87
|
+
applySettings(sessionKey: string, settings: Parameters<FileLarkActiveSessionStore["applySettings"]>[1]): Promise<ConversationSessionRecord>;
|
|
88
|
+
setAgent(sessionKey: string, agentName: string): Promise<ConversationSessionRecord>;
|
|
89
|
+
freeze(sessionKey: string, execution: Parameters<FileLarkActiveSessionStore["freeze"]>[1]): Promise<ConversationSessionRecord>;
|
|
90
|
+
private pinResolvedExecution;
|
|
78
91
|
private withAllocation;
|
|
79
92
|
private runMutation;
|
|
80
93
|
}
|
package/dist/host-adapters.js
CHANGED
|
@@ -6,8 +6,8 @@ import { FileLarkActiveSessionStore, } from "./lark-session-store.js";
|
|
|
6
6
|
export const LARK_RUN_EVENT_QUEUE_MAX_ITEMS = 256;
|
|
7
7
|
export const LARK_RUN_EVENT_QUEUE_MAX_BYTES = 8 * 1024 * 1024;
|
|
8
8
|
/**
|
|
9
|
-
* ConversationRuntime-shaped adapter backed exclusively by
|
|
10
|
-
*
|
|
9
|
+
* ConversationRuntime-shaped adapter backed exclusively by the typed Host API.
|
|
10
|
+
* The plugin never receives the daemon's runtime, abort controller,
|
|
11
11
|
* steer controller, or session bus.
|
|
12
12
|
*/
|
|
13
13
|
export class HostConversationRuntime {
|
|
@@ -37,7 +37,7 @@ export class HostConversationRuntime {
|
|
|
37
37
|
const interrupt = () => {
|
|
38
38
|
if (!runId || terminal)
|
|
39
39
|
return;
|
|
40
|
-
void this.host.
|
|
40
|
+
void this.host.sessions.interrupt({ runId }).catch(() => undefined);
|
|
41
41
|
};
|
|
42
42
|
const accept = (event, payload) => {
|
|
43
43
|
if (!runId) {
|
|
@@ -86,17 +86,11 @@ export class HostConversationRuntime {
|
|
|
86
86
|
unsubscribeEvents();
|
|
87
87
|
let started;
|
|
88
88
|
try {
|
|
89
|
-
started = await this.host.
|
|
89
|
+
started = await this.host.sessions.run({
|
|
90
90
|
sessionId: input.threadId,
|
|
91
|
+
model: input.model?.trim() || null,
|
|
92
|
+
reasoningEffort: input.reasoningEffort?.trim() || null,
|
|
91
93
|
message: input.message,
|
|
92
|
-
...(input.provider ? { provider: input.provider } : {}),
|
|
93
|
-
...(input.model ? { model: input.model } : {}),
|
|
94
|
-
...(input.reasoningEffort ? { reasoningEffort: input.reasoningEffort } : {}),
|
|
95
|
-
...(input.cwd ? { cwd: input.cwd } : {}),
|
|
96
|
-
...(input.agentName ? { agent: input.agentName } : {}),
|
|
97
|
-
...(input.developerInstructions
|
|
98
|
-
? { developerInstructions: input.developerInstructions }
|
|
99
|
-
: {}),
|
|
100
94
|
});
|
|
101
95
|
runId = started.runId;
|
|
102
96
|
if (earlyOverflow) {
|
|
@@ -117,7 +111,7 @@ export class HostConversationRuntime {
|
|
|
117
111
|
const unsteer = input.steer?.subscribe((text) => {
|
|
118
112
|
if (!runId || terminal)
|
|
119
113
|
return;
|
|
120
|
-
void this.host.
|
|
114
|
+
void this.host.sessions.steer({ runId, text }).catch(() => undefined);
|
|
121
115
|
});
|
|
122
116
|
input.signal?.addEventListener("abort", interrupt, { once: true });
|
|
123
117
|
const generator = (async function* () {
|
|
@@ -142,26 +136,23 @@ export class HostConversationRuntime {
|
|
|
142
136
|
};
|
|
143
137
|
}
|
|
144
138
|
}
|
|
145
|
-
/** Agent command adapter used by /models
|
|
139
|
+
/** Agent command adapter used by /models and /goal. Session fork is a Core RPC. */
|
|
146
140
|
export class HostAgentCapabilities {
|
|
147
141
|
host;
|
|
148
142
|
constructor(host) {
|
|
149
143
|
this.host = host;
|
|
150
144
|
}
|
|
151
145
|
listModels(runtime) {
|
|
152
|
-
return this.host.
|
|
146
|
+
return this.host.sessions.listModels(runtime ? { runtime } : undefined);
|
|
153
147
|
}
|
|
154
148
|
getGoal(sessionId) {
|
|
155
|
-
return this.host.
|
|
149
|
+
return this.host.sessions.goals.get({ sessionId });
|
|
156
150
|
}
|
|
157
151
|
setGoal(sessionId, objective) {
|
|
158
|
-
return this.host.
|
|
152
|
+
return this.host.sessions.goals.set({ sessionId, objective });
|
|
159
153
|
}
|
|
160
154
|
clearGoal(sessionId) {
|
|
161
|
-
return this.host.
|
|
162
|
-
}
|
|
163
|
-
forkSession(fromSessionId, toSessionId) {
|
|
164
|
-
return this.host.call("session.fork", { fromSessionId, toSessionId });
|
|
155
|
+
return this.host.sessions.goals.clear({ sessionId });
|
|
165
156
|
}
|
|
166
157
|
}
|
|
167
158
|
/** Narrow agent catalog + first-turn execution resolver backed by Host RPC. */
|
|
@@ -171,41 +162,82 @@ export class HostAgentCatalog {
|
|
|
171
162
|
this.host = host;
|
|
172
163
|
}
|
|
173
164
|
list() {
|
|
174
|
-
return this.host.
|
|
165
|
+
return this.host.agents.list();
|
|
175
166
|
}
|
|
176
167
|
get(id) {
|
|
177
|
-
return this.host.
|
|
168
|
+
return this.host.agents.get({ id });
|
|
178
169
|
}
|
|
179
170
|
resolveExecution(input) {
|
|
180
|
-
return this.host.
|
|
171
|
+
return this.host.agents.resolveExecution(input);
|
|
181
172
|
}
|
|
182
173
|
}
|
|
183
174
|
/** Daemon-owned session allocator. operationId must identify one allocation attempt durably. */
|
|
184
175
|
export class HostSessionProvisioner {
|
|
185
176
|
host;
|
|
186
177
|
instanceId;
|
|
178
|
+
resolvedExecutions = new Map();
|
|
187
179
|
constructor(host, instanceId) {
|
|
188
180
|
this.host = host;
|
|
189
181
|
this.instanceId = instanceId;
|
|
190
182
|
}
|
|
191
|
-
async provision(operationId) {
|
|
192
|
-
const result = await this.host.
|
|
183
|
+
async provision(operationId, session = {}) {
|
|
184
|
+
const result = await this.host.sessions.ensure({
|
|
193
185
|
scopeId: this.instanceId,
|
|
194
186
|
operationId,
|
|
195
|
-
session
|
|
187
|
+
session,
|
|
196
188
|
});
|
|
197
189
|
if (!result?.sessionId)
|
|
198
190
|
throw new Error("host did not return a provisioned session id");
|
|
191
|
+
this.resolvedExecutions.set(result.sessionId, {
|
|
192
|
+
runtime: result.execution.provider,
|
|
193
|
+
...(result.execution.model ? { model: result.execution.model } : {}),
|
|
194
|
+
...(result.execution.reasoningEffort
|
|
195
|
+
? { reasoningEffort: result.execution.reasoningEffort }
|
|
196
|
+
: {}),
|
|
197
|
+
...(session.agent ? { agent: session.agent } : {}),
|
|
198
|
+
});
|
|
199
199
|
return result.sessionId;
|
|
200
200
|
}
|
|
201
|
+
takeExecution(sessionId) {
|
|
202
|
+
const execution = this.resolvedExecutions.get(sessionId);
|
|
203
|
+
this.resolvedExecutions.delete(sessionId);
|
|
204
|
+
return execution;
|
|
205
|
+
}
|
|
206
|
+
async existingExecution(sessionId) {
|
|
207
|
+
try {
|
|
208
|
+
const session = await this.host.sessions.get({ sessionId });
|
|
209
|
+
return {
|
|
210
|
+
runtime: session.execution.provider,
|
|
211
|
+
...(session.execution.model ? { model: session.execution.model } : {}),
|
|
212
|
+
...(session.execution.reasoningEffort
|
|
213
|
+
? { reasoningEffort: session.execution.reasoningEffort }
|
|
214
|
+
: {}),
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
if (hostErrorCode(error) === "SESSION_NOT_FOUND")
|
|
219
|
+
return undefined;
|
|
220
|
+
throw error;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
201
223
|
allocationOperationId(sessionKey, previousSessionId) {
|
|
202
224
|
return stableOperationId("allocate", this.instanceId, sessionKey, previousSessionId ?? "initial");
|
|
203
225
|
}
|
|
204
226
|
forkOperationId(fromSessionId, newSessionKey) {
|
|
205
227
|
return stableOperationId("fork", this.instanceId, fromSessionId, newSessionKey);
|
|
206
228
|
}
|
|
229
|
+
async fork(operationId, sourceSessionId, title) {
|
|
230
|
+
const result = await this.host.sessions.fork({
|
|
231
|
+
sourceSessionId,
|
|
232
|
+
operationId,
|
|
233
|
+
...(title ? { title } : {}),
|
|
234
|
+
});
|
|
235
|
+
if (!result?.sessionId)
|
|
236
|
+
throw new Error("host did not return a forked session id");
|
|
237
|
+
return result.sessionId;
|
|
238
|
+
}
|
|
207
239
|
async setTitle(sessionId, title) {
|
|
208
|
-
await this.host.
|
|
240
|
+
await this.host.sessions.setTitle({ sessionId, title });
|
|
209
241
|
}
|
|
210
242
|
}
|
|
211
243
|
/**
|
|
@@ -217,6 +249,7 @@ export class HostSessionProvisioner {
|
|
|
217
249
|
export class HostProvisionedLarkSessionStore extends FileLarkActiveSessionStore {
|
|
218
250
|
operation;
|
|
219
251
|
mutationTail = Promise.resolve();
|
|
252
|
+
instanceDefaultAgent;
|
|
220
253
|
constructor(options) {
|
|
221
254
|
const operation = new AsyncLocalStorage();
|
|
222
255
|
super({
|
|
@@ -224,52 +257,94 @@ export class HostProvisionedLarkSessionStore extends FileLarkActiveSessionStore
|
|
|
224
257
|
defaultAgent: options.defaultAgent,
|
|
225
258
|
now: options.now,
|
|
226
259
|
createSessionId: async () => {
|
|
227
|
-
const
|
|
228
|
-
if (!
|
|
260
|
+
const allocation = operation.getStore();
|
|
261
|
+
if (!allocation)
|
|
229
262
|
throw new Error("session allocation is missing its stable operation id");
|
|
230
|
-
return options.provisioner.provision(operationId);
|
|
263
|
+
return options.provisioner.provision(allocation.operationId, allocation.session);
|
|
231
264
|
},
|
|
232
265
|
});
|
|
233
266
|
this.operation = operation;
|
|
234
267
|
this.provisioner = options.provisioner;
|
|
268
|
+
this.instanceDefaultAgent = options.defaultAgent;
|
|
235
269
|
}
|
|
236
270
|
provisioner;
|
|
237
271
|
async ensure(sessionKey) {
|
|
238
272
|
return this.runMutation(async () => {
|
|
239
273
|
const current = await super.get(sessionKey);
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
274
|
+
const existingExecution = current
|
|
275
|
+
? await this.provisioner.existingExecution(current.sessionId)
|
|
276
|
+
: undefined;
|
|
277
|
+
if (current && existingExecution) {
|
|
278
|
+
const pinned = current.runtime
|
|
279
|
+
? current
|
|
280
|
+
: await super.freeze(sessionKey, existingExecution);
|
|
281
|
+
return { ...current, ...pinned, source: "existing" };
|
|
282
|
+
}
|
|
283
|
+
if (current) {
|
|
284
|
+
const replacement = await this.withAllocation(sessionKey, current.sessionId, launchMeta(current), () => super.rotate(sessionKey));
|
|
285
|
+
return {
|
|
286
|
+
...await this.pinResolvedExecution(sessionKey, replacement),
|
|
287
|
+
source: "new",
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
const created = await this.withAllocation(sessionKey, undefined, this.instanceDefaultAgent ? { agent: this.instanceDefaultAgent } : {}, () => super.ensure(sessionKey));
|
|
291
|
+
return this.pinResolvedExecution(sessionKey, created);
|
|
243
292
|
});
|
|
244
293
|
}
|
|
245
294
|
async set(sessionKey, sessionId, cwd) {
|
|
246
|
-
return this.runMutation(() => super.set(sessionKey, sessionId, cwd));
|
|
295
|
+
return this.runMutation(async () => this.pinResolvedExecution(sessionKey, await super.set(sessionKey, sessionId, cwd)));
|
|
247
296
|
}
|
|
248
|
-
async
|
|
297
|
+
async get(sessionKey) {
|
|
249
298
|
return this.runMutation(async () => {
|
|
250
299
|
const current = await super.get(sessionKey);
|
|
251
|
-
|
|
300
|
+
if (!current)
|
|
301
|
+
return current;
|
|
302
|
+
const existingExecution = await this.provisioner.existingExecution(current.sessionId);
|
|
303
|
+
if (existingExecution) {
|
|
304
|
+
return current.runtime ? current : super.freeze(sessionKey, existingExecution);
|
|
305
|
+
}
|
|
306
|
+
const replacement = await this.withAllocation(sessionKey, current.sessionId, launchMeta(current), () => super.rotate(sessionKey));
|
|
307
|
+
return this.pinResolvedExecution(sessionKey, replacement);
|
|
252
308
|
});
|
|
253
309
|
}
|
|
254
|
-
async
|
|
310
|
+
async rotate(sessionKey) {
|
|
255
311
|
return this.runMutation(async () => {
|
|
256
312
|
const current = await super.get(sessionKey);
|
|
257
|
-
|
|
313
|
+
const rotated = await this.withAllocation(sessionKey, current?.sessionId, launchMeta(current), () => super.rotate(sessionKey));
|
|
314
|
+
return this.pinResolvedExecution(sessionKey, rotated);
|
|
258
315
|
});
|
|
259
316
|
}
|
|
317
|
+
async bindCwd(sessionKey, cwd) {
|
|
318
|
+
void sessionKey;
|
|
319
|
+
void cwd;
|
|
320
|
+
throw new Error("working directory is managed by the Session Project snapshot");
|
|
321
|
+
}
|
|
260
322
|
async applySettings(sessionKey, settings) {
|
|
261
323
|
return this.runMutation(async () => {
|
|
262
324
|
if (!settings.rotate && (await super.get(sessionKey))) {
|
|
263
325
|
return super.applySettings(sessionKey, settings);
|
|
264
326
|
}
|
|
265
327
|
const current = await super.get(sessionKey);
|
|
266
|
-
|
|
328
|
+
const providerChanged = Boolean(settings.runtime && settings.runtime !== current?.runtime);
|
|
329
|
+
const updated = await this.withAllocation(sessionKey, current?.sessionId, launchMeta({
|
|
330
|
+
...(providerChanged
|
|
331
|
+
? { provider: settings.runtime }
|
|
332
|
+
: (current?.agent ?? this.instanceDefaultAgent)
|
|
333
|
+
? { agent: current?.agent ?? this.instanceDefaultAgent }
|
|
334
|
+
: settings.runtime
|
|
335
|
+
? { provider: settings.runtime }
|
|
336
|
+
: {}),
|
|
337
|
+
...(settings.model ? { model: settings.model } : {}),
|
|
338
|
+
...(settings.reasoningEffort ? { reasoningEffort: settings.reasoningEffort } : {}),
|
|
339
|
+
}), () => super.applySettings(sessionKey, settings));
|
|
340
|
+
return this.pinResolvedExecution(sessionKey, updated);
|
|
267
341
|
});
|
|
268
342
|
}
|
|
269
343
|
async setAgent(sessionKey, agentName) {
|
|
270
344
|
return this.runMutation(async () => {
|
|
271
345
|
const current = await super.get(sessionKey);
|
|
272
|
-
|
|
346
|
+
const updated = await this.withAllocation(sessionKey, current?.sessionId, { agent: agentName }, () => super.setAgent(sessionKey, agentName));
|
|
347
|
+
return this.pinResolvedExecution(sessionKey, updated);
|
|
273
348
|
});
|
|
274
349
|
}
|
|
275
350
|
async freeze(sessionKey, execution) {
|
|
@@ -277,11 +352,22 @@ export class HostProvisionedLarkSessionStore extends FileLarkActiveSessionStore
|
|
|
277
352
|
const current = await super.get(sessionKey);
|
|
278
353
|
if (current)
|
|
279
354
|
return super.freeze(sessionKey, execution);
|
|
280
|
-
|
|
355
|
+
const frozen = await this.withAllocation(sessionKey, undefined, launchMeta(execution), () => super.freeze(sessionKey, execution));
|
|
356
|
+
return this.pinResolvedExecution(sessionKey, frozen);
|
|
281
357
|
});
|
|
282
358
|
}
|
|
283
|
-
|
|
284
|
-
|
|
359
|
+
async pinResolvedExecution(sessionKey, record) {
|
|
360
|
+
const execution = this.provisioner.takeExecution(record.sessionId);
|
|
361
|
+
if (!execution)
|
|
362
|
+
return record;
|
|
363
|
+
const frozen = await super.freeze(sessionKey, execution);
|
|
364
|
+
return { ...record, ...frozen };
|
|
365
|
+
}
|
|
366
|
+
withAllocation(sessionKey, previousSessionId, session, run) {
|
|
367
|
+
return this.operation.run({
|
|
368
|
+
operationId: this.provisioner.allocationOperationId(sessionKey, previousSessionId),
|
|
369
|
+
session,
|
|
370
|
+
}, run);
|
|
285
371
|
}
|
|
286
372
|
async runMutation(run) {
|
|
287
373
|
const previous = this.mutationTail;
|
|
@@ -298,6 +384,22 @@ export class HostProvisionedLarkSessionStore extends FileLarkActiveSessionStore
|
|
|
298
384
|
}
|
|
299
385
|
}
|
|
300
386
|
}
|
|
387
|
+
function launchMeta(input) {
|
|
388
|
+
if (!input)
|
|
389
|
+
return {};
|
|
390
|
+
return {
|
|
391
|
+
...(input.agent ? { agent: input.agent } : {}),
|
|
392
|
+
...(input.provider ? { provider: input.provider } : {}),
|
|
393
|
+
...(input.model ? { model: input.model } : {}),
|
|
394
|
+
...(input.reasoningEffort ? { reasoningEffort: input.reasoningEffort } : {}),
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
function hostErrorCode(error) {
|
|
398
|
+
return error && typeof error === "object" && "code" in error &&
|
|
399
|
+
typeof error.code === "string"
|
|
400
|
+
? error.code
|
|
401
|
+
: undefined;
|
|
402
|
+
}
|
|
301
403
|
export function stableOperationId(kind, ...parts) {
|
|
302
404
|
const digest = createHash("sha256").update(parts.join("\0")).digest("hex");
|
|
303
405
|
return `${kind}-${digest}`;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/** Public Lark plugin API.
|
|
2
|
-
*
|
|
3
|
-
* no legacy in-process `RynxPlugin` manifest or daemon Channel factory. */
|
|
1
|
+
/** Public Lark plugin API. Rynx loads the manifest's self-contained runtime
|
|
2
|
+
* module; this package exports no in-process daemon Channel factory. */
|
|
4
3
|
export { LocalLarkBotRuntime } from "./lark.js";
|
|
5
|
-
export { authorizeLark, larkConfigSchema, LARK_BOT_SCOPES, LARK_BOT_EVENTS, } from "./lark-setup.js";
|
|
4
|
+
export { authorizeLark, larkConfigSchema, LARK_BOT_SCOPES, LARK_BOT_EVENTS, type LarkAuthorizationMaterial, type LarkSetupField, } from "./lark-setup.js";
|
|
6
5
|
export { activate, createLarkPluginRuntime, LARK_CHANNEL_ID, type LarkPluginRuntimeOptions, } from "./runtime.js";
|
|
6
|
+
export { createLarkPluginSettings, type LarkPluginSettingsOptions, } from "./settings.js";
|
|
7
7
|
export { HostAgentCapabilities, HostAgentCatalog, HostConversationRuntime, HostProvisionedLarkSessionStore, HostSessionProvisioner, stableOperationId, } from "./host-adapters.js";
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/** Public Lark plugin API.
|
|
2
|
-
*
|
|
3
|
-
* no legacy in-process `RynxPlugin` manifest or daemon Channel factory. */
|
|
1
|
+
/** Public Lark plugin API. Rynx loads the manifest's self-contained runtime
|
|
2
|
+
* module; this package exports no in-process daemon Channel factory. */
|
|
4
3
|
export { LocalLarkBotRuntime } from "./lark.js";
|
|
5
4
|
export { authorizeLark, larkConfigSchema, LARK_BOT_SCOPES, LARK_BOT_EVENTS, } from "./lark-setup.js";
|
|
6
5
|
export { activate, createLarkPluginRuntime, LARK_CHANNEL_ID, } from "./runtime.js";
|
|
6
|
+
export { createLarkPluginSettings, } from "./settings.js";
|
|
7
7
|
export { HostAgentCapabilities, HostAgentCatalog, HostConversationRuntime, HostProvisionedLarkSessionStore, HostSessionProvisioner, stableOperationId, } from "./host-adapters.js";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { PluginExecutionDefaults } from "@rynx-ai/plugin-sdk";
|
|
2
|
+
export interface LarkInstanceConfig {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
enabled: boolean;
|
|
6
|
+
appId: string;
|
|
7
|
+
appSecret: string;
|
|
8
|
+
defaultAgent?: string;
|
|
9
|
+
executionDefaults: PluginExecutionDefaults;
|
|
10
|
+
}
|
|
11
|
+
export declare class LarkConfigStore {
|
|
12
|
+
private readonly file;
|
|
13
|
+
constructor(dataDir: string);
|
|
14
|
+
list(): LarkInstanceConfig[];
|
|
15
|
+
get(id: string): LarkInstanceConfig | undefined;
|
|
16
|
+
upsert(input: {
|
|
17
|
+
id?: string;
|
|
18
|
+
name: string;
|
|
19
|
+
enabled: boolean;
|
|
20
|
+
appId: string;
|
|
21
|
+
appSecret?: string;
|
|
22
|
+
defaultAgent?: string | null;
|
|
23
|
+
runtime?: PluginExecutionDefaults["runtime"];
|
|
24
|
+
allowedRoots?: string[];
|
|
25
|
+
}): LarkInstanceConfig;
|
|
26
|
+
remove(id: string): boolean;
|
|
27
|
+
setEnabled(id: string, enabled: boolean): LarkInstanceConfig;
|
|
28
|
+
private read;
|
|
29
|
+
private write;
|
|
30
|
+
}
|