lody 0.102.0 → 0.104.0

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 CHANGED
@@ -14,6 +14,38 @@ Install the CLI package:
14
14
  npm install -g lody@next
15
15
  ```
16
16
 
17
+ ## Daemon upgrades and autostart
18
+
19
+ Remote upgrades install globally using the daemon's npm environment, resolve the
20
+ installed package's declared CLI entry via `npm root -g`, and verify its version.
21
+ The watchdog launches that entry explicitly and only reports upgrade success after
22
+ the replacement reaches ready with the same version. A successful npm install alone
23
+ does not prove that the running daemon upgraded. Verification or handoff failure is
24
+ logged as failure; the existing restart recovery remains available.
25
+
26
+ Autostart scripts, scheduled tasks, and service definitions must invoke the stable
27
+ global installation, not an absolute `_npx` cache entry or a version-specific store
28
+ path. This repository does not generate or rewrite user-owned autostart scripts.
29
+ If an existing daemon was launched from such a pinned path:
30
+
31
+ 1. In the same OS environment and user account as the daemon, install the desired
32
+ version globally. Windows and WSL have separate installations.
33
+ 2. Find the global prefix with `npm prefix -g`. On Windows the stable launcher is
34
+ `<prefix>\lody.cmd`; on Linux/WSL/macOS it is `<prefix>/bin/lody`.
35
+ Check that launcher's `--version` before using it. Use the same Node/npm
36
+ installation and preserve the script's environment and daemon arguments.
37
+ 3. Replace the old cache path in the autostart command with that absolute launcher.
38
+ In PowerShell invoke a quoted launcher with `&`. Ensure the task's PATH includes
39
+ the intended Node runtime; WSL tasks must use the launcher inside that distro.
40
+ 4. Use the verified launcher to run `daemon stop`, then `daemon start` with the
41
+ original options, and check `daemon status` and the startup log's CLI version.
42
+ Restart the watchdog too: restarting only its Worker leaves old upgrade code alive.
43
+
44
+ An already-running old watchdog cannot acquire this fix merely by downloading it;
45
+ the one-time launcher correction and restart are needed for that deployment.
46
+ Older releases without versioned readiness cannot be verified by the new remote
47
+ handoff and must be started explicitly if a rollback is required.
48
+
17
49
  ## Workspace discovery
18
50
 
19
51
  The cloud workspace CLI and Lody MCP share resource queries. Lists return 20 entries
@@ -39,11 +71,20 @@ Matching MCP tools are `lody_machine_list`, `lody_project_list`,
39
71
  `lody_operation_list`. Session list adds `query`, `machineId`, `agentConfigId`,
40
72
  and `agentRoleId`. Creation provenance is what the Role filter matches.
41
73
 
74
+ `lody_session_create_options` and Agent config discovery expose `runConfig.modes`
75
+ and `runConfig.configOptions` (ids, types and choices, without current values).
76
+ Single and batch MCP creates accept `modeId` and `configOptionValues`, matching
77
+ CLI `--mode` and `--config-option` validation against target capabilities.
78
+ For example, a Grok target may use `configOptionValues: { permission_mode: "ask" }`;
79
+ its ACP mode `default` is not a permission policy. Explicit permissions may exceed
80
+ the parent; callers must follow their user authorization. Roles still override
81
+ manual configuration. Merge, Plan and retry behavior: [creation contract](../../specs/session-orchestration.md#session-creation-configuration).
82
+
42
83
  `project list` without catalog options retains the local daemon project listing.
43
84
  Workspace project listing now spans authorized machines and enabled GitHub repositories;
44
85
  `--machine` restricts it to local projects on that machine. Directory lists are
45
86
  paginated summaries rather than the old unbounded/full configuration dumps.
46
- `agent-config show` remains the trusted configuration inspection command;
87
+ `agent-config show` inspects a configuration with environment values hidden;
47
88
  `get` returns the safe discovery projection. Legacy `machine list --include-agents`
48
89
  and `--include-acp-capabilities` retain their detailed output and cannot combine with
49
90
  directory pagination/filter flags.
@@ -60,3 +101,20 @@ These workspace queries use the existing cloud command runtime. The OSS local
60
101
  composition does not enable cloud queries; local project listing remains available.
61
102
  Catalog `--offline` skips catalog synchronization but still verifies authorization;
62
103
  GitHub repository listing requires connectivity.
104
+
105
+ ## Agent configuration output
106
+
107
+ `agent-config show [id] [--json]` returns sorted `envKeys`, not environment values.
108
+ Text output marks every key `[configured]`, including empty values. For deliberate
109
+ inspection, `show --show-secrets` includes the original values (`env` in JSON).
110
+ That output may contain credentials: use it only where the output is trusted.
111
+ The flag is only available on `show`; list/get remain safe discovery summaries.
112
+
113
+ JSON create/update responses contain `ok`, `workspaceId`, `agentConfigId` and
114
+ `changedFields` (initialized/requested field names, not values), rather than `agentConfig`.
115
+ Scripts should read `agentConfigId` for the saved id and use a separate `show`
116
+ when inspection is needed. Scripts reading `show.agentConfig.env` must explicitly
117
+ opt in to secret output, or migrate to `envKeys`. The output is a presentation
118
+ contract, not a full configuration backup; runtime/auth/custom-launch fields are
119
+ not exported. No masked placeholder is stored or returned as an environment value.
120
+ Assignment errors report entry/line numbers without echoing their contents.
@@ -0,0 +1,480 @@
1
+ import { spawn } from "node:child_process";
2
+ import { createServer } from "node:net";
3
+ import { setTimeout as setTimeout$1 } from "node:timers/promises";
4
+ import { mkdtemp, writeFile, rm } from "node:fs/promises";
5
+ import { tmpdir } from "node:os";
6
+ import { join } from "node:path";
7
+ import { l as IosSimulatorDeviceControlSchema } from "./chunks/ios-simulator-hTbW-tat.js";
8
+ import { s as string, o as object, e as union, a as _enum, n as number, l as literal } from "./chunks/schemas-D_XLKCXC.js";
9
+ const guestButtonsSource = String.raw`
10
+ #import <Foundation/Foundation.h>
11
+ #import <objc/message.h>
12
+ #import <dlfcn.h>
13
+ #import <mach/mach_time.h>
14
+ #import <signal.h>
15
+ #import <unistd.h>
16
+
17
+ @interface LodyButtonProperties : NSObject
18
+ @end
19
+ @implementation LodyButtonProperties
20
+ - (id)propertyForKey:(NSString *)key forService:(id)service {
21
+ return (@{@"PrimaryUsagePage": @11, @"PrimaryUsage": @1,
22
+ @"DeviceUsagePairs": @[@{@"DeviceUsagePage": @11, @"DeviceUsage": @1}],
23
+ @"Transport": @"CoreDevice", @"Product": @"Lody simulator buttons",
24
+ @"Built-In": @YES, @"VendorID": @0, @"ProductID": @0,
25
+ @"VersionNumber": @0, @"ReportInterval": @8000})[key];
26
+ }
27
+ - (BOOL)setProperty:(id)value forKey:(NSString *)key forService:(id)service { return YES; }
28
+ - (id)copyEventMatching:(id)matching forService:(id)service { return nil; }
29
+ - (BOOL)setOutputEvent:(id)event forService:(id)service { return YES; }
30
+ - (void)notification:(uint32_t)type withProperty:(id)property forService:(id)service {}
31
+ @end
32
+ static volatile sig_atomic_t stopping = 0;
33
+ static void stop(int sig) { stopping = 1; }
34
+ int main(void) {
35
+ @autoreleasepool {
36
+ signal(SIGTERM, stop); signal(SIGINT, stop);
37
+ dlopen("/System/Library/PrivateFrameworks/HID.framework/HID", RTLD_NOW);
38
+ void *lib = dlopen("/System/Library/Frameworks/IOKit.framework/IOKit", RTLD_NOW);
39
+ CFTypeRef (*event)(CFAllocatorRef,uint64_t,uint32_t,uint32_t,Boolean,uint32_t) =
40
+ dlsym(lib, "IOHIDEventCreateKeyboardEvent");
41
+ id service = [[NSClassFromString(@"HIDVirtualEventService") alloc] init];
42
+ if (!event || !service) return 1;
43
+ LodyButtonProperties *properties = [LodyButtonProperties new];
44
+ ((void (*)(id,SEL,id))objc_msgSend)(service,sel_registerName("setDelegate:"),properties);
45
+ dispatch_queue_t queue = dispatch_queue_create("ai.lody.simulator.buttons", DISPATCH_QUEUE_SERIAL);
46
+ ((void (*)(id,SEL,id))objc_msgSend)(service,sel_registerName("setDispatchQueue:"),queue);
47
+ ((void (*)(id,SEL))objc_msgSend)(service,sel_registerName("activate"));
48
+ if (!((uint64_t (*)(id,SEL))objc_msgSend)(service,sel_registerName("serviceID"))) return 1;
49
+ // The guest enumerates the newly registered service asynchronously.
50
+ usleep(300000);
51
+ if (!stopping) { puts("ready"); fflush(stdout); }
52
+ char line[64];
53
+ while (!stopping && fgets(line,sizeof(line),stdin)) {
54
+ unsigned sequence = 0; char name[32], extra;
55
+ if (sscanf(line,"%u %31s %c",&sequence,name,&extra) != 2 || !sequence) break;
56
+ unsigned usage = 0, count = 1;
57
+ if (!strcmp(name,"home")) usage = 64;
58
+ else if (!strcmp(name,"app-switcher")) { usage = 64; count = 2; }
59
+ else if (!strcmp(name,"lock")) usage = 48;
60
+ else break;
61
+ BOOL ok = YES;
62
+ for (unsigned i=0; i<count && !stopping; i++) {
63
+ CFTypeRef down = event(kCFAllocatorDefault,mach_absolute_time(),12,usage,true,0);
64
+ if (!down) { ok = NO; break; }
65
+ BOOL sent = ((BOOL (*)(id,SEL,id))objc_msgSend)(service,sel_registerName("dispatchEvent:"),(__bridge id)down);
66
+ CFRelease(down);
67
+ usleep(100000);
68
+ // Always release a submitted down, including a shutdown during the hold.
69
+ CFTypeRef up = event(kCFAllocatorDefault,mach_absolute_time(),12,usage,false,0);
70
+ BOOL released = up && ((BOOL (*)(id,SEL,id))objc_msgSend)(service,sel_registerName("dispatchEvent:"),(__bridge id)up);
71
+ if (up) CFRelease(up);
72
+ ok = ok && sent && released;
73
+ if (i+1<count) usleep(150000);
74
+ }
75
+ if (stopping) break;
76
+ printf("%u %s\n",sequence,ok ? "ok" : "error"); fflush(stdout);
77
+ if (!ok) break;
78
+ }
79
+ ((void (*)(id,SEL))objc_msgSend)(service,sel_registerName("cancel"));
80
+ return 0;
81
+ }
82
+ }
83
+ `;
84
+ function createGuestButtons(signal, executable = "/usr/bin/xcrun") {
85
+ let directory;
86
+ let device;
87
+ let child2;
88
+ let childClosed;
89
+ let preparing;
90
+ let pending;
91
+ let sequence = 0;
92
+ let failed = false;
93
+ let stopping;
94
+ const error = () => new Error("Simulator buttons unavailable.");
95
+ const fail = () => {
96
+ failed = true;
97
+ pending?.reject(error());
98
+ pending = void 0;
99
+ };
100
+ let terminating;
101
+ function terminate() {
102
+ if (terminating) return terminating;
103
+ const owned = child2;
104
+ if (!owned) return Promise.resolve();
105
+ const closed = childClosed;
106
+ terminating = (async () => {
107
+ owned.stdin.end();
108
+ const send = (terminationSignal) => {
109
+ if (owned.pid) {
110
+ try {
111
+ process.kill(-owned.pid, terminationSignal);
112
+ return true;
113
+ } catch (e) {
114
+ if (!(e instanceof Error && "code" in e && e.code === "ESRCH")) throw e;
115
+ }
116
+ }
117
+ return false;
118
+ };
119
+ const term = setTimeout(() => send("SIGTERM"), 1e3);
120
+ const kill = setTimeout(() => send("SIGKILL"), 2e3);
121
+ await closed;
122
+ clearTimeout(term);
123
+ clearTimeout(kill);
124
+ if (send("SIGTERM")) {
125
+ const killAt = Date.now() + 1e3;
126
+ while (send(0)) {
127
+ if (Date.now() >= killAt) send("SIGKILL");
128
+ await setTimeout$1(25);
129
+ }
130
+ }
131
+ if (child2 === owned) child2 = void 0;
132
+ })();
133
+ return terminating;
134
+ }
135
+ function launch(args, protocol) {
136
+ signal.throwIfAborted();
137
+ if (failed) throw error();
138
+ const process2 = spawn(executable, args, { detached: true, stdio: ["pipe", "pipe", "ignore"] });
139
+ child2 = process2;
140
+ terminating = void 0;
141
+ childClosed = new Promise((resolve) => process2.once("close", resolve));
142
+ process2.stdin.on("error", fail);
143
+ return new Promise((resolve, reject) => {
144
+ let ready = false;
145
+ let buffer = "";
146
+ process2.once("error", () => {
147
+ fail();
148
+ reject(error());
149
+ });
150
+ process2.once("close", (code) => {
151
+ if (!protocol && code === 0 && !signal.aborted) resolve();
152
+ else {
153
+ fail();
154
+ reject(error());
155
+ }
156
+ });
157
+ if (protocol) {
158
+ pending = {
159
+ line: "ready",
160
+ resolve: () => {
161
+ ready = true;
162
+ resolve();
163
+ },
164
+ reject
165
+ };
166
+ process2.stdout.setEncoding("utf8");
167
+ process2.stdout.on("data", (chunk) => {
168
+ buffer += chunk;
169
+ if (buffer.length > 1024) {
170
+ fail();
171
+ void terminate();
172
+ return;
173
+ }
174
+ while (buffer.includes("\n")) {
175
+ const at = buffer.indexOf("\n");
176
+ const line = buffer.slice(0, at);
177
+ buffer = buffer.slice(at + 1);
178
+ const request = pending;
179
+ if (!request || line !== request.line || line === "ready" && ready) {
180
+ fail();
181
+ void terminate();
182
+ return;
183
+ }
184
+ pending = void 0;
185
+ request.resolve();
186
+ }
187
+ });
188
+ } else process2.stdin.end();
189
+ });
190
+ }
191
+ async function prepare(udid) {
192
+ directory = await mkdtemp(join(tmpdir(), "lody-simulator-buttons-"));
193
+ signal.throwIfAborted();
194
+ const source = join(directory, "buttons.m");
195
+ const binary = join(directory, "buttons");
196
+ await writeFile(source, guestButtonsSource, { mode: 384 });
197
+ await launch(
198
+ [
199
+ "--sdk",
200
+ "iphonesimulator",
201
+ "clang",
202
+ "-arch",
203
+ "arm64",
204
+ "-target",
205
+ "arm64-apple-ios17.0-simulator",
206
+ "-framework",
207
+ "Foundation",
208
+ "-fobjc-arc",
209
+ "-Wl,-adhoc_codesign",
210
+ source,
211
+ "-o",
212
+ binary
213
+ ],
214
+ false
215
+ );
216
+ await launch(["simctl", "spawn", udid, binary], true);
217
+ }
218
+ const close = () => {
219
+ stopping ??= (async () => {
220
+ fail();
221
+ await terminate();
222
+ await preparing?.catch(() => {
223
+ });
224
+ if (directory) await rm(directory, { recursive: true, force: true });
225
+ signal.removeEventListener("abort", onAbort);
226
+ })();
227
+ return stopping;
228
+ };
229
+ const onAbort = () => {
230
+ void close().catch(() => {
231
+ });
232
+ };
233
+ signal.addEventListener("abort", onAbort, { once: true });
234
+ return {
235
+ close,
236
+ async prepare(udid) {
237
+ await this.press(udid);
238
+ },
239
+ async press(udid, button) {
240
+ signal.throwIfAborted();
241
+ if (failed || pending || device && device !== udid) throw error();
242
+ device = udid;
243
+ const timeout = setTimeout(() => {
244
+ void close().catch(() => {
245
+ });
246
+ }, 1e4);
247
+ try {
248
+ preparing ??= prepare(udid);
249
+ await preparing;
250
+ if (failed || signal.aborted || !child2) throw error();
251
+ if (!button) return;
252
+ const id = ++sequence;
253
+ await new Promise((resolve, reject) => {
254
+ pending = { line: `${id} ok`, resolve, reject };
255
+ child2?.stdin.write(`${id} ${button}
256
+ `, (err) => {
257
+ if (err) fail();
258
+ });
259
+ });
260
+ } catch {
261
+ await close();
262
+ throw error();
263
+ } finally {
264
+ clearTimeout(timeout);
265
+ }
266
+ }
267
+ };
268
+ }
269
+ async function runSimulatorHostControl(udid, control, signal, executable = "/usr/bin/xcrun") {
270
+ async function run(args, input) {
271
+ signal.throwIfAborted();
272
+ return new Promise((resolve, reject) => {
273
+ const child2 = spawn(executable, args, {
274
+ stdio: ["pipe", "ignore", "ignore"],
275
+ // The IPC worker has a filtered environment. simctl decodes stdin with
276
+ // the locale, so an unset locale rejects non-ASCII pasteboard contents.
277
+ env: { ...process.env, LANG: "en_US.UTF-8", LC_ALL: "en_US.UTF-8" }
278
+ });
279
+ let kill;
280
+ const cancel = () => {
281
+ child2.kill("SIGTERM");
282
+ kill ??= setTimeout(() => child2.kill("SIGKILL"), 1e3);
283
+ };
284
+ signal.addEventListener("abort", cancel, { once: true });
285
+ if (signal.aborted) cancel();
286
+ child2.stdin.on("error", () => {
287
+ });
288
+ child2.stdin.end(input);
289
+ let failed = false;
290
+ child2.once("error", () => {
291
+ failed = true;
292
+ });
293
+ child2.once("close", (code2) => {
294
+ clearTimeout(kill);
295
+ signal.removeEventListener("abort", cancel);
296
+ if (signal.aborted || failed) reject(new Error("Simulator control failed."));
297
+ else resolve(code2);
298
+ });
299
+ });
300
+ }
301
+ let code;
302
+ switch (control.kind) {
303
+ case "prepare-buttons":
304
+ case "button":
305
+ throw new Error("Simulator buttons require the owned guest service.");
306
+ case "prepare-keyboard":
307
+ code = await run([
308
+ "simctl",
309
+ "spawn",
310
+ udid,
311
+ "defaults",
312
+ "write",
313
+ "com.apple.Preferences",
314
+ "AutomaticMinimizationEnabled",
315
+ "-bool",
316
+ "false"
317
+ ]);
318
+ if (code === 0)
319
+ code = await run([
320
+ "simctl",
321
+ "spawn",
322
+ udid,
323
+ "notifyutil",
324
+ "-p",
325
+ "com.apple.keyboard.preferences.changed"
326
+ ]);
327
+ break;
328
+ case "text":
329
+ code = await run(
330
+ ["devicectl", "device", "pasteboard", "copy", "--device", udid],
331
+ control.text
332
+ );
333
+ if (code !== 0) code = await run(["simctl", "pbcopy", udid], control.text);
334
+ break;
335
+ case "shake":
336
+ code = await run([
337
+ "simctl",
338
+ "spawn",
339
+ udid,
340
+ "notifyutil",
341
+ "-p",
342
+ "com.apple.UIKit.SimulatorShake"
343
+ ]);
344
+ break;
345
+ case "appearance":
346
+ code = await run(["simctl", "ui", udid, "appearance", control.appearance]);
347
+ break;
348
+ case "open-url":
349
+ code = await run(["simctl", "openurl", udid, control.url]);
350
+ break;
351
+ }
352
+ if (code !== 0) throw new Error("Simulator control failed.");
353
+ }
354
+ const abort = new AbortController();
355
+ const stop = () => abort.abort();
356
+ const buttons = createGuestButtons(abort.signal);
357
+ process.on("disconnect", stop);
358
+ let pendingHostControl;
359
+ const onMessage = (raw) => {
360
+ const request = object({
361
+ type: literal("control"),
362
+ id: number().int().positive(),
363
+ udid: string().uuid(),
364
+ control: union([
365
+ IosSimulatorDeviceControlSchema,
366
+ object({ kind: _enum(["prepare-keyboard", "prepare-buttons"]) }).strict()
367
+ ])
368
+ }).strict().safeParse(raw);
369
+ if (!request.success || pendingHostControl || abort.signal.aborted) {
370
+ stop();
371
+ return;
372
+ }
373
+ const { id, udid, control } = request.data;
374
+ if (!(control.kind === "button" && ["home", "app-switcher", "lock"].includes(control.button)) && control.kind !== "text" && control.kind !== "appearance" && control.kind !== "open-url" && control.kind !== "shake" && control.kind !== "prepare-buttons" && control.kind !== "prepare-keyboard") {
375
+ stop();
376
+ return;
377
+ }
378
+ pendingHostControl = (control.kind === "prepare-buttons" ? buttons.prepare(udid) : control.kind === "button" ? buttons.press(udid, _enum(["home", "app-switcher", "lock"]).parse(control.button)) : runSimulatorHostControl(
379
+ udid,
380
+ control,
381
+ AbortSignal.any([abort.signal, AbortSignal.timeout(1e4)])
382
+ )).then(
383
+ () => {
384
+ if (process.connected) process.send?.({ type: "control-result", id, success: true });
385
+ },
386
+ () => {
387
+ if (process.connected) process.send?.({ type: "control-result", id, success: false });
388
+ }
389
+ ).finally(() => {
390
+ pendingHostControl = void 0;
391
+ });
392
+ };
393
+ process.on("message", onMessage);
394
+ process.once("SIGTERM", stop);
395
+ process.once("SIGINT", stop);
396
+ let child;
397
+ let exited;
398
+ try {
399
+ if (!process.connected) throw new Error("Missing lifecycle owner");
400
+ const binary = string().min(1).parse(process.argv[2]);
401
+ const reservation = createServer();
402
+ await new Promise((resolve, reject) => {
403
+ reservation.once("error", reject);
404
+ reservation.listen(0, "127.0.0.1", resolve);
405
+ });
406
+ const address = reservation.address();
407
+ if (!address || typeof address === "string") throw new Error("Port allocation failed");
408
+ const port = address.port;
409
+ await new Promise(
410
+ (resolve, reject) => reservation.close((error) => error ? reject(error) : resolve())
411
+ );
412
+ abort.signal.throwIfAborted();
413
+ child = spawn(binary, ["serve", "--host", "127.0.0.1", "--port", String(port), "--no-plugins"], {
414
+ // Isolate the native server and its xcrun descendants in our own process group.
415
+ detached: true,
416
+ stdio: "ignore",
417
+ env: process.env
418
+ });
419
+ exited = new Promise((resolve) => {
420
+ child?.once("error", () => {
421
+ stop();
422
+ resolve();
423
+ });
424
+ child?.once("exit", () => {
425
+ stop();
426
+ resolve();
427
+ });
428
+ });
429
+ const signal = AbortSignal.any([abort.signal, AbortSignal.timeout(3e4)]);
430
+ while (true) {
431
+ signal.throwIfAborted();
432
+ try {
433
+ const response = await fetch(`http://127.0.0.1:${port}/simulators`, {
434
+ signal: AbortSignal.any([signal, AbortSignal.timeout(1e3)])
435
+ });
436
+ await response.body?.cancel();
437
+ if (response.ok) break;
438
+ } catch {
439
+ signal.throwIfAborted();
440
+ }
441
+ await setTimeout$1(100, void 0, { signal });
442
+ }
443
+ process.send?.({ type: "ready", port });
444
+ await new Promise((resolve) => {
445
+ if (abort.signal.aborted) resolve();
446
+ else abort.signal.addEventListener("abort", () => resolve(), { once: true });
447
+ });
448
+ } catch {
449
+ process.exitCode = 1;
450
+ } finally {
451
+ stop();
452
+ await pendingHostControl;
453
+ await buttons.close().catch(() => {
454
+ process.exitCode = 1;
455
+ });
456
+ if (child?.pid !== void 0) {
457
+ const group = -child.pid;
458
+ const signalGroup = (signal) => {
459
+ try {
460
+ process.kill(group, signal);
461
+ return true;
462
+ } catch (error) {
463
+ if (error instanceof Error && "code" in error && error.code === "ESRCH") return false;
464
+ throw error;
465
+ }
466
+ };
467
+ if (signalGroup("SIGTERM")) {
468
+ const killAt = Date.now() + 3e3;
469
+ while (signalGroup(0)) {
470
+ if (Date.now() >= killAt) signalGroup("SIGKILL");
471
+ await setTimeout$1(25);
472
+ }
473
+ }
474
+ await exited;
475
+ }
476
+ process.removeListener("disconnect", stop);
477
+ process.removeListener("message", onMessage);
478
+ if (process.connected) process.disconnect();
479
+ }
480
+ //# sourceMappingURL=baguette-worker.js.map
@@ -1,5 +1,5 @@
1
1
  import { pathToFileURL } from "node:url";
