lunel-cli 0.1.113 → 0.1.114

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, FileAttachment, ModelSelector, MessageInfo, ProviderInfo, SessionInfo, ShareInfo } from "./interface.js";
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;
@@ -29,7 +29,7 @@ export declare class CodexProvider implements AIProvider {
29
29
  getMessages(sessionId: string): Promise<{
30
30
  messages: MessageInfo[];
31
31
  }>;
32
- prompt(sessionId: string, text: string, model?: ModelSelector, agent?: string, files?: FileAttachment[]): Promise<{
32
+ prompt(sessionId: string, text: string, model?: ModelSelector, agent?: string, files?: FileAttachment[], codexOptions?: CodexPromptOptions): Promise<{
33
33
  ack: true;
34
34
  }>;
35
35
  abort(sessionId: string): Promise<Record<string, never>>;
@@ -106,6 +106,7 @@ export declare class CodexProvider implements AIProvider {
106
106
  private firstString;
107
107
  private firstStringFromSources;
108
108
  private readArray;
109
+ private readRawString;
109
110
  private readString;
110
111
  private asRecord;
111
112
  private normalizedItemType;
package/dist/ai/codex.js CHANGED
@@ -11,16 +11,19 @@ function joinStreamingText(previousText, nextChunk) {
11
11
  if (!previousText) {
12
12
  return nextChunk;
13
13
  }
14
- if (/[\s]$/.test(previousText) || /^[\s]/.test(nextChunk)) {
15
- return `${previousText}${nextChunk}`;
14
+ if (nextChunk.startsWith(previousText)) {
15
+ return nextChunk;
16
16
  }
17
- if (/^[.,!?;:)\]%}"'`]/.test(nextChunk)) {
18
- return `${previousText}${nextChunk}`;
17
+ if (previousText.endsWith(nextChunk)) {
18
+ return previousText;
19
19
  }
20
- if (/[(\[{/"'`]$/.test(previousText)) {
21
- return `${previousText}${nextChunk}`;
20
+ const maxOverlap = Math.min(previousText.length, nextChunk.length);
21
+ for (let overlap = maxOverlap; overlap > 0; overlap -= 1) {
22
+ if (previousText.slice(-overlap) === nextChunk.slice(0, overlap)) {
23
+ return previousText + nextChunk.slice(overlap);
24
+ }
22
25
  }
23
- return `${previousText} ${nextChunk}`;
26
+ return previousText + nextChunk;
24
27
  }
25
28
  export class CodexProvider {
26
29
  proc = null;
@@ -164,7 +167,7 @@ export class CodexProvider {
164
167
  });
165
168
  return { messages: session.messages };
166
169
  }
167
- async prompt(sessionId, text, model, agent, files = []) {
170
+ async prompt(sessionId, text, model, agent, files = [], codexOptions) {
168
171
  const session = this.ensureLocalSession(sessionId);
169
172
  session.updatedAt = Date.now();
170
173
  (async () => {
@@ -173,11 +176,22 @@ export class CodexProvider {
173
176
  let imageUrlKey = "url";
174
177
  while (true) {
175
178
  try {
179
+ const effortLevels = ["low", "medium", "high"];
180
+ const speedDelta = {
181
+ fast: -1,
182
+ balanced: 0,
183
+ quality: 1,
184
+ };
185
+ const baseEffort = codexOptions?.reasoningEffort ?? "medium";
186
+ const baseIndex = effortLevels.indexOf(baseEffort);
187
+ const adjustedIndex = Math.max(0, Math.min(effortLevels.length - 1, baseIndex + (codexOptions?.speed ? speedDelta[codexOptions.speed] : 0)));
188
+ const reasoningEffort = effortLevels[adjustedIndex];
176
189
  await this.call("turn/start", {
177
190
  threadId: session.id,
178
191
  input: this.makeTurnInputPayload(text, files, imageUrlKey),
179
192
  ...(model ? { model: model.providerID === "codex" ? model.modelID : `${model.providerID}/${model.modelID}` } : {}),
180
193
  ...(agent ? { agent } : {}),
194
+ ...(reasoningEffort ? { reasoningEffort } : {}),
181
195
  });
182
196
  break;
183
197
  }
@@ -1282,15 +1296,15 @@ export class CodexProvider {
1282
1296
  ?? this.readString(this.asRecord(this.asRecord(payload.event).item).id));
1283
1297
  }
1284
1298
  extractTextPayload(payload) {
1285
- return (this.readString(payload.delta)
1286
- ?? this.readString(payload.text)
1287
- ?? this.readString(payload.message)
1288
- ?? this.readString(this.asRecord(payload.item).text)
1289
- ?? this.readString(this.asRecord(payload.item).delta)
1290
- ?? this.readString(this.asRecord(payload.item).message)
1291
- ?? this.readString(this.asRecord(payload.event).text)
1292
- ?? this.readString(this.asRecord(payload.event).delta)
1293
- ?? this.readString(this.asRecord(payload.event).message));
1299
+ return (this.readRawString(payload.delta)
1300
+ ?? this.readRawString(payload.text)
1301
+ ?? this.readRawString(payload.message)
1302
+ ?? this.readRawString(this.asRecord(payload.item).text)
1303
+ ?? this.readRawString(this.asRecord(payload.item).delta)
1304
+ ?? this.readRawString(this.asRecord(payload.item).message)
1305
+ ?? this.readRawString(this.asRecord(payload.event).text)
1306
+ ?? this.readRawString(this.asRecord(payload.event).delta)
1307
+ ?? this.readRawString(this.asRecord(payload.event).message));
1294
1308
  }
1295
1309
  extractThreadId(payload) {
1296
1310
  if (!payload || typeof payload !== "object")
@@ -1362,6 +1376,9 @@ export class CodexProvider {
1362
1376
  readArray(value) {
1363
1377
  return Array.isArray(value) ? value : [];
1364
1378
  }
1379
+ readRawString(value) {
1380
+ return typeof value === "string" ? value : undefined;
1381
+ }
1365
1382
  readString(value) {
1366
1383
  return typeof value === "string" && value.trim() ? value.trim() : undefined;
1367
1384
  }
@@ -1,4 +1,4 @@
1
- import type { AiEvent, ModelSelector, FileAttachment } from "./interface.js";
1
+ import type { AiEvent, ModelSelector, FileAttachment, CodexPromptOptions } from "./interface.js";
2
2
  export type AiBackend = "opencode" | "codex";
3
3
  export declare class AiManager {
4
4
  private _providers;
@@ -26,7 +26,7 @@ export declare class AiManager {
26
26
  getMessages(backend: AiBackend, sessionId: string): Promise<{
27
27
  messages: import("./interface.js").MessageInfo[];
28
28
  }>;
29
- prompt(backend: AiBackend, sessionId: string, text: string, model?: ModelSelector, agent?: string, files?: FileAttachment[]): Promise<{
29
+ prompt(backend: AiBackend, sessionId: string, text: string, model?: ModelSelector, agent?: string, files?: FileAttachment[], codexOptions?: CodexPromptOptions): Promise<{
30
30
  ack: true;
31
31
  }>;
32
32
  abort(backend: AiBackend, sessionId: string): Promise<Record<string, never>>;
package/dist/ai/index.js CHANGED
@@ -73,9 +73,9 @@ export class AiManager {
73
73
  getSession(backend, id) { return this.get(backend).getSession(id); }
74
74
  deleteSession(backend, id) { return this.get(backend).deleteSession(id); }
75
75
  getMessages(backend, sessionId) { return this.get(backend).getMessages(sessionId); }
76
- prompt(backend, sessionId, text, model, agent, files) {
76
+ prompt(backend, sessionId, text, model, agent, files, codexOptions) {
77
77
  this.get(backend).setActiveSession?.(sessionId);
78
- return this.get(backend).prompt(sessionId, text, model, agent, files);
78
+ return this.get(backend).prompt(sessionId, text, model, agent, files, codexOptions);
79
79
  }
80
80
  abort(backend, sessionId) { return this.get(backend).abort(sessionId); }
81
81
  // Metadata — backend is optional, falls back to first available
@@ -7,6 +7,10 @@ export interface ModelSelector {
7
7
  providerID: string;
8
8
  modelID: string;
9
9
  }
10
+ export interface CodexPromptOptions {
11
+ reasoningEffort?: "low" | "medium" | "high";
12
+ speed?: "fast" | "balanced" | "quality";
13
+ }
10
14
  export interface FileAttachment {
11
15
  type: "file";
12
16
  mime: string;
@@ -59,7 +63,7 @@ export interface AIProvider {
59
63
  getMessages(sessionId: string): Promise<{
60
64
  messages: MessageInfo[];
61
65
  }>;
62
- prompt(sessionId: string, text: string, model?: ModelSelector, agent?: string, files?: FileAttachment[]): Promise<{
66
+ prompt(sessionId: string, text: string, model?: ModelSelector, agent?: string, files?: FileAttachment[], codexOptions?: CodexPromptOptions): Promise<{
63
67
  ack: true;
64
68
  }>;
65
69
  abort(sessionId: string): Promise<Record<string, never>>;
@@ -1,4 +1,4 @@
1
- import type { AIProvider, AiEventEmitter, FileAttachment, ModelSelector, MessageInfo, ProviderInfo, SessionInfo, ShareInfo } from "./interface.js";
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;
@@ -27,7 +27,7 @@ export declare class OpenCodeProvider implements AIProvider {
27
27
  getMessages(sessionId: string): Promise<{
28
28
  messages: MessageInfo[];
29
29
  }>;
30
- prompt(sessionId: string, text: string, model?: ModelSelector, agent?: string, files?: FileAttachment[]): Promise<{
30
+ prompt(sessionId: string, text: string, model?: ModelSelector, agent?: string, files?: FileAttachment[], codexOptions?: CodexPromptOptions): Promise<{
31
31
  ack: true;
32
32
  }>;
33
33
  abort(sessionId: string): Promise<Record<string, never>>;
@@ -140,7 +140,8 @@ export class OpenCodeProvider {
140
140
  // -------------------------------------------------------------------------
141
141
  // Interaction
142
142
  // -------------------------------------------------------------------------
143
- async prompt(sessionId, text, model, agent, files = []) {
143
+ async prompt(sessionId, text, model, agent, files = [], codexOptions) {
144
+ void codexOptions;
144
145
  if (sessionId)
145
146
  this.lastActiveSessionId = sessionId;
146
147
  if (VERBOSE_AI_LOGS) {
package/dist/index.js CHANGED
@@ -2617,7 +2617,7 @@ async function processMessage(message) {
2617
2617
  result = { backends: aiManager.availableBackends() };
2618
2618
  break;
2619
2619
  case "prompt":
2620
- result = await aiManager.prompt(backend, payload.sessionId, payload.text, payload.model, payload.agent, payload.files);
2620
+ result = await aiManager.prompt(backend, payload.sessionId, payload.text, payload.model, payload.agent, payload.files, payload.codexOptions);
2621
2621
  break;
2622
2622
  case "createSession":
2623
2623
  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.113",
3
+ "version": "0.1.114",
4
4
  "author": [
5
5
  {
6
6
  "name": "Soham Bharambe",