@haikeilabs/agentware 0.2.1 → 0.4.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.
@@ -1,2 +1,3 @@
1
1
  export * from "./runtimeLink.js";
2
+ export * from "./runtimeLinkRuntime.js";
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/kei/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/kei/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC"}
package/dist/kei/index.js CHANGED
@@ -1 +1,2 @@
1
1
  export * from "./runtimeLink.js";
2
+ export * from "./runtimeLinkRuntime.js";
@@ -2,12 +2,11 @@
2
2
  * RuntimeLink contract: the harness → Agentware → kei-connector-runtime heartbeat.
3
3
  *
4
4
  * TypeScript mirror of the Go reference `go/kei/runtimelink` for
5
- * `docs/specs/runtime-heartbeat-liveness.md` (HAI-141). Contract types only:
5
+ * `docs/specs/runtime-heartbeat-liveness.md` (HAI-141). This module defines
6
6
  * configuration, status, identity, failure classes, the child's JSONL wire
7
- * events, and redacted lifecycle events. It never spawns a process, opens a
8
- * network connection, or reads a credential value. The only heartbeat path is
9
- * harness → RuntimeLink → kei-connector-runtime; nothing here talks to the
10
- * catalog.
7
+ * events, and redacted lifecycle events. Process supervision is implemented
8
+ * in `runtimeLinkRuntime.ts`. The only heartbeat path is harness → RuntimeLink
9
+ * → kei-connector-runtime; Agentware does not call the catalog itself.
11
10
  *
12
11
  * All three SDK languages share `testing/contracts/runtime-link`. Durations
13
12
  * are milliseconds here (`intervalMs`), seconds in Python, and
@@ -171,6 +170,19 @@ export interface RuntimeIdentity {
171
170
  status: string;
172
171
  bindingStatus: string;
173
172
  runtimeVersion: string;
173
+ /**
174
+ * The installation's default agent from whoami; undefined when the runtime
175
+ * reports none (older runtimes omit it). A harness reads its agent from
176
+ * here and must not require an agent-ID env var.
177
+ */
178
+ defaultAgentId?: string;
179
+ /** Agents assigned to the installation; empty when the runtime reports none. */
180
+ agents: AssignedAgent[];
181
+ }
182
+ /** One agent assigned to a runtime installation. */
183
+ export interface AssignedAgent {
184
+ agentId: string;
185
+ isDefault: boolean;
174
186
  }
175
187
  export type ChildLineErrorKind = "line_too_long" | "malformed" | "contract_mismatch";
176
188
  /** A child line the SDK must drop and count. */
@@ -195,6 +207,8 @@ export interface TerminalEvent {
195
207
  export type ChildEvent = {
196
208
  kind: "identity";
197
209
  identity: RuntimeIdentity;
210
+ /** Malformed agent entries dropped from the event; counted like dropped lines. */
211
+ droppedAgents: number;
198
212
  } | {
199
213
  kind: "beat";
200
214
  beat: BeatEvent;
@@ -1 +1 @@
1
- {"version":3,"file":"runtimeLink.d.ts","sourceRoot":"","sources":["../../src/kei/runtimeLink.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runtimeLink.d.ts","sourceRoot":"","sources":["../../src/kei/runtimeLink.ts"],"names":[],"mappings":"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"}
@@ -2,12 +2,11 @@
2
2
  * RuntimeLink contract: the harness → Agentware → kei-connector-runtime heartbeat.
3
3
  *
4
4
  * TypeScript mirror of the Go reference `go/kei/runtimelink` for
5
- * `docs/specs/runtime-heartbeat-liveness.md` (HAI-141). Contract types only:
5
+ * `docs/specs/runtime-heartbeat-liveness.md` (HAI-141). This module defines
6
6
  * configuration, status, identity, failure classes, the child's JSONL wire
7
- * events, and redacted lifecycle events. It never spawns a process, opens a
8
- * network connection, or reads a credential value. The only heartbeat path is
9
- * harness → RuntimeLink → kei-connector-runtime; nothing here talks to the
10
- * catalog.
7
+ * events, and redacted lifecycle events. Process supervision is implemented
8
+ * in `runtimeLinkRuntime.ts`. The only heartbeat path is harness → RuntimeLink
9
+ * → kei-connector-runtime; Agentware does not call the catalog itself.
11
10
  *
12
11
  * All three SDK languages share `testing/contracts/runtime-link`. Durations
13
12
  * are milliseconds here (`intervalMs`), seconds in Python, and
@@ -410,6 +409,57 @@ class FieldReader {
410
409
  return v;
411
410
  }
412
411
  }
412
+ /**
413
+ * Fill identity.defaultAgentId and identity.agents from the optional agent_id
414
+ * and agents fields. Older runtimes omit both, so absence is not an error; a
415
+ * malformed agent_id, agents list, or entry is dropped and counted rather than
416
+ * failing the whole identity. When agent_id is absent, the first entry marked
417
+ * is_default supplies it. Returns the number of dropped values.
418
+ */
419
+ function parseAgents(raw, identity) {
420
+ let dropped = 0;
421
+ if (Object.hasOwn(raw, "agent_id")) {
422
+ const v = raw.agent_id;
423
+ if (typeof v === "string" && ID_RE.test(v))
424
+ identity.defaultAgentId = v;
425
+ else
426
+ dropped++;
427
+ }
428
+ if (!Object.hasOwn(raw, "agents"))
429
+ return dropped;
430
+ const entries = raw.agents;
431
+ if (!Array.isArray(entries))
432
+ return dropped + 1;
433
+ for (const entry of entries) {
434
+ const agent = parseAgentEntry(entry);
435
+ if (!agent) {
436
+ dropped++;
437
+ continue;
438
+ }
439
+ identity.agents.push(agent);
440
+ if (identity.defaultAgentId === undefined && agent.isDefault) {
441
+ identity.defaultAgentId = agent.agentId;
442
+ }
443
+ }
444
+ return dropped;
445
+ }
446
+ /** Read one {agent_id, is_default} entry; is_default is false when absent. */
447
+ function parseAgentEntry(entry) {
448
+ if (entry === null || typeof entry !== "object" || Array.isArray(entry)) {
449
+ return undefined;
450
+ }
451
+ const e = entry;
452
+ const agentId = e.agent_id;
453
+ if (typeof agentId !== "string" || !ID_RE.test(agentId))
454
+ return undefined;
455
+ let isDefault = false;
456
+ if (Object.hasOwn(e, "is_default")) {
457
+ if (typeof e.is_default !== "boolean")
458
+ return undefined;
459
+ isDefault = e.is_default;
460
+ }
461
+ return { agentId, isDefault };
462
+ }
413
463
  const encoder = new TextEncoder();
414
464
  const decoder = new TextDecoder();
415
465
  /**
@@ -445,20 +495,21 @@ export function parseChildLine(line) {
445
495
  throw new ChildLineError("malformed", "event");
446
496
  const f = new FieldReader(obj);
447
497
  switch (obj.event) {
448
- case "identity":
449
- return {
450
- kind: "identity",
451
- identity: {
452
- runId: f.id("run_id", true),
453
- installationId: f.id("installation_id", true),
454
- orgId: f.id("org_id", true),
455
- workspaceId: f.id("workspace_id", false),
456
- platform: f.id("platform", false),
457
- status: f.id("status", false),
458
- bindingStatus: f.id("binding_status", false),
459
- runtimeVersion: f.id("runtime_version", false),
460
- },
498
+ case "identity": {
499
+ const identity = {
500
+ runId: f.id("run_id", true),
501
+ installationId: f.id("installation_id", true),
502
+ orgId: f.id("org_id", true),
503
+ workspaceId: f.id("workspace_id", false),
504
+ platform: f.id("platform", false),
505
+ status: f.id("status", false),
506
+ bindingStatus: f.id("binding_status", false),
507
+ runtimeVersion: f.id("runtime_version", false),
508
+ agents: [],
461
509
  };
510
+ const droppedAgents = parseAgents(obj, identity);
511
+ return { kind: "identity", identity, droppedAgents };
512
+ }
462
513
  case "beat": {
463
514
  const runId = f.id("run_id", true);
464
515
  const seq = f.integer("seq", false, 0, MAX_SEQ);
@@ -0,0 +1,26 @@
1
+ import { type RuntimeLink, type RuntimeLinkConfig } from "./runtimeLink.js";
2
+ export interface RuntimeChild {
3
+ readonly stdout: AsyncIterable<Uint8Array | string>;
4
+ readonly exitCode: Promise<number>;
5
+ kill(signal?: "SIGTERM" | "SIGKILL"): void;
6
+ }
7
+ /** Injectable process boundary for tests and embedders. */
8
+ export interface RuntimeChildFactory {
9
+ start(command: string, args: readonly string[], env: Readonly<Record<string, string>>): RuntimeChild;
10
+ }
11
+ export interface RuntimeLinkOptions {
12
+ env?: Readonly<Record<string, string | undefined>>;
13
+ childFactory?: RuntimeChildFactory;
14
+ now?: () => Date;
15
+ random?: () => number;
16
+ sdkVersion?: string;
17
+ sdkInstanceId?: string;
18
+ audit?: (event: Readonly<Record<string, unknown>>) => void | Promise<void>;
19
+ }
20
+ /** Node process implementation. stderr is drained and discarded; never surfaced to audit or logs. */
21
+ export declare class NodeRuntimeChildFactory implements RuntimeChildFactory {
22
+ start(command: string, args: readonly string[], env: Readonly<Record<string, string>>): RuntimeChild;
23
+ }
24
+ /** Create a supervisor that owns the harness → kei-connector-runtime process and heartbeat boundary. */
25
+ export declare function newRuntimeLink(config: RuntimeLinkConfig, options?: RuntimeLinkOptions): RuntimeLink;
26
+ //# sourceMappingURL=runtimeLinkRuntime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtimeLinkRuntime.d.ts","sourceRoot":"","sources":["../../src/kei/runtimeLinkRuntime.ts"],"names":[],"mappings":"AAIA,OAAO,EAYL,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACvB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC;IACpD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACnC,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,IAAI,CAAC;CAC5C;AAED,2DAA2D;AAC3D,MAAM,WAAW,mBAAmB;IAClC,KAAK,CACH,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GACpC,YAAY,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IACnD,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5E;AAED,qGAAqG;AACrG,qBAAa,uBAAwB,YAAW,mBAAmB;IACjE,KAAK,CACH,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GACpC,YAAY;CA8BhB;AAWD,wGAAwG;AACxG,wBAAgB,cAAc,CAC5B,MAAM,EAAE,iBAAiB,EACzB,OAAO,GAAE,kBAAuB,GAC/B,WAAW,CAEb"}
@@ -0,0 +1,401 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { spawn } from "node:child_process";
3
+ import { createReadStream } from "node:fs";
4
+ import { createHash } from "node:crypto";
5
+ import { CHILD_ENV_ALLOWLIST, RUNTIME_LINK_SDK_LANG, linkEventToWire, normalizeRuntimeLinkConfig, parseChildLine, waitBackoff, } from "./runtimeLink.js";
6
+ /** Node process implementation. stderr is drained and discarded; never surfaced to audit or logs. */
7
+ export class NodeRuntimeChildFactory {
8
+ start(command, args, env) {
9
+ const child = spawn(command, [...args], {
10
+ env: { ...env },
11
+ stdio: ["ignore", "pipe", "ignore"],
12
+ detached: process.platform !== "win32",
13
+ });
14
+ const stdout = child.stdout;
15
+ if (!stdout)
16
+ throw new Error("runtime stdout unavailable");
17
+ const exitCode = new Promise((resolve) => {
18
+ child.once("error", () => resolve(1));
19
+ child.once("close", (code) => resolve(code ?? 1));
20
+ });
21
+ return {
22
+ stdout: (async function* () {
23
+ for await (const chunk of stdout)
24
+ yield chunk;
25
+ })(),
26
+ exitCode,
27
+ kill: (signal = "SIGTERM") => {
28
+ if (process.platform !== "win32" && child.pid) {
29
+ try {
30
+ process.kill(-child.pid, signal);
31
+ }
32
+ catch {
33
+ child.kill(signal);
34
+ }
35
+ }
36
+ else {
37
+ child.kill(signal);
38
+ }
39
+ },
40
+ };
41
+ }
42
+ }
43
+ const SDK_VERSION = "0.2.1";
44
+ const OUTCOME_FAILURE = {
45
+ catalog_unreachable: "catalog_unreachable",
46
+ catalog_timeout: "catalog_timeout",
47
+ catalog_error: "catalog_error",
48
+ catalog_backpressure: "catalog_backpressure",
49
+ catalog_rejected: "contract_mismatch",
50
+ };
51
+ /** Create a supervisor that owns the harness → kei-connector-runtime process and heartbeat boundary. */
52
+ export function newRuntimeLink(config, options = {}) {
53
+ return new RuntimeLinkImpl(normalizeRuntimeLinkConfig(config), options);
54
+ }
55
+ class RuntimeLinkImpl {
56
+ config;
57
+ options;
58
+ eventsQueue = [];
59
+ waiters = [];
60
+ controller = new AbortController();
61
+ sdkId;
62
+ state;
63
+ reason;
64
+ identityValue;
65
+ runId = "";
66
+ lastBeatAt;
67
+ lastCatalogOkAt;
68
+ consecutiveFails = 0;
69
+ restarts = 0;
70
+ started = false;
71
+ stopped = false;
72
+ supervisor;
73
+ child;
74
+ constructor(config, options) {
75
+ this.config = config;
76
+ this.options = options;
77
+ this.state = config.enabled ? "disabled" : "disabled";
78
+ this.sdkId = options.sdkInstanceId ?? randomUUID();
79
+ }
80
+ async start(signal) {
81
+ if (this.started || this.stopped || !this.config.enabled)
82
+ return;
83
+ this.started = true;
84
+ if (signal?.aborted) {
85
+ await this.stop();
86
+ return;
87
+ }
88
+ signal?.addEventListener("abort", () => {
89
+ void this.stop();
90
+ }, { once: true });
91
+ this.supervisor = this.supervise();
92
+ // Starting is non-blocking; only config errors can reject.
93
+ }
94
+ async stop() {
95
+ if (this.stopped) {
96
+ await this.withTimeout(this.supervisor);
97
+ return;
98
+ }
99
+ this.stopped = true;
100
+ this.controller.abort(new Error("RuntimeLink stopped"));
101
+ this.transition("stopped");
102
+ this.child?.kill("SIGTERM");
103
+ await this.withTimeout(this.supervisor);
104
+ this.child = undefined;
105
+ for (const resolve of this.waiters.splice(0))
106
+ resolve({ done: true, value: undefined });
107
+ }
108
+ status() {
109
+ return {
110
+ state: this.state,
111
+ reason: this.reason,
112
+ lastBeatAt: this.lastBeatAt,
113
+ lastCatalogOkAt: this.lastCatalogOkAt,
114
+ consecutiveFails: this.consecutiveFails,
115
+ runId: this.runId,
116
+ restarts: this.restarts,
117
+ };
118
+ }
119
+ identity() {
120
+ return this.identityValue && { ...this.identityValue };
121
+ }
122
+ events() {
123
+ const queue = this.eventsQueue;
124
+ const waiters = this.waiters;
125
+ return {
126
+ [Symbol.asyncIterator]() {
127
+ return {
128
+ next: () => queue.length
129
+ ? Promise.resolve({ done: false, value: queue.shift() })
130
+ : new Promise((resolve) => waiters.push(resolve)),
131
+ return: () => Promise.resolve({ done: true, value: undefined }),
132
+ };
133
+ },
134
+ };
135
+ }
136
+ async supervise() {
137
+ while (!this.controller.signal.aborted) {
138
+ if (this.restarts > 0) {
139
+ this.transition("reconnecting");
140
+ try {
141
+ await waitBackoff(this.config.restart, this.restarts - 1, {
142
+ signal: this.controller.signal,
143
+ random: this.options.random,
144
+ });
145
+ }
146
+ catch {
147
+ return;
148
+ }
149
+ }
150
+ if (this.controller.signal.aborted)
151
+ return;
152
+ this.transition("starting");
153
+ let failure = "runtime_unavailable";
154
+ try {
155
+ failure = await this.runChild();
156
+ }
157
+ catch (e) {
158
+ if (this.controller.signal.aborted)
159
+ return;
160
+ failure =
161
+ e instanceof BinaryFailure
162
+ ? "config_invalid"
163
+ : "runtime_unresponsive";
164
+ }
165
+ if (this.controller.signal.aborted || this.state === "terminal")
166
+ return;
167
+ this.restarts++;
168
+ this.consecutiveFails++;
169
+ this.reason = failure;
170
+ if (failure === "config_invalid" ||
171
+ failure === "contract_mismatch" ||
172
+ failure === "installation_unauthorized") {
173
+ this.transition("terminal", failure);
174
+ return;
175
+ }
176
+ this.transition("degraded", failure);
177
+ if (this.restarts >= 5) {
178
+ this.transition("terminal", "runtime_crashloop");
179
+ return;
180
+ }
181
+ }
182
+ }
183
+ async runChild() {
184
+ await this.verifyBinary();
185
+ const env = this.childEnv();
186
+ const factory = this.options.childFactory ?? new NodeRuntimeChildFactory();
187
+ const child = factory.start(this.config.binary.path, ["runtime", "heartbeat", "--output", "jsonl"], env);
188
+ this.child = child;
189
+ let identitySeen = false;
190
+ let heartbeatDeadline = Date.now() + this.config.beatTimeoutMs;
191
+ const lines = this.consume(child.stdout);
192
+ const abortPromise = new Promise((_, reject) => {
193
+ if (this.controller.signal.aborted)
194
+ reject(this.controller.signal.reason);
195
+ else
196
+ this.controller.signal.addEventListener("abort", () => reject(this.controller.signal.reason), { once: true });
197
+ });
198
+ try {
199
+ while (!this.controller.signal.aborted) {
200
+ const remaining = identitySeen
201
+ ? Math.max(1, heartbeatDeadline - Date.now())
202
+ : this.config.graceMs;
203
+ let timer;
204
+ const next = await Promise.race([
205
+ lines.next(),
206
+ new Promise((_, reject) => {
207
+ timer = setTimeout(() => reject(new Error("runtime heartbeat timeout")), remaining);
208
+ }),
209
+ abortPromise,
210
+ ]).finally(() => {
211
+ if (timer)
212
+ clearTimeout(timer);
213
+ });
214
+ if (next.done) {
215
+ const code = await child.exitCode;
216
+ const failure = code === 2
217
+ ? "contract_mismatch"
218
+ : code === 3
219
+ ? "installation_unauthorized"
220
+ : code >= 4
221
+ ? "config_invalid"
222
+ : "runtime_unavailable";
223
+ if (failure === "contract_mismatch" ||
224
+ failure === "installation_unauthorized" ||
225
+ failure === "config_invalid") {
226
+ this.transition("terminal", failure);
227
+ }
228
+ return failure;
229
+ }
230
+ let ev;
231
+ try {
232
+ ev = parseChildLine(next.value);
233
+ }
234
+ catch (error) {
235
+ this.consecutiveFails++;
236
+ if (error instanceof Error &&
237
+ error.message.includes("contract_mismatch"))
238
+ this.reason = "contract_mismatch";
239
+ continue;
240
+ }
241
+ if (ev.kind === "identity") {
242
+ this.identityValue = ev.identity;
243
+ this.consecutiveFails += ev.droppedAgents;
244
+ this.runId = ev.identity.runId;
245
+ identitySeen = true;
246
+ heartbeatDeadline = Date.now() + this.config.beatTimeoutMs;
247
+ this.transition("connected");
248
+ }
249
+ else if (ev.kind === "beat") {
250
+ this.runId = ev.beat.runId || this.runId;
251
+ this.lastBeatAt = this.options.now?.() ?? new Date();
252
+ heartbeatDeadline = Date.now() + this.config.beatTimeoutMs;
253
+ if (ev.beat.outcome === "ok") {
254
+ this.lastCatalogOkAt = this.lastBeatAt;
255
+ this.consecutiveFails = 0;
256
+ if (this.state !== "connected")
257
+ this.transition("connected");
258
+ }
259
+ else if (ev.beat.outcome === "unauthorized") {
260
+ this.transition("terminal", "installation_unauthorized");
261
+ return "installation_unauthorized";
262
+ }
263
+ else {
264
+ this.consecutiveFails++;
265
+ this.transition("degraded", OUTCOME_FAILURE[ev.beat.outcome] ?? "runtime_unavailable");
266
+ }
267
+ }
268
+ else if (ev.kind === "terminal") {
269
+ const reason = ev.terminal.reason === "unauthorized"
270
+ ? "installation_unauthorized"
271
+ : ev.terminal.reason === "contract"
272
+ ? "contract_mismatch"
273
+ : "runtime_unavailable";
274
+ this.transition("terminal", reason);
275
+ return reason;
276
+ }
277
+ }
278
+ return "runtime_unavailable";
279
+ }
280
+ finally {
281
+ child.kill("SIGTERM");
282
+ this.child = undefined;
283
+ }
284
+ }
285
+ async *consume(source) {
286
+ const decoder = new TextDecoder();
287
+ let pending = "";
288
+ for await (const chunk of source) {
289
+ if (this.controller.signal.aborted)
290
+ return;
291
+ pending +=
292
+ typeof chunk === "string"
293
+ ? chunk
294
+ : decoder.decode(chunk, { stream: true });
295
+ let idx;
296
+ while ((idx = pending.indexOf("\n")) >= 0) {
297
+ yield pending.slice(0, idx + 1);
298
+ pending = pending.slice(idx + 1);
299
+ }
300
+ if (new TextEncoder().encode(pending).length > 4097)
301
+ pending = " ".repeat(4098);
302
+ }
303
+ if (pending)
304
+ yield pending;
305
+ }
306
+ childEnv() {
307
+ const source = this.options.env ?? process.env;
308
+ const out = {};
309
+ for (const key of CHILD_ENV_ALLOWLIST) {
310
+ const value = source[key];
311
+ if (value !== undefined)
312
+ out[key] = value;
313
+ }
314
+ out.KEI_AGENTWARE_SDK_LANG = RUNTIME_LINK_SDK_LANG;
315
+ out.KEI_AGENTWARE_SDK_VERSION = this.options.sdkVersion ?? SDK_VERSION;
316
+ out.KEI_RUNTIME_CONTROL_PLANE_URL = this.config.controlPlaneUrl;
317
+ out.KEI_HARNESS_KIND = this.config.harness.kind;
318
+ out.KEI_HARNESS_VERSION = this.config.harness.version;
319
+ out.KEI_DEPLOYMENT_ENV = this.config.harness.deploymentEnv;
320
+ return out;
321
+ }
322
+ async verifyBinary() {
323
+ const expected = this.config.binary.sha256;
324
+ if (!expected)
325
+ return;
326
+ const hash = createHash("sha256");
327
+ try {
328
+ for await (const chunk of createReadStream(this.config.binary.path))
329
+ hash.update(chunk);
330
+ }
331
+ catch {
332
+ throw new BinaryFailure();
333
+ }
334
+ if (hash.digest("hex") !== expected)
335
+ throw new BinaryFailure();
336
+ }
337
+ transition(state, reason) {
338
+ if (this.state === state && this.reason === reason)
339
+ return;
340
+ this.state = state;
341
+ this.reason = reason;
342
+ const name = {
343
+ starting: "runtime.link.started",
344
+ connected: "runtime.link.connected",
345
+ degraded: "runtime.link.degraded",
346
+ reconnecting: "runtime.link.reconnecting",
347
+ terminal: "runtime.link.terminal",
348
+ stopped: "runtime.link.stopped",
349
+ }[state];
350
+ if (!name)
351
+ return;
352
+ const event = {
353
+ name,
354
+ at: this.options.now?.() ?? new Date(),
355
+ state,
356
+ reason: reason ?? "",
357
+ runId: this.runId,
358
+ seq: Date.now(),
359
+ sdkInstanceId: this.sdkId,
360
+ harness: {
361
+ kind: this.config.harness.kind,
362
+ version: this.config.harness.version,
363
+ deploymentEnv: this.config.harness.deploymentEnv,
364
+ sdkLang: RUNTIME_LINK_SDK_LANG,
365
+ sdkVersion: this.options.sdkVersion ?? SDK_VERSION,
366
+ },
367
+ restarts: this.restarts,
368
+ consecutiveFails: this.consecutiveFails,
369
+ };
370
+ try {
371
+ const safe = linkEventToWire(event);
372
+ if (this.waiters.length)
373
+ this.waiters.shift()({ done: false, value: event });
374
+ else {
375
+ if (this.eventsQueue.length >= 64)
376
+ this.eventsQueue.shift();
377
+ this.eventsQueue.push(event);
378
+ }
379
+ if (this.options.audit)
380
+ void Promise.resolve(this.options.audit(safe)).catch(() => undefined);
381
+ }
382
+ catch {
383
+ /* audit/event serialization must fail closed without leaking arbitrary input */
384
+ }
385
+ }
386
+ async withTimeout(task) {
387
+ if (!task)
388
+ return;
389
+ let timer;
390
+ await Promise.race([
391
+ task,
392
+ new Promise((resolve) => {
393
+ timer = setTimeout(resolve, this.config.stopTimeoutMs);
394
+ }),
395
+ ]);
396
+ if (timer)
397
+ clearTimeout(timer);
398
+ }
399
+ }
400
+ class BinaryFailure extends Error {
401
+ }
@@ -9,7 +9,7 @@ export class MiddlewareImpl {
9
9
  execute(toolName, args, caller) {
10
10
  const decision = this.evaluator
11
11
  ? this.evaluator.evaluate(toolName, args, caller)
12
- : { action: Action.ALLOW, rule: "default", reason: "no policy configured", timestamp: new Date() };
12
+ : { action: Action.DENY, rule: "default", reason: "no policy configured; default deny", timestamp: new Date() };
13
13
  if (this.auditor) {
14
14
  this.auditor.record({
15
15
  session_id: caller.session_id || "",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haikeilabs/agentware",
3
- "version": "0.2.1",
3
+ "version": "0.4.0",
4
4
  "description": "Agent middleware and tooling for LLM tool calling",
5
5
  "repository": {
6
6
  "type": "git",