@xopcai/xopc 0.0.196 → 0.0.197

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 (140) 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/{agent-avatar-dicebear-B1oxPli_.js → agent-avatar-dicebear-C5st7lt5.js} +1 -1
  4. package/dist/gateway/static/root/assets/agents-Baxfj44y.js +68 -0
  5. package/dist/gateway/static/root/assets/{app-management-settings-panel-vmuJ_Z6i.js → app-management-settings-panel-S8LhoD6G.js} +1 -1
  6. package/dist/gateway/static/root/assets/{appearance-settings-BMlEoe-G.js → appearance-settings-D8Cd5vDP.js} +1 -1
  7. package/dist/gateway/static/root/assets/apps-page-0uCxKyE5.js +1 -0
  8. package/dist/gateway/static/root/assets/{archive-plugin-BdE4Mati.js → archive-plugin-qL07mwnY.js} +1 -1
  9. package/dist/gateway/static/root/assets/{attachment-load-CTzaQcLV.js → attachment-load-CqSobpdi.js} +1 -1
  10. package/dist/gateway/static/root/assets/automations-page-XyDat125.js +6 -0
  11. package/dist/gateway/static/root/assets/{binary-plugins-B25zTNxl.js → binary-plugins-DBRPyLYE.js} +1 -1
  12. package/dist/gateway/static/root/assets/{block-editor-Cdrf2awF.js → block-editor-6wG1LU7t.js} +46 -46
  13. package/dist/gateway/static/root/assets/{browser-settings-page-BMTmGMM6.js → browser-settings-page-CrYNMR4w.js} +4 -4
  14. package/dist/gateway/static/root/assets/{browser-workflow-inputs-BsmHy0ks.js → browser-workflow-inputs-Abil4puY.js} +1 -1
  15. package/dist/gateway/static/root/assets/{browser-workflows-page-Wx9FrbK-.js → browser-workflows-page-BEu3E0et.js} +1 -1
  16. package/dist/gateway/static/root/assets/capabilities-settings-panel-CvMcDhGf.js +7 -0
  17. package/dist/gateway/static/root/assets/{capability-presets-settings-panel-9T2KXAs1.js → capability-presets-settings-panel-CHJDY-Ih.js} +2 -2
  18. package/dist/gateway/static/root/assets/{channels-settings-DquD4BPQ.js → channels-settings-Ds9BJbcY.js} +1 -1
  19. package/dist/gateway/static/root/assets/{connectors-api-BC-4ftOM.js → connectors-api-CgWjgPSI.js} +1 -1
  20. package/dist/gateway/static/root/assets/connectors-page-NUs-Zf7F.js +2 -0
  21. package/dist/gateway/static/root/assets/{cron-expression-BycQlU8Q.js → cron-expression-ZdDBAoqA.js} +1 -1
  22. package/dist/gateway/static/root/assets/{dependency-picker-BvYqHRz0.js → dependency-picker-BGeB1jpn.js} +1 -1
  23. package/dist/gateway/static/root/assets/{desktop-pet-BOb8sEhN.js → desktop-pet-CsLR4pWB.js} +1 -1
  24. package/dist/gateway/static/root/assets/{desktop-pet-settings-DStgPb82.js → desktop-pet-settings-CCjT1bdo.js} +1 -1
  25. package/dist/gateway/static/root/assets/directory-picker-path-field-C-Te1QN3.js +1 -0
  26. package/dist/gateway/static/root/assets/{extension-debug-page-p83TmZFd.js → extension-debug-page-CD73euAM.js} +1 -1
  27. package/dist/gateway/static/root/assets/{extension-page-DMQ3ovxA.js → extension-page-DAKjpNwd.js} +1 -1
  28. package/dist/gateway/static/root/assets/{extension-settings-page-BcSKEU8s.js → extension-settings-page-BLSNdlgd.js} +1 -1
  29. package/dist/gateway/static/root/assets/{gateway-config-api-C-MmtCc7.js → gateway-config-api-CQrf0k3D.js} +1 -1
  30. package/dist/gateway/static/root/assets/{gateway-settings-CuaRDWbg.js → gateway-settings-CvgH8IJI.js} +1 -1
  31. package/dist/gateway/static/root/assets/{heartbeat-settings-Dm8TrfGa.js → heartbeat-settings-SPpnqbjl.js} +1 -1
  32. package/dist/gateway/static/root/assets/home-page-BFoD6047.js +3 -0
  33. package/dist/gateway/static/root/assets/index-84ys9u-K.js +152 -0
  34. package/dist/gateway/static/root/assets/index-D-srnucP.css +1 -0
  35. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BQb06_jl.js → keyboard-shortcuts-settings-HMhxgOuD.js} +1 -1
  36. package/dist/gateway/static/root/assets/local-app-workbench-page-D5uL2_Fd.js +2 -0
  37. package/dist/gateway/static/root/assets/{local-apps-page-DQtsxjGs.js → local-apps-page-DIWkFa3g.js} +1 -1
  38. package/dist/gateway/static/root/assets/{logs-page-CDqIY72S.js → logs-page--6v8qq6y.js} +2 -2
  39. package/dist/gateway/static/root/assets/{management-settings-D7itDEHl.js → management-settings-DtEuS-kR.js} +1 -1
  40. package/dist/gateway/static/root/assets/{markdown-split-Db-KrpOQ.js → markdown-split-DvVBewS4.js} +1 -1
  41. package/dist/gateway/static/root/assets/{media-plugins-CHN66qs0.js → media-plugins-YVj7NVzD.js} +1 -1
  42. package/dist/gateway/static/root/assets/{notes-page-CJtKZM0P.js → notes-page-BDzuL2I9.js} +1 -1
  43. package/dist/gateway/static/root/assets/notes-workbench-IdjuNXvH.js +4 -0
  44. package/dist/gateway/static/root/assets/{page-tabs-HXweXqYE.js → page-tabs-7bSEWfSX.js} +1 -1
  45. package/dist/gateway/static/root/assets/{preview-open-alternatives-Dob6Oe2l.js → preview-open-alternatives-tgLbHgcV.js} +1 -1
  46. package/dist/gateway/static/root/assets/{product-open-page--RnCc9bb.js → product-open-page-Bwx_CQht.js} +1 -1
  47. package/dist/gateway/static/root/assets/project-detail-page-DnJXSuM4.js +1 -0
  48. package/dist/gateway/static/root/assets/projects-page-DckZKlBI.js +1 -0
  49. package/dist/gateway/static/root/assets/remote-access-hub-CfbUHBUH.js +1 -0
  50. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-Bg1W2__k.js → runtime-tools-settings-panel-Fe05Nus6.js} +1 -1
  51. package/dist/gateway/static/root/assets/{schema-form-BI4rVt3u.js → schema-form-CFfyC4CB.js} +1 -1
  52. package/dist/gateway/static/root/assets/sessions-page-BCfCh4My.js +1 -0
  53. package/dist/gateway/static/root/assets/settings-advanced-gate-Cbi4FvzO.js +1 -0
  54. package/dist/gateway/static/root/assets/{settings-form-section-C7rzhi7x.js → settings-form-section-gEnEYT_3.js} +1 -1
  55. package/dist/gateway/static/root/assets/{settings-loading-skeleton-BS36Mjzz.js → settings-loading-skeleton-BRE_-7Da.js} +1 -1
  56. package/dist/gateway/static/root/assets/{settings-page-BDSd7F9Y.js → settings-page-C1zxCpqB.js} +1 -1
  57. package/dist/gateway/static/root/assets/{settings-page-layout-CTMmZcwj.js → settings-page-layout-CRpXF_05.js} +1 -1
  58. package/dist/gateway/static/root/assets/setup-status-panel-BcHdpmFf.js +1 -0
  59. package/dist/gateway/static/root/assets/{share-preview-page-BeCxg6eb.js → share-preview-page-DU8L68A5.js} +1 -1
  60. package/dist/gateway/static/root/assets/{shares-settings-CXL1EldF.js → shares-settings-kjTqH9yY.js} +1 -1
  61. package/dist/gateway/static/root/assets/skill-reload-api-QAGpwzIM.js +1 -0
  62. package/dist/gateway/static/root/assets/{skills-page-CyfjEM4D.js → skills-page-lE1-YRdK.js} +1 -1
  63. package/dist/gateway/static/root/assets/{skills-page.utils-CnbJncdL.js → skills-page.utils-CYwFWTso.js} +1 -1
  64. package/dist/gateway/static/root/assets/{system-settings-panel-CAv0Yk0Y.js → system-settings-panel-CVDsiPKn.js} +1 -1
  65. package/dist/gateway/static/root/assets/task-detail-page-DsM13-cy.js +1 -0
  66. package/dist/gateway/static/root/assets/{typed-models-lib-DomX3Szl.js → typed-models-lib-DelyYgoc.js} +1 -1
  67. package/dist/gateway/static/root/assets/{use-autosave-BLc4gfG0.js → use-autosave-C50Mq5yQ.js} +1 -1
  68. package/dist/gateway/static/root/assets/{user-context-page-C2kQENTK.js → user-context-page-D-VEOt2A.js} +1 -1
  69. package/dist/gateway/static/root/assets/{voice-api-key-field-BijmpPjb.js → voice-api-key-field-DYfgTe3Y.js} +1 -1
  70. package/dist/gateway/static/root/assets/{work-discovery-overlay-D7w2JFFq.js → work-discovery-overlay-DPbujsp3.js} +1 -1
  71. package/dist/gateway/static/root/assets/work-discovery-page-D77opady.js +1 -0
  72. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-BEmugHfL.js → workflow-run-setup-panel-DqIb1oBB.js} +2 -2
  73. package/dist/gateway/static/root/assets/workflows-page-B9-PLmlX.js +5 -0
  74. package/dist/gateway/static/root/index.html +2 -2
  75. package/dist/package.js +1 -1
  76. package/dist/src/agent/embedded/execution-context.d.ts +2 -0
  77. package/dist/src/agent/embedded/execution-context.js +11 -0
  78. package/dist/src/agent/embedded/index.d.ts +3 -1
  79. package/dist/src/agent/embedded/index.js +5 -3
  80. package/dist/src/agent/embedded/run-turn.js +15 -9
  81. package/dist/src/agent/embedded/session-runner.d.ts +6 -11
  82. package/dist/src/agent/embedded/session-runner.js +25 -36
  83. package/dist/src/agent/embedded/transcript-runtime.d.ts +35 -0
  84. package/dist/src/agent/embedded/transcript-runtime.js +66 -0
  85. package/dist/src/agent/embedded/types.d.ts +3 -1
  86. package/dist/src/agent/service.d.ts +15 -0
  87. package/dist/src/agent/service.js +30 -0
  88. package/dist/src/config/agent-profile.js +1 -1
  89. package/dist/src/gateway/agents-admin.js +1 -1
  90. package/dist/src/gateway/hono/routes/home.d.ts +1 -1
  91. package/dist/src/gateway/hono/routes/home.js +2 -2
  92. package/dist/src/gateway/hono/routes/index.js +2 -0
  93. package/dist/src/gateway/hono/routes/projects.js +12 -1
  94. package/dist/src/gateway/hono/routes/side-chats.d.ts +3 -0
  95. package/dist/src/gateway/hono/routes/side-chats.js +173 -0
  96. package/dist/src/gateway/service/agent-runner.d.ts +4 -0
  97. package/dist/src/gateway/service/agent-runner.js +15 -1
  98. package/dist/src/gateway/service/run-gateway-agent.js +1 -1
  99. package/dist/src/gateway/service.d.ts +4 -0
  100. package/dist/src/gateway/service.js +33 -7
  101. package/dist/src/gateway/side-chat/context-snapshot.d.ts +11 -0
  102. package/dist/src/gateway/side-chat/context-snapshot.js +108 -0
  103. package/dist/src/gateway/side-chat/index.d.ts +5 -0
  104. package/dist/src/gateway/side-chat/index.js +4 -0
  105. package/dist/src/gateway/side-chat/manager.d.ts +45 -0
  106. package/dist/src/gateway/side-chat/manager.js +198 -0
  107. package/dist/src/gateway/side-chat/run-service.d.ts +22 -0
  108. package/dist/src/gateway/side-chat/run-service.js +110 -0
  109. package/dist/src/gateway/side-chat/types.d.ts +61 -0
  110. package/dist/src/gateway/side-chat/types.js +1 -0
  111. package/dist/src/routing/session-key-utils.d.ts +0 -1
  112. package/dist/src/routing/session-key-utils.js +1 -6
  113. package/dist/src/routing/session-key.js +2 -2
  114. package/dist/src/tasks/home-query-service.d.ts +24 -0
  115. package/dist/src/tasks/home-query-service.js +284 -5
  116. package/dist/src/tasks/index.js +3 -3
  117. package/dist/src/tasks/project-operating-view-service.d.ts +2 -1
  118. package/dist/src/tasks/project-operating-view-service.js +27 -4
  119. package/package.json +2 -2
  120. package/dist/gateway/static/root/assets/agents-VoFNMGL3.js +0 -68
  121. package/dist/gateway/static/root/assets/apps-page-CsNB6mv_.js +0 -1
  122. package/dist/gateway/static/root/assets/automations-page-CW1YWgiX.js +0 -6
  123. package/dist/gateway/static/root/assets/capabilities-settings-panel-C5l85__e.js +0 -7
  124. package/dist/gateway/static/root/assets/connectors-page-7zUxVHQg.js +0 -2
  125. package/dist/gateway/static/root/assets/directory-picker-path-field-DUUr9sq0.js +0 -1
  126. package/dist/gateway/static/root/assets/home-page-BYhDbUvI.js +0 -3
  127. package/dist/gateway/static/root/assets/index-BzPwnXho.js +0 -150
  128. package/dist/gateway/static/root/assets/index-CFFYvilx.css +0 -1
  129. package/dist/gateway/static/root/assets/local-app-workbench-page-CHk4x0kR.js +0 -2
  130. package/dist/gateway/static/root/assets/notes-workbench-epHGeKd5.js +0 -4
  131. package/dist/gateway/static/root/assets/project-detail-page-BxOD5-zj.js +0 -1
  132. package/dist/gateway/static/root/assets/projects-page-D-9AhrH5.js +0 -1
  133. package/dist/gateway/static/root/assets/remote-access-hub-CSUNXLKM.js +0 -1
  134. package/dist/gateway/static/root/assets/sessions-page-BxOUBMca.js +0 -1
  135. package/dist/gateway/static/root/assets/settings-advanced-gate-DAvTIbgw.js +0 -1
  136. package/dist/gateway/static/root/assets/setup-status-panel-D1v-2Ci-.js +0 -1
  137. package/dist/gateway/static/root/assets/skill-reload-api-BxwkKgVw.js +0 -1
  138. package/dist/gateway/static/root/assets/task-detail-page-DGTVJs_N.js +0 -1
  139. package/dist/gateway/static/root/assets/work-discovery-page-XtoPgPUS.js +0 -1
  140. package/dist/gateway/static/root/assets/workflows-page-D_K2xOWq.js +0 -5
