@nylorun/runtime 0.3.0-beta → 0.5.0-beta

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +53 -20
  3. package/dist/adapters/media.d.ts +2 -18
  4. package/dist/adapters/media.js +2 -52
  5. package/dist/adapters/observe.js +1 -1
  6. package/dist/cli.js +11 -6
  7. package/dist/config.d.ts +17 -10
  8. package/dist/contracts.d.ts +3 -166
  9. package/dist/dev-entry.d.ts +1 -0
  10. package/dist/dev-entry.js +2 -0
  11. package/dist/dev.js +6 -1
  12. package/dist/environment.d.ts +2 -0
  13. package/dist/environment.js +64 -0
  14. package/dist/index.d.ts +8 -8
  15. package/dist/index.js +5 -5
  16. package/dist/launcher.d.ts +1 -0
  17. package/dist/launcher.js +33 -0
  18. package/dist/media.d.ts +29 -0
  19. package/dist/media.js +53 -0
  20. package/dist/model/auth-store.d.ts +2 -1
  21. package/dist/model/auth-store.js +9 -2
  22. package/dist/model/configure.js +60 -30
  23. package/dist/model/defaults.d.ts +17 -0
  24. package/dist/model/defaults.js +21 -0
  25. package/dist/model/http-model.d.ts +12 -0
  26. package/dist/model/http-model.js +299 -0
  27. package/dist/model/models.d.ts +2 -2
  28. package/dist/model/models.js +24 -3
  29. package/dist/model/pi-model.d.ts +2 -1
  30. package/dist/model/pi-model.js +53 -8
  31. package/dist/model/settings.js +35 -13
  32. package/dist/node/index.d.ts +5 -0
  33. package/dist/node/index.js +5 -0
  34. package/dist/node/local-sessions.d.ts +5 -0
  35. package/dist/node/local-sessions.js +157 -0
  36. package/dist/redact.d.ts +1 -0
  37. package/dist/redact.js +14 -0
  38. package/dist/server/ag-ui.d.ts +1 -1
  39. package/dist/server/delivery.d.ts +24 -0
  40. package/dist/server/delivery.js +107 -0
  41. package/dist/server/host.d.ts +11 -6
  42. package/dist/server/host.js +236 -305
  43. package/dist/sessions/host.d.ts +29 -0
  44. package/dist/sessions/host.js +291 -0
  45. package/dist/sessions/store.d.ts +40 -0
  46. package/dist/sessions/store.js +30 -0
  47. package/package.json +11 -4
  48. package/dist/adapters/journal.d.ts +0 -35
  49. package/dist/adapters/journal.js +0 -130
package/CHANGELOG.md CHANGED
@@ -1,5 +1,36 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.0-beta
4
+
5
+ ### Minor Changes
6
+
7
+ - Breaking beta: Runtime hosts use Harness `info` (`getInfo` / `SubmitOptions.info`) instead of
8
+ `scope`. Session scheduling stays in Runtime; Node-only adapters remain under
9
+ `@nylorun/runtime/node`. Compatible with Harness capability manifests and ToolDescriptor-only
10
+ model requests.
11
+ - c5bbb1a: Breaking beta: make Harness `run()` a direct async state-in/state-out executor with
12
+ serializable pauses, application `info`, cancellation signals, awaited recording, and
13
+ agent-level output schemas. Runtime owns session scheduling with memory-default or exclusive
14
+ local storage and imports Harness contracts. Isolate Node adapters under `runtime/node`, stream
15
+ observations incrementally, and add opt-in bounded token previews with Studio reconciliation.
16
+ Migrate consumers and deployment guidance together; legacy event records remain archived, not
17
+ automatically replayed.
18
+
19
+ ### Patch Changes
20
+
21
+ - Ignore Hono Node `context.env` stream bindings (`incoming`/`outgoing`) when
22
+ resolving model environment so Node `nylorun dev` uses process `.env` /
23
+ `piModel` instead of an empty portable HTTP adapter.
24
+ - Update Runtime's canonical Harness dependency to the tested release.
25
+ - Updated dependencies [c5bbb1a]
26
+ - @nylorun/harness@0.13.0-beta
27
+
28
+ ## 0.4.0-beta
29
+
30
+ ### Minor Changes
31
+
32
+ - fa1860a: Use standard MODEL_PROVIDER, MODEL, MODEL_PROVIDER_API_KEY, and MODEL_PROVIDER_BASE_URL environment configuration. Export starter Hono apps and provide CLI development and production Node launchers. Existing starters require manual migration. Release preparation must update the creator Runtime compatibility pin with this release.
33
+
3
34
  ## 0.3.0-beta
4
35
 
5
36
  ### Minor Changes
package/README.md CHANGED
@@ -1,46 +1,79 @@
1
1
  # @nylorun/runtime
2
2
 
