lunel-cli 0.1.58 → 0.1.60
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 +4 -1
- package/dist/ai/index.d.ts +2 -2
- package/dist/ai/index.js +2 -2
- package/dist/ai/interface.d.ts +7 -1
- package/dist/ai/opencode.d.ts +3 -2
- package/dist/ai/opencode.js +48 -21
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/ai/codex.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AIProvider, AiEventEmitter, ModelSelector, MessageInfo, ProviderInfo, SessionInfo, ShareInfo } from "./interface.js";
|
|
1
|
+
import type { AIProvider, AiEventEmitter, 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;
|
|
@@ -25,7 +25,7 @@ export declare class CodexProvider implements AIProvider {
|
|
|
25
25
|
getMessages(sessionId: string): Promise<{
|
|
26
26
|
messages: MessageInfo[];
|
|
27
27
|
}>;
|
|
28
|
-
prompt(sessionId: string, text: string, model?: ModelSelector, agent?: string): Promise<{
|
|
28
|
+
prompt(sessionId: string, text: string, model?: ModelSelector, agent?: string, files?: FileAttachment[]): Promise<{
|
|
29
29
|
ack: true;
|
|
30
30
|
}>;
|
|
31
31
|
abort(sessionId: string): Promise<Record<string, never>>;
|
package/dist/ai/codex.js
CHANGED
|
@@ -120,7 +120,10 @@ export class CodexProvider {
|
|
|
120
120
|
});
|
|
121
121
|
return { messages: session.messages };
|
|
122
122
|
}
|
|
123
|
-
async prompt(sessionId, text, model, agent) {
|
|
123
|
+
async prompt(sessionId, text, model, agent, files = []) {
|
|
124
|
+
if (files.length > 0) {
|
|
125
|
+
throw new Error("Codex image attachments are not supported in Lunel yet");
|
|
126
|
+
}
|
|
124
127
|
const session = this.ensureLocalSession(sessionId);
|
|
125
128
|
session.updatedAt = Date.now();
|
|
126
129
|
(async () => {
|
package/dist/ai/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AiEvent, ModelSelector } from "./interface.js";
|
|
1
|
+
import type { AiEvent, ModelSelector, FileAttachment } from "./interface.js";
|
|
2
2
|
export type AiBackend = "opencode" | "codex";
|
|
3
3
|
export declare class AiManager {
|
|
4
4
|
private _providers;
|
|
@@ -24,7 +24,7 @@ export declare class AiManager {
|
|
|
24
24
|
getMessages(backend: AiBackend, sessionId: string): Promise<{
|
|
25
25
|
messages: import("./interface.js").MessageInfo[];
|
|
26
26
|
}>;
|
|
27
|
-
prompt(backend: AiBackend, sessionId: string, text: string, model?: ModelSelector, agent?: string): Promise<{
|
|
27
|
+
prompt(backend: AiBackend, sessionId: string, text: string, model?: ModelSelector, agent?: string, files?: FileAttachment[]): Promise<{
|
|
28
28
|
ack: true;
|
|
29
29
|
}>;
|
|
30
30
|
abort(backend: AiBackend, sessionId: string): Promise<Record<string, never>>;
|
package/dist/ai/index.js
CHANGED
|
@@ -67,9 +67,9 @@ export class AiManager {
|
|
|
67
67
|
getSession(backend, id) { return this.get(backend).getSession(id); }
|
|
68
68
|
deleteSession(backend, id) { return this.get(backend).deleteSession(id); }
|
|
69
69
|
getMessages(backend, sessionId) { return this.get(backend).getMessages(sessionId); }
|
|
70
|
-
prompt(backend, sessionId, text, model, agent) {
|
|
70
|
+
prompt(backend, sessionId, text, model, agent, files) {
|
|
71
71
|
this.get(backend).setActiveSession?.(sessionId);
|
|
72
|
-
return this.get(backend).prompt(sessionId, text, model, agent);
|
|
72
|
+
return this.get(backend).prompt(sessionId, text, model, agent, files);
|
|
73
73
|
}
|
|
74
74
|
abort(backend, sessionId) { return this.get(backend).abort(sessionId); }
|
|
75
75
|
// Metadata — backend is optional, falls back to first available
|
package/dist/ai/interface.d.ts
CHANGED
|
@@ -7,6 +7,12 @@ export interface ModelSelector {
|
|
|
7
7
|
providerID: string;
|
|
8
8
|
modelID: string;
|
|
9
9
|
}
|
|
10
|
+
export interface FileAttachment {
|
|
11
|
+
type: "file";
|
|
12
|
+
mime: string;
|
|
13
|
+
filename?: string;
|
|
14
|
+
url: string;
|
|
15
|
+
}
|
|
10
16
|
export interface MessageInfo {
|
|
11
17
|
id: string;
|
|
12
18
|
role: string;
|
|
@@ -51,7 +57,7 @@ export interface AIProvider {
|
|
|
51
57
|
getMessages(sessionId: string): Promise<{
|
|
52
58
|
messages: MessageInfo[];
|
|
53
59
|
}>;
|
|
54
|
-
prompt(sessionId: string, text: string, model?: ModelSelector, agent?: string): Promise<{
|
|
60
|
+
prompt(sessionId: string, text: string, model?: ModelSelector, agent?: string, files?: FileAttachment[]): Promise<{
|
|
55
61
|
ack: true;
|
|
56
62
|
}>;
|
|
57
63
|
abort(sessionId: string): Promise<Record<string, never>>;
|
package/dist/ai/opencode.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AIProvider, AiEventEmitter, ModelSelector, MessageInfo, ProviderInfo, SessionInfo, ShareInfo } from "./interface.js";
|
|
1
|
+
import type { AIProvider, AiEventEmitter, 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;
|
|
@@ -25,7 +25,7 @@ export declare class OpenCodeProvider implements AIProvider {
|
|
|
25
25
|
getMessages(sessionId: string): Promise<{
|
|
26
26
|
messages: MessageInfo[];
|
|
27
27
|
}>;
|
|
28
|
-
prompt(sessionId: string, text: string, model?: ModelSelector, agent?: string): Promise<{
|
|
28
|
+
prompt(sessionId: string, text: string, model?: ModelSelector, agent?: string, files?: FileAttachment[]): Promise<{
|
|
29
29
|
ack: true;
|
|
30
30
|
}>;
|
|
31
31
|
abort(sessionId: string): Promise<Record<string, never>>;
|
|
@@ -51,6 +51,7 @@ export declare class OpenCodeProvider implements AIProvider {
|
|
|
51
51
|
private refreshSessionsMetadata;
|
|
52
52
|
private refreshPendingPermissions;
|
|
53
53
|
private refreshPendingQuestions;
|
|
54
|
+
private fetchOpenCodeJson;
|
|
54
55
|
private refreshSessionStatuses;
|
|
55
56
|
private trackPermissionEvent;
|
|
56
57
|
private asRecord;
|
package/dist/ai/opencode.js
CHANGED
|
@@ -139,7 +139,7 @@ export class OpenCodeProvider {
|
|
|
139
139
|
// -------------------------------------------------------------------------
|
|
140
140
|
// Interaction
|
|
141
141
|
// -------------------------------------------------------------------------
|
|
142
|
-
async prompt(sessionId, text, model, agent) {
|
|
142
|
+
async prompt(sessionId, text, model, agent, files = []) {
|
|
143
143
|
if (sessionId)
|
|
144
144
|
this.lastActiveSessionId = sessionId;
|
|
145
145
|
if (VERBOSE_AI_LOGS) {
|
|
@@ -153,7 +153,7 @@ export class OpenCodeProvider {
|
|
|
153
153
|
// Fire-and-forget — results come back through the SSE event stream.
|
|
154
154
|
// Prefer the async prompt endpoint so long-running turns do not get tied
|
|
155
155
|
// to the request lifecycle the way the basic prompt route can be.
|
|
156
|
-
this.sendPromptAsync(sessionId, text, model, agent).catch((err) => {
|
|
156
|
+
this.sendPromptAsync(sessionId, text, model, agent, files).catch((err) => {
|
|
157
157
|
console.error("[ai] prompt error:", err.message);
|
|
158
158
|
this.emitter?.({
|
|
159
159
|
type: "prompt_error",
|
|
@@ -244,21 +244,18 @@ export class OpenCodeProvider {
|
|
|
244
244
|
return {};
|
|
245
245
|
}
|
|
246
246
|
async questionReply(sessionId, questionId, answers) {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
await questionApi.reply({ requestID: questionId, answers });
|
|
247
|
+
await this.fetchOpenCodeJson(`/question/${encodeURIComponent(questionId)}/reply`, {
|
|
248
|
+
method: "POST",
|
|
249
|
+
body: { answers },
|
|
250
|
+
});
|
|
252
251
|
this.knownPendingQuestionIds.delete(questionId);
|
|
253
252
|
this.emitter?.({ type: "question.replied", properties: { sessionID: sessionId, requestID: questionId, answers } });
|
|
254
253
|
return {};
|
|
255
254
|
}
|
|
256
255
|
async questionReject(sessionId, questionId) {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
await questionApi.reject({ requestID: questionId });
|
|
256
|
+
await this.fetchOpenCodeJson(`/question/${encodeURIComponent(questionId)}/reject`, {
|
|
257
|
+
method: "POST",
|
|
258
|
+
});
|
|
262
259
|
this.knownPendingQuestionIds.delete(questionId);
|
|
263
260
|
this.emitter?.({ type: "question.rejected", properties: { sessionID: sessionId, requestID: questionId } });
|
|
264
261
|
return {};
|
|
@@ -336,7 +333,7 @@ export class OpenCodeProvider {
|
|
|
336
333
|
}
|
|
337
334
|
}
|
|
338
335
|
}
|
|
339
|
-
async sendPromptAsync(sessionId, text, model, agent) {
|
|
336
|
+
async sendPromptAsync(sessionId, text, model, agent, files = []) {
|
|
340
337
|
const server = this.server;
|
|
341
338
|
const authHeader = this.authHeader;
|
|
342
339
|
if (!server || !authHeader) {
|
|
@@ -351,7 +348,10 @@ export class OpenCodeProvider {
|
|
|
351
348
|
accept: "application/json",
|
|
352
349
|
},
|
|
353
350
|
body: JSON.stringify({
|
|
354
|
-
parts: [
|
|
351
|
+
parts: [
|
|
352
|
+
...(text.trim().length > 0 ? [{ type: "text", text }] : []),
|
|
353
|
+
...files,
|
|
354
|
+
],
|
|
355
355
|
...(model ? { model } : {}),
|
|
356
356
|
...(agent ? { agent } : {}),
|
|
357
357
|
}),
|
|
@@ -433,14 +433,12 @@ export class OpenCodeProvider {
|
|
|
433
433
|
}
|
|
434
434
|
}
|
|
435
435
|
async refreshPendingQuestions() {
|
|
436
|
-
const
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
const response = await questionApi.list();
|
|
441
|
-
const data = Array.isArray(response.data) ? response.data : [];
|
|
436
|
+
const data = await this.fetchOpenCodeJson("/question", {
|
|
437
|
+
method: "GET",
|
|
438
|
+
});
|
|
439
|
+
const questions = Array.isArray(data) ? data : [];
|
|
442
440
|
const nextIds = new Set();
|
|
443
|
-
for (const entry of
|
|
441
|
+
for (const entry of questions) {
|
|
444
442
|
const question = this.asRecord(entry);
|
|
445
443
|
const id = this.readString(question.id);
|
|
446
444
|
const sessionID = this.readString(question.sessionID) ?? this.readString(question.sessionId);
|
|
@@ -467,6 +465,35 @@ export class OpenCodeProvider {
|
|
|
467
465
|
this.knownPendingQuestionIds.delete(id);
|
|
468
466
|
}
|
|
469
467
|
}
|
|
468
|
+
async fetchOpenCodeJson(pathname, options = {}) {
|
|
469
|
+
const server = this.server;
|
|
470
|
+
const authHeader = this.authHeader;
|
|
471
|
+
if (!server || !authHeader) {
|
|
472
|
+
throw new Error("OpenCode server is not ready");
|
|
473
|
+
}
|
|
474
|
+
const url = new URL(pathname, server.url);
|
|
475
|
+
const response = await fetch(url, {
|
|
476
|
+
method: options.method ?? "GET",
|
|
477
|
+
headers: {
|
|
478
|
+
Authorization: authHeader,
|
|
479
|
+
accept: "application/json",
|
|
480
|
+
...(options.body ? { "content-type": "application/json" } : {}),
|
|
481
|
+
},
|
|
482
|
+
...(options.body ? { body: JSON.stringify(options.body) } : {}),
|
|
483
|
+
});
|
|
484
|
+
if (!response.ok) {
|
|
485
|
+
let detail = "";
|
|
486
|
+
try {
|
|
487
|
+
detail = await response.text();
|
|
488
|
+
}
|
|
489
|
+
catch {
|
|
490
|
+
// ignore detail read failures
|
|
491
|
+
}
|
|
492
|
+
const suffix = detail.trim().length > 0 ? `: ${detail.trim()}` : "";
|
|
493
|
+
throw new Error(`OpenCode request failed (${response.status})${suffix}`);
|
|
494
|
+
}
|
|
495
|
+
return response.json().catch(() => null);
|
|
496
|
+
}
|
|
470
497
|
async refreshSessionStatuses() {
|
|
471
498
|
const server = this.server;
|
|
472
499
|
const authHeader = this.authHeader;
|
package/dist/index.js
CHANGED
|
@@ -2363,7 +2363,7 @@ async function processMessage(message) {
|
|
|
2363
2363
|
result = { backends: aiManager.availableBackends() };
|
|
2364
2364
|
break;
|
|
2365
2365
|
case "prompt":
|
|
2366
|
-
result = await aiManager.prompt(backend, payload.sessionId, payload.text, payload.model, payload.agent);
|
|
2366
|
+
result = await aiManager.prompt(backend, payload.sessionId, payload.text, payload.model, payload.agent, payload.files);
|
|
2367
2367
|
break;
|
|
2368
2368
|
case "createSession":
|
|
2369
2369
|
result = await aiManager.createSession(backend, payload.title);
|