pi-acp 0.0.33 → 0.0.34
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/README.md +6 -2
- package/dist/index.js +134 -76
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -25,6 +25,10 @@ Expect some minor breaking changes.
|
|
|
25
25
|
- Loads file-based slash commands compatible with pi’s conventions
|
|
26
26
|
- Adds a small set of built-in commands for headless/editor usage
|
|
27
27
|
- Supports skill commands (if enabled in pi settings, they appear as `/skill:skill-name` in the ACP client)
|
|
28
|
+
- Context window usage
|
|
29
|
+
- Reports pi's real context occupancy (`get_session_stats` → `contextUsage`) to the client as ACP `usage_update` after each turn, on `session/new` and `session/load`, and after a model switch
|
|
30
|
+
- Requires a pi version whose `get_session_stats` response includes `contextUsage`; otherwise no usage is reported
|
|
31
|
+
- Right after compaction pi may not have a trustworthy token count yet, so the client keeps the previous value until the next model response
|
|
28
32
|
- Skills are loaded by pi directly and are available in ACP sessions
|
|
29
33
|
- (Zed) `pi-acp` emits “startup info” block into the session (pi version, context, skills, prompts, extensions - similar to `pi` in the terminal). You can disable it by setting `quietStartup: true` in pi settings (`~/.pi/agent/settings.json` or `<project>/.pi/settings.json`). When `quietStartup` is enabled, `pi-acp` will still emit a 'New version available' message if the installed pi version is outdated.
|
|
30
34
|
- (Zed) Session history is supported in Zed starting with [`v0.225.0`](https://zed.dev/releases/preview/0.225.0). Session loading / history maps to pi's session files. Sessions can be resumed both in `pi` and in the ACP client.
|
|
@@ -38,7 +42,7 @@ npm install -g @earendil-works/pi-coding-agent
|
|
|
38
42
|
```
|
|
39
43
|
|
|
40
44
|
- Node.js 22+
|
|
41
|
-
- `pi` v0.
|
|
45
|
+
- `pi` v0.81.0+ installed and available on your `PATH` (the adapter runs the `pi` executable)
|
|
42
46
|
- Configure `pi` separately for your model providers/API keys
|
|
43
47
|
|
|
44
48
|
## Install
|
|
@@ -155,7 +159,7 @@ Loaded from:
|
|
|
155
159
|
|
|
156
160
|
Other built-in commands:
|
|
157
161
|
|
|
158
|
-
- `/model` -
|
|
162
|
+
- `/model` - not implemented (use the model selector UI in Zed)
|
|
159
163
|
- `/thinking` - maps to 'mode' selector in Zed
|
|
160
164
|
- `/clear` - not implemented (use ACP client 'new' command)
|
|
161
165
|
|
package/dist/index.js
CHANGED
|
@@ -54,6 +54,7 @@ import { isAbsolute, resolve as resolvePath } from "path";
|
|
|
54
54
|
// src/pi-rpc/process.ts
|
|
55
55
|
import { spawn } from "child_process";
|
|
56
56
|
import * as readline from "readline";
|
|
57
|
+
import crossSpawn from "cross-spawn";
|
|
57
58
|
|
|
58
59
|
// src/pi-rpc/command.ts
|
|
59
60
|
import { platform } from "os";
|
|
@@ -89,6 +90,7 @@ var ANSI_ESCAPE_REGEX = new RegExp(
|
|
|
89
90
|
function stripAnsi(s) {
|
|
90
91
|
return s.replace(ANSI_ESCAPE_REGEX, "");
|
|
91
92
|
}
|
|
93
|
+
var SESSION_STATS_TIMEOUT_MS = 1e3;
|
|
92
94
|
var PiRpcProcess = class _PiRpcProcess {
|
|
93
95
|
child;
|
|
94
96
|
pending = /* @__PURE__ */ new Map();
|
|
@@ -109,14 +111,8 @@ var PiRpcProcess = class _PiRpcProcess {
|
|
|
109
111
|
}
|
|
110
112
|
if (msg?.type === "response") {
|
|
111
113
|
const id = typeof msg.id === "string" ? msg.id : void 0;
|
|
112
|
-
if (id)
|
|
113
|
-
|
|
114
|
-
if (pending) {
|
|
115
|
-
this.pending.delete(id);
|
|
116
|
-
pending.resolve(msg);
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
114
|
+
if (id !== void 0) this.pending.get(id)?.resolve(msg);
|
|
115
|
+
return;
|
|
120
116
|
}
|
|
121
117
|
for (const h of this.eventHandlers) h(msg);
|
|
122
118
|
});
|
|
@@ -134,11 +130,11 @@ var PiRpcProcess = class _PiRpcProcess {
|
|
|
134
130
|
const cmd = getPiCommand(params.piCommand);
|
|
135
131
|
const args = ["--mode", "rpc", "--no-themes"];
|
|
136
132
|
if (params.sessionPath) args.push("--session", params.sessionPath);
|
|
137
|
-
const
|
|
133
|
+
const start = shouldUseShellForPiCommand(cmd) ? crossSpawn : spawn;
|
|
134
|
+
const child = start(cmd, args, {
|
|
138
135
|
cwd: params.cwd,
|
|
139
136
|
stdio: "pipe",
|
|
140
|
-
env: process.env
|
|
141
|
-
shell: shouldUseShellForPiCommand(cmd)
|
|
137
|
+
env: process.env
|
|
142
138
|
});
|
|
143
139
|
try {
|
|
144
140
|
await new Promise((resolve4, reject) => {
|
|
@@ -229,6 +225,17 @@ var PiRpcProcess = class _PiRpcProcess {
|
|
|
229
225
|
if (!res.success) throw new Error(`pi set_model failed: ${res.error ?? JSON.stringify(res.data)}`);
|
|
230
226
|
return res.data;
|
|
231
227
|
}
|
|
228
|
+
async getAvailableThinkingLevels() {
|
|
229
|
+
const res = await this.request({ type: "get_available_thinking_levels" });
|
|
230
|
+
if (!res.success)
|
|
231
|
+
throw new Error(`pi get_available_thinking_levels failed: ${res.error ?? JSON.stringify(res.data)}`);
|
|
232
|
+
const data = res.data;
|
|
233
|
+
const levels = data && typeof data === "object" && "levels" in data ? data.levels : void 0;
|
|
234
|
+
if (!Array.isArray(levels) || levels.length === 0 || !levels.every((level) => typeof level === "string" && level.length > 0)) {
|
|
235
|
+
throw new Error("pi get_available_thinking_levels returned invalid levels");
|
|
236
|
+
}
|
|
237
|
+
return levels;
|
|
238
|
+
}
|
|
232
239
|
async setThinkingLevel(level) {
|
|
233
240
|
const res = await this.request({ type: "set_thinking_level", level });
|
|
234
241
|
if (!res.success) throw new Error(`pi set_thinking_level failed: ${res.error ?? JSON.stringify(res.data)}`);
|
|
@@ -250,10 +257,10 @@ var PiRpcProcess = class _PiRpcProcess {
|
|
|
250
257
|
const res = await this.request({ type: "set_auto_compaction", enabled });
|
|
251
258
|
if (!res.success) throw new Error(`pi set_auto_compaction failed: ${res.error ?? JSON.stringify(res.data)}`);
|
|
252
259
|
}
|
|
253
|
-
async getSessionStats() {
|
|
254
|
-
const res = await this.request({ type: "get_session_stats" });
|
|
260
|
+
async getSessionStats(timeoutMs) {
|
|
261
|
+
const res = await this.request({ type: "get_session_stats" }, { timeoutMs });
|
|
255
262
|
if (!res.success) throw new Error(`pi get_session_stats failed: ${res.error ?? JSON.stringify(res.data)}`);
|
|
256
|
-
return res.data;
|
|
263
|
+
return res.data ?? {};
|
|
257
264
|
}
|
|
258
265
|
async setSessionName(name) {
|
|
259
266
|
const res = await this.request({ type: "set_session_name", name });
|
|
@@ -283,15 +290,41 @@ var PiRpcProcess = class _PiRpcProcess {
|
|
|
283
290
|
await this.writeLine(`${JSON.stringify({ type: "extension_ui_response", ...response })}
|
|
284
291
|
`);
|
|
285
292
|
}
|
|
286
|
-
request(cmd) {
|
|
293
|
+
request(cmd, opts) {
|
|
287
294
|
const id = crypto.randomUUID();
|
|
288
295
|
const withId = { ...cmd, id };
|
|
296
|
+
const timeoutMs = opts?.timeoutMs;
|
|
289
297
|
const line = `${JSON.stringify(withId)}
|
|
290
298
|
`;
|
|
291
299
|
return new Promise((resolve4, reject) => {
|
|
292
|
-
|
|
300
|
+
let timer;
|
|
301
|
+
const drop = () => {
|
|
302
|
+
if (timer !== void 0) {
|
|
303
|
+
clearTimeout(timer);
|
|
304
|
+
timer = void 0;
|
|
305
|
+
}
|
|
306
|
+
return this.pending.delete(id);
|
|
307
|
+
};
|
|
308
|
+
this.pending.set(id, {
|
|
309
|
+
resolve: (res) => {
|
|
310
|
+
drop();
|
|
311
|
+
resolve4(res);
|
|
312
|
+
},
|
|
313
|
+
reject: (error) => {
|
|
314
|
+
drop();
|
|
315
|
+
reject(error);
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
if (timeoutMs !== void 0) {
|
|
319
|
+
timer = setTimeout(() => {
|
|
320
|
+
timer = void 0;
|
|
321
|
+
if (!this.pending.delete(id)) return;
|
|
322
|
+
reject(new Error(`pi ${cmd.type} timed out after ${timeoutMs}ms`));
|
|
323
|
+
}, timeoutMs);
|
|
324
|
+
timer.unref?.();
|
|
325
|
+
}
|
|
293
326
|
void this.writeLine(line).catch((error) => {
|
|
294
|
-
|
|
327
|
+
if (!drop()) return;
|
|
295
328
|
reject(error);
|
|
296
329
|
});
|
|
297
330
|
});
|
|
@@ -610,6 +643,13 @@ var CONFIRM_PERMISSION_OPTIONS = [
|
|
|
610
643
|
];
|
|
611
644
|
var EXTENSION_UI_RAW_INPUT_KEYS = ["title", "message", "options", "placeholder", "prefill"];
|
|
612
645
|
var CHOICE_OPTION_PREFIX = "choice-";
|
|
646
|
+
function toUsageUpdate(stats) {
|
|
647
|
+
const used = stats?.contextUsage?.tokens;
|
|
648
|
+
const size = stats?.contextUsage?.contextWindow;
|
|
649
|
+
if (typeof used !== "number" || !Number.isSafeInteger(used) || used < 0) return null;
|
|
650
|
+
if (typeof size !== "number" || !Number.isSafeInteger(size) || size <= 0) return null;
|
|
651
|
+
return { sessionUpdate: "usage_update", used, size };
|
|
652
|
+
}
|
|
613
653
|
function findUniqueLineNumber(text, needle) {
|
|
614
654
|
if (!needle) return void 0;
|
|
615
655
|
const first = text.indexOf(needle);
|
|
@@ -881,6 +921,41 @@ var PiAcpSession = class {
|
|
|
881
921
|
async flushEmits() {
|
|
882
922
|
await this.lastEmit;
|
|
883
923
|
}
|
|
924
|
+
/**
|
|
925
|
+
* Best-effort: publish the real pi context-window occupancy as ACP `usage_update`.
|
|
926
|
+
* Queued updates are flushed even when the stats query fails or times out, so callers
|
|
927
|
+
* can await this before resolving `session/prompt`.
|
|
928
|
+
*/
|
|
929
|
+
async publishContextUsage() {
|
|
930
|
+
try {
|
|
931
|
+
if (typeof this.proc.getSessionStats === "function") {
|
|
932
|
+
const update = toUsageUpdate(await this.proc.getSessionStats(SESSION_STATS_TIMEOUT_MS));
|
|
933
|
+
if (update) this.emit(update);
|
|
934
|
+
}
|
|
935
|
+
} catch {
|
|
936
|
+
}
|
|
937
|
+
await this.flushEmits();
|
|
938
|
+
}
|
|
939
|
+
async settleTurn() {
|
|
940
|
+
await this.publishContextUsage();
|
|
941
|
+
const reason = this.cancelRequested ? "cancelled" : "end_turn";
|
|
942
|
+
this.pendingTurn?.resolve(reason);
|
|
943
|
+
this.pendingTurn = null;
|
|
944
|
+
this.inAgentLoop = false;
|
|
945
|
+
const next = this.turnQueue.shift();
|
|
946
|
+
if (next) {
|
|
947
|
+
this.emit({
|
|
948
|
+
sessionUpdate: "agent_message_chunk",
|
|
949
|
+
content: { type: "text", text: `Starting queued message. (${this.turnQueue.length} remaining)` }
|
|
950
|
+
});
|
|
951
|
+
this.startTurn(next);
|
|
952
|
+
} else {
|
|
953
|
+
this.emit({
|
|
954
|
+
sessionUpdate: "session_info_update",
|
|
955
|
+
_meta: { piAcp: { queueDepth: 0, running: false } }
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
}
|
|
884
959
|
emitBashToolCall(params) {
|
|
885
960
|
this.bashToolCallIds.add(params.toolCallId);
|
|
886
961
|
this.emit({
|
|
@@ -1210,25 +1285,7 @@ var PiAcpSession = class {
|
|
|
1210
1285
|
break;
|
|
1211
1286
|
}
|
|
1212
1287
|
case "agent_settled": {
|
|
1213
|
-
void this.
|
|
1214
|
-
const reason = this.cancelRequested ? "cancelled" : "end_turn";
|
|
1215
|
-
this.pendingTurn?.resolve(reason);
|
|
1216
|
-
this.pendingTurn = null;
|
|
1217
|
-
this.inAgentLoop = false;
|
|
1218
|
-
const next = this.turnQueue.shift();
|
|
1219
|
-
if (next) {
|
|
1220
|
-
this.emit({
|
|
1221
|
-
sessionUpdate: "agent_message_chunk",
|
|
1222
|
-
content: { type: "text", text: `Starting queued message. (${this.turnQueue.length} remaining)` }
|
|
1223
|
-
});
|
|
1224
|
-
this.startTurn(next);
|
|
1225
|
-
} else {
|
|
1226
|
-
this.emit({
|
|
1227
|
-
sessionUpdate: "session_info_update",
|
|
1228
|
-
_meta: { piAcp: { queueDepth: 0, running: false } }
|
|
1229
|
-
});
|
|
1230
|
-
}
|
|
1231
|
-
});
|
|
1288
|
+
void this.settleTurn();
|
|
1232
1289
|
break;
|
|
1233
1290
|
}
|
|
1234
1291
|
default:
|
|
@@ -2004,10 +2061,15 @@ var PiAcpAgent = class {
|
|
|
2004
2061
|
"Configure an API key or log in with an OAuth provider."
|
|
2005
2062
|
);
|
|
2006
2063
|
}
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2064
|
+
let configuration;
|
|
2065
|
+
try {
|
|
2066
|
+
if (stateErr) throw stateErr;
|
|
2067
|
+
configuration = await getSessionConfiguration(session.proc, { state, availableModels });
|
|
2068
|
+
} catch (err) {
|
|
2069
|
+
this.cleanupFailedNewSession(session.sessionId, state);
|
|
2070
|
+
throw maybeAuthRequiredError(err) ?? RequestError3.internalError({}, String(err?.message ?? err));
|
|
2071
|
+
}
|
|
2072
|
+
const { configOptions, models, modes } = configuration;
|
|
2011
2073
|
const quietStartup = getQuietStartup(params.cwd);
|
|
2012
2074
|
const updateNotice = buildUpdateNotice();
|
|
2013
2075
|
const preludeText = quietStartup ? updateNotice ? updateNotice + "\n" : "" : buildStartupInfo({
|
|
@@ -2032,6 +2094,7 @@ var PiAcpAgent = class {
|
|
|
2032
2094
|
if (preludeText) setTimeout(() => session.sendStartupInfoIfPending(), 0);
|
|
2033
2095
|
setTimeout(() => {
|
|
2034
2096
|
void (async () => {
|
|
2097
|
+
await session.publishContextUsage();
|
|
2035
2098
|
try {
|
|
2036
2099
|
const pi = await session.proc.getCommands();
|
|
2037
2100
|
const { commands } = toAvailableCommandsFromPiGetCommands(pi, {
|
|
@@ -2473,6 +2536,14 @@ ${JSON.stringify(stats, null, 2)}`;
|
|
|
2473
2536
|
mcpServers: params.mcpServers
|
|
2474
2537
|
});
|
|
2475
2538
|
const proc = session.proc;
|
|
2539
|
+
let configuration;
|
|
2540
|
+
try {
|
|
2541
|
+
configuration = await getSessionConfiguration(proc);
|
|
2542
|
+
} catch (err) {
|
|
2543
|
+
this.sessions.close(session.sessionId);
|
|
2544
|
+
throw err;
|
|
2545
|
+
}
|
|
2546
|
+
const { configOptions, models, modes } = configuration;
|
|
2476
2547
|
const fileCommands = loadSlashCommands(params.cwd);
|
|
2477
2548
|
this.sessions.closeAllExcept?.(session.sessionId);
|
|
2478
2549
|
this.store.upsert({
|
|
@@ -2566,7 +2637,6 @@ ${JSON.stringify(stats, null, 2)}`;
|
|
|
2566
2637
|
});
|
|
2567
2638
|
}
|
|
2568
2639
|
}
|
|
2569
|
-
const { configOptions, models, modes } = await getSessionConfiguration(proc);
|
|
2570
2640
|
const response = {
|
|
2571
2641
|
configOptions,
|
|
2572
2642
|
models,
|
|
@@ -2579,6 +2649,7 @@ ${JSON.stringify(stats, null, 2)}`;
|
|
|
2579
2649
|
};
|
|
2580
2650
|
setTimeout(() => {
|
|
2581
2651
|
void (async () => {
|
|
2652
|
+
await session.publishContextUsage();
|
|
2582
2653
|
try {
|
|
2583
2654
|
const pi = await proc.getCommands();
|
|
2584
2655
|
const { commands } = toAvailableCommandsFromPiGetCommands(pi, {
|
|
@@ -2626,66 +2697,48 @@ ${JSON.stringify(stats, null, 2)}`;
|
|
|
2626
2697
|
const session = await this.restoreSession(params.sessionId);
|
|
2627
2698
|
await setSessionModel(session.proc, params.modelId);
|
|
2628
2699
|
await emitConfigOptionsUpdate(this.conn, session.sessionId, session.proc);
|
|
2700
|
+
await session.publishContextUsage();
|
|
2629
2701
|
}
|
|
2630
2702
|
async setSessionMode(params) {
|
|
2631
2703
|
const session = await this.restoreSession(params.sessionId);
|
|
2632
|
-
const mode =
|
|
2633
|
-
if (
|
|
2634
|
-
throw RequestError3.invalidParams(
|
|
2704
|
+
const mode = params.modeId;
|
|
2705
|
+
if (typeof mode !== "string" || mode.length === 0) {
|
|
2706
|
+
throw RequestError3.invalidParams("Expected nonempty string modeId");
|
|
2635
2707
|
}
|
|
2636
2708
|
await session.proc.setThinkingLevel(mode);
|
|
2637
|
-
void this.conn.sessionUpdate({
|
|
2638
|
-
sessionId: session.sessionId,
|
|
2639
|
-
update: {
|
|
2640
|
-
sessionUpdate: "current_mode_update",
|
|
2641
|
-
currentModeId: mode
|
|
2642
|
-
}
|
|
2643
|
-
});
|
|
2644
2709
|
await emitConfigOptionsUpdate(this.conn, session.sessionId, session.proc);
|
|
2645
2710
|
return {};
|
|
2646
2711
|
}
|
|
2647
2712
|
async setSessionConfigOption(params) {
|
|
2648
2713
|
const session = await this.restoreSession(params.sessionId);
|
|
2649
2714
|
const configId = String(params.configId);
|
|
2715
|
+
let modelChanged = false;
|
|
2650
2716
|
if (typeof params.value !== "string") {
|
|
2651
2717
|
throw RequestError3.invalidParams(`Expected string value for config option: ${configId}`);
|
|
2652
2718
|
}
|
|
2653
2719
|
if (configId === MODEL_CONFIG_ID) {
|
|
2654
2720
|
await setSessionModel(session.proc, params.value);
|
|
2721
|
+
modelChanged = true;
|
|
2655
2722
|
} else if (configId === THOUGHT_LEVEL_CONFIG_ID) {
|
|
2656
|
-
if (
|
|
2657
|
-
throw RequestError3.invalidParams(
|
|
2723
|
+
if (params.value.length === 0) {
|
|
2724
|
+
throw RequestError3.invalidParams("Expected nonempty thinking level");
|
|
2658
2725
|
}
|
|
2659
2726
|
await session.proc.setThinkingLevel(params.value);
|
|
2660
|
-
void this.conn.sessionUpdate({
|
|
2661
|
-
sessionId: session.sessionId,
|
|
2662
|
-
update: {
|
|
2663
|
-
sessionUpdate: "current_mode_update",
|
|
2664
|
-
currentModeId: params.value
|
|
2665
|
-
}
|
|
2666
|
-
});
|
|
2667
2727
|
} else {
|
|
2668
2728
|
throw RequestError3.invalidParams(`Unknown config option: ${configId}`);
|
|
2669
2729
|
}
|
|
2670
2730
|
const configOptions = await emitConfigOptionsUpdate(this.conn, session.sessionId, session.proc);
|
|
2731
|
+
if (modelChanged) await session.publishContextUsage();
|
|
2671
2732
|
return { configOptions };
|
|
2672
2733
|
}
|
|
2673
2734
|
};
|
|
2674
|
-
function isThinkingLevel(x) {
|
|
2675
|
-
return x === "off" || x === "minimal" || x === "low" || x === "medium" || x === "high" || x === "xhigh";
|
|
2676
|
-
}
|
|
2677
2735
|
async function getThinkingState(proc, pre) {
|
|
2678
|
-
|
|
2679
|
-
const
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
}
|
|
2685
|
-
})();
|
|
2686
|
-
const tl = typeof state?.thinkingLevel === "string" ? state.thinkingLevel : null;
|
|
2687
|
-
if (tl && isThinkingLevel(tl)) current = tl;
|
|
2688
|
-
const available = ["off", "minimal", "low", "medium", "high", "xhigh"];
|
|
2736
|
+
const state = pre?.state ?? await proc.getState();
|
|
2737
|
+
const available = await proc.getAvailableThinkingLevels();
|
|
2738
|
+
const current = state && typeof state === "object" && "thinkingLevel" in state ? state.thinkingLevel : void 0;
|
|
2739
|
+
if (typeof current !== "string" || current.length === 0 || !available.includes(current)) {
|
|
2740
|
+
throw new Error("pi returned a thinking level absent from available levels");
|
|
2741
|
+
}
|
|
2689
2742
|
return {
|
|
2690
2743
|
currentModeId: current,
|
|
2691
2744
|
availableModes: available.map((id) => ({
|
|
@@ -2696,7 +2749,8 @@ async function getThinkingState(proc, pre) {
|
|
|
2696
2749
|
};
|
|
2697
2750
|
}
|
|
2698
2751
|
async function getSessionConfiguration(proc, pre) {
|
|
2699
|
-
const
|
|
2752
|
+
const state = pre?.state ?? await proc.getState();
|
|
2753
|
+
const [models, modes] = await Promise.all([getModelState(proc, { ...pre, state }), getThinkingState(proc, { state })]);
|
|
2700
2754
|
return {
|
|
2701
2755
|
configOptions: buildConfigOptions({ models, modes }),
|
|
2702
2756
|
models,
|
|
@@ -2779,7 +2833,11 @@ async function getModelState(proc, pre) {
|
|
|
2779
2833
|
};
|
|
2780
2834
|
}
|
|
2781
2835
|
async function emitConfigOptionsUpdate(conn, sessionId, proc) {
|
|
2782
|
-
const { configOptions } = await getSessionConfiguration(proc);
|
|
2836
|
+
const { configOptions, modes } = await getSessionConfiguration(proc);
|
|
2837
|
+
await conn.sessionUpdate({
|
|
2838
|
+
sessionId,
|
|
2839
|
+
update: { sessionUpdate: "current_mode_update", currentModeId: modes.currentModeId }
|
|
2840
|
+
});
|
|
2783
2841
|
await conn.sessionUpdate({
|
|
2784
2842
|
sessionId,
|
|
2785
2843
|
update: {
|