3
- Portable agent lifecycle, a mountable Hono protocol router, pi-ai model providers, and the `nylorun` CLI. Runtime has no Harness dependency.
3
+ Optional hosting for stateless Harness agents: session coordination, replaceable storage, Hono routes, model adapters, and the Node CLI. Runtime depends directly on canonical Harness types; Harness does not depend on Runtime.
4
4
 
5
5
  ```ts
6
+ import { Hono } from "hono";
6
7
  import { Runtime, serveAgents } from "@nylorun/runtime";
7
-
8
8
  const runtime = new Runtime();
9
- app.route(
10
- "/agents",
11
- serveAgents({ agents, runtime })
12
- );
9
+ const app = new Hono();
10
+ app.route("/agents", serveAgents({ agents, runtime }));
11
+ export default app;
12
+ ```
13
+
14
+ The default is `memorySessions()` and no file observer. Portable imports do not initialize the filesystem. `httpModel()` supports text/tool/structured-output requests to OpenAI-compatible and Anthropic HTTP endpoints using injected environment values or process variables where available. It requires API keys; media inputs require a supplied media-aware adapter. The Node CLI installs `piModel()` for its broader provider catalog, local credential fallback, OAuth, and media support. Direct portable imports do not load dotenv or local credentials.
15
+
16
+ ## Storage and coordination
17
+
18
+ ```ts
19
+ import { localSessions, piModel } from "@nylorun/runtime/node";
20
+ const runtime = new Runtime({
21
+ sessions: localSessions({ root: ".data/sessions" }),
22
+ onModelCall: piModel(),
23
+ });
13
24
  ```
14
25
 
15
- `Runtime` is the primitive stack: model adapter (`piModel` by default), observer (`jsonlObserver` per session by default), and durability (`localJsonl` by default). Session files live together under `.data/sessions/<agent>/<session>/` as `events.jsonl` and `observe.jsonl`. Agents bind only when served.
26
+ A `SessionStore` provides `get(agentId, sessionId)`, atomic `put(agentId, sessionId, document)`, and `list(agentId)`. StoredSession includes Runtime metadata, Harness state, an active marker, and committed event history. Stores implement data operations only. The built-in SessionHost serializes inputs, cancels and awaits active work before replacement, persists accepted inputs before execution, and commits terminal state before reporting success. It restores completed and explicitly paused sessions; active markers found after a crash require reconciliation. Legacy event-only records remain archived history.
27
+
28
+ `localSessions` exclusively owns its root through `.owner.lock`. Multiple owners are rejected, including adapters in the same process. Writes use temporary files and atomic replacement; lost ownership stops writes. Orderly `runtime.close()` releases the matching lock. Locks are never stolen by age or PID: after a crash, confirm the owner stopped before manually removing the lock. No shared-filesystem or multi-replica guarantee is made.
29
+
30
+ The host's scheduling scope is one process. A shared store is not a distributed scheduler. Advanced applications can use `SessionHost` without Hono, reuse `agUiEvents()` protocol translation, or compose Harness with their own host. Managed Cloud Runtime remains future work.
16
31
 
17
- The application owns Hono composition, authentication, CORS, logging, process lifecycle, and deployment. Runtime owns agent sessions, durability, media, and AG-UI/session protocol routes. Graceful shutdown is optional: if the application installs signal handlers and wants to drain live sessions, flush pending journal writes, and run optional agent cleanup, it should await `runtime.close()`. An application that does not install handlers exits normally on its host's shutdown policy; `runtime.close()` does not run on crash, OOM, or SIGKILL.
32
+ ## Info, delivery, and resources
18
33
 
19
- Runtime publishes root-relative discovery and endpoint URLs. It infers the Hono
20
- mount from each request URL (so a separate consumer `hono` install still works).
21
- Mount at `/agents` or `/api/agents` without repeating that path in `serveAgents`.
22
- Pass explicit `basePath` when a reverse proxy rewrites the public prefix.
34
+ Application middleware authorizes every route. `getInfo(context)` supplies extra application data for each invocation; Runtime adds `sessionId`. `getEnvironment(context)` can supply per-request provider bindings without changing process globals. Neither info nor live resources are implicitly model-visible. `getActor` remains a convenience for userId; use `getInfo` for typed application identity.
23
35
 
24
- `nylorun dev` enables local Studio connections automatically by setting `NYLORUN_DEV=1` for its child application. This allows HTTP/HTTPS browser origins on `localhost`, `127.0.0.1`, or `[::1]`, including Studio's fallback ports. Ordinary production startup does not enable this policy; the application owns production CORS and authorization.
36
+ Runtime delivers ordered observations incrementally, separately from committed history. `tokens: true` enables provisional text previews on compatible model adapters; the default is off. `createModel({ environment, media, onPreview })` supplies preview support for custom adapters. Studio shows drafts separately and discards them on settlement; accepted output remains authoritative. Partial tool arguments never dispatch tools.
25
37
 
