@oh-my-pi/pi-coding-agent 15.11.7 → 15.11.8
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/CHANGELOG.md +30 -2
- package/dist/cli.js +363 -356
- package/dist/types/cli/args.d.ts +2 -0
- package/dist/types/collab/crypto.d.ts +12 -0
- package/dist/types/collab/guest.d.ts +21 -0
- package/dist/types/collab/host.d.ts +13 -0
- package/dist/types/collab/protocol.d.ts +100 -0
- package/dist/types/collab/relay-client.d.ts +22 -0
- package/dist/types/commands/join.d.ts +12 -0
- package/dist/types/config/settings-schema.d.ts +21 -1
- package/dist/types/extensibility/slash-commands.d.ts +1 -11
- package/dist/types/modes/components/agent-hub.d.ts +13 -0
- package/dist/types/modes/components/collab-prompt-message.d.ts +10 -0
- package/dist/types/modes/components/hook-selector.d.ts +4 -6
- package/dist/types/modes/components/segment-track.d.ts +11 -6
- package/dist/types/modes/components/status-line/component.d.ts +4 -1
- package/dist/types/modes/components/status-line/types.d.ts +9 -0
- package/dist/types/modes/interactive-mode.d.ts +7 -0
- package/dist/types/modes/types.d.ts +8 -0
- package/dist/types/session/agent-session.d.ts +11 -0
- package/dist/types/session/session-manager.d.ts +21 -0
- package/dist/types/session/snapcompact-inline.d.ts +6 -3
- package/dist/types/slash-commands/builtin-registry.d.ts +9 -0
- package/package.json +14 -12
- package/scripts/bench-guard.ts +71 -0
- package/src/cli/args.ts +2 -0
- package/src/cli-commands.ts +1 -0
- package/src/collab/crypto.ts +57 -0
- package/src/collab/guest.ts +421 -0
- package/src/collab/host.ts +494 -0
- package/src/collab/protocol.ts +191 -0
- package/src/collab/relay-client.ts +216 -0
- package/src/commands/join.ts +39 -0
- package/src/config/model-registry.ts +22 -14
- package/src/config/settings-schema.ts +27 -1
- package/src/extensibility/slash-commands.ts +1 -97
- package/src/internal-urls/docs-index.generated.ts +3 -2
- package/src/main.ts +11 -2
- package/src/modes/components/agent-hub.ts +119 -22
- package/src/modes/components/assistant-message.ts +126 -6
- package/src/modes/components/collab-prompt-message.ts +30 -0
- package/src/modes/components/hook-selector.ts +4 -5
- package/src/modes/components/segment-track.ts +44 -7
- package/src/modes/components/status-line/component.ts +21 -1
- package/src/modes/components/status-line/presets.ts +1 -1
- package/src/modes/components/status-line/segments.ts +13 -0
- package/src/modes/components/status-line/types.ts +10 -0
- package/src/modes/components/tips.txt +2 -1
- package/src/modes/controllers/input-controller.ts +72 -6
- package/src/modes/controllers/selector-controller.ts +2 -0
- package/src/modes/controllers/streaming-reveal.ts +7 -0
- package/src/modes/interactive-mode.ts +12 -4
- package/src/modes/types.ts +8 -0
- package/src/modes/utils/ui-helpers.ts +7 -0
- package/src/sdk.ts +239 -36
- package/src/session/agent-session.ts +17 -0
- package/src/session/session-manager.ts +44 -0
- package/src/session/snapcompact-inline.ts +9 -3
- package/src/slash-commands/builtin-registry.ts +210 -0
- package/src/tools/read.ts +38 -5
- package/src/tools/write.ts +13 -42
|
@@ -493,6 +493,18 @@ const sessionNameSegment: StatusLineSegment = {
|
|
|
493
493
|
},
|
|
494
494
|
};
|
|
495
495
|
|
|
496
|
+
const collabSegment: StatusLineSegment = {
|
|
497
|
+
id: "collab",
|
|
498
|
+
render(ctx) {
|
|
499
|
+
if (!ctx.collab) return { content: "", visible: false };
|
|
500
|
+
const label =
|
|
501
|
+
ctx.collab.role === "host"
|
|
502
|
+
? `⇄ collab:${ctx.collab.participantCount}`
|
|
503
|
+
: `⇄ collab guest:${ctx.collab.participantCount}`;
|
|
504
|
+
return { content: theme.fg("accent", label), visible: true };
|
|
505
|
+
},
|
|
506
|
+
};
|
|
507
|
+
|
|
496
508
|
function pickUsageColor(percent: number): "muted" | "warning" | "error" {
|
|
497
509
|
if (percent >= 80) return "error";
|
|
498
510
|
if (percent >= 50) return "warning";
|
|
@@ -573,6 +585,7 @@ export const SEGMENTS: Record<StatusLineSegmentId, StatusLineSegment> = {
|
|
|
573
585
|
cache_hit: cacheHitSegment,
|
|
574
586
|
session_name: sessionNameSegment,
|
|
575
587
|
usage: usageSegment,
|
|
588
|
+
collab: collabSegment,
|
|
576
589
|
};
|
|
577
590
|
|
|
578
591
|
export function renderSegment(id: StatusLineSegmentId, ctx: SegmentContext): RenderedSegment {
|
|
@@ -1,8 +1,17 @@
|
|
|
1
|
+
import type { CollabSessionState } from "../../../collab/protocol";
|
|
1
2
|
import type { StatusLinePreset, StatusLineSegmentId, StatusLineSeparatorStyle } from "../../../config/settings-schema";
|
|
2
3
|
import type { AgentSession } from "../../../session/agent-session";
|
|
3
4
|
|
|
4
5
|
export type { StatusLinePreset, StatusLineSegmentId, StatusLineSeparatorStyle };
|
|
5
6
|
|
|
7
|
+
/** Collab session indicator + (guest-only) host-state override for segments. */
|
|
8
|
+
export interface CollabStatus {
|
|
9
|
+
role: "host" | "guest";
|
|
10
|
+
participantCount: number;
|
|
11
|
+
/** Guest only: host footer snapshot that overrides locally computed values. */
|
|
12
|
+
stateOverride?: CollabSessionState | null;
|
|
13
|
+
}
|
|
14
|
+
|
|
6
15
|
export interface StatusLineSegmentOptions {
|
|
7
16
|
model?: { showThinkingLevel?: boolean };
|
|
8
17
|
path?: { abbreviate?: boolean; maxLength?: number; stripWorkPrefix?: boolean };
|
|
@@ -49,6 +58,7 @@ export interface SegmentContext {
|
|
|
49
58
|
enabled: boolean;
|
|
50
59
|
paused: boolean;
|
|
51
60
|
} | null;
|
|
61
|
+
collab: CollabStatus | null;
|
|
52
62
|
// Cached values for performance (computed once per render)
|
|
53
63
|
usageStats: {
|
|
54
64
|
input: number;
|
|
@@ -16,4 +16,5 @@ Press alt+p (or /switch) to switch provider, and ctrl+p to cycle role models smo
|
|
|
16
16
|
Press ctrl+r to search your prompt history and reuse a past message
|
|
17
17
|
`/force read` pins the next turn to one specific tool when the model keeps reaching for the wrong one
|
|
18
18
|
`/copy code` grabs the last code block to your clipboard — `/copy cmd` grabs the last shell/python command
|
|
19
|
-
`/shake` rips heavy tool results out of context to reclaim tokens without a full /compact — `/shake images` drops just images
|
|
19
|
+
`/shake` rips heavy tool results out of context to reclaim tokens without a full /compact — `/shake images` drops just images
|
|
20
|
+
Pair up live: `/collab` shares your session through an end-to-end encrypted relay link — a teammate runs `/join <link>` to watch tool calls stream and prompt the agent from their own omp
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import * as fs from "node:fs/promises";
|
|
2
2
|
import type { ImageContent } from "@oh-my-pi/pi-ai";
|
|
3
3
|
import type { AutocompleteProvider, SlashCommand } from "@oh-my-pi/pi-tui";
|
|
4
|
-
import { $env, logger, sanitizeText } from "@oh-my-pi/pi-utils";
|
|
5
|
-
import { getRoleInfo } from "../../config/model-roles";
|
|
4
|
+
import { $env, isEnoent, logger, sanitizeText } from "@oh-my-pi/pi-utils";
|
|
6
5
|
import { isSettingsInitialized, settings } from "../../config/settings";
|
|
7
6
|
import { AssistantMessageComponent } from "../../modes/components/assistant-message";
|
|
8
7
|
import { renderSegmentTrack } from "../../modes/components/segment-track";
|
|
@@ -18,6 +17,7 @@ import { isTinyTitleLocalModelKey } from "../../tiny/models";
|
|
|
18
17
|
import { isLowSignalTitleInput } from "../../tiny/text";
|
|
19
18
|
import { tinyTitleClient } from "../../tiny/title-client";
|
|
20
19
|
import type { TinyTitleProgressEvent } from "../../tiny/title-protocol";
|
|
20
|
+
import { shortenPath, TRUNCATE_LENGTHS, truncateToWidth } from "../../tools/render-utils";
|
|
21
21
|
import { copyToClipboard, readImageFromClipboard, readTextFromClipboard } from "../../utils/clipboard";
|
|
22
22
|
import { EnhancedPasteController } from "../../utils/enhanced-paste";
|
|
23
23
|
import { getEditorCommand, openInEditor } from "../../utils/external-editor";
|
|
@@ -125,6 +125,16 @@ export class InputController {
|
|
|
125
125
|
if (this.ctx.hasActiveOmfg() && this.ctx.handleOmfgEscape()) {
|
|
126
126
|
return;
|
|
127
127
|
}
|
|
128
|
+
if (this.ctx.collabGuest) {
|
|
129
|
+
// Guest Esc: ask the host to interrupt its agent; the local replica
|
|
130
|
+
// session is never streaming, so the native abort path below would
|
|
131
|
+
// no-op.
|
|
132
|
+
if (this.ctx.collabGuest.state?.isStreaming || this.ctx.loadingAnimation) {
|
|
133
|
+
this.ctx.notifyInterrupting();
|
|
134
|
+
this.ctx.collabGuest.sendAbort();
|
|
135
|
+
}
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
128
138
|
if (this.ctx.loadingAnimation) {
|
|
129
139
|
if (this.ctx.cancelPendingSubmission()) {
|
|
130
140
|
return;
|
|
@@ -392,6 +402,32 @@ export class InputController {
|
|
|
392
402
|
text = slashResult;
|
|
393
403
|
}
|
|
394
404
|
|
|
405
|
+
// Collab guest: prompts execute on the host; local slash/skill/bash/
|
|
406
|
+
// python execution is host-only (builtins are gated inside
|
|
407
|
+
// executeBuiltinSlashCommand, which already consumed allowed ones).
|
|
408
|
+
if (this.ctx.collabGuest) {
|
|
409
|
+
if (text.startsWith("/")) {
|
|
410
|
+
this.ctx.showStatus(`${text.split(/\s+/, 1)[0]} is host-only during a collab session`);
|
|
411
|
+
this.ctx.editor.setText("");
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
if (text.startsWith("!") || text.startsWith("$")) {
|
|
415
|
+
this.ctx.showStatus("Local execution is host-only during a collab session");
|
|
416
|
+
this.ctx.editor.setText("");
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
this.ctx.editor.addToHistory(text);
|
|
420
|
+
this.ctx.editor.setText("");
|
|
421
|
+
this.ctx.editor.imageLinks = undefined;
|
|
422
|
+
const images = inputImages && inputImages.length > 0 ? [...inputImages] : undefined;
|
|
423
|
+
this.ctx.pendingImages = [];
|
|
424
|
+
this.ctx.pendingImageLinks = [];
|
|
425
|
+
// No local render: the prompt comes back from the host as a
|
|
426
|
+
// collab-prompt event/entry and renders with the author badge.
|
|
427
|
+
this.ctx.collabGuest.sendPrompt(text, images);
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
|
|
395
431
|
// Handle skill commands (/skill:name [args]). Enter ⇒ steer (matches the
|
|
396
432
|
// free-text Enter semantics applied a few lines below at the streaming
|
|
397
433
|
// branch). Ctrl+Enter routes through `handleFollowUp` and dispatches the
|
|
@@ -874,11 +910,41 @@ export class InputController {
|
|
|
874
910
|
`Unsupported pasted image format: ${image.mimeType}`,
|
|
875
911
|
);
|
|
876
912
|
} catch (error) {
|
|
913
|
+
if (error instanceof ImageInputTooLargeError) {
|
|
914
|
+
this.ctx.editor.pasteText(path);
|
|
915
|
+
this.ctx.ui.requestRender();
|
|
916
|
+
this.ctx.showStatus(error.message);
|
|
917
|
+
return;
|
|
918
|
+
}
|
|
919
|
+
if (isEnoent(error)) {
|
|
920
|
+
// #2375: the bracketed paste forwarded by a local terminal carries a
|
|
921
|
+
// path on the *local* filesystem. When omp itself runs over SSH, that
|
|
922
|
+
// path is unreachable here; pasting it as text would look like the
|
|
923
|
+
// image was attached when in fact nothing was sent. Refuse the silent
|
|
924
|
+
// degrade and tell the user how to send the bytes for real. The
|
|
925
|
+
// pasted path is untrusted terminal input — strip control/ANSI/
|
|
926
|
+
// newlines, collapse home to `~`, and bound the displayed length
|
|
927
|
+
// before splicing it into the status string.
|
|
928
|
+
const displayPath = truncateToWidth(
|
|
929
|
+
shortenPath(
|
|
930
|
+
sanitizeText(path)
|
|
931
|
+
.replace(/[\r\n\t]+/g, " ")
|
|
932
|
+
.trim(),
|
|
933
|
+
),
|
|
934
|
+
TRUNCATE_LENGTHS.CONTENT,
|
|
935
|
+
);
|
|
936
|
+
const env = process.env;
|
|
937
|
+
const overSsh = Boolean(env.SSH_CONNECTION || env.SSH_TTY || env.SSH_CLIENT);
|
|
938
|
+
this.ctx.showStatus(
|
|
939
|
+
overSsh
|
|
940
|
+
? `Image not found at ${displayPath}. Over SSH this path is local to your terminal — paste the image directly (clipboard image-paste shortcut) to send its bytes.`
|
|
941
|
+
: `Image not found at ${displayPath}`,
|
|
942
|
+
);
|
|
943
|
+
return;
|
|
944
|
+
}
|
|
877
945
|
this.ctx.editor.pasteText(path);
|
|
878
946
|
this.ctx.ui.requestRender();
|
|
879
|
-
this.ctx.showStatus(
|
|
880
|
-
error instanceof ImageInputTooLargeError ? error.message : "Failed to read pasted image path",
|
|
881
|
-
);
|
|
947
|
+
this.ctx.showStatus("Failed to read pasted image path");
|
|
882
948
|
}
|
|
883
949
|
}
|
|
884
950
|
|
|
@@ -1007,7 +1073,7 @@ export class InputController {
|
|
|
1007
1073
|
// the cycle status is just a status-line-style chip track (active role
|
|
1008
1074
|
// filled), matching the plan-approval model slider.
|
|
1009
1075
|
const track = renderSegmentTrack(
|
|
1010
|
-
cycleOrder.map(role => ({ label: role
|
|
1076
|
+
cycleOrder.map(role => ({ label: role })),
|
|
1011
1077
|
cycleOrder.indexOf(result.role),
|
|
1012
1078
|
);
|
|
1013
1079
|
this.ctx.showStatus(track, { dim: false });
|
|
@@ -1188,6 +1188,8 @@ export class SelectorController {
|
|
|
1188
1188
|
hubKeys,
|
|
1189
1189
|
onDone: done,
|
|
1190
1190
|
requestRender: () => this.ctx.ui.requestRender(),
|
|
1191
|
+
registry: this.ctx.collabGuest?.agentRegistry,
|
|
1192
|
+
remote: this.ctx.collabGuest?.hubRemote,
|
|
1191
1193
|
});
|
|
1192
1194
|
|
|
1193
1195
|
overlayHandle = this.ctx.ui.showOverlay(hub, {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { AssistantMessage } from "@oh-my-pi/pi-ai";
|
|
2
2
|
import { getSegmenter } from "@oh-my-pi/pi-tui";
|
|
3
|
+
import { LRUCache } from "lru-cache/raw";
|
|
3
4
|
import type { AssistantMessageComponent } from "../components/assistant-message";
|
|
4
5
|
|
|
5
6
|
export const STREAMING_REVEAL_FRAME_MS = 1000 / 30;
|
|
@@ -15,11 +16,17 @@ type StreamingRevealControllerOptions = {
|
|
|
15
16
|
requestRender(): void;
|
|
16
17
|
};
|
|
17
18
|
|
|
19
|
+
const graphemeCountCache = new LRUCache<string, number>({ max: 128 });
|
|
20
|
+
|
|
18
21
|
function countGraphemes(text: string): number {
|
|
22
|
+
if (text.length === 0) return 0;
|
|
23
|
+
const cached = graphemeCountCache.get(text);
|
|
24
|
+
if (cached !== undefined) return cached;
|
|
19
25
|
let count = 0;
|
|
20
26
|
for (const _segment of getSegmenter().segment(text)) {
|
|
21
27
|
count += 1;
|
|
22
28
|
}
|
|
29
|
+
graphemeCountCache.set(text, count);
|
|
23
30
|
return count;
|
|
24
31
|
}
|
|
25
32
|
|
|
@@ -49,8 +49,9 @@ import {
|
|
|
49
49
|
} from "@oh-my-pi/pi-utils";
|
|
50
50
|
import chalk from "chalk";
|
|
51
51
|
import { reset as resetCapabilities } from "../capability";
|
|
52
|
+
import type { CollabGuestLink } from "../collab/guest";
|
|
53
|
+
import type { CollabHost } from "../collab/host";
|
|
52
54
|
import { KeybindingsManager } from "../config/keybindings";
|
|
53
|
-
import { MODEL_ROLES, type ModelRole } from "../config/model-roles";
|
|
54
55
|
import { isSettingsInitialized, onStatusLineSessionAccentChanged, Settings, settings } from "../config/settings";
|
|
55
56
|
import { clearClaudePluginRootsCache } from "../discovery/helpers";
|
|
56
57
|
import type {
|
|
@@ -62,7 +63,7 @@ import type {
|
|
|
62
63
|
ExtensionWidgetOptions,
|
|
63
64
|
} from "../extensibility/extensions";
|
|
64
65
|
import type { CompactOptions } from "../extensibility/extensions/types";
|
|
65
|
-
import {
|
|
66
|
+
import { loadSlashCommands } from "../extensibility/slash-commands";
|
|
66
67
|
import type { Goal, GoalModeState } from "../goals/state";
|
|
67
68
|
import { resolveLocalUrlToPath } from "../internal-urls";
|
|
68
69
|
import { LSP_STARTUP_EVENT_CHANNEL, type LspStartupEvent } from "../lsp/startup-events";
|
|
@@ -82,7 +83,7 @@ import { HistoryStorage } from "../session/history-storage";
|
|
|
82
83
|
import type { SessionContext, SessionManager } from "../session/session-manager";
|
|
83
84
|
import { getRecentSessions } from "../session/session-manager";
|
|
84
85
|
import type { ShakeMode } from "../session/shake-types";
|
|
85
|
-
import { BUILTIN_SLASH_COMMAND_RESERVED_NAMES } from "../slash-commands/builtin-registry";
|
|
86
|
+
import { BUILTIN_SLASH_COMMAND_RESERVED_NAMES, BUILTIN_SLASH_COMMANDS } from "../slash-commands/builtin-registry";
|
|
86
87
|
import { formatDuration } from "../slash-commands/helpers/format";
|
|
87
88
|
import { STTController, type SttState } from "../stt";
|
|
88
89
|
import { discoverTitleSystemPromptFile, resolvePromptInput } from "../system-prompt";
|
|
@@ -397,6 +398,8 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
397
398
|
fileSlashCommands: Set<string> = new Set();
|
|
398
399
|
skillCommands: Map<string, string> = new Map();
|
|
399
400
|
oauthManualInput: OAuthManualInputManager = new OAuthManualInputManager();
|
|
401
|
+
collabHost?: CollabHost;
|
|
402
|
+
collabGuest?: CollabGuestLink;
|
|
400
403
|
|
|
401
404
|
#pendingSlashCommands: SlashCommand[] = [];
|
|
402
405
|
#cleanupUnsubscribe?: () => void;
|
|
@@ -423,6 +426,12 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
423
426
|
readonly #commandController: CommandController;
|
|
424
427
|
readonly #todoCommandController: TodoCommandController;
|
|
425
428
|
readonly #eventController: EventController;
|
|
429
|
+
get eventController(): EventController {
|
|
430
|
+
return this.#eventController;
|
|
431
|
+
}
|
|
432
|
+
get eventBus(): EventBus | undefined {
|
|
433
|
+
return this.#eventBus;
|
|
434
|
+
}
|
|
426
435
|
readonly #extensionUiController: ExtensionUiController;
|
|
427
436
|
readonly #inputController: InputController;
|
|
428
437
|
readonly #selectorController: SelectorController;
|
|
@@ -2491,7 +2500,6 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
2491
2500
|
index: startTierIndex,
|
|
2492
2501
|
segments: cycle.models.map(entry => ({
|
|
2493
2502
|
label: entry.role,
|
|
2494
|
-
color: MODEL_ROLES[entry.role as ModelRole]?.color,
|
|
2495
2503
|
detail: entry.model.name || entry.model.id,
|
|
2496
2504
|
})),
|
|
2497
2505
|
onChange: index => {
|
package/src/modes/types.ts
CHANGED
|
@@ -2,6 +2,8 @@ import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
|
2
2
|
import type { CompactionOutcome } from "@oh-my-pi/pi-agent-core/compaction";
|
|
3
3
|
import type { AssistantMessage, ImageContent, Message, UsageReport } from "@oh-my-pi/pi-ai";
|
|
4
4
|
import type { Component, Container, EditorTheme, Loader, Spacer, Text, TUI } from "@oh-my-pi/pi-tui";
|
|
5
|
+
import type { CollabGuestLink } from "../collab/guest";
|
|
6
|
+
import type { CollabHost } from "../collab/host";
|
|
5
7
|
import type { KeybindingsManager } from "../config/keybindings";
|
|
6
8
|
import type { Settings } from "../config/settings";
|
|
7
9
|
import type {
|
|
@@ -19,6 +21,7 @@ import type { HistoryStorage } from "../session/history-storage";
|
|
|
19
21
|
import type { SessionContext, SessionManager } from "../session/session-manager";
|
|
20
22
|
import type { ShakeMode } from "../session/shake-types";
|
|
21
23
|
import type { LspStartupServerInfo } from "../tools";
|
|
24
|
+
import type { EventBus } from "../utils/event-bus";
|
|
22
25
|
import type { AssistantMessageComponent } from "./components/assistant-message";
|
|
23
26
|
import type { BashExecutionComponent } from "./components/bash-execution";
|
|
24
27
|
import type { CustomEditor } from "./components/custom-editor";
|
|
@@ -29,6 +32,7 @@ import type { HookSelectorComponent, HookSelectorOptions } from "./components/ho
|
|
|
29
32
|
import type { StatusLineComponent } from "./components/status-line";
|
|
30
33
|
import type { ToolExecutionHandle } from "./components/tool-execution";
|
|
31
34
|
import type { TranscriptContainer } from "./components/transcript-container";
|
|
35
|
+
import type { EventController } from "./controllers/event-controller";
|
|
32
36
|
import type { LoopLimitRuntime } from "./loop-limit";
|
|
33
37
|
import type { OAuthManualInputManager } from "./oauth-manual-input";
|
|
34
38
|
import type { Theme } from "./theme/theme";
|
|
@@ -101,6 +105,10 @@ export interface InteractiveModeContext {
|
|
|
101
105
|
mcpManager?: MCPManager;
|
|
102
106
|
lspServers?: LspStartupServerInfo[];
|
|
103
107
|
titleSystemPrompt?: string;
|
|
108
|
+
collabHost?: CollabHost;
|
|
109
|
+
collabGuest?: CollabGuestLink;
|
|
110
|
+
eventController: EventController;
|
|
111
|
+
eventBus?: EventBus;
|
|
104
112
|
|
|
105
113
|
// State
|
|
106
114
|
isInitialized: boolean;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
2
2
|
import type { AssistantMessage, ImageContent, Message } from "@oh-my-pi/pi-ai";
|
|
3
3
|
import { type Component, Spacer, Text, TruncatedText } from "@oh-my-pi/pi-tui";
|
|
4
|
+
import { COLLAB_PROMPT_MESSAGE_TYPE, type CollabPromptDetails } from "../../collab/protocol";
|
|
4
5
|
import { settings } from "../../config/settings";
|
|
5
6
|
import { getFileSnapshotStore } from "../../edit/file-snapshot-store";
|
|
6
7
|
import { AssistantMessageComponent } from "../../modes/components/assistant-message";
|
|
7
8
|
import { BashExecutionComponent } from "../../modes/components/bash-execution";
|
|
8
9
|
import { BranchSummaryMessageComponent } from "../../modes/components/branch-summary-message";
|
|
10
|
+
import { CollabPromptMessageComponent } from "../../modes/components/collab-prompt-message";
|
|
9
11
|
import { CompactionSummaryMessageComponent } from "../../modes/components/compaction-summary-message";
|
|
10
12
|
import { CustomMessageComponent } from "../../modes/components/custom-message";
|
|
11
13
|
import { DynamicBorder } from "../../modes/components/dynamic-border";
|
|
@@ -185,6 +187,11 @@ export class UiHelpers {
|
|
|
185
187
|
this.ctx.chatContainer.addChild(component);
|
|
186
188
|
break;
|
|
187
189
|
}
|
|
190
|
+
if (message.customType === COLLAB_PROMPT_MESSAGE_TYPE) {
|
|
191
|
+
const component = new CollabPromptMessageComponent(message as CustomMessage<CollabPromptDetails>);
|
|
192
|
+
this.ctx.chatContainer.addChild(component);
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
188
195
|
if (message.customType === SKILL_PROMPT_MESSAGE_TYPE) {
|
|
189
196
|
const component = new SkillMessageComponent(message as CustomMessage<SkillPromptDetails>);
|
|
190
197
|
component.setExpanded(this.ctx.toolOutputExpanded);
|