bloby-bot 0.70.8 → 0.70.10
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-bloby/assets/{bloby-CXmOcb1r.js → bloby-DSNB0g4w.js} +4 -4
- package/dist-bloby/assets/{globals-DpO5tO92.js → globals-B3cTbITX.js} +1 -1
- package/dist-bloby/assets/{highlighted-body-OFNGDK62-D7cU1Y-Z.js → highlighted-body-OFNGDK62-BLforpkr.js} +1 -1
- package/dist-bloby/assets/mermaid-GHXKKRXX-C1H_fSCU.js +1 -0
- package/dist-bloby/assets/{onboard-B96ELhXn.js → onboard-Dn2Ws_G2.js} +1 -1
- package/dist-bloby/bloby.html +2 -2
- package/dist-bloby/onboard.html +2 -2
- package/package.json +1 -1
- package/scripts/sync-pi-models.ts +37 -6
- package/supervisor/chat/OnboardWizard.tsx +4 -4
- package/supervisor/harnesses/pi/async-queue.ts +7 -11
- package/supervisor/harnesses/pi/index.ts +475 -73
- package/supervisor/harnesses/pi/models-catalog.generated.ts +840 -210
- package/supervisor/harnesses/pi/providers/humanize-error.ts +125 -0
- package/supervisor/harnesses/pi/providers/retry.ts +87 -0
- package/supervisor/harnesses/pi/providers/stream-anthropic.ts +73 -11
- package/supervisor/harnesses/pi/providers/stream-google.ts +15 -5
- package/supervisor/harnesses/pi/providers/stream-openai-completions.ts +55 -19
- package/supervisor/harnesses/pi/providers/types.ts +26 -1
- package/supervisor/harnesses/pi/session.ts +179 -73
- package/supervisor/harnesses/pi/sub-providers.ts +30 -1
- package/supervisor/harnesses/pi/test-completion.ts +8 -2
- package/supervisor/harnesses/pi/tools/registry.ts +25 -9
- package/supervisor/harnesses/pi/tools/task.ts +108 -0
- package/supervisor/harnesses/pi/tools/types.ts +15 -0
- package/supervisor/index.ts +11 -10
- package/supervisor/public/morphy_sad.mov +0 -0
- package/supervisor/public/morphy_sad.webm +0 -0
- package/supervisor/shell.ts +1 -1
- package/supervisor/workspace-guard.js +1 -1
- package/workspace/client/public/morphy_bounce.mov +0 -0
- package/workspace/client/public/morphy_bounce.webm +0 -0
- package/workspace/client/public/morphy_hi.mov +0 -0
- package/workspace/client/public/morphy_hi.webm +0 -0
- package/workspace/client/src/App.tsx +5 -3
- package/dist-bloby/assets/mermaid-GHXKKRXX-D5YxphBn.js +0 -1
- package/supervisor/public/what-happened.mp4 +0 -0
- package/supervisor/public/what-happened.webm +0 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task tool — background sub-agent delegation (audit D4-1, Phase B).
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the Claude Agent SDK's Task tool contract and feel:
|
|
5
|
+
* - the model calls Task({description, prompt, subagent_type})
|
|
6
|
+
* - the tool returns IMMEDIATELY with an acknowledgement, so the parent turn
|
|
7
|
+
* ends in seconds and the chat stays fully conversational
|
|
8
|
+
* - the child runs as an in-process `createPiSession` (Bloby owns the agent
|
|
9
|
+
* loop, so no subprocess is needed — unlike upstream pi's subagent
|
|
10
|
+
* extension, which must spawn the pi CLI)
|
|
11
|
+
* - completion is injected back into the parent's input queue as a synthetic
|
|
12
|
+
* message that drives the user-facing "Done!" continuation turn
|
|
13
|
+
*
|
|
14
|
+
* Also registered under the alias 'Agent' (registry.ts): the pi system prompt
|
|
15
|
+
* sells "the Agent tool" — with this tool live, those sections are true as
|
|
16
|
+
* written, closing the audit's D4-2 finding without a prompt edit.
|
|
17
|
+
*
|
|
18
|
+
* Agent definitions come from `supervisor/agents/index.ts:buildAgents()` —
|
|
19
|
+
* the same roster the Claude harness uses, so both harnesses stay in sync.
|
|
20
|
+
*/
|
|
21
|
+
import type { PiTool } from './types.js';
|
|
22
|
+
import type { PiToolDef } from '../providers/types.js';
|
|
23
|
+
import { buildAgents } from '../../../agents/index.js';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Tool definition with a FRESH subagent enum — built per session start (not at
|
|
27
|
+
* module load) so prompt-file/roster edits apply without a supervisor restart,
|
|
28
|
+
* and so the workspace is guaranteed to exist when prompts are read.
|
|
29
|
+
*/
|
|
30
|
+
export function taskToolDef(): PiToolDef {
|
|
31
|
+
const agents = buildAgents();
|
|
32
|
+
const names = Object.keys(agents);
|
|
33
|
+
return {
|
|
34
|
+
name: 'Task',
|
|
35
|
+
description:
|
|
36
|
+
'Delegate heavy work to a background sub-agent and keep chatting while it runs. ' +
|
|
37
|
+
'Returns immediately — you will automatically receive the result when the agent finishes, ' +
|
|
38
|
+
'so acknowledge the user briefly and end your turn. ' +
|
|
39
|
+
'Available agents: ' +
|
|
40
|
+
(names.map((n) => `${n} (${agents[n].description})`).join('; ') || 'none configured'),
|
|
41
|
+
inputSchema: {
|
|
42
|
+
type: 'object',
|
|
43
|
+
properties: {
|
|
44
|
+
description: {
|
|
45
|
+
type: 'string',
|
|
46
|
+
description: 'Short (3-5 word) description of the task, shown to the user as a progress card.',
|
|
47
|
+
},
|
|
48
|
+
prompt: {
|
|
49
|
+
type: 'string',
|
|
50
|
+
description: 'Complete, self-contained instructions for the sub-agent. It cannot ask follow-up questions — include every detail it needs.',
|
|
51
|
+
},
|
|
52
|
+
subagent_type: {
|
|
53
|
+
type: 'string',
|
|
54
|
+
...(names.length > 0 ? { enum: names } : {}),
|
|
55
|
+
description: 'Which sub-agent to delegate to.',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
required: ['description', 'prompt', 'subagent_type'],
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const taskTool: PiTool = {
|
|
64
|
+
name: 'Task',
|
|
65
|
+
description: 'Delegate heavy work to a background sub-agent.',
|
|
66
|
+
// Static placeholder (no file I/O at module load) — providers receive the
|
|
67
|
+
// dynamic enum schema from taskToolDef() via registry.toolDefsForProvider.
|
|
68
|
+
inputSchema: {
|
|
69
|
+
type: 'object',
|
|
70
|
+
properties: {
|
|
71
|
+
description: { type: 'string' },
|
|
72
|
+
prompt: { type: 'string' },
|
|
73
|
+
subagent_type: { type: 'string' },
|
|
74
|
+
},
|
|
75
|
+
required: ['description', 'prompt', 'subagent_type'],
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
async run(input, ctx) {
|
|
79
|
+
if (!ctx.tasks) {
|
|
80
|
+
return {
|
|
81
|
+
output:
|
|
82
|
+
'The Task tool is not available in this context — do the work yourself with your other tools.',
|
|
83
|
+
isError: true,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
const description = typeof input?.description === 'string' ? input.description.trim() : '';
|
|
87
|
+
const prompt = typeof input?.prompt === 'string' ? input.prompt.trim() : '';
|
|
88
|
+
const subagentType = typeof input?.subagent_type === 'string' ? input.subagent_type.trim() : '';
|
|
89
|
+
if (!prompt) {
|
|
90
|
+
return { output: 'Task requires `prompt` — complete instructions for the sub-agent.', isError: true };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const res = ctx.tasks.spawn({
|
|
94
|
+
description: description || prompt.slice(0, 60),
|
|
95
|
+
prompt,
|
|
96
|
+
subagentType: subagentType || 'coder',
|
|
97
|
+
});
|
|
98
|
+
if (!res.ok) return { output: res.error, isError: true };
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
output:
|
|
102
|
+
`Background task started (id: ${res.taskId}). It is now running while you keep chatting. ` +
|
|
103
|
+
`Tell the user in ONE short sentence that you're on it (your usual voice — never mention ` +
|
|
104
|
+
`agents, tasks, or ids), then end your turn. You will automatically receive the result ` +
|
|
105
|
+
`when it finishes.`,
|
|
106
|
+
};
|
|
107
|
+
},
|
|
108
|
+
};
|
|
@@ -14,11 +14,26 @@ export interface PiToolResult {
|
|
|
14
14
|
isError?: boolean;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Host interface a live conversation exposes to the Task tool so it can spawn
|
|
19
|
+
* background sub-agents (audit D4-1). Only PARENT sessions provide it — child
|
|
20
|
+
* sessions get `ctx.tasks` undefined, so a sub-agent cannot spawn
|
|
21
|
+
* grandchildren (Claude SDK parity).
|
|
22
|
+
*/
|
|
23
|
+
export interface PiTaskHost {
|
|
24
|
+
/** Spawn a background sub-agent. Returns synchronously; the child runs detached. */
|
|
25
|
+
spawn(req: { description: string; prompt: string; subagentType: string }):
|
|
26
|
+
| { ok: true; taskId: string }
|
|
27
|
+
| { ok: false; error: string };
|
|
28
|
+
}
|
|
29
|
+
|
|
17
30
|
export interface PiToolContext {
|
|
18
31
|
/** Workspace root — every tool resolves paths against this. */
|
|
19
32
|
cwd: string;
|
|
20
33
|
/** Aborted when the session ends so long-running tools stop fast. */
|
|
21
34
|
signal?: AbortSignal;
|
|
35
|
+
/** Present only in live parent sessions — lets the Task tool spawn sub-agents. */
|
|
36
|
+
tasks?: PiTaskHost;
|
|
22
37
|
}
|
|
23
38
|
|
|
24
39
|
export interface PiTool {
|
package/supervisor/index.ts
CHANGED
|
@@ -91,8 +91,8 @@ const PLATFORM_ASSETS = new Set([
|
|
|
91
91
|
'/pi-logo.svg',
|
|
92
92
|
'/codex.svg',
|
|
93
93
|
'/manifest.json',
|
|
94
|
-
'/
|
|
95
|
-
'/
|
|
94
|
+
'/morphy_sad.webm',
|
|
95
|
+
'/morphy_sad.mov',
|
|
96
96
|
]);
|
|
97
97
|
|
|
98
98
|
// Directory-prefix platform assets — anything under these is served from supervisor/public/.
|
|
@@ -313,8 +313,8 @@ const RECOVERING_HTML = `<!DOCTYPE html>
|
|
|
313
313
|
</style></head>
|
|
314
314
|
<body><div class="c">
|
|
315
315
|
<div class="video-wrap"><video autoplay loop muted playsinline>
|
|
316
|
-
<source src="/
|
|
317
|
-
<source src="/
|
|
316
|
+
<source src="/morphy_sad.mov" type='video/mp4; codecs="hvc1"'>
|
|
317
|
+
<source src="/morphy_sad.webm" type="video/webm">
|
|
318
318
|
</video></div>
|
|
319
319
|
<h1>Reconnecting…</h1>
|
|
320
320
|
<p class="lead">Hang tight — your app is coming back online.</p>
|
|
@@ -378,8 +378,8 @@ function backendDownPage(logTail: string): string {
|
|
|
378
378
|
</style></head>
|
|
379
379
|
<body><div class="c">
|
|
380
380
|
<div class="video-wrap"><video autoplay loop muted playsinline>
|
|
381
|
-
<source src="/
|
|
382
|
-
<source src="/
|
|
381
|
+
<source src="/morphy_sad.mov" type='video/mp4; codecs="hvc1"'>
|
|
382
|
+
<source src="/morphy_sad.webm" type="video/webm">
|
|
383
383
|
</video></div>
|
|
384
384
|
<h1>Your app's backend is down</h1>
|
|
385
385
|
<p class="lead">The workspace server crashed and couldn't restart on its own.</p>
|
|
@@ -1140,7 +1140,7 @@ export async function startSupervisor() {
|
|
|
1140
1140
|
<div class="container">
|
|
1141
1141
|
${connected
|
|
1142
1142
|
? `<div class="confetti-wrap">${confettiHTML}</div>
|
|
1143
|
-
<div class="video-wrap"><video autoplay muted playsinline><source src="/
|
|
1143
|
+
<div class="video-wrap"><video autoplay muted playsinline><source src="/morphy_bounce.mov" type='video/mp4; codecs="hvc1"'><source src="/morphy_bounce.webm" type="video/webm"></video></div>
|
|
1144
1144
|
<div class="text-wrap"><div class="title">Connected!</div><p class="subtitle">WhatsApp is linked. You can close this page.</p>
|
|
1145
1145
|
<button onclick="relink()" style="margin-top:20px;padding:10px 24px;background:#2a2a2a;border:1px solid rgba(255,255,255,0.15);border-radius:10px;color:#999;font-size:13px;cursor:pointer;font-family:inherit;transition:all .2s" onmouseover="this.style.borderColor='#0069FE';this.style.color='#f5f5f5'" onmouseout="this.style.borderColor='rgba(255,255,255,0.15)';this.style.color='#999'">Relink to a different number</button>
|
|
1146
1146
|
</div>
|
|
@@ -1628,7 +1628,7 @@ ${!connected ? `<script>
|
|
|
1628
1628
|
<div class="container" id="root">
|
|
1629
1629
|
${alreadyLinked
|
|
1630
1630
|
? `<div class="confetti-wrap">${confettiHTML}</div>
|
|
1631
|
-
<div class="video-wrap"><video autoplay muted playsinline><source src="/
|
|
1631
|
+
<div class="video-wrap"><video autoplay muted playsinline><source src="/morphy_bounce.mov" type='video/mp4; codecs="hvc1"'><source src="/morphy_bounce.webm" type="video/webm"></video></div>
|
|
1632
1632
|
<div class="text-wrap">
|
|
1633
1633
|
<div class="title">Connected!</div>
|
|
1634
1634
|
<p class="success-sub">Alexa is linked. Say <b style="color:#f5f5f5">"Alexa, open Morphy Agent"</b> to start a conversation, or <b style="color:#f5f5f5">"Alexa, tell Morphy Agent <command>"</b> for one-shots.</p>
|
|
@@ -1991,7 +1991,7 @@ mint();
|
|
|
1991
1991
|
<div class="container" id="root">
|
|
1992
1992
|
${alreadyLinked
|
|
1993
1993
|
? `<div class="confetti-wrap">${confettiHTML}</div>
|
|
1994
|
-
<div class="video-wrap"><video autoplay muted playsinline><source src="/
|
|
1994
|
+
<div class="video-wrap"><video autoplay muted playsinline><source src="/morphy_bounce.mov" type='video/mp4; codecs="hvc1"'><source src="/morphy_bounce.webm" type="video/webm"></video></div>
|
|
1995
1995
|
<div class="text-wrap">
|
|
1996
1996
|
<div class="title">Connected!</div>
|
|
1997
1997
|
<p class="success-sub">Telegram is linked${linkedUsername ? ` to <b style="color:#f5f5f5">@${linkedUsername}</b>` : ''}. Open Telegram and message your bot to start chatting.</p>
|
|
@@ -2844,7 +2844,8 @@ ${alreadyLinked ? '' : `
|
|
|
2844
2844
|
}
|
|
2845
2845
|
|
|
2846
2846
|
// Bloby routes → serve pre-built static files from dist-bloby/
|
|
2847
|
-
// Note: must check '/bloby/' (with slash)
|
|
2847
|
+
// Note: must check '/bloby/' (with slash) so the route only claims the chat UI under
|
|
2848
|
+
// /bloby/, never a root-served asset that merely starts with "bloby".
|
|
2848
2849
|
if (req.url === '/bloby' || req.url?.startsWith('/bloby/')) {
|
|
2849
2850
|
// Strip /bloby prefix, then query strings, then resolve file path
|
|
2850
2851
|
let filePath = req.url!.replace(/^\/bloby\/?/, '').split('?')[0] || 'bloby.html';
|
|
Binary file
|
|
Binary file
|
package/supervisor/shell.ts
CHANGED
|
@@ -170,7 +170,7 @@ export const SHELL_HTML = `<!DOCTYPE html>
|
|
|
170
170
|
// preload=auto so the clip is fetched (and SW-cached) while the supervisor is
|
|
171
171
|
// still up — by the time we show this, the origin is unreachable.
|
|
172
172
|
'<video autoplay loop muted playsinline preload="auto" style="position:relative;width:100%;height:100%;object-fit:contain;border-radius:50%">' +
|
|
173
|
-
'<source src="/
|
|
173
|
+
'<source src="/morphy_sad.webm" type="video/webm"><source src="/morphy_sad.mov" type="video/mp4">' +
|
|
174
174
|
'</video>' +
|
|
175
175
|
'</div>' +
|
|
176
176
|
'<h1 style="font-size:1.5rem;font-weight:700;margin:0 0 .6rem;background:linear-gradient(135deg,#0166FF,#009AFE,#4AEEFF);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">Workspace is restarting…</h1>' +
|
|
@@ -562,7 +562,7 @@
|
|
|
562
562
|
'<div style="position:relative;width:160px;height:160px;margin:0 auto 1.2rem">' +
|
|
563
563
|
'<div style="position:absolute;inset:-18px;background:radial-gradient(circle,rgba(1,102,255,.18) 0%,transparent 60%);filter:blur(18px)"></div>' +
|
|
564
564
|
'<video autoplay loop muted playsinline style="position:relative;width:100%;height:100%;object-fit:contain;border-radius:50%">' +
|
|
565
|
-
'<source src="/
|
|
565
|
+
'<source src="/morphy_sad.webm" type="video/webm"><source src="/morphy_sad.mov" type="video/mp4">' +
|
|
566
566
|
'</video>' +
|
|
567
567
|
'</div>' +
|
|
568
568
|
'<h1 style="font-size:1.5rem;font-weight:700;margin:0 0 .6rem;background:linear-gradient(135deg,#0166FF,#009AFE,#4AEEFF);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text">Workspace error</h1>' +
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -9,13 +9,15 @@ function DashboardError() {
|
|
|
9
9
|
return (
|
|
10
10
|
<div style={{ background: '#222122', color: '#fff', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', height: '100dvh', width: '100vw', position: 'fixed', inset: 0, zIndex: 50, fontFamily: 'system-ui, -apple-system, sans-serif', textAlign: 'center', padding: '24px' }}>
|
|
11
11
|
<video
|
|
12
|
-
src="/bloby_say_hi.webm"
|
|
13
12
|
autoPlay
|
|
14
13
|
loop
|
|
15
14
|
muted
|
|
16
15
|
playsInline
|
|
17
|
-
style={{ height: 120,
|
|
18
|
-
|
|
16
|
+
style={{ height: 120, objectFit: 'contain', marginBottom: 32 }}
|
|
17
|
+
>
|
|
18
|
+
<source src="/morphy_hi.mov" type='video/mp4; codecs="hvc1"' />
|
|
19
|
+
<source src="/morphy_hi.webm" type="video/webm" />
|
|
20
|
+
</video>
|
|
19
21
|
<h1 style={{ fontSize: 20, fontWeight: 600, marginBottom: 8 }}>Oopss.. Something wrong is not right</h1>
|
|
20
22
|
<p style={{ fontSize: 14, color: 'rgba(255,255,255,0.5)', maxWidth: 320, lineHeight: 1.5 }}>
|
|
21
23
|
If your agent is working, this is normal. If not, go poke them
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{i as e}from"./bloby-CXmOcb1r.js";export{e as Mermaid};
|
|
Binary file
|
|
Binary file
|