@@ -0,0 +1,198 @@
1
+ import { createLogger } from "../../utils/logger/index.js";
2
+ import { init_logger } from "../../utils/logger.js";
3
+ import { evictEmbeddedSessionRunner } from "../../agent/embedded/session-runner.js";
4
+ import { InMemoryTranscriptRuntime } from "../../agent/embedded/transcript-runtime.js";
5
+ import { createSideChatContextSnapshot, formatSideChatSelections, validateSideChatSelections } from "./context-snapshot.js";
6
+ import { randomUUID } from "node:crypto";
7
+ //#region src/gateway/side-chat/manager.ts
8
+ init_logger();
9
+ const DEFAULT_IDLE_TTL_MS = 1800 * 1e3;
10
+ const DEFAULT_MAX_PER_CLIENT = 5;
11
+ const DEFAULT_MAX_TOTAL = 50;
12
+ const log = createLogger("Gateway:SideChat");
13
+ var SideChatError = class extends Error {
14
+ constructor(message, code) {
15
+ super(message);
16
+ this.code = code;
17
+ }
18
+ };
19
+ var EphemeralSideChatManager = class {
20
+ entries = /* @__PURE__ */ new Map();
21
+ now;
22
+ idleTtlMs;
23
+ maxPerClient;
24
+ maxTotal;
25
+ sweepTimer;
26
+ constructor(options) {
27
+ this.options = options;
28
+ this.now = options.now ?? Date.now;
29
+ this.idleTtlMs = options.idleTtlMs ?? DEFAULT_IDLE_TTL_MS;
30
+ this.maxPerClient = options.maxPerClient ?? DEFAULT_MAX_PER_CLIENT;
31
+ this.maxTotal = options.maxTotal ?? DEFAULT_MAX_TOTAL;
32
+ this.sweepTimer = options.startSweepTimer === false ? null : setInterval(() => {
33
+ this.sweepExpired().catch((err) => {
34
+ log.warn({
35
+ err,
36
+ phase: "side_chat_sweep"
37
+ }, "Side chat expiry sweep failed");
38
+ });
39
+ }, Math.min(this.idleTtlMs, 6e4));
40
+ this.sweepTimer?.unref();
41
+ }
42
+ async create(input) {
43
+ const parentSessionKey = input.parentSessionKey.trim();
44
+ const clientInstanceId = input.clientInstanceId.trim();
45
+ if (!parentSessionKey || !clientInstanceId) throw new SideChatError("parentSessionKey and clientInstanceId are required", "INVALID_REQUEST");
46
+ if (this.entries.size >= this.maxTotal) throw new SideChatError("The side chat capacity has been reached", "LIMIT_REACHED");
47
+ if ([...this.entries.values()].filter((entry) => entry.clientInstanceId === clientInstanceId).length >= this.maxPerClient) throw new SideChatError(`A client can have at most ${this.maxPerClient} side chats`, "LIMIT_REACHED");
48
+ const metadata = await this.options.getParentMetadata(parentSessionKey);
49
+ if (!metadata || !metadata.sessionId) throw new SideChatError("Parent session not found", "NOT_FOUND");
50
+ const parentMessages = await this.options.loadParentMessages(parentSessionKey);
51
+ let selections;
52
+ try {
53
+ selections = validateSideChatSelections(input.selections);
54
+ } catch (error) {
55
+ throw new SideChatError(error instanceof Error ? error.message : "Invalid selections", "INVALID_REQUEST");
56
+ }
57
+ const now = this.now();
58
+ const createdAt = new Date(now).toISOString();
59
+ const id = randomUUID();
60
+ const runtime = new InMemoryTranscriptRuntime({
61
+ runtimeId: `${parentSessionKey}:side-chat:${id}`,
62
+ cwd: this.options.getWorkspacePath(metadata),
63
+ initialMessages: structuredClone(parentMessages)
64
+ });
65
+ const selectionContext = formatSideChatSelections(selections);
66
+ if (selectionContext) runtime.openSessionManager(this.options.getWorkspacePath(metadata)).appendCustomMessageEntry("side-chat-selection", selectionContext, false);
67
+ runtime.captureBaseline();
68
+ const config = {
69
+ modelRef: normalizeOptionalString(input.config?.modelRef) || this.options.getDefaultModelRef(parentSessionKey),
70
+ thinkingLevel: input.config?.thinkingLevel
71
+ };
72
+ const entry = {
73
+ id,
74
+ parentSessionKey,
75
+ clientInstanceId,
76
+ status: "idle",
77
+ createdAt,
78
+ lastActiveAt: createdAt,
79
+ expiresAt: new Date(now + this.idleTtlMs).toISOString(),
80
+ messageCount: 0,
81
+ context: createSideChatContextSnapshot({
82
+ parentSessionKey,
83
+ parentSessionId: metadata.sessionId,
84
+ parentMessages,
85
+ selections,
86
+ createdAt
87
+ }),
88
+ config,
89
+ runtime
90
+ };
91
+ this.entries.set(id, entry);
92
+ return toView(entry);
93
+ }
94
+ get(id, clientInstanceId) {
95
+ return toView(this.requireEntry(id, clientInstanceId));
96
+ }
97
+ getRuntime(id, clientInstanceId) {
98
+ return this.requireEntry(id, clientInstanceId).runtime;
99
+ }
100
+ getMessages(id, clientInstanceId) {
101
+ const entry = this.requireEntry(id, clientInstanceId);
102
+ const messages = entry.runtime.loadConversationMessages();
103
+ entry.messageCount = messages.length;
104
+ return structuredClone(messages);
105
+ }
106
+ updateConfig(id, clientInstanceId, patch) {
107
+ const entry = this.requireEntry(id, clientInstanceId);
108
+ if (entry.status === "running") throw new SideChatError("Cannot change config while a run is active", "CONFLICT");
109
+ const modelRef = patch.modelRef === void 0 ? entry.config.modelRef : normalizeOptionalString(patch.modelRef);
110
+ if (!modelRef) throw new SideChatError("modelRef cannot be empty", "INVALID_REQUEST");
111
+ entry.config = {
112
+ modelRef,
113
+ thinkingLevel: patch.thinkingLevel === void 0 ? entry.config.thinkingLevel : patch.thinkingLevel
114
+ };
115
+ this.touchEntry(entry);
116
+ return toView(entry);
117
+ }
118
+ heartbeat(id, clientInstanceId) {
119
+ const entry = this.requireEntry(id, clientInstanceId);
120
+ this.touchEntry(entry);
121
+ return toView(entry);
122
+ }
123
+ setStatus(id, clientInstanceId, status) {
124
+ const entry = this.requireEntry(id, clientInstanceId);
125
+ entry.status = status;
126
+ this.touchEntry(entry);
127
+ return toView(entry);
128
+ }
129
+ async dispose(id, clientInstanceId) {
130
+ const entry = this.entries.get(id);
131
+ if (!entry || entry.clientInstanceId !== clientInstanceId) return false;
132
+ entry.status = "closing";
133
+ await this.runBeforeDispose(id, clientInstanceId);
134
+ this.entries.delete(id);
135
+ await evictEmbeddedSessionRunner(entry.runtime.runtimeId, "side_chat_dispose");
136
+ return true;
137
+ }
138
+ async disposeClient(clientInstanceId) {
139
+ const ids = [...this.entries.values()].filter((entry) => entry.clientInstanceId === clientInstanceId).map((entry) => entry.id);
140
+ await Promise.all(ids.map((id) => this.dispose(id, clientInstanceId)));
141
+ return ids.length;
142
+ }
143
+ async sweepExpired(at = this.now()) {
144
+ const expired = [...this.entries.values()].filter((entry) => Date.parse(entry.expiresAt) <= at);
145
+ await Promise.all(expired.map((entry) => this.dispose(entry.id, entry.clientInstanceId)));
146
+ return expired.length;
147
+ }
148
+ async disposeAll() {
149
+ if (this.sweepTimer) clearInterval(this.sweepTimer);
150
+ const entries = [...this.entries.values()];
151
+ await Promise.all(entries.map((entry) => this.runBeforeDispose(entry.id, entry.clientInstanceId)));
152
+ this.entries.clear();
153
+ await Promise.all(entries.map((entry) => evictEmbeddedSessionRunner(entry.runtime.runtimeId, "side_chat_shutdown")));
154
+ }
155
+ requireEntry(id, clientInstanceId) {
156
+ const entry = this.entries.get(id);
157
+ if (!entry || entry.clientInstanceId !== clientInstanceId) throw new SideChatError("Side chat not found", "NOT_FOUND");
158
+ return entry;
159
+ }
160
+ touchEntry(entry) {
161
+ const now = this.now();
162
+ entry.lastActiveAt = new Date(now).toISOString();
163
+ entry.expiresAt = new Date(now + this.idleTtlMs).toISOString();
164
+ }
165
+ async runBeforeDispose(id, clientInstanceId) {
166
+ try {
167
+ await this.options.onBeforeDispose?.(id, clientInstanceId);
168
+ } catch (err) {
169
+ log.warn({
170
+ err,
171
+ sideChatId: id,
172
+ phase: "side_chat_abort"
173
+ }, "Side chat run cleanup failed");
174
+ }
175
+ }
176
+ };
177
+ function toView(entry) {
178
+ const { runtime: _runtime, ...view } = entry;
179
+ return structuredClone(view);
180
+ }
181
+ function normalizeOptionalString(value) {
182
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
183
+ }
184
+ function parseThinkingLevel(value) {
185
+ if (value === void 0 || value === null || value === "") return void 0;
186
+ if (typeof value !== "string" || !new Set([
187
+ "off",
188
+ "minimal",
189
+ "low",
190
+ "medium",
191
+ "high",
192
+ "xhigh",
193
+ "max"
194
+ ]).has(value)) throw new SideChatError("Invalid thinkingLevel", "INVALID_REQUEST");
195
+ return value;
196
+ }
197
+ //#endregion
198
+ export { EphemeralSideChatManager, SideChatError, parseThinkingLevel };
@@ -0,0 +1,22 @@
1
+ import type { AgentService } from '../../agent/service.js';
2
+ import type { GatewayAgentRunner } from '../service/agent-runner.js';
3
+ import { type EphemeralSideChatManager } from './manager.js';
4
+ export interface SideChatRunServiceOptions {
5
+ manager: EphemeralSideChatManager;
6
+ getAgentService: () => AgentService;
7
+ agentRunner: GatewayAgentRunner;
8
+ publishRealtime: (topic: string, event: string, data: unknown) => void;
9
+ completeRealtimeTopic: (topic: string) => void;
10
+ }
11
+ export declare class SideChatRunService {
12
+ private readonly options;
13
+ private readonly activeBySideChat;
14
+ constructor(options: SideChatRunServiceOptions);
15
+ submit(sideChatId: string, clientInstanceId: string, content: string): {
16
+ runId: string;
17
+ };
18
+ abort(sideChatId: string, clientInstanceId: string, runId?: string): Promise<boolean>;
19
+ dispose(sideChatId: string, clientInstanceId: string): Promise<boolean>;
20
+ submitClarification(sideChatId: string, clientInstanceId: string, requestId: string, answer: string): boolean;
21
+ private execute;
22
+ }
@@ -0,0 +1,110 @@
1
+ import { createLogger } from "../../utils/logger/index.js";
2
+ import { init_logger } from "../../utils/logger.js";
3
+ import { abortEmbeddedRun } from "../../agent/embedded/runs.js";
4
+ import { SideChatError } from "./manager.js";
5
+ import { ChatStreamMapper } from "../chat-stream/mapper.js";
6
+ import { randomUUID } from "node:crypto";
7
+ //#region src/gateway/side-chat/run-service.ts
8
+ init_logger();
9
+ const log = createLogger("Gateway:SideChatRun");
10
+ var SideChatRunService = class {
11
+ activeBySideChat = /* @__PURE__ */ new Map();
12
+ constructor(options) {
13
+ this.options = options;
14
+ }
15
+ submit(sideChatId, clientInstanceId, content) {
16
+ const text = content.trim();
17
+ if (!text) throw new SideChatError("content is required", "INVALID_REQUEST");
18
+ const sideChat = this.options.manager.get(sideChatId, clientInstanceId);
19
+ if (this.activeBySideChat.has(sideChatId)) throw new SideChatError("A side chat run is already active", "CONFLICT");
20
+ const run = {
21
+ sideChatId,
22
+ clientInstanceId,
23
+ executionSessionKey: this.options.manager.getRuntime(sideChatId, clientInstanceId).runtimeId,
24
+ runId: randomUUID(),
25
+ abortController: new AbortController()
26
+ };
27
+ this.activeBySideChat.set(sideChatId, run);
28
+ this.options.manager.setStatus(sideChatId, clientInstanceId, "running");
29
+ this.execute(run, text, sideChat.config).catch((err) => {
30
+ log.error({
31
+ err,
32
+ sideChatId,
33
+ runId: run.runId
34
+ }, "Side chat run cleanup failed");
35
+ });
36
+ return { runId: run.runId };
37
+ }
38
+ async abort(sideChatId, clientInstanceId, runId) {
39
+ this.options.manager.get(sideChatId, clientInstanceId);
40
+ const active = this.activeBySideChat.get(sideChatId);
41
+ if (!active || runId && active.runId !== runId) return false;
42
+ this.options.agentRunner.cancelClarificationForRun(active.runId);
43
+ active.abortController.abort();
44
+ await abortEmbeddedRun(active.executionSessionKey).catch(() => false);
45
+ return true;
46
+ }
47
+ async dispose(sideChatId, clientInstanceId) {
48
+ await this.abort(sideChatId, clientInstanceId).catch(() => false);
49
+ return this.options.manager.dispose(sideChatId, clientInstanceId);
50
+ }
51
+ submitClarification(sideChatId, clientInstanceId, requestId, answer) {
52
+ this.options.manager.get(sideChatId, clientInstanceId);
53
+ return this.options.agentRunner.submitClarifyResponse(requestId, answer);
54
+ }
55
+ async execute(run, content, config) {
56
+ const topic = `run:${run.runId}`;
57
+ const mapper = new ChatStreamMapper({
58
+ runId: run.runId,
59
+ sessionKey: run.sideChatId,
60
+ channel: "side-chat"
61
+ });
62
+ const publish = (event) => {
63
+ this.options.publishRealtime(topic, event.type, event);
64
+ };
65
+ const publishMapped = (event) => {
66
+ for (const mapped of mapper.map(event)) publish(mapped);
67
+ };
68
+ try {
69
+ for (const event of mapper.start()) publish(event);
70
+ publishMapped({
71
+ type: "user_message",
72
+ message: {
73
+ role: "user",
74
+ content,
75
+ timestamp: Date.now()
76
+ }
77
+ });
78
+ this.options.agentRunner.registerExternalWebchatRun(run.executionSessionKey, run.runId, (event) => publishMapped(event));
79
+ const result = await this.options.getAgentService().runEphemeralTurn({
80
+ executionSessionKey: run.executionSessionKey,
81
+ parentSessionKey: this.options.manager.get(run.sideChatId, run.clientInstanceId).parentSessionKey,
82
+ runId: run.runId,
83
+ content,
84
+ modelRef: config.modelRef,
85
+ thinkingLevel: config.thinkingLevel,
86
+ transcriptRuntime: this.options.manager.getRuntime(run.sideChatId, run.clientInstanceId),
87
+ abortSignal: run.abortController.signal,
88
+ onEvent: publishMapped
89
+ });
90
+ const cancelled = run.abortController.signal.aborted;
91
+ const status = cancelled ? "cancelled" : result.ok ? "success" : "error";
92
+ if (!result.ok && result.errorMessage) for (const event of mapper.error(result.errorMessage)) publish(event);
93
+ for (const event of mapper.end(status, cancelled ? "Interrupted" : result.errorMessage)) publish(event);
94
+ } catch (error) {
95
+ const message = error instanceof Error ? error.message : String(error);
96
+ for (const event of mapper.error(message)) publish(event);
97
+ for (const event of mapper.end("error", message)) publish(event);
98
+ } finally {
99
+ this.options.agentRunner.unregisterExternalWebchatRun(run.executionSessionKey, run.runId);
100
+ this.activeBySideChat.delete(run.sideChatId);
101
+ try {
102
+ this.options.manager.getMessages(run.sideChatId, run.clientInstanceId);
103
+ this.options.manager.setStatus(run.sideChatId, run.clientInstanceId, "idle");
104
+ } catch {}
105
+ this.options.completeRealtimeTopic(topic);
106
+ }
107
+ }
108
+ };
109
+ //#endregion
110
+ export { SideChatRunService };
@@ -0,0 +1,61 @@
1
+ import type { ThinkingLevel } from '@earendil-works/pi-agent-core';
2
+ export type SideChatStatus = 'idle' | 'running' | 'waiting-approval' | 'waiting-input' | 'closing';
3
+ export type SideChatSelection = {
4
+ id: string;
5
+ type: 'message';
6
+ messageId: string;
7
+ role: string;
8
+ content: string;
9
+ label?: string;
10
+ } | {
11
+ id: string;
12
+ type: 'text';
13
+ text: string;
14
+ sourceMessageId?: string;
15
+ label?: string;
16
+ } | {
17
+ id: string;
18
+ type: 'file-range';
19
+ path: string;
20
+ startLine: number;
21
+ endLine: number;
22
+ text: string;
23
+ contentHash?: string;
24
+ label?: string;
25
+ } | {
26
+ id: string;
27
+ type: 'diff';
28
+ diff: string;
29
+ path?: string;
30
+ label?: string;
31
+ };
32
+ export interface SideChatContextSnapshot {
33
+ parentSessionKey: string;
34
+ parentSessionId: string;
35
+ parentMessageCount: number;
36
+ createdAt: string;
37
+ selections: SideChatSelection[];
38
+ contentHash: string;
39
+ }
40
+ export interface SideChatConfig {
41
+ modelRef: string;
42
+ thinkingLevel?: ThinkingLevel;
43
+ }
44
+ export interface SideChatView {
45
+ id: string;
46
+ parentSessionKey: string;
47
+ clientInstanceId: string;
48
+ status: SideChatStatus;
49
+ createdAt: string;
50
+ lastActiveAt: string;
51
+ expiresAt: string;
52
+ messageCount: number;
53
+ context: SideChatContextSnapshot;
54
+ config: SideChatConfig;
55
+ }
56
+ export interface CreateSideChatInput {
57
+ parentSessionKey: string;
58
+ clientInstanceId: string;
59
+ selections?: SideChatSelection[];
60
+ config?: Partial<SideChatConfig>;
61
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -14,7 +14,6 @@ export type RawSessionConversationRef = {
14
14
  };
15
15
  /** Parse `agent:{agentId}:{rest}` session keys (OpenClaw canonical form). */
16
16
  export declare function parseAgentSessionKey(sessionKey: string | undefined | null): ParsedAgentSessionKey | null;
17
- export declare function isCronRunSessionKey(sessionKey: string | undefined | null): boolean;
18
17
  export declare function isCronSessionKey(sessionKey: string | undefined | null): boolean;
19
18
  export declare function isSubagentSessionKey(sessionKey: string | undefined | null): boolean;
20
19
  export declare function getSubagentDepth(sessionKey: string | undefined | null): number;
@@ -16,11 +16,6 @@ function parseAgentSessionKey(sessionKey) {
16
16
  rest
17
17
  };
18
18
  }
