lunel-cli 0.1.59 → 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.
@@ -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 () => {
@@ -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
@@ -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>>;
@@ -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>>;
@@ -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",
@@ -333,7 +333,7 @@ export class OpenCodeProvider {
333
333
  }
334
334
  }
335
335
  }
336
- async sendPromptAsync(sessionId, text, model, agent) {
336
+ async sendPromptAsync(sessionId, text, model, agent, files = []) {
337
337
  const server = this.server;
338
338
  const authHeader = this.authHeader;
339
339
  if (!server || !authHeader) {
@@ -348,7 +348,10 @@ export class OpenCodeProvider {
348
348
  accept: "application/json",
349
349
  },
350
350
  body: JSON.stringify({
351
- parts: [{ type: "text", text }],
351
+ parts: [
352
+ ...(text.trim().length > 0 ? [{ type: "text", text }] : []),
353
+ ...files,
354
+ ],
352
355
  ...(model ? { model } : {}),
353
356
  ...(agent ? { agent } : {}),
354
357
  }),
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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lunel-cli",
3
- "version": "0.1.59",
3
+ "version": "0.1.60",
4
4
  "author": [
5
5
  {
6
6
  "name": "Soham Bharambe",