@openacp/cli 2026.331.3 → 2026.331.5

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/dist/index.d.ts CHANGED
@@ -1056,7 +1056,7 @@ interface IChannelAdapter {
1056
1056
  createSessionThread(sessionId: string, name: string): Promise<string>;
1057
1057
  renameSessionThread(sessionId: string, newName: string): Promise<void>;
1058
1058
  deleteSessionThread?(sessionId: string): Promise<void>;
1059
- archiveSessionTopic?(sessionId: string): Promise<string>;
1059
+ archiveSessionTopic?(sessionId: string): Promise<void>;
1060
1060
  stripTTSBlock?(sessionId: string): Promise<void>;
1061
1061
  sendSkillCommands?(sessionId: string, commands: AgentCommand[]): Promise<void>;
1062
1062
  cleanupSkillCommands?(sessionId: string): Promise<void>;
@@ -1084,7 +1084,7 @@ declare abstract class ChannelAdapter<TCore = unknown> implements IChannelAdapte
1084
1084
  sendSkillCommands(_sessionId: string, _commands: AgentCommand[]): Promise<void>;
1085
1085
  cleanupSkillCommands(_sessionId: string): Promise<void>;
1086
1086
  cleanupSessionState(_sessionId: string): Promise<void>;
1087
- archiveSessionTopic(_sessionId: string): Promise<string>;
1087
+ archiveSessionTopic(_sessionId: string): Promise<void>;
1088
1088
  }
1089
1089
 
1090
1090
  declare function nodeToWebWritable(nodeStream: NodeJS.WritableStream): WritableStream<Uint8Array>;
@@ -2014,6 +2014,14 @@ interface EventBusEvents {
2014
2014
  attachments?: unknown[];
2015
2015
  }) => void;
2016
2016
  "usage:recorded": (data: UsageRecordEvent) => void;
2017
+ "session:agentSwitch": (data: {
2018
+ sessionId: string;
2019
+ fromAgent: string;
2020
+ toAgent: string;
2021
+ status: "starting" | "succeeded" | "failed";
2022
+ resumed?: boolean;
2023
+ error?: string;
2024
+ }) => void;
2017
2025
  }
2018
2026
  declare class EventBus extends TypedEmitter<EventBusEvents> {
2019
2027
  }
