@pasko70/pibo 3.0.0 → 3.0.2
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/dist/agent-runtime/context-build.js +26 -2
- package/dist/agent-runtime/routed-session.js +108 -9
- 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 +49 -8
- 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 +43 -3
- 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/session-query-service.js +33 -10
- package/dist/apps/chat/data/timeline-query-service.js +60 -35
- 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 +236 -64
- package/dist/apps/chat-ui/assets/{dist-BBDMeU5-.js → dist-B6GZgWSj.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-mqCviI-c.js → dist-BPotHecb.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-JnW4v8UE.js → dist-BzqQKeVO.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BDIATCQt.js → dist-CvaPTBTN.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-lRiLP9rr.js → dist-paagejNj.js} +1 -1
- package/dist/apps/chat-ui/assets/index-6JJV-eic.js +228 -0
- package/dist/apps/chat-ui/assets/index-CeL9JPP5.css +1 -0
- package/dist/apps/chat-ui/index.html +2 -2
- package/dist/apps/chat-vscode-web/assets/{index-Dtw2Z7jz.js → index-U-MSErGa.js} +4 -4
- package/dist/apps/chat-vscode-web/index.html +1 -1
- 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/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 +67 -20
- package/dist/data/ingest-service.js +91 -9
- package/dist/data/navigation-store.js +5 -5
- package/dist/data/schema.js +122 -2
- package/dist/data/session-store.js +3 -3
- package/dist/debug/index.js +44 -2
- package/dist/gateway/web.js +8 -8
- package/dist/local/client.js +3 -2
- package/dist/plugins/context-files-store.js +30 -0
- 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/reliability/store.js +246 -37
- package/dist/session-ui/terminalRows.js +6 -3
- 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/tool.js +7 -3
- package/docs/ops/vscode-extension-release.md +9 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +2 -1
- 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/vscode-artifacts/latest.vsix +0 -0
- package/dist/apps/vscode-artifacts/pibo-vscode-ext-3.0.0.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-U-MSErGa.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/apps/chat-vscode/assets/index-SluZr_-r.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
@@ -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 };
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { DEFAULT_PIBO_PROFILE_NAME,
|
|
2
|
+
import { DEFAULT_PIBO_PROFILE_NAME, resolvePiboProfileNameFromRegistryOrDefault, } from "../plugins/builtin.js";
|
|
3
|
+
import { createDefaultPiboUserProfileRegistry } from "../plugins/user-profile-resources.js";
|
|
3
4
|
import { createDefaultPiboDataSessionStore } from "../sessions/pibo-data-store.js";
|
|
5
|
+
import { OutputRenderSequencer, outputRenderHighWaterStore, validRenderSequence } from "../core/output-render-sequence.js";
|
|
6
|
+
import { OutputPersistenceRetryQueue, } from "../core/output-persistence-retry.js";
|
|
4
7
|
import { getDefaultPiboWorkspace } from "../core/workspace.js";
|
|
5
8
|
import { buildTraceView } from "../apps/chat/trace.js";
|
|
6
9
|
import { storedPiboEventFromV2Row, } from "../apps/chat/data/chat-data-mappers.js";
|
|
7
|
-
import { ChatDataIngestService } from "../data/ingest-service.js";
|
|
10
|
+
import { ChatDataIngestService, outputIdempotencyKey, outputPersistenceDeliveryKey } from "../data/ingest-service.js";
|
|
11
|
+
import { OutputCompactor } from "../apps/chat/output-compactor.js";
|
|
12
|
+
import { isPiboOutputEvent } from "../apps/chat/output-event-policy.js";
|
|
8
13
|
import { ChatRoomService } from "../apps/chat/data/room-service.js";
|
|
9
14
|
import { ChatHistoryQueryService } from "../apps/chat/data/history-query-service.js";
|
|
15
|
+
import { createDefaultPiboReliabilityStore, } from "../reliability/store.js";
|
|
10
16
|
import { buildSlashCommandCatalog, normalizeCommandErrorDescriptor, normalizeCommandResultDescriptor, } from "../session-ui/index.js";
|
|
17
|
+
import { patchTraceViewWithEvent } from "../shared/trace-engine.js";
|
|
11
18
|
import { CliSourceError, } from "./sessionSource.js";
|
|
12
19
|
export const CLI_LOCAL_RECOVERY_SOURCE_ID = "local:root";
|
|
13
20
|
export const CLI_LOCAL_RECOVERY_SOURCE_LABEL = "Local recovery";
|
|
@@ -20,9 +27,14 @@ export class LocalCliSessionSource {
|
|
|
20
27
|
ownsRouter;
|
|
21
28
|
unsubscribeRouter;
|
|
22
29
|
now;
|
|
30
|
+
outputRenderSequencer;
|
|
31
|
+
outputCompactor = new OutputCompactor();
|
|
32
|
+
outputPersistenceRetries;
|
|
23
33
|
statusMessage;
|
|
24
34
|
dataStore;
|
|
25
35
|
ownsDataStore;
|
|
36
|
+
reliabilityStore;
|
|
37
|
+
ownsReliabilityStore;
|
|
26
38
|
ingestService;
|
|
27
39
|
roomService;
|
|
28
40
|
agentSummaries;
|
|
@@ -39,14 +51,28 @@ export class LocalCliSessionSource {
|
|
|
39
51
|
options.ownsSessionStore ?? options.sessionStore === undefined;
|
|
40
52
|
this.roomProvider = options.roomProvider;
|
|
41
53
|
this.pluginRegistry =
|
|
42
|
-
options.pluginRegistry ??
|
|
54
|
+
options.pluginRegistry ?? createDefaultPiboUserProfileRegistry();
|
|
43
55
|
this.router = options.router;
|
|
44
56
|
this.ownsRouter = options.ownsRouter ?? false;
|
|
45
|
-
this.unsubscribeRouter = this.router?.subscribe((event) => this.handleRouterEvent(event));
|
|
46
57
|
this.now = options.now ?? (() => new Date().toISOString());
|
|
58
|
+
this.outputRenderSequencer = new OutputRenderSequencer({
|
|
59
|
+
now: () => {
|
|
60
|
+
const timestamp = Date.parse(this.now());
|
|
61
|
+
return Number.isFinite(timestamp) ? timestamp : Date.now();
|
|
62
|
+
},
|
|
63
|
+
highWaterStore: outputRenderHighWaterStore(this.sessionStore),
|
|
64
|
+
});
|
|
47
65
|
this.statusMessage = options.statusMessage;
|
|
48
66
|
this.dataStore = options.dataStore;
|
|
49
67
|
this.ownsDataStore = options.ownsDataStore === true;
|
|
68
|
+
this.reliabilityStore = options.reliabilityStore
|
|
69
|
+
?? (this.ownsDataStore ? createDefaultPiboReliabilityStore() : undefined);
|
|
70
|
+
this.ownsReliabilityStore = options.ownsReliabilityStore
|
|
71
|
+
?? (this.ownsDataStore && options.reliabilityStore === undefined);
|
|
72
|
+
this.outputPersistenceRetries = new OutputPersistenceRetryQueue({
|
|
73
|
+
durableStore: this.reliabilityStore,
|
|
74
|
+
queueName: "output-persistence-cli",
|
|
75
|
+
});
|
|
50
76
|
this.ingestService = options.dataStore
|
|
51
77
|
? new ChatDataIngestService(options.dataStore)
|
|
52
78
|
: undefined;
|
|
@@ -56,6 +82,13 @@ export class LocalCliSessionSource {
|
|
|
56
82
|
this.agentSummaries = options.agentSummaries
|
|
57
83
|
? [...options.agentSummaries]
|
|
58
84
|
: undefined;
|
|
85
|
+
this.outputPersistenceRetries.recover((job) => {
|
|
86
|
+
const persistenceState = parseCliOutputPersistenceState(job.payload);
|
|
87
|
+
if (!persistenceState)
|
|
88
|
+
throw new Error(`Invalid durable CLI output persistence job ${job.key}`);
|
|
89
|
+
return this.createOutputPersistenceJob(persistenceState);
|
|
90
|
+
});
|
|
91
|
+
this.unsubscribeRouter = this.router?.subscribe((event) => this.handleRouterEvent(event));
|
|
59
92
|
}
|
|
60
93
|
async listRooms() {
|
|
61
94
|
this.assertOpen();
|
|
@@ -179,6 +212,14 @@ export class LocalCliSessionSource {
|
|
|
179
212
|
const session = this.resolveSession(sessionId);
|
|
180
213
|
const eventId = randomUUID();
|
|
181
214
|
this.ingestUserMessage(session, eventId, trimmed);
|
|
215
|
+
this.recordOutputEvent({
|
|
216
|
+
type: "message_queued",
|
|
217
|
+
piboSessionId: sessionId,
|
|
218
|
+
eventId,
|
|
219
|
+
text: trimmed,
|
|
220
|
+
source: "ui",
|
|
221
|
+
queuedMessages: 0,
|
|
222
|
+
});
|
|
182
223
|
if (this.router) {
|
|
183
224
|
try {
|
|
184
225
|
await this.router.emit({
|
|
@@ -195,7 +236,6 @@ export class LocalCliSessionSource {
|
|
|
195
236
|
}
|
|
196
237
|
return;
|
|
197
238
|
}
|
|
198
|
-
this.recordLocalUserMessage(sessionId, eventId, trimmed, "done");
|
|
199
239
|
this.updateSessionStatus(sessionId, "idle");
|
|
200
240
|
}
|
|
201
241
|
async listAgents() {
|
|
@@ -371,14 +411,20 @@ export class LocalCliSessionSource {
|
|
|
371
411
|
}
|
|
372
412
|
try {
|
|
373
413
|
this.closed = true;
|
|
414
|
+
await this.outputPersistenceRetries.drain();
|
|
415
|
+
this.outputPersistenceRetries.dispose();
|
|
374
416
|
for (const handle of [...this.openHandles])
|
|
375
417
|
handle.close();
|
|
376
418
|
this.listeners.clear();
|
|
419
|
+
this.outputRenderSequencer.disposeAll();
|
|
420
|
+
this.outputCompactor.disposeAll();
|
|
377
421
|
this.unsubscribeRouter?.();
|
|
378
422
|
if (this.ownsSessionStore)
|
|
379
423
|
this.sessionStore.close?.();
|
|
380
424
|
if (this.ownsDataStore)
|
|
381
425
|
this.dataStore?.close();
|
|
426
|
+
if (this.ownsReliabilityStore)
|
|
427
|
+
this.reliabilityStore?.close();
|
|
382
428
|
}
|
|
383
429
|
finally {
|
|
384
430
|
this.closing = false;
|
|
@@ -544,170 +590,95 @@ export class LocalCliSessionSource {
|
|
|
544
590
|
handleRouterEvent(event) {
|
|
545
591
|
if (this.closed)
|
|
546
592
|
return;
|
|
593
|
+
if (!isPiboOutputEvent(event)) {
|
|
594
|
+
this.outputPersistenceRetries.quarantine("runtime_output_event_invalid");
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
547
597
|
const session = this.sessionStore.get(event.piboSessionId);
|
|
548
598
|
if (!session)
|
|
549
599
|
return;
|
|
550
|
-
this.
|
|
551
|
-
this.
|
|
600
|
+
const positionedEvent = this.outputRenderSequencer.position(event);
|
|
601
|
+
const compacted = this.outputCompactor.prepare(positionedEvent);
|
|
602
|
+
if (compacted.persistedEvents.length === 0) {
|
|
603
|
+
compacted.ack();
|
|
604
|
+
}
|
|
605
|
+
else {
|
|
606
|
+
const persistenceState = {
|
|
607
|
+
version: 1,
|
|
608
|
+
piboSessionId: session.id,
|
|
609
|
+
deliveries: compacted.persistedEvents.map((persistedEvent) => ({ event: persistedEvent })),
|
|
610
|
+
};
|
|
611
|
+
this.outputPersistenceRetries.enqueue(this.createOutputPersistenceJob(persistenceState, () => compacted.ack(), () => compacted.rollback()));
|
|
612
|
+
}
|
|
613
|
+
for (const liveEvent of compacted.liveEvents)
|
|
614
|
+
this.recordOutputEvent(liveEvent);
|
|
615
|
+
}
|
|
616
|
+
createOutputPersistenceJob(persistenceState, onSuccess, onDeadLetter) {
|
|
617
|
+
const firstEvent = persistenceState.deliveries[0]?.event;
|
|
618
|
+
return {
|
|
619
|
+
key: JSON.stringify(persistenceState.deliveries.map((delivery) => outputPersistenceDeliveryKey(delivery.event))),
|
|
620
|
+
piboSessionId: persistenceState.piboSessionId,
|
|
621
|
+
eventId: firstEvent ? outputPersistenceDeliveryKey(firstEvent) : undefined,
|
|
622
|
+
payload: persistenceState,
|
|
623
|
+
run: (retryContext) => this.deliverOutputPersistenceState(retryContext),
|
|
624
|
+
onSuccess,
|
|
625
|
+
onDeadLetter,
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
deliverOutputPersistenceState(retryContext) {
|
|
629
|
+
const persistenceState = parseCliOutputPersistenceState(retryContext.payload);
|
|
630
|
+
if (!persistenceState)
|
|
631
|
+
throw new Error("Invalid durable CLI output persistence state");
|
|
632
|
+
const session = this.sessionStore.get(persistenceState.piboSessionId);
|
|
633
|
+
if (!session)
|
|
634
|
+
throw new Error(`No session available for ${persistenceState.piboSessionId}`);
|
|
635
|
+
for (const delivery of persistenceState.deliveries) {
|
|
636
|
+
if (delivery.persisted)
|
|
637
|
+
continue;
|
|
638
|
+
if (!this.ingestOutputEvent(session, delivery.event)) {
|
|
639
|
+
throw new Error(`Failed to persist ${outputPersistenceDeliveryKey(delivery.event)}`);
|
|
640
|
+
}
|
|
641
|
+
delivery.persisted = true;
|
|
642
|
+
retryContext.updatePayload(persistenceState);
|
|
643
|
+
}
|
|
552
644
|
}
|
|
553
645
|
recordOutputEvent(event) {
|
|
554
|
-
const
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
646
|
+
const positionedEvent = validRenderSequence(event.renderSequence)
|
|
647
|
+
? event
|
|
648
|
+
: this.outputRenderSequencer.position(event);
|
|
649
|
+
const sessionId = positionedEvent.piboSessionId;
|
|
650
|
+
const session = this.resolveSession(sessionId);
|
|
651
|
+
const current = this.traceViews.get(sessionId) ?? emptyTraceView(session);
|
|
652
|
+
const status = positionedEvent.type === "session_error"
|
|
653
|
+
? "error"
|
|
654
|
+
: positionedEvent.type === "message_finished"
|
|
655
|
+
? "idle"
|
|
656
|
+
: "running";
|
|
657
|
+
const next = patchTraceViewWithEvent(current, storedEvent(positionedEvent, this.now(), current.rawEvents.length + 1), status === "idle" ? "idle" : status);
|
|
658
|
+
next.eventCount = next.rawEvents.length;
|
|
659
|
+
next.version = `local-${next.rawEvents.length}-${session.updatedAt}`;
|
|
660
|
+
this.traceViews.set(sessionId, next);
|
|
661
|
+
this.emit(sessionId, {
|
|
662
|
+
type: "trace",
|
|
663
|
+
session: sessionToSummary(session, this.ensureDefaultRoom().id),
|
|
664
|
+
traceView: next,
|
|
665
|
+
});
|
|
666
|
+
if (positionedEvent.type === "message_queued" || positionedEvent.type === "message_started") {
|
|
558
667
|
this.updateSessionStatus(sessionId, "running");
|
|
559
|
-
return;
|
|
560
668
|
}
|
|
561
|
-
if (
|
|
669
|
+
else if (positionedEvent.type === "message_finished") {
|
|
562
670
|
this.updateSessionStatus(sessionId, "idle");
|
|
563
|
-
return;
|
|
564
|
-
}
|
|
565
|
-
if (event.type === "assistant_delta") {
|
|
566
|
-
this.upsertTraceNode(sessionId, {
|
|
567
|
-
id: traceNodeId("assistant", eventId, event.assistantIndex ?? event.contentIndex),
|
|
568
|
-
piboSessionId: sessionId,
|
|
569
|
-
type: "assistant.message",
|
|
570
|
-
title: "Agent Message",
|
|
571
|
-
status: "running",
|
|
572
|
-
startedAt: this.now(),
|
|
573
|
-
output: event.text,
|
|
574
|
-
children: [],
|
|
575
|
-
}, { appendOutput: true, rawEvent: event });
|
|
576
|
-
return;
|
|
577
|
-
}
|
|
578
|
-
if (event.type === "assistant_message") {
|
|
579
|
-
this.upsertTraceNode(sessionId, {
|
|
580
|
-
id: traceNodeId("assistant", eventId, event.assistantIndex ?? event.contentIndex),
|
|
581
|
-
piboSessionId: sessionId,
|
|
582
|
-
type: "assistant.message",
|
|
583
|
-
title: "Agent Message",
|
|
584
|
-
status: "done",
|
|
585
|
-
startedAt: this.now(),
|
|
586
|
-
completedAt: this.now(),
|
|
587
|
-
output: event.text,
|
|
588
|
-
children: [],
|
|
589
|
-
}, { rawEvent: event });
|
|
590
|
-
return;
|
|
591
|
-
}
|
|
592
|
-
if (event.type === "tool_call" ||
|
|
593
|
-
event.type === "tool_execution_started" ||
|
|
594
|
-
event.type === "tool_execution_updated" ||
|
|
595
|
-
event.type === "tool_execution_finished") {
|
|
596
|
-
const finished = event.type === "tool_execution_finished";
|
|
597
|
-
this.upsertTraceNode(sessionId, {
|
|
598
|
-
id: traceNodeId("tool", event.toolCallId),
|
|
599
|
-
piboSessionId: sessionId,
|
|
600
|
-
eventId,
|
|
601
|
-
toolCallId: event.toolCallId,
|
|
602
|
-
type: finished ? "tool.result" : "tool.call",
|
|
603
|
-
title: event.toolName,
|
|
604
|
-
status: finished ? (event.isError ? "error" : "done") : "running",
|
|
605
|
-
startedAt: this.now(),
|
|
606
|
-
completedAt: finished ? this.now() : undefined,
|
|
607
|
-
input: "args" in event ? event.args : undefined,
|
|
608
|
-
output: finished
|
|
609
|
-
? event.result
|
|
610
|
-
: "partialResult" in event
|
|
611
|
-
? event.partialResult
|
|
612
|
-
: undefined,
|
|
613
|
-
children: [],
|
|
614
|
-
}, { rawEvent: event });
|
|
615
|
-
return;
|
|
616
671
|
}
|
|
617
|
-
if (
|
|
618
|
-
this.
|
|
619
|
-
return;
|
|
672
|
+
else if (positionedEvent.type === "session_error") {
|
|
673
|
+
this.updateSessionStatus(sessionId, "error");
|
|
620
674
|
}
|
|
621
|
-
this.appendRawEvent(sessionId, event);
|
|
622
|
-
}
|
|
623
|
-
recordLocalUserMessage(sessionId, eventId, text, status) {
|
|
624
|
-
this.upsertTraceNode(sessionId, {
|
|
625
|
-
id: traceNodeId("user", eventId),
|
|
626
|
-
piboSessionId: sessionId,
|
|
627
|
-
eventId,
|
|
628
|
-
type: "user.message",
|
|
629
|
-
title: "User Message",
|
|
630
|
-
status,
|
|
631
|
-
startedAt: this.now(),
|
|
632
|
-
completedAt: status === "done" ? this.now() : undefined,
|
|
633
|
-
output: text,
|
|
634
|
-
children: [],
|
|
635
|
-
}, {
|
|
636
|
-
rawEvent: {
|
|
637
|
-
type: "message_queued",
|
|
638
|
-
piboSessionId: sessionId,
|
|
639
|
-
eventId,
|
|
640
|
-
queuedMessages: 0,
|
|
641
|
-
text,
|
|
642
|
-
source: "ui",
|
|
643
|
-
},
|
|
644
|
-
});
|
|
645
675
|
}
|
|
646
676
|
recordLocalError(sessionId, eventId, error) {
|
|
647
|
-
this.
|
|
648
|
-
|
|
677
|
+
this.recordOutputEvent({
|
|
678
|
+
type: "session_error",
|
|
649
679
|
piboSessionId: sessionId,
|
|
650
680
|
eventId,
|
|
651
|
-
type: "error",
|
|
652
|
-
title: "CLI source error",
|
|
653
|
-
status: "error",
|
|
654
|
-
startedAt: this.now(),
|
|
655
|
-
completedAt: this.now(),
|
|
656
681
|
error: error instanceof Error ? error.message : String(error),
|
|
657
|
-
children: [],
|
|
658
|
-
}, {
|
|
659
|
-
rawEvent: {
|
|
660
|
-
type: "session_error",
|
|
661
|
-
piboSessionId: sessionId,
|
|
662
|
-
eventId,
|
|
663
|
-
error: error instanceof Error ? error.message : String(error),
|
|
664
|
-
},
|
|
665
|
-
});
|
|
666
|
-
this.updateSessionStatus(sessionId, "error");
|
|
667
|
-
}
|
|
668
|
-
upsertTraceNode(sessionId, node, options = {}) {
|
|
669
|
-
const session = this.resolveSession(sessionId);
|
|
670
|
-
const traceView = cloneJson(this.traceViews.get(sessionId) ?? emptyTraceView(session));
|
|
671
|
-
const index = traceView.nodes.findIndex((candidate) => candidate.id === node.id);
|
|
672
|
-
if (index >= 0) {
|
|
673
|
-
const previous = traceView.nodes[index];
|
|
674
|
-
const output = options.appendOutput &&
|
|
675
|
-
typeof previous.output === "string" &&
|
|
676
|
-
typeof node.output === "string"
|
|
677
|
-
? previous.output + node.output
|
|
678
|
-
: node.output;
|
|
679
|
-
traceView.nodes[index] = {
|
|
680
|
-
...previous,
|
|
681
|
-
...node,
|
|
682
|
-
output,
|
|
683
|
-
children: node.children ?? previous.children,
|
|
684
|
-
};
|
|
685
|
-
}
|
|
686
|
-
else {
|
|
687
|
-
traceView.nodes.push(node);
|
|
688
|
-
}
|
|
689
|
-
if (options.rawEvent)
|
|
690
|
-
traceView.rawEvents.push(storedEvent(options.rawEvent, this.now(), traceView.rawEvents.length + 1));
|
|
691
|
-
traceView.eventCount = traceView.rawEvents.length;
|
|
692
|
-
traceView.version = `local-${traceView.rawEvents.length}-${session.updatedAt}`;
|
|
693
|
-
this.traceViews.set(sessionId, traceView);
|
|
694
|
-
this.emit(sessionId, {
|
|
695
|
-
type: "trace",
|
|
696
|
-
session: sessionToSummary(session, this.ensureDefaultRoom().id),
|
|
697
|
-
traceView: cloneJson(traceView),
|
|
698
|
-
});
|
|
699
|
-
}
|
|
700
|
-
appendRawEvent(sessionId, event) {
|
|
701
|
-
const session = this.resolveSession(sessionId);
|
|
702
|
-
const traceView = cloneJson(this.traceViews.get(sessionId) ?? emptyTraceView(session));
|
|
703
|
-
traceView.rawEvents.push(storedEvent(event, this.now(), traceView.rawEvents.length + 1));
|
|
704
|
-
traceView.eventCount = traceView.rawEvents.length;
|
|
705
|
-
traceView.version = `local-${traceView.rawEvents.length}-${session.updatedAt}`;
|
|
706
|
-
this.traceViews.set(sessionId, traceView);
|
|
707
|
-
this.emit(sessionId, {
|
|
708
|
-
type: "trace",
|
|
709
|
-
session: sessionToSummary(session, this.ensureDefaultRoom().id),
|
|
710
|
-
traceView: cloneJson(traceView),
|
|
711
682
|
});
|
|
712
683
|
}
|
|
713
684
|
updateSessionStatus(sessionId, status) {
|
|
@@ -770,7 +741,7 @@ export class LocalCliSessionSource {
|
|
|
770
741
|
}
|
|
771
742
|
ingestOutputEvent(session, event) {
|
|
772
743
|
if (!this.ingestService)
|
|
773
|
-
return;
|
|
744
|
+
return true;
|
|
774
745
|
try {
|
|
775
746
|
this.ingestService.ingestOutputEvent({
|
|
776
747
|
session,
|
|
@@ -779,9 +750,11 @@ export class LocalCliSessionSource {
|
|
|
779
750
|
event,
|
|
780
751
|
createdAt: this.now(),
|
|
781
752
|
});
|
|
753
|
+
return true;
|
|
782
754
|
}
|
|
783
755
|
catch {
|
|
784
|
-
//
|
|
756
|
+
// The caller retains the prepared compaction and retries this exact event identity.
|
|
757
|
+
return false;
|
|
785
758
|
}
|
|
786
759
|
}
|
|
787
760
|
buildStatus(session) {
|
|
@@ -860,6 +833,29 @@ export class LocalCliSessionSource {
|
|
|
860
833
|
export function createLocalCliSessionSource(options = {}) {
|
|
861
834
|
return new LocalCliSessionSource(options);
|
|
862
835
|
}
|
|
836
|
+
function parseCliOutputPersistenceState(value) {
|
|
837
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
838
|
+
return undefined;
|
|
839
|
+
const candidate = value;
|
|
840
|
+
if (candidate.version !== 1 || typeof candidate.piboSessionId !== "string" || !Array.isArray(candidate.deliveries))
|
|
841
|
+
return undefined;
|
|
842
|
+
const deliveries = [];
|
|
843
|
+
for (const rawDelivery of candidate.deliveries) {
|
|
844
|
+
if (!rawDelivery || typeof rawDelivery !== "object" || Array.isArray(rawDelivery))
|
|
845
|
+
return undefined;
|
|
846
|
+
const delivery = rawDelivery;
|
|
847
|
+
const event = delivery.event;
|
|
848
|
+
if (!isPiboOutputEvent(event) || !outputIdempotencyKey(event))
|
|
849
|
+
return undefined;
|
|
850
|
+
deliveries.push({
|
|
851
|
+
event: event,
|
|
852
|
+
...(delivery.persisted === true ? { persisted: true } : {}),
|
|
853
|
+
});
|
|
854
|
+
}
|
|
855
|
+
if (!deliveries.length)
|
|
856
|
+
return undefined;
|
|
857
|
+
return { version: 1, piboSessionId: candidate.piboSessionId, deliveries };
|
|
858
|
+
}
|
|
863
859
|
export function redactCliSecretText(text) {
|
|
864
860
|
return text
|
|
865
861
|
.replace(/\b([A-Z0-9_]*(?:API[_-]?KEY|TOKEN|SECRET|PASSWORD)[A-Z0-9_]*)\s*=\s*([^\s]+)/gi, "$1=[redacted]")
|
|
@@ -989,17 +985,13 @@ function storedEvent(event, createdAt, eventSequence) {
|
|
|
989
985
|
id: eventId ?? `${event.piboSessionId}-${event.type}-${eventSequence}`,
|
|
990
986
|
piboSessionId: event.piboSessionId,
|
|
991
987
|
eventSequence,
|
|
988
|
+
renderSequence: event.renderSequence,
|
|
992
989
|
eventId,
|
|
993
990
|
type: event.type,
|
|
994
991
|
createdAt,
|
|
995
992
|
payload: cloneJson(event),
|
|
996
993
|
};
|
|
997
994
|
}
|
|
998
|
-
function traceNodeId(kind, eventId, index) {
|
|
999
|
-
return ["local", kind, eventId ?? "event", index]
|
|
1000
|
-
.filter((part) => part !== undefined)
|
|
1001
|
-
.join(":");
|
|
1002
|
-
}
|
|
1003
995
|
function toCliSourceError(code, message, cause) {
|
|
1004
996
|
return cause instanceof CliSourceError
|
|
1005
997
|
? cause
|
package/dist/cli.js
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
2
|
import { Command } from "commander";
|
|
3
3
|
import { PIBO_CONFIG_KEYS, getDefaultPiboConfigPath, deletePiboConfigValue, getDisplayPiboConfigValue, loadPiboConfig, redactPiboConfig, savePiboConfig, setPiboConfigValue, } from "./config/config.js";
|
|
4
4
|
import { parsePiboThinkingLevel } from "./core/thinking.js";
|
|
5
|
-
import { ensurePrivatePiboHome
|
|
5
|
+
import { ensurePrivatePiboHome } from "./core/pibo-home.js";
|
|
6
6
|
async function resolveCliProfile(profileName) {
|
|
7
|
-
const {
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
if (existsSync(chatAgentStorePath)) {
|
|
11
|
-
const { createPiboChatCustomAgentProfilesPlugin } = await import("./plugins/chat-custom-agents.js");
|
|
12
|
-
registry.registerPlugin(createPiboChatCustomAgentProfilesPlugin({ agentStorePath: chatAgentStorePath }));
|
|
13
|
-
}
|
|
7
|
+
const { createGatewayProducerPiboProfile, createPiboProfileFromRegistryOrDefault } = await import("./plugins/builtin.js");
|
|
8
|
+
const { createDefaultPiboUserProfileRegistry } = await import("./plugins/user-profile-resources.js");
|
|
9
|
+
const registry = createDefaultPiboUserProfileRegistry();
|
|
14
10
|
const profile = profileName === "gateway-producer" || profileName === "pibo-gateway-producer"
|
|
15
11
|
? createGatewayProducerPiboProfile()
|
|
16
12
|
: createPiboProfileFromRegistryOrDefault(registry, profileName);
|
|
@@ -281,7 +277,7 @@ export async function runPiboCli(argv = process.argv) {
|
|
|
281
277
|
});
|
|
282
278
|
program
|
|
283
279
|
.command("setup")
|
|
284
|
-
.description("Plan
|
|
280
|
+
.description("Plan and manage supported host installation profiles")
|
|
285
281
|
.helpOption(false)
|
|
286
282
|
.allowUnknownOption(true)
|
|
287
283
|
.allowExcessArguments(true)
|
|
@@ -533,7 +529,7 @@ Commands:
|
|
|
533
529
|
compute Manage Pibo Docker compute workers
|
|
534
530
|
resources Inspect and safely reap managed compute and browser resources
|
|
535
531
|
preview Expose session-linked live development previews
|
|
536
|
-
setup Plan
|
|
532
|
+
setup Plan and manage supported host installation profiles
|
|
537
533
|
skills Manage Pibo user skills
|
|
538
534
|
cron Manage scheduled Pibo jobs
|
|
539
535
|
loop Manage continuous agent loops (goal mode by default)
|
|
@@ -214,6 +214,7 @@ function withoutRequestedModels(profile) {
|
|
|
214
214
|
mcpServers: profile.mcpServers,
|
|
215
215
|
piPackages: profile.piPackages,
|
|
216
216
|
contextFiles: profile.contextFiles,
|
|
217
|
+
diagnostics: profile.diagnostics,
|
|
217
218
|
builtinTools: profile.builtinTools,
|
|
218
219
|
builtinToolNames: profile.builtinToolNames,
|
|
219
220
|
autoContextFiles: profile.autoContextFiles,
|
|
@@ -229,15 +230,15 @@ function toolDefinitionSchema(definition, toolInfo) {
|
|
|
229
230
|
}
|
|
230
231
|
function generatedOriginForTool(name, profile) {
|
|
231
232
|
if (name === "runtime")
|
|
232
|
-
return "
|
|
233
|
+
return "pibo-runtime";
|
|
233
234
|
if (name.startsWith("pibo_agents_"))
|
|
234
|
-
return "
|
|
235
|
+
return "pibo-subagents";
|
|
235
236
|
if (name.startsWith("pibo_run_"))
|
|
236
|
-
return "
|
|
237
|
+
return "pibo-run-control";
|
|
237
238
|
if (PIBO_GOAL_TOOL_NAMES.includes(name))
|
|
238
|
-
return "
|
|
239
|
+
return "pibo-goal-control";
|
|
239
240
|
if (name === "apply_patch" || name === "view_image")
|
|
240
|
-
return "
|
|
241
|
+
return "codex-compat";
|
|
241
242
|
if (profile.builtinToolNames.includes(name) || DEFAULT_BUILTIN_TOOL_NAMES.includes(name))
|
|
242
243
|
return undefined;
|
|
243
244
|
return undefined;
|
|
@@ -502,17 +503,6 @@ export async function inspectPiboContextBuild(options = {}) {
|
|
|
502
503
|
},
|
|
503
504
|
});
|
|
504
505
|
}
|
|
505
|
-
if (generatedOrigin) {
|
|
506
|
-
children.push({
|
|
507
|
-
id: `tools/${name}/generated-origin`,
|
|
508
|
-
kind: "metadata",
|
|
509
|
-
title: "Generated Origin",
|
|
510
|
-
source: "generated",
|
|
511
|
-
state: "active",
|
|
512
|
-
badges: ["GENERATED", "PIBO"],
|
|
513
|
-
hydratedText: generatedOrigin,
|
|
514
|
-
});
|
|
515
|
-
}
|
|
516
506
|
if (providerTool?.providerTool.kind === "web_search") {
|
|
517
507
|
children.push({
|
|
518
508
|
id: `tools/${name}/provider-payload`,
|
|
@@ -568,6 +558,7 @@ export async function inspectPiboContextBuild(options = {}) {
|
|
|
568
558
|
hasDefinition: Boolean(definition || info),
|
|
569
559
|
description: definition?.description ?? info?.description ?? providerTool?.description,
|
|
570
560
|
...(toolSource === "pibo" || toolSource === "generated" ? { owner: "pibo", deliveryMode: "direct" } : {}),
|
|
561
|
+
...(generatedOrigin ? { inspectorOrigin: { label: generatedOrigin, modelVisible: false } } : {}),
|
|
571
562
|
},
|
|
572
563
|
children,
|
|
573
564
|
};
|