@pasko70/pibo 3.0.1 → 3.1.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/README.md +20 -6
- package/compute-image/Dockerfile +47 -0
- package/compute-image/Dockerfile.dockerignore +5 -0
- package/dist/agent-runtime/context-build.js +26 -2
- package/dist/agent-runtime/contract.js +78 -28
- package/dist/agent-runtime/portable-history.js +19 -9
- package/dist/agent-runtime/registry.js +8 -2
- package/dist/agent-runtime/routed-session.js +120 -15
- package/dist/agent-runtimes/codex-native/adapter.js +12 -0
- package/dist/agent-runtimes/codex-native/resource-delivery.js +35 -7
- package/dist/agent-runtimes/omp/adapter.js +3 -7
- package/dist/agent-runtimes/pi/adapter.js +5 -3
- package/dist/agent-runtimes/pi/routed-session.js +59 -12
- package/dist/agent-runtimes/pi/runtime.js +6 -0
- package/dist/apps/chat/agent-profiles.js +31 -2
- package/dist/apps/chat/agent-store.js +98 -6
- package/dist/apps/chat/chat-request-normalizers.js +31 -0
- package/dist/apps/chat/data/chat-data-mappers.js +61 -11
- package/dist/apps/chat/data/project-service.js +119 -15
- package/dist/apps/chat/data/room-service.js +21 -0
- package/dist/apps/chat/data/session-query-service.js +33 -10
- package/dist/apps/chat/data/timeline-query-service.js +60 -35
- package/dist/apps/chat/loop-api.js +10 -2
- package/dist/apps/chat/output-compactor.js +144 -21
- package/dist/apps/chat/output-event-policy.js +179 -2
- package/dist/apps/chat/stream.js +16 -7
- package/dist/apps/chat/trace-v2.js +1 -0
- package/dist/apps/chat/web-app.js +317 -86
- package/dist/apps/chat-ui/assets/{dist-BDIATCQt.js → dist-CUQJqggN.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-mqCviI-c.js → dist-ClUlQWYN.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-JnW4v8UE.js → dist-Djul9BmZ.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-lRiLP9rr.js → dist-GD0JGdCi.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BBDMeU5-.js → dist-W5HOqHym.js} +1 -1
- package/dist/apps/chat-ui/assets/index-BcjkX-iP.js +228 -0
- package/dist/apps/chat-ui/assets/index-CmqRSbBU.css +1 -0
- package/dist/apps/chat-ui/index.html +2 -2
- package/dist/apps/chat-vscode-web/assets/index-JvrPUGvI.js +43 -0
- package/dist/apps/chat-vscode-web/index.html +1 -1
- package/dist/apps/cli-ui/InkSessionApp.js +111 -12
- package/dist/apps/cli-ui/cliSessionsCommand.js +34 -8
- package/dist/cli-session/localSessionSource.js +153 -161
- package/dist/cli.js +7 -11
- package/dist/compute/cli.js +35 -16
- package/dist/compute/docker.js +341 -94
- package/dist/config/config.js +3 -0
- package/dist/core/context-build.js +7 -16
- package/dist/core/output-persistence-retry.js +484 -0
- package/dist/core/output-render-sequence.js +331 -0
- package/dist/core/profiles.js +24 -0
- package/dist/core/provider-recovery.js +7 -1
- package/dist/core/session-model.js +37 -1
- package/dist/core/session-router.js +78 -110
- package/dist/data/ingest-service.js +91 -9
- package/dist/data/navigation-store.js +5 -5
- package/dist/data/pibo-store.js +8 -1
- package/dist/data/schema.js +243 -3
- package/dist/data/session-store.js +3 -3
- package/dist/debug/agents.js +91 -89
- package/dist/debug/index.js +46 -2
- package/dist/debug/pty.js +127 -48
- package/dist/gateway/cli.js +4 -0
- package/dist/gateway/web.js +8 -8
- package/dist/local/client.js +3 -2
- package/dist/loops/channel.js +3 -1
- package/dist/loops/cli.js +2 -1
- package/dist/loops/service.js +90 -11
- package/dist/loops/store.js +100 -74
- package/dist/mcp/agent-context.js +13 -26
- package/dist/mcp/commands/info.js +3 -1
- package/dist/mcp/config-command.js +46 -2
- package/dist/mcp/config.js +18 -4
- package/dist/plugins/context-files-store.js +36 -6
- package/dist/plugins/context-files.js +52 -1
- package/dist/plugins/registry.js +2 -0
- package/dist/plugins/user-profile-resources.js +22 -0
- package/dist/previews/base-url.js +34 -0
- package/dist/previews/config.js +2 -32
- package/dist/ralph/store.js +5 -0
- package/dist/reliability/store.js +378 -106
- package/dist/session-ui/terminalRows.js +8 -4
- package/dist/sessions/pibo-data-store.js +145 -0
- package/dist/sessions/store.js +42 -0
- package/dist/setup/cli.js +422 -6
- package/dist/setup/installation-profiles.js +464 -0
- package/dist/shared/deterministic-digest.js +94 -0
- package/dist/shared/trace-engine.js +54 -0
- package/dist/shared/trace-event-projection.js +124 -67
- package/dist/shared/trace-history.js +47 -12
- package/dist/shared/trace-live-reducer.js +23 -4
- package/dist/shared/trace-nodes.js +17 -28
- package/dist/shared/trace-order.js +41 -5
- package/dist/shared/trace-page-merge.js +44 -14
- package/dist/shared/trace-patch-nodes.js +2 -0
- package/dist/shared/trace-subagent-links.js +4 -1
- package/dist/shared/trace-tool-identity.js +15 -8
- package/dist/signals/projector.js +28 -6
- package/dist/subagents/observation-query.js +121 -0
- package/dist/subagents/tool.js +7 -3
- package/dist/tools/agent-browser-leases.js +58 -23
- package/dist/tools/agent-browser-wrapper.js +1 -1
- package/dist/tools/browser-use-leases.js +129 -16
- package/dist/tools/browser-use-wrapper.js +1 -1
- package/dist/tools/index.js +27 -11
- package/dist/tools/python-runtime.js +10 -3
- package/dist/tools/registry.js +1 -1
- package/dist/tools/runtime/node-backend.js +16 -5
- package/dist/tools/runtime/node-worker-source.js +112 -33
- package/dist/tools/runtime/python-backend.js +16 -5
- package/dist/tools/runtime/python-worker-source.js +167 -16
- package/dist/tools/runtime/registry.js +23 -10
- package/dist/user-skills/store.js +0 -1
- package/docs/ops/vscode-extension-release.md +9 -1
- package/npm-shrinkwrap.json +9 -2
- package/package.json +9 -2
- package/scripts/docker-entrypoint.sh +46 -0
- package/scripts/prepare-agent-browser-wrapper.sh +70 -0
- package/scripts/prepare-browser-use-wrapper.sh +255 -0
- package/dist/apps/chat-ui/assets/index-0XOOVxLP.js +0 -228
- package/dist/apps/chat-ui/assets/index-DV7_CgsC.css +0 -1
- package/dist/apps/chat-vscode-web/assets/index-Dtw2Z7jz.js +0 -43
- package/dist/apps/vscode-artifacts/latest.vsix +0 -0
- package/dist/apps/vscode-artifacts/pibo-vscode-ext-3.0.1.vsix +0 -0
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<meta name="theme-color" content="#101d22" />
|
|
7
7
|
<title>Pibo</title>
|
|
8
|
-
<script type="module" crossorigin src="/apps/chat-vscode/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/apps/chat-vscode/assets/index-JvrPUGvI.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/apps/chat-vscode/assets/index-SluZr_-r.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
@@ -5,10 +5,23 @@ import { buildCompactTerminalRows, buildSlashCommandCatalog, buildTerminalStatus
|
|
|
5
5
|
import { InkTerminalView } from "./InkTerminalView.js";
|
|
6
6
|
import { isExpandableTerminalRow } from "./InkTerminalRow.js";
|
|
7
7
|
const IDENTIFIER_PATTERN = /^(?:user|room|ps|pi|entry|evt|run|create|provider|model|agent)[_:]/i;
|
|
8
|
+
export async function runInkPickerActivation(guard, picker, activate) {
|
|
9
|
+
if (guard.inFlight || guard.lastPicker === picker)
|
|
10
|
+
return undefined;
|
|
11
|
+
guard.inFlight = true;
|
|
12
|
+
guard.lastPicker = picker;
|
|
13
|
+
try {
|
|
14
|
+
return await activate();
|
|
15
|
+
}
|
|
16
|
+
finally {
|
|
17
|
+
guard.inFlight = false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
8
20
|
const INITIAL_STATE = {
|
|
9
21
|
loading: true,
|
|
10
22
|
rows: [],
|
|
11
23
|
input: "",
|
|
24
|
+
inputCursor: 0,
|
|
12
25
|
mode: "transcript",
|
|
13
26
|
};
|
|
14
27
|
export function InkSessionApp({ source, initialSessionId, maxRows, maxLineChars, onExit }) {
|
|
@@ -18,6 +31,7 @@ export function InkSessionApp({ source, initialSessionId, maxRows, maxLineChars,
|
|
|
18
31
|
const unsubscribeRef = useRef(undefined);
|
|
19
32
|
const closedRef = useRef(false);
|
|
20
33
|
const stateRef = useRef(state);
|
|
34
|
+
const pickerActivationRef = useRef({ inFlight: false });
|
|
21
35
|
useEffect(() => {
|
|
22
36
|
stateRef.current = state;
|
|
23
37
|
}, [state]);
|
|
@@ -120,7 +134,7 @@ export function InkSessionApp({ source, initialSessionId, maxRows, maxLineChars,
|
|
|
120
134
|
error: undefined,
|
|
121
135
|
}));
|
|
122
136
|
}, [source]);
|
|
123
|
-
const
|
|
137
|
+
const activatePickerItem = useCallback(async () => {
|
|
124
138
|
const picker = stateRef.current.picker;
|
|
125
139
|
const item = picker?.items[picker.selectedIndex];
|
|
126
140
|
if (!picker || !item) {
|
|
@@ -136,8 +150,12 @@ export function InkSessionApp({ source, initialSessionId, maxRows, maxLineChars,
|
|
|
136
150
|
return;
|
|
137
151
|
}
|
|
138
152
|
if (picker.action === "select-room") {
|
|
139
|
-
const
|
|
140
|
-
|
|
153
|
+
const currentSession = stateRef.current.session;
|
|
154
|
+
const preserveSession = currentSession?.roomId === room.id;
|
|
155
|
+
const status = await source.getStatus({ sessionId: preserveSession ? currentSession.id : undefined });
|
|
156
|
+
if (!preserveSession)
|
|
157
|
+
closeOpenSession();
|
|
158
|
+
setState((current) => selectInkSessionRoom(current, room, status));
|
|
141
159
|
return;
|
|
142
160
|
}
|
|
143
161
|
await openSessionPickerForRoom(room, picker);
|
|
@@ -174,7 +192,13 @@ export function InkSessionApp({ source, initialSessionId, maxRows, maxLineChars,
|
|
|
174
192
|
catch (error) {
|
|
175
193
|
setState((current) => ({ ...current, mode: "transcript", picker: undefined, error: formatCliSessionError(error), message: undefined }));
|
|
176
194
|
}
|
|
177
|
-
}, [openSession, openSessionPickerForRoom, source]);
|
|
195
|
+
}, [closeOpenSession, openSession, openSessionPickerForRoom, source]);
|
|
196
|
+
const selectPickerItem = useCallback(async () => {
|
|
197
|
+
const picker = stateRef.current.picker;
|
|
198
|
+
if (!picker)
|
|
199
|
+
return;
|
|
200
|
+
await runInkPickerActivation(pickerActivationRef.current, picker, activatePickerItem);
|
|
201
|
+
}, [activatePickerItem]);
|
|
178
202
|
useEffect(() => {
|
|
179
203
|
closedRef.current = false;
|
|
180
204
|
void (async () => {
|
|
@@ -215,6 +239,22 @@ export function InkSessionApp({ source, initialSessionId, maxRows, maxLineChars,
|
|
|
215
239
|
setState((current) => reduceInkSessionInputState(current, { type: "down" }));
|
|
216
240
|
return;
|
|
217
241
|
}
|
|
242
|
+
if (key.leftArrow) {
|
|
243
|
+
setState((current) => reduceInkSessionInputState(current, { type: "left" }));
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (key.rightArrow) {
|
|
247
|
+
setState((current) => reduceInkSessionInputState(current, { type: "right" }));
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (key.home) {
|
|
251
|
+
setState((current) => reduceInkSessionInputState(current, { type: "home" }));
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if (key.end) {
|
|
255
|
+
setState((current) => reduceInkSessionInputState(current, { type: "end" }));
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
218
258
|
if (key.return) {
|
|
219
259
|
const submitted = stateRef.current.input;
|
|
220
260
|
if (submitted.length === 0 && !stateRef.current.picker && !stateRef.current.slashSuggestions && canToggleSelectedRowDetails(stateRef.current)) {
|
|
@@ -224,11 +264,11 @@ export function InkSessionApp({ source, initialSessionId, maxRows, maxLineChars,
|
|
|
224
264
|
if (stateRef.current.slashSuggestions && !stateRef.current.picker) {
|
|
225
265
|
const accepted = acceptSlashSuggestion(stateRef.current);
|
|
226
266
|
if (accepted.runInput) {
|
|
227
|
-
setState((current) => ({ ...current, input: "", slashSuggestions: undefined, message: undefined, error: undefined }));
|
|
267
|
+
setState((current) => ({ ...current, input: "", inputCursor: 0, slashSuggestions: undefined, message: undefined, error: undefined }));
|
|
228
268
|
void submitCommandOrMessage(accepted.runInput);
|
|
229
269
|
}
|
|
230
270
|
else {
|
|
231
|
-
setState((current) => ({ ...current, input: accepted.input, slashSuggestions: undefined, message: `Accepted ${accepted.input.trim()}. Press Enter to run or add arguments.`, error: undefined }));
|
|
271
|
+
setState((current) => ({ ...current, input: accepted.input, inputCursor: accepted.input.length, slashSuggestions: undefined, message: `Accepted ${accepted.input.trim()}. Press Enter to run or add arguments.`, error: undefined }));
|
|
232
272
|
}
|
|
233
273
|
return;
|
|
234
274
|
}
|
|
@@ -238,6 +278,7 @@ export function InkSessionApp({ source, initialSessionId, maxRows, maxLineChars,
|
|
|
238
278
|
return;
|
|
239
279
|
}
|
|
240
280
|
if (stateRef.current.picker) {
|
|
281
|
+
setState((current) => reduceInkSessionInputState(current, { type: "enter" }));
|
|
241
282
|
void selectPickerItem();
|
|
242
283
|
return;
|
|
243
284
|
}
|
|
@@ -292,19 +333,44 @@ export function InkSessionPickerView({ picker, maxLineChars }) {
|
|
|
292
333
|
return React.createElement(Box, { flexDirection: "column" }, React.createElement(Text, { color: "yellow" }, title), ...picker.items.map((item, index) => React.createElement(Text, { key: item.id, color: overlayItemColor(index === picker.selectedIndex, item.disabled === true) }, formatOverlayItemLine(item, index === picker.selectedIndex, lineLimit))), React.createElement(Text, { color: "gray" }, "↑↓ select · enter confirm · esc back/cancel · ctrl-c exit"));
|
|
293
334
|
}
|
|
294
335
|
export function reduceInkSessionInputState(state, action) {
|
|
295
|
-
if (action.type === "text")
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
336
|
+
if (action.type === "text") {
|
|
337
|
+
const inputCursor = normalizeInputCursor(state.input, state.inputCursor);
|
|
338
|
+
return withSlashSuggestions({
|
|
339
|
+
...state,
|
|
340
|
+
input: state.input.slice(0, inputCursor) + action.value + state.input.slice(inputCursor),
|
|
341
|
+
inputCursor: inputCursor + action.value.length,
|
|
342
|
+
message: undefined,
|
|
343
|
+
error: undefined,
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
if (action.type === "backspace") {
|
|
347
|
+
const inputCursor = normalizeInputCursor(state.input, state.inputCursor);
|
|
348
|
+
const previousCursor = adjacentInputCursor(state.input, inputCursor, -1);
|
|
349
|
+
if (previousCursor === inputCursor)
|
|
350
|
+
return state;
|
|
351
|
+
return withSlashSuggestions({
|
|
352
|
+
...state,
|
|
353
|
+
input: state.input.slice(0, previousCursor) + state.input.slice(inputCursor),
|
|
354
|
+
inputCursor: previousCursor,
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
if (action.type === "left" || action.type === "right") {
|
|
358
|
+
const inputCursor = normalizeInputCursor(state.input, state.inputCursor);
|
|
359
|
+
return { ...state, inputCursor: adjacentInputCursor(state.input, inputCursor, action.type === "left" ? -1 : 1) };
|
|
360
|
+
}
|
|
361
|
+
if (action.type === "home")
|
|
362
|
+
return { ...state, inputCursor: 0 };
|
|
363
|
+
if (action.type === "end")
|
|
364
|
+
return { ...state, inputCursor: state.input.length };
|
|
299
365
|
if (action.type === "toggle-details")
|
|
300
366
|
return toggleSelectedRowDetails(state);
|
|
301
367
|
if (action.type === "escape") {
|
|
302
368
|
if (state.slashSuggestions)
|
|
303
369
|
return { ...state, slashSuggestions: undefined, overlayStack: popInkSessionOverlay(state.overlayStack), message: "Closed slash suggestions." };
|
|
304
370
|
if (state.picker?.parent) {
|
|
305
|
-
return withPickerOverlay({ ...state, picker: state.picker.parent, mode: pickerMode(state.picker.parent), message: "Back." }, state.picker.parent);
|
|
371
|
+
return withPickerOverlay({ ...state, input: "", picker: state.picker.parent, mode: pickerMode(state.picker.parent), message: "Back." }, state.picker.parent);
|
|
306
372
|
}
|
|
307
|
-
return { ...state, input: "", mode: "transcript", picker: undefined, overlayStack: popInkSessionOverlay(state.overlayStack), message: "Canceled." };
|
|
373
|
+
return { ...state, input: "", inputCursor: 0, mode: "transcript", picker: undefined, overlayStack: popInkSessionOverlay(state.overlayStack), message: "Canceled." };
|
|
308
374
|
}
|
|
309
375
|
if (action.type === "up" || action.type === "down") {
|
|
310
376
|
if (state.slashSuggestions && !state.picker && state.slashSuggestions.items.length > 0) {
|
|
@@ -323,11 +389,30 @@ export function reduceInkSessionInputState(state, action) {
|
|
|
323
389
|
return {
|
|
324
390
|
...state,
|
|
325
391
|
input: "",
|
|
392
|
+
inputCursor: 0,
|
|
326
393
|
slashSuggestions: undefined,
|
|
327
394
|
message: undefined,
|
|
328
395
|
error: undefined,
|
|
329
396
|
};
|
|
330
397
|
}
|
|
398
|
+
const INPUT_GRAPHEME_SEGMENTER = new Intl.Segmenter(undefined, { granularity: "grapheme" });
|
|
399
|
+
function normalizeInputCursor(input, inputCursor) {
|
|
400
|
+
if (inputCursor === undefined)
|
|
401
|
+
return input.length;
|
|
402
|
+
const clamped = Math.max(0, Math.min(input.length, inputCursor));
|
|
403
|
+
return inputGraphemeBoundaries(input).findLast((boundary) => boundary <= clamped) ?? 0;
|
|
404
|
+
}
|
|
405
|
+
function adjacentInputCursor(input, inputCursor, direction) {
|
|
406
|
+
const boundaries = inputGraphemeBoundaries(input);
|
|
407
|
+
const index = boundaries.indexOf(inputCursor);
|
|
408
|
+
return boundaries[Math.max(0, Math.min(boundaries.length - 1, index + direction))] ?? inputCursor;
|
|
409
|
+
}
|
|
410
|
+
function inputGraphemeBoundaries(input) {
|
|
411
|
+
const boundaries = [0];
|
|
412
|
+
for (const segment of INPUT_GRAPHEME_SEGMENTER.segment(input))
|
|
413
|
+
boundaries.push(segment.index + segment.segment.length);
|
|
414
|
+
return boundaries;
|
|
415
|
+
}
|
|
331
416
|
export function normalizeInkRowSelection(state) {
|
|
332
417
|
const expandableIds = expandableRowIds(state.rows);
|
|
333
418
|
const expandedRowIds = (state.expandedRowIds ?? []).filter((id) => expandableIds.includes(id));
|
|
@@ -338,6 +423,20 @@ export function normalizeInkRowSelection(state) {
|
|
|
338
423
|
: expandableIds[expandableIds.length - 1];
|
|
339
424
|
return { ...state, selectedRowId, expandedRowIds };
|
|
340
425
|
}
|
|
426
|
+
export function selectInkSessionRoom(state, room, status) {
|
|
427
|
+
const preserveSession = state.session?.roomId === room.id;
|
|
428
|
+
return {
|
|
429
|
+
...state,
|
|
430
|
+
status,
|
|
431
|
+
activeRoom: room,
|
|
432
|
+
...(preserveSession ? {} : { session: undefined, rows: [], selectedRowId: undefined, expandedRowIds: [] }),
|
|
433
|
+
mode: "transcript",
|
|
434
|
+
picker: undefined,
|
|
435
|
+
overlayStack: undefined,
|
|
436
|
+
message: `Selected room ${room.title}.`,
|
|
437
|
+
error: undefined,
|
|
438
|
+
};
|
|
439
|
+
}
|
|
341
440
|
function selectExpandableRow(state, direction) {
|
|
342
441
|
const normalized = normalizeInkRowSelection(state);
|
|
343
442
|
const ids = expandableRowIds(normalized.rows);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { render } from "ink";
|
|
4
|
-
import { createCustomAgentProfileDefinition } from "../../apps/chat/agent-profiles.js";
|
|
5
4
|
import { createDefaultCustomAgentStore } from "../../apps/chat/agent-store.js";
|
|
6
5
|
import { createDefaultFakeCliSessionSource, LocalCliSessionSource } from "../../cli-session/index.js";
|
|
7
6
|
import { PiboSessionRouter } from "../../core/session-router.js";
|
|
8
7
|
import { PiboDataStore } from "../../data/pibo-store.js";
|
|
9
8
|
import { createDefaultPiboPluginRegistry } from "../../plugins/builtin.js";
|
|
9
|
+
import { registerPiboUserProfileResources } from "../../plugins/user-profile-resources.js";
|
|
10
10
|
import { PiboDataSessionStore } from "../../sessions/pibo-data-store.js";
|
|
11
11
|
import { cliCommandSummaryText, InkSessionApp } from "./InkSessionApp.js";
|
|
12
12
|
export async function runCliSessionsUi(options = {}) {
|
|
@@ -43,6 +43,18 @@ export function createDefaultLocalCliSessionSource() {
|
|
|
43
43
|
}
|
|
44
44
|
function createDebugMockedLocalCliSessionSource(options) {
|
|
45
45
|
const context = createLocalCliSessionSourceContext();
|
|
46
|
+
if (process.env.PIBO_DEBUG_PTY_STREAM_REVIEW === "1") {
|
|
47
|
+
const appendEvent = context.dataStore.eventLog.appendEvent.bind(context.dataStore.eventLog);
|
|
48
|
+
let failFirstAssistantFinal = true;
|
|
49
|
+
context.dataStore.eventLog.appendEvent = (input) => {
|
|
50
|
+
if (failFirstAssistantFinal && input.type === "assistant_message") {
|
|
51
|
+
failFirstAssistantFinal = false;
|
|
52
|
+
process.stderr.write("[debug-pty] injected once-only assistant persistence failure; automatic retry scheduled\n");
|
|
53
|
+
throw new Error("Injected once-only PTY persistence failure");
|
|
54
|
+
}
|
|
55
|
+
return appendEvent(input);
|
|
56
|
+
};
|
|
57
|
+
}
|
|
46
58
|
const debugRooms = debugRoomSummariesFromEnv();
|
|
47
59
|
const router = new DebugMockCliSessionRouter(options.assistantReply);
|
|
48
60
|
return createLocalCliSessionSourceFromContext({
|
|
@@ -71,15 +83,10 @@ function createLocalCliSessionSourceContext() {
|
|
|
71
83
|
const sessionStore = new PiboDataSessionStore(dataStore);
|
|
72
84
|
const pluginRegistry = createDefaultPiboPluginRegistry();
|
|
73
85
|
const builtInAgentSummaries = pluginRegistry.getProfileInfos().map((profile) => ({ id: profile.name, name: profile.name, description: profile.description, profileName: profile.name }));
|
|
86
|
+
registerPiboUserProfileResources(pluginRegistry, { contextFilesMode: "catalog" });
|
|
74
87
|
const customAgentStore = createDefaultCustomAgentStore();
|
|
75
88
|
const customAgents = customAgentStore.list();
|
|
76
|
-
|
|
77
|
-
for (const agent of customAgents)
|
|
78
|
-
pluginRegistry.upsertProfile(createCustomAgentProfileDefinition(agent, { missingReferenceMode: "silent" }));
|
|
79
|
-
}
|
|
80
|
-
finally {
|
|
81
|
-
customAgentStore.close();
|
|
82
|
-
}
|
|
89
|
+
customAgentStore.close();
|
|
83
90
|
const agentSummaries = [
|
|
84
91
|
...builtInAgentSummaries,
|
|
85
92
|
...customAgents.map((agent) => ({ id: agent.profileName, name: agent.profileName, description: agent.description || agent.displayName, profileName: agent.profileName })),
|
|
@@ -122,6 +129,25 @@ class DebugMockCliSessionRouter {
|
|
|
122
129
|
this.publish({ type: "message_queued", piboSessionId: event.piboSessionId, eventId, queuedMessages: 1, text: event.text, source: event.source });
|
|
123
130
|
this.statuses.set(event.piboSessionId, this.status(event.piboSessionId, { processing: true, queuedMessages: 0 }));
|
|
124
131
|
this.publish({ type: "message_started", piboSessionId: event.piboSessionId, eventId, text: event.text, source: event.source });
|
|
132
|
+
if (process.env.PIBO_DEBUG_PTY_STREAM_REVIEW === "1") {
|
|
133
|
+
const tool = { piboSessionId: event.piboSessionId, eventId, toolCallId: "pty-reused", toolName: "read" };
|
|
134
|
+
this.publish({ type: "thinking_started", piboSessionId: event.piboSessionId, eventId, thinkingIndex: 0 });
|
|
135
|
+
this.publish({ type: "thinking_delta", piboSessionId: event.piboSessionId, eventId, thinkingIndex: 0, text: "PTY retained thought" });
|
|
136
|
+
this.publish({ ...tool, type: "tool_execution_finished", result: "PTY tool result", isError: false });
|
|
137
|
+
this.publish({ ...tool, type: "tool_execution_updated", args: { path: "README.md" }, partialResult: "PTY partial tool result" });
|
|
138
|
+
this.publish({ ...tool, type: "tool_execution_started", args: { path: "README.md" } });
|
|
139
|
+
this.publish({ ...tool, type: "tool_call", args: { path: "README.md" }, argsComplete: true });
|
|
140
|
+
this.publish({ ...tool, type: "tool_execution_finished", result: "PTY tool result", isError: false });
|
|
141
|
+
this.publish({ type: "assistant_delta", piboSessionId: event.piboSessionId, eventId, assistantIndex: 0, contentIndex: 0, text: "PTY retained " });
|
|
142
|
+
this.publish({ type: "assistant_delta", piboSessionId: event.piboSessionId, eventId, assistantIndex: 0, contentIndex: 0, text: "answer" });
|
|
143
|
+
this.publish({ type: "thinking_finished", piboSessionId: event.piboSessionId, eventId, thinkingIndex: 0, text: "" });
|
|
144
|
+
const assistant = { type: "assistant_message", piboSessionId: event.piboSessionId, eventId, assistantIndex: 0, contentIndex: 0, text: "" };
|
|
145
|
+
this.publish(assistant);
|
|
146
|
+
const finished = { type: "message_finished", piboSessionId: event.piboSessionId, eventId, source: event.source };
|
|
147
|
+
this.statuses.set(event.piboSessionId, this.status(event.piboSessionId, { processing: false, queuedMessages: 0 }));
|
|
148
|
+
this.publish(finished);
|
|
149
|
+
return assistant;
|
|
150
|
+
}
|
|
125
151
|
const assistant = { type: "assistant_message", piboSessionId: event.piboSessionId, eventId, assistantIndex: 0, contentIndex: 0, text: this.assistantReply };
|
|
126
152
|
this.publish(assistant);
|
|
127
153
|
const finished = { type: "message_finished", piboSessionId: event.piboSessionId, eventId, source: event.source };
|