@muha-sdk/agy-adapter 0.0.0-stage → 0.1.13

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.
@@ -0,0 +1,205 @@
1
+ #define _GNU_SOURCE
2
+ #include <errno.h>
3
+ #include <fcntl.h>
4
+ #include <limits.h>
5
+ #include <poll.h>
6
+ #include <signal.h>
7
+ #include <stdbool.h>
8
+ #include <stdio.h>
9
+ #include <stdlib.h>
10
+ #include <string.h>
11
+ #include <sys/prctl.h>
12
+ #include <sys/signalfd.h>
13
+ #include <sys/types.h>
14
+ #include <sys/wait.h>
15
+ #include <time.h>
16
+ #include <unistd.h>
17
+
18
+ /* fd 0/1/2 belong to the CLI; fd 3 is a private duplex
19
+ * control channel, closed before native exec. The helper is single-threaded
20
+ * and the only reaper of its children. Shared by AGY and the ACP transport.
21
+ * ADR-0128 (AGY) and ADR-0138 (shared ACP) separately exclude complete
22
+ * reclamation after this helper's own death; callers must report that failure.
23
+ * This process alone cannot reclaim descendants after its own SIGKILL. */
24
+ static int control_fd = 3;
25
+ static int signal_fd = -1;
26
+ static int exec_fd = -1;
27
+ static pid_t native_pid = -1;
28
+ static bool closing = false;
29
+ static bool cleanup_error = false;
30
+ static long long force_at;
31
+ static char children_path[96];
32
+
33
+ static long long now_ms(void) {
34
+ struct timespec value;
35
+ if (clock_gettime(CLOCK_MONOTONIC, &value) < 0) _exit(125);
36
+ return (long long)value.tv_sec * 1000 + value.tv_nsec / 1000000;
37
+ }
38
+
39
+ static void error_event(const char *operation) {
40
+ int saved = errno;
41
+ dprintf(control_fd, "{\"type\":\"error\",\"operation\":\"%s\",\"errno\":%d}\n", operation, saved);
42
+ cleanup_error = true;
43
+ }
44
+
45
+ /* No wait(), SIGCHLD reaper, SA_NOCLDWAIT, or second thread may run between
46
+ * reading a PID here and signalling it. Even an exited direct child remains
47
+ * ours, unreaped, so its PID cannot be reused. A truncated/racing list is never
48
+ * treated as complete: subsequent adoption passes continue until ECHILD. */
49
+ static int signal_direct_children(int signo) {
50
+ FILE *children = fopen(children_path, "re");
51
+ if (!children) return -1;
52
+ long value;
53
+ int count = 0;
54
+ while (fscanf(children, "%ld", &value) == 1) {
55
+ if (value <= 1 || value > INT_MAX || value == getpid()) {
56
+ errno = EINVAL;
57
+ fclose(children);
58
+ return -1;
59
+ }
60
+ if (kill((pid_t)value, signo) < 0 && errno != ESRCH) {
61
+ int saved = errno;
62
+ fclose(children);
63
+ errno = saved;
64
+ return -1;
65
+ }
66
+ count++;
67
+ }
68
+ if (ferror(children)) {
69
+ int saved = errno;
70
+ fclose(children);
71
+ errno = saved;
72
+ return -1;
73
+ }
74
+ fclose(children);
75
+ return count;
76
+ }
77
+
78
+ static void start_close(const char *reason, int signo, long grace_ms) {
79
+ if (closing) return;
80
+ closing = true;
81
+ force_at = now_ms() + grace_ms;
82
+ dprintf(control_fd, "{\"type\":\"closing\",\"reason\":\"%s\"}\n", reason);
83
+ if (signal_direct_children(signo) < 0) error_event("signalOwnedChildren");
84
+ }
85
+
86
+ /* Returns true only after the kernel confirms that this sole owner has no
87
+ * children left. Once native spawning is disabled, ECHILD also excludes any
88
+ * remaining descendant that could later fork or become an adopted orphan. */
89
+ static bool reap_children(void) {
90
+ int status;
91
+ pid_t pid;
92
+ while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
93
+ if (pid == native_pid) {
94
+ native_pid = -1;
95
+ dprintf(control_fd, "{\"type\":\"nativeExit\",\"code\":%d,\"signal\":%d}\n",
96
+ WIFEXITED(status) ? WEXITSTATUS(status) : -1,
97
+ WIFSIGNALED(status) ? WTERMSIG(status) : 0);
98
+ if (!closing) start_close("nativeExit", SIGKILL, 0);
99
+ }
100
+ }
101
+ if (pid < 0 && errno != ECHILD && errno != EINTR) error_event("waitpid");
102
+ return pid < 0 && errno == ECHILD;
103
+ }
104
+
105
+ static void start_native(char **argv, const sigset_t *original_mask, const struct sigaction *original_pipe) {
106
+ int startup[2];
107
+ if (pipe2(startup, O_CLOEXEC) < 0) { error_event("execPipe"); start_close("spawnError", SIGKILL, 0); return; }
108
+ if (fcntl(startup[0], F_SETFL, O_NONBLOCK) < 0) {
109
+ close(startup[0]); close(startup[1]); error_event("execPipeFlags"); start_close("spawnError", SIGKILL, 0); return;
110
+ }
111
+ native_pid = fork();
112
+ if (native_pid == 0) {
113
+ close(startup[0]);
114
+ close(control_fd);
115
+ close(signal_fd);
116
+ if (sigprocmask(SIG_SETMASK, original_mask, NULL) < 0 || sigaction(SIGPIPE, original_pipe, NULL) < 0 || setsid() < 0) {
117
+ int saved = errno;
118
+ _exit(write(startup[1], &saved, sizeof(saved)) == sizeof(saved) ? 126 : 125);
119
+ }
120
+ execvp(argv[0], argv);
121
+ int saved = errno;
122
+ _exit(write(startup[1], &saved, sizeof(saved)) == sizeof(saved) ? 127 : 125);
123
+ }
124
+ close(startup[1]);
125
+ if (native_pid < 0) {
126
+ close(startup[0]); error_event("fork"); start_close("spawnError", SIGKILL, 0); return;
127
+ }
128
+ exec_fd = startup[0];
129
+ }
130
+
131
+ static void observe_exec(void) {
132
+ if (exec_fd < 0) return;
133
+ int exec_errno = 0;
134
+ ssize_t size = read(exec_fd, &exec_errno, sizeof(exec_errno));
135
+ if (size < 0 && (errno == EAGAIN || errno == EINTR)) return;
136
+ close(exec_fd);
137
+ exec_fd = -1;
138
+ if (size != 0) {
139
+ errno = size == sizeof(exec_errno) ? exec_errno : EIO;
140
+ error_event("exec"); start_close("spawnError", SIGKILL, 0); return;
141
+ }
142
+ dprintf(control_fd, "{\"type\":\"spawned\",\"pid\":%d}\n", native_pid);
143
+ }
144
+
145
+ int main(int argc, char **argv) {
146
+ if (argc < 3) return 64;
147
+ char *end;
148
+ errno = 0;
149
+ long grace_ms = strtol(argv[1], &end, 10);
150
+ if (errno || *end || grace_ms < 0 || grace_ms > 60000) return 64;
151
+ struct sigaction action = { .sa_handler = SIG_DFL }, original_pipe;
152
+ sigemptyset(&action.sa_mask);
153
+ if (sigaction(SIGCHLD, &action, NULL) < 0) return 125;
154
+ action.sa_handler = SIG_IGN;
155
+ if (sigaction(SIGPIPE, &action, &original_pipe) < 0) return 125;
156
+ sigset_t mask, original_mask;
157
+ sigemptyset(&mask);
158
+ sigaddset(&mask, SIGCHLD);
159
+ if (sigprocmask(SIG_BLOCK, &mask, &original_mask) < 0 || prctl(PR_SET_CHILD_SUBREAPER, 1) < 0) return 125;
160
+ signal_fd = signalfd(-1, &mask, SFD_CLOEXEC | SFD_NONBLOCK);
161
+ if (signal_fd < 0) return 125;
162
+ snprintf(children_path, sizeof(children_path), "/proc/%d/task/%d/children", getpid(), getpid());
163
+ if (signal_direct_children(0) < 0) { error_event("ownershipPreflight"); return 125; }
164
+ dprintf(control_fd, "{\"type\":\"ready\",\"pid\":%d}\n", getpid());
165
+ char command[128];
166
+ size_t used = 0;
167
+ bool started = false, control_open = true;
168
+ for (;;) {
169
+ observe_exec();
170
+ if (closing && now_ms() >= force_at && signal_direct_children(SIGKILL) < 0) error_event("forceOwnedChildren");
171
+ if (reap_children() && closing) {
172
+ dprintf(control_fd, "{\"type\":\"closed\",\"noChildren\":true,\"cleanupError\":%s}\n", cleanup_error ? "true" : "false");
173
+ return cleanup_error ? 125 : 0;
174
+ }
175
+ struct pollfd fds[3] = { { .fd = control_open ? control_fd : -1, .events = POLLIN }, { .fd = signal_fd, .events = POLLIN }, { .fd = exec_fd, .events = POLLIN } };
176
+ int timeout = closing ? (now_ms() >= force_at ? 1 : (int)(force_at - now_ms())) : -1;
177
+ int count = poll(fds, 3, timeout);
178
+ if (count < 0) { if (errno == EINTR) continue; error_event("poll"); start_close("controlError", SIGKILL, 0); continue; }
179
+ if (fds[1].revents & POLLIN) {
180
+ struct signalfd_siginfo info;
181
+ while (read(signal_fd, &info, sizeof(info)) == sizeof(info)) {}
182
+ }
183
+ if (!(fds[0].revents & (POLLIN | POLLHUP | POLLERR | POLLNVAL))) continue;
184
+ char chunk[128];
185
+ ssize_t size = read(control_fd, chunk, sizeof(chunk));
186
+ if (size <= 0) {
187
+ if (size < 0 && (errno == EINTR || errno == EAGAIN)) continue;
188
+ control_open = false;
189
+ start_close("controlEof", SIGKILL, 0);
190
+ continue;
191
+ }
192
+ for (ssize_t i = 0; i < size; i++) {
193
+ if (chunk[i] != '\n') {
194
+ if (used + 1 == sizeof(command)) { start_close("invalidControl", SIGKILL, 0); used = 0; break; }
195
+ command[used++] = chunk[i]; continue;
196
+ }
197
+ command[used] = 0;
198
+ used = 0;
199
+ if (!strcmp(command, "go") && !started && !closing) { started = true; start_native(argv + 2, &original_mask, &original_pipe); }
200
+ else if (!strcmp(command, "close")) start_close("close", SIGTERM, grace_ms);
201
+ else if (!strcmp(command, "interrupt")) start_close("interrupt", SIGINT, grace_ms);
202
+ else start_close("invalidControl", SIGKILL, 0);
203
+ }
204
+ }
205
+ }
@@ -0,0 +1,4 @@
1
+ import type { HarnessRegistration, OfficialAdapterOptions } from "@muha-sdk/core";
2
+ export type { OfficialAdapterOptions } from "@muha-sdk/core";
3
+ export declare function agyAdapter(options?: OfficialAdapterOptions): HarnessRegistration;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAuB,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAevG,YAAY,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC7D,wBAAgB,UAAU,CAAC,OAAO,GAAE,sBAA2B,GAAG,mBAAmB,CAOpF"}
package/dist/index.js ADDED
@@ -0,0 +1,19 @@
1
+ import { composeWorkspaceConfigurator, createOfficialHarnessRegistration, createSkillsCliPlanner } from "@muha-sdk/core/internal";
2
+ import { AgyProcess } from "./agy-process.js";
3
+ // Stage-five target declaration; admission additionally requires the complete
4
+ // Conformance matrix and real CLI / Orchestrator qualification in #1.
5
+ const capabilities = Object.freeze({
6
+ sessionListing: false, imageInput: false,
7
+ approvalPolicies: Object.freeze(["harnessManaged", "autoApprove"]),
8
+ turnQuestions: false, workspaceSkills: true, workspaceMcp: false,
9
+ model: Object.freeze({ selectionAt: Object.freeze(["createSession", "resumeSession"]), observation: "selectedOnly" }),
10
+ effort: Object.freeze({ selectionAt: Object.freeze(["createSession", "resumeSession"]), observation: "selectedOnly", requiresKnownModel: false }),
11
+ assistantMessageStreaming: true, assistantReasoningStreaming: false, toolEvents: true, turnUsage: true,
12
+ });
13
+ export function agyAdapter(options = {}) {
14
+ return createOfficialHarnessRegistration("agy", options, capabilities, composeWorkspaceConfigurator({
15
+ planSkill: createSkillsCliPlanner("antigravity-cli"),
16
+ planMcpServer() { throw new Error("AGY Workspace MCP is not supported"); },
17
+ }), (snapshot, context) => new AgyProcess(snapshot, context));
18
+ }
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,4BAA4B,EAAE,iCAAiC,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAClI,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,8EAA8E;AAC9E,sEAAsE;AACtE,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC;IACjC,cAAc,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK;IACxC,gBAAgB,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,gBAAgB,EAAE,aAAa,CAAU,CAAC;IAC3E,aAAa,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK;IAChE,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,eAAe,EAAE,eAAe,CAAU,CAAC,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9H,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,eAAe,EAAE,eAAe,CAAU,CAAC,EAAE,WAAW,EAAE,cAAc,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC;IAC1J,yBAAyB,EAAE,IAAI,EAAE,2BAA2B,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI;CACzE,CAAC,CAAC;AAGjC,MAAM,UAAU,UAAU,CAAC,UAAkC,EAAE;IAC7D,OAAO,iCAAiC,CAAC,KAAK,EAAE,OAAO,EAAE,YAAY,EACnE,4BAA4B,CAAC;QAC3B,SAAS,EAAE,sBAAsB,CAAC,iBAAiB,CAAC;QACpD,aAAa,KAAK,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC,CAAC,CAAC;KAC3E,CAAC,EACF,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { HarnessErrorData } from "@muha-sdk/core";
2
+ export declare function nativeBinding(env: NodeJS.ProcessEnv, id: string, workspace: string, operation?: HarnessErrorData["operation"]): Promise<string>;
3
+ //# sourceMappingURL=native-metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-metadata.d.ts","sourceRoot":"","sources":["../src/native-metadata.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAKvD,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EACvF,SAAS,GAAE,gBAAgB,CAAC,WAAW,CAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CA2D7E"}
@@ -0,0 +1,164 @@
1
+ import { constants } from "node:fs";
2
+ import { access, open, realpath } from "node:fs/promises";
3
+ import { homedir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { DatabaseSync } from "node:sqlite";
6
+ import { fileURLToPath } from "node:url";
7
+ import { failure, object } from "./protocol.js";
8
+ // Private native format qualified in the metadata research. Never enumerate
9
+ // conversations, read transcripts, repair a DB, or maintain a Muha index.
10
+ export async function nativeBinding(env, id, workspace, operation = "resumeSession") {
11
+ const invalid = (detail) => { throw failure(operation, `Unusable AGY Session metadata: ${detail}`); };
12
+ if (!safeComponent(id))
13
+ invalid("invalid native identity");
14
+ const home = env.HOME ?? homedir();
15
+ const path = join(home, ".gemini/antigravity-cli/conversations", `${id}.db`);
16
+ try {
17
+ await access(path);
18
+ }
19
+ catch (error) {
20
+ if (error.code === "ENOENT")
21
+ throw {
22
+ ...failure(operation, "AGY native Session does not exist"), nativeCode: "session_not_found",
23
+ };
24
+ invalid("cannot access native database");
25
+ }
26
+ let projectId;
27
+ let workspaceUris;
28
+ try {
29
+ const db = new DatabaseSync(path, { readOnly: true });
30
+ try {
31
+ db.exec("PRAGMA busy_timeout=0; PRAGMA query_only=ON; BEGIN");
32
+ // Inspect lengths in a separate statement before SQLite materializes
33
+ // values. substr alone would still load a corrupt oversized BLOB.
34
+ const identitySizes = db.prepare("SELECT typeof(cascade_id) AS kind, octet_length(cascade_id) AS size FROM trajectory_meta LIMIT 2").all();
35
+ const blobSizes = db.prepare("SELECT typeof(id) AS idKind, octet_length(id) AS idSize, typeof(data) AS kind, octet_length(data) AS size FROM trajectory_metadata_blob LIMIT 2").all();
36
+ if (identitySizes.length !== 1 || identitySizes[0].kind !== "text" ||
37
+ identitySizes[0].size !== Buffer.byteLength(id) ||
38
+ blobSizes.length !== 1 || blobSizes[0].idKind !== "text" || blobSizes[0].idSize !== 4 ||
39
+ blobSizes[0].kind !== "blob" || typeof blobSizes[0].size !== "number" || blobSizes[0].size > 1024 * 1024) {
40
+ invalid("identity, metadata cardinality, or supported size bound");
41
+ }
42
+ const identities = db.prepare("SELECT cascade_id FROM trajectory_meta LIMIT 2").all();
43
+ const blobs = db.prepare("SELECT id, data FROM trajectory_metadata_blob LIMIT 2").all();
44
+ if (identities.length !== 1 || identities[0].cascade_id !== id || blobs.length !== 1 ||
45
+ blobs[0].id !== "main" || !(blobs[0].data instanceof Uint8Array))
46
+ invalid("identity or metadata cardinality");
47
+ const data = blobs[0].data;
48
+ if (blobSizes[0].size !== data.byteLength)
49
+ invalid("metadata changed within its read snapshot");
50
+ const fields = decodeFields(data);
51
+ const projects = strings(fields, 18);
52
+ workspaceUris = strings(fields, 7);
53
+ if (projects.length !== 1 || !safeComponent(projects[0]) || workspaceUris.length !== 1)
54
+ invalid("Project or Workspace cardinality");
55
+ projectId = projects[0];
56
+ // Deprecated workspaces supply a consistency check only. Their git root
57
+ // field is deliberately not treated as an additional Workspace.
58
+ const legacy = fields.filter(field => field.number === 1);
59
+ if (legacy.length) {
60
+ if (legacy.length !== 1 || legacy[0].wire !== 2)
61
+ invalid("legacy Workspace cardinality");
62
+ const oldUris = strings(decodeFields(legacy[0].bytes), 1);
63
+ if (oldUris.length !== 1 || await directory(oldUris[0]) !== await directory(workspaceUris[0]))
64
+ invalid("conflicting Workspace metadata");
65
+ }
66
+ db.exec("COMMIT");
67
+ }
68
+ finally {
69
+ db.close();
70
+ }
71
+ const json = await readProject(join(home, ".gemini/config/projects", `${projectId}.json`));
72
+ const project = object(JSON.parse(json));
73
+ const resources = object(project.projectResources).resources;
74
+ if (project.id !== projectId || !Array.isArray(resources) || resources.length !== 1)
75
+ return invalid("Project identity or resources");
76
+ const folderUri = object(resources[0]).folderUri;
77
+ if (typeof folderUri !== "string")
78
+ invalid("Project has no directory binding");
79
+ if (await directory(folderUri) !== workspace || await directory(workspaceUris[0]) !== workspace) {
80
+ invalid("Session, Project, and requested Workspace disagree");
81
+ }
82
+ return projectId;
83
+ }
84
+ catch {
85
+ return invalid("unknown format, unreadable data, or conflicting Workspace binding");
86
+ }
87
+ }
88
+ async function readProject(path) {
89
+ const limit = 1024 * 1024;
90
+ const file = await open(path, constants.O_RDONLY | constants.O_NONBLOCK);
91
+ try {
92
+ const metadata = await file.stat();
93
+ if (!metadata.isFile() || metadata.size > limit)
94
+ throw new Error("Unsupported Project file");
95
+ const buffer = Buffer.alloc(limit + 1);
96
+ let offset = 0;
97
+ while (offset < buffer.length) {
98
+ const { bytesRead } = await file.read(buffer, offset, buffer.length - offset, offset);
99
+ if (bytesRead === 0)
100
+ break;
101
+ offset += bytesRead;
102
+ }
103
+ if (offset > limit)
104
+ throw new Error("Project exceeds supported bound");
105
+ return new TextDecoder("utf-8", { fatal: true }).decode(buffer.subarray(0, offset));
106
+ }
107
+ finally {
108
+ await file.close();
109
+ }
110
+ }
111
+ function safeComponent(value) {
112
+ return value.length > 0 && value.length < 256 && value !== "." && value !== ".." && !/[\/\\\u0000-\u001f]/u.test(value);
113
+ }
114
+ async function directory(value) {
115
+ const uri = new URL(value);
116
+ if (uri.protocol !== "file:" || uri.hostname !== "" || uri.search || uri.hash)
117
+ throw new Error("Nonlocal Workspace URI");
118
+ const path = fileURLToPath(uri);
119
+ if (path.includes("\0"))
120
+ throw new Error("Invalid Workspace URI");
121
+ return realpath(path);
122
+ }
123
+ function decodeFields(data) {
124
+ let offset = 0;
125
+ const varint = () => {
126
+ let value = 0n;
127
+ for (let shift = 0n; shift < 70n; shift += 7n) {
128
+ const byte = data[offset++];
129
+ if (byte === undefined || (shift === 63n && byte > 1))
130
+ throw new Error("Invalid protobuf varint");
131
+ value |= BigInt(byte & 127) << shift;
132
+ if (!(byte & 128))
133
+ return value;
134
+ }
135
+ throw new Error("Unterminated protobuf varint");
136
+ };
137
+ const fields = [];
138
+ while (offset < data.length) {
139
+ const tag = varint();
140
+ const number = Number(tag >> 3n);
141
+ const wire = Number(tag & 7n);
142
+ if (number < 1 || number > 0x1fffffff)
143
+ throw new Error("Invalid protobuf field");
144
+ if (wire === 0) {
145
+ varint();
146
+ fields.push({ number, wire });
147
+ continue;
148
+ }
149
+ const length = wire === 2 ? Number(varint()) : wire === 1 ? 8 : wire === 5 ? 4 : -1;
150
+ if (!Number.isSafeInteger(length) || length < 0 || length > data.length - offset)
151
+ throw new Error("Invalid protobuf length or wire type");
152
+ fields.push({ number, wire, bytes: data.subarray(offset, offset + length) });
153
+ offset += length;
154
+ }
155
+ return fields;
156
+ }
157
+ function strings(fields, number) {
158
+ return fields.filter(field => field.number === number).map(field => {
159
+ if (field.wire !== 2)
160
+ throw new Error("Incorrect native field type");
161
+ return new TextDecoder("utf-8", { fatal: true }).decode(field.bytes);
162
+ });
163
+ }
164
+ //# sourceMappingURL=native-metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-metadata.js","sourceRoot":"","sources":["../src/native-metadata.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { HarnessErrorData } from "@muha-sdk/core";
2
+ import type { LiveHarnessAdapterContext } from "@muha-sdk/core/internal";
3
+ import { Deferred, type JsonObject } from "./protocol.js";
4
+ export declare class OwnedCli {
5
+ #private;
6
+ readonly ready: Deferred<JsonObject>;
7
+ constructor(args: readonly string[], cwd: string, env: NodeJS.ProcessEnv, shutdownMs: number, context: LiveHarnessAdapterContext, onEvent: (event: JsonObject, printTimedOut: boolean) => void, onLoss: (error: HarnessErrorData) => void, operation: HarnessErrorData["operation"]);
8
+ write(event: JsonObject): void;
9
+ close(interrupt?: boolean): Promise<void>;
10
+ }
11
+ //# sourceMappingURL=owned-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"owned-cli.d.ts","sourceRoot":"","sources":["../src/owned-cli.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACzE,OAAO,EAAW,QAAQ,EAAmB,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAIpF,qBAAa,QAAQ;;IACnB,QAAQ,CAAC,KAAK,uBAA8B;gBAiBhC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,EAC1F,OAAO,EAAE,yBAAyB,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,KAAK,IAAI,EAChG,MAAM,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,EAAE,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC;IA4GrF,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAC9B,KAAK,CAAC,SAAS,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAuBxC"}
@@ -0,0 +1,182 @@
1
+ import { spawn } from "node:child_process";
2
+ import { createInterface } from "node:readline";
3
+ import { fileURLToPath } from "node:url";
4
+ import { bounded, Deferred, failure, object } from "./protocol.js";
5
+ // The independent helper owns/reaps its descendants. Nothing changes the
6
+ // consuming Node process's signals, child ownership, cwd, or environment.
7
+ export class OwnedCli {
8
+ ready = new Deferred();
9
+ #closed = new Deferred();
10
+ #child;
11
+ #control;
12
+ #input;
13
+ #shutdownMs;
14
+ #onLoss;
15
+ #incoming = Promise.resolve();
16
+ #closePromise;
17
+ #closing = false;
18
+ #reaped = false;
19
+ #lost = false;
20
+ #nativeReady = false;
21
+ #nativeExited = false;
22
+ #printTimedOut = false;
23
+ #outputEnded = new Deferred();
24
+ constructor(args, cwd, env, shutdownMs, context, onEvent, onLoss, operation) {
25
+ this.#shutdownMs = shutdownMs;
26
+ this.#onLoss = onLoss;
27
+ this.#child = spawn(fileURLToPath(new URL("./agy-supervisor", import.meta.url)), [String(Math.min(1_000, Math.floor(shutdownMs / 2))), "agy", ...args], { cwd, env, shell: false, stdio: ["pipe", "pipe", "pipe", "pipe"] });
28
+ this.#control = this.#child.stdio[3];
29
+ this.#input = this.#child.stdin;
30
+ const lose = (message) => {
31
+ const error = failure("closeHarness", message);
32
+ this.ready.reject(error);
33
+ if (!this.#closing && !this.#lost) {
34
+ this.#lost = true;
35
+ onLoss(error);
36
+ }
37
+ };
38
+ this.#child.once("error", error => lose(`AGY supervisor spawn failed: ${error.message}`));
39
+ this.#input.on("error", error => lose(`AGY input channel failed: ${error.message}`));
40
+ this.#control.on("error", error => lose(`AGY ownership channel failed: ${error.message}`));
41
+ this.#control.on("end", () => {
42
+ if (!this.#reaped && !this.#nativeExited)
43
+ lose("AGY ownership channel ended before cleanup");
44
+ });
45
+ const controlLines = createInterface({ input: this.#control });
46
+ controlLines.on("error", error => lose(`AGY ownership reader failed: ${error.message}`));
47
+ controlLines.on("line", line => {
48
+ try {
49
+ const event = object(JSON.parse(line));
50
+ if (event.type === "ready")
51
+ this.#control.write("go\n");
52
+ else if (event.type === "closed") {
53
+ this.#reaped = event.noChildren === true && event.cleanupError === false;
54
+ if (!this.#reaped)
55
+ this.#closed.reject(failure("closeSession", "AGY owned-process cleanup failed"));
56
+ }
57
+ else if (event.type === "nativeExit") {
58
+ this.#nativeExited = true;
59
+ // stdout and fd3 are independent pipes: drain semantic responses
60
+ // before classifying an exit, especially an explicit startup ERROR.
61
+ void this.#outputEnded.promise.then(() => this.#incoming).then(() => lose("AGY native process exited"), () => lose("AGY output failed before exit"));
62
+ }
63
+ else if (event.type === "error")
64
+ lose(`AGY supervisor failed during ${String(event.operation)} (${String(event.errno)})`);
65
+ }
66
+ catch {
67
+ lose("Invalid AGY ownership response");
68
+ }
69
+ });
70
+ const output = this.#child.stdout;
71
+ const handle = async (line) => {
72
+ if (!line.trim())
73
+ return;
74
+ const event = object(JSON.parse(line));
75
+ if (event.event !== "init" && event.event !== "step_update" && event.event !== "result") {
76
+ throw new Error("Unrecognized AGY semantic envelope");
77
+ }
78
+ await context.recordNativeEvent("agy", event);
79
+ if (event.event === "init") {
80
+ if (this.#nativeReady)
81
+ throw new Error("AGY repeated Session initialization");
82
+ this.#nativeReady = true;
83
+ this.ready.resolve(event);
84
+ }
85
+ else if (!this.#nativeReady && event.event === "result" && object(event.result).status === "ERROR") {
86
+ const result = object(event.result);
87
+ this.#closing = true;
88
+ this.ready.reject({ ...failure(operation, typeof result.error === "string" ? result.error : "AGY rejected Session initialization"),
89
+ nativeCode: "ERROR", stage: "handshake" });
90
+ }
91
+ else {
92
+ // Native timeout reporting precedes result on a separate stderr
93
+ // pipe. Drain this poll's ready descriptors before its terminal.
94
+ if (event.event === "result")
95
+ await new Promise(resolve => setImmediate(resolve));
96
+ onEvent(event, this.#printTimedOut);
97
+ }
98
+ };
99
+ output.setEncoding("utf8");
100
+ this.#incoming = (async () => {
101
+ let buffer = "";
102
+ try {
103
+ for await (const chunk of output) {
104
+ buffer += String(chunk);
105
+ if (Buffer.byteLength(buffer) > 8 * 1024 * 1024)
106
+ throw new Error("AGY protocol frame exceeds 8 MiB");
107
+ let end;
108
+ while ((end = buffer.indexOf("\n")) >= 0) {
109
+ const line = buffer.slice(0, end);
110
+ buffer = buffer.slice(end + 1);
111
+ await handle(line);
112
+ }
113
+ }
114
+ if (buffer.trim())
115
+ await handle(buffer);
116
+ lose("AGY output channel ended");
117
+ }
118
+ catch {
119
+ lose("AGY output protocol or diagnostic recording failed");
120
+ }
121
+ finally {
122
+ this.#outputEnded.resolve();
123
+ }
124
+ })();
125
+ // Stderr is a bounded control observation, never a Native Event Record.
126
+ let stderrLine = "";
127
+ this.#child.stderr.setEncoding("utf8");
128
+ this.#child.stderr.on("data", (chunk) => {
129
+ stderrLine += chunk;
130
+ let end;
131
+ while ((end = stderrLine.indexOf("\n")) >= 0) {
132
+ const line = stderrLine.slice(0, end);
133
+ stderrLine = stderrLine.slice(end + 1);
134
+ if (/^\[agy\] print timeout after .+ with turn in progress; returning partial output\r?$/u.test(line))
135
+ this.#printTimedOut = true;
136
+ }
137
+ if (stderrLine.length > 4_096)
138
+ stderrLine = stderrLine.slice(-4_096);
139
+ });
140
+ this.#child.stderr.on("error", error => lose(`AGY error channel failed: ${error.message}`));
141
+ this.#child.once("close", (code, signal) => {
142
+ void this.#incoming.finally(() => {
143
+ // This shipped helper exits 0 only after ECHILD with no cleanup error.
144
+ // A close write can race its exit and lose the final fd3 response; the
145
+ // child's exit status remains independent evidence of reclamation.
146
+ if (code === 0 && signal === null)
147
+ this.#reaped = true;
148
+ if (this.#reaped)
149
+ this.#closed.resolve();
150
+ else
151
+ this.#closed.reject(failure("closeSession", "AGY supervisor exited without confirming descendant cleanup"));
152
+ lose("AGY supervisor exited");
153
+ }).catch(() => { });
154
+ });
155
+ }
156
+ write(event) { this.#printTimedOut = false; this.#input.write(`${JSON.stringify(event)}\n`); }
157
+ close(interrupt = false) {
158
+ if (this.#closePromise)
159
+ return this.#closePromise;
160
+ this.#closing = true;
161
+ if (!this.#reaped && !this.#control.destroyed)
162
+ this.#control.write(interrupt ? "interrupt\n" : "close\n");
163
+ this.#closePromise = bounded(this.#closed.promise, this.#shutdownMs, failure("closeSession", "AGY descendant cleanup timed out")).catch(error => {
164
+ // Helper death is outside the complete cleanup guarantee (ADR-0128).
165
+ // A deadline reports failure and never claims descendants were reaped.
166
+ this.#child.kill("SIGKILL");
167
+ this.#control.destroy();
168
+ this.#input.destroy();
169
+ this.#child.stdout?.destroy();
170
+ this.#child.stderr?.destroy();
171
+ // An intentional close suppresses expected EOF, never an inability
172
+ // to reclaim execution. Helper loss remains fatal under ADR-0128.
173
+ if (!this.#lost) {
174
+ this.#lost = true;
175
+ this.#onLoss(error);
176
+ }
177
+ throw error;
178
+ });
179
+ return this.#closePromise;
180
+ }
181
+ }
182
+ //# sourceMappingURL=owned-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"owned-cli.js","sourceRoot":"","sources":["../src/owned-cli.ts"],"names":[],"mappings":"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"}