@zetaloop/chappie 0.3.1 → 0.3.2
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/docs/tools.md +2 -2
- package/package.json +1 -1
- package/src/broker.ts +59 -33
- package/src/instructions.md +1 -1
- package/src/server.ts +21 -4
- package/src/session.ts +0 -1
- package/src/state.ts +23 -9
- package/src/tools.ts +2 -1
package/docs/tools.md
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
Call `init` at the start of local work. Without `sessionId`, it reuses the conversation's saved default or selects an online Pi session with no saved ChatGPT binding. Pass a Pi session ID to resume a specific task, including from another ChatGPT conversation or branch.
|
|
21
21
|
|
|
22
|
-
`sessions` lists connected sessions with their ID, device, working directory, name, execution status, and binding count.
|
|
22
|
+
`sessions` lists connected sessions with their ID, device, working directory, name, execution status, and binding count. The first session tool call establishes the default using its `sessionId` or an online session with no saved bindings. Once a default exists, another tool's `sessionId` selects only that operation's target; `init({ sessionId })` changes the default.
|
|
23
23
|
|
|
24
24
|
Several ChatGPT conversations can use the same Pi session. One conversation can also operate on several Pi sessions explicitly. Requests already assigned to a session continue there even if the conversation later changes its default.
|
|
25
25
|
|
|
@@ -82,7 +82,7 @@ Call `ask_assert` with the returned ID to confirm that the widget loaded:
|
|
|
82
82
|
{ "questionId": "<question-id>" }
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
Answers, revisions, and skips arrive later as `webAnswer` in normal Chappie results. `options` can be omitted for a text answer, and `allowMultiple: true` allows several choices. `sessionId` associates the question with a Pi session
|
|
85
|
+
Answers, revisions, and skips arrive later as `webAnswer` in normal Chappie results. `options` can be omitted for a text answer, and `allowMultiple: true` allows several choices. `sessionId` associates the question with a Pi session using the session selection rules above.
|
|
86
86
|
|
|
87
87
|
Questions remain available after the assistant response and across broker restarts. Pi's own interactive tools remain ordinary Pi tools and can be invoked through `call`.
|
|
88
88
|
|
package/package.json
CHANGED
package/src/broker.ts
CHANGED
|
@@ -127,12 +127,7 @@ export class Broker {
|
|
|
127
127
|
signal: AbortSignal,
|
|
128
128
|
): Promise<AbortSignal> {
|
|
129
129
|
if (!this.#latestWorkflow || !chatId) return signal;
|
|
130
|
-
const id =
|
|
131
|
-
typeof requestId === "string"
|
|
132
|
-
? /^wfr_[0-9a-f]{12}7[0-9a-f]{3}[89ab][0-9a-f]{15}(?=\/|$)/i
|
|
133
|
-
.exec(requestId)?.[0]
|
|
134
|
-
.toLowerCase()
|
|
135
|
-
: undefined;
|
|
130
|
+
const id = workflowId(requestId);
|
|
136
131
|
if (!id) return signal;
|
|
137
132
|
signal.throwIfAborted();
|
|
138
133
|
const latest = this.#state.workflow(chatId);
|
|
@@ -177,17 +172,16 @@ export class Broker {
|
|
|
177
172
|
async initialize(
|
|
178
173
|
chatId: string,
|
|
179
174
|
sessionId: string | undefined,
|
|
175
|
+
requestId: unknown,
|
|
180
176
|
signal: AbortSignal,
|
|
181
177
|
): Promise<InitializedSession> {
|
|
182
|
-
const previous = this.#state.binding(chatId);
|
|
183
178
|
const { sessionId: target, selection } = await this.#selectSession(
|
|
184
179
|
chatId,
|
|
185
180
|
sessionId,
|
|
181
|
+
requestId,
|
|
186
182
|
signal,
|
|
187
183
|
true,
|
|
188
184
|
);
|
|
189
|
-
if (previous === target)
|
|
190
|
-
await this.#notify(target, `ChatGPT ${chatId.slice(-4)} joined`);
|
|
191
185
|
const { inspection, inputs, globalAgents } = await this.#inspect(
|
|
192
186
|
target,
|
|
193
187
|
signal,
|
|
@@ -209,13 +203,14 @@ export class Broker {
|
|
|
209
203
|
chatId: string,
|
|
210
204
|
sessionId: string | undefined,
|
|
211
205
|
text: string,
|
|
206
|
+
requestId: unknown,
|
|
212
207
|
signal: AbortSignal,
|
|
213
208
|
): Promise<ChatResult> {
|
|
214
209
|
const { sessionId: target } = await this.#selectSession(
|
|
215
210
|
chatId,
|
|
216
211
|
sessionId,
|
|
212
|
+
requestId,
|
|
217
213
|
signal,
|
|
218
|
-
false,
|
|
219
214
|
);
|
|
220
215
|
const result = await this.#request(
|
|
221
216
|
target,
|
|
@@ -233,13 +228,14 @@ export class Broker {
|
|
|
233
228
|
chatId: string,
|
|
234
229
|
sessionId: string | undefined,
|
|
235
230
|
names: string[] | undefined,
|
|
231
|
+
requestId: unknown,
|
|
236
232
|
signal: AbortSignal,
|
|
237
233
|
): Promise<InspectedSession> {
|
|
238
234
|
const { sessionId: target } = await this.#selectSession(
|
|
239
235
|
chatId,
|
|
240
236
|
sessionId,
|
|
237
|
+
requestId,
|
|
241
238
|
signal,
|
|
242
|
-
false,
|
|
243
239
|
);
|
|
244
240
|
const { inspection, inputs } = await this.#inspect(target, signal);
|
|
245
241
|
await this.#ackInputs(target, inputs);
|
|
@@ -257,13 +253,14 @@ export class Broker {
|
|
|
257
253
|
chatId: string,
|
|
258
254
|
sessionId: string | undefined,
|
|
259
255
|
calls: ToolInput[],
|
|
256
|
+
requestId: unknown,
|
|
260
257
|
signal: AbortSignal,
|
|
261
258
|
): Promise<CallResult> {
|
|
262
259
|
const { sessionId: target } = await this.#selectSession(
|
|
263
260
|
chatId,
|
|
264
261
|
sessionId,
|
|
262
|
+
requestId,
|
|
265
263
|
signal,
|
|
266
|
-
false,
|
|
267
264
|
);
|
|
268
265
|
const toolCalls: ToolCall[] = calls.map((call) => ({
|
|
269
266
|
type: "toolCall",
|
|
@@ -297,10 +294,14 @@ export class Broker {
|
|
|
297
294
|
async inputs(
|
|
298
295
|
chatId: string,
|
|
299
296
|
sessionId: string | undefined,
|
|
297
|
+
requestId: unknown,
|
|
300
298
|
signal: AbortSignal,
|
|
301
299
|
): Promise<SessionInput[]> {
|
|
302
|
-
const
|
|
300
|
+
const boundId = this.#state.binding(chatId);
|
|
301
|
+
const target = sessionId ?? boundId;
|
|
303
302
|
if (!target || !this.#sessions.has(target)) return [];
|
|
303
|
+
signal.throwIfAborted();
|
|
304
|
+
if (target === boundId) await this.#join(chatId, target, requestId);
|
|
304
305
|
const { inputs } = await this.#inspect(target, signal);
|
|
305
306
|
await this.#ackInputs(target, inputs);
|
|
306
307
|
return inputs;
|
|
@@ -310,13 +311,14 @@ export class Broker {
|
|
|
310
311
|
chatId: string,
|
|
311
312
|
sessionId: string | undefined,
|
|
312
313
|
input: QuestionInput,
|
|
314
|
+
requestId: unknown,
|
|
313
315
|
signal: AbortSignal,
|
|
314
316
|
): Promise<Question> {
|
|
315
317
|
const { sessionId: target } = await this.#selectSession(
|
|
316
318
|
chatId,
|
|
317
319
|
sessionId,
|
|
320
|
+
requestId,
|
|
318
321
|
signal,
|
|
319
|
-
false,
|
|
320
322
|
);
|
|
321
323
|
const session = this.#sessions.get(target);
|
|
322
324
|
if (!session) throw new Error(`Pi session ${target} is offline`);
|
|
@@ -460,50 +462,66 @@ export class Broker {
|
|
|
460
462
|
async #selectSession(
|
|
461
463
|
chatId: string,
|
|
462
464
|
requestedId: string | undefined,
|
|
465
|
+
requestId: unknown,
|
|
463
466
|
signal: AbortSignal,
|
|
464
|
-
bindRequested
|
|
467
|
+
bindRequested = false,
|
|
465
468
|
): Promise<{
|
|
466
469
|
sessionId: string;
|
|
467
470
|
selection: InitializedSession["selection"];
|
|
468
471
|
}> {
|
|
469
472
|
if (requestedId) {
|
|
470
473
|
await this.#waitForSession(requestedId, signal);
|
|
471
|
-
|
|
472
|
-
|
|
474
|
+
signal.throwIfAborted();
|
|
475
|
+
const boundId = this.#state.binding(chatId);
|
|
476
|
+
if (bindRequested || !boundId || boundId === requestedId) {
|
|
477
|
+
await this.#join(chatId, requestedId, requestId, bindRequested);
|
|
473
478
|
}
|
|
474
479
|
return { sessionId: requestedId, selection: "explicit" };
|
|
475
480
|
}
|
|
476
481
|
|
|
477
|
-
const boundId = this.#state.binding(chatId);
|
|
478
|
-
if (boundId) {
|
|
479
|
-
await this.#waitForSession(boundId, signal);
|
|
480
|
-
return { sessionId: boundId, selection: "existing" };
|
|
481
|
-
}
|
|
482
|
-
|
|
483
482
|
for (;;) {
|
|
483
|
+
signal.throwIfAborted();
|
|
484
|
+
const boundId = this.#state.binding(chatId);
|
|
485
|
+
if (boundId) {
|
|
486
|
+
await this.#waitForSession(boundId, signal);
|
|
487
|
+
signal.throwIfAborted();
|
|
488
|
+
if (bindRequested || this.#state.binding(chatId) === boundId) {
|
|
489
|
+
await this.#join(chatId, boundId, requestId, bindRequested);
|
|
490
|
+
}
|
|
491
|
+
return { sessionId: boundId, selection: "existing" };
|
|
492
|
+
}
|
|
484
493
|
const occupied = this.#state.bindingCounts();
|
|
485
494
|
const candidate = [...this.#sessions.keys()].find(
|
|
486
495
|
(sessionId) => !occupied.has(sessionId),
|
|
487
496
|
);
|
|
488
497
|
if (candidate) {
|
|
489
|
-
await this.#
|
|
498
|
+
await this.#join(chatId, candidate, requestId, bindRequested);
|
|
490
499
|
return { sessionId: candidate, selection: "automatic" };
|
|
491
500
|
}
|
|
492
501
|
await this.#waitForChange(signal);
|
|
493
502
|
}
|
|
494
503
|
}
|
|
495
504
|
|
|
496
|
-
async #
|
|
505
|
+
async #join(
|
|
506
|
+
chatId: string,
|
|
507
|
+
sessionId: string,
|
|
508
|
+
requestId: unknown,
|
|
509
|
+
explicit = false,
|
|
510
|
+
): Promise<void> {
|
|
497
511
|
const previous = this.#state.binding(chatId);
|
|
498
|
-
|
|
499
|
-
this.#
|
|
500
|
-
if (previous) {
|
|
501
|
-
|
|
502
|
-
if (
|
|
503
|
-
await this.#notify(previous,
|
|
504
|
-
|
|
512
|
+
const workflow = workflowId(requestId);
|
|
513
|
+
const joined = await this.#state.join(chatId, sessionId, workflow);
|
|
514
|
+
if (previous !== sessionId) {
|
|
515
|
+
this.#notifyChange();
|
|
516
|
+
if (previous)
|
|
517
|
+
await this.#notify(previous, `ChatGPT ${chatId.slice(-4)} left`);
|
|
518
|
+
}
|
|
519
|
+
if (joined || explicit) {
|
|
520
|
+
await this.#notify(
|
|
521
|
+
sessionId,
|
|
522
|
+
`ChatGPT ${chatId.slice(-4)}${workflow ? ` (${workflow.slice(-4)})` : ""} joined`,
|
|
523
|
+
);
|
|
505
524
|
}
|
|
506
|
-
await this.#notify(sessionId, `ChatGPT ${chatId.slice(-4)} joined`);
|
|
507
525
|
}
|
|
508
526
|
|
|
509
527
|
async #notify(sessionId: string, message: string): Promise<void> {
|
|
@@ -630,6 +648,14 @@ export class Broker {
|
|
|
630
648
|
}
|
|
631
649
|
}
|
|
632
650
|
|
|
651
|
+
function workflowId(requestId: unknown): string | undefined {
|
|
652
|
+
return typeof requestId === "string"
|
|
653
|
+
? /^wfr_[0-9a-f]{12}7[0-9a-f]{3}[89ab][0-9a-f]{15}(?=\/|$)/i
|
|
654
|
+
.exec(requestId)?.[0]
|
|
655
|
+
.toLowerCase()
|
|
656
|
+
: undefined;
|
|
657
|
+
}
|
|
658
|
+
|
|
633
659
|
function abortError(signal: AbortSignal): Error {
|
|
634
660
|
return signal.reason instanceof Error
|
|
635
661
|
? signal.reason
|
package/src/instructions.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Chappie connects this ChatGPT conversation to Pi sessions on one or more devices. Resume work with init using the task's Pi sessionId, including in a new chat or branch. When only a project or session name is known, find its device/cwd/name in sessions, then call init. If the target is absent or ambiguous, ask the user to resolve it. Pi sessions appear while the chappie/chatgpt provider is selected.
|
|
2
2
|
|
|
3
|
-
init sets this chat's default Pi session.
|
|
3
|
+
init sets this chat's default Pi session. A session tool also establishes a default on first use: sessionId selects its target, or omitting it selects the first online session with no saved bindings. These sessions may already contain work. Once a default exists, another tool's sessionId selects only that call's target. Defaults survive broker restarts, and several chats can share one Pi session.
|
|
4
4
|
|
|
5
5
|
The active model is this existing ChatGPT conversation. A Pi tool that starts another chappie/chatgpt agent has no ChatGPT conversation to attach to and will wait indefinitely. Subagents targeting another configured model keep that provider's normal behavior.
|
|
6
6
|
|
package/src/server.ts
CHANGED
|
@@ -96,6 +96,7 @@ export function createServer(broker: Broker): McpServer {
|
|
|
96
96
|
const { inputs, ...initialized } = await broker.initialize(
|
|
97
97
|
chatId,
|
|
98
98
|
args.sessionId,
|
|
99
|
+
context.mcpReq._meta?.["otunnel/requestId"],
|
|
99
100
|
context.mcpReq.signal,
|
|
100
101
|
);
|
|
101
102
|
return finishResult(broker, context, textResult(initialized, inputs));
|
|
@@ -114,7 +115,9 @@ export function createServer(broker: Broker): McpServer {
|
|
|
114
115
|
sessionId: z
|
|
115
116
|
.string()
|
|
116
117
|
.optional()
|
|
117
|
-
.describe(
|
|
118
|
+
.describe(
|
|
119
|
+
"Pi session for this operation; becomes the default if none is set",
|
|
120
|
+
),
|
|
118
121
|
}),
|
|
119
122
|
annotations: toolAnnotations,
|
|
120
123
|
},
|
|
@@ -124,6 +127,7 @@ export function createServer(broker: Broker): McpServer {
|
|
|
124
127
|
chatId,
|
|
125
128
|
args.sessionId,
|
|
126
129
|
args.text,
|
|
130
|
+
context.mcpReq._meta?.["otunnel/requestId"],
|
|
127
131
|
context.mcpReq.signal,
|
|
128
132
|
);
|
|
129
133
|
return finishResult(
|
|
@@ -158,6 +162,7 @@ export function createServer(broker: Broker): McpServer {
|
|
|
158
162
|
requireChatId(context),
|
|
159
163
|
sessionId,
|
|
160
164
|
input,
|
|
165
|
+
context.mcpReq._meta?.["otunnel/requestId"],
|
|
161
166
|
context.mcpReq.signal,
|
|
162
167
|
);
|
|
163
168
|
const result = await finishResult(broker, context, {
|
|
@@ -285,7 +290,9 @@ export function createServer(broker: Broker): McpServer {
|
|
|
285
290
|
sessionId: z
|
|
286
291
|
.string()
|
|
287
292
|
.optional()
|
|
288
|
-
.describe(
|
|
293
|
+
.describe(
|
|
294
|
+
"Pi session for this operation; becomes the default if none is set",
|
|
295
|
+
),
|
|
289
296
|
}),
|
|
290
297
|
annotations: toolAnnotations,
|
|
291
298
|
},
|
|
@@ -294,6 +301,7 @@ export function createServer(broker: Broker): McpServer {
|
|
|
294
301
|
requireChatId(context),
|
|
295
302
|
args.sessionId,
|
|
296
303
|
args.names,
|
|
304
|
+
context.mcpReq._meta?.["otunnel/requestId"],
|
|
297
305
|
context.mcpReq.signal,
|
|
298
306
|
);
|
|
299
307
|
return finishResult(
|
|
@@ -326,7 +334,9 @@ export function createServer(broker: Broker): McpServer {
|
|
|
326
334
|
sessionId: z
|
|
327
335
|
.string()
|
|
328
336
|
.optional()
|
|
329
|
-
.describe(
|
|
337
|
+
.describe(
|
|
338
|
+
"Pi session for this operation; becomes the default if none is set",
|
|
339
|
+
),
|
|
330
340
|
}),
|
|
331
341
|
annotations: toolAnnotations,
|
|
332
342
|
},
|
|
@@ -335,6 +345,7 @@ export function createServer(broker: Broker): McpServer {
|
|
|
335
345
|
requireChatId(context),
|
|
336
346
|
args.sessionId,
|
|
337
347
|
args.calls,
|
|
348
|
+
context.mcpReq._meta?.["otunnel/requestId"],
|
|
338
349
|
context.mcpReq.signal,
|
|
339
350
|
);
|
|
340
351
|
return finishResult(
|
|
@@ -374,6 +385,7 @@ export function createServer(broker: Broker): McpServer {
|
|
|
374
385
|
requireChatId(context),
|
|
375
386
|
sessionId,
|
|
376
387
|
calls,
|
|
388
|
+
context.mcpReq._meta?.["otunnel/requestId"],
|
|
377
389
|
context.mcpReq.signal,
|
|
378
390
|
);
|
|
379
391
|
return finishResult(
|
|
@@ -408,7 +420,12 @@ export function createServer(broker: Broker): McpServer {
|
|
|
408
420
|
handle(async (args, context) => {
|
|
409
421
|
const chatId = requestChatId(context);
|
|
410
422
|
const inputs = chatId
|
|
411
|
-
? await broker.inputs(
|
|
423
|
+
? await broker.inputs(
|
|
424
|
+
chatId,
|
|
425
|
+
args.sessionId,
|
|
426
|
+
context.mcpReq._meta?.["otunnel/requestId"],
|
|
427
|
+
context.mcpReq.signal,
|
|
428
|
+
)
|
|
412
429
|
: [];
|
|
413
430
|
const result = textResult(
|
|
414
431
|
{
|
package/src/session.ts
CHANGED
|
@@ -194,7 +194,6 @@ export class LocalSession {
|
|
|
194
194
|
this.#resetInputs(context);
|
|
195
195
|
}
|
|
196
196
|
if (!this.#connection) {
|
|
197
|
-
this.#notify("Connecting to Chappie…");
|
|
198
197
|
this.#connection = new IpcClient(this.#agentDir, this.#connect, {
|
|
199
198
|
onOpen: async () => {
|
|
200
199
|
await this.#sync();
|
package/src/state.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type { QuestionAnswer, QuestionRecord } from "./questions.ts";
|
|
|
5
5
|
|
|
6
6
|
interface StateFile {
|
|
7
7
|
bindings?: Record<string, string>;
|
|
8
|
+
joins?: Record<string, string[]>;
|
|
8
9
|
workflows?: Record<string, string>;
|
|
9
10
|
deliveries?: DeliveryRecord[];
|
|
10
11
|
questions?: QuestionRecord[];
|
|
@@ -14,6 +15,7 @@ export class State {
|
|
|
14
15
|
readonly #path: string;
|
|
15
16
|
readonly #temporaryPath: string;
|
|
16
17
|
readonly #bindings = new Map<string, string>();
|
|
18
|
+
readonly #joins = new Map<string, Set<string>>();
|
|
17
19
|
readonly #workflows = new Map<string, string>();
|
|
18
20
|
readonly #deliveries = new Map<string, DeliveryRecord>();
|
|
19
21
|
readonly #questions = new Map<string, QuestionRecord>();
|
|
@@ -36,6 +38,9 @@ export class State {
|
|
|
36
38
|
for (const [chatId, sessionId] of Object.entries(state.bindings ?? {})) {
|
|
37
39
|
if (typeof sessionId === "string") this.#bindings.set(chatId, sessionId);
|
|
38
40
|
}
|
|
41
|
+
for (const [chatId, ids] of Object.entries(state.joins ?? {})) {
|
|
42
|
+
this.#joins.set(chatId, new Set(ids));
|
|
43
|
+
}
|
|
39
44
|
for (const [chatId, id] of Object.entries(state.workflows ?? {})) {
|
|
40
45
|
this.#workflows.set(chatId, id);
|
|
41
46
|
}
|
|
@@ -59,12 +64,6 @@ export class State {
|
|
|
59
64
|
return this.#bindings.get(chatId);
|
|
60
65
|
}
|
|
61
66
|
|
|
62
|
-
chats(sessionId: string): string[] {
|
|
63
|
-
return [...this.#bindings]
|
|
64
|
-
.filter(([, target]) => target === sessionId)
|
|
65
|
-
.map(([chatId]) => chatId);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
67
|
bindingCounts(): Map<string, number> {
|
|
69
68
|
const counts = new Map<string, number>();
|
|
70
69
|
for (const sessionId of this.#bindings.values()) {
|
|
@@ -73,9 +72,21 @@ export class State {
|
|
|
73
72
|
return counts;
|
|
74
73
|
}
|
|
75
74
|
|
|
76
|
-
|
|
75
|
+
async join(
|
|
76
|
+
chatId: string,
|
|
77
|
+
sessionId: string,
|
|
78
|
+
workflowId: string | undefined,
|
|
79
|
+
): Promise<boolean> {
|
|
80
|
+
const changed = this.#bindings.get(chatId) !== sessionId;
|
|
81
|
+
const workflows = changed
|
|
82
|
+
? new Set<string>()
|
|
83
|
+
: (this.#joins.get(chatId) ?? new Set<string>());
|
|
84
|
+
if (!changed && (!workflowId || workflows.has(workflowId))) return false;
|
|
77
85
|
this.#bindings.set(chatId, sessionId);
|
|
78
|
-
|
|
86
|
+
if (workflowId) workflows.add(workflowId);
|
|
87
|
+
this.#joins.set(chatId, workflows);
|
|
88
|
+
await this.#save();
|
|
89
|
+
return true;
|
|
79
90
|
}
|
|
80
91
|
|
|
81
92
|
deliveries(chatId: string): DeliveryRecord[] {
|
|
@@ -168,10 +179,13 @@ export class State {
|
|
|
168
179
|
#save(): Promise<void> {
|
|
169
180
|
const saved = this.#writes.then(async () => {
|
|
170
181
|
const bindings = Object.fromEntries(this.#bindings);
|
|
182
|
+
const joins = Object.fromEntries(
|
|
183
|
+
[...this.#joins].map(([chatId, ids]) => [chatId, [...ids]]),
|
|
184
|
+
);
|
|
171
185
|
const workflows = Object.fromEntries(this.#workflows);
|
|
172
186
|
await writeFile(
|
|
173
187
|
this.#temporaryPath,
|
|
174
|
-
`${JSON.stringify({ bindings, workflows, deliveries: [...this.#deliveries.values()], questions: [...this.#questions.values()] }, null, 2)}\n`,
|
|
188
|
+
`${JSON.stringify({ bindings, joins, workflows, deliveries: [...this.#deliveries.values()], questions: [...this.#questions.values()] }, null, 2)}\n`,
|
|
175
189
|
{
|
|
176
190
|
mode: 0o600,
|
|
177
191
|
},
|
package/src/tools.ts
CHANGED
|
@@ -73,7 +73,8 @@ function withSessionId(
|
|
|
73
73
|
...copy.properties,
|
|
74
74
|
sessionId: {
|
|
75
75
|
type: "string",
|
|
76
|
-
description:
|
|
76
|
+
description:
|
|
77
|
+
"Pi session for this operation; becomes the default if none is set",
|
|
77
78
|
},
|
|
78
79
|
},
|
|
79
80
|
additionalProperties: false,
|