@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
package/dist/types/cli/args.d.ts
CHANGED
|
@@ -26,6 +26,8 @@ export interface Args {
|
|
|
26
26
|
sessionDir?: string;
|
|
27
27
|
providerSessionId?: string;
|
|
28
28
|
fork?: string;
|
|
29
|
+
/** Collab link to join at startup (set by the `join` subcommand; no CLI flag). */
|
|
30
|
+
join?: string;
|
|
29
31
|
models?: string[];
|
|
30
32
|
tools?: string[];
|
|
31
33
|
noTools?: boolean;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AES-256-GCM sealing for collab frames.
|
|
3
|
+
*
|
|
4
|
+
* The room key lives only in the link fragment; the relay sees opaque bytes.
|
|
5
|
+
* Sealed layout: `[12B IV][ciphertext+tag]`.
|
|
6
|
+
*/
|
|
7
|
+
import type { CollabFrame } from "./protocol";
|
|
8
|
+
export declare function generateRoomKey(): Uint8Array;
|
|
9
|
+
export declare function importRoomKey(raw: Uint8Array): Promise<CryptoKey>;
|
|
10
|
+
export declare function seal(key: CryptoKey, frame: CollabFrame): Promise<Uint8Array>;
|
|
11
|
+
/** Inverse of {@link seal}. Throws on auth failure or malformed input. */
|
|
12
|
+
export declare function open(key: CryptoKey, data: Uint8Array): Promise<CollabFrame>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ImageContent } from "@oh-my-pi/pi-ai";
|
|
2
|
+
import type { AgentHubRemote } from "../modes/components/agent-hub";
|
|
3
|
+
import type { InteractiveModeContext } from "../modes/types";
|
|
4
|
+
import { AgentRegistry } from "../registry/agent-registry";
|
|
5
|
+
import { type CollabSessionState } from "./protocol";
|
|
6
|
+
/** Commands a guest may run locally; everything else is host-only. */
|
|
7
|
+
export declare const COLLAB_GUEST_ALLOWED_COMMANDS: Record<string, true>;
|
|
8
|
+
export declare class CollabGuestLink {
|
|
9
|
+
#private;
|
|
10
|
+
state: CollabSessionState | null;
|
|
11
|
+
/** Local mirror of the host's agent ecosystem (refs carry `session: null`). */
|
|
12
|
+
readonly agentRegistry: AgentRegistry;
|
|
13
|
+
/** Agent Hub actions routed to the host over the wire. */
|
|
14
|
+
get hubRemote(): AgentHubRemote;
|
|
15
|
+
constructor(ctx: InteractiveModeContext);
|
|
16
|
+
join(link: string): Promise<void>;
|
|
17
|
+
/** User-initiated leave (or post-disconnect cleanup): restore the previous session. */
|
|
18
|
+
leave(_reason: string): Promise<void>;
|
|
19
|
+
sendPrompt(text: string, images?: ImageContent[]): void;
|
|
20
|
+
sendAbort(): void;
|
|
21
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { InteractiveModeContext } from "../modes/types";
|
|
2
|
+
import { type CollabParticipant } from "./protocol";
|
|
3
|
+
/** Display name for this process's user in collab sessions. */
|
|
4
|
+
export declare function collabDisplayName(ctx: InteractiveModeContext): string;
|
|
5
|
+
export declare class CollabHost {
|
|
6
|
+
#private;
|
|
7
|
+
constructor(ctx: InteractiveModeContext);
|
|
8
|
+
get link(): string;
|
|
9
|
+
get participants(): CollabParticipant[];
|
|
10
|
+
start(relayUrl: string): Promise<void>;
|
|
11
|
+
/** Broadcast a goodbye, detach all taps, and close the socket. */
|
|
12
|
+
stop(reason: string): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collab live-session wire protocol.
|
|
3
|
+
*
|
|
4
|
+
* Hub topology: the host is authoritative, guests never peer. All session
|
|
5
|
+
* payloads (`CollabFrame`) travel AES-256-GCM sealed; the relay only sees the
|
|
6
|
+
* plaintext envelope (`[4B uint32 BE peerId][sealed payload]`) plus TEXT JSON
|
|
7
|
+
* control messages that carry no session data.
|
|
8
|
+
*/
|
|
9
|
+
import type { ImageContent, Model } from "@oh-my-pi/pi-ai";
|
|
10
|
+
import type { BusChannel, GuestFrame, ParsedCollabLink, Participant, SessionState, AgentSnapshot as WireAgentSnapshot } from "@oh-my-pi/pi-wire";
|
|
11
|
+
import { DEFAULT_RELAY_URL, ENVELOPE_HEADER_LENGTH, ROOM_ID_BYTES } from "@oh-my-pi/pi-wire";
|
|
12
|
+
import type { ContextUsage } from "../extensibility/extensions/types";
|
|
13
|
+
import type { AgentSessionEvent } from "../session/agent-session";
|
|
14
|
+
import type { SessionEntry, SessionHeader } from "../session/session-manager";
|
|
15
|
+
export type { CollabPromptDetails, ParsedCollabLink, RelayControlMessage, RelayControlToGuest, RelayControlToHost, } from "@oh-my-pi/pi-wire";
|
|
16
|
+
export { COLLAB_PROMPT_MESSAGE_TYPE, COLLAB_PROTO } from "@oh-my-pi/pi-wire";
|
|
17
|
+
export { DEFAULT_RELAY_URL, ENVELOPE_HEADER_LENGTH, ROOM_ID_BYTES };
|
|
18
|
+
export type CollabParticipant = Participant;
|
|
19
|
+
export type AgentSnapshot = WireAgentSnapshot;
|
|
20
|
+
/** Debounced footer snapshot broadcast by the host. */
|
|
21
|
+
export type CollabSessionState = SessionState & {
|
|
22
|
+
/**
|
|
23
|
+
* Host model (full catalog object). Guests apply it to their replica
|
|
24
|
+
* agent state so model display and context-window math are native.
|
|
25
|
+
*/
|
|
26
|
+
model?: Model;
|
|
27
|
+
/** Host status-line context numbers (guest system prompt/tools differ, so local estimates drift). */
|
|
28
|
+
contextUsage?: ContextUsage;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Encrypted payload frames (inside AES-GCM, JSON). The wire package pins the
|
|
32
|
+
* JSON skeleton (`WireFrame`); host-side frames carry the rich session types
|
|
33
|
+
* that serialize into those shapes.
|
|
34
|
+
*/
|
|
35
|
+
export type CollabFrame = Exclude<GuestFrame, {
|
|
36
|
+
t: "prompt";
|
|
37
|
+
}> | {
|
|
38
|
+
t: "prompt";
|
|
39
|
+
text: string;
|
|
40
|
+
images?: ImageContent[];
|
|
41
|
+
} | {
|
|
42
|
+
t: "welcome";
|
|
43
|
+
proto: number;
|
|
44
|
+
header: SessionHeader;
|
|
45
|
+
entries: SessionEntry[];
|
|
46
|
+
state: CollabSessionState;
|
|
47
|
+
agents: AgentSnapshot[];
|
|
48
|
+
} | {
|
|
49
|
+
t: "entry";
|
|
50
|
+
entry: SessionEntry;
|
|
51
|
+
} | {
|
|
52
|
+
t: "event";
|
|
53
|
+
event: AgentSessionEvent;
|
|
54
|
+
} | {
|
|
55
|
+
t: "state";
|
|
56
|
+
state: CollabSessionState;
|
|
57
|
+
}
|
|
58
|
+
/** Mirrored EventBus traffic (task subagent lifecycle/progress channels only). */
|
|
59
|
+
| {
|
|
60
|
+
t: "bus";
|
|
61
|
+
channel: BusChannel;
|
|
62
|
+
data: unknown;
|
|
63
|
+
}
|
|
64
|
+
/** Full agent-registry snapshot (debounced on registry change). */
|
|
65
|
+
| {
|
|
66
|
+
t: "agents";
|
|
67
|
+
agents: AgentSnapshot[];
|
|
68
|
+
}
|
|
69
|
+
/** Targeted reply to fetch-transcript; `text` is decoded JSONL from `fromByte`, `newSize` the next offset base. */
|
|
70
|
+
| {
|
|
71
|
+
t: "transcript";
|
|
72
|
+
reqId: number;
|
|
73
|
+
text: string;
|
|
74
|
+
newSize: number;
|
|
75
|
+
error?: string;
|
|
76
|
+
} | {
|
|
77
|
+
t: "bye";
|
|
78
|
+
reason: string;
|
|
79
|
+
} | {
|
|
80
|
+
t: "error";
|
|
81
|
+
message: string;
|
|
82
|
+
};
|
|
83
|
+
export declare function packEnvelope(peerId: number, sealed: Uint8Array): Uint8Array;
|
|
84
|
+
export declare function unpackEnvelope(data: Uint8Array): {
|
|
85
|
+
peerId: number;
|
|
86
|
+
payload: Uint8Array;
|
|
87
|
+
} | null;
|
|
88
|
+
/** Rewrite the peerId in place without copying the payload. */
|
|
89
|
+
export declare function rewriteEnvelopePeer(data: Uint8Array, peerId: number): void;
|
|
90
|
+
export declare function generateRoomId(): string;
|
|
91
|
+
/**
|
|
92
|
+
* Render the shareable link. Compact forms: the default relay collapses to
|
|
93
|
+
* `<roomId>#<key>`, other wss relays drop the scheme (`host[:port]/r/…`);
|
|
94
|
+
* only localhost ws:// links keep their full URL so parsing cannot
|
|
95
|
+
* mis-infer wss.
|
|
96
|
+
*/
|
|
97
|
+
export declare function formatCollabLink(relayUrl: string, roomId: string, key: Uint8Array): string;
|
|
98
|
+
export declare function parseCollabLink(link: string): ParsedCollabLink | {
|
|
99
|
+
error: string;
|
|
100
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { CollabFrame, RelayControlMessage } from "./protocol";
|
|
2
|
+
export interface CollabSocketOptions {
|
|
3
|
+
/** wss://host[:port]/r/<roomId> — no query string. */
|
|
4
|
+
wsUrl: string;
|
|
5
|
+
role: "host" | "guest";
|
|
6
|
+
key: CryptoKey;
|
|
7
|
+
}
|
|
8
|
+
export declare class CollabSocket {
|
|
9
|
+
#private;
|
|
10
|
+
/** Fires after every successful (re)connect. */
|
|
11
|
+
onOpen?: () => void;
|
|
12
|
+
onFrame?: (frame: CollabFrame, fromPeer: number) => void;
|
|
13
|
+
onControl?: (msg: RelayControlMessage) => void;
|
|
14
|
+
/** Fires once per terminal close (intentional, fatal code, or bad key). willReconnect=true for transient drops that will retry. */
|
|
15
|
+
onClose?: (reason: string, willReconnect: boolean) => void;
|
|
16
|
+
constructor(opts: CollabSocketOptions);
|
|
17
|
+
get isOpen(): boolean;
|
|
18
|
+
connect(): void;
|
|
19
|
+
send(frame: CollabFrame, targetPeer?: number): void;
|
|
20
|
+
/** Intentional close: clears any retry timer, suppresses reconnect. A later connect() starts fresh. */
|
|
21
|
+
close(): void;
|
|
22
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Command } from "@oh-my-pi/pi-utils/cli";
|
|
2
|
+
export default class Join extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static args: {
|
|
5
|
+
link: import("@oh-my-pi/pi-utils/cli").ArgDescriptor & {
|
|
6
|
+
description: string;
|
|
7
|
+
required: true;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
static examples: string[];
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -33,7 +33,7 @@ export declare const TAB_METADATA: Record<SettingTab, {
|
|
|
33
33
|
*/
|
|
34
34
|
export declare const TAB_GROUPS: Record<SettingTab, readonly string[]>;
|
|
35
35
|
/** Status line segment identifiers */
|
|
36
|
-
export type StatusLineSegmentId = "pi" | "model" | "mode" | "path" | "git" | "pr" | "subagents" | "token_in" | "token_out" | "token_total" | "token_rate" | "cost" | "context_pct" | "context_total" | "time_spent" | "time" | "session" | "hostname" | "cache_read" | "cache_write" | "cache_hit" | "session_name" | "usage";
|
|
36
|
+
export type StatusLineSegmentId = "pi" | "model" | "mode" | "path" | "git" | "pr" | "subagents" | "token_in" | "token_out" | "token_total" | "token_rate" | "cost" | "context_pct" | "context_total" | "time_spent" | "time" | "session" | "hostname" | "cache_read" | "cache_write" | "cache_hit" | "session_name" | "usage" | "collab";
|
|
37
37
|
/** Submenu choice metadata. */
|
|
38
38
|
export type SubmenuOption<V extends string = string> = {
|
|
39
39
|
value: V;
|
|
@@ -1394,6 +1394,26 @@ export declare const SETTINGS_SCHEMA: {
|
|
|
1394
1394
|
readonly description: "Notify when the ask tool is waiting for input";
|
|
1395
1395
|
};
|
|
1396
1396
|
};
|
|
1397
|
+
readonly "collab.relayUrl": {
|
|
1398
|
+
readonly type: "string";
|
|
1399
|
+
readonly default: "wss://relay.omp.sh";
|
|
1400
|
+
readonly ui: {
|
|
1401
|
+
readonly tab: "interaction";
|
|
1402
|
+
readonly group: "Collab";
|
|
1403
|
+
readonly label: "Relay URL";
|
|
1404
|
+
readonly description: "Relay used by /collab (wss://host[:port]; self-host with the omp-collab-relay service)";
|
|
1405
|
+
};
|
|
1406
|
+
};
|
|
1407
|
+
readonly "collab.displayName": {
|
|
1408
|
+
readonly type: "string";
|
|
1409
|
+
readonly default: "";
|
|
1410
|
+
readonly ui: {
|
|
1411
|
+
readonly tab: "interaction";
|
|
1412
|
+
readonly group: "Collab";
|
|
1413
|
+
readonly label: "Display Name";
|
|
1414
|
+
readonly description: "Name shown to other collab participants (default: OS username)";
|
|
1415
|
+
};
|
|
1416
|
+
};
|
|
1397
1417
|
readonly "stt.enabled": {
|
|
1398
1418
|
readonly type: "boolean";
|
|
1399
1419
|
readonly default: false;
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type { AutocompleteItem } from "@oh-my-pi/pi-tui";
|
|
2
|
-
import { type BuiltinSlashCommand } from "../slash-commands/builtin-registry";
|
|
3
1
|
export type SlashCommandSource = "extension" | "prompt" | "skill";
|
|
4
2
|
export type SlashCommandLocation = "user" | "project" | "path";
|
|
5
3
|
export interface SlashCommandInfo {
|
|
@@ -9,15 +7,7 @@ export interface SlashCommandInfo {
|
|
|
9
7
|
location?: SlashCommandLocation;
|
|
10
8
|
path?: string;
|
|
11
9
|
}
|
|
12
|
-
export type { BuiltinSlashCommand, SubcommandDef } from "../slash-commands/
|
|
13
|
-
/**
|
|
14
|
-
* Materialized builtin slash commands with completion functions derived from
|
|
15
|
-
* declarative subcommand/hint definitions.
|
|
16
|
-
*/
|
|
17
|
-
export declare const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand & {
|
|
18
|
-
getArgumentCompletions?: (prefix: string) => AutocompleteItem[] | null;
|
|
19
|
-
getInlineHint?: (argumentText: string) => string | null;
|
|
20
|
-
}>;
|
|
10
|
+
export type { BuiltinSlashCommand, SubcommandDef } from "../slash-commands/types";
|
|
21
11
|
/**
|
|
22
12
|
* Represents a custom slash command loaded from a file
|
|
23
13
|
*/
|
|
@@ -4,6 +4,17 @@ import { IrcBus } from "../../irc/bus";
|
|
|
4
4
|
import { AgentLifecycleManager } from "../../registry/agent-lifecycle";
|
|
5
5
|
import { AgentRegistry } from "../../registry/agent-registry";
|
|
6
6
|
import type { SessionObserverRegistry } from "../session-observer-registry";
|
|
7
|
+
/** Guest-side proxy for hub actions executed on the collab host. */
|
|
8
|
+
export interface AgentHubRemote {
|
|
9
|
+
chat(id: string, text: string): void;
|
|
10
|
+
kill(id: string): void;
|
|
11
|
+
revive(id: string): void;
|
|
12
|
+
/** Mirrors readFileIncremental: text from fromByte (complete JSONL lines), newSize = next fromByte base; null = unavailable. */
|
|
13
|
+
readTranscript(id: string, fromByte: number): Promise<{
|
|
14
|
+
text: string;
|
|
15
|
+
newSize: number;
|
|
16
|
+
} | null>;
|
|
17
|
+
}
|
|
7
18
|
export interface AgentHubDeps {
|
|
8
19
|
/** Progress/status snapshot source (task lifecycle + progress channels). */
|
|
9
20
|
observers: SessionObserverRegistry;
|
|
@@ -17,6 +28,8 @@ export interface AgentHubDeps {
|
|
|
17
28
|
lifecycle?: AgentLifecycleManager;
|
|
18
29
|
/** Injectable for tests; defaults to the process-global bus. */
|
|
19
30
|
irc?: IrcBus;
|
|
31
|
+
/** Collab guest: route actions/transcripts to the host instead of local sessions. */
|
|
32
|
+
remote?: AgentHubRemote;
|
|
20
33
|
}
|
|
21
34
|
export declare class AgentHubOverlayComponent extends Container {
|
|
22
35
|
#private;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Container } from "@oh-my-pi/pi-tui";
|
|
2
|
+
import type { CollabPromptDetails } from "../../collab/protocol";
|
|
3
|
+
import type { CustomMessage } from "../../session/messages";
|
|
4
|
+
/**
|
|
5
|
+
* Renders a collab guest prompt on every participant's transcript: a
|
|
6
|
+
* user-message-styled bubble prefixed with the author's name.
|
|
7
|
+
*/
|
|
8
|
+
export declare class CollabPromptMessageComponent extends Container {
|
|
9
|
+
constructor(message: CustomMessage<CollabPromptDetails>);
|
|
10
|
+
}
|
|
@@ -3,14 +3,12 @@
|
|
|
3
3
|
* Displays a list of string options with keyboard navigation.
|
|
4
4
|
*/
|
|
5
5
|
import { Container, type TUI } from "@oh-my-pi/pi-tui";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
/** One segment of a {@link HookSelectorSlider} — a label and an optional
|
|
7
|
+
* detail line (e.g. the resolved model name) shown beneath the track while
|
|
8
|
+
* the segment is active. Segment colors come from the track's theme palette,
|
|
9
|
+
* assigned by position. */
|
|
10
10
|
export interface HookSelectorSliderSegment {
|
|
11
11
|
label: string;
|
|
12
|
-
/** Theme color for the segment label; defaults to `accent`. */
|
|
13
|
-
color?: ThemeColor;
|
|
14
12
|
/** Secondary line rendered under the track when this segment is selected. */
|
|
15
13
|
detail?: string;
|
|
16
14
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared renderer for a horizontal row of colored "segments" styled after the
|
|
3
|
-
* status line: each segment
|
|
4
|
-
* as a powerline chip (its
|
|
5
|
-
* flanked by triangle caps) and the
|
|
6
|
-
* thin separator.
|
|
3
|
+
* status line: each segment is colored by its track position from the theme's
|
|
4
|
+
* own palette, the active one is filled as a powerline chip (its color as the
|
|
5
|
+
* background, a luminance-matched label, flanked by triangle caps) and the
|
|
6
|
+
* rest are plain colored labels joined by a thin separator.
|
|
7
7
|
*
|
|
8
8
|
* Used by the plan-mode model-tier slider ({@link HookSelectorComponent}) and
|
|
9
9
|
* the ctrl+p role-cycle status so both surfaces read identically.
|
|
@@ -11,9 +11,14 @@
|
|
|
11
11
|
import { type ThemeColor } from "../theme/theme";
|
|
12
12
|
export interface TrackSegment {
|
|
13
13
|
label: string;
|
|
14
|
-
/** Theme color for the segment; defaults to `accent`. */
|
|
15
|
-
color?: ThemeColor;
|
|
16
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Resolve up to `count` theme colors that render distinctly under the active
|
|
17
|
+
* theme, in candidate preference order. May return fewer than `count` when the
|
|
18
|
+
* theme has fewer distinct hues (e.g. monochrome themes) — callers wrap with
|
|
19
|
+
* modulo. Never returns an empty array: `accent` always resolves.
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveSegmentPalette(count: number): ThemeColor[];
|
|
17
22
|
/**
|
|
18
23
|
* Render `segments` as a colored chip track with `activeIndex` filled. Returns
|
|
19
24
|
* a single line of styled text with no surrounding caption or arrows — callers
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Component } from "@oh-my-pi/pi-tui";
|
|
2
2
|
import type { AgentSession } from "../../../session/agent-session";
|
|
3
|
-
import type { EffectiveStatusLineSettings, StatusLineSettings } from "./types";
|
|
3
|
+
import type { CollabStatus, EffectiveStatusLineSettings, StatusLineSettings } from "./types";
|
|
4
4
|
export declare class StatusLineComponent implements Component {
|
|
5
5
|
#private;
|
|
6
6
|
private readonly session;
|
|
@@ -9,6 +9,8 @@ export declare class StatusLineComponent implements Component {
|
|
|
9
9
|
getEffectiveSettingsForTest(): EffectiveStatusLineSettings;
|
|
10
10
|
setAutoCompactEnabled(enabled: boolean): void;
|
|
11
11
|
setSubagentCount(count: number): void;
|
|
12
|
+
/** Active subagent count as currently displayed (collab state mirroring). */
|
|
13
|
+
get subagentCount(): number;
|
|
12
14
|
setSessionStartTime(time: number): void;
|
|
13
15
|
setPlanModeStatus(status: {
|
|
14
16
|
enabled: boolean;
|
|
@@ -21,6 +23,7 @@ export declare class StatusLineComponent implements Component {
|
|
|
21
23
|
enabled: boolean;
|
|
22
24
|
paused: boolean;
|
|
23
25
|
} | undefined): void;
|
|
26
|
+
setCollabStatus(status: CollabStatus | null): void;
|
|
24
27
|
setHookStatus(key: string, text: string | undefined): void;
|
|
25
28
|
watchBranch(onBranchChange: () => void): void;
|
|
26
29
|
dispose(): void;
|
|
@@ -1,6 +1,14 @@
|
|
|
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
|
export type { StatusLinePreset, StatusLineSegmentId, StatusLineSeparatorStyle };
|
|
5
|
+
/** Collab session indicator + (guest-only) host-state override for segments. */
|
|
6
|
+
export interface CollabStatus {
|
|
7
|
+
role: "host" | "guest";
|
|
8
|
+
participantCount: number;
|
|
9
|
+
/** Guest only: host footer snapshot that overrides locally computed values. */
|
|
10
|
+
stateOverride?: CollabSessionState | null;
|
|
11
|
+
}
|
|
4
12
|
export interface StatusLineSegmentOptions {
|
|
5
13
|
model?: {
|
|
6
14
|
showThinkingLevel?: boolean;
|
|
@@ -50,6 +58,7 @@ export interface SegmentContext {
|
|
|
50
58
|
enabled: boolean;
|
|
51
59
|
paused: boolean;
|
|
52
60
|
} | null;
|
|
61
|
+
collab: CollabStatus | null;
|
|
53
62
|
usageStats: {
|
|
54
63
|
input: number;
|
|
55
64
|
output: number;
|
|
@@ -3,6 +3,8 @@ 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, EditorTheme } from "@oh-my-pi/pi-tui";
|
|
5
5
|
import { Container, Loader, Spacer, Text, TUI } from "@oh-my-pi/pi-tui";
|
|
6
|
+
import type { CollabGuestLink } from "../collab/guest";
|
|
7
|
+
import type { CollabHost } from "../collab/host";
|
|
6
8
|
import { KeybindingsManager } from "../config/keybindings";
|
|
7
9
|
import { Settings } from "../config/settings";
|
|
8
10
|
import type { ExtensionUIContext, ExtensionUIDialogOptions, ExtensionUISelectItem, ExtensionWidgetContent, ExtensionWidgetOptions } from "../extensibility/extensions";
|
|
@@ -25,6 +27,7 @@ import type { HookSelectorComponent, HookSelectorSlider } from "./components/hoo
|
|
|
25
27
|
import { StatusLineComponent } from "./components/status-line";
|
|
26
28
|
import type { ToolExecutionHandle } from "./components/tool-execution";
|
|
27
29
|
import { TranscriptContainer } from "./components/transcript-container";
|
|
30
|
+
import { EventController } from "./controllers/event-controller";
|
|
28
31
|
import { type LoopLimitRuntime } from "./loop-limit";
|
|
29
32
|
import { OAuthManualInputManager } from "./oauth-manual-input";
|
|
30
33
|
import type { ObservableSession } from "./session-observer-registry";
|
|
@@ -119,8 +122,12 @@ export declare class InteractiveMode implements InteractiveModeContext {
|
|
|
119
122
|
fileSlashCommands: Set<string>;
|
|
120
123
|
skillCommands: Map<string, string>;
|
|
121
124
|
oauthManualInput: OAuthManualInputManager;
|
|
125
|
+
collabHost?: CollabHost;
|
|
126
|
+
collabGuest?: CollabGuestLink;
|
|
122
127
|
readonly lspServers: LspStartupServerInfo[] | undefined;
|
|
123
128
|
mcpManager?: MCPManager;
|
|
129
|
+
get eventController(): EventController;
|
|
130
|
+
get eventBus(): EventBus | undefined;
|
|
124
131
|
constructor(session: AgentSession, version: string, changelogMarkdown?: string | undefined, setToolUIContext?: (uiContext: ExtensionUIContext, hasUI: boolean) => void, lspServers?: LspStartupServerInfo[] | undefined, mcpManager?: MCPManager, eventBus?: EventBus, titleSystemPrompt?: string);
|
|
125
132
|
playWelcomeIntro(): void;
|
|
126
133
|
init(options?: InteractiveModeInitOptions): Promise<void>;
|
|
@@ -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 { ExtensionUIContext, ExtensionUIDialogOptions, ExtensionUISelectItem, ExtensionWidgetContent, ExtensionWidgetOptions } from "../extensibility/extensions";
|
|
@@ -13,6 +15,7 @@ import type { HistoryStorage } from "../session/history-storage";
|
|
|
13
15
|
import type { SessionContext, SessionManager } from "../session/session-manager";
|
|
14
16
|
import type { ShakeMode } from "../session/shake-types";
|
|
15
17
|
import type { LspStartupServerInfo } from "../tools";
|
|
18
|
+
import type { EventBus } from "../utils/event-bus";
|
|
16
19
|
import type { AssistantMessageComponent } from "./components/assistant-message";
|
|
17
20
|
import type { BashExecutionComponent } from "./components/bash-execution";
|
|
18
21
|
import type { CustomEditor } from "./components/custom-editor";
|
|
@@ -23,6 +26,7 @@ import type { HookSelectorComponent, HookSelectorOptions } from "./components/ho
|
|
|
23
26
|
import type { StatusLineComponent } from "./components/status-line";
|
|
24
27
|
import type { ToolExecutionHandle } from "./components/tool-execution";
|
|
25
28
|
import type { TranscriptContainer } from "./components/transcript-container";
|
|
29
|
+
import type { EventController } from "./controllers/event-controller";
|
|
26
30
|
import type { LoopLimitRuntime } from "./loop-limit";
|
|
27
31
|
import type { OAuthManualInputManager } from "./oauth-manual-input";
|
|
28
32
|
import type { Theme } from "./theme/theme";
|
|
@@ -84,6 +88,10 @@ export interface InteractiveModeContext {
|
|
|
84
88
|
mcpManager?: MCPManager;
|
|
85
89
|
lspServers?: LspStartupServerInfo[];
|
|
86
90
|
titleSystemPrompt?: string;
|
|
91
|
+
collabHost?: CollabHost;
|
|
92
|
+
collabGuest?: CollabGuestLink;
|
|
93
|
+
eventController: EventController;
|
|
94
|
+
eventBus?: EventBus;
|
|
87
95
|
isInitialized: boolean;
|
|
88
96
|
isBashMode: boolean;
|
|
89
97
|
toolOutputExpanded: boolean;
|
|
@@ -385,6 +385,9 @@ export declare class AgentSession {
|
|
|
385
385
|
*/
|
|
386
386
|
subscribe(listener: AgentSessionEventListener): () => void;
|
|
387
387
|
subscribeCommandMetadataChanged(listener: CommandMetadataChangedListener): () => void;
|
|
388
|
+
/** True once dispose() has begun; deferred background work (e.g. the deferred
|
|
389
|
+
* MCP discovery task in sdk.ts) must not touch the session past this point. */
|
|
390
|
+
get isDisposed(): boolean;
|
|
388
391
|
/**
|
|
389
392
|
* Synchronously mark the session as disposing so new work is rejected
|
|
390
393
|
* immediately: Python/eval starts throw, queued asides are dropped, and the
|
|
@@ -443,6 +446,14 @@ export declare class AgentSession {
|
|
|
443
446
|
*/
|
|
444
447
|
getAllToolNames(): string[];
|
|
445
448
|
isMCPDiscoveryEnabled(): boolean;
|
|
449
|
+
/**
|
|
450
|
+
* Flip MCP discovery on after deferred discovery learns the real tool count.
|
|
451
|
+
* UI sessions resolve `tools.discoveryMode: "auto"` before MCP servers
|
|
452
|
+
* connect, so a large MCP toolset discovered later must be able to upgrade
|
|
453
|
+
* the session from the force-activate path to the discovery path. One-way:
|
|
454
|
+
* discovery is never downgraded mid-session.
|
|
455
|
+
*/
|
|
456
|
+
enableMCPDiscovery(): void;
|
|
446
457
|
getSelectedMCPToolNames(): string[];
|
|
447
458
|
activateDiscoveredMCPTools(toolNames: string[]): Promise<string[]>;
|
|
448
459
|
isToolDiscoveryEnabled(): boolean;
|
|
@@ -309,6 +309,12 @@ export declare class SessionManager {
|
|
|
309
309
|
private sessionDir;
|
|
310
310
|
private readonly persist;
|
|
311
311
|
private readonly storage;
|
|
312
|
+
/**
|
|
313
|
+
* Collab replication tap: invoked for every appended entry with the
|
|
314
|
+
* in-memory (pre-blob-externalization) entry, so inline images survive.
|
|
315
|
+
* Failures are swallowed — a broadcast error must never break persistence.
|
|
316
|
+
*/
|
|
317
|
+
onEntryAppended?: (entry: SessionEntry) => void;
|
|
312
318
|
private constructor();
|
|
313
319
|
/** Puts a binary blob into the blob store and returns the blob reference */
|
|
314
320
|
putBlob(data: Buffer, options?: BlobPutOptions): Promise<BlobPutResult>;
|
|
@@ -434,6 +440,21 @@ export declare class SessionManager {
|
|
|
434
440
|
*/
|
|
435
441
|
setSessionName(name: string, source?: "auto" | "user"): Promise<boolean>;
|
|
436
442
|
_persist(entry: SessionEntry): void;
|
|
443
|
+
/**
|
|
444
|
+
* Append a foreign (host-authored) entry verbatim, preserving its
|
|
445
|
+
* `id`/`parentId` — no id minting. Used by collab guests to mirror the
|
|
446
|
+
* host session into the local replica file.
|
|
447
|
+
*/
|
|
448
|
+
ingestReplicatedEntry(entry: SessionEntry): void;
|
|
449
|
+
/**
|
|
450
|
+
* Snapshot the session for collab replication: the live header plus a deep
|
|
451
|
+
* copy of every entry (the host mutates entries in place on
|
|
452
|
+
* truncation/rewrite paths, so guests must not share references).
|
|
453
|
+
*/
|
|
454
|
+
snapshotForReplication(): {
|
|
455
|
+
header: SessionHeader;
|
|
456
|
+
entries: SessionEntry[];
|
|
457
|
+
};
|
|
437
458
|
/** Append a message as child of current leaf, then advance leaf. Returns entry id.
|
|
438
459
|
* Does not allow writing CompactionSummaryMessage and BranchSummaryMessage directly.
|
|
439
460
|
* Reason: we want these to be top-level entries in the session, not message session entries,
|
|
@@ -24,14 +24,16 @@ export interface SnapcompactInlineOptions {
|
|
|
24
24
|
}
|
|
25
25
|
/** Tool-result swap candidate, in context order. */
|
|
26
26
|
export interface InlineToolResultCandidate {
|
|
27
|
-
/**
|
|
27
|
+
/** Stable identifier for rendering cache key and applying the swap. */
|
|
28
28
|
id: string;
|
|
29
|
-
/** Token count of the joined text blocks (0
|
|
29
|
+
/** Token count of the joined text blocks (0 for empty or image-carrying). */
|
|
30
30
|
textTokens: number;
|
|
31
|
-
/** Frames needed to render the text (0 = empty
|
|
31
|
+
/** Frames needed to render the text (0 = empty, below floor, image-carrying, or error). */
|
|
32
32
|
frames: number;
|
|
33
33
|
/** Already carries an image (screenshot etc.) — never re-imaged. */
|
|
34
34
|
hasImage: boolean;
|
|
35
|
+
/** Error tool results must stay text-only for provider API validation. */
|
|
36
|
+
isError?: boolean;
|
|
35
37
|
}
|
|
36
38
|
export interface InlineSystemPromptCandidate {
|
|
37
39
|
textTokens: number;
|
|
@@ -73,6 +75,7 @@ export interface InlineMessageView {
|
|
|
73
75
|
role: string;
|
|
74
76
|
toolCallId?: string;
|
|
75
77
|
content?: unknown;
|
|
78
|
+
isError?: boolean;
|
|
76
79
|
}
|
|
77
80
|
export interface SnapcompactSavingsEstimate {
|
|
78
81
|
/** Frames only ship on models that accept image input. */
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AutocompleteItem } from "@oh-my-pi/pi-tui";
|
|
1
2
|
import type { BuiltinSlashCommand, ParsedSlashCommand, SlashCommandResult, SlashCommandRuntime, SlashCommandSpec, TuiSlashCommandRuntime } from "./types";
|
|
2
3
|
export type { BuiltinSlashCommand, SubcommandDef } from "./types";
|
|
3
4
|
/** TUI-specific runtime accepted by `executeBuiltinSlashCommand`. */
|
|
@@ -5,6 +6,14 @@ export type BuiltinSlashCommandRuntime = TuiSlashCommandRuntime;
|
|
|
5
6
|
export declare const BUILTIN_SLASH_COMMAND_RESERVED_NAMES: ReadonlySet<string>;
|
|
6
7
|
/** Builtin command metadata used for slash-command autocomplete and help text. */
|
|
7
8
|
export declare const BUILTIN_SLASH_COMMAND_DEFS: ReadonlyArray<BuiltinSlashCommand>;
|
|
9
|
+
/**
|
|
10
|
+
* Materialized builtin slash commands with completion functions derived from
|
|
11
|
+
* declarative subcommand/hint definitions.
|
|
12
|
+
*/
|
|
13
|
+
export declare const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand & {
|
|
14
|
+
getArgumentCompletions?: (prefix: string) => AutocompleteItem[] | null;
|
|
15
|
+
getInlineHint?: (argumentText: string) => string | null;
|
|
16
|
+
}>;
|
|
8
17
|
/**
|
|
9
18
|
* Unified registry exposed for cross-mode tooling. Each spec carries at least
|
|
10
19
|
* one of `handle` / `handleTui`. The TUI dispatcher prefers `handleTui`; the
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-coding-agent",
|
|
4
|
-
"version": "15.11.
|
|
4
|
+
"version": "15.11.8",
|
|
5
5
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -41,22 +41,24 @@
|
|
|
41
41
|
"format-prompts": "bun scripts/format-prompts.ts",
|
|
42
42
|
"generate-docs-index": "bun scripts/generate-docs-index.ts",
|
|
43
43
|
"prepack": "bun scripts/generate-docs-index.ts && bun scripts/bundle-dist.ts",
|
|
44
|
-
"generate-template": "bun scripts/generate-template.ts"
|
|
44
|
+
"generate-template": "bun scripts/generate-template.ts",
|
|
45
|
+
"bench:guard": "bun scripts/bench-guard.ts"
|
|
45
46
|
},
|
|
46
47
|
"dependencies": {
|
|
47
48
|
"@agentclientprotocol/sdk": "0.22.1",
|
|
48
49
|
"@babel/parser": "^7.29.7",
|
|
49
50
|
"@mozilla/readability": "^0.6.0",
|
|
50
|
-
"@oh-my-pi/hashline": "15.11.
|
|
51
|
-
"@oh-my-pi/omp-stats": "15.11.
|
|
52
|
-
"@oh-my-pi/pi-agent-core": "15.11.
|
|
53
|
-
"@oh-my-pi/pi-ai": "15.11.
|
|
54
|
-
"@oh-my-pi/pi-catalog": "15.11.
|
|
55
|
-
"@oh-my-pi/pi-mnemopi": "15.11.
|
|
56
|
-
"@oh-my-pi/pi-natives": "15.11.
|
|
57
|
-
"@oh-my-pi/pi-tui": "15.11.
|
|
58
|
-
"@oh-my-pi/pi-utils": "15.11.
|
|
59
|
-
"@oh-my-pi/
|
|
51
|
+
"@oh-my-pi/hashline": "15.11.8",
|
|
52
|
+
"@oh-my-pi/omp-stats": "15.11.8",
|
|
53
|
+
"@oh-my-pi/pi-agent-core": "15.11.8",
|
|
54
|
+
"@oh-my-pi/pi-ai": "15.11.8",
|
|
55
|
+
"@oh-my-pi/pi-catalog": "15.11.8",
|
|
56
|
+
"@oh-my-pi/pi-mnemopi": "15.11.8",
|
|
57
|
+
"@oh-my-pi/pi-natives": "15.11.8",
|
|
58
|
+
"@oh-my-pi/pi-tui": "15.11.8",
|
|
59
|
+
"@oh-my-pi/pi-utils": "15.11.8",
|
|
60
|
+
"@oh-my-pi/pi-wire": "15.11.8",
|
|
61
|
+
"@oh-my-pi/snapcompact": "15.11.8",
|
|
60
62
|
"@opentelemetry/api": "^1.9.1",
|
|
61
63
|
"@opentelemetry/context-async-hooks": "^2.7.1",
|
|
62
64
|
"@opentelemetry/exporter-trace-otlp-proto": "^0.218.0",
|