mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 21:03:19 +00:00
Rename /branch command to /fork
- RPC: branch -> fork, get_branch_messages -> get_fork_messages - SDK: branch() -> fork(), getBranchMessages() -> getForkMessages() - AgentSession: branch() -> fork(), getUserMessagesForBranching() -> getUserMessagesForForking() - Extension events: session_before_branch -> session_before_fork, session_branch -> session_fork - Settings: doubleEscapeAction 'branch' -> 'fork' fixes #641
This commit is contained in:
parent
e7352a50bf
commit
df3f5f41c0
27 changed files with 162 additions and 156 deletions
|
|
@ -37,8 +37,8 @@ import {
|
|||
import { exportSessionToHtml } from "./export-html/index.js";
|
||||
import type {
|
||||
ExtensionRunner,
|
||||
SessionBeforeBranchResult,
|
||||
SessionBeforeCompactResult,
|
||||
SessionBeforeForkResult,
|
||||
SessionBeforeSwitchResult,
|
||||
SessionBeforeTreeResult,
|
||||
TreePreparation,
|
||||
|
|
@ -1831,32 +1831,32 @@ export class AgentSession {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a branch from a specific entry.
|
||||
* Emits before_branch/branch session events to extensions.
|
||||
* Create a fork from a specific entry.
|
||||
* Emits before_fork/fork session events to extensions.
|
||||
*
|
||||
* @param entryId ID of the entry to branch from
|
||||
* @param entryId ID of the entry to fork from
|
||||
* @returns Object with:
|
||||
* - selectedText: The text of the selected user message (for editor pre-fill)
|
||||
* - cancelled: True if an extension cancelled the branch
|
||||
* - cancelled: True if an extension cancelled the fork
|
||||
*/
|
||||
async branch(entryId: string): Promise<{ selectedText: string; cancelled: boolean }> {
|
||||
async fork(entryId: string): Promise<{ selectedText: string; cancelled: boolean }> {
|
||||
const previousSessionFile = this.sessionFile;
|
||||
const selectedEntry = this.sessionManager.getEntry(entryId);
|
||||
|
||||
if (!selectedEntry || selectedEntry.type !== "message" || selectedEntry.message.role !== "user") {
|
||||
throw new Error("Invalid entry ID for branching");
|
||||
throw new Error("Invalid entry ID for forking");
|
||||
}
|
||||
|
||||
const selectedText = this._extractUserMessageText(selectedEntry.message.content);
|
||||
|
||||
let skipConversationRestore = false;
|
||||
|
||||
// Emit session_before_branch event (can be cancelled)
|
||||
if (this._extensionRunner?.hasHandlers("session_before_branch")) {
|
||||
// Emit session_before_fork event (can be cancelled)
|
||||
if (this._extensionRunner?.hasHandlers("session_before_fork")) {
|
||||
const result = (await this._extensionRunner.emit({
|
||||
type: "session_before_branch",
|
||||
type: "session_before_fork",
|
||||
entryId,
|
||||
})) as SessionBeforeBranchResult | undefined;
|
||||
})) as SessionBeforeForkResult | undefined;
|
||||
|
||||
if (result?.cancel) {
|
||||
return { selectedText, cancelled: true };
|
||||
|
|
@ -1877,15 +1877,15 @@ export class AgentSession {
|
|||
// Reload messages from entries (works for both file and in-memory mode)
|
||||
const sessionContext = this.sessionManager.buildSessionContext();
|
||||
|
||||
// Emit session_branch event to extensions (after branch completes)
|
||||
// Emit session_fork event to extensions (after fork completes)
|
||||
if (this._extensionRunner) {
|
||||
await this._extensionRunner.emit({
|
||||
type: "session_branch",
|
||||
type: "session_fork",
|
||||
previousSessionFile,
|
||||
});
|
||||
}
|
||||
|
||||
// Emit session event to custom tools (with reason "branch")
|
||||
// Emit session event to custom tools (with reason "fork")
|
||||
|
||||
if (!skipConversationRestore) {
|
||||
this.agent.replaceMessages(sessionContext.messages);
|
||||
|
|
@ -1900,7 +1900,7 @@ export class AgentSession {
|
|||
|
||||
/**
|
||||
* Navigate to a different node in the session tree.
|
||||
* Unlike branch() which creates a new session file, this stays in the same file.
|
||||
* Unlike fork() which creates a new session file, this stays in the same file.
|
||||
*
|
||||
* @param targetId The entry ID to navigate to
|
||||
* @param options.summarize Whether user wants to summarize abandoned branch
|
||||
|
|
@ -2061,9 +2061,9 @@ export class AgentSession {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get all user messages from session for branch selector.
|
||||
* Get all user messages from session for fork selector.
|
||||
*/
|
||||
getUserMessagesForBranching(): Array<{ entryId: string; text: string }> {
|
||||
getUserMessagesForForking(): Array<{ entryId: string; text: string }> {
|
||||
const entries = this.sessionManager.getEntries();
|
||||
const result: Array<{ entryId: string; text: string }> = [];
|
||||
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ export {
|
|||
loadExtensions,
|
||||
} from "./loader.js";
|
||||
export type {
|
||||
BranchHandler,
|
||||
ExtensionErrorListener,
|
||||
ForkHandler,
|
||||
NavigateTreeHandler,
|
||||
NewSessionHandler,
|
||||
ShutdownHandler,
|
||||
|
|
@ -75,17 +75,17 @@ export type {
|
|||
RegisteredTool,
|
||||
SendMessageHandler,
|
||||
SendUserMessageHandler,
|
||||
SessionBeforeBranchEvent,
|
||||
SessionBeforeBranchResult,
|
||||
SessionBeforeCompactEvent,
|
||||
SessionBeforeCompactResult,
|
||||
SessionBeforeForkEvent,
|
||||
SessionBeforeForkResult,
|
||||
SessionBeforeSwitchEvent,
|
||||
SessionBeforeSwitchResult,
|
||||
SessionBeforeTreeEvent,
|
||||
SessionBeforeTreeResult,
|
||||
SessionBranchEvent,
|
||||
SessionCompactEvent,
|
||||
SessionEvent,
|
||||
SessionForkEvent,
|
||||
SessionShutdownEvent,
|
||||
// Events - Session
|
||||
SessionStartEvent,
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ export type NewSessionHandler = (options?: {
|
|||
setup?: (sessionManager: SessionManager) => Promise<void>;
|
||||
}) => Promise<{ cancelled: boolean }>;
|
||||
|
||||
export type BranchHandler = (entryId: string) => Promise<{ cancelled: boolean }>;
|
||||
export type ForkHandler = (entryId: string) => Promise<{ cancelled: boolean }>;
|
||||
|
||||
export type NavigateTreeHandler = (
|
||||
targetId: string,
|
||||
|
|
@ -111,7 +111,7 @@ export class ExtensionRunner {
|
|||
private abortFn: () => void = () => {};
|
||||
private hasPendingMessagesFn: () => boolean = () => false;
|
||||
private newSessionHandler: NewSessionHandler = async () => ({ cancelled: false });
|
||||
private branchHandler: BranchHandler = async () => ({ cancelled: false });
|
||||
private forkHandler: ForkHandler = async () => ({ cancelled: false });
|
||||
private navigateTreeHandler: NavigateTreeHandler = async () => ({ cancelled: false });
|
||||
private shutdownHandler: ShutdownHandler = () => {};
|
||||
|
||||
|
|
@ -158,7 +158,7 @@ export class ExtensionRunner {
|
|||
if (commandContextActions) {
|
||||
this.waitForIdleFn = commandContextActions.waitForIdle;
|
||||
this.newSessionHandler = commandContextActions.newSession;
|
||||
this.branchHandler = commandContextActions.branch;
|
||||
this.forkHandler = commandContextActions.fork;
|
||||
this.navigateTreeHandler = commandContextActions.navigateTree;
|
||||
}
|
||||
this.uiContext = uiContext ?? noOpUIContext;
|
||||
|
|
@ -329,17 +329,17 @@ export class ExtensionRunner {
|
|||
...this.createContext(),
|
||||
waitForIdle: () => this.waitForIdleFn(),
|
||||
newSession: (options) => this.newSessionHandler(options),
|
||||
branch: (entryId) => this.branchHandler(entryId),
|
||||
fork: (entryId) => this.forkHandler(entryId),
|
||||
navigateTree: (targetId, options) => this.navigateTreeHandler(targetId, options),
|
||||
};
|
||||
}
|
||||
|
||||
private isSessionBeforeEvent(
|
||||
type: string,
|
||||
): type is "session_before_switch" | "session_before_branch" | "session_before_compact" | "session_before_tree" {
|
||||
): type is "session_before_switch" | "session_before_fork" | "session_before_compact" | "session_before_tree" {
|
||||
return (
|
||||
type === "session_before_switch" ||
|
||||
type === "session_before_branch" ||
|
||||
type === "session_before_fork" ||
|
||||
type === "session_before_compact" ||
|
||||
type === "session_before_tree"
|
||||
);
|
||||
|
|
|
|||
|
|
@ -218,8 +218,8 @@ export interface ExtensionCommandContext extends ExtensionContext {
|
|||
setup?: (sessionManager: SessionManager) => Promise<void>;
|
||||
}): Promise<{ cancelled: boolean }>;
|
||||
|
||||
/** Branch from a specific entry, creating a new session file. */
|
||||
branch(entryId: string): Promise<{ cancelled: boolean }>;
|
||||
/** Fork from a specific entry, creating a new session file. */
|
||||
fork(entryId: string): Promise<{ cancelled: boolean }>;
|
||||
|
||||
/** Navigate to a different point in the session tree. */
|
||||
navigateTree(targetId: string, options?: { summarize?: boolean }): Promise<{ cancelled: boolean }>;
|
||||
|
|
@ -289,15 +289,15 @@ export interface SessionSwitchEvent {
|
|||
previousSessionFile: string | undefined;
|
||||
}
|
||||
|
||||
/** Fired before branching a session (can be cancelled) */
|
||||
export interface SessionBeforeBranchEvent {
|
||||
type: "session_before_branch";
|
||||
/** Fired before forking a session (can be cancelled) */
|
||||
export interface SessionBeforeForkEvent {
|
||||
type: "session_before_fork";
|
||||
entryId: string;
|
||||
}
|
||||
|
||||
/** Fired after branching a session */
|
||||
export interface SessionBranchEvent {
|
||||
type: "session_branch";
|
||||
/** Fired after forking a session */
|
||||
export interface SessionForkEvent {
|
||||
type: "session_fork";
|
||||
previousSessionFile: string | undefined;
|
||||
}
|
||||
|
||||
|
|
@ -351,8 +351,8 @@ export type SessionEvent =
|
|||
| SessionStartEvent
|
||||
| SessionBeforeSwitchEvent
|
||||
| SessionSwitchEvent
|
||||
| SessionBeforeBranchEvent
|
||||
| SessionBranchEvent
|
||||
| SessionBeforeForkEvent
|
||||
| SessionForkEvent
|
||||
| SessionBeforeCompactEvent
|
||||
| SessionCompactEvent
|
||||
| SessionShutdownEvent
|
||||
|
|
@ -577,7 +577,7 @@ export interface SessionBeforeSwitchResult {
|
|||
cancel?: boolean;
|
||||
}
|
||||
|
||||
export interface SessionBeforeBranchResult {
|
||||
export interface SessionBeforeForkResult {
|
||||
cancel?: boolean;
|
||||
skipConversationRestore?: boolean;
|
||||
}
|
||||
|
|
@ -641,11 +641,8 @@ export interface ExtensionAPI {
|
|||
handler: ExtensionHandler<SessionBeforeSwitchEvent, SessionBeforeSwitchResult>,
|
||||
): void;
|
||||
on(event: "session_switch", handler: ExtensionHandler<SessionSwitchEvent>): void;
|
||||
on(
|
||||
event: "session_before_branch",
|
||||
handler: ExtensionHandler<SessionBeforeBranchEvent, SessionBeforeBranchResult>,
|
||||
): void;
|
||||
on(event: "session_branch", handler: ExtensionHandler<SessionBranchEvent>): void;
|
||||
on(event: "session_before_fork", handler: ExtensionHandler<SessionBeforeForkEvent, SessionBeforeForkResult>): void;
|
||||
on(event: "session_fork", handler: ExtensionHandler<SessionForkEvent>): void;
|
||||
on(
|
||||
event: "session_before_compact",
|
||||
handler: ExtensionHandler<SessionBeforeCompactEvent, SessionBeforeCompactResult>,
|
||||
|
|
@ -858,7 +855,7 @@ export interface ExtensionCommandContextActions {
|
|||
parentSession?: string;
|
||||
setup?: (sessionManager: SessionManager) => Promise<void>;
|
||||
}) => Promise<{ cancelled: boolean }>;
|
||||
branch: (entryId: string) => Promise<{ cancelled: boolean }>;
|
||||
fork: (entryId: string) => Promise<{ cancelled: boolean }>;
|
||||
navigateTree: (targetId: string, options?: { summarize?: boolean }) => Promise<{ cancelled: boolean }>;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,12 +41,12 @@ export {
|
|||
type LoadExtensionsResult,
|
||||
type MessageRenderer,
|
||||
type RegisteredCommand,
|
||||
type SessionBeforeBranchEvent,
|
||||
type SessionBeforeCompactEvent,
|
||||
type SessionBeforeForkEvent,
|
||||
type SessionBeforeSwitchEvent,
|
||||
type SessionBeforeTreeEvent,
|
||||
type SessionBranchEvent,
|
||||
type SessionCompactEvent,
|
||||
type SessionForkEvent,
|
||||
type SessionShutdownEvent,
|
||||
type SessionStartEvent,
|
||||
type SessionSwitchEvent,
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ export interface Settings {
|
|||
terminal?: TerminalSettings;
|
||||
images?: ImageSettings;
|
||||
enabledModels?: string[]; // Model patterns for cycling (same format as --models CLI flag)
|
||||
doubleEscapeAction?: "branch" | "tree"; // Action for double-escape with empty editor (default: "tree")
|
||||
doubleEscapeAction?: "fork" | "tree"; // Action for double-escape with empty editor (default: "tree")
|
||||
thinkingBudgets?: ThinkingBudgetsSettings; // Custom token budgets for thinking levels
|
||||
}
|
||||
|
||||
|
|
@ -452,11 +452,11 @@ export class SettingsManager {
|
|||
this.save();
|
||||
}
|
||||
|
||||
getDoubleEscapeAction(): "branch" | "tree" {
|
||||
getDoubleEscapeAction(): "fork" | "tree" {
|
||||
return this.settings.doubleEscapeAction ?? "tree";
|
||||
}
|
||||
|
||||
setDoubleEscapeAction(action: "branch" | "tree"): void {
|
||||
setDoubleEscapeAction(action: "fork" | "tree"): void {
|
||||
this.globalSettings.doubleEscapeAction = action;
|
||||
this.save();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue