theway-daemon 0.1.15

theway daemon — the single agent-runtime kernel (bin `thewayd`): harness assembly, local/sandbox tool policy, triggers/cron/session/DAG runtime, skills, MCP/LSP wiring, serving the gRPC/HTTP/MCP transports from theway-transport. Terminal UI lives in the theway-tui crate.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
pub(super) const HOST_BOOTSTRAP_SOURCE: &str = r#"
globalThis.__thewayHandlers = Object.create(null);
globalThis.__thewayEffects = [];
globalThis.__thewayRegistrations = Object.create(null);
globalThis.__thewayRegistrationSequence = 0;
globalThis.__thewayMigrationRegistrationId = null;
globalThis.__thewayCurrentEnvelope = null;
globalThis.__thewayPendingDurableActions = [];
globalThis.__thewayPendingState = new Map();
globalThis.__thewayDisposers = [];
// Runtime identity injected by the host before setup (v2 bridge surface).
globalThis.__thewayRuntimeVersion = globalThis.__thewayRuntimeVersion ?? "0.0.0";
globalThis.__thewayRuntimePluginId = globalThis.__thewayRuntimePluginId ?? "";
globalThis.__thewayRuntimeSessionId = globalThis.__thewayRuntimeSessionId ?? "";

function __thewayDisposedRegistrationIds() {
  return Object.values(globalThis.__thewayRegistrations)
    .filter(({ disposed }) => disposed)
    .map(({ id }) => id);
}

// Dispose queue: `api.effect(fn)` runs `fn` immediately; the disposer it
// returns is executed in reverse registration order when the plugin unloads
// (before the QuickJS VM is destroyed). Each disposer runs isolated — one
// throwing disposer cannot stop the rest.
function __thewayDispose() {
  const report = { executed: 0, errors: [] };
  for (let index = globalThis.__thewayDisposers.length - 1; index >= 0; index--) {
    const entry = globalThis.__thewayDisposers[index];
    if (entry.disposed) continue;
    entry.disposed = true;
    // Count every queue entry as executed even when its disposer throws:
    // a throwing disposer still ran; the error is isolated per entry.
    report.executed++;
    try {
      const disposer = entry.disposer;
      if (typeof disposer === "function") {
        const result = disposer();
        if (result && typeof result.then === "function") {
          result.catch((error) => report.errors.push(String(error?.message ?? error)));
        }
      }
    } catch (error) {
      report.errors.push(String(error?.message ?? error));
    }
  }
  globalThis.__thewayDisposers = [];
  return report;
}

function __thewayHandle(registration) {
  return Object.freeze({
    id: `effect-${registration.id}`,
    dispose() { registration.disposed = true; },
    update(descriptor) {
      if (registration.disposed) {
        const error = new Error("registration handle is disposed");
        error.code = "effect_disposed";
        throw error;
      }
      if (descriptor === null || typeof descriptor !== "object") {
        throw new TypeError("registration descriptor must be an object");
      }
      registration.descriptor = descriptor;
    },
  });
}

function __thewayRegister(kind, descriptor, handler) {
  if (descriptor === null || typeof descriptor !== "object") {
    throw new TypeError(`api.register${kind} requires a descriptor`);
  }
  if ((kind === "tool" || kind === "command" || kind === "request_policy")
      && typeof handler !== "function") {
    throw new TypeError(`${kind} registration requires a handler`);
  }
  const registration = {
    id: globalThis.__thewayRegistrationSequence++,
    kind,
    descriptor,
    handler,
    sequence: globalThis.__thewayRegistrationSequence,
    disposed: false,
  };
  globalThis.__thewayEffects.push(registration);
  globalThis.__thewayRegistrations[registration.id] = registration;
  return __thewayHandle(registration);
}

function __thewayRegisterHandler(event, descriptor, handler, once) {
  let effectiveHandler = handler;
  if (once) {
    effectiveHandler = async (envelope, context) => {
      registration.disposed = true;
      try {
        return await handler(envelope, context);
      } catch (error) {
        throw error;
      }
    };
  }
  const registration = {
    id: globalThis.__thewayRegistrationSequence,
    event,
    descriptor: descriptor ?? {},
    handler: effectiveHandler,
    priority: Number.isFinite(descriptor?.priority) ? descriptor.priority : 0,
    sequence: globalThis.__thewayRegistrationSequence++,
    disposed: false,
  };
  (globalThis.__thewayHandlers[event] ??= []).push(registration);
  globalThis.__thewayRegistrations[registration.id] = registration;
  return __thewayHandle(registration);
}

function __thewayBrokerCall(operation, brokerArgs = {}) {
  const response = JSON.parse(globalThis.__thewayBroker(operation, JSON.stringify(brokerArgs)));
  if (!response.ok) {
    const error = new Error(response.error?.message ?? "capability broker failed");
    error.code = response.error?.code ?? "broker_failed";
    throw error;
  }
  return response.value;
}

function __thewayRequireInvocation() {
  const envelope = globalThis.__thewayCurrentEnvelope;
  if (envelope === null) {
    throw new Error("durable state writes require an active lifecycle invocation");
  }
  return envelope;
}

function __thewayQueueDurable(kind, entry) {
  const envelope = __thewayRequireInvocation();
  const stateSchemaVersion = __thewayBrokerCall("state.schema", {});
  globalThis.__thewayPendingDurableActions.push({
    kind,
    payload: {
      extensionId: envelope.context.extensionId,
      stateSchemaVersion,
      originSequence: Math.max(1, envelope.context.sequence),
      entry,
    },
  });
}

globalThis.__thewaySetup = async function () {
  try {
    const registered = globalThis.__thewayRegisteredExtension ?? null;
    const defaultExport = globalThis.__thewayExtension?.default;
    if (registered !== null && defaultExport !== undefined && defaultExport !== null) {
      throw new TypeError("extension entry uses both register() and a default export; choose one");
    }
    const candidate = registered ?? defaultExport;
    const setup = typeof candidate === "function" ? candidate : candidate?.setup;
    if (typeof setup !== "function") {
      throw new TypeError("extension entry must call register(setup) or export defineExtension(setup)");
    }
    // Optional service dependency declaration: `export const inject = ["svc"]`
    // (module scope), the definition's `inject` field, or `register(setup,
    // { inject })` for the side-effect entry form.
    const moduleInject = globalThis.__thewayExtension.inject;
    const declaredInject = Array.isArray(moduleInject)
      ? moduleInject
      : Array.isArray(candidate?.inject)
        ? candidate.inject
        : [];
    const api = Object.freeze({
      capabilities: Object.freeze({
        has(permission) {
          return __thewayBrokerCall("capabilities.has", { permission });
        },
      }),
      workspace: Object.freeze({
        async readText(path) {
          return __thewayBrokerCall("workspace.readText", { path });
        },
        async writeText(path, content) {
          return __thewayBrokerCall("workspace.writeText", { path, content });
        },
      }),
      process: Object.freeze({
        async run(argv, options = {}) {
          return __thewayBrokerCall("process.run", {
            argv,
            timeoutMs: options.timeoutMs ?? null,
          });
        },
      }),
      network: Object.freeze({
        async fetch(url, options = {}) {
          return __thewayBrokerCall("network.fetch", {
            url,
            method: options.method ?? null,
            headers: options.headers ?? {},
            body: options.body ?? null,
          });
        },
      }),
      secrets: Object.freeze({
        async read(name) {
          return __thewayBrokerCall("secrets.read", { name });
        },
      }),
      providerRaw: Object.freeze({
        async read() {
          return __thewayBrokerCall("providerRaw.read", {});
        },
      }),
      state: Object.freeze({
        get(key) {
          if (globalThis.__thewayPendingState.has(key)) {
            return globalThis.__thewayPendingState.get(key);
          }
          return __thewayBrokerCall("state.get", { key });
        },
        set(key, value) {
          __thewayQueueDurable("set_state", {
            kind: "state_mutation",
            key,
            mutation: { operation: "set", value },
          });
          globalThis.__thewayPendingState.set(key, value);
        },
        delete(key) {
          __thewayQueueDurable("delete_state", {
            kind: "state_mutation",
            key,
            mutation: { operation: "delete" },
          });
          globalThis.__thewayPendingState.set(key, null);
        },
      }),
      events: Object.freeze({
        replay(customType = null) {
          return __thewayBrokerCall("events.replay", { customType });
        },
        append(eventId, type, payload) {
          __thewayQueueDurable("append_custom_event", {
            kind: "custom_event",
            eventId,
            customType: type,
            payload,
          });
        },
      }),
      modelContext: Object.freeze({
        append(contextId, placement, content) {
          __thewayQueueDurable("append_model_context", {
            kind: "model_context",
            contextId,
            placement,
            content,
          });
        },
      }),
      memory: Object.freeze({
        get(key) {
          return __thewayBrokerCall("memory.get", { key });
        },
        set(key, value) {
          return __thewayBrokerCall("memory.set", { key, value });
        },
        delete(key) {
          return __thewayBrokerCall("memory.delete", { key });
        },
        clear() {
          return __thewayBrokerCall("memory.clear", {});
        },
      }),
      effect(execute) {
        if (typeof execute !== "function") {
          throw new TypeError("api.effect requires a function");
        }
        const disposer = execute();
        globalThis.__thewayDisposers.push({
          disposer: typeof disposer === "function" ? disposer : null,
          disposed: false,
        });
        const registration = {
          id: globalThis.__thewayRegistrationSequence++,
          kind: "effect",
          disposed: false,
        };
        globalThis.__thewayRegistrations[registration.id] = registration;
        return __thewayHandle(registration);
      },
      getConfig() {
        return __thewayBrokerCall("config.get", {});
      },
      provide(name, value) {
        return __thewayBrokerCall("services.provide", { name, value });
      },
      get(name) {
        const value = __thewayBrokerCall("services.get", { name });
        return value === null ? undefined : value;
      },
      migrateState(handler) {        if (typeof handler !== "function") {
          throw new TypeError("api.migrateState requires a handler");
        }
        if (globalThis.__thewayMigrationRegistrationId !== null) {
          throw new Error("only one state migration handler may be registered");
        }
        const registration = {
          id: globalThis.__thewayRegistrationSequence++,
          kind: "state_migration",
          handler,
          disposed: false,
        };
        globalThis.__thewayRegistrations[registration.id] = registration;
        globalThis.__thewayMigrationRegistrationId = registration.id;
        return __thewayHandle(registration);
      },
      registerTool(descriptor, handler) {
        // Dual signature: registerTool(name, desc, schema, fn) positional form
        // and registerTool(descriptor, handler) object form.
        if (typeof descriptor === "string" && arguments.length >= 3) {
          const name = descriptor;
          const description = arguments[1];
          const inputSchema = arguments[2];
          handler = arguments[3];
          descriptor = {
            name,
            label: description,
            description,
            inputSchema,
          };
        } else if (descriptor && typeof descriptor === "object") {
          // Object form: tolerate the bare { name, description, inputSchema }
          // shape by deriving the required label from description/name.
          if (descriptor.label === undefined) {
            descriptor = { ...descriptor, label: descriptor.description ?? descriptor.name ?? "" };
          }
        }
        return __thewayRegister("tool", descriptor, handler);
      },
      registerCommand(descriptor, handler) {
        return __thewayRegister("command", descriptor, handler);
      },
      registerProvider(descriptor) {
        return __thewayRegister("provider", descriptor, undefined);
      },
      registerPromptSection(descriptor) {
        return __thewayRegister("prompt_section", descriptor, undefined);
      },
      registerRequestPolicy(descriptor, handler) {
        return __thewayRegister("request_policy", descriptor, handler);
      },
      contribute(descriptor) {
        return __thewayRegister("contribution", descriptor, undefined);
      },
      on(event, descriptor, handler) {
        if (typeof descriptor === "function") {
          handler = descriptor;
          descriptor = {};
        }
        if (typeof event !== "string" || event.length === 0 || typeof handler !== "function") {
          throw new TypeError("api.on requires an event name and handler");
        }
        return __thewayRegisterHandler(event, descriptor, handler, false);
      },
      once(event, descriptor, handler) {
        if (typeof descriptor === "function") {
          handler = descriptor;
          descriptor = {};
        }
        if (typeof event !== "string" || event.length === 0 || typeof handler !== "function") {
          throw new TypeError("api.once requires an event name and handler");
        }
        return __thewayRegisterHandler(event, descriptor, handler, true);
      },
      registerAction(descriptor, handler) {
        // Dual shape: registerAction(name, fn) or registerAction(descriptor, handler).
        if (typeof descriptor === "string") {
          handler = arguments[1];
          descriptor = { name: descriptor, description: "", inputSchema: {} };
        }
        return __thewayRegister("action", descriptor, handler);
      },
      registerPromptVariable(descriptor) {
        return __thewayRegister("prompt_variable", descriptor, undefined);
      },
      native(name, args) {
        return __thewayBrokerCall("native.call", { name, args: args ?? {} });
      },
      log(level, message) {
        return __thewayBrokerCall("native.call", {
          name: "log",
          args: { level, message },
        });
      },
      runtime: Object.freeze({
        version: __thewayRuntimeVersion,
        pluginId: __thewayRuntimePluginId,
        sessionId: __thewayRuntimeSessionId,
      }),
      emit(event, payload, mode) {
        return __thewayBrokerCall("events.publish", {
          event,
          payload: payload ?? null,
          mode: mode ?? null,
        });
      },
    });
    await setup(api);
    return JSON.stringify({
      ok: true,
      value: {
        registrations: Object.values(globalThis.__thewayHandlers)
          .flat()
          .filter(({ disposed }) => !disposed)
          .map(({ id, event, descriptor, sequence }) => ({
            registrationId: id,
            event,
            descriptor,
            sequence,
          })),
        effects: globalThis.__thewayEffects
          .filter(({ disposed }) => !disposed)
          .map(({ id, kind, descriptor, sequence }) => ({
            registrationId: id,
            kind,
            descriptor,
            sequence,
          })),
        migrationRegistrationId: globalThis.__thewayMigrationRegistrationId,
        inject: declaredInject,
      },
    });
  } catch (error) {
    return JSON.stringify({ error: String(error?.message ?? error) });
  }
};

globalThis.__thewayInvoke = async function (serializedEnvelope, registrationId) {
  try {
    let envelope = JSON.parse(serializedEnvelope);
    globalThis.__thewayCurrentEnvelope = envelope;
    globalThis.__thewayPendingDurableActions = [];
    globalThis.__thewayPendingState = new Map();
    const registration = globalThis.__thewayRegistrations[registrationId];
    if (registration === undefined) {
      throw new Error("registration is unavailable");
    }
    if (registration.disposed) {
      const error = new Error("registration handle is disposed");
      error.code = "effect_disposed";
      throw error;
    }
    // The host resolves public names to the internal event before dispatch.
    // Restore the author-facing subscription name for the handler, and unwrap
    // the custom-event envelope (`custom` → { event, payload }).
    if (typeof registration.event === "string" && registration.event !== envelope.event) {
      envelope = {
        ...envelope,
        event: registration.event,
        payload: envelope.event === "custom" && envelope.payload !== null
          && typeof envelope.payload === "object"
          ? envelope.payload.payload
          : envelope.payload,
      };
      globalThis.__thewayCurrentEnvelope = envelope;
    }
    const result = registration.event !== undefined
      ? await registration.handler(envelope, envelope.context)
      : await registration.handler(envelope.payload, envelope.context);
    globalThis.__thewayCurrentEnvelope = null;
    return JSON.stringify({
      ok: true,
      value: {
        result: result ?? null,
        disposedRegistrationIds: __thewayDisposedRegistrationIds(),
        queuedDurableActions: globalThis.__thewayPendingDurableActions,
      },
    });
  } catch (error) {
    globalThis.__thewayCurrentEnvelope = null;
    globalThis.__thewayPendingDurableActions = [];
    globalThis.__thewayPendingState = new Map();
    return JSON.stringify({ error: String(error?.message ?? error) });
  }
};
"#;