lody 0.103.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 +59 -1
- package/dist/baguette-worker.js +480 -0
- package/dist/chunks/{acp-BzvviK-N.js → acp-C0LiROfB.js} +3 -3
- package/dist/chunks/{cloudflared-native-DbUToPHH.js → cloudflared-native-BWtpTE_5.js} +3 -3
- package/dist/chunks/{daemon-session-tools-DESvdAeY.js → daemon-session-tools-C6AE_3JK.js} +12 -9
- package/dist/chunks/{directory-handle-CtdCjbNh.js → directory-handle-DgcESjFj.js} +28 -22
- package/dist/chunks/{index-DEdPzgH7.js → index-Sv4ANSUY.js} +8893 -2560
- package/dist/chunks/ios-simulator-hTbW-tat.js +161 -0
- package/dist/chunks/{review-viewer-BZiXmQnJ.js → review-viewer-nQBrydLp.js} +13 -10
- package/dist/chunks/{schemas-WuyisFi9.js → schemas-D_XLKCXC.js} +8 -8
- package/dist/claude-acp.js +1 -1
- package/dist/cloudflared-worker.js +2 -2
- package/dist/codex-acp.js +1 -1
- package/dist/deepseek-acp.js +253 -128
- package/dist/devin-acp.js +1152 -0
- package/dist/file-index-scan-worker.js +2 -2
- package/dist/index.js +107512 -37004
- package/package.json +7 -5
- package/dist/chunks/index-DhSXbMsB.js +0 -742
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`
|
|
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 {
|
|
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",
|
|
@@ -53,7 +53,7 @@ const ACP_EXTENSION_DSH_VERSION = "0.2.0";
|
|
|
53
53
|
const DEEPSEEK_HARNESS_VERSION = "0.1.5-rc.2";
|
|
54
54
|
const DEEPSEEK_HARNESS_PI_AI_VERSION = "0.85.1";
|
|
55
55
|
const DEEPSEEK_HARNESS_SCHEMASTERY_VERSION = "3.18.2";
|
|
56
|
-
const ACP_EXTENSION_DSH_PROFILE_REVISION = "
|
|
56
|
+
const ACP_EXTENSION_DSH_PROFILE_REVISION = "v15";
|
|
57
57
|
const ACP_EXTENSION_DSH_SESSION_ROOT_ENV = "ACP_EXTENSION_DSH_SESSION_ROOT";
|
|
58
58
|
const ACP_EXTENSION_DSH_QUERY_PATH_ENV = "ACP_EXTENSION_DSH_QUERY_PATH";
|
|
59
59
|
const DEEPSEEK_HARNESS_DEFAULT_SESSION_COMPRESSION = "zstd";
|
|
@@ -4943,4 +4943,4 @@ export {
|
|
|
4943
4943
|
DEEPSEEK_HARNESS_DEFAULT_MODEL as q,
|
|
4944
4944
|
DEEPSEEK_HARNESS_PROVIDER as r
|
|
4945
4945
|
};
|
|
4946
|
-
//# sourceMappingURL=acp-
|
|
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-
|
|
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
|
-
"
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
100
|
+
//# sourceMappingURL=daemon-session-tools-C6AE_3JK.js.map
|