19
- function isCronRunSessionKey(sessionKey) {
20
- const parsed = parseAgentSessionKey(sessionKey);
21
- if (!parsed) return false;
22
- return /^cron:[^:]+:run:[^:]+$/.test(parsed.rest);
23
- }
24
19
  function isCronSessionKey(sessionKey) {
25
20
  const parsed = parseAgentSessionKey(sessionKey);
26
21
  if (!parsed) return false;
@@ -87,4 +82,4 @@ var init_session_key_utils = __esmMin((() => {
87
82
  }));
88
83
  //#endregion
89
84
  init_session_key_utils();
90
- export { getSubagentDepth, init_session_key_utils, isAcpSessionKey, isCronRunSessionKey, isCronSessionKey, isSubagentSessionKey, parseAgentSessionKey, parseRawSessionConversationRef, parseThreadSessionSuffix, resolveThreadParentSessionKey };
85
+ export { getSubagentDepth, init_session_key_utils, isAcpSessionKey, isCronSessionKey, isSubagentSessionKey, parseAgentSessionKey, parseRawSessionConversationRef, parseThreadSessionSuffix, resolveThreadParentSessionKey };
@@ -1,6 +1,6 @@
1
1
  import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
2
  import { DEFAULT_ACCOUNT_ID, normalizeAccountId, normalizeOptionalAccountId } from "./account-id.js";
3
- import { getSubagentDepth, init_session_key_utils, isAcpSessionKey, isCronRunSessionKey, isCronSessionKey, isSubagentSessionKey, parseAgentSessionKey, parseRawSessionConversationRef, parseThreadSessionSuffix, resolveThreadParentSessionKey } from "./session-key-utils.js";
3
+ import { getSubagentDepth, init_session_key_utils, isAcpSessionKey, isCronSessionKey, isSubagentSessionKey, parseAgentSessionKey, parseRawSessionConversationRef, parseThreadSessionSuffix, resolveThreadParentSessionKey } from "./session-key-utils.js";
4
4
  import { DEFAULT_AGENT_ID, DEFAULT_MAIN_KEY, assertAgentSessionKey, buildAgentMainSessionKey, buildAgentPeerSessionKey, buildGroupHistoryKey, classifySessionKeyShape, defaultMainSessionKey, init_agent_session_key, isValidAgentId, normalizeAgentId, normalizeMainKey, normalizeSessionKey, resolveAgentIdFromSessionKey, resolveThreadSessionKeys, sanitizeAgentId, scopedHeartbeatWakeOptions, toAgentRequestSessionKey, toAgentStoreSessionKey } from "./agent-session-key.js";
5
5
  //#region src/routing/session-key.ts
6
6
  function sanitizeSegment(value, options) {
@@ -188,4 +188,4 @@ var init_session_key = __esmMin((() => {
188
188
  }));
189
189
  //#endregion
190
190
  init_session_key();
191
- export { DEFAULT_ACCOUNT_ID, DEFAULT_AGENT_ID, DEFAULT_MAIN_KEY, assertAgentSessionKey, buildAgentMainSessionKey, buildAgentPeerSessionKey, buildGroupHistoryKey, buildSessionKey, buildSubagentSessionKey, classifySessionKeyShape, defaultMainSessionKey, getParentSessionKey, getSubagentDepth, init_session_key, isAcpSessionKey, isCronRunSessionKey, isCronSessionKey, isSubagentSessionKey, isValidAgentId, isValidSegment, normalizeAccountId, normalizeAgentId, normalizeMainKey, normalizeOptionalAccountId, normalizeSessionKey, parseAgentSessionKey, parseRawSessionConversationRef, parseSessionKey, parseThreadSessionSuffix, resolveAgentIdFromSessionKey, resolveThreadParentSessionKey, resolveThreadSessionKeys, sanitizeAgentId, sanitizeSegment, scopedHeartbeatWakeOptions, toAgentRequestSessionKey, toAgentStoreSessionKey };
191
+ export { DEFAULT_ACCOUNT_ID, DEFAULT_AGENT_ID, DEFAULT_MAIN_KEY, assertAgentSessionKey, buildAgentMainSessionKey, buildAgentPeerSessionKey, buildGroupHistoryKey, buildSessionKey, buildSubagentSessionKey, classifySessionKeyShape, defaultMainSessionKey, getParentSessionKey, getSubagentDepth, init_session_key, isAcpSessionKey, isCronSessionKey, isSubagentSessionKey, isValidAgentId, isValidSegment, normalizeAccountId, normalizeAgentId, normalizeMainKey, normalizeOptionalAccountId, normalizeSessionKey, parseAgentSessionKey, parseRawSessionConversationRef, parseSessionKey, parseThreadSessionSuffix, resolveAgentIdFromSessionKey, resolveThreadParentSessionKey, resolveThreadSessionKeys, sanitizeAgentId, sanitizeSegment, scopedHeartbeatWakeOptions, toAgentRequestSessionKey, toAgentStoreSessionKey };
@@ -6,12 +6,25 @@ import type { NotesService } from '../notes/service.js';
6
6
  import type { ProactiveInboxService } from '../proactive/inbox/service.js';
7
7
  import type { ProjectService } from '../projects/project-service.js';
8
8
  import type { SessionIndex } from '../session/manager.js';
9
+ import type { WorkflowRunSummary } from '../workflows/domain/index.js';
9
10
  import type { WorkflowRunService } from '../workflows/service/workflow-run-service.js';
10
11
  import { type TaskReadModel } from './task-read-model-projector.js';
11
12
  type HomeDecision = HomeResponse['decisions'][number];
12
13
  type HomeAttention = HomeResponse['attention'][number];
13
14
  type HomeBriefingWin = HomeResponse['briefing']['wins'][number];
14
15
  type HomeAutomation = HomeResponse['upcomingAutomations'][number];
16
+ type HomeFocusItem = HomeResponse['focusItems'][number];
17
+ type HomeWorkflowRun = {
18
+ id: string;
19
+ definitionId: string;
20
+ title: string;
21
+ status: WorkflowRunSummary['status'];
22
+ sessionKey?: string;
23
+ createdAtMs: number;
24
+ startedAtMs?: number;
25
+ completedAtMs?: number;
26
+ metrics: WorkflowRunSummary['metrics'];
27
+ };
15
28
  type HomeAutomationRun = {
16
29
  id: string;
17
30
  automationId: string;
@@ -126,6 +139,17 @@ export declare function buildHomeBriefing(input: {
126
139
  name?: string;
127
140
  };
128
141
  };
142
+ export declare function buildHomeFocusItems(input: {
143
+ locale?: string;
144
+ decisions: HomeDecision[];
145
+ attention: HomeAttention[];
146
+ activeWorkflowRuns: HomeWorkflowRun[];
147
+ runningTasks: HomeResponse['tasks']['running'];
148
+ wins: HomeBriefingWin[];
149
+ nextScheduled?: HomeAutomation;
150
+ inboxCount: number;
151
+ nowMs: number;
152
+ }): HomeFocusItem[];
129
153
  export declare class HomeQueryService {
130
154
  #private;
131
155
  private readonly service;