pikiclaw 0.2.52 → 0.2.54
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 -1
- package/dist/bot-feishu-render.js +3 -1
- package/dist/bot-feishu.js +15 -1
- package/dist/bot-telegram-render.js +4 -2
- package/dist/bot-telegram.js +2 -1
- package/dist/channel-feishu.js +14 -1
- package/dist/code-agent.js +36 -4
- package/dist/dashboard-ui.js +11 -11
- package/dist/driver-codex.js +20 -3
- package/dist/driver-gemini.js +126 -11
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -199,8 +199,10 @@ export function buildHumanLoopPromptMarkdown(prompt) {
|
|
|
199
199
|
// ---------------------------------------------------------------------------
|
|
200
200
|
// LivePreview renderer — produces Markdown for Feishu card elements
|
|
201
201
|
// ---------------------------------------------------------------------------
|
|
202
|
-
export function buildInitialPreviewMarkdown(agent, model, effort) {
|
|
202
|
+
export function buildInitialPreviewMarkdown(agent, model, effort, waiting = false) {
|
|
203
203
|
const parts = [];
|
|
204
|
+
if (waiting)
|
|
205
|
+
parts.push('Waiting in queue...');
|
|
204
206
|
if (model)
|
|
205
207
|
parts.push(model);
|
|
206
208
|
else
|
package/dist/bot-feishu.js
CHANGED
|
@@ -28,6 +28,7 @@ const SHUTDOWN_EXIT_CODE = {
|
|
|
28
28
|
SIGINT: 130,
|
|
29
29
|
SIGTERM: 143,
|
|
30
30
|
};
|
|
31
|
+
const FEISHU_FILE_STAGE_REACTION = 'Get';
|
|
31
32
|
function describeError(err) {
|
|
32
33
|
if (!(err instanceof Error))
|
|
33
34
|
return String(err ?? 'unknown error');
|
|
@@ -464,6 +465,17 @@ export class FeishuBot extends Bot {
|
|
|
464
465
|
return active.result;
|
|
465
466
|
};
|
|
466
467
|
}
|
|
468
|
+
async safeSetMessageReaction(chatId, messageId, reactions) {
|
|
469
|
+
if (!supportsChannelCapability(this.channel, 'messageReactions'))
|
|
470
|
+
return;
|
|
471
|
+
const setReaction = this.channel?.setMessageReaction;
|
|
472
|
+
if (typeof setReaction !== 'function')
|
|
473
|
+
return;
|
|
474
|
+
try {
|
|
475
|
+
await setReaction.call(this.channel, chatId, messageId, reactions);
|
|
476
|
+
}
|
|
477
|
+
catch { }
|
|
478
|
+
}
|
|
467
479
|
// ---- streaming bridge -----------------------------------------------------
|
|
468
480
|
async handleMessage(msg, ctx) {
|
|
469
481
|
const text = msg.text.trim();
|
|
@@ -507,6 +519,7 @@ export class FeishuBot extends Bot {
|
|
|
507
519
|
throw new Error('no files persisted');
|
|
508
520
|
this.log(`[handleMessage] staged files chat=${ctx.chatId} session=${staged.sessionId} files=${staged.importedFiles.length}`);
|
|
509
521
|
this.registerSessionMessage(ctx.chatId, ctx.messageId, session);
|
|
522
|
+
await this.safeSetMessageReaction(ctx.chatId, ctx.messageId, [FEISHU_FILE_STAGE_REACTION]);
|
|
510
523
|
}
|
|
511
524
|
catch (e) {
|
|
512
525
|
this.log(`[handleMessage] stage files failed: ${e?.message || e}`);
|
|
@@ -525,6 +538,7 @@ export class FeishuBot extends Bot {
|
|
|
525
538
|
const start = Date.now();
|
|
526
539
|
this.log(`[handleMessage] start chat=${ctx.chatId} agent=${session.agent} session=${session.sessionId || '(new)'} ` +
|
|
527
540
|
`files=${files.length} prompt="${prompt.slice(0, 100)}"`);
|
|
541
|
+
const waiting = this.sessionHasPendingWork(session);
|
|
528
542
|
const taskId = this.createTaskId(session);
|
|
529
543
|
this.beginTask({
|
|
530
544
|
taskId,
|
|
@@ -538,7 +552,7 @@ export class FeishuBot extends Bot {
|
|
|
538
552
|
const stopKeyboard = this.buildStopKeyboard(this.actionIdForTask(taskId));
|
|
539
553
|
const model = session.modelId || this.modelForAgent(session.agent);
|
|
540
554
|
const effort = this.effortForAgent(session.agent);
|
|
541
|
-
const placeholderId = await this.channel.sendStreamingCard(ctx.chatId, buildInitialPreviewMarkdown(session.agent, model, effort), {
|
|
555
|
+
const placeholderId = await this.channel.sendStreamingCard(ctx.chatId, buildInitialPreviewMarkdown(session.agent, model, effort, waiting), {
|
|
542
556
|
replyTo: ctx.messageId || undefined,
|
|
543
557
|
keyboard: stopKeyboard,
|
|
544
558
|
});
|
|
@@ -327,8 +327,10 @@ function trimActivityForPreview(text, maxChars = 900) {
|
|
|
327
327
|
return text.slice(0, Math.max(0, maxChars - 3)).trimEnd() + '...';
|
|
328
328
|
return [...head, '...', ...tail].join('\n');
|
|
329
329
|
}
|
|
330
|
-
export function buildInitialPreviewHtml(agent) {
|
|
331
|
-
return
|
|
330
|
+
export function buildInitialPreviewHtml(agent, waiting = false) {
|
|
331
|
+
return waiting
|
|
332
|
+
? `<i>Waiting in queue...</i>\n\n${formatPreviewFooterHtml(agent, 0)}`
|
|
333
|
+
: formatPreviewFooterHtml(agent, 0);
|
|
332
334
|
}
|
|
333
335
|
export function buildStreamPreviewHtml(input) {
|
|
334
336
|
const maxBody = 2400;
|
package/dist/bot-telegram.js
CHANGED
|
@@ -502,9 +502,10 @@ export class TelegramBot extends Bot {
|
|
|
502
502
|
sourceMessageId: ctx.messageId,
|
|
503
503
|
});
|
|
504
504
|
const stopKeyboard = this.buildStopKeyboard(this.actionIdForTask(taskId));
|
|
505
|
+
const waiting = this.sessionHasPendingWork(session);
|
|
505
506
|
let phId = null;
|
|
506
507
|
if (canEditMessages) {
|
|
507
|
-
const placeholderId = await ctx.reply(buildInitialPreviewHtml(session.agent), { parseMode: 'HTML', messageThreadId, keyboard: stopKeyboard });
|
|
508
|
+
const placeholderId = await ctx.reply(buildInitialPreviewHtml(session.agent, waiting), { parseMode: 'HTML', messageThreadId, keyboard: stopKeyboard });
|
|
508
509
|
phId = typeof placeholderId === 'number' ? placeholderId : null;
|
|
509
510
|
if (phId != null) {
|
|
510
511
|
this.registerSessionMessage(ctx.chatId, phId, session);
|
package/dist/channel-feishu.js
CHANGED
|
@@ -217,7 +217,7 @@ class FeishuChannel extends Channel {
|
|
|
217
217
|
typingIndicators: false,
|
|
218
218
|
commandMenu: true,
|
|
219
219
|
callbackActions: true,
|
|
220
|
-
messageReactions:
|
|
220
|
+
messageReactions: true,
|
|
221
221
|
fileUpload: true,
|
|
222
222
|
fileDownload: true,
|
|
223
223
|
threads: false,
|
|
@@ -710,6 +710,19 @@ class FeishuChannel extends Channel {
|
|
|
710
710
|
async sendTyping(_chatId) {
|
|
711
711
|
// Feishu has no typing indicator API — no-op
|
|
712
712
|
}
|
|
713
|
+
async setMessageReaction(_chatId, msgId, reactions) {
|
|
714
|
+
const messageId = String(msgId || '').trim();
|
|
715
|
+
const emojiTypes = [...new Set(reactions.map(reaction => String(reaction || '').trim()).filter(Boolean))];
|
|
716
|
+
if (!messageId || !emojiTypes.length)
|
|
717
|
+
return;
|
|
718
|
+
this._logOutgoing('setReaction', `msg_id=${messageId} reactions=${emojiTypes.join(',')}`);
|
|
719
|
+
for (const emojiType of emojiTypes) {
|
|
720
|
+
await this.client.im.messageReaction.create({
|
|
721
|
+
path: { message_id: messageId },
|
|
722
|
+
data: { reaction_type: { emoji_type: emojiType } },
|
|
723
|
+
}).catch(() => { });
|
|
724
|
+
}
|
|
725
|
+
}
|
|
713
726
|
// ========================================================================
|
|
714
727
|
// Streaming cards (CardKit v1) — typewriter effect
|
|
715
728
|
// ========================================================================
|
package/dist/code-agent.js
CHANGED
|
@@ -97,6 +97,36 @@ export function shortValue(value, max = 90) {
|
|
|
97
97
|
return text;
|
|
98
98
|
return `${text.slice(0, Math.max(0, max - 3)).trimEnd()}...`;
|
|
99
99
|
}
|
|
100
|
+
export function normalizeErrorMessage(value) {
|
|
101
|
+
if (typeof value === 'string')
|
|
102
|
+
return value.trim();
|
|
103
|
+
if (value instanceof Error)
|
|
104
|
+
return value.message.trim();
|
|
105
|
+
if (Array.isArray(value)) {
|
|
106
|
+
return value.map(item => normalizeErrorMessage(item)).filter(Boolean).join('; ').trim();
|
|
107
|
+
}
|
|
108
|
+
if (value && typeof value === 'object') {
|
|
109
|
+
const record = value;
|
|
110
|
+
const preferred = normalizeErrorMessage(record.message)
|
|
111
|
+
|| normalizeErrorMessage(record.error)
|
|
112
|
+
|| normalizeErrorMessage(record.detail)
|
|
113
|
+
|| normalizeErrorMessage(record.type)
|
|
114
|
+
|| normalizeErrorMessage(record.code)
|
|
115
|
+
|| normalizeErrorMessage(record.status);
|
|
116
|
+
if (preferred)
|
|
117
|
+
return preferred;
|
|
118
|
+
try {
|
|
119
|
+
return JSON.stringify(value).trim();
|
|
120
|
+
}
|
|
121
|
+
catch { }
|
|
122
|
+
}
|
|
123
|
+
return value == null ? '' : String(value).trim();
|
|
124
|
+
}
|
|
125
|
+
export function joinErrorMessages(errors) {
|
|
126
|
+
if (!errors?.length)
|
|
127
|
+
return '';
|
|
128
|
+
return errors.map(error => normalizeErrorMessage(error)).filter(Boolean).join('; ').trim();
|
|
129
|
+
}
|
|
100
130
|
export function appendSystemPrompt(base, extra) {
|
|
101
131
|
const lhs = String(base || '').trim();
|
|
102
132
|
const rhs = String(extra || '').trim();
|
|
@@ -655,6 +685,7 @@ export async function run(cmd, opts, parseLine) {
|
|
|
655
685
|
recentActivity: [],
|
|
656
686
|
claudeToolsById: new Map(),
|
|
657
687
|
seenClaudeToolIds: new Set(),
|
|
688
|
+
geminiToolsById: new Map(),
|
|
658
689
|
};
|
|
659
690
|
const shellCmd = cmd.map(Q).join(' ');
|
|
660
691
|
agentLog(`[spawn] full command: cd ${Q(opts.workdir)} && ${shellCmd}`);
|
|
@@ -729,16 +760,17 @@ export async function run(cmd, opts, parseLine) {
|
|
|
729
760
|
s.text = s.msgs.join('\n\n');
|
|
730
761
|
if (!s.thinking.trim() && s.thinkParts.length)
|
|
731
762
|
s.thinking = s.thinkParts.join('\n\n');
|
|
763
|
+
const errorText = joinErrorMessages(s.errors);
|
|
732
764
|
const ok = procOk && !s.errors && !timedOut && !interrupted;
|
|
733
|
-
const error =
|
|
765
|
+
const error = errorText
|
|
734
766
|
|| (interrupted ? 'Interrupted by user.' : null)
|
|
735
767
|
|| (timedOut ? `Timed out after ${opts.timeout}s before the agent reported completion.` : null)
|
|
736
768
|
|| (!procOk ? (stderr.trim() || `Failed (exit=${code}).`) : null);
|
|
737
769
|
const incomplete = !ok || s.stopReason === 'max_tokens' || s.stopReason === 'timeout';
|
|
738
770
|
const elapsed = ((Date.now() - start) / 1000).toFixed(1);
|
|
739
771
|
agentLog(`[result] ok=${ok && !s.errors} elapsed=${elapsed}s text=${s.text.length}chars thinking=${s.thinking.length}chars session=${s.sessionId || '?'}`);
|
|
740
|
-
if (
|
|
741
|
-
agentLog(`[result] errors: ${
|
|
772
|
+
if (errorText)
|
|
773
|
+
agentLog(`[result] errors: ${errorText}`);
|
|
742
774
|
if (s.stopReason)
|
|
743
775
|
agentLog(`[result] stop_reason=${s.stopReason}`);
|
|
744
776
|
if (stderr.trim() && !procOk)
|
|
@@ -746,7 +778,7 @@ export async function run(cmd, opts, parseLine) {
|
|
|
746
778
|
return {
|
|
747
779
|
ok, sessionId: s.sessionId, workspacePath: null,
|
|
748
780
|
model: s.model, thinkingEffort: s.thinkingEffort,
|
|
749
|
-
message: s.text.trim() ||
|
|
781
|
+
message: s.text.trim() || errorText || (procOk ? '(no textual response)' : `Failed (exit=${code}).\n\n${stderr.trim() || '(no output)'}`),
|
|
750
782
|
thinking: s.thinking.trim() || null,
|
|
751
783
|
elapsedS: (Date.now() - start) / 1000,
|
|
752
784
|
inputTokens: s.inputTokens, outputTokens: s.outputTokens, cachedInputTokens: s.cachedInputTokens,
|