@frockbot/plugin-shell 0.3.20 → 0.3.21
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/package.json +32 -32
- package/src/agent.test.ts +32 -0
- package/src/agent.ts +27 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frockbot/plugin-shell",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.21",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -52,42 +52,42 @@
|
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@cordisjs/plugin-webui": "0.8.2",
|
|
55
|
-
"@frockbot/agent-runtime": "0.3.
|
|
56
|
-
"@frockbot/application-foundation": "0.3.
|
|
57
|
-
"@frockbot/catalog-core": "0.3.
|
|
58
|
-
"@frockbot/client-core": "0.3.
|
|
59
|
-
"@frockbot/client-ui": "0.3.
|
|
60
|
-
"@frockbot/computer-core": "0.3.
|
|
61
|
-
"@frockbot/computer-host-protocol": "0.3.
|
|
62
|
-
"@frockbot/configuration-core": "0.3.
|
|
63
|
-
"@frockbot/connection-core": "0.3.
|
|
64
|
-
"@frockbot/kernel-agent-loop": "0.3.
|
|
65
|
-
"@frockbot/kernel-composition": "0.3.
|
|
66
|
-
"@frockbot/kernel-contracts": "0.3.
|
|
67
|
-
"@frockbot/kernel-do": "0.3.
|
|
68
|
-
"@frockbot/machine-protocol": "0.3.
|
|
69
|
-
"@frockbot/plugin-applets": "0.3.
|
|
70
|
-
"@frockbot/plugin-authoring": "0.3.
|
|
71
|
-
"@frockbot/plugin-bot-template": "0.3.
|
|
72
|
-
"@frockbot/plugin-computer": "0.3.
|
|
73
|
-
"@frockbot/plugin-flock": "0.3.
|
|
74
|
-
"@frockbot/plugin-image": "0.3.
|
|
75
|
-
"@frockbot/plugin-machine-messages": "0.3.
|
|
76
|
-
"@frockbot/plugin-mcp": "0.3.
|
|
77
|
-
"@frockbot/plugin-memory": "0.3.
|
|
78
|
-
"@frockbot/plugin-package-catalog": "0.3.
|
|
79
|
-
"@frockbot/plugin-routines": "0.3.
|
|
80
|
-
"@frockbot/plugin-skills": "0.3.
|
|
81
|
-
"@frockbot/plugin-subagents": "0.3.
|
|
82
|
-
"@frockbot/plugin-user-machine": "0.3.
|
|
83
|
-
"@frockbot/protocol": "0.3.
|
|
55
|
+
"@frockbot/agent-runtime": "0.3.21",
|
|
56
|
+
"@frockbot/application-foundation": "0.3.21",
|
|
57
|
+
"@frockbot/catalog-core": "0.3.21",
|
|
58
|
+
"@frockbot/client-core": "0.3.21",
|
|
59
|
+
"@frockbot/client-ui": "0.3.21",
|
|
60
|
+
"@frockbot/computer-core": "0.3.21",
|
|
61
|
+
"@frockbot/computer-host-protocol": "0.3.21",
|
|
62
|
+
"@frockbot/configuration-core": "0.3.21",
|
|
63
|
+
"@frockbot/connection-core": "0.3.21",
|
|
64
|
+
"@frockbot/kernel-agent-loop": "0.3.21",
|
|
65
|
+
"@frockbot/kernel-composition": "0.3.21",
|
|
66
|
+
"@frockbot/kernel-contracts": "0.3.21",
|
|
67
|
+
"@frockbot/kernel-do": "0.3.21",
|
|
68
|
+
"@frockbot/machine-protocol": "0.3.21",
|
|
69
|
+
"@frockbot/plugin-applets": "0.3.21",
|
|
70
|
+
"@frockbot/plugin-authoring": "0.3.21",
|
|
71
|
+
"@frockbot/plugin-bot-template": "0.3.21",
|
|
72
|
+
"@frockbot/plugin-computer": "0.3.21",
|
|
73
|
+
"@frockbot/plugin-flock": "0.3.21",
|
|
74
|
+
"@frockbot/plugin-image": "0.3.21",
|
|
75
|
+
"@frockbot/plugin-machine-messages": "0.3.21",
|
|
76
|
+
"@frockbot/plugin-mcp": "0.3.21",
|
|
77
|
+
"@frockbot/plugin-memory": "0.3.21",
|
|
78
|
+
"@frockbot/plugin-package-catalog": "0.3.21",
|
|
79
|
+
"@frockbot/plugin-routines": "0.3.21",
|
|
80
|
+
"@frockbot/plugin-skills": "0.3.21",
|
|
81
|
+
"@frockbot/plugin-subagents": "0.3.21",
|
|
82
|
+
"@frockbot/plugin-user-machine": "0.3.21",
|
|
83
|
+
"@frockbot/protocol": "0.3.21",
|
|
84
84
|
"cordis": "4.0.0-rc.8",
|
|
85
85
|
"vue": "3.5.41"
|
|
86
86
|
},
|
|
87
87
|
"devDependencies": {
|
|
88
88
|
"@cloudflare/workers-types": "latest",
|
|
89
|
-
"@frockbot/plugin-prompt": "0.3.
|
|
90
|
-
"@frockbot/plugin-tools": "0.3.
|
|
89
|
+
"@frockbot/plugin-prompt": "0.3.21",
|
|
90
|
+
"@frockbot/plugin-tools": "0.3.21",
|
|
91
91
|
"@types/bun": "1.3.6",
|
|
92
92
|
"@types/node": "26.2.0",
|
|
93
93
|
"@vitejs/plugin-vue": "6.0.8",
|
package/src/agent.test.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
type ToolCall,
|
|
8
8
|
type ToolExecutionContext,
|
|
9
9
|
type TurnTypeV1,
|
|
10
|
+
TURN_DEADLINE_MS_V1,
|
|
10
11
|
} from "@frockbot/kernel-contracts";
|
|
11
12
|
import { SystemPromptRegistry } from "@frockbot/plugin-prompt";
|
|
12
13
|
import { ToolRegistry } from "@frockbot/plugin-tools";
|
|
@@ -19,6 +20,7 @@ import {
|
|
|
19
20
|
PARENT_HANDOFF_CAPABILITY_V1,
|
|
20
21
|
SEND_MESSAGE_ALIAS_V1,
|
|
21
22
|
SEND_TO_USER_TOOL_V1,
|
|
23
|
+
TIME_BUDGET_WARNING_MS_V1,
|
|
22
24
|
USER_VOICE_CAPABILITY_V1,
|
|
23
25
|
WAKE_PARENT_TOOL_V1,
|
|
24
26
|
} from "./agent.ts";
|
|
@@ -575,6 +577,36 @@ describe("the acknowledgement reaches the user", () => {
|
|
|
575
577
|
}
|
|
576
578
|
});
|
|
577
579
|
|
|
580
|
+
test("the last two minutes of a Turn tell the model to send a status", async () => {
|
|
581
|
+
const mounted = await mount();
|
|
582
|
+
try {
|
|
583
|
+
const assemble = (remainingMs: number) =>
|
|
584
|
+
mounted.root.systemPrompt.assemble({
|
|
585
|
+
sessionId: "session-1",
|
|
586
|
+
provider: "provider-1",
|
|
587
|
+
model: "model-1",
|
|
588
|
+
turnType: "chat",
|
|
589
|
+
step: { current: 61, max: 64 },
|
|
590
|
+
deadline: {
|
|
591
|
+
at: TURN_DEADLINE_MS_V1,
|
|
592
|
+
now: TURN_DEADLINE_MS_V1 - remainingMs,
|
|
593
|
+
},
|
|
594
|
+
});
|
|
595
|
+
const boundary = await assemble(TIME_BUDGET_WARNING_MS_V1);
|
|
596
|
+
expect(boundary.text).not.toContain("<time_budget>");
|
|
597
|
+
const warning = await assemble(TIME_BUDGET_WARNING_MS_V1 - 1);
|
|
598
|
+
expect(warning.text).toContain("<time_budget>");
|
|
599
|
+
expect(warning.text).toContain("fewer than 2 minutes left");
|
|
600
|
+
expect(warning.text).toContain("Do not start new work");
|
|
601
|
+
expect(warning.text).toContain(SEND_TO_USER_TOOL_V1);
|
|
602
|
+
expect(warning.text.indexOf("<time_budget>")).toBeGreaterThan(
|
|
603
|
+
warning.text.indexOf("<step_budget>"),
|
|
604
|
+
);
|
|
605
|
+
} finally {
|
|
606
|
+
await mounted.dispose();
|
|
607
|
+
}
|
|
608
|
+
});
|
|
609
|
+
|
|
578
610
|
test("a step that already spoke is left alone, and a replay adds nothing", async () => {
|
|
579
611
|
const mounted = await mount();
|
|
580
612
|
try {
|
package/src/agent.ts
CHANGED
|
@@ -234,6 +234,11 @@ export const STEP_BUDGET_PROMPT_SECTION_V1 = "step-budget";
|
|
|
234
234
|
export const STEP_BUDGET_PROMPT_ORDER_V1 = 90;
|
|
235
235
|
/** The section appears when this many steps or fewer remain after this one. */
|
|
236
236
|
export const STEP_BUDGET_WARNING_STEPS_V1 = 3;
|
|
237
|
+
export const TIME_BUDGET_PROMPT_SECTION_V1 = "time-budget";
|
|
238
|
+
/** Immediately after the step warning, so the time warning is read last. */
|
|
239
|
+
export const TIME_BUDGET_PROMPT_ORDER_V1 = 91;
|
|
240
|
+
/** The section appears only once strictly fewer than two minutes remain. */
|
|
241
|
+
export const TIME_BUDGET_WARNING_MS_V1 = 2 * 60_000;
|
|
237
242
|
|
|
238
243
|
/**
|
|
239
244
|
* What the model is told when its reply is about to be stopped.
|
|
@@ -265,6 +270,23 @@ export function stepBudgetPromptTextV1(context: {
|
|
|
265
270
|
].join("\n");
|
|
266
271
|
}
|
|
267
272
|
|
|
273
|
+
/** Warns by wall-clock budget even when the model has used few steps. */
|
|
274
|
+
export function timeBudgetPromptTextV1(context: {
|
|
275
|
+
deadline?: { at: number; now: number };
|
|
276
|
+
}): string {
|
|
277
|
+
const deadline = context.deadline;
|
|
278
|
+
if (!deadline) return "";
|
|
279
|
+
const remaining = deadline.at - deadline.now;
|
|
280
|
+
if (!Number.isFinite(remaining) || remaining >= TIME_BUDGET_WARNING_MS_V1) {
|
|
281
|
+
return "";
|
|
282
|
+
}
|
|
283
|
+
return [
|
|
284
|
+
"<time_budget>",
|
|
285
|
+
`This Turn has fewer than 2 minutes left before it is stopped automatically. Do not start new work. Call \`${SEND_TO_USER_TOOL_V1}\` now with a short status for the person: what is finished, what is not, and what they can do next.`,
|
|
286
|
+
"</time_budget>",
|
|
287
|
+
].join("\n");
|
|
288
|
+
}
|
|
289
|
+
|
|
268
290
|
export const CONVERSATION_PROMPT_TEXT_V1 = [
|
|
269
291
|
"## Talking to the user",
|
|
270
292
|
"",
|
|
@@ -469,6 +491,11 @@ export const shellAgentPlugin: Plugin.Function = (ctx) => {
|
|
|
469
491
|
order: STEP_BUDGET_PROMPT_ORDER_V1,
|
|
470
492
|
render: (context) => stepBudgetPromptTextV1(context),
|
|
471
493
|
}),
|
|
494
|
+
ctx.systemPrompt.register({
|
|
495
|
+
id: TIME_BUDGET_PROMPT_SECTION_V1,
|
|
496
|
+
order: TIME_BUDGET_PROMPT_ORDER_V1,
|
|
497
|
+
render: (context) => timeBudgetPromptTextV1(context),
|
|
498
|
+
}),
|
|
472
499
|
ctx.tools.register(
|
|
473
500
|
createSendToUserTool(SEND_TO_USER_TOOL_V1, ctx.sessions),
|
|
474
501
|
userVoice ? { admissionCeiling: userVoice } : undefined,
|