26
- `getActor(context)` supplies an optional actor id and session context for newly created sessions. `getRequestMetadata(context)` supplies JSON-safe metadata for inbound messages. Application middleware remains responsible for authorizing every agent route.
38
+ Delivery limits default to 64 KiB of preview data per model invocation (also bounding queued previews), and 256 events or 1 MiB of queued execution/control data. Configure them with `delivery: { previewBytes, eventCount, eventBytes }`. Preview overflow suppresses further previews for that model invocation and emits an incomplete marker. Authoritative overflow closes the subscription. Neither path blocks model consumption; request-attached execution is cooperatively cancelled on disconnect. Independent execution/reconnection belongs to a custom host.
39
+
40
+ Runtime owns controllers and its store lifecycle. It does not close application tools, databases, browsers, or subprocesses. The Node launcher drains registered Runtime hosts during orderly shutdown; application resource cleanup remains explicit. Imports never open a listening socket. Root-relative discovery supports ordinary Hono mounts; use `basePath` for a rewriting proxy. Production authentication, CORS, ingress timeouts, and TLS belong to the application and infrastructure.
27
41
 
28
42
  ## Commands
29
43
 
30
44
  - `nylorun configure`
31
45
  - `nylorun dev [--no-studio] [--no-open]`
46
+ - `nylorun start [entry]` (default: `dist/src/index.js`)
32
47
  - `nylorun studio --agent-url http://localhost:3000/agents [--port 4161] [--no-open]`
33
48
 
34
- Studio attaches to an application you run. Use your own TypeScript/build tooling and a Node adapter such as `@hono/node-server` when applicable. `projectAsset("agents/skills/catalog")` resolves bundled application assets from source or a compiled `dist/` deployment.
49
+ Export your Hono application with `export default app`. The CLI supplies the Node server adapter. `nylorun dev` watches `src/index.ts`, waits for `/agents/v1/agents`, and starts project-local Studio. `PORT` defaults to 3000. `--no-studio` runs only the application; `--no-open` keeps the browser closed. Ctrl-C stops both processes. `nylorun start` serves the built app without Studio or development CORS.
50
+
51
+ ### Environment configuration
35
52
 
36
- Provider credentials are stored in `.env/auth.json`, and selection in `.env/model.json`. `nylorun configure` can run before an agent graph is importable.
53
+ Copy `.env.example` to `.env` and fill it in, or run `nylorun configure` before your agent graph is importable:
54
+
55
+ ```dotenv
56
+ MODEL_PROVIDER=custom
57
+ MODEL=your-model-id
58
+ MODEL_PROVIDER_API_KEY=your-key
59
+ MODEL_PROVIDER_BASE_URL=https://your-provider.example/v1
60
+ ```
37
61
 
38
- `nylorun dev` runs project-local `tsx watch src/index.ts`, waits for `/agents/v1/agents`, then starts project-local Studio. `PORT` defaults to 3000. `--no-studio` runs just the application; `--no-open` keeps the browser closed. Both flags can be combined. Ctrl-C stops both processes.
62
+ `MODEL_PROVIDER_BASE_URL` is required only for `MODEL_PROVIDER=custom`; omit it for built-in providers. `configure`, `dev`, and `start` load `.env` before importing the app. Existing process variables win; a missing `.env` is valid. `.env.local` is ignored by Git but is not automatically loaded. Direct imports of Runtime do not load dotenv files.
63
+
64
+ Explicit `piModel({ selection })` options take precedence over environment selection. Environment selection takes precedence over legacy files; incomplete selection produces an error. `MODEL_PROVIDER_API_KEY` overrides provider-native variables such as `OPENAI_API_KEY` and `ANTHROPIC_API_KEY`, which override stored credentials. API-key deployments require no credential files. Supply the same variables through your hosting provider's environment settings.
65
+
66
+ The optional wizard writes selection and entered API keys to `.env`, preserving unrelated configuration. It reuses environment credentials without copying them into the file. OAuth is an alternative where supported; its credentials and refresh state live in ignored `.nylorun/auth.json`. Keep `.env` and `.nylorun/` private.
39
67
 
40
68
  ### Upgrading an existing starter
41
69
 
42
- After upgrading Runtime to a release containing `nylorun dev`, change the development script to `"dev": "nylorun dev"` and remove `dev:app` and `scripts/dev.mjs`. Remove the duplicated `basePath` option for normal Hono mounts.
70
+ Migration is manual; the CLI will not replace a legacy `.env` directory.
71
+
72
+ 1. Back up the existing `.env/` directory to a private location outside the project before replacing it with a file. Preserve any `config/model.json` too.
73
+ 2. Translate `model.json` fields `provider`, `model`, and `custom.baseUrl` into `MODEL_PROVIDER`, `MODEL`, and `MODEL_PROVIDER_BASE_URL`. Copy API keys into `MODEL_PROVIDER_API_KEY` or provider-native variables. Replace the old `NYLO_CUSTOM_API_KEY` variable with `MODEL_PROVIDER_API_KEY`.
74
+ 3. Merge `integrations.env` variables into `.env`. Move OAuth records into `.nylorun/auth.json`. Add `.env`, `.env.local`, and `.nylorun/` to `.gitignore`; remove the old `.env/` exceptions.
75
+ 4. Replace the entrypoint's `serve(...)` call and Node adapter import with `export default app`. Set scripts to `"dev": "nylorun dev"` and `"start": "nylorun start"`. Remove the application's `@hono/node-server` dependency if unused elsewhere. Keep your build and asset-copy steps.
43
76
 