@@ -2174,8 +2182,9 @@ declare class SessionFactory {
2174
2182
  private sessionManager;
2175
2183
  private speechServiceAccessor;
2176
2184
  private eventBus;
2185
+ private instanceRoot?;
2177
2186
  middlewareChain?: MiddlewareChain;
2178
- constructor(agentManager: AgentManager, sessionManager: SessionManager, speechServiceAccessor: SpeechService | (() => SpeechService), eventBus: EventBus);
2187
+ constructor(agentManager: AgentManager, sessionManager: SessionManager, speechServiceAccessor: SpeechService | (() => SpeechService), eventBus: EventBus, instanceRoot?: string | undefined);
2179
2188
  private get speechService();
2180
2189
  create(params: SessionCreateParams): Promise<Session>;
2181
2190
  wireSideEffects(session: Session, deps: SideEffectDeps): void;
@@ -2409,7 +2418,6 @@ declare class OpenACPCore {
2409
2418
  stop(): Promise<void>;
2410
2419
  archiveSession(sessionId: string): Promise<{
2411
2420
  ok: true;
2412
- newThreadId: string;
2413
2421
  } | {
2414
2422
  ok: false;
2415
2423
  error: string;
@@ -3203,7 +3211,7 @@ declare class TelegramAdapter extends MessagingAdapter {
3203
3211
  cleanupSkillCommands(sessionId: string): Promise<void>;
3204
3212
  cleanupSessionState(sessionId: string): Promise<void>;
3205
3213
  stripTTSBlock(sessionId: string): Promise<void>;
3206
- archiveSessionTopic(sessionId: string): Promise<string>;
3214
+ archiveSessionTopic(sessionId: string): Promise<void>;
3207
3215
  }
3208
3216
 
3209
3217
  export { ActivityTracker, type AdapterCapabilities, type AgentCapabilities, AgentCatalog, type AgentCommand, type AgentDefinition, type AgentDistribution, type AgentEvent, AgentInstance, type AgentListItem, AgentManager, AgentStore, type AgentSwitchEntry, type ApiConfig, ApiServer, type Attachment, type AuthMethod, type AuthenticateRequest, type AvailabilityResult, BaseRenderer, type BridgeDeps, CONFIG_REGISTRY, ChannelAdapter, type ChannelConfig, type CleanupResult, type CommandArgs, type CommandDef, CommandRegistry, type CommandResponse, type Config, type ConfigFieldDef, ConfigManager$1 as ConfigManager, type ConfigOption, type ConfigSelectChoice, type ConfigSelectGroup, type ContentBlock, ContextManager, type ContextOptions, type ContextProvider, type ContextQuery, type ContextResult, type ContextService, type SessionInfo as ContextSessionInfo, type DeleteTopicResult, DisplaySpecBuilder, type DisplayVerbosity, DoctorEngine, type DoctorReport, DraftManager, EntireProvider, EventBus, type EventBusEvents, FileService, type FileServiceInterface, GroqSTT, type IChannelAdapter, type IRenderer, type IncomingMessage, type InstallContext, type InstallProgress, type InstallResult, type InstalledAgent, KIND_ICONS, type ListItem, type Logger$1 as Logger, type LoggingConfig, type McpServerConfig, type MenuOption, MessageTransformer, MessagingAdapter, type MessagingAdapterConfig, type MigrateContext, type ModelInfo, type NewSessionResponse, NotificationManager, type NotificationMessage, type NotificationService, OpenACPCore, type OpenACPPlugin, type OutgoingMessage, type OutputMode, OutputModeResolver, PRODUCT_GUIDE, type PendingFix, PermissionGate, type PermissionOption, type PermissionRequest, type PlanEntry, type PluginContext, type PluginPermission, type PluginStorage, PromptQueue, type PromptResponse, type RegistryAgent, type RegistryBinaryTarget, type RegistryDistribution, type RenderedMessage, SSEManager, STATUS_ICONS, type STTOptions, type STTProvider$1 as STTProvider, type STTResult, SecurityGuard, type SecurityService, SendQueue, Session, SessionBridge, type SessionCreateParams, type SessionEvents, SessionFactory, type SessionListItem, type SessionListResponse, type SessionListResult, SessionManager, type SessionMode, type SessionModeState, type SessionModelState, type SessionRecord, type SessionStatus, type SetConfigOptionValue, type SettingsAPI, type SideEffectDeps, type SpeechProviderConfig, SpeechService, type SpeechServiceConfig, type SpeechServiceInterface, StaticServer, StderrCapture, type StopReason, StreamAdapter, type TTSOptions, type TTSProvider$1 as TTSProvider, type TTSResult, TelegramAdapter, type TelegramPlatformData, type TerminalIO, ThoughtBuffer, type ThoughtDisplaySpec, type ToolCallMeta, ToolCallTracker, type ToolCardSnapshot, ToolCardState, type ToolCardStateConfig, type ToolDisplaySpec, type ToolEntry, ToolStateMap, type ToolUpdateMeta, type TopicInfo, TopicManager, type TunnelServiceInterface, TypedEmitter, type UsageConfig, type UsageRecord, type UsageRecordEvent, type UsageService, type ViewerLinks, cleanupOldSessionLogs, createChildLogger, createSessionLogger, expandHome, extractContentText, formatTokens, formatToolSummary, formatToolTitle, getConfigValue, getFieldDef, getPidPath, getSafeFields, getStatus, initLogger, installAutoStart, isAutoStartInstalled, isAutoStartSupported, isHotReloadable, log, nodeToWebReadable, nodeToWebWritable, progressBar, resolveOptions, resolveToolIcon, runConfigEditor, setLogLevel, shutdownLogger, splitMessage, startDaemon, stopDaemon, stripCodeFences, truncateContent, uninstallAutoStart };
package/dist/index.js CHANGED
@@ -2383,7 +2383,6 @@ var ChannelAdapter = class {
2383
2383
  async cleanupSessionState(_sessionId) {
2384
2384
  }
2385
2385
  async archiveSessionTopic(_sessionId) {
2386
- return "";
2387
2386
  }
2388
2387
  };
2389
2388
 
@@ -4742,13 +4741,17 @@ var SessionBridge = class {
4742
4741
  }
4743
4742
  };
4744
4743
  this.session.on("status_change", this.statusChangeHandler);
4745
- this.namedHandler = (name) => {
4746
- this.deps.sessionManager.patchRecord(this.session.id, { name });
4744
+ this.namedHandler = async (name) => {
4745
+ const record = this.deps.sessionManager.getSessionRecord(this.session.id);
4746
+ const alreadyNamed = !!record?.name;
4747
+ await this.deps.sessionManager.patchRecord(this.session.id, { name });
4747
4748
  this.deps.eventBus?.emit("session:updated", {
4748
4749
  sessionId: this.session.id,
4749
4750
  name
4750
4751
  });
4751
- this.adapter.renameSessionThread(this.session.id, name);
4752
+ if (!alreadyNamed) {
4753
+ await this.adapter.renameSessionThread(this.session.id, name);
4754
+ }
4752
4755
  };
4753
4756
  this.session.on("named", this.namedHandler);
4754
4757
  this.promptCountHandler = (count) => {
@@ -4762,11 +4765,12 @@ var SessionBridge = class {
4762
4765
  init_log();
4763
4766
  var log7 = createChildLogger({ module: "session-factory" });
4764
4767
  var SessionFactory = class {
4765
- constructor(agentManager, sessionManager, speechServiceAccessor, eventBus) {
4768
+ constructor(agentManager, sessionManager, speechServiceAccessor, eventBus, instanceRoot) {
4766
4769
  this.agentManager = agentManager;
4767
4770
  this.sessionManager = sessionManager;
4768
4771
  this.speechServiceAccessor = speechServiceAccessor;
4769
4772
  this.eventBus = eventBus;
4773
+ this.instanceRoot = instanceRoot;
4770
4774
  }
4771
4775
  middlewareChain;
4772
4776
  get speechService() {
@@ -4793,14 +4797,73 @@ var SessionFactory = class {
4793
4797
  channelId: result.channelId
4794
4798
  };
4795
4799
  }
4796
- const agentInstance = createParams.resumeAgentSessionId ? await this.agentManager.resume(
4797
- createParams.agentName,
4798
- createParams.workingDirectory,
4799
- createParams.resumeAgentSessionId
4800
- ) : await this.agentManager.spawn(
4801
- createParams.agentName,
4802
- createParams.workingDirectory
4803
- );
4800
+ let agentInstance;
4801
+ try {
4802
+ agentInstance = createParams.resumeAgentSessionId ? await this.agentManager.resume(
4803
+ createParams.agentName,
4804
+ createParams.workingDirectory,
4805
+ createParams.resumeAgentSessionId
4806
+ ) : await this.agentManager.spawn(
4807
+ createParams.agentName,
4808
+ createParams.workingDirectory
4809
+ );
4810
+ } catch (err) {
4811
+ const message = err instanceof Error ? err.message : String(err);
4812
+ const guidanceLines = [
4813
+ `\u274C Failed to start agent "${createParams.agentName}": ${message}`,
4814
+ "",
4815
+ "Run the agent CLI once in a terminal for this OpenACP instance to complete login or setup."
4816
+ ];
4817
+ if (this.instanceRoot) {
4818
+ guidanceLines.push(
4819
+ "",
4820
+ "Copy and run this command in your terminal:",
4821
+ ` cd "${this.instanceRoot}" && openacp agents run ${createParams.agentName}`
4822
+ );
4823
+ } else {
4824
+ guidanceLines.push(
4825
+ "",
4826
+ "Copy and run this command in your terminal (same project where you started OpenACP):",
4827
+ ` openacp agents run ${createParams.agentName}`
4828
+ );
4829
+ }
4830
+ guidanceLines.push(
4831
+ "",
4832
+ "After setup completes, retry creating the session here."
4833
+ );
4834
+ const guidance = {
4835
+ type: "system_message",
4836
+ message: guidanceLines.join("\n")
4837
+ };
4838
+ const failedSession = new Session({
4839
+ id: createParams.existingSessionId,
4840
+ channelId: createParams.channelId,
4841
+ agentName: createParams.agentName,
4842
+ workingDirectory: createParams.workingDirectory,
4843
+ // Dummy agent instance — will never be prompted
4844
+ agentInstance: {
4845
+ sessionId: "",
4846
+ prompt: async () => {
4847
+ },
4848
+ cancel: async () => {
4849
+ },
4850
+ destroy: async () => {
4851
+ },
4852
+ on: () => {
4853
+ },
4854
+ off: () => {
4855
+ }
4856
+ },
4857
+ speechService: this.speechService
4858
+ });
4859
+ this.sessionManager.registerSession(failedSession);
4860
+ failedSession.emit("agent_event", guidance);
4861
+ this.eventBus.emit("agent:event", {
4862
+ sessionId: failedSession.id,
4863
+ event: guidance
4864
+ });
4865
+ throw err;
4866
+ }
4804
4867
  agentInstance.middlewareChain = this.middlewareChain;
4805
4868
  const session = new Session({
4806
4869
  id: createParams.existingSessionId,
@@ -6313,7 +6376,8 @@ var OpenACPCore = class {
6313
6376
  this.agentManager,
6314
6377
  this.sessionManager,
6315
6378
  () => this.speechService,
6316
- this.eventBus
6379
+ this.eventBus,
6380
+ ctx?.root
6317
6381
  );
6318
6382
  this.lifecycleManager = new LifecycleManager({
6319
6383
  serviceRegistry: new ServiceRegistry(),
@@ -6408,20 +6472,9 @@ var OpenACPCore = class {
6408
6472
  if (!adapter) return { ok: false, error: "Adapter not found for session" };
6409
6473
  if (!adapter.archiveSessionTopic) return { ok: false, error: "Adapter does not support topic archiving" };
6410
6474
  try {
6411
- const newThreadId = await adapter.archiveSessionTopic(session.id);
6412
- session.threadId = newThreadId;
6413
- try {
6414
- const platform2 = {};
6415
- if (session.channelId === "telegram") {
6416
- platform2.topicId = Number(newThreadId);
6417
- } else {
6418
- platform2.threadId = newThreadId;
6419
- }
6420
- await this.sessionManager.patchRecord(sessionId, { platform: platform2 });
6421
- } catch (patchErr) {
6422
- log12.warn({ err: patchErr, sessionId }, "Failed to update session record after archive \u2014 session will work but may not survive restart");
6423
- }
6424
- return { ok: true, newThreadId };
6475
+ await adapter.archiveSessionTopic(session.id);
6476
+ await this.sessionManager.cancelSession(sessionId);
6477
+ return { ok: true };
6425
6478
  } catch (err) {
6426
6479
  session.archiving = false;
6427
6480
  return { ok: false, error: err.message };
@@ -6728,6 +6781,21 @@ var OpenACPCore = class {
6728
6781
  const caps = getAgentCapabilities(toAgent);
6729
6782
  const canResume = !!(lastEntry && caps.supportsResume && lastEntry.promptCount === 0);
6730
6783
  const resumed = canResume;
6784
+ const startEvent = {
6785
+ type: "system_message",
6786
+ message: `Switching from ${fromAgent} to ${toAgent}...`
6787
+ };
6788
+ session.emit("agent_event", startEvent);
6789
+ this.eventBus.emit("agent:event", {
6790
+ sessionId,
6791
+ event: startEvent
6792
+ });
6793
+ this.eventBus.emit("session:agentSwitch", {
6794
+ sessionId,
6795
+ fromAgent,
6796
+ toAgent,
6797
+ status: "starting"
6798
+ });
6731
6799
  const bridge = this.bridges.get(sessionId);
6732
6800
  if (bridge) bridge.disconnect();
6733
6801
  const switchAdapter = this.adapters.get(session.channelId);
@@ -6762,7 +6830,40 @@ var OpenACPCore = class {
6762
6830
  return instance;
6763
6831
  }
6764
6832
  });
6833
+ const successEvent = {
6834
+ type: "system_message",
6835
+ message: resumed ? `Switched to ${toAgent} (resumed previous session).` : `Switched to ${toAgent} (new session).`
6836
+ };
6837
+ session.emit("agent_event", successEvent);
6838
+ this.eventBus.emit("agent:event", {
6839
+ sessionId,
6840
+ event: successEvent
6841
+ });
6842
+ this.eventBus.emit("session:agentSwitch", {
6843
+ sessionId,
6844
+ fromAgent,
6845
+ toAgent,
6846
+ status: "succeeded",
6847
+ resumed
6848
+ });
6765
6849
  } catch (err) {
6850
+ const errorMessage = err instanceof Error ? err.message : String(err);
6851
+ const failedEvent = {
6852
+ type: "system_message",
6853
+ message: `Failed to switch to ${toAgent}: ${errorMessage}`
6854
+ };
6855
+ session.emit("agent_event", failedEvent);
6856
+ this.eventBus.emit("agent:event", {
6857
+ sessionId,
6858
+ event: failedEvent
6859
+ });
6860
+ this.eventBus.emit("session:agentSwitch", {
6861
+ sessionId,
6862
+ fromAgent,
6863
+ toAgent,
6864
+ status: "failed",
6865
+ error: errorMessage
6866
+ });
6766
6867
  try {
6767
6868
  let rollbackInstance;
6768
6869
  try {
@@ -13912,7 +14013,7 @@ async function handleArchive(ctx, core) {
13912
14013
  return;
13913
14014
  }
13914
14015
  await ctx.reply(
13915
- "\u26A0\uFE0F <b>Archive this session?</b>\n\nThis will:\n\u2022 Delete this topic and recreate it (clearing chat history)\n\u2022 The agent session will keep running\n\n<i>Chat history cannot be recovered.</i>",
14016
+ "\u26A0\uFE0F <b>Archive this session?</b>\n\nThis will:\n\u2022 Stop the agent session\n\u2022 Delete this topic permanently\n\n<i>This cannot be undone.</i>",
13916
14017
  {
13917
14018
  parse_mode: "HTML",
13918
14019
  reply_markup: new InlineKeyboard3().text("\u{1F5D1} Yes, archive", `ar:yes:${identifier}`).text("\u274C Cancel", `ar:no:${identifier}`)
@@ -13933,18 +14034,7 @@ async function handleArchiveConfirm(ctx, core, chatId) {
13933
14034
  return;
13934
14035
  }
13935
14036
  const result = await core.archiveSession(identifier);
13936
- if (result.ok) {
13937
- const adapter = core.adapters.get("telegram");
13938
- if (adapter) {
13939
- try {
13940
- await adapter.sendMessage(identifier, {
13941
- type: "text",
13942
- text: "Chat history cleared. Session is still active \u2014 send a message to continue."
13943
- });
13944
- } catch {
13945
- }
13946
- }
13947
- } else {
14037
+ if (!result.ok) {
13948
14038
  try {
13949
14039
  await ctx.editMessageText(`Failed to archive: <code>${escapeHtml(result.error)}</code>`, { parse_mode: "HTML" });
13950
14040
  } catch {
@@ -17733,10 +17823,6 @@ Task completed.
17733
17823
  this.sessionTrackers.delete(session.id);
17734
17824
  }
17735
17825
  await deleteSessionTopic(this.bot, chatId, oldTopicId);
17736
- const topicName = session.name ?? `Session ${session.id.slice(0, 6)}`;
17737
- const newTopicId = await createSessionTopic(this.bot, chatId, topicName);
17738
- session.archiving = false;
17739
- return String(newTopicId);
17740
17826
  }
17741
17827
  };
17742
17828
  export {