@love-moon/ai-sdk 0.2.31 → 0.2.33
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/client.d.ts +5 -0
- package/dist/client.js +31 -0
- package/dist/providers/claude-agent-sdk-session.d.ts +8 -0
- package/dist/providers/claude-agent-sdk-session.js +61 -6
- package/dist/providers/codex-app-server-session.d.ts +9 -0
- package/dist/providers/codex-app-server-session.js +84 -6
- package/dist/providers/kimi-cli-session.d.ts +8 -0
- package/dist/providers/kimi-cli-session.js +80 -7
- package/dist/providers/opencode-sdk-session.d.ts +9 -0
- package/dist/providers/opencode-sdk-session.js +82 -9
- package/package.json +2 -2
- package/dist/resume.d.ts +0 -26
- package/dist/resume.js +0 -380
- package/dist/tui-session.d.ts +0 -153
- package/dist/tui-session.js +0 -941
|
@@ -134,6 +134,8 @@ export class KimiCliSession extends EventEmitter {
|
|
|
134
134
|
this.currentTurn = null;
|
|
135
135
|
this.lastTokenUsage = null;
|
|
136
136
|
this.lastContextUsagePercent = undefined;
|
|
137
|
+
this.currentTurnStatus = null;
|
|
138
|
+
this.currentTurnActivityAt = 0;
|
|
137
139
|
this.turnDeadlineMs = getBoundedEnvInt("CONDUCTOR_TURN_DEADLINE_MS", DEFAULT_TURN_DEADLINE_MS, MIN_TURN_DEADLINE_MS, MAX_TURN_DEADLINE_MS);
|
|
138
140
|
this.workingStatusDedupeMs = getBoundedEnvInt("CONDUCTOR_KIMI_STATUS_DEDUPE_MS", DEFAULT_STATUS_DEDUPE_MS, 0, MAX_STATUS_TIMING_MS);
|
|
139
141
|
this.workingStatusThrottleMs = getBoundedEnvInt("CONDUCTOR_KIMI_STATUS_THROTTLE_MS", DEFAULT_STATUS_THROTTLE_MS, 0, MAX_STATUS_TIMING_MS);
|
|
@@ -216,12 +218,16 @@ export class KimiCliSession extends EventEmitter {
|
|
|
216
218
|
command: this.buildManualResumeCommand(),
|
|
217
219
|
}
|
|
218
220
|
: null,
|
|
221
|
+
currentTurnStatus: this.getCurrentTurnStatus(),
|
|
219
222
|
pid: this.transport.pid || undefined,
|
|
220
223
|
};
|
|
221
224
|
}
|
|
222
225
|
getSessionInfo() {
|
|
223
226
|
return this.sessionInfo ? { ...this.sessionInfo } : null;
|
|
224
227
|
}
|
|
228
|
+
getCurrentTurnStatus() {
|
|
229
|
+
return this.currentTurnStatus ? { ...this.currentTurnStatus } : null;
|
|
230
|
+
}
|
|
225
231
|
async ensureSessionInfo() {
|
|
226
232
|
await this.boot();
|
|
227
233
|
return this.getSessionInfo();
|
|
@@ -261,6 +267,39 @@ export class KimiCliSession extends EventEmitter {
|
|
|
261
267
|
getCurrentReplyTarget() {
|
|
262
268
|
return this.activeReplyTarget || this.lastReplyTarget || undefined;
|
|
263
269
|
}
|
|
270
|
+
touchTurnActivity() {
|
|
271
|
+
this.currentTurnActivityAt = this.now();
|
|
272
|
+
}
|
|
273
|
+
updateCurrentTurnStatus(payload) {
|
|
274
|
+
const updatedAtMs = this.now();
|
|
275
|
+
this.currentTurnActivityAt = updatedAtMs;
|
|
276
|
+
this.currentTurnStatus = {
|
|
277
|
+
...payload,
|
|
278
|
+
updated_at: new Date(updatedAtMs).toISOString(),
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
markTurnStartedStatus() {
|
|
282
|
+
this.updateCurrentTurnStatus({
|
|
283
|
+
source: KIMI_PROVIDER_VARIANT,
|
|
284
|
+
reply_in_progress: true,
|
|
285
|
+
replyTo: this.getCurrentReplyTarget(),
|
|
286
|
+
phase: "turn_started",
|
|
287
|
+
status_line: statusLineForPhase("turn_started"),
|
|
288
|
+
thread_id: this.sessionId || undefined,
|
|
289
|
+
session_id: this.sessionId || undefined,
|
|
290
|
+
session_file_path: undefined,
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
async failPendingTurnStart(error, onProgress = null) {
|
|
294
|
+
if (this.closeRequested || error?.reason === "session_closed") {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
await this.emitWorkingStatus({
|
|
298
|
+
phase: "turn_failed",
|
|
299
|
+
reply_in_progress: false,
|
|
300
|
+
status_done_line: error instanceof Error ? error.message : String(error),
|
|
301
|
+
}, onProgress);
|
|
302
|
+
}
|
|
264
303
|
buildWorkingStatusFingerprint(payload) {
|
|
265
304
|
return JSON.stringify({
|
|
266
305
|
reply_in_progress: Boolean(payload?.reply_in_progress),
|
|
@@ -338,18 +377,22 @@ export class KimiCliSession extends EventEmitter {
|
|
|
338
377
|
session_file_path: undefined,
|
|
339
378
|
};
|
|
340
379
|
if (this.shouldSuppressWorkingStatus(normalized)) {
|
|
380
|
+
this.updateCurrentTurnStatus(normalized);
|
|
341
381
|
return;
|
|
342
382
|
}
|
|
383
|
+
this.updateCurrentTurnStatus(normalized);
|
|
384
|
+
const snapshot = this.getCurrentTurnStatus();
|
|
343
385
|
this.recordWorkingStatusEmission(normalized);
|
|
344
386
|
if (typeof onProgress === "function") {
|
|
345
|
-
onProgress(
|
|
387
|
+
onProgress(snapshot);
|
|
346
388
|
}
|
|
347
389
|
if (typeof this.workingStatusHandler === "function") {
|
|
348
|
-
await this.workingStatusHandler(
|
|
390
|
+
await this.workingStatusHandler(snapshot);
|
|
349
391
|
}
|
|
350
|
-
this.emit("working_status",
|
|
392
|
+
this.emit("working_status", snapshot);
|
|
351
393
|
}
|
|
352
394
|
async emitAssistantMessage(text) {
|
|
395
|
+
this.touchTurnActivity();
|
|
353
396
|
const payload = {
|
|
354
397
|
text,
|
|
355
398
|
preserveWhitespace: true,
|
|
@@ -423,8 +466,27 @@ export class KimiCliSession extends EventEmitter {
|
|
|
423
466
|
};
|
|
424
467
|
}
|
|
425
468
|
let timer = null;
|
|
426
|
-
|
|
469
|
+
let settled = false;
|
|
470
|
+
const schedule = (reject) => {
|
|
471
|
+
const now = this.now();
|
|
472
|
+
const lastActivityAt = Number.isFinite(this.currentTurnActivityAt) && this.currentTurnActivityAt > 0
|
|
473
|
+
? this.currentTurnActivityAt
|
|
474
|
+
: now;
|
|
475
|
+
const elapsedMs = Math.max(0, now - lastActivityAt);
|
|
476
|
+
const waitMs = Math.max(1, this.turnDeadlineMs - elapsedMs);
|
|
427
477
|
timer = setTimeout(() => {
|
|
478
|
+
if (settled) {
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
const activityNow = this.now();
|
|
482
|
+
const latestActivityAt = Number.isFinite(this.currentTurnActivityAt) && this.currentTurnActivityAt > 0
|
|
483
|
+
? this.currentTurnActivityAt
|
|
484
|
+
: activityNow;
|
|
485
|
+
if (activityNow - latestActivityAt < this.turnDeadlineMs) {
|
|
486
|
+
schedule(reject);
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
settled = true;
|
|
428
490
|
try {
|
|
429
491
|
onTimeout?.();
|
|
430
492
|
}
|
|
@@ -432,14 +494,18 @@ export class KimiCliSession extends EventEmitter {
|
|
|
432
494
|
// best effort
|
|
433
495
|
}
|
|
434
496
|
reject(this.createTurnTimeoutError(this.turnDeadlineMs));
|
|
435
|
-
},
|
|
436
|
-
if (typeof timer
|
|
497
|
+
}, waitMs);
|
|
498
|
+
if (typeof timer?.unref === "function") {
|
|
437
499
|
timer.unref();
|
|
438
500
|
}
|
|
501
|
+
};
|
|
502
|
+
const promise = new Promise((_, reject) => {
|
|
503
|
+
schedule(reject);
|
|
439
504
|
});
|
|
440
505
|
return {
|
|
441
506
|
promise,
|
|
442
507
|
cleanup: () => {
|
|
508
|
+
settled = true;
|
|
443
509
|
if (timer) {
|
|
444
510
|
clearTimeout(timer);
|
|
445
511
|
}
|
|
@@ -763,12 +829,19 @@ export class KimiCliSession extends EventEmitter {
|
|
|
763
829
|
if (!effectivePrompt) {
|
|
764
830
|
return buildEmptyTurnResult();
|
|
765
831
|
}
|
|
766
|
-
await this.boot();
|
|
767
832
|
if (this.currentTurn) {
|
|
768
833
|
throw createTurnError("Kimi turn already running", {
|
|
769
834
|
reason: "turn_already_running",
|
|
770
835
|
});
|
|
771
836
|
}
|
|
837
|
+
this.markTurnStartedStatus();
|
|
838
|
+
try {
|
|
839
|
+
await this.boot();
|
|
840
|
+
}
|
|
841
|
+
catch (error) {
|
|
842
|
+
await this.failPendingTurnStart(error, onProgress);
|
|
843
|
+
throw error;
|
|
844
|
+
}
|
|
772
845
|
this.history.push({ role: "user", content: promptText });
|
|
773
846
|
const currentTurn = {
|
|
774
847
|
fullText: "",
|
|
@@ -46,6 +46,9 @@ export class OpencodeSdkSession extends EventEmitter<[never]> {
|
|
|
46
46
|
};
|
|
47
47
|
} | null;
|
|
48
48
|
lastAssistantInfo: any;
|
|
49
|
+
currentTurnStatus: any;
|
|
50
|
+
currentTurnActivityAt: number;
|
|
51
|
+
now: any;
|
|
49
52
|
turnDeadlineMs: any;
|
|
50
53
|
client: any;
|
|
51
54
|
sdkModulePromise: Promise<any> | Promise<typeof import("@opencode-ai/sdk/v2/client")> | null;
|
|
@@ -74,12 +77,14 @@ export class OpencodeSdkSession extends EventEmitter<[never]> {
|
|
|
74
77
|
useSessionFileReplyStream: boolean;
|
|
75
78
|
resumeReady: boolean;
|
|
76
79
|
manualResume: null;
|
|
80
|
+
currentTurnStatus: any;
|
|
77
81
|
pid: any;
|
|
78
82
|
};
|
|
79
83
|
getSessionInfo(): {
|
|
80
84
|
backend: string;
|
|
81
85
|
sessionId: any;
|
|
82
86
|
} | null;
|
|
87
|
+
getCurrentTurnStatus(): any;
|
|
83
88
|
ensureSessionInfo(): Promise<{
|
|
84
89
|
backend: string;
|
|
85
90
|
sessionId: any;
|
|
@@ -106,6 +111,10 @@ export class OpencodeSdkSession extends EventEmitter<[never]> {
|
|
|
106
111
|
setWorkingStatusHandler(handler: any): void;
|
|
107
112
|
setSessionReplyTarget(replyTo: any): void;
|
|
108
113
|
getCurrentReplyTarget(): string | undefined;
|
|
114
|
+
touchTurnActivity(): void;
|
|
115
|
+
updateCurrentTurnStatus(payload: any): void;
|
|
116
|
+
markTurnStartedStatus(): void;
|
|
117
|
+
failPendingTurnStart(error: any, onProgress?: null): Promise<void>;
|
|
109
118
|
emitWorkingStatus(payload: any, onProgress?: null): Promise<void>;
|
|
110
119
|
emitAssistantMessage(text: any): Promise<void>;
|
|
111
120
|
emitTerminalWorkingStatus(currentTurn: any, payload: any, onProgress?: null): Promise<void>;
|
|
@@ -154,6 +154,9 @@ export class OpencodeSdkSession extends EventEmitter {
|
|
|
154
154
|
this.currentTurn = null;
|
|
155
155
|
this.lastUsage = null;
|
|
156
156
|
this.lastAssistantInfo = null;
|
|
157
|
+
this.currentTurnStatus = null;
|
|
158
|
+
this.currentTurnActivityAt = 0;
|
|
159
|
+
this.now = typeof options.now === "function" ? options.now : () => Date.now();
|
|
157
160
|
this.turnDeadlineMs = getBoundedEnvInt("CONDUCTOR_TURN_DEADLINE_MS", DEFAULT_TURN_DEADLINE_MS, MIN_TURN_DEADLINE_MS, MAX_TURN_DEADLINE_MS);
|
|
158
161
|
this.client = null;
|
|
159
162
|
this.sdkModulePromise = null;
|
|
@@ -219,12 +222,16 @@ export class OpencodeSdkSession extends EventEmitter {
|
|
|
219
222
|
useSessionFileReplyStream: this.usesSessionFileReplyStream(),
|
|
220
223
|
resumeReady: Boolean(this.sessionId),
|
|
221
224
|
manualResume: null,
|
|
225
|
+
currentTurnStatus: this.getCurrentTurnStatus(),
|
|
222
226
|
pid: this.transport.pid || undefined,
|
|
223
227
|
};
|
|
224
228
|
}
|
|
225
229
|
getSessionInfo() {
|
|
226
230
|
return this.sessionInfo ? { ...this.sessionInfo } : null;
|
|
227
231
|
}
|
|
232
|
+
getCurrentTurnStatus() {
|
|
233
|
+
return this.currentTurnStatus ? { ...this.currentTurnStatus } : null;
|
|
234
|
+
}
|
|
228
235
|
async ensureSessionInfo() {
|
|
229
236
|
await this.boot();
|
|
230
237
|
return this.getSessionInfo();
|
|
@@ -260,6 +267,39 @@ export class OpencodeSdkSession extends EventEmitter {
|
|
|
260
267
|
getCurrentReplyTarget() {
|
|
261
268
|
return this.activeReplyTarget || this.lastReplyTarget || undefined;
|
|
262
269
|
}
|
|
270
|
+
touchTurnActivity() {
|
|
271
|
+
this.currentTurnActivityAt = this.now();
|
|
272
|
+
}
|
|
273
|
+
updateCurrentTurnStatus(payload) {
|
|
274
|
+
const updatedAtMs = this.now();
|
|
275
|
+
this.currentTurnActivityAt = updatedAtMs;
|
|
276
|
+
this.currentTurnStatus = {
|
|
277
|
+
...payload,
|
|
278
|
+
updated_at: new Date(updatedAtMs).toISOString(),
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
markTurnStartedStatus() {
|
|
282
|
+
this.updateCurrentTurnStatus({
|
|
283
|
+
source: OPENCODE_PROVIDER_VARIANT,
|
|
284
|
+
reply_in_progress: true,
|
|
285
|
+
replyTo: this.getCurrentReplyTarget(),
|
|
286
|
+
phase: "turn_started",
|
|
287
|
+
status_line: "opencode is working",
|
|
288
|
+
thread_id: this.sessionId || undefined,
|
|
289
|
+
session_id: this.sessionId || undefined,
|
|
290
|
+
session_file_path: undefined,
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
async failPendingTurnStart(error, onProgress = null) {
|
|
294
|
+
if (this.closeRequested || error?.reason === "session_closed") {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
await this.emitWorkingStatus({
|
|
298
|
+
phase: "turn_failed",
|
|
299
|
+
reply_in_progress: false,
|
|
300
|
+
status_done_line: error instanceof Error ? error.message : String(error),
|
|
301
|
+
}, onProgress);
|
|
302
|
+
}
|
|
263
303
|
async emitWorkingStatus(payload, onProgress = null) {
|
|
264
304
|
const normalized = {
|
|
265
305
|
source: OPENCODE_PROVIDER_VARIANT,
|
|
@@ -274,15 +314,18 @@ export class OpencodeSdkSession extends EventEmitter {
|
|
|
274
314
|
session_id: this.sessionId || undefined,
|
|
275
315
|
session_file_path: undefined,
|
|
276
316
|
};
|
|
317
|
+
this.updateCurrentTurnStatus(normalized);
|
|
318
|
+
const snapshot = this.getCurrentTurnStatus();
|
|
277
319
|
if (typeof onProgress === "function") {
|
|
278
|
-
onProgress(
|
|
320
|
+
onProgress(snapshot);
|
|
279
321
|
}
|
|
280
322
|
if (typeof this.workingStatusHandler === "function") {
|
|
281
|
-
await this.workingStatusHandler(
|
|
323
|
+
await this.workingStatusHandler(snapshot);
|
|
282
324
|
}
|
|
283
|
-
this.emit("working_status",
|
|
325
|
+
this.emit("working_status", snapshot);
|
|
284
326
|
}
|
|
285
327
|
async emitAssistantMessage(text) {
|
|
328
|
+
this.touchTurnActivity();
|
|
286
329
|
const payload = {
|
|
287
330
|
text,
|
|
288
331
|
preserveWhitespace: true,
|
|
@@ -356,8 +399,27 @@ export class OpencodeSdkSession extends EventEmitter {
|
|
|
356
399
|
};
|
|
357
400
|
}
|
|
358
401
|
let timer = null;
|
|
359
|
-
|
|
402
|
+
let settled = false;
|
|
403
|
+
const schedule = (reject) => {
|
|
404
|
+
const now = this.now();
|
|
405
|
+
const lastActivityAt = Number.isFinite(this.currentTurnActivityAt) && this.currentTurnActivityAt > 0
|
|
406
|
+
? this.currentTurnActivityAt
|
|
407
|
+
: now;
|
|
408
|
+
const elapsedMs = Math.max(0, now - lastActivityAt);
|
|
409
|
+
const waitMs = Math.max(1, this.turnDeadlineMs - elapsedMs);
|
|
360
410
|
timer = setTimeout(() => {
|
|
411
|
+
if (settled) {
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
const activityNow = this.now();
|
|
415
|
+
const latestActivityAt = Number.isFinite(this.currentTurnActivityAt) && this.currentTurnActivityAt > 0
|
|
416
|
+
? this.currentTurnActivityAt
|
|
417
|
+
: activityNow;
|
|
418
|
+
if (activityNow - latestActivityAt < this.turnDeadlineMs) {
|
|
419
|
+
schedule(reject);
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
settled = true;
|
|
361
423
|
try {
|
|
362
424
|
onTimeout?.();
|
|
363
425
|
}
|
|
@@ -365,14 +427,18 @@ export class OpencodeSdkSession extends EventEmitter {
|
|
|
365
427
|
// best effort
|
|
366
428
|
}
|
|
367
429
|
reject(this.createTurnTimeoutError(this.turnDeadlineMs));
|
|
368
|
-
},
|
|
369
|
-
if (typeof timer
|
|
430
|
+
}, waitMs);
|
|
431
|
+
if (typeof timer?.unref === "function") {
|
|
370
432
|
timer.unref();
|
|
371
433
|
}
|
|
434
|
+
};
|
|
435
|
+
const promise = new Promise((_, reject) => {
|
|
436
|
+
schedule(reject);
|
|
372
437
|
});
|
|
373
438
|
return {
|
|
374
439
|
promise,
|
|
375
440
|
cleanup: () => {
|
|
441
|
+
settled = true;
|
|
376
442
|
if (timer) {
|
|
377
443
|
clearTimeout(timer);
|
|
378
444
|
}
|
|
@@ -1076,14 +1142,21 @@ export class OpencodeSdkSession extends EventEmitter {
|
|
|
1076
1142
|
if (!effectivePrompt) {
|
|
1077
1143
|
return buildEmptyTurnResult();
|
|
1078
1144
|
}
|
|
1079
|
-
await this.boot();
|
|
1080
1145
|
if (this.currentTurn) {
|
|
1081
1146
|
throw createTurnError("Opencode turn already running", {
|
|
1082
1147
|
reason: "turn_already_running",
|
|
1083
1148
|
});
|
|
1084
1149
|
}
|
|
1085
|
-
|
|
1086
|
-
|
|
1150
|
+
this.markTurnStartedStatus();
|
|
1151
|
+
try {
|
|
1152
|
+
await this.boot();
|
|
1153
|
+
if (!this.client?.session || typeof this.client.session.promptAsync !== "function") {
|
|
1154
|
+
throw new Error("Opencode session client is unavailable");
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
catch (error) {
|
|
1158
|
+
await this.failPendingTurnStart(error, onProgress);
|
|
1159
|
+
throw error;
|
|
1087
1160
|
}
|
|
1088
1161
|
this.history.push({ role: "user", content: promptText });
|
|
1089
1162
|
const abortController = new AbortController();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@love-moon/ai-sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.33",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -25,5 +25,5 @@
|
|
|
25
25
|
"@types/node": "^22.10.2",
|
|
26
26
|
"typescript": "^5.6.3"
|
|
27
27
|
},
|
|
28
|
-
"gitCommitId": "
|
|
28
|
+
"gitCommitId": "db7f9bf"
|
|
29
29
|
}
|
package/dist/resume.d.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
export function resumeProviderForBackend(backend: any): "codex" | "claude" | "copilot" | null;
|
|
2
|
-
export function findSessionPath(provider: any, sessionId: any, options?: {}): Promise<any>;
|
|
3
|
-
export function findCodexSessionPath(sessionId: any, options?: {}): Promise<string | null>;
|
|
4
|
-
export function findClaudeSessionPath(sessionId: any, options?: {}): Promise<any>;
|
|
5
|
-
export function findCopilotSessionPath(sessionId: any, options?: {}): Promise<string | null>;
|
|
6
|
-
export function resolveSessionRunDirectory(sessionPath: any): Promise<string>;
|
|
7
|
-
export function inspectResumeTarget(backend: any, sessionId: any, options?: {}): Promise<{
|
|
8
|
-
provider: string;
|
|
9
|
-
sessionId: string;
|
|
10
|
-
sessionPath: any;
|
|
11
|
-
cwd: string;
|
|
12
|
-
debugMetadata: {
|
|
13
|
-
cwdSource: string;
|
|
14
|
-
sessionPath: any;
|
|
15
|
-
};
|
|
16
|
-
}>;
|
|
17
|
-
export function resolveResumeContext(backend: any, sessionId: any, options?: {}): Promise<{
|
|
18
|
-
provider: string;
|
|
19
|
-
sessionId: string;
|
|
20
|
-
sessionPath: any;
|
|
21
|
-
cwd: string;
|
|
22
|
-
debugMetadata: {
|
|
23
|
-
cwdSource: string;
|
|
24
|
-
sessionPath: any;
|
|
25
|
-
};
|
|
26
|
-
}>;
|