pikiclaw 0.2.70 → 0.2.71
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/README.md +1 -0
- package/dist/bot-commands.js +1 -1
- package/dist/bot-feishu-render.js +7 -3
- package/dist/bot-feishu.js +53 -7
- package/dist/bot-handler.js +1 -1
- package/dist/bot-telegram-render.js +8 -4
- package/dist/bot-telegram.js +41 -5
- package/dist/bot.js +56 -1
- package/dist/channel-feishu.js +4 -2
- package/dist/code-agent.js +2 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -142,6 +142,7 @@ npx pikiclaw@latest --doctor # check environment only
|
|
|
142
142
|
|
|
143
143
|
- Streaming preview with continuous message updates
|
|
144
144
|
- Session switching, resume, and multi-turn conversations
|
|
145
|
+
- Task queue with **Steer** — interrupt the running task and let a queued message jump ahead
|
|
145
146
|
- Working directory browsing and switching
|
|
146
147
|
- File attachments automatically enter the session workspace
|
|
147
148
|
- Long-task sleep prevention, watchdog, and auto-restart
|
package/dist/bot-commands.js
CHANGED
|
@@ -78,7 +78,7 @@ export async function getSessionsPageData(bot, chatId, page, pageSize = 5) {
|
|
|
78
78
|
runState: status.isRunning ? 'running' : s.runState,
|
|
79
79
|
runDetail: s.runDetail,
|
|
80
80
|
});
|
|
81
|
-
const title = s.title ? s.title.replace(/\n/g, ' ').slice(0,
|
|
81
|
+
const title = s.title ? s.title.replace(/\n/g, ' ').slice(0, 20) : sessionKey.slice(0, 20);
|
|
82
82
|
const time = s.createdAt
|
|
83
83
|
? new Date(s.createdAt).toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' })
|
|
84
84
|
: '?';
|
|
@@ -179,10 +179,14 @@ export function buildHumanLoopPromptMarkdown(prompt) {
|
|
|
179
179
|
// ---------------------------------------------------------------------------
|
|
180
180
|
// LivePreview renderer — produces Markdown for Feishu card elements
|
|
181
181
|
// ---------------------------------------------------------------------------
|
|
182
|
-
export function buildInitialPreviewMarkdown(agent, model, effort, waiting = false) {
|
|
182
|
+
export function buildInitialPreviewMarkdown(agent, model, effort, waiting = false, queuePosition = 0) {
|
|
183
183
|
const parts = [];
|
|
184
|
-
if (waiting)
|
|
185
|
-
|
|
184
|
+
if (waiting) {
|
|
185
|
+
const queueLabel = queuePosition > 0
|
|
186
|
+
? `Queued · ${queuePosition} ${queuePosition === 1 ? 'task' : 'tasks'} ahead`
|
|
187
|
+
: 'Waiting in queue...';
|
|
188
|
+
parts.push(queueLabel);
|
|
189
|
+
}
|
|
186
190
|
if (model)
|
|
187
191
|
parts.push(model);
|
|
188
192
|
else
|
package/dist/bot-feishu.js
CHANGED
|
@@ -201,7 +201,13 @@ export class FeishuBot extends Bot {
|
|
|
201
201
|
}
|
|
202
202
|
resolveIncomingSession(ctx, text, files) {
|
|
203
203
|
const cs = this.chat(ctx.chatId);
|
|
204
|
-
|
|
204
|
+
const replyMessageId = ctx.replyToMessageId || null;
|
|
205
|
+
const repliedSession = this.sessionFromMessage(ctx.chatId, replyMessageId);
|
|
206
|
+
if (repliedSession) {
|
|
207
|
+
this.log(`[resolveSession] reply matched session=${repliedSession.sessionId} chat=${ctx.chatId}`);
|
|
208
|
+
this.applySessionSelection(cs, repliedSession);
|
|
209
|
+
return repliedSession;
|
|
210
|
+
}
|
|
205
211
|
const selected = this.getSelectedSession(cs);
|
|
206
212
|
if (selected)
|
|
207
213
|
return selected;
|
|
@@ -257,9 +263,27 @@ export class FeishuBot extends Bot {
|
|
|
257
263
|
}
|
|
258
264
|
}
|
|
259
265
|
sessionsPageSize = 5;
|
|
260
|
-
buildStopKeyboard(actionId) {
|
|
266
|
+
buildStopKeyboard(actionId, opts) {
|
|
261
267
|
if (!actionId)
|
|
262
268
|
return undefined;
|
|
269
|
+
if (opts?.queued) {
|
|
270
|
+
return {
|
|
271
|
+
rows: [{
|
|
272
|
+
actions: [
|
|
273
|
+
{
|
|
274
|
+
tag: 'button',
|
|
275
|
+
text: { tag: 'plain_text', content: 'Recall' },
|
|
276
|
+
value: { action: `tsk:stop:${actionId}` },
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
tag: 'button',
|
|
280
|
+
text: { tag: 'plain_text', content: 'Steer' },
|
|
281
|
+
value: { action: `tsk:steer:${actionId}` },
|
|
282
|
+
},
|
|
283
|
+
],
|
|
284
|
+
}],
|
|
285
|
+
};
|
|
286
|
+
}
|
|
263
287
|
return {
|
|
264
288
|
rows: [{
|
|
265
289
|
actions: [{
|
|
@@ -512,7 +536,7 @@ export class FeishuBot extends Bot {
|
|
|
512
536
|
workdir: this.workdir,
|
|
513
537
|
files: msg.files,
|
|
514
538
|
sessionId: session.sessionId,
|
|
515
|
-
title:
|
|
539
|
+
title: undefined,
|
|
516
540
|
});
|
|
517
541
|
session.workspacePath = staged.workspacePath;
|
|
518
542
|
this.syncSelectedChats(session);
|
|
@@ -550,12 +574,13 @@ export class FeishuBot extends Bot {
|
|
|
550
574
|
startedAt: start,
|
|
551
575
|
sourceMessageId: ctx.messageId,
|
|
552
576
|
});
|
|
553
|
-
const
|
|
577
|
+
const queuePosition = waiting ? this.getQueuePosition(session.key, taskId) : 0;
|
|
578
|
+
const placeholderKeyboard = this.buildStopKeyboard(this.actionIdForTask(taskId), { queued: waiting });
|
|
554
579
|
const model = session.modelId || this.modelForAgent(session.agent);
|
|
555
580
|
const effort = this.effortForAgent(session.agent);
|
|
556
|
-
const placeholderId = await this.channel.sendStreamingCard(ctx.chatId, buildInitialPreviewMarkdown(session.agent, model, effort, waiting), {
|
|
581
|
+
const placeholderId = await this.channel.sendStreamingCard(ctx.chatId, buildInitialPreviewMarkdown(session.agent, model, effort, waiting, queuePosition), {
|
|
557
582
|
replyTo: ctx.messageId || undefined,
|
|
558
|
-
keyboard:
|
|
583
|
+
keyboard: placeholderKeyboard,
|
|
559
584
|
});
|
|
560
585
|
if (placeholderId) {
|
|
561
586
|
this.registerSessionMessage(ctx.chatId, placeholderId, session);
|
|
@@ -576,6 +601,14 @@ export class FeishuBot extends Bot {
|
|
|
576
601
|
this.log(`[handleMessage] skipped cancelled queued task chat=${ctx.chatId} msg=${ctx.messageId}`);
|
|
577
602
|
return;
|
|
578
603
|
}
|
|
604
|
+
// Task is now running — update keyboard from Recall/Steer to Stop
|
|
605
|
+
const runningKeyboard = this.buildStopKeyboard(this.actionIdForTask(taskId));
|
|
606
|
+
if (placeholderId && waiting) {
|
|
607
|
+
try {
|
|
608
|
+
await this.channel.editMessage(ctx.chatId, placeholderId, buildInitialPreviewMarkdown(session.agent, model, effort, false), { keyboard: runningKeyboard });
|
|
609
|
+
}
|
|
610
|
+
catch { }
|
|
611
|
+
}
|
|
579
612
|
if (placeholderId) {
|
|
580
613
|
const renderer = this.channel.isStreamingCard(placeholderId)
|
|
581
614
|
? feishuStreamingPreviewRenderer
|
|
@@ -591,7 +624,7 @@ export class FeishuBot extends Bot {
|
|
|
591
624
|
canEditMessages: supportsChannelCapability(this.channel, 'editMessages'),
|
|
592
625
|
canSendTyping: false,
|
|
593
626
|
parseMode: 'Markdown',
|
|
594
|
-
keyboard:
|
|
627
|
+
keyboard: runningKeyboard,
|
|
595
628
|
log: (message) => this.log(message),
|
|
596
629
|
});
|
|
597
630
|
livePreview.start();
|
|
@@ -787,6 +820,7 @@ export class FeishuBot extends Bot {
|
|
|
787
820
|
messageId: ctx.messageId,
|
|
788
821
|
from: ctx.from,
|
|
789
822
|
chatType: 'p2p',
|
|
823
|
+
replyToMessageId: null,
|
|
790
824
|
reply: (text, opts) => ctx.channel.send(ctx.chatId, text, opts),
|
|
791
825
|
editReply: (msgId, text, opts) => ctx.channel.editMessage(ctx.chatId, msgId, text, opts),
|
|
792
826
|
channel: ctx.channel,
|
|
@@ -800,6 +834,8 @@ export class FeishuBot extends Bot {
|
|
|
800
834
|
return;
|
|
801
835
|
if (await this.handleTaskStopCallback(data, ctx))
|
|
802
836
|
return;
|
|
837
|
+
if (await this.handleTaskSteerCallback(data, ctx))
|
|
838
|
+
return;
|
|
803
839
|
if (await this.handleSwitchNavigateCallback(data, ctx))
|
|
804
840
|
return;
|
|
805
841
|
if (await this.handleSwitchSelectCallback(data, ctx))
|
|
@@ -877,6 +913,16 @@ export class FeishuBot extends Bot {
|
|
|
877
913
|
}
|
|
878
914
|
return true;
|
|
879
915
|
}
|
|
916
|
+
async handleTaskSteerCallback(data, ctx) {
|
|
917
|
+
if (!data.startsWith('tsk:steer:'))
|
|
918
|
+
return false;
|
|
919
|
+
const actionId = data.slice('tsk:steer:'.length).trim();
|
|
920
|
+
const result = this.steerTaskByActionId(actionId);
|
|
921
|
+
if (!result.task)
|
|
922
|
+
return true;
|
|
923
|
+
// The queued task will naturally run next after the running task is interrupted
|
|
924
|
+
return true;
|
|
925
|
+
}
|
|
880
926
|
async handleSwitchNavigateCallback(data, ctx) {
|
|
881
927
|
if (!data.startsWith('sw:n:'))
|
|
882
928
|
return false;
|
package/dist/bot-handler.js
CHANGED
|
@@ -258,10 +258,14 @@ function formatFinalFooterHtml(status, agent, elapsedMs, contextPercent) {
|
|
|
258
258
|
export function formatProviderUsageLines(usage) {
|
|
259
259
|
return buildProviderUsageLines(usage).map(line => line.bold ? `<b>${escapeHtml(line.text)}</b>` : escapeHtml(line.text));
|
|
260
260
|
}
|
|
261
|
-
export function buildInitialPreviewHtml(agent, waiting = false) {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
261
|
+
export function buildInitialPreviewHtml(agent, waiting = false, queuePosition = 0) {
|
|
262
|
+
if (waiting) {
|
|
263
|
+
const queueLabel = queuePosition > 0
|
|
264
|
+
? `Queued · ${queuePosition} ${queuePosition === 1 ? 'task' : 'tasks'} ahead`
|
|
265
|
+
: 'Waiting in queue...';
|
|
266
|
+
return `<i>${escapeHtml(queueLabel)}</i>\n\n${formatPreviewFooterHtml(agent, 0)}`;
|
|
267
|
+
}
|
|
268
|
+
return formatPreviewFooterHtml(agent, 0);
|
|
265
269
|
}
|
|
266
270
|
export function buildStreamPreviewHtml(input) {
|
|
267
271
|
const data = extractStreamPreviewData(input);
|
package/dist/bot-telegram.js
CHANGED
|
@@ -178,6 +178,7 @@ export class TelegramBot extends Bot {
|
|
|
178
178
|
: null;
|
|
179
179
|
const repliedSession = this.sessionFromMessage(ctx.chatId, replyMessageId);
|
|
180
180
|
if (repliedSession) {
|
|
181
|
+
this.log(`[resolveSession] reply matched session=${repliedSession.sessionId} chat=${ctx.chatId}`);
|
|
181
182
|
this.applySessionSelection(cs, repliedSession);
|
|
182
183
|
return repliedSession;
|
|
183
184
|
}
|
|
@@ -262,9 +263,17 @@ export class TelegramBot extends Bot {
|
|
|
262
263
|
}
|
|
263
264
|
}
|
|
264
265
|
sessionsPageSize = 5;
|
|
265
|
-
buildStopKeyboard(actionId) {
|
|
266
|
+
buildStopKeyboard(actionId, opts) {
|
|
266
267
|
if (!actionId)
|
|
267
268
|
return undefined;
|
|
269
|
+
if (opts?.queued) {
|
|
270
|
+
return {
|
|
271
|
+
inline_keyboard: [[
|
|
272
|
+
{ text: 'Recall', callback_data: `tsk:stop:${actionId}` },
|
|
273
|
+
{ text: 'Steer', callback_data: `tsk:steer:${actionId}` },
|
|
274
|
+
]],
|
|
275
|
+
};
|
|
276
|
+
}
|
|
268
277
|
return {
|
|
269
278
|
inline_keyboard: [[
|
|
270
279
|
{ text: 'Stop', callback_data: `tsk:stop:${actionId}` },
|
|
@@ -462,7 +471,7 @@ export class TelegramBot extends Bot {
|
|
|
462
471
|
workdir: this.workdir,
|
|
463
472
|
files: msg.files,
|
|
464
473
|
sessionId: session.sessionId,
|
|
465
|
-
title:
|
|
474
|
+
title: undefined,
|
|
466
475
|
});
|
|
467
476
|
session.workspacePath = staged.workspacePath;
|
|
468
477
|
this.syncSelectedChats(session);
|
|
@@ -501,11 +510,12 @@ export class TelegramBot extends Bot {
|
|
|
501
510
|
startedAt: start,
|
|
502
511
|
sourceMessageId: ctx.messageId,
|
|
503
512
|
});
|
|
504
|
-
const stopKeyboard = this.buildStopKeyboard(this.actionIdForTask(taskId));
|
|
505
513
|
const waiting = this.sessionHasPendingWork(session);
|
|
514
|
+
const queuePosition = waiting ? this.getQueuePosition(session.key, taskId) : 0;
|
|
515
|
+
const placeholderKeyboard = this.buildStopKeyboard(this.actionIdForTask(taskId), { queued: waiting });
|
|
506
516
|
let phId = null;
|
|
507
517
|
if (canEditMessages) {
|
|
508
|
-
const placeholderId = await ctx.reply(buildInitialPreviewHtml(session.agent, waiting), { parseMode: 'HTML', messageThreadId, keyboard:
|
|
518
|
+
const placeholderId = await ctx.reply(buildInitialPreviewHtml(session.agent, waiting, queuePosition), { parseMode: 'HTML', messageThreadId, keyboard: placeholderKeyboard });
|
|
509
519
|
phId = typeof placeholderId === 'number' ? placeholderId : null;
|
|
510
520
|
if (phId != null) {
|
|
511
521
|
this.registerSessionMessage(ctx.chatId, phId, session);
|
|
@@ -534,6 +544,14 @@ export class TelegramBot extends Bot {
|
|
|
534
544
|
this.log(`[handleMessage] skipped cancelled queued task chat=${ctx.chatId} msg=${ctx.messageId}`);
|
|
535
545
|
return;
|
|
536
546
|
}
|
|
547
|
+
// Task is now running — update keyboard from Recall/Steer to Stop
|
|
548
|
+
const runningKeyboard = this.buildStopKeyboard(this.actionIdForTask(taskId));
|
|
549
|
+
if (phId != null && waiting) {
|
|
550
|
+
try {
|
|
551
|
+
await this.channel.editMessage(ctx.chatId, phId, buildInitialPreviewHtml(session.agent, false), { parseMode: 'HTML', keyboard: runningKeyboard });
|
|
552
|
+
}
|
|
553
|
+
catch { }
|
|
554
|
+
}
|
|
537
555
|
if (phId != null || canSendTyping) {
|
|
538
556
|
livePreview = new LivePreview({
|
|
539
557
|
agent: session.agent,
|
|
@@ -546,7 +564,7 @@ export class TelegramBot extends Bot {
|
|
|
546
564
|
canEditMessages,
|
|
547
565
|
canSendTyping,
|
|
548
566
|
messageThreadId,
|
|
549
|
-
keyboard:
|
|
567
|
+
keyboard: runningKeyboard,
|
|
550
568
|
log: (message) => this.log(message),
|
|
551
569
|
});
|
|
552
570
|
livePreview.start();
|
|
@@ -758,6 +776,22 @@ export class TelegramBot extends Bot {
|
|
|
758
776
|
await ctx.answerCallback('Nothing to stop.');
|
|
759
777
|
return true;
|
|
760
778
|
}
|
|
779
|
+
async handleTaskSteerCallback(data, ctx) {
|
|
780
|
+
if (!data.startsWith('tsk:steer:'))
|
|
781
|
+
return false;
|
|
782
|
+
const actionId = data.slice('tsk:steer:'.length).trim();
|
|
783
|
+
const result = this.steerTaskByActionId(actionId);
|
|
784
|
+
if (!result.task) {
|
|
785
|
+
await ctx.answerCallback('This task already finished.');
|
|
786
|
+
return true;
|
|
787
|
+
}
|
|
788
|
+
if (result.task.status !== 'queued') {
|
|
789
|
+
await ctx.answerCallback('Task is already running.');
|
|
790
|
+
return true;
|
|
791
|
+
}
|
|
792
|
+
await ctx.answerCallback(result.interrupted ? 'Steering — interrupting current task...' : 'No running task to interrupt.');
|
|
793
|
+
return true;
|
|
794
|
+
}
|
|
761
795
|
async handleHumanLoopCallback(data, ctx) {
|
|
762
796
|
if (!data.startsWith('hl:'))
|
|
763
797
|
return false;
|
|
@@ -824,6 +858,8 @@ export class TelegramBot extends Bot {
|
|
|
824
858
|
return;
|
|
825
859
|
if (await this.handleTaskStopCallback(data, ctx))
|
|
826
860
|
return;
|
|
861
|
+
if (await this.handleTaskSteerCallback(data, ctx))
|
|
862
|
+
return;
|
|
827
863
|
if (await this.handleSwitchNavigateCallback(data, ctx))
|
|
828
864
|
return;
|
|
829
865
|
if (await this.handleSwitchSelectCallback(data, ctx))
|
package/dist/bot.js
CHANGED
|
@@ -617,7 +617,7 @@ export class Bot {
|
|
|
617
617
|
workdir: this.workdir,
|
|
618
618
|
files: [],
|
|
619
619
|
sessionId: null,
|
|
620
|
-
title: title ||
|
|
620
|
+
title: title || 'New session',
|
|
621
621
|
});
|
|
622
622
|
const runtime = this.upsertSessionRuntime({
|
|
623
623
|
agent: cs.agent,
|
|
@@ -767,6 +767,61 @@ export class Bot {
|
|
|
767
767
|
}
|
|
768
768
|
return { task, interrupted: false, cancelled: false };
|
|
769
769
|
}
|
|
770
|
+
/**
|
|
771
|
+
* Steer: interrupt the running task so a queued task (identified by actionId) runs next.
|
|
772
|
+
* Returns { task, interrupted } where task is the queued task and interrupted indicates
|
|
773
|
+
* whether a running task was aborted.
|
|
774
|
+
*/
|
|
775
|
+
steerTaskByActionId(actionId) {
|
|
776
|
+
const taskId = this.taskKeysByActionId.get(String(actionId));
|
|
777
|
+
if (!taskId)
|
|
778
|
+
return { task: null, interrupted: false };
|
|
779
|
+
const task = this.activeTasks.get(taskId) || null;
|
|
780
|
+
if (!task || task.status !== 'queued')
|
|
781
|
+
return { task, interrupted: false };
|
|
782
|
+
const interrupted = this.interruptRunningTask(task.sessionKey);
|
|
783
|
+
return { task, interrupted };
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* Interrupt only the currently running task for a session, leaving queued tasks intact.
|
|
787
|
+
* Used by the "Steer" action to let a queued task run next.
|
|
788
|
+
*/
|
|
789
|
+
interruptRunningTask(sessionKey) {
|
|
790
|
+
const session = this.getSessionRuntimeByKey(sessionKey, { allowAnyWorkdir: true });
|
|
791
|
+
if (!session)
|
|
792
|
+
return false;
|
|
793
|
+
for (const taskId of session.runningTaskIds) {
|
|
794
|
+
const task = this.activeTasks.get(taskId);
|
|
795
|
+
if (!task || task.status !== 'running')
|
|
796
|
+
continue;
|
|
797
|
+
try {
|
|
798
|
+
task.abort?.();
|
|
799
|
+
}
|
|
800
|
+
catch { }
|
|
801
|
+
return true;
|
|
802
|
+
}
|
|
803
|
+
return false;
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* Return the number of tasks ahead of the given task in its session queue.
|
|
807
|
+
* Counts running + queued (non-cancelled) tasks that were started before this one.
|
|
808
|
+
*/
|
|
809
|
+
getQueuePosition(sessionKey, taskId) {
|
|
810
|
+
const session = this.getSessionRuntimeByKey(sessionKey, { allowAnyWorkdir: true });
|
|
811
|
+
if (!session)
|
|
812
|
+
return 0;
|
|
813
|
+
let ahead = 0;
|
|
814
|
+
for (const otherId of session.runningTaskIds) {
|
|
815
|
+
if (otherId === taskId)
|
|
816
|
+
continue;
|
|
817
|
+
const other = this.activeTasks.get(otherId);
|
|
818
|
+
if (!other || other.cancelled)
|
|
819
|
+
continue;
|
|
820
|
+
if (other.status === 'running' || other.status === 'queued')
|
|
821
|
+
ahead++;
|
|
822
|
+
}
|
|
823
|
+
return ahead;
|
|
824
|
+
}
|
|
770
825
|
sourceMessageKey(chatId, sourceMessageId) {
|
|
771
826
|
return `${String(chatId)}:${String(sourceMessageId)}`;
|
|
772
827
|
}
|
package/dist/channel-feishu.js
CHANGED
|
@@ -423,7 +423,8 @@ class FeishuChannel extends Channel {
|
|
|
423
423
|
this._log(`[recv] skipped: not mentioned in group ${chatId}`);
|
|
424
424
|
return;
|
|
425
425
|
}
|
|
426
|
-
const
|
|
426
|
+
const parentId = typeof msg.parent_id === 'string' && msg.parent_id ? msg.parent_id : null;
|
|
427
|
+
const ctx = this._makeCtx(chatId, messageId, from, chatType, event, parentId);
|
|
427
428
|
// Parse message content
|
|
428
429
|
let text = '';
|
|
429
430
|
const files = [];
|
|
@@ -1031,12 +1032,13 @@ class FeishuChannel extends Channel {
|
|
|
1031
1032
|
// ========================================================================
|
|
1032
1033
|
// Internal helpers
|
|
1033
1034
|
// ========================================================================
|
|
1034
|
-
_makeCtx(chatId, messageId, from, chatType, raw) {
|
|
1035
|
+
_makeCtx(chatId, messageId, from, chatType, raw, replyToMessageId) {
|
|
1035
1036
|
return {
|
|
1036
1037
|
chatId,
|
|
1037
1038
|
messageId,
|
|
1038
1039
|
from,
|
|
1039
1040
|
chatType,
|
|
1041
|
+
replyToMessageId: replyToMessageId || null,
|
|
1040
1042
|
reply: (text, opts) => this.send(chatId, text, { ...opts, replyTo: messageId || opts?.replyTo }),
|
|
1041
1043
|
editReply: (msgId, text, opts) => this.editMessage(chatId, msgId, text, opts),
|
|
1042
1044
|
channel: this,
|
package/dist/code-agent.js
CHANGED
|
@@ -748,8 +748,7 @@ export function stageSessionFiles(opts) {
|
|
|
748
748
|
const importedFiles = importFilesIntoWorkspace(session.workspacePath, opts.files);
|
|
749
749
|
if (importedFiles.length) {
|
|
750
750
|
session.record.stagedFiles = dedupeStrings([...session.record.stagedFiles, ...importedFiles]);
|
|
751
|
-
|
|
752
|
-
session.record.title = importedFiles[0];
|
|
751
|
+
/* title will be set when the first text prompt arrives */
|
|
753
752
|
saveSessionRecord(opts.workdir, session.record);
|
|
754
753
|
}
|
|
755
754
|
return { sessionId: session.sessionId, workspacePath: session.workspacePath, importedFiles };
|
|
@@ -890,7 +889,7 @@ function prepareStreamOpts(opts) {
|
|
|
890
889
|
const stagedFiles = [...session.record.stagedFiles];
|
|
891
890
|
session.record.stagedFiles = [];
|
|
892
891
|
if (!session.record.title)
|
|
893
|
-
session.record.title = summarizePromptTitle(opts.prompt) ||
|
|
892
|
+
session.record.title = summarizePromptTitle(opts.prompt) || null;
|
|
894
893
|
setSessionRunState(session.record, 'running', null);
|
|
895
894
|
saveSessionRecord(opts.workdir, session.record);
|
|
896
895
|
const attachmentPaths = attachmentRelPaths.map(relPath => path.join(session.workspacePath, relPath));
|
package/package.json
CHANGED