2
- import { c as array, u as unknown, N as NEVER, e as union, n as number, s as string, o as object, r as record, Q as int, l as literal, b as boolean, E as intersection, H as url } from "./schemas-WuyisFi9.js";
2
+ import { b as array, u as unknown, N as NEVER, e as union, n as number, s as string, o as object, r as record, Q as int, l as literal, c as boolean, D as intersection, H as url } from "./schemas-D_XLKCXC.js";
3
3
  const DEEPSEEK_HARNESS_PERMISSION_PRESETS = [
4
4
  {
5
5
  id: "read-only",
@@ -51,7 +51,9 @@ const DEEPSEEK_HARNESS_AGENT_PRESETS = [
51
51
  ];
52
52
  const ACP_EXTENSION_DSH_VERSION = "0.2.0";
53
53
  const DEEPSEEK_HARNESS_VERSION = "0.1.5-rc.2";
54
- const ACP_EXTENSION_DSH_PROFILE_REVISION = "v13";
54
+ const DEEPSEEK_HARNESS_PI_AI_VERSION = "0.85.1";
55
+ const DEEPSEEK_HARNESS_SCHEMASTERY_VERSION = "3.18.2";
56
+ const ACP_EXTENSION_DSH_PROFILE_REVISION = "v15";
55
57
  const ACP_EXTENSION_DSH_SESSION_ROOT_ENV = "ACP_EXTENSION_DSH_SESSION_ROOT";
56
58
  const ACP_EXTENSION_DSH_QUERY_PATH_ENV = "ACP_EXTENSION_DSH_QUERY_PATH";
57
59
  const DEEPSEEK_HARNESS_DEFAULT_SESSION_COMPRESSION = "zstd";
@@ -308,7 +310,11 @@ const DEEPSEEK_HARNESS_CORDIS_PACKAGE_VERSIONS = {
308
310
  "@deepseek-ai/cordis-plugin-timer": "1.1.4"
309
311
  };
310
312
  function createDeepSeekHarnessNpxSpecifiers(versions = DEEPSEEK_HARNESS_CORDIS_PACKAGE_VERSIONS) {
311
- return DEEPSEEK_HARNESS_NPX_PACKAGES.map((packageName) => `${packageName}@${versions[packageName] ?? DEEPSEEK_HARNESS_VERSION}`);
313
+ return [
314
+ ...DEEPSEEK_HARNESS_NPX_PACKAGES.map((packageName) => `${packageName}@${versions[packageName] ?? DEEPSEEK_HARNESS_VERSION}`),
315
+ `@earendil-works/pi-ai@${DEEPSEEK_HARNESS_PI_AI_VERSION}`,
316
+ `@deepseek-ai/schemastery@${DEEPSEEK_HARNESS_SCHEMASTERY_VERSION}`
317
+ ];
312
318
  }
313
319
  function toAdapterModuleSpecifier(adapterPath, windows = process.platform === "win32") {
314
320
  if (adapterPath.startsWith("file:"))
@@ -369,6 +375,14 @@ function createDeepSeekHarnessProfileFiles(config) {
369
375
  provider: ${JSON.stringify(provider)}
370
376
  model: ${JSON.stringify(model)}
371
377
 
378
+ # Dormant until llm-pi-ai.providers in settings.yaml declares a route. The
379
+ # upstream adapter owns profile validation, route lifecycle, and credentials.
380
+ - id: llm-pi-ai
381
+ name: '@deepseek-ai/dsh-llm-pi-ai'
382
+ inject: [settings]
383
+ config:
384
+ providers: {}
385
+
372
386
  # Preserve the product's three permission modes with client-facing labels.
373
387
  - id: permission
374
388
  config:
@@ -4929,4 +4943,4 @@ export {
4929
4943
  DEEPSEEK_HARNESS_DEFAULT_MODEL as q,
4930
4944
  DEEPSEEK_HARNESS_PROVIDER as r
4931
4945
  };
4932
- //# sourceMappingURL=acp-Bsd2Lmd6.js.map
4946
+ //# sourceMappingURL=acp-C0LiROfB.js.map
@@ -2,7 +2,7 @@ import { spawn } from "node:child_process";
2
2
  import { mkdtemp, writeFile, rm } from "node:fs/promises";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
- import { o as object, a as _enum, s as string } from "./schemas-WuyisFi9.js";
5
+ import { o as object, a as _enum, s as string } from "./schemas-D_XLKCXC.js";
6
6
  class CloudflaredError extends Error {
7
7
  constructor(stage, message, cause) {
8
8
  super(message, { cause });
@@ -76,7 +76,7 @@ async function startCloudflaredNative(options) {
76
76
  "--metrics",
77
77
  "127.0.0.1:0",
78
78
  "--protocol",
79
- "auto",
79
+ "http2",
80
80
  "--url",
81
81
  proxy.origin
82
82
  ],
@@ -237,4 +237,4 @@ export {
237
237
  CloudflaredError as C,
238
238
  startCloudflaredNative as s
239
239
  };
240
- //# sourceMappingURL=cloudflared-native-DbUToPHH.js.map
240
+ //# sourceMappingURL=cloudflared-native-BWtpTE_5.js.map
@@ -7,7 +7,7 @@ import "fs";
7
7
  import "crypto";
8
8
  import "node:os";
9
9
  import "node:path";
10
- import "./schemas-WuyisFi9.js";
10
+ import "./schemas-D_XLKCXC.js";
11
11
  import "node:events";
12
12
  import "node:child_process";
13
13
  import "node:process";
@@ -28,8 +28,9 @@ import "node:fs/promises";
28
28
  import "node:zlib";
29
29
  import "child_process";
30
30
  import "./plan-mode-D0D5cnMs.js";
31
- import "./acp-Bsd2Lmd6.js";
31
+ import "./acp-C0LiROfB.js";
32
32
  import "node:url";
33
+ import "./ios-simulator-hTbW-tat.js";
33
34
  import "./subagent-events-BJ9JwZva.js";
34
35
  import "./loro_wasm_bg-DIxpLA2J.js";
35
36
  import "perf_hooks";
@@ -52,19 +53,21 @@ import "node:util/types";
52
53
  import "node:worker_threads";
53
54
  import "node:console";
54
55
  import "node:dns";
55
- import "./directory-handle-CtdCjbNh.js";
56
- import "./diff-line-counts-DDGc5P-T.js";
57
56
  import "node:stream/promises";
58
57
  import "node:string_decoder";
58
+ import "async_hooks";
59
+ import "./cloudflared-native-BWtpTE_5.js";
60
+ import "node:dns/promises";
61
+ import "dgram";
62
+ import "timers/promises";
63
+ import "node:timers/promises";
64
+ import "./directory-handle-DgcESjFj.js";
65
+ import "./diff-line-counts-DDGc5P-T.js";
59
66
  import "./package-BoOO46ct.js";
60
67
  import "./session-DyqwlJbY.js";
61
- import "async_hooks";
62
68
  import "module";
63
69
  import "./diff-worker-task-MZsLArT5.js";
64
70
  import "./workspace-watch-protocol-POg9Lpeq.js";
65
- import "node:dns/promises";
66
- import "./cloudflared-native-DbUToPHH.js";
67
- import "node:timers/promises";
68
71
  import "node:module";
69
72
  import "node:v8";
70
73
  import "http2";
@@ -94,4 +97,4 @@ async function executeDaemonSessionTool(context, name, args) {
94
97
  export {
95
98
  executeDaemonSessionTool
96
99
  };
97
- //# sourceMappingURL=daemon-session-tools-BeXk1A1E.js.map
100
+ //# sourceMappingURL=daemon-session-tools-C6AE_3JK.js.map