bloby-bot 0.70.12 → 0.71.0
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/bin/cli.js +234 -48
- package/dist-bloby/assets/{bloby-DSNB0g4w.js → bloby-es6cZJzs.js} +6 -6
- package/dist-bloby/assets/globals-DBqwNiJV.css +2 -0
- package/dist-bloby/assets/{globals-B3cTbITX.js → globals-DN3F0CQE.js} +1 -1
- package/dist-bloby/assets/{highlighted-body-OFNGDK62-BLforpkr.js → highlighted-body-OFNGDK62-8PiOHw9p.js} +1 -1
- package/dist-bloby/assets/mermaid-GHXKKRXX-BJWX8urU.js +1 -0
- package/dist-bloby/assets/{onboard-Dn2Ws_G2.js → onboard-BKgy17OU.js} +1 -1
- package/dist-bloby/bloby.html +3 -3
- package/dist-bloby/onboard.html +3 -3
- package/package.json +3 -4
- package/scripts/install +156 -41
- package/scripts/install.ps1 +146 -29
- package/scripts/install.sh +156 -41
- package/shared/config.ts +37 -2
- package/shared/relay.ts +3 -1
- package/supervisor/channels/manager.ts +84 -44
- package/supervisor/channels/telegram.ts +57 -16
- package/supervisor/channels/types.ts +4 -1
- package/supervisor/channels/whatsapp.ts +57 -10
- package/supervisor/chat/OnboardWizard.tsx +0 -15
- package/supervisor/chat/src/components/Chat/AudioBubble.tsx +1 -1
- package/supervisor/chat/src/components/Chat/AuthedImage.tsx +16 -3
- package/supervisor/chat/src/components/Chat/BlobyImageCard.tsx +2 -2
- package/supervisor/chat/src/components/Chat/ImageLightbox.tsx +25 -8
- package/supervisor/chat/src/components/Chat/InputBar.tsx +62 -7
- package/supervisor/chat/src/components/Chat/MessageBubble.tsx +37 -18
- package/supervisor/chat/src/components/Chat/MessageList.tsx +3 -3
- package/supervisor/chat/src/hooks/useChat.ts +52 -0
- package/supervisor/chat/src/lib/authedFile.ts +24 -12
- package/supervisor/file-saver.ts +92 -19
- package/supervisor/harnesses/attachment-policy.ts +111 -0
- package/supervisor/harnesses/claude.ts +62 -15
- package/supervisor/harnesses/codex.ts +69 -43
- package/supervisor/harnesses/pi/index.ts +367 -112
- package/supervisor/harnesses/pi/providers/humanize-error.ts +27 -2
- package/supervisor/harnesses/pi/providers/retry.ts +31 -0
- package/supervisor/harnesses/pi/providers/stream-anthropic.ts +31 -3
- package/supervisor/harnesses/pi/providers/stream-google.ts +26 -3
- package/supervisor/harnesses/pi/providers/stream-openai-completions.ts +32 -9
- package/supervisor/harnesses/pi/providers/types.ts +29 -1
- package/supervisor/harnesses/pi/session.ts +143 -3
- package/supervisor/harnesses/pi/test-completion.ts +56 -0
- package/supervisor/harnesses/pi/tools/bash.ts +198 -22
- package/supervisor/harnesses/pi/tools/glob.ts +79 -0
- package/supervisor/harnesses/pi/tools/grep.ts +0 -0
- package/supervisor/harnesses/pi/tools/registry.ts +18 -6
- package/supervisor/harnesses/pi/tools/todo-write.ts +45 -0
- package/supervisor/harnesses/pi/tools/web-fetch.ts +129 -0
- package/supervisor/index.ts +93 -18
- package/supervisor/widget.js +19 -5
- package/worker/db.ts +2 -0
- package/worker/index.ts +18 -1
- package/worker/prompts/bloby-system-prompt-codex.txt +1 -1
- package/worker/prompts/bloby-system-prompt-pi.txt +6 -24
- package/worker/prompts/bloby-system-prompt.txt +1 -1
- package/workspace/client/src/components/Dashboard/DashboardPage.tsx +4 -117
- package/workspace/client/src/components/Dashboard/deleteme_placeholders.tsx +194 -0
- package/workspace/client/src/components/Layout/Sidebar.tsx +52 -30
- package/workspace/client/src/components/deleteme_onboarding/WorkspaceTour.tsx +25 -15
- package/workspace/client/src/components/deleteme_onboarding/tour-theme.css +24 -0
- package/workspace/skills/mac/SKILL.md +13 -4
- package/dist-bloby/assets/globals-DyeW509Y.css +0 -2
- package/dist-bloby/assets/mermaid-GHXKKRXX-C1H_fSCU.js +0 -1
- package/supervisor/public/headphones_spritesheet.webp +0 -0
- package/supervisor/public/spritesheet.webp +0 -0
|
@@ -44,6 +44,15 @@ import type { SavedFile } from '../file-saver.js';
|
|
|
44
44
|
import { getCodexAccessToken } from '../../worker/codex-auth.js';
|
|
45
45
|
import { assembleSystemPrompt } from '../../worker/prompts/prompt-assembler.js';
|
|
46
46
|
import { mirrorSkillsInto } from './skills.js';
|
|
47
|
+
import {
|
|
48
|
+
routeAttachment,
|
|
49
|
+
normalizeImageMediaType,
|
|
50
|
+
approxBase64Bytes,
|
|
51
|
+
buildSavedFilesNote,
|
|
52
|
+
INLINE_TEXT_PER_FILE_CHARS,
|
|
53
|
+
INLINE_TEXT_TOTAL_CHARS,
|
|
54
|
+
MAX_INLINE_IMAGE_BYTES,
|
|
55
|
+
} from './attachment-policy.js';
|
|
47
56
|
import type { OnAgentMessage, RecentMessage, AgentAttachment, AgentQueryRequest, AgentQueryResult } from './types.js';
|
|
48
57
|
export type { RecentMessage, AgentAttachment };
|
|
49
58
|
|
|
@@ -555,42 +564,24 @@ function emitDone(conv: CodexConversation): void {
|
|
|
555
564
|
|
|
556
565
|
/* ── Input building ────────────────────────────────────────────────────── */
|
|
557
566
|
|
|
558
|
-
/**
|
|
559
|
-
*
|
|
560
|
-
*
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
567
|
+
/**
|
|
568
|
+
* Build codex `UserInput` blocks from the user text + saved files + raw
|
|
569
|
+
* attachments. Routing is delegated to the shared attachment-policy so codex
|
|
570
|
+
* stays byte-for-byte consistent with the Claude/PI harnesses. Codex's UserInput
|
|
571
|
+
* has NO native document type (verified against 0.138), so canNativeDocument is
|
|
572
|
+
* FALSE: PDFs/binaries become a disk-pointer note and the agent opens them with
|
|
573
|
+
* its file tools.
|
|
574
|
+
*
|
|
575
|
+
* Block order is MEDIA-first then TEXT (matching Claude/PI): the inline-text
|
|
576
|
+
* notes and the saved-files pointer are folded into the trailing text block.
|
|
577
|
+
*/
|
|
565
578
|
function buildUserInput(text: string, savedFiles?: SavedFile[], attachments?: AgentAttachment[]): Array<Record<string, any>> {
|
|
566
579
|
const input: Array<Record<string, any>> = [];
|
|
567
580
|
|
|
568
|
-
let promptText = text || '(attached files)';
|
|
569
|
-
if (savedFiles?.length) {
|
|
570
|
-
const lines = savedFiles.map((f) => `- ${f.name} -> ${f.relPath}`);
|
|
571
|
-
promptText += `\n\n[Attached files saved to disk]\n${lines.join('\n')}\nYou can read or reference these files using the paths above (relative to your cwd).`;
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
// Inline text-like attachments (size-capped) so the model can answer about
|
|
575
|
-
// their contents immediately instead of shelling out to read them from disk.
|
|
576
|
-
if (attachments?.length) {
|
|
577
|
-
let budget = INLINE_TEXT_TOTAL_BUDGET;
|
|
578
|
-
for (const att of attachments) {
|
|
579
|
-
if (att.type !== 'file' || !INLINE_TEXT_MEDIA.test(att.mediaType || '')) continue;
|
|
580
|
-
const approxBytes = Math.floor((att.data?.length || 0) * 0.75);
|
|
581
|
-
if (approxBytes === 0 || approxBytes > INLINE_TEXT_MAX_BYTES || approxBytes > budget) continue;
|
|
582
|
-
try {
|
|
583
|
-
const decoded = Buffer.from(att.data, 'base64').toString('utf-8');
|
|
584
|
-
budget -= approxBytes;
|
|
585
|
-
promptText += `\n\n[Attached file content: ${att.name}]\n\`\`\`\n${decoded}\n\`\`\``;
|
|
586
|
-
} catch {}
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
input.push({ type: 'text', text: promptText });
|
|
591
|
-
|
|
592
581
|
// Codex understands `localImage` (path on disk) — Bloby's file-saver already
|
|
593
|
-
// wrote attachments to disk, so we
|
|
582
|
+
// wrote image attachments to disk, so we point at the absolute path. Track a
|
|
583
|
+
// per-name COUNT (not presence): WhatsApp multi-image pushes share one
|
|
584
|
+
// attachment name and each saved file covers exactly one of them.
|
|
594
585
|
const savedImageCounts = new Map<string, number>();
|
|
595
586
|
if (savedFiles?.length) {
|
|
596
587
|
for (const f of savedFiles) {
|
|
@@ -601,23 +592,58 @@ function buildUserInput(text: string, savedFiles?: SavedFile[], attachments?: Ag
|
|
|
601
592
|
}
|
|
602
593
|
}
|
|
603
594
|
|
|
604
|
-
//
|
|
605
|
-
//
|
|
606
|
-
//
|
|
607
|
-
//
|
|
608
|
-
|
|
595
|
+
// Route every attachment through the shared policy. Inline-text notes are
|
|
596
|
+
// accumulated into `inlineNotes` (appended to the trailing text block);
|
|
597
|
+
// images become data-URL blocks (with the localImage path already covering
|
|
598
|
+
// disk-saved copies); everything else falls back to the saved-files pointer.
|
|
599
|
+
let promptText = text || '(attached files)';
|
|
600
|
+
const inlineNotes: string[] = [];
|
|
601
|
+
let inlineBudget = INLINE_TEXT_TOTAL_CHARS;
|
|
609
602
|
if (attachments?.length) {
|
|
610
603
|
for (const att of attachments) {
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
604
|
+
switch (routeAttachment(att, { canNativeDocument: false })) {
|
|
605
|
+
case 'image': {
|
|
606
|
+
if (!att.data) break;
|
|
607
|
+
// Skip data-URL inlining when a disk copy exists (localImage already
|
|
608
|
+
// points codex at it) or when the payload is too big to resend on
|
|
609
|
+
// every stateless turn — the saved-files pointer covers it instead.
|
|
610
|
+
const remaining = savedImageCounts.get(att.name) || 0;
|
|
611
|
+
if (remaining > 0) {
|
|
612
|
+
savedImageCounts.set(att.name, remaining - 1);
|
|
613
|
+
break;
|
|
614
|
+
}
|
|
615
|
+
if (approxBase64Bytes(att.data) > MAX_INLINE_IMAGE_BYTES) break;
|
|
616
|
+
const mediaType = normalizeImageMediaType(att.mediaType);
|
|
617
|
+
input.push({ type: 'image', url: `data:${mediaType};base64,${att.data}` });
|
|
618
|
+
break;
|
|
619
|
+
}
|
|
620
|
+
case 'inline-text': {
|
|
621
|
+
if (!att.data) break;
|
|
622
|
+
try {
|
|
623
|
+
let decoded = Buffer.from(att.data, 'base64').toString('utf-8');
|
|
624
|
+
if (decoded.length > INLINE_TEXT_PER_FILE_CHARS) decoded = decoded.slice(0, INLINE_TEXT_PER_FILE_CHARS);
|
|
625
|
+
if (decoded.length > inlineBudget) decoded = decoded.slice(0, inlineBudget);
|
|
626
|
+
if (!decoded.length) break;
|
|
627
|
+
inlineBudget -= decoded.length;
|
|
628
|
+
inlineNotes.push(`\n\n[Attached file content: ${att.name}]\n\`\`\`\n${decoded}\n\`\`\``);
|
|
629
|
+
} catch {}
|
|
630
|
+
break;
|
|
631
|
+
}
|
|
632
|
+
// 'native-document' cannot occur (canNativeDocument:false); it and
|
|
633
|
+
// 'reference-only' both rely on the saved-files disk pointer below.
|
|
634
|
+
default:
|
|
635
|
+
break;
|
|
616
636
|
}
|
|
617
|
-
input.push({ type: 'image', url: `data:${att.mediaType};base64,${att.data}` });
|
|
618
637
|
}
|
|
619
638
|
}
|
|
620
639
|
|
|
640
|
+
for (const note of inlineNotes) promptText += note;
|
|
641
|
+
|
|
642
|
+
const savedNote = buildSavedFilesNote(savedFiles || []);
|
|
643
|
+
if (savedNote) promptText += `\n\n${savedNote}`;
|
|
644
|
+
|
|
645
|
+
input.push({ type: 'text', text: promptText });
|
|
646
|
+
|
|
621
647
|
return input;
|
|
622
648
|
}
|
|
623
649
|
|