mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-20 14:05:08 +00:00
fix(coding-agent): bind extension UI context on startup
This commit is contained in:
parent
f86e3c3103
commit
5dbeadae05
4 changed files with 60 additions and 66 deletions
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
- Git extension updates now handle force-pushed remotes gracefully instead of failing ([#961](https://github.com/badlogic/pi-mono/pull/961) by [@aliou](https://github.com/aliou))
|
- Git extension updates now handle force-pushed remotes gracefully instead of failing ([#961](https://github.com/badlogic/pi-mono/pull/961) by [@aliou](https://github.com/aliou))
|
||||||
- Extension `ctx.newSession({ setup })` now properly syncs agent state and renders messages after setup callback runs ([#968](https://github.com/badlogic/pi-mono/issues/968))
|
- Extension `ctx.newSession({ setup })` now properly syncs agent state and renders messages after setup callback runs ([#968](https://github.com/badlogic/pi-mono/issues/968))
|
||||||
|
- Fixed extension UI bindings not initializing when starting with no extensions, which broke UI methods after `/reload`
|
||||||
|
|
||||||
## [0.50.0] - 2026-01-26
|
## [0.50.0] - 2026-01-26
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -976,13 +976,6 @@ export class InteractiveMode {
|
||||||
* Initialize the extension system with TUI-based UI context.
|
* Initialize the extension system with TUI-based UI context.
|
||||||
*/
|
*/
|
||||||
private async initExtensions(): Promise<void> {
|
private async initExtensions(): Promise<void> {
|
||||||
const extensionRunner = this.session.extensionRunner;
|
|
||||||
if (!extensionRunner) {
|
|
||||||
this.showLoadedResources({ extensionPaths: [], force: false });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create extension UI context
|
|
||||||
const uiContext = this.createExtensionUIContext();
|
const uiContext = this.createExtensionUIContext();
|
||||||
await this.session.bindExtensions({
|
await this.session.bindExtensions({
|
||||||
uiContext,
|
uiContext,
|
||||||
|
|
@ -1057,6 +1050,12 @@ export class InteractiveMode {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const extensionRunner = this.session.extensionRunner;
|
||||||
|
if (!extensionRunner) {
|
||||||
|
this.showLoadedResources({ extensionPaths: [], force: false });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.setupExtensionShortcuts(extensionRunner);
|
this.setupExtensionShortcuts(extensionRunner);
|
||||||
this.showLoadedResources({ extensionPaths: extensionRunner.getExtensionPaths(), force: false });
|
this.showLoadedResources({ extensionPaths: extensionRunner.getExtensionPaths(), force: false });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,37 +36,34 @@ export async function runPrintMode(session: AgentSession, options: PrintModeOpti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Set up extensions for print mode (no UI)
|
// Set up extensions for print mode (no UI)
|
||||||
const extensionRunner = session.extensionRunner;
|
await session.bindExtensions({
|
||||||
if (extensionRunner) {
|
commandContextActions: {
|
||||||
await session.bindExtensions({
|
waitForIdle: () => session.agent.waitForIdle(),
|
||||||
commandContextActions: {
|
newSession: async (options) => {
|
||||||
waitForIdle: () => session.agent.waitForIdle(),
|
const success = await session.newSession({ parentSession: options?.parentSession });
|
||||||
newSession: async (options) => {
|
if (success && options?.setup) {
|
||||||
const success = await session.newSession({ parentSession: options?.parentSession });
|
await options.setup(session.sessionManager);
|
||||||
if (success && options?.setup) {
|
}
|
||||||
await options.setup(session.sessionManager);
|
return { cancelled: !success };
|
||||||
}
|
|
||||||
return { cancelled: !success };
|
|
||||||
},
|
|
||||||
fork: async (entryId) => {
|
|
||||||
const result = await session.fork(entryId);
|
|
||||||
return { cancelled: result.cancelled };
|
|
||||||
},
|
|
||||||
navigateTree: async (targetId, options) => {
|
|
||||||
const result = await session.navigateTree(targetId, {
|
|
||||||
summarize: options?.summarize,
|
|
||||||
customInstructions: options?.customInstructions,
|
|
||||||
replaceInstructions: options?.replaceInstructions,
|
|
||||||
label: options?.label,
|
|
||||||
});
|
|
||||||
return { cancelled: result.cancelled };
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
onError: (err) => {
|
fork: async (entryId) => {
|
||||||
console.error(`Extension error (${err.extensionPath}): ${err.error}`);
|
const result = await session.fork(entryId);
|
||||||
|
return { cancelled: result.cancelled };
|
||||||
},
|
},
|
||||||
});
|
navigateTree: async (targetId, options) => {
|
||||||
}
|
const result = await session.navigateTree(targetId, {
|
||||||
|
summarize: options?.summarize,
|
||||||
|
customInstructions: options?.customInstructions,
|
||||||
|
replaceInstructions: options?.replaceInstructions,
|
||||||
|
label: options?.label,
|
||||||
|
});
|
||||||
|
return { cancelled: result.cancelled };
|
||||||
|
},
|
||||||
|
},
|
||||||
|
onError: (err) => {
|
||||||
|
console.error(`Extension error (${err.extensionPath}): ${err.error}`);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
// Always subscribe to enable session persistence via _handleAgentEvent
|
// Always subscribe to enable session persistence via _handleAgentEvent
|
||||||
session.subscribe((event) => {
|
session.subscribe((event) => {
|
||||||
|
|
|
||||||
|
|
@ -254,39 +254,36 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set up extensions with RPC-based UI context
|
// Set up extensions with RPC-based UI context
|
||||||
const extensionRunner = session.extensionRunner;
|
await session.bindExtensions({
|
||||||
if (extensionRunner) {
|
uiContext: createExtensionUIContext(),
|
||||||
await session.bindExtensions({
|
commandContextActions: {
|
||||||
uiContext: createExtensionUIContext(),
|
waitForIdle: () => session.agent.waitForIdle(),
|
||||||
commandContextActions: {
|
newSession: async (options) => {
|
||||||
waitForIdle: () => session.agent.waitForIdle(),
|
// Delegate to AgentSession (handles setup + agent state sync)
|
||||||
newSession: async (options) => {
|
const success = await session.newSession(options);
|
||||||
// Delegate to AgentSession (handles setup + agent state sync)
|
return { cancelled: !success };
|
||||||
const success = await session.newSession(options);
|
|
||||||
return { cancelled: !success };
|
|
||||||
},
|
|
||||||
fork: async (entryId) => {
|
|
||||||
const result = await session.fork(entryId);
|
|
||||||
return { cancelled: result.cancelled };
|
|
||||||
},
|
|
||||||
navigateTree: async (targetId, options) => {
|
|
||||||
const result = await session.navigateTree(targetId, {
|
|
||||||
summarize: options?.summarize,
|
|
||||||
customInstructions: options?.customInstructions,
|
|
||||||
replaceInstructions: options?.replaceInstructions,
|
|
||||||
label: options?.label,
|
|
||||||
});
|
|
||||||
return { cancelled: result.cancelled };
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
shutdownHandler: () => {
|
fork: async (entryId) => {
|
||||||
shutdownRequested = true;
|
const result = await session.fork(entryId);
|
||||||
|
return { cancelled: result.cancelled };
|
||||||
},
|
},
|
||||||
onError: (err) => {
|
navigateTree: async (targetId, options) => {
|
||||||
output({ type: "extension_error", extensionPath: err.extensionPath, event: err.event, error: err.error });
|
const result = await session.navigateTree(targetId, {
|
||||||
|
summarize: options?.summarize,
|
||||||
|
customInstructions: options?.customInstructions,
|
||||||
|
replaceInstructions: options?.replaceInstructions,
|
||||||
|
label: options?.label,
|
||||||
|
});
|
||||||
|
return { cancelled: result.cancelled };
|
||||||
},
|
},
|
||||||
});
|
},
|
||||||
}
|
shutdownHandler: () => {
|
||||||
|
shutdownRequested = true;
|
||||||
|
},
|
||||||
|
onError: (err) => {
|
||||||
|
output({ type: "extension_error", extensionPath: err.extensionPath, event: err.event, error: err.error });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
// Output all agent events as JSON
|
// Output all agent events as JSON
|
||||||
session.subscribe((event) => {
|
session.subscribe((event) => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue