@xopcai/xopc 0.0.167 → 0.0.169

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.
Files changed (137) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/xopc.extension.json +1 -1
  3. package/dist/gateway/static/root/assets/{activity-store-DjEDu38T.js → activity-store-DumQD8EX.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DQULz7qY.js → agent-avatar-dicebear-CNI1HQdV.js} +1 -1
  5. package/dist/gateway/static/root/assets/{agents-CnzkBgKC.js → agents-DfpeWAnu.js} +2 -2
  6. package/dist/gateway/static/root/assets/{api-DwVCuPOb.js → api-D7eNcGmE.js} +1 -1
  7. package/dist/gateway/static/root/assets/{app-management-settings-panel-DOjWALVF.js → app-management-settings-panel-BPbnbnFn.js} +1 -1
  8. package/dist/gateway/static/root/assets/{appearance-settings-C31COUIC.js → appearance-settings-WWFCDver.js} +1 -1
  9. package/dist/gateway/static/root/assets/{apps-page-lSC486eu.js → apps-page-B27faKqW.js} +1 -1
  10. package/dist/gateway/static/root/assets/{archive-plugin-DQPvLqfx.js → archive-plugin-Cu2dsFtI.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-DwT1x1rc.js → attachment-load-C9mycbtr.js} +1 -1
  12. package/dist/gateway/static/root/assets/{automation-suggestion-card-ByYBiiMR.js → automation-suggestion-card-DtHqVViI.js} +1 -1
  13. package/dist/gateway/static/root/assets/{automations-page-iZTnc1YZ.js → automations-page-BoH5grBX.js} +1 -1
  14. package/dist/gateway/static/root/assets/{binary-plugins-CRXiHoZS.js → binary-plugins-DqrPRyjm.js} +1 -1
  15. package/dist/gateway/static/root/assets/{block-editor-CHO6ILiz.js → block-editor-B9dc3pqc.js} +1 -1
  16. package/dist/gateway/static/root/assets/{browser-settings-page-C-OOPZcJ.js → browser-settings-page-CK2fnxHY.js} +1 -1
  17. package/dist/gateway/static/root/assets/{browser-workflow-inputs-3UaarfXS.js → browser-workflow-inputs-70k5yvTc.js} +1 -1
  18. package/dist/gateway/static/root/assets/{browser-workflows-page-BFaa-N_D.js → browser-workflows-page-DBNuaWwR.js} +1 -1
  19. package/dist/gateway/static/root/assets/{capabilities-settings-panel-BayH0Uom.js → capabilities-settings-panel-gg9GXU00.js} +6 -6
  20. package/dist/gateway/static/root/assets/{capability-presets-api-DdCHSzcA.js → capability-presets-api-CvV4M4Oe.js} +1 -1
  21. package/dist/gateway/static/root/assets/capability-presets-settings-panel-A1qGVyll.js +1 -0
  22. package/dist/gateway/static/root/assets/{channel-recipient-api-BOkLI89e.js → channel-recipient-api-BnLOBd7v.js} +1 -1
  23. package/dist/gateway/static/root/assets/{channels-settings-C-Spmwr5.js → channels-settings-H4vCzqiD.js} +1 -1
  24. package/dist/gateway/static/root/assets/channels-status-swr-DtswVkDX.js +1 -0
  25. package/dist/gateway/static/root/assets/{chunk-KS7C4IRE-uQ0fehio.js → chunk-KS7C4IRE-BMhrPKJC.js} +2 -2
  26. package/dist/gateway/static/root/assets/{connector-logo-CbcC0T6i.js → connector-logo-CYQPu4Nn.js} +1 -1
  27. package/dist/gateway/static/root/assets/{connectors-page-DpDmJ3Nx.js → connectors-page-DphVkloc.js} +1 -1
  28. package/dist/gateway/static/root/assets/{desktop-pet-CR7RGQff.js → desktop-pet-Deb8fsr-.js} +1 -1
  29. package/dist/gateway/static/root/assets/{desktop-pet-settings-BudmCcPE.js → desktop-pet-settings-DHTY5Ku1.js} +1 -1
  30. package/dist/gateway/static/root/assets/{directory-picker-path-field-BLG2Oe6z.js → directory-picker-path-field-cGL2aEB6.js} +1 -1
  31. package/dist/gateway/static/root/assets/{dreaming-settings-BwBGC0SG.js → dreaming-settings-C2XF2wL4.js} +1 -1
  32. package/dist/gateway/static/root/assets/{extension-debug-page-Pr65_hLC.js → extension-debug-page-F8AzDx0d.js} +1 -1
  33. package/dist/gateway/static/root/assets/{extension-page-BuJDcoKn.js → extension-page-ZrX_Ge87.js} +1 -1
  34. package/dist/gateway/static/root/assets/{extension-settings-page-B3802tn5.js → extension-settings-page-VypAD6ok.js} +1 -1
  35. package/dist/gateway/static/root/assets/{gateway-config-api-D-NVkfts.js → gateway-config-api-C-UsxEKi.js} +1 -1
  36. package/dist/gateway/static/root/assets/{gateway-settings-DIdsKVXv.js → gateway-settings-ChG26Coy.js} +1 -1
  37. package/dist/gateway/static/root/assets/{gateway-startup-retry-qnEmj-vL.js → gateway-startup-retry-D73V3EVy.js} +1 -1
  38. package/dist/gateway/static/root/assets/{goal-create-dialog-51j_DxgV.js → goal-create-dialog-B6aBG2KK.js} +1 -1
  39. package/dist/gateway/static/root/assets/{goal-detail-page-CeqMr5GF.js → goal-detail-page-B_G9oVL1.js} +3 -3
  40. package/dist/gateway/static/root/assets/{goals-config-api-BkVBh7ct.js → goals-config-api-fv7JLhjy.js} +1 -1
  41. package/dist/gateway/static/root/assets/{goals-page-lf3oM4Xa.js → goals-page-BQmg_7aD.js} +1 -1
  42. package/dist/gateway/static/root/assets/{goals-settings-Cg7MJLvx.js → goals-settings-DlfyneMz.js} +1 -1
  43. package/dist/gateway/static/root/assets/{heartbeat-settings-BV3kJOcX.js → heartbeat-settings-BPyFbSbh.js} +1 -1
  44. package/dist/gateway/static/root/assets/image-generation-api-CSKX7PsM.js +1 -0
  45. package/dist/gateway/static/root/assets/index-DJtuKve9.js +199 -0
  46. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-B9K5rTZZ.js → keyboard-shortcuts-settings-BUxrnWH_.js} +1 -1
  47. package/dist/gateway/static/root/assets/{local-app-workbench-page-ehzr9CBG.js → local-app-workbench-page-Dzlj4fH8.js} +1 -1
  48. package/dist/gateway/static/root/assets/{local-apps-page-BBx6mfAD.js → local-apps-page-BsZMeDnS.js} +1 -1
  49. package/dist/gateway/static/root/assets/{locale-store-tnRLWdx2.js → locale-store-DXq-Y8Bi.js} +1 -1
  50. package/dist/gateway/static/root/assets/{logs-page-xuwEkusZ.js → logs-page-Bg1B-cKU.js} +1 -1
  51. package/dist/gateway/static/root/assets/{markdown-split-DRDddIt8.js → markdown-split-Cmaw70yM.js} +1 -1
  52. package/dist/gateway/static/root/assets/{media-plugins-Dn3hxhOV.js → media-plugins-Blqj_oJD.js} +1 -1
  53. package/dist/gateway/static/root/assets/{messages-B1EG4gdu.js → messages-Cj_n7gUv.js} +2 -2
  54. package/dist/gateway/static/root/assets/notes-page-B6Fdlf_s.js +1 -0
  55. package/dist/gateway/static/root/assets/{notes-workbench-DXGXn5XF.js → notes-workbench-4HYPR6Hb.js} +2 -2
  56. package/dist/gateway/static/root/assets/{page-tabs-P2BEd1D8.js → page-tabs-D6zFoyJY.js} +1 -1
  57. package/dist/gateway/static/root/assets/{preview-open-alternatives-DrkjmW0F.js → preview-open-alternatives-BLoo7Ad8.js} +1 -1
  58. package/dist/gateway/static/root/assets/{product-open-page-CGzMEowb.js → product-open-page-0-tt2dp7.js} +1 -1
  59. package/dist/gateway/static/root/assets/{project-detail-page-IiE2ddWb.js → project-detail-page-CGa68F1d.js} +1 -1
  60. package/dist/gateway/static/root/assets/{projects-page-DGOVhaYI.js → projects-page-BXmIeErj.js} +1 -1
  61. package/dist/gateway/static/root/assets/{remote-access-hub-l_y_Shgl.js → remote-access-hub-bxrIHaRt.js} +1 -1
  62. package/dist/gateway/static/root/assets/{save-bar-controls-BkGrufxl.js → save-bar-controls-9ujl7LRy.js} +1 -1
  63. package/dist/gateway/static/root/assets/{schedule-field-A8tDpL-9.js → schedule-field-e80Mj-0z.js} +1 -1
  64. package/dist/gateway/static/root/assets/{schema-form-N6_hDWgx.js → schema-form-DYZQD-PL.js} +1 -1
  65. package/dist/gateway/static/root/assets/{sessions-page-CAX4ipPv.js → sessions-page-D_7ms_LG.js} +1 -1
  66. package/dist/gateway/static/root/assets/settings-advanced-gate-VLuu9WHc.js +1 -0
  67. package/dist/gateway/static/root/assets/{settings-form-section-Bb6yYt5f.js → settings-form-section-Clt3p-mk.js} +1 -1
  68. package/dist/gateway/static/root/assets/{settings-loading-skeleton-Q_Vh6HEl.js → settings-loading-skeleton-CTuS66nC.js} +1 -1
  69. package/dist/gateway/static/root/assets/{settings-page-CjOtQpbR.js → settings-page-CMP_owwc.js} +1 -1
  70. package/dist/gateway/static/root/assets/{settings-page-layout-CtESNNdx.js → settings-page-layout-BWUV_wx6.js} +1 -1
  71. package/dist/gateway/static/root/assets/{setup-status-panel-CGxHXgJB.js → setup-status-panel-CAClgrxi.js} +1 -1
  72. package/dist/gateway/static/root/assets/{share-preview-page-C65IsFmd.js → share-preview-page-tISZJtRK.js} +1 -1
  73. package/dist/gateway/static/root/assets/{shares-settings-Ct3fcbHr.js → shares-settings-t-hP0QDv.js} +1 -1
  74. package/dist/gateway/static/root/assets/skill-reload-api-CYRaxTqs.js +1 -0
  75. package/dist/gateway/static/root/assets/{skills-page-FeieOEn3.js → skills-page-C6CXLWnN.js} +1 -1
  76. package/dist/gateway/static/root/assets/{system-settings-panel-CdUl2I0D.js → system-settings-panel-6u0k0wJi.js} +1 -1
  77. package/dist/gateway/static/root/assets/{theme-store-H9T49Iar.js → theme-store-DSpAOJ9G.js} +1 -1
  78. package/dist/gateway/static/root/assets/{time-picker-EkhqT3fS.js → time-picker-BF3f8el1.js} +1 -1
  79. package/dist/gateway/static/root/assets/{typed-models-lib-5xRRUE9Y.js → typed-models-lib-CyRCjjGS.js} +1 -1
  80. package/dist/gateway/static/root/assets/{use-channel-catalog-UACJTyH0.js → use-channel-catalog-B_Igd7ec.js} +1 -1
  81. package/dist/gateway/static/root/assets/{user-context-page-DHiRvd4i.js → user-context-page-B3zeQLeM.js} +1 -1
  82. package/dist/gateway/static/root/assets/{voice-api-key-field-Bql0SPCp.js → voice-api-key-field-BanJk_cf.js} +1 -1
  83. package/dist/gateway/static/root/assets/{work-discovery-page-BcmZux7y.js → work-discovery-page-BCANmOUS.js} +1 -1
  84. package/dist/gateway/static/root/assets/{work-item-detail-page-D94Q5zVD.js → work-item-detail-page-t5xiIEFv.js} +1 -1
  85. package/dist/gateway/static/root/assets/{work-page-DdFBMDcB.js → work-page-CEI3zs-y.js} +1 -1
  86. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-Dow7ZztR.js → workflow-run-setup-panel-DCXTQx7p.js} +1 -1
  87. package/dist/gateway/static/root/assets/{workflows-page-wOVSoduy.js → workflows-page-B8FRLCHp.js} +3 -3
  88. package/dist/gateway/static/root/index.html +7 -7
  89. package/dist/package.js +1 -1
  90. package/dist/src/agent/agent-manager.js +12 -5
  91. package/dist/src/agent/memory/dreaming/config.js +1 -1
  92. package/dist/src/agent/models/manager.d.ts +5 -0
  93. package/dist/src/agent/models/manager.js +8 -0
  94. package/dist/src/agent/prompt/sections/messaging-runtime.js +1 -1
  95. package/dist/src/agent/prompt/sections/tooling.js +1 -1
  96. package/dist/src/agent/tools/communication.js +25 -7
  97. package/dist/src/agent-runtime/index.js +1 -1
  98. package/dist/src/agent-runtime/runtime-profile.js +1 -1
  99. package/dist/src/channels/plugin-registry.js +6 -1
  100. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  101. package/dist/src/config/agent-profile.js +1 -1
  102. package/dist/src/gateway/agents-admin.js +1 -1
  103. package/dist/src/gateway/hono/routes/composer-history.d.ts +3 -0
  104. package/dist/src/gateway/hono/routes/composer-history.js +28 -0
  105. package/dist/src/gateway/hono/routes/index.js +2 -0
  106. package/dist/src/session/client-history.d.ts +2 -0
  107. package/dist/src/session/client-history.js +2 -0
  108. package/dist/src/session/patch-metadata.d.ts +2 -0
  109. package/dist/src/session/patch-metadata.js +2 -0
  110. package/dist/src/storage/sqlite/composer-input-history-repository.d.ts +12 -0
  111. package/dist/src/storage/sqlite/composer-input-history-repository.js +42 -0
  112. package/dist/src/storage/sqlite/index.d.ts +1 -0
  113. package/dist/src/storage/sqlite/index.js +2 -1
  114. package/dist/src/storage/sqlite/migrations/059_composer_input_history.sql +8 -0
  115. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  116. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  117. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  118. package/dist/src/storage/sqlite/schema.js +1 -1
  119. package/dist/src/tui/backends/embedded-backend.d.ts +5 -1
  120. package/dist/src/tui/backends/embedded-backend.js +53 -9
  121. package/dist/src/tui/backends/gateway-sse-backend.d.ts +3 -1
  122. package/dist/src/tui/backends/gateway-sse-backend.js +23 -3
  123. package/dist/src/tui/components/custom-editor.d.ts +1 -0
  124. package/dist/src/tui/components/custom-editor.js +6 -0
  125. package/dist/src/tui/tui-backend.d.ts +11 -0
  126. package/dist/src/tui/tui-empty-session-cleanup.d.ts +11 -0
  127. package/dist/src/tui/tui-empty-session-cleanup.js +37 -0
  128. package/dist/src/tui/tui-submit.d.ts +1 -0
  129. package/dist/src/tui/tui-submit.js +1 -1
  130. package/dist/src/tui/tui.js +101 -17
  131. package/package.json +1 -1
  132. package/dist/gateway/static/root/assets/capability-presets-settings-panel-JlhjAhT7.js +0 -2
  133. package/dist/gateway/static/root/assets/channels-status-swr-ZrqadU60.js +0 -1
  134. package/dist/gateway/static/root/assets/index-B24B26og.js +0 -199
  135. package/dist/gateway/static/root/assets/notes-page-BtKHSb4z.js +0 -1
  136. package/dist/gateway/static/root/assets/settings-advanced-gate-eVlH9brU.js +0 -1
  137. package/dist/gateway/static/root/assets/skill-reload-api-ElA5kabh.js +0 -1
@@ -1,6 +1,7 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
3
  import { openXopcDatabase } from "../../storage/sqlite/connection.js";
4
+ import { appendComposerInputHistory, listComposerInputHistory } from "../../storage/sqlite/composer-input-history-repository.js";
4
5
  import { init_agent_session_key, resolveAgentIdFromSessionKey } from "../../routing/agent-session-key.js";
5
6
  import { getSessionMetadata } from "../../storage/sqlite/session-repository.js";
6
7
  import "../../storage/sqlite/index.js";
@@ -77,6 +78,12 @@ var EmbeddedBackend = class {
77
78
  get connectionLabel() {
78
79
  return "local embedded";
79
80
  }
81
+ async getComposerInputHistory() {
82
+ return listComposerInputHistory();
83
+ }
84
+ async recordComposerInputHistory(text) {
85
+ return appendComposerInputHistory(text).item;
86
+ }
80
87
  start() {
81
88
  if (this.running) return;
82
89
  this.running = true;
@@ -122,6 +129,7 @@ var EmbeddedBackend = class {
122
129
  }
123
130
  }
124
131
  async createAgent(config, sessionIndex) {
132
+ await this.refreshXopcCloudModels();
125
133
  const { AgentService } = await import("../../agent/service.js");
126
134
  const workspace = this.workspace || getWorkspacePath(config);
127
135
  const modelId = getAgentDefaultModelRef(config);
@@ -143,6 +151,20 @@ var EmbeddedBackend = class {
143
151
  await agent.start();
144
152
  return agent;
145
153
  }
154
+ async refreshXopcCloudModels() {
155
+ try {
156
+ const { XopcCloudModelSource } = await import("../../providers/xopc-cloud-model-source.js");
157
+ const result = await new XopcCloudModelSource().refresh();
158
+ if (result.status === "updated") log.info({ modelCount: result.modelCount }, `XOPC Cloud model catalog refreshed: ${result.modelCount} models`);
159
+ } catch (err) {
160
+ const errorMessage = err instanceof Error ? err.message : String(err);
161
+ log.warn({
162
+ err,
163
+ errorMessage,
164
+ phase: "model_catalog_refresh"
165
+ }, `XOPC Cloud model catalog refresh failed: ${errorMessage}`);
166
+ }
167
+ }
146
168
  stop() {
147
169
  this.running = false;
148
170
  this.chatAbort?.abort();
@@ -419,9 +441,10 @@ var EmbeddedBackend = class {
419
441
  }
420
442
  }
421
443
  async getSessionStats(sessionKey) {
422
- if (!this.agent) return computeTuiSessionStats([]);
444
+ const store = this.agent?.sessionStore ?? this.sessionIndex?.getStore();
445
+ if (!store) return computeTuiSessionStats([]);
423
446
  try {
424
- return computeTuiSessionStats(await this.agent.sessionStore.loadTranscriptRows(sessionKey));
447
+ return computeTuiSessionStats(await store.loadTranscriptRows(sessionKey));
425
448
  } catch (error) {
426
449
  const errorMessage = error instanceof Error ? error.message : String(error);
427
450
  log.warn({
@@ -485,9 +508,10 @@ var EmbeddedBackend = class {
485
508
  }
486
509
  }
487
510
  async deleteSession(sessionKey) {
488
- if (!this.agent) return { ok: false };
511
+ const store = this.agent?.sessionStore ?? this.sessionIndex?.getStore();
512
+ if (!store) return { ok: false };
489
513
  try {
490
- return { ok: await this.agent.sessionStore.deleteSession(sessionKey) };
514
+ return { ok: await store.deleteSession(sessionKey) };
491
515
  } catch (error) {
492
516
  const errorMessage = error instanceof Error ? error.message : String(error);
493
517
  log.warn({
@@ -535,6 +559,9 @@ var EmbeddedBackend = class {
535
559
  contextWindow: model.contextWindow
536
560
  }));
537
561
  }
562
+ async refreshModels() {
563
+ await this.refreshXopcCloudModels();
564
+ }
538
565
  async resetSession(sessionKey) {
539
566
  if (!this.agent) return;
540
567
  await this.agent.resetSession(sessionKey);
@@ -542,11 +569,6 @@ var EmbeddedBackend = class {
542
569
  async patchSession(sessionKey, patch) {
543
570
  const agent = await this.ensureAgent();
544
571
  const projectId = typeof patch.projectId === "string" ? patch.projectId.trim() : "";
545
- if (projectId) {
546
- await this.sessionIndexReady;
547
- await this.sessionIndex?.getStore().resolveTranscriptPath(sessionKey);
548
- new ProjectService().attachSession(sessionKey, projectId);
549
- }
550
572
  const result = await agent.sessionConfig.patch(sessionKey, {
551
573
  model: typeof patch.model === "string" ? patch.model : void 0,
552
574
  thinkingLevel: typeof patch.thinkingLevel === "string" ? patch.thinkingLevel : void 0,
@@ -555,6 +577,28 @@ var EmbeddedBackend = class {
555
577
  workingDirectory: typeof patch.workingDirectory === "string" ? patch.workingDirectory : void 0
556
578
  });
557
579
  if (!result.ok) throw new Error(result.error);
580
+ if (projectId) {
581
+ await this.sessionIndexReady;
582
+ await this.sessionIndex?.getStore().resolveTranscriptPath(sessionKey);
583
+ new ProjectService().attachSession(sessionKey, projectId);
584
+ }
585
+ const hiddenFromSessionList = typeof patch.hiddenFromSessionList === "boolean" ? patch.hiddenFromSessionList : void 0;
586
+ const customData = patch.customData && typeof patch.customData === "object" && !Array.isArray(patch.customData) ? patch.customData : void 0;
587
+ if (hiddenFromSessionList !== void 0 || customData !== void 0) {
588
+ await this.sessionIndexReady;
589
+ const store = this.sessionIndex?.getStore();
590
+ if (store) {
591
+ await store.resolveTranscriptPath(sessionKey);
592
+ const existing = getSessionMetadata(sessionKey);
593
+ if (existing && existing.messageCount === 0) await store.updateMetadata(sessionKey, {
594
+ ...hiddenFromSessionList !== void 0 ? { hiddenFromSessionList } : {},
595
+ ...customData ? { customData: {
596
+ ...existing.customData ?? {},
597
+ ...customData
598
+ } } : {}
599
+ });
600
+ }
601
+ }
558
602
  }
559
603
  async compactSession(sessionKey, options) {
560
604
  if (!this.agent) return {
@@ -1,6 +1,6 @@
1
1
  import type { ExportFormat } from '../../session/types.js';
2
2
  import type { SessionTimelineItem } from '../../session/transcript-outline.js';
3
- import type { ChatSendOptions, HistoryMessage, TuiBackend, TuiCompactionResult, TuiEvent, TuiModelChoice, TuiShareRequest, TuiShareResult, TuiSessionStats, TuiSessionItem, TuiStartupResources, TuiTranscriptTreeEntry, TuiAgentInfo, TuiWorkspaceFileSearchEntry, TuiWorkflowRunStartRequest, TuiWorkflowRunStartResult, TuiStartupProjectResult } from '../tui-backend.js';
3
+ import type { ChatSendOptions, HistoryMessage, TuiBackend, TuiCompactionResult, TuiComposerHistoryItem, TuiEvent, TuiModelChoice, TuiShareRequest, TuiShareResult, TuiSessionStats, TuiSessionItem, TuiStartupResources, TuiTranscriptTreeEntry, TuiAgentInfo, TuiWorkspaceFileSearchEntry, TuiWorkflowRunStartRequest, TuiWorkflowRunStartResult, TuiStartupProjectResult } from '../tui-backend.js';
4
4
  import type { SessionInfo } from '../tui-types.js';
5
5
  import type { ReviewContext } from '../../review/review-git.js';
6
6
  import { type GatewayCredential } from '../../gateway/credential.js';
@@ -33,6 +33,8 @@ export declare class GatewaySseBackend implements TuiBackend {
33
33
  start(): void;
34
34
  stop(): void;
35
35
  getActiveSignal(): AbortSignal | undefined;
36
+ getComposerInputHistory(): Promise<TuiComposerHistoryItem[]>;
37
+ recordComposerInputHistory(text: string): Promise<TuiComposerHistoryItem>;
36
38
  sendChat(opts: ChatSendOptions): Promise<{
37
39
  runId: string;
38
40
  }>;
@@ -80,6 +80,19 @@ var GatewaySseBackend = class {
80
80
  const signal = this.chatAbort?.signal;
81
81
  return signal && !signal.aborted ? signal : void 0;
82
82
  }
83
+ async getComposerInputHistory() {
84
+ const res = await gatewayFetch(this.baseUrl, "/api/composer-history", this.credential);
85
+ if (!res.ok) throw new Error(`Failed to load composer history (${res.status})`);
86
+ return (await res.json()).items ?? [];
87
+ }
88
+ async recordComposerInputHistory(text) {
89
+ const res = await gatewayFetch(this.baseUrl, "/api/composer-history", this.credential, {
90
+ method: "POST",
91
+ body: JSON.stringify({ text })
92
+ });
93
+ if (!res.ok) throw new Error(`Failed to save composer history (${res.status})`);
94
+ return (await res.json()).item;
95
+ }
83
96
  async sendChat(opts) {
84
97
  this.chatAbort?.abort();
85
98
  this.chatAbort = new AbortController();
@@ -793,13 +806,20 @@ var GatewaySseBackend = class {
793
806
  const json = await res.json().catch(() => ({}));
794
807
  if (!res.ok || json.ok === false) throw new Error(json.error ?? `Session config patch failed (${res.status})`);
795
808
  const projectId = typeof patch.projectId === "string" ? patch.projectId.trim() : "";
796
- if (projectId) {
809
+ const hiddenFromSessionList = typeof patch.hiddenFromSessionList === "boolean" ? patch.hiddenFromSessionList : void 0;
810
+ const customData = patch.customData && typeof patch.customData === "object" && !Array.isArray(patch.customData) ? patch.customData : void 0;
811
+ if (projectId || hiddenFromSessionList !== void 0 || customData !== void 0) {
812
+ const metadataPatch = {
813
+ ...projectId ? { projectId } : {},
814
+ ...hiddenFromSessionList !== void 0 ? { hiddenFromSessionList } : {},
815
+ ...customData ? { customData } : {}
816
+ };
797
817
  const metaRes = await gatewayFetch(this.baseUrl, `/api/sessions/${encodeURIComponent(sessionKey)}`, this.credential, {
798
818
  method: "PATCH",
799
- body: JSON.stringify({ projectId })
819
+ body: JSON.stringify(metadataPatch)
800
820
  });
801
821
  const metaJson = await metaRes.json().catch(() => ({}));
802
- if (!metaRes.ok || metaJson.ok === false) throw new Error(metaJson.error ?? `Session project patch failed (${metaRes.status})`);
822
+ if (!metaRes.ok || metaJson.ok === false) throw new Error(metaJson.error ?? `Session metadata patch failed (${metaRes.status})`);
803
823
  }
804
824
  }
805
825
  async renameSession(sessionKey, name) {
@@ -13,5 +13,6 @@ export declare class CustomEditor extends Editor {
13
13
  onExtensionShortcut?: (data: string) => boolean;
14
14
  constructor(tui: TUI, theme: EditorTheme, keybindings: KeybindingsManager, options?: EditorOptions);
15
15
  onAction(action: XopcTuiAppKeybinding, handler: () => void): void;
16
+ replaceHistory(itemsNewestFirst: string[]): void;
16
17
  handleInput(data: string): void;
17
18
  }
@@ -18,6 +18,12 @@ var CustomEditor = class extends Editor {
18
18
  onAction(action, handler) {
19
19
  this.actionHandlers.set(action, handler);
20
20
  }
21
+ replaceHistory(itemsNewestFirst) {
22
+ const internals = this;
23
+ internals.history = itemsNewestFirst.slice(0, 100);
24
+ internals.historyIndex = -1;
25
+ internals.historyDraft = "";
26
+ }
21
27
  handleInput(data) {
22
28
  if (this.onExtensionShortcut?.(data)) return;
23
29
  if (this.keybindings.matches(data, "app.clipboard.pasteImage")) {
@@ -25,6 +25,11 @@ export interface TuiEvent {
25
25
  data: unknown;
26
26
  source?: TuiEventSource;
27
27
  }
28
+ export interface TuiComposerHistoryItem {
29
+ id: number;
30
+ text: string;
31
+ createdAt: number;
32
+ }
28
33
  /** Minimal session list item. */
29
34
  export interface TuiSessionItem {
30
35
  key: string;
@@ -180,6 +185,10 @@ export interface TuiBackend {
180
185
  stop(): void;
181
186
  /** Current active chat abort signal, if a run is in progress. */
182
187
  getActiveSignal?(): AbortSignal | undefined;
188
+ /** Global composer history, shared across sessions and clients. */
189
+ getComposerInputHistory(): Promise<TuiComposerHistoryItem[]>;
190
+ /** Persist one submitted chat input. */
191
+ recordComposerInputHistory(text: string): Promise<TuiComposerHistoryItem>;
183
192
  /** Send a chat message, returns the run id. */
184
193
  sendChat(opts: ChatSendOptions): Promise<{
185
194
  runId: string;
@@ -255,6 +264,8 @@ export interface TuiBackend {
255
264
  getSessionInfo(sessionKey: string): Promise<SessionInfo>;
256
265
  /** List available models. */
257
266
  listModels(): Promise<TuiModelChoice[]>;
267
+ /** Refresh dynamic model catalogs after credentials change. */
268
+ refreshModels?(): Promise<void>;
258
269
  /** Reset / create new session. */
259
270
  resetSession(sessionKey: string): Promise<void>;
260
271
  /** Rename session display name. */
@@ -0,0 +1,11 @@
1
+ import type { TuiBackend } from './tui-backend.js';
2
+ export declare const GENERATED_TUI_SESSION_SHELL_PATCH: {
3
+ readonly hiddenFromSessionList: true;
4
+ readonly customData: {
5
+ readonly genericNewChatShell: true;
6
+ };
7
+ };
8
+ export declare function isGeneratedTuiSessionKey(sessionKey: string): boolean;
9
+ export declare function deleteGeneratedTuiSessionIfEmpty(client: Pick<TuiBackend, 'getSessionStats' | 'deleteSession'>, sessionKey: string): Promise<boolean>;
10
+ export declare function cleanupAbandonedTuiSessions(client: Pick<TuiBackend, 'listSessions' | 'getSessionStats' | 'deleteSession'>, currentSessionKey: string, nowMs?: number): Promise<string[]>;
11
+ export declare function hideLegacyEmptyTuiSessions(client: Pick<TuiBackend, 'listSessions' | 'patchSession'>): Promise<string[]>;
@@ -0,0 +1,37 @@
1
+ import { parseAgentSessionKey } from "../routing/session-key-utils.js";
2
+ import { init_agent_session_key } from "../routing/agent-session-key.js";
3
+ //#region src/tui/tui-empty-session-cleanup.ts
4
+ init_agent_session_key();
5
+ const GENERATED_TUI_SUFFIX_RE = /^tui-[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
6
+ const ABANDONED_SESSION_AGE_MS = 60 * 6e4;
7
+ const GENERATED_TUI_SESSION_SHELL_PATCH = {
8
+ hiddenFromSessionList: true,
9
+ customData: { genericNewChatShell: true }
10
+ };
11
+ function isGeneratedTuiSessionKey(sessionKey) {
12
+ const parsed = parseAgentSessionKey(sessionKey);
13
+ return parsed ? GENERATED_TUI_SUFFIX_RE.test(parsed.rest) : false;
14
+ }
15
+ async function deleteGeneratedTuiSessionIfEmpty(client, sessionKey) {
16
+ if (!isGeneratedTuiSessionKey(sessionKey)) return false;
17
+ if ((await client.getSessionStats(sessionKey)).totalMessages > 0) return false;
18
+ return (await client.deleteSession(sessionKey)).ok;
19
+ }
20
+ async function cleanupAbandonedTuiSessions(client, currentSessionKey, nowMs = Date.now()) {
21
+ const candidates = (await client.listSessions()).filter((session) => session.key !== currentSessionKey && session.messageCount === 0 && typeof session.updatedAt === "number" && session.updatedAt <= nowMs - ABANDONED_SESSION_AGE_MS && isGeneratedTuiSessionKey(session.key));
22
+ const deleted = [];
23
+ for (const session of candidates) if (await deleteGeneratedTuiSessionIfEmpty(client, session.key)) deleted.push(session.key);
24
+ return deleted;
25
+ }
26
+ async function hideLegacyEmptyTuiSessions(client) {
27
+ const sessions = await client.listSessions();
28
+ const hidden = [];
29
+ for (const session of sessions) {
30
+ if (session.messageCount !== 0 || !isGeneratedTuiSessionKey(session.key)) continue;
31
+ await client.patchSession(session.key, GENERATED_TUI_SESSION_SHELL_PATCH);
32
+ hidden.push(session.key);
33
+ }
34
+ return hidden;
35
+ }
36
+ //#endregion
37
+ export { GENERATED_TUI_SESSION_SHELL_PATCH, cleanupAbandonedTuiSessions, deleteGeneratedTuiSessionIfEmpty, hideLegacyEmptyTuiSessions, isGeneratedTuiSessionKey };
@@ -7,6 +7,7 @@ export declare function createEditorSubmitHandler(params: {
7
7
  setText: (value: string) => void;
8
8
  addToHistory: (value: string) => void;
9
9
  };
10
+ recordChatHistory?: (value: string) => void;
10
11
  handleCommand: (value: string) => void | Promise<void>;
11
12
  sendMessage: (value: string) => void | Promise<void>;
12
13
  handleBangLine: (value: string) => void | Promise<void>;
@@ -36,7 +36,7 @@ function createEditorSubmitHandler(params) {
36
36
  params.handleBangLine(raw);
37
37
  return;
38
38
  }
39
- params.editor.addToHistory(value);
39
+ if (rawTrimmed) (params.recordChatHistory ?? params.editor.addToHistory)(rawTrimmed);
40
40
  if (value.startsWith("/")) {
41
41
  params.handleCommand(value);
42
42
  return;
@@ -27,6 +27,7 @@ import { transcriptTreeEntryIdToRowNumber } from "./tui-transcript-tree.js";
27
27
  import { formatTuiCompactionResult, formatTuiShareResult } from "./tui-command-formatters.js";
28
28
  import { formatTuiStartupText } from "./tui-startup-text.js";
29
29
  import { createTuiCommandHandler, getSlashCommands } from "./tui-commands.js";
30
+ import { GENERATED_TUI_SESSION_SHELL_PATCH, cleanupAbandonedTuiSessions, deleteGeneratedTuiSessionIfEmpty, hideLegacyEmptyTuiSessions, isGeneratedTuiSessionKey } from "./tui-empty-session-cleanup.js";
30
31
  import { extensionCustomMessageContentToText, extensionCustomMessageToTurnText, extensionUserMessageContentToText } from "./tui-extension-user-message.js";
31
32
  import { resolveFdPath } from "./tui-fd-path.js";
32
33
  import { drainFollowUpQueue, restoreQueuedMessages } from "./tui-follow-up-queue.js";
@@ -197,6 +198,9 @@ async function runTui(opts) {
197
198
  let tuiSettings = loadTuiSettings();
198
199
  initTuiTheme({ themeId: opts.theme ?? tuiSettings.theme });
199
200
  const state = createInitialState(startup.sessionKey);
201
+ const generatedStartupSessionKey = !opts.session?.trim() && isGeneratedTuiSessionKey(startup.sessionKey) ? startup.sessionKey : null;
202
+ const generatedStartupSessionKeys = new Set(generatedStartupSessionKey ? [generatedStartupSessionKey] : []);
203
+ let startupSessionHadUserTurn = false;
200
204
  const startupWorkingDirectory = resolveStartupWorkingDirectory(opts, isLocalMode);
201
205
  const implicitTrustedWorkspace = startupWorkingDirectory ?? (isLocalMode ? process.cwd() : void 0);
202
206
  const projectTrustStore = new ProjectTrustStore();
@@ -356,6 +360,7 @@ async function runTui(opts) {
356
360
  paddingX: tuiSettings.editorPaddingX,
357
361
  autocompleteMaxVisible: tuiSettings.autocompleteMaxVisible
358
362
  });
363
+ let composerHistoryTexts = [];
359
364
  let editor = defaultEditor;
360
365
  let editorComponentFactory;
361
366
  const editorContainer = new Container();
@@ -417,6 +422,7 @@ async function runTui(opts) {
417
422
  nextEditor.setAutocompleteProvider?.(extensionRuntime.autocompleteProvider);
418
423
  copyDefaultEditorAppHandlers(nextEditor);
419
424
  editor = nextEditor;
425
+ for (const text of composerHistoryTexts.slice().reverse()) editor.addToHistory?.(text);
420
426
  } else {
421
427
  defaultEditor.setText(currentText);
422
428
  editor = defaultEditor;
@@ -947,14 +953,21 @@ async function runTui(opts) {
947
953
  clearInterval(streamWatchdogId);
948
954
  streamWatchdogId = null;
949
955
  }
950
- client.stop();
951
956
  tui.terminal.setProgress(false);
952
- drainAndStopTuiSafely(tui).then(() => {
957
+ (async () => {
958
+ const removedEmptyStartupSessions = /* @__PURE__ */ new Set();
959
+ if (!state.activeRunId) for (const sessionKey of generatedStartupSessionKeys) {
960
+ if (sessionKey === state.currentSessionKey && startupSessionHadUserTurn) continue;
961
+ if (await deleteGeneratedTuiSessionIfEmpty(client, sessionKey).catch(() => false)) removedEmptyStartupSessions.add(sessionKey);
962
+ }
963
+ client.stop();
964
+ await drainAndStopTuiSafely(tui);
953
965
  restoreStdio();
954
- if (options?.showResumeHint !== false) process.stdout.write(`\nTo resume this session: ${formatTuiResumeCommand(opts, state.currentSessionKey)}\n`);
966
+ const currentSessionWasRemoved = removedEmptyStartupSessions.has(state.currentSessionKey);
967
+ if (options?.showResumeHint !== false && !currentSessionWasRemoved) process.stdout.write(`\nTo resume this session: ${formatTuiResumeCommand(opts, state.currentSessionKey)}\n`);
955
968
  finishTui?.();
956
969
  process.exit(0);
957
- });
970
+ })();
958
971
  };
959
972
  const { refreshSessionInfo, loadHistory: loadSessionHistory, loadHistoryWindow, setSession, abortActive, resetCurrentSession, clearChatForSessionSwitch } = createSessionActions({
960
973
  client,
@@ -1001,7 +1014,10 @@ async function runTui(opts) {
1001
1014
  const applyStartupWorkingDirectory = async () => {
1002
1015
  if (startupWorkingDirectoryApplied || !startupWorkingDirectory) return;
1003
1016
  startupWorkingDirectoryApplied = true;
1004
- await client.patchSession(state.currentSessionKey, { workingDirectory: startupWorkingDirectory });
1017
+ await client.patchSession(state.currentSessionKey, {
1018
+ workingDirectory: startupWorkingDirectory,
1019
+ ...isGeneratedTuiSessionKey(state.currentSessionKey) ? GENERATED_TUI_SESSION_SHELL_PATCH : {}
1020
+ });
1005
1021
  state.sessionInfo.effectiveWorkspacePath = startupWorkingDirectory;
1006
1022
  state.sessionInfo.workingDirectoryLocked = true;
1007
1023
  };
@@ -1018,15 +1034,22 @@ async function runTui(opts) {
1018
1034
  const projectAgentId = result.project.defaultAgentId?.trim() ? normalizeAgentId(result.project.defaultAgentId) : void 0;
1019
1035
  const currentParsed = parseAgentSessionKey(state.currentSessionKey);
1020
1036
  if (!opts.agentId?.trim() && currentParsed?.rest && projectAgentId && projectAgentId !== currentAgentId) {
1021
- await setSession(`agent:${projectAgentId}:${currentParsed.rest}`);
1037
+ const targetSessionKey = `agent:${projectAgentId}:${currentParsed.rest}`;
1038
+ await setSession(targetSessionKey);
1039
+ if (isGeneratedTuiSessionKey(targetSessionKey)) generatedStartupSessionKeys.add(targetSessionKey);
1022
1040
  currentAgentId = projectAgentId;
1041
+ if (isGeneratedTuiSessionKey(state.currentSessionKey)) await client.patchSession(state.currentSessionKey, GENERATED_TUI_SESSION_SHELL_PATCH);
1023
1042
  await client.patchSession(state.currentSessionKey, {
1024
1043
  projectId: result.project.id,
1025
- workingDirectory: startupWorkingDirectory
1044
+ workingDirectory: startupWorkingDirectory,
1045
+ ...isGeneratedTuiSessionKey(state.currentSessionKey) ? GENERATED_TUI_SESSION_SHELL_PATCH : {}
1026
1046
  });
1027
1047
  state.sessionInfo.effectiveWorkspacePath = startupWorkingDirectory;
1028
1048
  state.sessionInfo.workingDirectoryLocked = true;
1029
- } else await client.patchSession(state.currentSessionKey, { projectId: result.project.id });
1049
+ } else await client.patchSession(state.currentSessionKey, {
1050
+ projectId: result.project.id,
1051
+ ...isGeneratedTuiSessionKey(state.currentSessionKey) ? GENERATED_TUI_SESSION_SHELL_PATCH : {}
1052
+ });
1030
1053
  const verb = result.created ? "Created project" : "Using project";
1031
1054
  chatLog.addStatus(theme.dim(`${verb}: ${result.project.name}`));
1032
1055
  };
@@ -1458,6 +1481,7 @@ async function runTui(opts) {
1458
1481
  return;
1459
1482
  }
1460
1483
  chatLog.addUser(userDisplayContentForAttachments(text, attachments));
1484
+ startupSessionHadUserTurn = true;
1461
1485
  sessionSnapshot.appendMessage("user", messageText);
1462
1486
  lastRetryMessageText = messageText;
1463
1487
  markRunSending(state);
@@ -1682,14 +1706,18 @@ async function runTui(opts) {
1682
1706
  getEntry: () => projectTrustStore.getEntry(process.cwd()),
1683
1707
  getSessionDecision: () => projectTrustSessionDecision
1684
1708
  },
1685
- runLogin: (provider) => runTuiOAuthLogin(provider, {
1686
- chatLog,
1687
- tui,
1688
- editor,
1689
- openOverlay: openCommandOverlay,
1690
- closeOverlay: closeCommandOverlay,
1691
- keybindings
1692
- })
1709
+ runLogin: async (provider) => {
1710
+ await runTuiOAuthLogin(provider, {
1711
+ chatLog,
1712
+ tui,
1713
+ editor,
1714
+ openOverlay: openCommandOverlay,
1715
+ closeOverlay: closeCommandOverlay,
1716
+ keybindings
1717
+ });
1718
+ await client.refreshModels?.();
1719
+ await refreshModelChoices();
1720
+ }
1693
1721
  });
1694
1722
  const { runLocalShellLine } = createLocalShellRunner({
1695
1723
  chatLog,
@@ -1736,12 +1764,48 @@ async function runTui(opts) {
1736
1764
  updateFooter();
1737
1765
  tui.requestRender();
1738
1766
  };
1767
+ let composerHistory = [];
1768
+ let composerHistoryWriteQueue = Promise.resolve();
1769
+ const applyComposerHistory = (next) => {
1770
+ composerHistory = next.slice(0, 100);
1771
+ composerHistoryTexts = composerHistory.map((item) => item.text);
1772
+ if (editor === defaultEditor) {
1773
+ defaultEditor.replaceHistory(composerHistory.map((item) => item.text));
1774
+ return;
1775
+ }
1776
+ for (const item of composerHistory.slice().reverse()) editor.addToHistory?.(item.text);
1777
+ };
1778
+ const refreshComposerHistory = async () => {
1779
+ try {
1780
+ await composerHistoryWriteQueue;
1781
+ applyComposerHistory(await client.getComposerInputHistory());
1782
+ } catch {}
1783
+ };
1784
+ const recordChatHistory = (value) => {
1785
+ const text = value.trim();
1786
+ if (!text) return;
1787
+ editor.addToHistory?.(text);
1788
+ if (composerHistory[0]?.text !== text) {
1789
+ composerHistory = [{
1790
+ id: 0,
1791
+ text,
1792
+ createdAt: Date.now()
1793
+ }, ...composerHistory].slice(0, 100);
1794
+ composerHistoryTexts = composerHistory.map((item) => item.text);
1795
+ }
1796
+ composerHistoryWriteQueue = composerHistoryWriteQueue.then(async () => {
1797
+ const item = await client.recordComposerInputHistory(text);
1798
+ const optimisticIndex = composerHistory.findIndex((entry) => entry.id === 0 && entry.text === item.text);
1799
+ if (optimisticIndex >= 0) composerHistory[optimisticIndex] = item;
1800
+ }).catch(() => {});
1801
+ };
1739
1802
  const submitBurst = createSubmitBurstCoalescer({
1740
1803
  submit: createEditorSubmitHandler({
1741
1804
  editor: {
1742
1805
  setText: (value) => editor.setText(value),
1743
1806
  addToHistory: (value) => editor.addToHistory?.(value)
1744
1807
  },
1808
+ recordChatHistory: (value) => recordChatHistory(value),
1745
1809
  handleCommand,
1746
1810
  sendMessage,
1747
1811
  handleBangLine: runLocalShellLine,
@@ -1772,7 +1836,7 @@ async function runTui(opts) {
1772
1836
  tui.requestRender();
1773
1837
  return;
1774
1838
  }
1775
- editor.addToHistory(text);
1839
+ recordChatHistory(text);
1776
1840
  state.messageFollowUpQueue.push(text);
1777
1841
  editor.setText("");
1778
1842
  chatLog.addSystem(theme.dim(`Queued follow-up (${state.messageFollowUpQueue.length} in queue). ${tuiSettings.followUpMode === "all" ? "All queued messages send together when this reply finishes." : "Next sends when this reply finishes."}`));
@@ -2026,6 +2090,23 @@ async function runTui(opts) {
2026
2090
  };
2027
2091
  client.onEvent = (evt) => {
2028
2092
  const data = evt.data ?? {};
2093
+ if (evt.event === "composer-history.appended") {
2094
+ const item = data;
2095
+ if (typeof item.text === "string" && typeof item.id === "number") {
2096
+ const optimisticIndex = composerHistory.findIndex((entry) => entry.id === 0 && entry.text === item.text);
2097
+ if (optimisticIndex >= 0) composerHistory[optimisticIndex] = item;
2098
+ else if (composerHistory[0]?.text !== item.text) {
2099
+ composerHistory = [item, ...composerHistory].slice(0, 100);
2100
+ composerHistoryTexts = composerHistory.map((entry) => entry.text);
2101
+ editor.addToHistory?.(item.text);
2102
+ } else composerHistory[0] = item;
2103
+ }
2104
+ return;
2105
+ }
2106
+ if (evt.event === "composer-history.cleared") {
2107
+ applyComposerHistory([]);
2108
+ return;
2109
+ }
2029
2110
  if (evt.event === "workflow.run.updated" && handleWorkflowRunUpdated(data)) return;
2030
2111
  dispatchAgentEvent(evt.event, data, state, chatLog, tui, setActivityStatus, touchStreamingActivity, onAgentRunEnded, (message) => sessionSnapshot.appendMessage("assistant", assistantMessagePlainText(message)), evt.source);
2031
2112
  };
@@ -2035,6 +2116,7 @@ async function runTui(opts) {
2035
2116
  setConnectionStatus(isLocalMode ? "local ready" : "gateway connected");
2036
2117
  touchStreamingActivity();
2037
2118
  (async () => {
2119
+ await refreshComposerHistory();
2038
2120
  if (opts.openSessionPickerOnStart && !startupSessionPickerOpened) {
2039
2121
  startupSessionPickerOpened = true;
2040
2122
  await openSessionPickerOverlay(pickerSvc, {
@@ -2064,6 +2146,7 @@ async function runTui(opts) {
2064
2146
  await refreshSessionInfoWithBorder();
2065
2147
  await refreshModelChoices();
2066
2148
  await loadSessionHistory({ merge: true });
2149
+ cleanupAbandonedTuiSessions(client, state.currentSessionKey).then(() => hideLegacyEmptyTuiSessions(client)).catch(() => {});
2067
2150
  showStartupCardOnce();
2068
2151
  refreshStartupResources().then(() => {
2069
2152
  updateFooter();
@@ -2098,6 +2181,7 @@ async function runTui(opts) {
2098
2181
  setConnectionStatus(`event gap: expected ${info.expected}, got ${info.received}`);
2099
2182
  if (state.activeRunId) recoverActiveRunFromHistory("broadcast event gap");
2100
2183
  else loadSessionHistory({ merge: true });
2184
+ refreshComposerHistory();
2101
2185
  tui.requestRender();
2102
2186
  };
2103
2187
  const sigintHandler = () => handleCtrlC();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xopcai/xopc",
3
- "version": "0.0.167",
3
+ "version": "0.0.169",
4
4
  "description": "Local-first AI system that remembers context, coordinates AI, and sustains long-term progress.",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",