44
- Run `npm run configure` to move model selection to `.env/model.json`. Runtime reads the legacy `config/model.json` only when the new file is absent. Successful configuration removes the legacy file and its directory only if empty; credentials remain in `.env/auth.json`. Do not set `NYLORUN_DEV` in production.
77
+ Runtime retains legacy `.env/model.json`, `config/model.json`, and `.env/auth.json` reads for existing applications using their own launcher. It does not automatically move or delete these files. Use the matching Runtime release pinned by the new creator; older releases cannot launch an exported app.
45
78
 
46
- The starter now uses one `tsconfig.json` with `rootDir: "."` and `outDir: "dist"`. Remove `noEmit` from that file and use `tsc --noEmit` for checks. Change the build's compiler invocation to `tsc -p tsconfig.json` before deleting `tsconfig.build.json`. Keep your existing asset-copy step. Projects whose checks include tests may retain separate build configuration.
79
+ The exported app follows Hono composition conventions. See [deployment verification and limits](../DEPLOYMENT.md) and the [breaking migration guide](../MIGRATION.md). Node-only `projectAsset()` resolves bundled assets from source or compiled deployments.
@@ -1,16 +1,5 @@
1
- export declare const IMAGE_MEDIA_TYPES: readonly string[];
2
- export declare const MAX_IMAGE_BYTES: number;
3
- export interface MediaAsset {
4
- readonly id: string;
5
- readonly mediaType: string;
6
- readonly bytes: number;
7
- readonly kind: "input" | "generated";
8
- }
9
- /** Opaque reference retained by Harness and resolved by the configured media adapter. */
10
- export interface MediaReference {
11
- readonly agentId: string;
12
- readonly assetId: string;
13
- }
1
+ import { type MediaAsset, type MediaReference } from "../media.js";
2
+ export * from "../media.js";
14
3
  /** Explicit local asset store; agents receive only opaque references. */
15
4
  export declare class MediaStore {
16
5
  private readonly root;
@@ -30,11 +19,6 @@ export declare class MediaStore {
30
19
  private readMetadata;
31
20
  private directory;
32
21
  }
33
- /** Decode one canonical base64 image before it is persisted or sent to a provider. */
34
- export declare function decodeImageBase64(mediaType: string, base64: string): Uint8Array;
35
- /** Verify the asserted media type and lightweight file signature for a supported image. */
36
- export declare function validateImageBytes(mediaType: string, bytes: Uint8Array): void;
37
22
  export declare function localMedia(options?: {
38
23
  root?: string;
39
24
  }): MediaStore;
40
- export type RuntimeMedia = Pick<MediaStore, "saveInput" | "saveGenerated" | "dataUrl" | "latestInput" | "read">;
@@ -1,12 +1,8 @@
1
1
  import { mkdir, readFile, readdir, writeFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
3
  import { randomUUID } from "node:crypto";
4
- export const IMAGE_MEDIA_TYPES = Object.freeze([
5
- "image/jpeg",
6
- "image/png",
7
- "image/webp",
8
- ]);
9
- export const MAX_IMAGE_BYTES = 8 * 1024 * 1024;
4
+ import { IMAGE_MEDIA_TYPES, MAX_IMAGE_BYTES, decodeImageBase64, validateImageBytes, } from "../media.js";
5
+ export * from "../media.js";
10
6
  /** Explicit local asset store; agents receive only opaque references. */
11
7
  export class MediaStore {
12
8
  root;
@@ -91,52 +87,6 @@ export class MediaStore {
91
87
  }
92
88
  }
93
89
  /** Decode one canonical base64 image before it is persisted or sent to a provider. */
94
- export function decodeImageBase64(mediaType, base64) {
95
- if (!IMAGE_MEDIA_TYPES.includes(mediaType))
96
- throw new Error("Only JPEG, PNG, and WebP images are supported.");
97
- if (typeof base64 !== "string" || base64 === "")
98
- throw new Error("Image data is required.");
99
- if (base64.length % 4 !== 0 || !/^[A-Za-z0-9+/]*={0,2}$/u.test(base64))
100
- throw new Error("Image data must be canonical base64.");
101
- const bytes = Buffer.from(base64, "base64");
102
- if (bytes.toString("base64") !== base64)
103
- throw new Error("Image data must be canonical base64.");
104
- validateImageBytes(mediaType, bytes);
105
- return bytes;
106
- }
107
- /** Verify the asserted media type and lightweight file signature for a supported image. */
108
- export function validateImageBytes(mediaType, bytes) {
109
- if (!IMAGE_MEDIA_TYPES.includes(mediaType))
110
- throw new Error("Only JPEG, PNG, and WebP images are supported.");
111
- if (bytes.byteLength === 0 || bytes.byteLength > MAX_IMAGE_BYTES)
112
- throw new Error("Images must be no larger than 8 MiB.");
113
- const signature = mediaType === "image/jpeg"
114
- ? bytes.byteLength >= 3 &&
115
- bytes[0] === 0xff &&
116
- bytes[1] === 0xd8 &&
117
- bytes[2] === 0xff
118
- : mediaType === "image/png"
119
- ? bytes.byteLength >= 8 &&
120
- bytes[0] === 0x89 &&
121
- bytes[1] === 0x50 &&
122
- bytes[2] === 0x4e &&
123
- bytes[3] === 0x47 &&
124
- bytes[4] === 0x0d &&
125
- bytes[5] === 0x0a &&
126
- bytes[6] === 0x1a &&
127
- bytes[7] === 0x0a
128
- : bytes.byteLength >= 12 &&
129
- bytes[0] === 0x52 &&
130
- bytes[1] === 0x49 &&
131
- bytes[2] === 0x46 &&
132
- bytes[3] === 0x46 &&
133
- bytes[8] === 0x57 &&
134
- bytes[9] === 0x45 &&
135
- bytes[10] === 0x42 &&
136
- bytes[11] === 0x50;
137
- if (!signature)
138
- throw new Error(`Image bytes do not match ${mediaType}.`);
139
- }
140
90
  function validAsset(value) {
141
91
  if (!value || typeof value !== "object")
142
92
  return false;
@@ -1,6 +1,6 @@
1
1
  import { appendFile, mkdir } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
- import { scrub } from "./journal.js";
3
+ import { scrub } from "../redact.js";
4
4
  import { projectSecrets } from "../model/settings.js";
5
5
  /** Local JSONL observer. Writes raw engine events beside session durability files. */
6
6
  export function jsonlObserver(options) {
package/dist/cli.js CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
- import { existsSync } from "node:fs";
3
- import { loadEnvFile } from "node:process";
4
2
  import { join } from "node:path";
5
3
  import { pathToFileURL } from "node:url";
6
4
  import { createRequire } from "node:module";
7
5
  import { ConfigurationCancelled, configureProvider, } from "./model/configure.js";
6
+ import { loadProjectEnvironment } from "./environment.js";
8
7
  import { develop } from "./dev.js";
9
- const usage = `nylorun <configure|dev|studio>
8
+ const usage = `nylorun <configure|dev|start|studio>
10
9
  dev [--no-studio] [--no-open]
10
+ start [entry]
11
11
  configure
12
12
  studio --agent-url <http(s)-url> [--port <n>] [--no-open]`;
13
13
  async function startStudio(agentServerUrl, open, port) {
@@ -37,6 +37,14 @@ async function main() {
37
37
  const [command, ...args] = process.argv.slice(2);
38
38
  if (!command || command === "--help" || command === "-h")
39
39
  return void console.log(usage);
40
+ if (["configure", "dev", "start"].includes(command))
41
+ loadProjectEnvironment();
42
+ if (command === "start") {
43
+ if (args.length > 1 || args[0]?.startsWith("--"))
44
+ throw new Error(usage);
45
+ await (await import("./launcher.js")).start(args[0]);
46
+ return;
47
+ }
40
48
  if (command === "dev") {
41
49
  process.exitCode = await develop(args);
42
50
  return;
@@ -48,9 +56,6 @@ async function main() {
48
56
  const cancel = (signal) => controller.abort(new ConfigurationCancelled(signal));
49
57
  process.once("SIGINT", () => cancel("SIGINT"));
50
58
  process.once("SIGTERM", () => cancel("SIGTERM"));
51
- const integrations = join(process.cwd(), ".env", "integrations.env");
52
- if (existsSync(integrations))
53
- loadEnvFile(integrations);
54
59
  await configureProvider({ signal: controller.signal });
55
60
  return;
56
61
  }
package/dist/config.d.ts CHANGED
@@ -1,13 +1,20 @@
1
- import type { RuntimeModelAdapter } from "./contracts.js";
2
- import type { RuntimeDurability } from "./adapters/journal.js";
3
- import type { RuntimeMedia } from "./adapters/media.js";
1
+ import type { ModelAdapter } from "@nylorun/harness";
2
+ import type { SessionStore } from "./sessions/store.js";
3
+ import type { RuntimeMedia } from "./media.js";
4
+ import type { ModelEnvironment } from "./model/http-model.js";
4
5
  export interface RuntimeConfig {
5
- readonly onModelCall?: RuntimeModelAdapter;
6
- readonly observer?: {
7
- (event: {
8
- readonly type: string;
9
- }): void | Promise<void>;
10
- };
11
- readonly durability?: RuntimeDurability;
6
+ readonly onModelCall?: ModelAdapter;
7
+ readonly createModel?: (options: import("./model/defaults.js").ModelFactoryOptions) => ModelAdapter;
8
+ readonly observer?: (event: {
9
+ readonly type: string;
10
+ }) => void | Promise<void>;
11
+ readonly sessions?: SessionStore;
12
12
  readonly media?: RuntimeMedia;
13
+ readonly environment?: ModelEnvironment;
14
+ readonly tokens?: boolean;
15
+ readonly delivery?: {
16
+ readonly previewBytes?: number;
17
+ readonly eventBytes?: number;
18
+ readonly eventCount?: number;
19
+ };
13
20
  }
@@ -1,166 +1,3 @@
1
- /** Portable values and callable interfaces. No agent engine is required. */
2
- export type JsonValue = string | number | boolean | null | JsonObject | readonly JsonValue[];
3
- export type JsonObject = {
4
- readonly [key: string]: JsonValue;
5
- };
6
- export type UserContentPart = {
7
- readonly type: "text";
8
- readonly text: string;
9
- } | {
10
- readonly type: "media";
11
- readonly mediaType: string;
12
- readonly reference: JsonValue;
13
- };
14
- export type MessageInput = string | {
15
- readonly text: string;
16
- readonly metadata?: JsonObject;
17
- } | {
18
- readonly content: readonly UserContentPart[];
19
- readonly metadata?: JsonObject;
20
- };
21
- export type InteractionReply = {
22
- readonly kind: "approve";
23
- readonly interactionId: string;
24
- readonly approved: boolean;
25
- } | {
26
- readonly kind: "respond";
27
- readonly interactionId: string;
28
- readonly value: JsonValue;
29
- };
30
- export type RuntimeInput = MessageInput | InteractionReply;
31
- export type RuntimeInputEvent = InteractionReply | {
32
- readonly kind: "user-message" | "interrupt";
33
- readonly text?: string;
34
- readonly content?: readonly UserContentPart[];
35
- };
36
- /** Lifecycle events are delivered in completion order; other events are diagnostics. */
37
- export interface RuntimeEvent {
38
- readonly type: string;
39
- readonly output?: JsonValue;
40
- readonly event?: RuntimeInputEvent;
41
- readonly interaction?: unknown;
42
- readonly attributes?: unknown;
43
- readonly tripwire?: {
44
- readonly code: string;
45
- readonly message?: string;
46
- };
47
- }
48
- export interface RuntimeCompletion {
49
- readonly status: "completed" | "waiting" | "rejected" | "cancelled" | "stopped";
50
- readonly events: readonly RuntimeEvent[];
51
- }
52
- export interface RuntimeSession {
53
- readonly id: string;
54
- input(event: RuntimeInput, options?: {
55
- readonly signal?: AbortSignal;
56
- }): {
57
- readonly completed: Promise<RuntimeCompletion>;
58
- };
59
- stream(): AsyncIterable<RuntimeEvent>;
60
- stop(reason?: string): Promise<void>;
61
- }
62
- export interface RuntimeRunOptions {
63
- readonly id?: string;
64
- readonly userId?: string;
65
- readonly context?: JsonObject;
66
- readonly onModelCall: RuntimeModelAdapter;
67
- readonly observer?: {
68
- (event: {
69
- readonly type: string;
70
- }): void | Promise<void>;
71
- };
72
- }
73
- export interface RuntimeAgent {
74
- readonly id: string;
75
- readonly name: string;
76
- readonly manifest: {
77
- readonly id: string;
78
- readonly name: string;
79
- };
80
- run(options: RuntimeRunOptions): RuntimeSession;
81
- close?(): Promise<void>;
82
- }
83
- export type PromptContentPart = Exclude<UserContentPart, {
84
- readonly type: "text";
85
- }> | {
86
- readonly type: "text" | "reasoning";
87
- readonly text: string;
88
- readonly providerMetadata?: JsonObject;
89
- } | {
90
- readonly type: "tool-call";
91
- readonly providerMetadata?: JsonObject;
92
- readonly id: string;
93
- readonly name: string;
94
- readonly args: JsonObject;
95
- };
96
- export type PromptItem = {
97
- readonly kind: "instructions";
98
- readonly role: "system";
99
- readonly content: readonly PromptContentPart[];
100
- } | {
101
- readonly kind: "message";
102
- readonly role: "user" | "assistant";
103
- readonly content: readonly PromptContentPart[];
104
- } | {
105
- readonly kind: "context";
106
- readonly role: "user";
107
- readonly content: readonly PromptContentPart[];
108
- } | {
109
- readonly kind: "tool-result";
110
- readonly toolCallId: string;
111
- readonly toolName: string;
112
- readonly status: "completed" | "denied" | "failed";
113
- readonly content: readonly PromptContentPart[];
114
- };
115
- export interface RuntimeModelCall {
116
- readonly sessionId: string;
117
- readonly prompt: readonly PromptItem[];
118
- readonly tools: readonly {
119
- readonly name: string;
120
- readonly description?: string;
121
- readonly inputSchema: JsonObject;
122
- }[];
123
- readonly outputSchema?: JsonObject;
124
- readonly model?: {
125
- readonly id?: string;
126
- readonly controls?: {
127
- readonly temperature?: number;
128
- readonly maxOutputTokens?: number;
129
- };
130
- readonly config?: JsonObject;
131
- };
132
- }
133
- export interface RuntimeModelCandidate {
134
- readonly output: readonly ({
135
- readonly type: "text" | "reasoning";
136
- readonly text: string;
137
- readonly providerMetadata?: JsonObject;
138
- } | {
139
- readonly type: "json";
140
- readonly value: JsonValue;
141
- } | {
142
- readonly type: "tool-call";
143
- readonly providerMetadata?: JsonObject;
144
- readonly id: string;
145
- readonly name: string;
146
- readonly args: JsonObject;
147
- })[];
148
- readonly finishReason?: "stop" | "length" | "tool-calls" | "content-filter" | "other";
149
- readonly usage?: {
150
- readonly inputTokens?: number;
151
- readonly outputTokens?: number;
152
- readonly totalTokens?: number;
153
- readonly costUsd?: number;
154
- };
155
- readonly evidence?: {
156
- readonly resolvedModel?: string;
157
- };
158
- }
159
- export interface RuntimeModelContext {
160
- readonly signal: AbortSignal;
161
- reportPreparedCall?(prepared: {
162
- readonly adapter: string;
163
- readonly call: JsonValue;
164
- }): void;
165
- }
166
- export type RuntimeModelAdapter = (call: RuntimeModelCall, context: RuntimeModelContext) => Promise<RuntimeModelCandidate>;
1
+ /** Execution contracts are owned by Harness. */
2
+ export type { JsonValue, JsonObject, MessageInput, UserContentPart, PromptContentPart, PromptItem, ModelCall as RuntimeModelCall, ModelCandidate as RuntimeModelCandidate, ModelAdapter as RuntimeModelAdapter, ModelAdapterContext as RuntimeModelContext, ExecutionInput as RuntimeInput, InputEvent as RuntimeInputEvent, RunResult as RuntimeCompletion, ExecutionEvent as RuntimeEvent, } from "@nylorun/harness";
3
+ export type RuntimeAgent = import("@nylorun/harness").BuiltAgent<any, any>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import { start } from "./launcher.js";
2
+ await start(process.argv[2] ?? "src/index.ts", true);
package/dist/dev.js CHANGED
@@ -69,7 +69,12 @@ export async function develop(args) {
69
69
  }));
70
70
  };
71
71
  try {
72
- launch([tsx, "watch", "src/index.ts"]);
72
+ launch([
73
+ tsx,
74
+ "watch",
75
+ fileURLToPath(new URL("./dev-entry.js", import.meta.url)),
76
+ "src/index.ts",
77
+ ]);
73
78
  if (!args.includes("--no-studio")) {
74
79
  const url = `http://127.0.0.1:${port}/agents/v1/agents`;
75
80
  const deadline = Date.now() + 20_000;
@@ -0,0 +1,2 @@
1
+ export declare function loadProjectEnvironment(root?: string): void;
2
+ export declare function saveEnvironment(root: string, updates: Record<string, string | undefined>, signal?: AbortSignal): Promise<void>;
@@ -0,0 +1,64 @@
1
+ import { readFileSync, statSync } from "node:fs";
2
+ import { writeFile, rename, rm } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { randomUUID } from "node:crypto";
5
+ import { loadEnvFile } from "node:process";
6
+ export function loadProjectEnvironment(root = process.cwd()) {
7
+ const file = join(root, ".env");
8
+ try {
9
+ if (statSync(file).isDirectory())
10
+ throw new Error("The .env directory must be migrated manually: back it up, create a .env file with MODEL_PROVIDER, MODEL and MODEL_PROVIDER_API_KEY, and move OAuth credentials to .nylorun/auth.json. See the Runtime migration guide.");
11
+ }
12
+ catch (error) {
13
+ if (error.code === "ENOENT")
14
+ return;
15
+ throw error;
16
+ }
17
+ loadEnvFile(file);
18
+ }
19
+ // Match complete dotenv assignments, including quoted multiline values.
20
+ const assignment = /^(?:export\s+)?([\w]+)[\t ]*=[\t ]*(?:"[^"]*"|'[^']*'|`[^`]*`|[^#\r\n]*)([^\r\n]*)(?:\r?\n|$)/gm;
21
+ export async function saveEnvironment(root, updates, signal) {
22
+ const file = join(root, ".env");
23
+ let contents = "";
24
+ try {
25
+ contents = readFileSync(file, "utf8");
26
+ }
27
+ catch (error) {
28
+ if (error.code !== "ENOENT")
29
+ throw error;
30
+ }
31
+ const encode = (value) => {
32
+ // Node's dotenv parser has no general quote-escaping syntax. Select a
33
+ // delimiter absent from the value rather than changing the credential.
34
+ for (const quote of ["'", '"', "`"]) {
35
+ if (!value.includes(quote) && !(quote === '"' && /\\[nr]/.test(value)))
36
+ return quote + value + quote;
37
+ }
38
+ throw new Error("This value contains all dotenv quote delimiters; set it through your process environment instead.");
39
+ };
40
+ const remaining = new Set(Object.keys(updates));
41
+ contents = contents.replace(assignment, (whole, key, suffix) => {
42
+ if (!(key in updates))
43
+ return whole;
44
+ if (!remaining.delete(key))
45
+ return "";
46
+ return updates[key] === undefined
47
+ ? ""
48
+ : `${key}=${encode(updates[key])}${suffix}\n`;
49
+ });
50
+ if (contents && !contents.endsWith("\n"))
51
+ contents += "\n";
52
+ for (const key of remaining)
53
+ if (updates[key] !== undefined)
54
+ contents += `${key}=${encode(updates[key])}\n`;
55
+ const temporary = join(root, `.env-${randomUUID()}.tmp`);
56
+ try {
57
+ await writeFile(temporary, contents, { mode: 0o600, signal });
58
+ signal?.throwIfAborted();
59
+ await rename(temporary, file);
60
+ }
61
+ finally {
62
+ await rm(temporary, { force: true });
63
+ }
64
+ }
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  export type { RuntimeConfig } from "./config.js";
2
2
  export type * from "./contracts.js";
3
3
  export { Runtime, serveAgents, type AgentRouterOptions, type RuntimeActor, type ServeAgentsOptions, } from "./server/host.js";
4
- export { localJsonl, memoryHistory, JsonlJournal } from "./adapters/journal.js";
5
- export type { RuntimeDurability, CanonicalEvent, SessionSummary, } from "./adapters/journal.js";
6
- export { jsonlObserver } from "./adapters/observe.js";
7
- export { localMedia, MediaStore, IMAGE_MEDIA_TYPES, MAX_IMAGE_BYTES, decodeImageBase64, validateImageBytes, } from "./adapters/media.js";
8
- export type { RuntimeMedia, MediaAsset, MediaReference, } from "./adapters/media.js";
9
- export { piModel } from "./model/pi-model.js";
10
- export type { PiModelOptions } from "./model/pi-model.js";
11
- export { projectAsset } from "./assets.js";
4
+ export { SessionHost, type SubmitOptions } from "./sessions/host.js";
5
+ export { memorySessions } from "./sessions/store.js";
6
+ export type { SessionStore, ManagedSessionStore, StoredSession, SessionSummary, CanonicalEvent, } from "./sessions/store.js";
7
+ export { IMAGE_MEDIA_TYPES, MAX_IMAGE_BYTES, decodeImageBase64, validateImageBytes, } from "./media.js";
8
+ export type { RuntimeMedia, MediaAsset, MediaReference } from "./media.js";
9
+ export { httpModel, type HttpModelOptions, type ModelEnvironment, } from "./model/http-model.js";
10
+ export { agUiEvents } from "./server/ag-ui.js";
11
+ export type { ModelFactoryOptions, ModelPreview } from "./model/defaults.js";
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export { Runtime, serveAgents, } from "./server/host.js";
2
- export { localJsonl, memoryHistory, JsonlJournal } from "./adapters/journal.js";
3
- export { jsonlObserver } from "./adapters/observe.js";
4
- export { localMedia, MediaStore, IMAGE_MEDIA_TYPES, MAX_IMAGE_BYTES, decodeImageBase64, validateImageBytes, } from "./adapters/media.js";
5
- export { piModel } from "./model/pi-model.js";
6
- export { projectAsset } from "./assets.js";
2
+ export { SessionHost } from "./sessions/host.js";
3
+ export { memorySessions } from "./sessions/store.js";
4
+ export { IMAGE_MEDIA_TYPES, MAX_IMAGE_BYTES, decodeImageBase64, validateImageBytes, } from "./media.js";
5
+ export { httpModel, } from "./model/http-model.js";
6
+ export { agUiEvents } from "./server/ag-ui.js";
@@ -0,0 +1 @@
1
+ export declare function start(entry?: string, development?: boolean): Promise<void>;