@frockbot/plugin-shell 0.3.15 → 0.3.16
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frockbot/plugin-shell",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.16",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -51,42 +51,42 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@cordisjs/plugin-webui": "0.8.2",
|
|
54
|
-
"@frockbot/agent-runtime": "0.3.
|
|
55
|
-
"@frockbot/application-foundation": "0.3.
|
|
56
|
-
"@frockbot/catalog-core": "0.3.
|
|
57
|
-
"@frockbot/client-core": "0.3.
|
|
58
|
-
"@frockbot/client-ui": "0.3.
|
|
59
|
-
"@frockbot/computer-core": "0.3.
|
|
60
|
-
"@frockbot/computer-host-protocol": "0.3.
|
|
61
|
-
"@frockbot/configuration-core": "0.3.
|
|
62
|
-
"@frockbot/connection-core": "0.3.
|
|
63
|
-
"@frockbot/kernel-agent-loop": "0.3.
|
|
64
|
-
"@frockbot/kernel-composition": "0.3.
|
|
65
|
-
"@frockbot/kernel-contracts": "0.3.
|
|
66
|
-
"@frockbot/kernel-do": "0.3.
|
|
67
|
-
"@frockbot/machine-protocol": "0.3.
|
|
68
|
-
"@frockbot/plugin-applets": "0.3.
|
|
69
|
-
"@frockbot/plugin-authoring": "0.3.
|
|
70
|
-
"@frockbot/plugin-bot-template": "0.3.
|
|
71
|
-
"@frockbot/plugin-computer": "0.3.
|
|
72
|
-
"@frockbot/plugin-flock": "0.3.
|
|
73
|
-
"@frockbot/plugin-image": "0.3.
|
|
74
|
-
"@frockbot/plugin-machine-messages": "0.3.
|
|
75
|
-
"@frockbot/plugin-mcp": "0.3.
|
|
76
|
-
"@frockbot/plugin-memory": "0.3.
|
|
77
|
-
"@frockbot/plugin-package-catalog": "0.3.
|
|
78
|
-
"@frockbot/plugin-routines": "0.3.
|
|
79
|
-
"@frockbot/plugin-skills": "0.3.
|
|
80
|
-
"@frockbot/plugin-subagents": "0.3.
|
|
81
|
-
"@frockbot/plugin-user-machine": "0.3.
|
|
82
|
-
"@frockbot/protocol": "0.3.
|
|
54
|
+
"@frockbot/agent-runtime": "0.3.16",
|
|
55
|
+
"@frockbot/application-foundation": "0.3.16",
|
|
56
|
+
"@frockbot/catalog-core": "0.3.16",
|
|
57
|
+
"@frockbot/client-core": "0.3.16",
|
|
58
|
+
"@frockbot/client-ui": "0.3.16",
|
|
59
|
+
"@frockbot/computer-core": "0.3.16",
|
|
60
|
+
"@frockbot/computer-host-protocol": "0.3.16",
|
|
61
|
+
"@frockbot/configuration-core": "0.3.16",
|
|
62
|
+
"@frockbot/connection-core": "0.3.16",
|
|
63
|
+
"@frockbot/kernel-agent-loop": "0.3.16",
|
|
64
|
+
"@frockbot/kernel-composition": "0.3.16",
|
|
65
|
+
"@frockbot/kernel-contracts": "0.3.16",
|
|
66
|
+
"@frockbot/kernel-do": "0.3.16",
|
|
67
|
+
"@frockbot/machine-protocol": "0.3.16",
|
|
68
|
+
"@frockbot/plugin-applets": "0.3.16",
|
|
69
|
+
"@frockbot/plugin-authoring": "0.3.16",
|
|
70
|
+
"@frockbot/plugin-bot-template": "0.3.16",
|
|
71
|
+
"@frockbot/plugin-computer": "0.3.16",
|
|
72
|
+
"@frockbot/plugin-flock": "0.3.16",
|
|
73
|
+
"@frockbot/plugin-image": "0.3.16",
|
|
74
|
+
"@frockbot/plugin-machine-messages": "0.3.16",
|
|
75
|
+
"@frockbot/plugin-mcp": "0.3.16",
|
|
76
|
+
"@frockbot/plugin-memory": "0.3.16",
|
|
77
|
+
"@frockbot/plugin-package-catalog": "0.3.16",
|
|
78
|
+
"@frockbot/plugin-routines": "0.3.16",
|
|
79
|
+
"@frockbot/plugin-skills": "0.3.16",
|
|
80
|
+
"@frockbot/plugin-subagents": "0.3.16",
|
|
81
|
+
"@frockbot/plugin-user-machine": "0.3.16",
|
|
82
|
+
"@frockbot/protocol": "0.3.16",
|
|
83
83
|
"cordis": "4.0.0-rc.8",
|
|
84
84
|
"vue": "3.5.41"
|
|
85
85
|
},
|
|
86
86
|
"devDependencies": {
|
|
87
87
|
"@cloudflare/workers-types": "latest",
|
|
88
|
-
"@frockbot/plugin-prompt": "0.3.
|
|
89
|
-
"@frockbot/plugin-tools": "0.3.
|
|
88
|
+
"@frockbot/plugin-prompt": "0.3.16",
|
|
89
|
+
"@frockbot/plugin-tools": "0.3.16",
|
|
90
90
|
"@types/bun": "1.3.6",
|
|
91
91
|
"@types/node": "26.2.0",
|
|
92
92
|
"@vitejs/plugin-vue": "6.0.8",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
import { type SessionEvent } from "@frockbot/kernel-contracts";
|
|
3
3
|
import { initializeBotSettingsV1 } from "@frockbot/configuration-core";
|
|
4
|
+
import { SessionEventLog } from "@frockbot/kernel-do";
|
|
4
5
|
import {
|
|
5
6
|
botTurnCommandFingerprintV1,
|
|
6
7
|
type BotTurnCompletion,
|
|
@@ -81,11 +82,15 @@ class MemoryRunStorage implements RunTerminalStorage {
|
|
|
81
82
|
return Promise.resolve(this.values.get(key) as T | undefined);
|
|
82
83
|
}
|
|
83
84
|
|
|
84
|
-
put(
|
|
85
|
-
|
|
86
|
-
if (this.putFailure) return Promise.reject(this.putFailure);
|
|
87
|
-
for (const [key, value] of Object.entries(entries)) {
|
|
85
|
+
put(key: string | Record<string, unknown>, value?: unknown): Promise<void> {
|
|
86
|
+
if (typeof key === "string") {
|
|
88
87
|
this.values.set(key, structuredClone(value));
|
|
88
|
+
return Promise.resolve();
|
|
89
|
+
}
|
|
90
|
+
this.putBatches.push(structuredClone(key));
|
|
91
|
+
if (this.putFailure) return Promise.reject(this.putFailure);
|
|
92
|
+
for (const [entry, item] of Object.entries(key)) {
|
|
93
|
+
this.values.set(entry, structuredClone(item));
|
|
89
94
|
}
|
|
90
95
|
return Promise.resolve();
|
|
91
96
|
}
|
|
@@ -93,6 +98,16 @@ class MemoryRunStorage implements RunTerminalStorage {
|
|
|
93
98
|
delete(key: string): Promise<boolean> {
|
|
94
99
|
return Promise.resolve(this.values.delete(key));
|
|
95
100
|
}
|
|
101
|
+
|
|
102
|
+
list<T>(options: { prefix: string }): Promise<Map<string, T>> {
|
|
103
|
+
return Promise.resolve(
|
|
104
|
+
new Map(
|
|
105
|
+
[...this.values.entries()].filter(([key]) =>
|
|
106
|
+
key.startsWith(options.prefix),
|
|
107
|
+
) as Array<[string, T]>,
|
|
108
|
+
),
|
|
109
|
+
);
|
|
110
|
+
}
|
|
96
111
|
}
|
|
97
112
|
|
|
98
113
|
describe("Bot run terminal persistence", () => {
|
|
@@ -284,6 +299,8 @@ describe("Bot run terminal persistence", () => {
|
|
|
284
299
|
failure: "provider-bound retrieval unavailable",
|
|
285
300
|
});
|
|
286
301
|
expect(storage.values.get(keys.activeRun)).toBe("run-1");
|
|
287
|
-
expect(storage.
|
|
302
|
+
expect(await new SessionEventLog(storage).read("user:primary")).toEqual([
|
|
303
|
+
request,
|
|
304
|
+
]);
|
|
288
305
|
});
|
|
289
306
|
});
|
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
UserSettingsViewV1,
|
|
7
7
|
} from "@frockbot/configuration-core";
|
|
8
8
|
import type { PackageSettingDefinition } from "@frockbot/kernel-composition";
|
|
9
|
+
import { SessionEventLog } from "@frockbot/kernel-do";
|
|
9
10
|
import { createShellBotBackendContribution } from "./backend.js";
|
|
10
11
|
import { createIsolateCapabilityHost } from "./backend-isolate.js";
|
|
11
12
|
import { notificationIdV1 } from "./notification-id.js";
|
|
@@ -549,11 +550,12 @@ describe("generic per-Turn model resolution", () => {
|
|
|
549
550
|
});
|
|
550
551
|
|
|
551
552
|
expect(result.text).toBe("Cordis runtime: hello");
|
|
552
|
-
const durableEvents = storage.
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
expect(durableEvents
|
|
556
|
-
|
|
553
|
+
const durableEvents = await new SessionEventLog(storage).read(
|
|
554
|
+
"user-1:primary",
|
|
555
|
+
);
|
|
556
|
+
expect(durableEvents.length).toBeGreaterThan(0);
|
|
557
|
+
expect(durableEvents.map((event) => event.seq)).toEqual(
|
|
558
|
+
durableEvents.map((_, index) => index),
|
|
557
559
|
);
|
|
558
560
|
const settings = await contribution.getSettings(identity);
|
|
559
561
|
expect(settings).toMatchObject({ revision: 0, packageValues: {} });
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
import { initializeBotSettingsV1 } from "@frockbot/configuration-core";
|
|
3
|
+
import { SessionEventLog, storedRunRecordV2 } from "@frockbot/kernel-do";
|
|
3
4
|
import { createShellBotBackendContribution } from "./backend.js";
|
|
4
5
|
import type { StoredRun } from "./backend-contracts.js";
|
|
5
6
|
|
|
@@ -154,6 +155,54 @@ describe("Bot debug snapshot", () => {
|
|
|
154
155
|
expect(snapshot.activeRunId).toBeUndefined();
|
|
155
156
|
});
|
|
156
157
|
|
|
158
|
+
test("reads bounded projections instead of hydrating full model prompts", async () => {
|
|
159
|
+
const storage = new MemoryStorage();
|
|
160
|
+
const event = {
|
|
161
|
+
type: "model/request",
|
|
162
|
+
turn: 1,
|
|
163
|
+
step: 1,
|
|
164
|
+
request: {
|
|
165
|
+
requestId: "request-large",
|
|
166
|
+
provider: "fake",
|
|
167
|
+
model: "large-context",
|
|
168
|
+
system: "s".repeat(80_000),
|
|
169
|
+
messages: [{ role: "user", content: "last question" }],
|
|
170
|
+
tools: [],
|
|
171
|
+
},
|
|
172
|
+
seq: 0,
|
|
173
|
+
timestamp: "2026-08-28T00:00:01.000Z",
|
|
174
|
+
} as StoredRun["events"][number];
|
|
175
|
+
const run = storedRun({ events: [event] });
|
|
176
|
+
await new SessionEventLog(storage).rewrite(run.sessionId, [event]);
|
|
177
|
+
await storage.put({
|
|
178
|
+
identity: IDENTITY,
|
|
179
|
+
[`run:${run.runId}`]: storedRunRecordV2(run),
|
|
180
|
+
[`run-index:${run.acceptedAt}:${run.runId}`]: run.runId,
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
const snapshot = await contributionOver(storage).debugSnapshot(IDENTITY, {
|
|
184
|
+
schemaVersion: 1,
|
|
185
|
+
runId: run.runId,
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
expect(snapshot.runs[0]?.eventCount).toBe(1);
|
|
189
|
+
expect(snapshot.runs[0]?.events?.[0]).toMatchObject({
|
|
190
|
+
type: "model/request",
|
|
191
|
+
cut: { marker: "content-cut", originalBytes: expect.any(Number) },
|
|
192
|
+
request: {
|
|
193
|
+
requestId: "request-large",
|
|
194
|
+
messageCount: 1,
|
|
195
|
+
toolCount: 0,
|
|
196
|
+
sha256: expect.stringMatching(/^[0-9a-f]{64}$/),
|
|
197
|
+
truncated: true,
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
expect(JSON.stringify(snapshot)).not.toContain("s".repeat(10_000));
|
|
201
|
+
expect(
|
|
202
|
+
new TextEncoder().encode(JSON.stringify(snapshot)).byteLength,
|
|
203
|
+
).toBeLessThan(20_000);
|
|
204
|
+
});
|
|
205
|
+
|
|
157
206
|
test("includes an active run older than the page it would otherwise fall off", async () => {
|
|
158
207
|
const storage = new MemoryStorage();
|
|
159
208
|
const stale = storedRun({
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
type UserSettingsViewV1,
|
|
10
10
|
} from "@frockbot/configuration-core";
|
|
11
11
|
import { compileFoundationApplication } from "@frockbot/application-foundation/runtime";
|
|
12
|
+
import { SessionEventLog } from "@frockbot/kernel-do";
|
|
12
13
|
import { createShellBotBackendContribution } from "./backend.js";
|
|
13
14
|
import {
|
|
14
15
|
botTurnCommandFingerprintV1,
|
|
@@ -291,10 +292,23 @@ describe("Bot recovery", () => {
|
|
|
291
292
|
},
|
|
292
293
|
]);
|
|
293
294
|
expect(settledEffects).toHaveLength(2);
|
|
295
|
+
const eventLog = new SessionEventLog(storage);
|
|
294
296
|
for (const runId of ["ollama-run-1", "ollama-run-2"]) {
|
|
295
|
-
const run = await storage.get<
|
|
297
|
+
const run = await storage.get<
|
|
298
|
+
Omit<StoredRun, "events"> & {
|
|
299
|
+
eventRange: { startSeq: number; endSeq: number };
|
|
300
|
+
}
|
|
301
|
+
>(`run:${runId}`);
|
|
302
|
+
expect(run).not.toHaveProperty("events");
|
|
303
|
+
const events = run
|
|
304
|
+
? await eventLog.readRange(
|
|
305
|
+
"user-1:primary",
|
|
306
|
+
run.eventRange.startSeq,
|
|
307
|
+
run.eventRange.endSeq,
|
|
308
|
+
)
|
|
309
|
+
: [];
|
|
296
310
|
expect(
|
|
297
|
-
|
|
311
|
+
events.find((event) => event.type === "model/request"),
|
|
298
312
|
).toMatchObject({
|
|
299
313
|
request: {
|
|
300
314
|
provider: "ollama-cloud",
|
package/src/backend.ts
CHANGED
|
@@ -46,12 +46,13 @@ import {
|
|
|
46
46
|
ACTIVE_RUN_KEY,
|
|
47
47
|
BotDurableAuthority,
|
|
48
48
|
IDENTITY_KEY,
|
|
49
|
-
LATEST_EVENTS_KEY,
|
|
50
49
|
NOTIFICATION_PREFIX,
|
|
51
50
|
RECOVERY_ALARM_DELAY_MS,
|
|
52
51
|
RUN_ADMISSION_FENCE_PREFIX,
|
|
53
52
|
RUN_INDEX_PREFIX,
|
|
54
53
|
RUN_PREFIX,
|
|
54
|
+
SessionEventLog,
|
|
55
|
+
storedRunRecordV2,
|
|
55
56
|
CONVERSATION_BUSY_MESSAGE_V1,
|
|
56
57
|
isConversationBusyV1,
|
|
57
58
|
type BotIdentity,
|
|
@@ -1156,8 +1157,10 @@ export class ShellBotBackendContribution {
|
|
|
1156
1157
|
const announcements = [...stored.entries()]
|
|
1157
1158
|
.sort(([left], [right]) => left.localeCompare(right))
|
|
1158
1159
|
.map(([, value]) => decodeSessionEvent(value));
|
|
1159
|
-
const
|
|
1160
|
-
|
|
1160
|
+
const sessionId = await this.authority.readConversationSessionId();
|
|
1161
|
+
const session = sessionId
|
|
1162
|
+
? await this.authority.readSessionEvents(sessionId)
|
|
1163
|
+
: [];
|
|
1161
1164
|
for (const event of session) {
|
|
1162
1165
|
if (event.type === "conversation/compacted") announcements.push(event);
|
|
1163
1166
|
}
|
|
@@ -1171,8 +1174,10 @@ export class ShellBotBackendContribution {
|
|
|
1171
1174
|
* timestamp of the place it belongs rather than the moment it was written.
|
|
1172
1175
|
*/
|
|
1173
1176
|
private async projectAnnouncementPage() {
|
|
1174
|
-
const
|
|
1175
|
-
|
|
1177
|
+
const sessionId = await this.authority.readConversationSessionId();
|
|
1178
|
+
const session = sessionId
|
|
1179
|
+
? await this.authority.readSessionEvents(sessionId)
|
|
1180
|
+
: [];
|
|
1176
1181
|
return projectClientAnnouncementsV1(
|
|
1177
1182
|
await this.listAnnouncements(),
|
|
1178
1183
|
session,
|
|
@@ -5951,10 +5956,13 @@ export class ShellBotBackendContribution {
|
|
|
5951
5956
|
let budget = BOT_DEBUG_EVENT_BYTES_V1;
|
|
5952
5957
|
const runs: BotDebugRunV1[] = [];
|
|
5953
5958
|
for (const candidate of candidates) {
|
|
5954
|
-
const
|
|
5955
|
-
|
|
5959
|
+
const projected = await this.authority.readRunEventProjections(
|
|
5960
|
+
candidate.runId,
|
|
5961
|
+
);
|
|
5962
|
+
if (!projected) continue;
|
|
5963
|
+
const { run: stored } = projected;
|
|
5956
5964
|
const bounded = includeEvents
|
|
5957
|
-
? boundDebugEventsV1(
|
|
5965
|
+
? boundDebugEventsV1(projected.events, budget)
|
|
5958
5966
|
: undefined;
|
|
5959
5967
|
if (bounded) budget = Math.max(0, budget - bounded.spent);
|
|
5960
5968
|
runs.push({
|
|
@@ -5967,7 +5975,7 @@ export class ShellBotBackendContribution {
|
|
|
5967
5975
|
commandFingerprint: stored.commandFingerprint,
|
|
5968
5976
|
compositionGenerationId: stored.compositionGenerationId,
|
|
5969
5977
|
previousEventCount: stored.previousEventCount,
|
|
5970
|
-
eventCount:
|
|
5978
|
+
eventCount: projected.eventCount,
|
|
5971
5979
|
...(stored.responseText === undefined
|
|
5972
5980
|
? {}
|
|
5973
5981
|
: { responseText: stored.responseText }),
|
|
@@ -6328,7 +6336,24 @@ export class ShellBotBackendContribution {
|
|
|
6328
6336
|
transaction.get<BotIdentity>(IDENTITY_KEY),
|
|
6329
6337
|
transaction.get<unknown>(`${RUN_PREFIX}${runId}`),
|
|
6330
6338
|
]);
|
|
6331
|
-
const
|
|
6339
|
+
const storedRun = optionalStoredRun(candidate);
|
|
6340
|
+
let run = storedRun;
|
|
6341
|
+
if (storedRun?.eventRange) {
|
|
6342
|
+
const events = await new SessionEventLog(transaction).readRange(
|
|
6343
|
+
storedRun.sessionId,
|
|
6344
|
+
storedRun.eventRange.startSeq,
|
|
6345
|
+
storedRun.eventRange.endSeq,
|
|
6346
|
+
);
|
|
6347
|
+
if (
|
|
6348
|
+
events.length !==
|
|
6349
|
+
storedRun.eventRange.endSeq - storedRun.eventRange.startSeq
|
|
6350
|
+
) {
|
|
6351
|
+
throw new Error(
|
|
6352
|
+
`run "${storedRun.runId}" has an incomplete event range`,
|
|
6353
|
+
);
|
|
6354
|
+
}
|
|
6355
|
+
run = requireStoredRunV1({ ...storedRun, events });
|
|
6356
|
+
}
|
|
6332
6357
|
if (
|
|
6333
6358
|
activeRunId !== runId ||
|
|
6334
6359
|
!run ||
|
|
@@ -6388,7 +6413,10 @@ export class ShellBotBackendContribution {
|
|
|
6388
6413
|
{ kind: effect.kind, effectId: effect.effectId, outcome },
|
|
6389
6414
|
],
|
|
6390
6415
|
} satisfies StoredRun);
|
|
6391
|
-
await transaction.put(
|
|
6416
|
+
await transaction.put(
|
|
6417
|
+
`${RUN_PREFIX}${runId}`,
|
|
6418
|
+
structuredClone(storedRunRecordV2(next)),
|
|
6419
|
+
);
|
|
6392
6420
|
return outcome === "admitted";
|
|
6393
6421
|
});
|
|
6394
6422
|
}
|
package/src/debug-protocol.ts
CHANGED
|
@@ -20,9 +20,10 @@ export const BOT_DEBUG_RUN_LIMIT_V1 = 20;
|
|
|
20
20
|
export const BOT_DEBUG_DEFAULT_RUN_LIMIT_V1 = 5;
|
|
21
21
|
export const BOT_DEBUG_GENERATION_LIMIT_V1 = 5;
|
|
22
22
|
/**
|
|
23
|
-
* The event budget one snapshot spends.
|
|
24
|
-
* a handful of runs can
|
|
25
|
-
*
|
|
23
|
+
* The event budget one snapshot spends. Large durable events are already
|
|
24
|
+
* bounded diagnostic projections, but a handful of runs can still accumulate
|
|
25
|
+
* many of them; past this the *oldest* events of a run are dropped, because a
|
|
26
|
+
* failure is described by the tail of its log.
|
|
26
27
|
*/
|
|
27
28
|
export const BOT_DEBUG_EVENT_BYTES_V1 = 512_000;
|
|
28
29
|
|