lunel-cli 0.1.119 → 0.1.121
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/ai/codex.d.ts +2 -2
- package/dist/ai/codex.js +51 -69
- package/dist/ai/index.d.ts +0 -18
- package/dist/ai/index.js +0 -45
- package/dist/ai/interface.d.ts +2 -16
- package/dist/ai/opencode.d.ts +1 -5
- package/dist/ai/opencode.js +16 -90
- package/dist/index.js +4 -234
- package/package.json +1 -1
package/dist/ai/codex.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AIProvider, AiEventEmitter, CodexPromptOptions,
|
|
1
|
+
import type { AIProvider, AiEventEmitter, CodexPromptOptions, FileAttachment, ModelSelector, MessageInfo, ProviderInfo, SessionInfo, ShareInfo } from "./interface.js";
|
|
2
2
|
export declare class CodexProvider implements AIProvider {
|
|
3
3
|
private proc;
|
|
4
4
|
private shuttingDown;
|
|
@@ -36,7 +36,6 @@ export declare class CodexProvider implements AIProvider {
|
|
|
36
36
|
getMessages(sessionId: string): Promise<{
|
|
37
37
|
messages: MessageInfo[];
|
|
38
38
|
}>;
|
|
39
|
-
syncState(sessionIds?: string[]): Promise<AiSyncState>;
|
|
40
39
|
prompt(sessionId: string, text: string, model?: ModelSelector, agent?: string, files?: FileAttachment[], codexOptions?: CodexPromptOptions): Promise<{
|
|
41
40
|
ack: true;
|
|
42
41
|
}>;
|
|
@@ -77,6 +76,7 @@ export declare class CodexProvider implements AIProvider {
|
|
|
77
76
|
private refreshSessionMetadata;
|
|
78
77
|
private fetchServerThreadsByArchiveState;
|
|
79
78
|
private fetchModels;
|
|
79
|
+
private fetchModelById;
|
|
80
80
|
private resolveModelId;
|
|
81
81
|
private buildCollaborationMode;
|
|
82
82
|
private parseThreadListEntry;
|
package/dist/ai/codex.js
CHANGED
|
@@ -268,80 +268,25 @@ export class CodexProvider {
|
|
|
268
268
|
}
|
|
269
269
|
return { messages: session.messages };
|
|
270
270
|
}
|
|
271
|
-
async syncState(sessionIds = []) {
|
|
272
|
-
await this.listSessions().catch(() => ({ sessions: [] }));
|
|
273
|
-
const messageSessionIds = new Set(sessionIds);
|
|
274
|
-
for (const session of this.sessions.values()) {
|
|
275
|
-
if (session.activeTurnId)
|
|
276
|
-
messageSessionIds.add(session.id);
|
|
277
|
-
}
|
|
278
|
-
for (const pending of this.pendingPermissionRequestIds.values()) {
|
|
279
|
-
if (pending.sessionId)
|
|
280
|
-
messageSessionIds.add(pending.sessionId);
|
|
281
|
-
}
|
|
282
|
-
for (const pending of this.pendingQuestionRequestIds.values()) {
|
|
283
|
-
if (pending.sessionId)
|
|
284
|
-
messageSessionIds.add(pending.sessionId);
|
|
285
|
-
}
|
|
286
|
-
const messages = {};
|
|
287
|
-
const statuses = [];
|
|
288
|
-
await Promise.allSettled(Array.from(messageSessionIds).map(async (sessionId) => {
|
|
289
|
-
const response = await this.getMessages(sessionId);
|
|
290
|
-
messages[sessionId] = response.messages;
|
|
291
|
-
const session = this.sessions.get(sessionId);
|
|
292
|
-
if (!session)
|
|
293
|
-
return;
|
|
294
|
-
const activeTurnId = await this.resolveInFlightTurnId(sessionId).catch(() => undefined);
|
|
295
|
-
session.activeTurnId = activeTurnId;
|
|
296
|
-
if (activeTurnId) {
|
|
297
|
-
statuses.push({
|
|
298
|
-
sessionID: sessionId,
|
|
299
|
-
status: { type: "running", activeTurnId },
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
}));
|
|
303
|
-
return {
|
|
304
|
-
sessions: Array.from(this.sessions.values()).map((session) => this.toSessionInfo(session)),
|
|
305
|
-
statuses,
|
|
306
|
-
messages,
|
|
307
|
-
pendingPermissions: Array.from(this.pendingPermissionRequestIds.entries()).map(([id, pending]) => ({
|
|
308
|
-
id,
|
|
309
|
-
sessionID: pending.sessionId,
|
|
310
|
-
messageID: pending.messageId,
|
|
311
|
-
callID: pending.callId,
|
|
312
|
-
type: pending.method,
|
|
313
|
-
title: pending.method,
|
|
314
|
-
metadata: { method: pending.method },
|
|
315
|
-
})),
|
|
316
|
-
pendingQuestions: Array.from(this.pendingQuestionRequestIds.entries()).map(([id, pending]) => ({
|
|
317
|
-
id,
|
|
318
|
-
sessionID: pending.sessionId,
|
|
319
|
-
questions: [],
|
|
320
|
-
tool: {
|
|
321
|
-
...(pending.messageId ? { messageID: pending.messageId } : {}),
|
|
322
|
-
...(pending.callId ? { callID: pending.callId } : {}),
|
|
323
|
-
},
|
|
324
|
-
})),
|
|
325
|
-
statusAuthoritative: true,
|
|
326
|
-
generatedAt: Date.now(),
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
271
|
async prompt(sessionId, text, model, agent, files = [], codexOptions) {
|
|
330
272
|
const session = this.ensureLocalSession(sessionId);
|
|
331
273
|
session.updatedAt = Date.now();
|
|
332
274
|
(async () => {
|
|
333
275
|
try {
|
|
334
|
-
const effortLevels = ["low", "medium", "high"];
|
|
335
|
-
const speedDelta = {
|
|
336
|
-
fast: -1,
|
|
337
|
-
balanced: 0,
|
|
338
|
-
quality: 1,
|
|
339
|
-
};
|
|
340
|
-
const baseEffort = codexOptions?.reasoningEffort ?? "medium";
|
|
341
|
-
const baseIndex = effortLevels.indexOf(baseEffort);
|
|
342
|
-
const adjustedIndex = Math.max(0, Math.min(effortLevels.length - 1, baseIndex + (codexOptions?.speed ? speedDelta[codexOptions.speed] : 0)));
|
|
343
|
-
const reasoningEffort = effortLevels[adjustedIndex];
|
|
344
276
|
const modelId = await this.resolveModelId(model);
|
|
277
|
+
const modelInfo = await this.fetchModelById(modelId);
|
|
278
|
+
const effortLevels = modelInfo?.supportedReasoningEfforts.map((effort) => effort.reasoningEffort) ?? [];
|
|
279
|
+
const defaultEffort = modelInfo?.defaultReasoningEffort ?? effortLevels[0] ?? "medium";
|
|
280
|
+
const requestedEffort = codexOptions?.reasoningEffort;
|
|
281
|
+
const reasoningEffort = requestedEffort && effortLevels.includes(requestedEffort)
|
|
282
|
+
? requestedEffort
|
|
283
|
+
: defaultEffort;
|
|
284
|
+
const requestedSpeedTier = codexOptions?.speed && codexOptions.speed !== "default"
|
|
285
|
+
? codexOptions.speed
|
|
286
|
+
: undefined;
|
|
287
|
+
const serviceTier = requestedSpeedTier && modelInfo?.additionalSpeedTiers.includes(requestedSpeedTier)
|
|
288
|
+
? requestedSpeedTier
|
|
289
|
+
: undefined;
|
|
345
290
|
const collaborationMode = this.buildCollaborationMode(agent, modelId, reasoningEffort);
|
|
346
291
|
// Freshly created sessions already have a live backend thread from
|
|
347
292
|
// thread/start. Forcing thread/resume here can attach stale state to a
|
|
@@ -354,7 +299,8 @@ export class CodexProvider {
|
|
|
354
299
|
threadId: session.id,
|
|
355
300
|
input: this.makeTurnInputPayload(text, files, imageUrlKey),
|
|
356
301
|
...(modelId ? { model: modelId } : {}),
|
|
357
|
-
...(reasoningEffort ? { reasoningEffort } : {}),
|
|
302
|
+
...(reasoningEffort ? { effort: reasoningEffort } : {}),
|
|
303
|
+
...(serviceTier ? { serviceTier } : {}),
|
|
358
304
|
...(collaborationMode ? { collaborationMode } : {}),
|
|
359
305
|
});
|
|
360
306
|
break;
|
|
@@ -400,6 +346,9 @@ export class CodexProvider {
|
|
|
400
346
|
name: item.displayName || item.model,
|
|
401
347
|
provider: "codex",
|
|
402
348
|
description: item.description,
|
|
349
|
+
defaultReasoningEffort: item.defaultReasoningEffort,
|
|
350
|
+
supportedReasoningEfforts: item.supportedReasoningEfforts,
|
|
351
|
+
additionalSpeedTiers: item.additionalSpeedTiers,
|
|
403
352
|
},
|
|
404
353
|
]));
|
|
405
354
|
const defaultModel = items.find((item) => item.isDefault)?.model;
|
|
@@ -1044,16 +993,49 @@ export class CodexProvider {
|
|
|
1044
993
|
const displayName = this.readString(obj.displayName)
|
|
1045
994
|
?? this.readString(obj.display_name)
|
|
1046
995
|
?? model;
|
|
996
|
+
const supportedReasoningEfforts = Array.isArray(obj.supportedReasoningEfforts)
|
|
997
|
+
? obj.supportedReasoningEfforts
|
|
998
|
+
.map((effort) => {
|
|
999
|
+
const effortObj = this.asRecord(effort);
|
|
1000
|
+
const reasoningEffort = this.readString(effortObj.reasoningEffort)
|
|
1001
|
+
?? this.readString(effortObj.reasoning_effort);
|
|
1002
|
+
if (!reasoningEffort)
|
|
1003
|
+
return undefined;
|
|
1004
|
+
const description = this.readString(effortObj.description);
|
|
1005
|
+
return {
|
|
1006
|
+
reasoningEffort,
|
|
1007
|
+
...(description ? { description } : {}),
|
|
1008
|
+
};
|
|
1009
|
+
})
|
|
1010
|
+
.filter((effort) => Boolean(effort))
|
|
1011
|
+
: [];
|
|
1012
|
+
const defaultReasoningEffort = this.readString(obj.defaultReasoningEffort)
|
|
1013
|
+
?? this.readString(obj.default_reasoning_effort);
|
|
1014
|
+
const additionalSpeedTiers = Array.isArray(obj.additionalSpeedTiers)
|
|
1015
|
+
? obj.additionalSpeedTiers.filter((tier) => typeof tier === "string" && tier.length > 0)
|
|
1016
|
+
: [];
|
|
1047
1017
|
return {
|
|
1048
1018
|
id: this.readString(obj.id) ?? model,
|
|
1049
1019
|
model,
|
|
1050
1020
|
displayName,
|
|
1051
1021
|
description: this.readString(obj.description) ?? "",
|
|
1052
1022
|
isDefault: Boolean(obj.isDefault ?? obj.is_default),
|
|
1023
|
+
...(defaultReasoningEffort ? { defaultReasoningEffort } : {}),
|
|
1024
|
+
supportedReasoningEfforts,
|
|
1025
|
+
additionalSpeedTiers,
|
|
1053
1026
|
};
|
|
1054
1027
|
})
|
|
1055
1028
|
.filter((value) => Boolean(value));
|
|
1056
1029
|
}
|
|
1030
|
+
async fetchModelById(modelId) {
|
|
1031
|
+
const items = await this.fetchModels();
|
|
1032
|
+
if (!modelId) {
|
|
1033
|
+
return items.find((item) => item.isDefault) ?? items[0];
|
|
1034
|
+
}
|
|
1035
|
+
return items.find((item) => item.model === modelId || item.id === modelId)
|
|
1036
|
+
?? items.find((item) => item.isDefault)
|
|
1037
|
+
?? items[0];
|
|
1038
|
+
}
|
|
1057
1039
|
async resolveModelId(model) {
|
|
1058
1040
|
if (model) {
|
|
1059
1041
|
return model.providerID === "codex" ? model.modelID : `${model.providerID}/${model.modelID}`;
|
package/dist/ai/index.d.ts
CHANGED
|
@@ -14,24 +14,6 @@ export declare class AiManager {
|
|
|
14
14
|
backend: AiBackend;
|
|
15
15
|
}>;
|
|
16
16
|
}>;
|
|
17
|
-
syncState(sessionIds?: Partial<Record<AiBackend, string[]>>): Promise<{
|
|
18
|
-
sessions: Array<Record<string, unknown> & {
|
|
19
|
-
backend: AiBackend;
|
|
20
|
-
}>;
|
|
21
|
-
statuses: Array<Record<string, unknown> & {
|
|
22
|
-
backend: AiBackend;
|
|
23
|
-
}>;
|
|
24
|
-
messages: Record<string, unknown>;
|
|
25
|
-
pendingPermissions: Array<Record<string, unknown> & {
|
|
26
|
-
backend: AiBackend;
|
|
27
|
-
}>;
|
|
28
|
-
pendingQuestions: Array<Record<string, unknown> & {
|
|
29
|
-
backend: AiBackend;
|
|
30
|
-
}>;
|
|
31
|
-
statusAuthoritativeByBackend: Partial<Record<AiBackend, boolean>>;
|
|
32
|
-
syncedBackends: AiBackend[];
|
|
33
|
-
generatedAt: number;
|
|
34
|
-
}>;
|
|
35
17
|
createSession(backend: AiBackend, title?: string): Promise<{
|
|
36
18
|
session: import("./interface.js").SessionInfo;
|
|
37
19
|
}>;
|
package/dist/ai/index.js
CHANGED
|
@@ -68,51 +68,6 @@ export class AiManager {
|
|
|
68
68
|
const sessions = results.flatMap((r) => (r.status === "fulfilled" ? r.value : []));
|
|
69
69
|
return { sessions };
|
|
70
70
|
}
|
|
71
|
-
async syncState(sessionIds = {}) {
|
|
72
|
-
const results = await Promise.allSettled(this._available.map(async (backend) => {
|
|
73
|
-
const provider = this._providers[backend];
|
|
74
|
-
const state = provider.syncState
|
|
75
|
-
? await provider.syncState(sessionIds[backend])
|
|
76
|
-
: {
|
|
77
|
-
sessions: (await provider.listSessions()).sessions,
|
|
78
|
-
statuses: [],
|
|
79
|
-
messages: {},
|
|
80
|
-
generatedAt: Date.now(),
|
|
81
|
-
};
|
|
82
|
-
return { backend, state };
|
|
83
|
-
}));
|
|
84
|
-
const sessions = [];
|
|
85
|
-
const statuses = [];
|
|
86
|
-
const messages = {};
|
|
87
|
-
const pendingPermissions = [];
|
|
88
|
-
const pendingQuestions = [];
|
|
89
|
-
const statusAuthoritativeByBackend = {};
|
|
90
|
-
const syncedBackends = [];
|
|
91
|
-
for (const result of results) {
|
|
92
|
-
if (result.status !== "fulfilled")
|
|
93
|
-
continue;
|
|
94
|
-
const { backend, state } = result.value;
|
|
95
|
-
syncedBackends.push(backend);
|
|
96
|
-
statusAuthoritativeByBackend[backend] = state.statusAuthoritative !== false;
|
|
97
|
-
sessions.push(...(state.sessions ?? []).map((session) => ({ ...session, backend })));
|
|
98
|
-
statuses.push(...(state.statuses ?? []).map((status) => ({ ...status, backend })));
|
|
99
|
-
for (const [sessionId, value] of Object.entries(state.messages ?? {})) {
|
|
100
|
-
messages[`${backend}:${sessionId}`] = value;
|
|
101
|
-
}
|
|
102
|
-
pendingPermissions.push(...(state.pendingPermissions ?? []).map((permission) => ({ ...permission, backend })));
|
|
103
|
-
pendingQuestions.push(...(state.pendingQuestions ?? []).map((question) => ({ ...question, backend })));
|
|
104
|
-
}
|
|
105
|
-
return {
|
|
106
|
-
sessions,
|
|
107
|
-
statuses,
|
|
108
|
-
messages,
|
|
109
|
-
pendingPermissions,
|
|
110
|
-
pendingQuestions,
|
|
111
|
-
statusAuthoritativeByBackend,
|
|
112
|
-
syncedBackends,
|
|
113
|
-
generatedAt: Date.now(),
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
71
|
// Session management — all require explicit backend
|
|
117
72
|
createSession(backend, title) { return this.get(backend).createSession(title); }
|
|
118
73
|
getSession(backend, id) { return this.get(backend).getSession(id); }
|
package/dist/ai/interface.d.ts
CHANGED
|
@@ -8,8 +8,8 @@ export interface ModelSelector {
|
|
|
8
8
|
modelID: string;
|
|
9
9
|
}
|
|
10
10
|
export interface CodexPromptOptions {
|
|
11
|
-
reasoningEffort?:
|
|
12
|
-
speed?:
|
|
11
|
+
reasoningEffort?: string;
|
|
12
|
+
speed?: string;
|
|
13
13
|
permissionMode?: "default" | "full-access";
|
|
14
14
|
}
|
|
15
15
|
export interface FileAttachment {
|
|
@@ -35,19 +35,6 @@ export interface ProviderInfo {
|
|
|
35
35
|
default: Record<string, string>;
|
|
36
36
|
[key: string]: unknown;
|
|
37
37
|
}
|
|
38
|
-
export interface AiSessionStatus {
|
|
39
|
-
sessionID: string;
|
|
40
|
-
status: Record<string, unknown> | string;
|
|
41
|
-
}
|
|
42
|
-
export interface AiSyncState {
|
|
43
|
-
sessions: unknown[];
|
|
44
|
-
statuses: AiSessionStatus[];
|
|
45
|
-
messages: Record<string, MessageInfo[]>;
|
|
46
|
-
pendingPermissions?: Record<string, unknown>[];
|
|
47
|
-
pendingQuestions?: Record<string, unknown>[];
|
|
48
|
-
statusAuthoritative?: boolean;
|
|
49
|
-
generatedAt: number;
|
|
50
|
-
}
|
|
51
38
|
/**
|
|
52
39
|
* Every AI backend (OpenCode, Codex, …) implements this interface.
|
|
53
40
|
* Method names map 1-to-1 with the "ai" namespace actions in index.ts.
|
|
@@ -80,7 +67,6 @@ export interface AIProvider {
|
|
|
80
67
|
getMessages(sessionId: string): Promise<{
|
|
81
68
|
messages: MessageInfo[];
|
|
82
69
|
}>;
|
|
83
|
-
syncState?(sessionIds?: string[]): Promise<AiSyncState>;
|
|
84
70
|
prompt(sessionId: string, text: string, model?: ModelSelector, agent?: string, files?: FileAttachment[], codexOptions?: CodexPromptOptions): Promise<{
|
|
85
71
|
ack: true;
|
|
86
72
|
}>;
|
package/dist/ai/opencode.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AIProvider, AiEventEmitter, CodexPromptOptions,
|
|
1
|
+
import type { AIProvider, AiEventEmitter, CodexPromptOptions, FileAttachment, ModelSelector, MessageInfo, ProviderInfo, SessionInfo, ShareInfo } from "./interface.js";
|
|
2
2
|
export declare class OpenCodeProvider implements AIProvider {
|
|
3
3
|
private client;
|
|
4
4
|
private server;
|
|
@@ -33,7 +33,6 @@ export declare class OpenCodeProvider implements AIProvider {
|
|
|
33
33
|
getMessages(sessionId: string): Promise<{
|
|
34
34
|
messages: MessageInfo[];
|
|
35
35
|
}>;
|
|
36
|
-
syncState(sessionIds?: string[]): Promise<AiSyncState>;
|
|
37
36
|
prompt(sessionId: string, text: string, model?: ModelSelector, agent?: string, files?: FileAttachment[], codexOptions?: CodexPromptOptions): Promise<{
|
|
38
37
|
ack: true;
|
|
39
38
|
}>;
|
|
@@ -58,9 +57,6 @@ export declare class OpenCodeProvider implements AIProvider {
|
|
|
58
57
|
private sendPromptAsync;
|
|
59
58
|
private reconcileOpenCodeState;
|
|
60
59
|
private refreshBusySessionMessages;
|
|
61
|
-
private fetchSessionStatuses;
|
|
62
|
-
private listPendingPermissions;
|
|
63
|
-
private listPendingQuestions;
|
|
64
60
|
private refreshSessionsMetadata;
|
|
65
61
|
private refreshPendingPermissions;
|
|
66
62
|
private refreshPendingQuestions;
|
package/dist/ai/opencode.js
CHANGED
|
@@ -102,10 +102,19 @@ function normalizeOpenCodePart(part) {
|
|
|
102
102
|
});
|
|
103
103
|
}
|
|
104
104
|
else if (status === "error") {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
105
|
+
if (metadata.interrupted === true) {
|
|
106
|
+
normalized.state = "completed";
|
|
107
|
+
normalized.interrupted = true;
|
|
108
|
+
const interruptedOutput = readString(metadata.output);
|
|
109
|
+
if (interruptedOutput)
|
|
110
|
+
normalized.output = interruptedOutput;
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
normalized.error = readString(state.error) ?? "Tool failed";
|
|
114
|
+
const errorMessage = readString(state.error);
|
|
115
|
+
if (errorMessage)
|
|
116
|
+
normalized.output = errorMessage;
|
|
117
|
+
}
|
|
109
118
|
}
|
|
110
119
|
const attachments = Array.isArray(state.attachments) ? state.attachments : [];
|
|
111
120
|
if (attachments.length > 0) {
|
|
@@ -393,57 +402,10 @@ export class OpenCodeProvider {
|
|
|
393
402
|
throw err;
|
|
394
403
|
}
|
|
395
404
|
}
|
|
396
|
-
async syncState(sessionIds = []) {
|
|
397
|
-
const [sessionsResult, statusesResult, permissionsResult, questionsResult] = await Promise.allSettled([
|
|
398
|
-
this.listSessions(),
|
|
399
|
-
this.fetchSessionStatuses(),
|
|
400
|
-
this.listPendingPermissions(),
|
|
401
|
-
this.listPendingQuestions(),
|
|
402
|
-
]);
|
|
403
|
-
const sessions = sessionsResult.status === "fulfilled"
|
|
404
|
-
? (sessionsResult.value.sessions ?? [])
|
|
405
|
-
: [];
|
|
406
|
-
const statuses = statusesResult.status === "fulfilled" ? statusesResult.value : [];
|
|
407
|
-
const pendingPermissions = permissionsResult.status === "fulfilled" ? permissionsResult.value : [];
|
|
408
|
-
const pendingQuestions = questionsResult.status === "fulfilled" ? questionsResult.value : [];
|
|
409
|
-
const messageSessionIds = new Set(sessionIds);
|
|
410
|
-
for (const entry of statuses) {
|
|
411
|
-
const statusObj = typeof entry.status === "object" && entry.status !== null ? entry.status : {};
|
|
412
|
-
const statusType = typeof statusObj.type === "string" ? statusObj.type.toLowerCase() : String(entry.status ?? "").toLowerCase();
|
|
413
|
-
if (statusType === "busy" || statusType === "running" || statusType === "working" || statusType === "retry") {
|
|
414
|
-
messageSessionIds.add(entry.sessionID);
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
for (const permission of pendingPermissions) {
|
|
418
|
-
const sessionID = this.readString(permission.sessionID) ?? this.readString(permission.sessionId);
|
|
419
|
-
if (sessionID)
|
|
420
|
-
messageSessionIds.add(sessionID);
|
|
421
|
-
}
|
|
422
|
-
for (const question of pendingQuestions) {
|
|
423
|
-
const sessionID = this.readString(question.sessionID) ?? this.readString(question.sessionId);
|
|
424
|
-
if (sessionID)
|
|
425
|
-
messageSessionIds.add(sessionID);
|
|
426
|
-
}
|
|
427
|
-
const messages = {};
|
|
428
|
-
await Promise.allSettled(Array.from(messageSessionIds).map(async (sessionId) => {
|
|
429
|
-
const response = await this.getMessages(sessionId);
|
|
430
|
-
messages[sessionId] = response.messages;
|
|
431
|
-
}));
|
|
432
|
-
return {
|
|
433
|
-
sessions,
|
|
434
|
-
statuses,
|
|
435
|
-
messages,
|
|
436
|
-
pendingPermissions,
|
|
437
|
-
pendingQuestions,
|
|
438
|
-
statusAuthoritative: statusesResult.status === "fulfilled",
|
|
439
|
-
generatedAt: Date.now(),
|
|
440
|
-
};
|
|
441
|
-
}
|
|
442
405
|
// -------------------------------------------------------------------------
|
|
443
406
|
// Interaction
|
|
444
407
|
// -------------------------------------------------------------------------
|
|
445
408
|
async prompt(sessionId, text, model, agent, files = [], codexOptions) {
|
|
446
|
-
void codexOptions;
|
|
447
409
|
if (sessionId)
|
|
448
410
|
this.lastActiveSessionId = sessionId;
|
|
449
411
|
if (VERBOSE_AI_LOGS) {
|
|
@@ -457,7 +419,7 @@ export class OpenCodeProvider {
|
|
|
457
419
|
// Fire-and-forget — results come back through the SSE event stream.
|
|
458
420
|
// Prefer the async prompt endpoint so long-running turns do not get tied
|
|
459
421
|
// to the request lifecycle the way the basic prompt route can be.
|
|
460
|
-
this.sendPromptAsync(sessionId, text, model, agent, files).catch((err) => {
|
|
422
|
+
this.sendPromptAsync(sessionId, text, model, agent, files, codexOptions).catch((err) => {
|
|
461
423
|
console.error("[ai] prompt error:", err.message);
|
|
462
424
|
this.emitter?.({
|
|
463
425
|
type: "prompt_error",
|
|
@@ -644,7 +606,7 @@ export class OpenCodeProvider {
|
|
|
644
606
|
}
|
|
645
607
|
}
|
|
646
608
|
}
|
|
647
|
-
async sendPromptAsync(sessionId, text, model, agent, files = []) {
|
|
609
|
+
async sendPromptAsync(sessionId, text, model, agent, files = [], promptOptions) {
|
|
648
610
|
const server = this.server;
|
|
649
611
|
const authHeader = this.authHeader;
|
|
650
612
|
if (!server || !authHeader) {
|
|
@@ -665,6 +627,7 @@ export class OpenCodeProvider {
|
|
|
665
627
|
],
|
|
666
628
|
...(model ? { model } : {}),
|
|
667
629
|
...(agent ? { agent } : {}),
|
|
630
|
+
...(promptOptions?.reasoningEffort ? { variant: promptOptions.reasoningEffort } : {}),
|
|
668
631
|
}),
|
|
669
632
|
});
|
|
670
633
|
if (!response.ok) {
|
|
@@ -736,43 +699,6 @@ export class OpenCodeProvider {
|
|
|
736
699
|
}
|
|
737
700
|
}
|
|
738
701
|
}
|
|
739
|
-
async fetchSessionStatuses() {
|
|
740
|
-
const payload = await this.fetchOpenCodeJson("/session/status", { method: "GET" });
|
|
741
|
-
if (!payload || typeof payload !== "object")
|
|
742
|
-
return [];
|
|
743
|
-
return Object.entries(payload).map(([sessionID, status]) => ({
|
|
744
|
-
sessionID,
|
|
745
|
-
status: status,
|
|
746
|
-
}));
|
|
747
|
-
}
|
|
748
|
-
async listPendingPermissions() {
|
|
749
|
-
const permissionApi = this.client?.permission;
|
|
750
|
-
if (!permissionApi?.list)
|
|
751
|
-
return [];
|
|
752
|
-
const response = await permissionApi.list();
|
|
753
|
-
const data = Array.isArray(response.data) ? response.data : [];
|
|
754
|
-
return data
|
|
755
|
-
.map((entry) => normalizePermissionProperties(this.asRecord(entry)))
|
|
756
|
-
.filter((entry) => !!this.readString(entry.id));
|
|
757
|
-
}
|
|
758
|
-
async listPendingQuestions() {
|
|
759
|
-
const data = await this.fetchOpenCodeJson("/question", { method: "GET" });
|
|
760
|
-
const questions = Array.isArray(data) ? data : [];
|
|
761
|
-
return questions
|
|
762
|
-
.flatMap((entry) => {
|
|
763
|
-
const question = this.asRecord(entry);
|
|
764
|
-
const id = this.readString(question.id);
|
|
765
|
-
const sessionID = this.readString(question.sessionID) ?? this.readString(question.sessionId);
|
|
766
|
-
if (!id || !sessionID)
|
|
767
|
-
return [];
|
|
768
|
-
return [{
|
|
769
|
-
id,
|
|
770
|
-
sessionID,
|
|
771
|
-
questions: Array.isArray(question.questions) ? question.questions : [],
|
|
772
|
-
tool: typeof question.tool === "object" && question.tool !== null ? question.tool : undefined,
|
|
773
|
-
}];
|
|
774
|
-
});
|
|
775
|
-
}
|
|
776
702
|
async refreshSessionsMetadata() {
|
|
777
703
|
const response = await this.client.session.list();
|
|
778
704
|
const sessions = Array.isArray(response.data) ? response.data : [];
|
package/dist/index.js
CHANGED
|
@@ -90,13 +90,10 @@ let aiManagerInitPromise = null;
|
|
|
90
90
|
// Proxy tunnel management
|
|
91
91
|
let currentSessionCode = null;
|
|
92
92
|
let currentSessionPassword = null;
|
|
93
|
-
let currentManagerSessionId = null;
|
|
94
93
|
let currentPrimaryGateway = DEFAULT_PROXY_URL;
|
|
95
94
|
let activeGatewayUrl = DEFAULT_PROXY_URL;
|
|
96
|
-
let appPeerConnected = false;
|
|
97
95
|
let shuttingDown = false;
|
|
98
96
|
let activeV2Transport = null;
|
|
99
|
-
const runningAiSessions = new Set();
|
|
100
97
|
const trackedEditorFiles = new Map();
|
|
101
98
|
const trackedEditorDirectories = new Map();
|
|
102
99
|
const pendingTrackedFileChecks = new Set();
|
|
@@ -305,21 +302,7 @@ async function readCliConfig() {
|
|
|
305
302
|
rootDir: entry.rootDir,
|
|
306
303
|
sessionCode: typeof entry.sessionCode === "string" ? entry.sessionCode : null,
|
|
307
304
|
sessionPassword: entry.sessionPassword,
|
|
308
|
-
managerSessionId: typeof entry.managerSessionId === "string" ? entry.managerSessionId : null,
|
|
309
305
|
savedAt: entry.savedAt,
|
|
310
|
-
pushDevices: Array.isArray(entry.pushDevices)
|
|
311
|
-
? entry.pushDevices.filter((device) => (!!device
|
|
312
|
-
&& typeof device.phoneId === "string"
|
|
313
|
-
&& typeof device.notificationsEnabled === "boolean"
|
|
314
|
-
&& typeof device.updatedAt === "number"
|
|
315
|
-
&& (typeof device.expoPushToken === "string" || device.expoPushToken === null))).map((device) => ({
|
|
316
|
-
phoneId: device.phoneId,
|
|
317
|
-
expoPushToken: device.expoPushToken,
|
|
318
|
-
notificationsEnabled: device.notificationsEnabled,
|
|
319
|
-
platform: typeof device.platform === "string" ? device.platform : null,
|
|
320
|
-
updatedAt: device.updatedAt,
|
|
321
|
-
}))
|
|
322
|
-
: [],
|
|
323
306
|
}))
|
|
324
307
|
: [],
|
|
325
308
|
};
|
|
@@ -334,9 +317,7 @@ async function readCliConfig() {
|
|
|
334
317
|
}
|
|
335
318
|
async function writeCliConfig(config) {
|
|
336
319
|
await fs.mkdir(path.dirname(CLI_CONFIG_PATH), { recursive: true });
|
|
337
|
-
|
|
338
|
-
await fs.writeFile(tmpPath, JSON.stringify(config, null, 2), "utf-8");
|
|
339
|
-
await fs.rename(tmpPath, CLI_CONFIG_PATH);
|
|
320
|
+
await fs.writeFile(CLI_CONFIG_PATH, JSON.stringify(config, null, 2), "utf-8");
|
|
340
321
|
cliConfigPromise = Promise.resolve(config);
|
|
341
322
|
}
|
|
342
323
|
let cliConfigPromise = null;
|
|
@@ -350,17 +331,14 @@ function getSavedSessionForRoot(config, rootDir) {
|
|
|
350
331
|
const sessions = Array.isArray(config.sessions) ? config.sessions : [];
|
|
351
332
|
return sessions.find((entry) => entry.rootDir === rootDir) || null;
|
|
352
333
|
}
|
|
353
|
-
async function saveSessionForRoot(sessionCode, sessionPassword
|
|
334
|
+
async function saveSessionForRoot(sessionCode, sessionPassword) {
|
|
354
335
|
const config = await getCliConfig();
|
|
355
336
|
const sessions = Array.isArray(config.sessions) ? [...config.sessions] : [];
|
|
356
|
-
const previous = sessions.find((entry) => entry.rootDir === ROOT_DIR);
|
|
357
337
|
const nextEntry = {
|
|
358
338
|
rootDir: ROOT_DIR,
|
|
359
339
|
sessionCode,
|
|
360
340
|
sessionPassword,
|
|
361
|
-
managerSessionId,
|
|
362
341
|
savedAt: Date.now(),
|
|
363
|
-
pushDevices: previous?.pushDevices ?? [],
|
|
364
342
|
};
|
|
365
343
|
const deduped = sessions.filter((entry) => entry.rootDir !== ROOT_DIR);
|
|
366
344
|
deduped.unshift(nextEntry);
|
|
@@ -369,192 +347,6 @@ async function saveSessionForRoot(sessionCode, sessionPassword, managerSessionId
|
|
|
369
347
|
sessions: deduped.slice(0, 100),
|
|
370
348
|
});
|
|
371
349
|
}
|
|
372
|
-
async function savePushDeviceForCurrentSession(payload) {
|
|
373
|
-
if (!currentSessionPassword) {
|
|
374
|
-
throw Object.assign(new Error("No active session"), { code: "EUNAVAILABLE" });
|
|
375
|
-
}
|
|
376
|
-
const phoneId = typeof payload.phoneId === "string" ? payload.phoneId.trim() : "";
|
|
377
|
-
if (!phoneId) {
|
|
378
|
-
throw Object.assign(new Error("phoneId is required"), { code: "EINVAL" });
|
|
379
|
-
}
|
|
380
|
-
const expoPushToken = typeof payload.expoPushToken === "string" && payload.expoPushToken.trim()
|
|
381
|
-
? payload.expoPushToken.trim()
|
|
382
|
-
: null;
|
|
383
|
-
const notificationsEnabled = payload.notificationsEnabled === true && Boolean(expoPushToken);
|
|
384
|
-
const platform = typeof payload.platform === "string" && payload.platform.trim()
|
|
385
|
-
? payload.platform.trim()
|
|
386
|
-
: null;
|
|
387
|
-
const config = await getCliConfig();
|
|
388
|
-
const sessions = Array.isArray(config.sessions) ? [...config.sessions] : [];
|
|
389
|
-
const now = Date.now();
|
|
390
|
-
const currentEntry = sessions.find((entry) => entry.rootDir === ROOT_DIR) ?? {
|
|
391
|
-
rootDir: ROOT_DIR,
|
|
392
|
-
sessionCode: currentSessionCode,
|
|
393
|
-
sessionPassword: currentSessionPassword,
|
|
394
|
-
managerSessionId: currentManagerSessionId,
|
|
395
|
-
savedAt: now,
|
|
396
|
-
pushDevices: [],
|
|
397
|
-
};
|
|
398
|
-
const nextDevices = (currentEntry.pushDevices ?? []).filter((device) => device.phoneId !== phoneId);
|
|
399
|
-
nextDevices.unshift({
|
|
400
|
-
phoneId,
|
|
401
|
-
expoPushToken,
|
|
402
|
-
notificationsEnabled,
|
|
403
|
-
platform,
|
|
404
|
-
updatedAt: now,
|
|
405
|
-
});
|
|
406
|
-
const nextEntry = {
|
|
407
|
-
...currentEntry,
|
|
408
|
-
sessionCode: currentSessionCode,
|
|
409
|
-
sessionPassword: currentSessionPassword,
|
|
410
|
-
managerSessionId: currentManagerSessionId,
|
|
411
|
-
savedAt: now,
|
|
412
|
-
pushDevices: nextDevices.slice(0, 10),
|
|
413
|
-
};
|
|
414
|
-
const deduped = sessions.filter((entry) => entry.rootDir !== ROOT_DIR);
|
|
415
|
-
deduped.unshift(nextEntry);
|
|
416
|
-
await writeCliConfig({
|
|
417
|
-
...config,
|
|
418
|
-
sessions: deduped.slice(0, 100),
|
|
419
|
-
});
|
|
420
|
-
return { ok: true, notificationsEnabled, tokenStored: Boolean(expoPushToken) };
|
|
421
|
-
}
|
|
422
|
-
function readAiEventSessionId(event) {
|
|
423
|
-
const properties = event.properties || {};
|
|
424
|
-
const info = properties.info && typeof properties.info === "object" ? properties.info : {};
|
|
425
|
-
return ((typeof properties.sessionID === "string" && properties.sessionID)
|
|
426
|
-
|| (typeof properties.sessionId === "string" && properties.sessionId)
|
|
427
|
-
|| (typeof info.sessionID === "string" && info.sessionID)
|
|
428
|
-
|| (typeof info.sessionId === "string" && info.sessionId)
|
|
429
|
-
|| (typeof info.id === "string" && info.id)
|
|
430
|
-
|| null);
|
|
431
|
-
}
|
|
432
|
-
function readAiStatusType(status) {
|
|
433
|
-
if (typeof status === "string")
|
|
434
|
-
return status.toLowerCase();
|
|
435
|
-
if (status && typeof status === "object") {
|
|
436
|
-
const value = status.type;
|
|
437
|
-
if (typeof value === "string")
|
|
438
|
-
return value.toLowerCase();
|
|
439
|
-
}
|
|
440
|
-
return "";
|
|
441
|
-
}
|
|
442
|
-
function isRunningAiStatus(status) {
|
|
443
|
-
const value = readAiStatusType(status);
|
|
444
|
-
return value === "running" || value === "busy" || value === "working" || value === "processing" || value === "retry";
|
|
445
|
-
}
|
|
446
|
-
function isTerminalAiStatus(status) {
|
|
447
|
-
const value = readAiStatusType(status);
|
|
448
|
-
return (value === "idle"
|
|
449
|
-
|| value === "complete"
|
|
450
|
-
|| value === "completed"
|
|
451
|
-
|| value === "done"
|
|
452
|
-
|| value === "finished"
|
|
453
|
-
|| value === "error"
|
|
454
|
-
|| value === "failed"
|
|
455
|
-
|| value === "cancelled"
|
|
456
|
-
|| value === "canceled");
|
|
457
|
-
}
|
|
458
|
-
async function getCurrentNotificationDevices() {
|
|
459
|
-
const config = await getCliConfig();
|
|
460
|
-
const saved = getSavedSessionForRoot(config, ROOT_DIR);
|
|
461
|
-
if (!saved || saved.sessionPassword !== currentSessionPassword)
|
|
462
|
-
return [];
|
|
463
|
-
return (saved.pushDevices ?? []).filter((device) => (device.notificationsEnabled
|
|
464
|
-
&& typeof device.expoPushToken === "string"
|
|
465
|
-
&& device.expoPushToken.length > 0));
|
|
466
|
-
}
|
|
467
|
-
async function clearInvalidNotificationDevices(phoneIds) {
|
|
468
|
-
if (phoneIds.length === 0)
|
|
469
|
-
return;
|
|
470
|
-
const invalidPhoneIds = new Set(phoneIds);
|
|
471
|
-
const config = await getCliConfig();
|
|
472
|
-
const sessions = Array.isArray(config.sessions) ? [...config.sessions] : [];
|
|
473
|
-
const saved = getSavedSessionForRoot(config, ROOT_DIR);
|
|
474
|
-
if (!saved?.pushDevices?.length)
|
|
475
|
-
return;
|
|
476
|
-
const nextEntry = {
|
|
477
|
-
...saved,
|
|
478
|
-
pushDevices: saved.pushDevices.map((device) => (invalidPhoneIds.has(device.phoneId)
|
|
479
|
-
? { ...device, expoPushToken: null, notificationsEnabled: false, updatedAt: Date.now() }
|
|
480
|
-
: device)),
|
|
481
|
-
};
|
|
482
|
-
const deduped = sessions.filter((entry) => entry.rootDir !== ROOT_DIR);
|
|
483
|
-
deduped.unshift(nextEntry);
|
|
484
|
-
await writeCliConfig({
|
|
485
|
-
...config,
|
|
486
|
-
sessions: deduped.slice(0, 100),
|
|
487
|
-
});
|
|
488
|
-
}
|
|
489
|
-
async function notifyManagerAiCompletion(backend, aiSessionId) {
|
|
490
|
-
if (appPeerConnected)
|
|
491
|
-
return;
|
|
492
|
-
if (!currentManagerSessionId || !currentSessionPassword)
|
|
493
|
-
return;
|
|
494
|
-
const devices = await getCurrentNotificationDevices();
|
|
495
|
-
if (devices.length === 0)
|
|
496
|
-
return;
|
|
497
|
-
const response = await fetch(new URL("/v1/notifications/ai-complete", MANAGER_URL), {
|
|
498
|
-
method: "POST",
|
|
499
|
-
headers: { "Content-Type": "application/json" },
|
|
500
|
-
signal: AbortSignal.timeout(10_000),
|
|
501
|
-
body: JSON.stringify({
|
|
502
|
-
sessionId: currentManagerSessionId,
|
|
503
|
-
resumeToken: currentSessionPassword,
|
|
504
|
-
backend,
|
|
505
|
-
aiSessionId,
|
|
506
|
-
devices: devices.map((device) => ({
|
|
507
|
-
phoneId: device.phoneId,
|
|
508
|
-
expoPushToken: device.expoPushToken,
|
|
509
|
-
platform: device.platform,
|
|
510
|
-
})),
|
|
511
|
-
}),
|
|
512
|
-
});
|
|
513
|
-
if (!response.ok) {
|
|
514
|
-
if (DEBUG_MODE) {
|
|
515
|
-
console.warn(`[notifications] manager notify failed: ${response.status}`);
|
|
516
|
-
}
|
|
517
|
-
return;
|
|
518
|
-
}
|
|
519
|
-
const body = await response.json().catch(() => ({}));
|
|
520
|
-
const invalidPhoneIds = Array.isArray(body.invalidPhoneIds)
|
|
521
|
-
? body.invalidPhoneIds.filter((value) => typeof value === "string")
|
|
522
|
-
: [];
|
|
523
|
-
if (invalidPhoneIds.length > 0) {
|
|
524
|
-
await clearInvalidNotificationDevices(invalidPhoneIds);
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
function handleAiNotificationEvent(backend, event) {
|
|
528
|
-
const sessionId = readAiEventSessionId(event);
|
|
529
|
-
if (!sessionId)
|
|
530
|
-
return;
|
|
531
|
-
const key = `${backend}:${sessionId}`;
|
|
532
|
-
if (event.type === "session.status") {
|
|
533
|
-
if (isRunningAiStatus(event.properties.status)) {
|
|
534
|
-
runningAiSessions.add(key);
|
|
535
|
-
return;
|
|
536
|
-
}
|
|
537
|
-
if (!isTerminalAiStatus(event.properties.status))
|
|
538
|
-
return;
|
|
539
|
-
if (!runningAiSessions.delete(key))
|
|
540
|
-
return;
|
|
541
|
-
void notifyManagerAiCompletion(backend, sessionId).catch((error) => {
|
|
542
|
-
if (DEBUG_MODE) {
|
|
543
|
-
console.warn("[notifications] failed to notify manager:", error instanceof Error ? error.message : String(error));
|
|
544
|
-
}
|
|
545
|
-
});
|
|
546
|
-
return;
|
|
547
|
-
}
|
|
548
|
-
if (event.type !== "session.idle")
|
|
549
|
-
return;
|
|
550
|
-
if (!runningAiSessions.delete(key))
|
|
551
|
-
return;
|
|
552
|
-
void notifyManagerAiCompletion(backend, sessionId).catch((error) => {
|
|
553
|
-
if (DEBUG_MODE) {
|
|
554
|
-
console.warn("[notifications] failed to notify manager:", error instanceof Error ? error.message : String(error));
|
|
555
|
-
}
|
|
556
|
-
});
|
|
557
|
-
}
|
|
558
350
|
async function clearSavedSessionForRoot() {
|
|
559
351
|
const config = await getCliConfig();
|
|
560
352
|
const sessions = Array.isArray(config.sessions) ? config.sessions : [];
|
|
@@ -1741,7 +1533,6 @@ function handleSystemCapabilities() {
|
|
|
1741
1533
|
platform: os.platform(),
|
|
1742
1534
|
rootDir: ROOT_DIR,
|
|
1743
1535
|
hostname: os.hostname(),
|
|
1744
|
-
managerSessionId: currentManagerSessionId,
|
|
1745
1536
|
};
|
|
1746
1537
|
}
|
|
1747
1538
|
function handleSystemPing() {
|
|
@@ -2715,9 +2506,6 @@ async function processMessage(message) {
|
|
|
2715
2506
|
case "ping":
|
|
2716
2507
|
result = handleSystemPing();
|
|
2717
2508
|
break;
|
|
2718
|
-
case "setPushToken":
|
|
2719
|
-
result = await savePushDeviceForCurrentSession(payload);
|
|
2720
|
-
break;
|
|
2721
2509
|
case "pairDevice": {
|
|
2722
2510
|
throw Object.assign(new Error("pairDevice is no longer supported"), { code: "EINVAL" });
|
|
2723
2511
|
}
|
|
@@ -2928,14 +2716,6 @@ async function processMessage(message) {
|
|
|
2928
2716
|
case "listSessions":
|
|
2929
2717
|
result = await aiManager.listAllSessions();
|
|
2930
2718
|
break;
|
|
2931
|
-
case "syncState": {
|
|
2932
|
-
const rawSessionIds = payload.sessionIds;
|
|
2933
|
-
result = await aiManager.syncState({
|
|
2934
|
-
opencode: Array.isArray(rawSessionIds?.opencode) ? rawSessionIds.opencode.filter((id) => typeof id === "string") : undefined,
|
|
2935
|
-
codex: Array.isArray(rawSessionIds?.codex) ? rawSessionIds.codex.filter((id) => typeof id === "string") : undefined,
|
|
2936
|
-
});
|
|
2937
|
-
break;
|
|
2938
|
-
}
|
|
2939
2719
|
case "getSession":
|
|
2940
2720
|
result = await aiManager.getSession(backend, payload.id);
|
|
2941
2721
|
break;
|
|
@@ -3107,11 +2887,7 @@ async function assembleWithCode(code) {
|
|
|
3107
2887
|
return;
|
|
3108
2888
|
settled = true;
|
|
3109
2889
|
ws.send(JSON.stringify({ type: "ack" }));
|
|
3110
|
-
resolve({
|
|
3111
|
-
code: parsed.code,
|
|
3112
|
-
password: parsed.password,
|
|
3113
|
-
sessionId: typeof parsed.sessionId === "string" ? parsed.sessionId : null,
|
|
3114
|
-
});
|
|
2890
|
+
resolve({ code: parsed.code, password: parsed.password });
|
|
3115
2891
|
}
|
|
3116
2892
|
catch (error) {
|
|
3117
2893
|
fail(error instanceof Error ? error : new Error(String(error)));
|
|
@@ -3373,7 +3149,6 @@ function startAiManagerInBackground() {
|
|
|
3373
3149
|
}
|
|
3374
3150
|
aiManager = manager;
|
|
3375
3151
|
aiManager.subscribe((backend, event) => {
|
|
3376
|
-
handleAiNotificationEvent(backend, event);
|
|
3377
3152
|
emitAppEvent({
|
|
3378
3153
|
v: 1,
|
|
3379
3154
|
id: `evt-${Date.now()}`,
|
|
@@ -3413,19 +3188,16 @@ async function connectWebSocketV2() {
|
|
|
3413
3188
|
if (message.type === "connected")
|
|
3414
3189
|
return;
|
|
3415
3190
|
if (message.type === "peer_connected") {
|
|
3416
|
-
appPeerConnected = true;
|
|
3417
3191
|
console.log("App connected!\n");
|
|
3418
3192
|
void publishDiscoveredPorts(true);
|
|
3419
3193
|
return;
|
|
3420
3194
|
}
|
|
3421
3195
|
if (message.type === "peer_disconnected") {
|
|
3422
|
-
appPeerConnected = false;
|
|
3423
3196
|
console.log("App disconnected. Waiting for reconnect window.\n");
|
|
3424
3197
|
stopPortSync();
|
|
3425
3198
|
return;
|
|
3426
3199
|
}
|
|
3427
3200
|
if (message.type === "app_disconnected") {
|
|
3428
|
-
appPeerConnected = false;
|
|
3429
3201
|
if (message.reconnectDeadline) {
|
|
3430
3202
|
console.log(`[session] app disconnected, waiting until ${new Date(message.reconnectDeadline).toISOString()}`);
|
|
3431
3203
|
}
|
|
@@ -3530,7 +3302,6 @@ async function main() {
|
|
|
3530
3302
|
displaySavedSessionNotice();
|
|
3531
3303
|
sessionCodeToUse = savedSession.sessionCode;
|
|
3532
3304
|
sessionPasswordToUse = savedSession.sessionPassword;
|
|
3533
|
-
currentManagerSessionId = savedSession.managerSessionId ?? null;
|
|
3534
3305
|
usedSavedSession = true;
|
|
3535
3306
|
}
|
|
3536
3307
|
else {
|
|
@@ -3544,8 +3315,7 @@ async function main() {
|
|
|
3544
3315
|
const assembled = await assembleWithCode(qr.code);
|
|
3545
3316
|
sessionCodeToUse = assembled.code;
|
|
3546
3317
|
sessionPasswordToUse = assembled.password;
|
|
3547
|
-
|
|
3548
|
-
await saveSessionForRoot(sessionCodeToUse, sessionPasswordToUse, currentManagerSessionId);
|
|
3318
|
+
await saveSessionForRoot(sessionCodeToUse, sessionPasswordToUse);
|
|
3549
3319
|
}
|
|
3550
3320
|
currentSessionCode = sessionCodeToUse;
|
|
3551
3321
|
currentSessionPassword = sessionPasswordToUse;
|