ai-runtime-engine 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +78 -0
- package/LICENSE +15 -0
- package/README.md +489 -0
- package/dist/artifacts/artifacts.d.ts +28 -0
- package/dist/artifacts/artifacts.js +46 -0
- package/dist/benchmark/benchmark.d.ts +23 -0
- package/dist/benchmark/benchmark.js +40 -0
- package/dist/cli/cli.d.ts +6 -0
- package/dist/cli/cli.js +161 -0
- package/dist/cli/commands/cleanup.d.ts +47 -0
- package/dist/cli/commands/cleanup.js +96 -0
- package/dist/cli/commands/config.d.ts +8 -0
- package/dist/cli/commands/config.js +28 -0
- package/dist/cli/commands/doctor.d.ts +57 -0
- package/dist/cli/commands/doctor.js +86 -0
- package/dist/cli/commands/executions.d.ts +9 -0
- package/dist/cli/commands/executions.js +25 -0
- package/dist/cli/commands/info.d.ts +43 -0
- package/dist/cli/commands/info.js +53 -0
- package/dist/cli/commands/init.d.ts +5 -0
- package/dist/cli/commands/init.js +75 -0
- package/dist/cli/commands/inspect.d.ts +16 -0
- package/dist/cli/commands/inspect.js +60 -0
- package/dist/cli/commands/phase2.d.ts +22 -0
- package/dist/cli/commands/phase2.js +83 -0
- package/dist/cli/commands/route.d.ts +14 -0
- package/dist/cli/commands/route.js +49 -0
- package/dist/cli/commands/run.d.ts +11 -0
- package/dist/cli/commands/run.js +37 -0
- package/dist/cli/commands/setup.d.ts +34 -0
- package/dist/cli/commands/setup.js +104 -0
- package/dist/cli/commands/skills.d.ts +28 -0
- package/dist/cli/commands/skills.js +48 -0
- package/dist/cli/commands/test.d.ts +7 -0
- package/dist/cli/commands/test.js +29 -0
- package/dist/cli/context.d.ts +12 -0
- package/dist/cli/context.js +16 -0
- package/dist/cli/interactive/repl.d.ts +6 -0
- package/dist/cli/interactive/repl.js +45 -0
- package/dist/cli/interactive/session.d.ts +36 -0
- package/dist/cli/interactive/session.js +356 -0
- package/dist/cli/prompt.d.ts +6 -0
- package/dist/cli/prompt.js +18 -0
- package/dist/cli/render.d.ts +7 -0
- package/dist/cli/render.js +14 -0
- package/dist/comparison/analysis.d.ts +46 -0
- package/dist/comparison/analysis.js +177 -0
- package/dist/comparison/comparator.d.ts +46 -0
- package/dist/comparison/comparator.js +270 -0
- package/dist/comparison/comparison.d.ts +140 -0
- package/dist/comparison/comparison.js +9 -0
- package/dist/comparison/render.d.ts +7 -0
- package/dist/comparison/render.js +66 -0
- package/dist/config/defaults.d.ts +52 -0
- package/dist/config/defaults.js +56 -0
- package/dist/config/load.d.ts +17 -0
- package/dist/config/load.js +50 -0
- package/dist/config/providerDefaults.d.ts +17 -0
- package/dist/config/providerDefaults.js +61 -0
- package/dist/config/schema.d.ts +9 -0
- package/dist/config/schema.js +78 -0
- package/dist/context/budget.d.ts +13 -0
- package/dist/context/budget.js +17 -0
- package/dist/context/compiler.d.ts +61 -0
- package/dist/context/compiler.js +125 -0
- package/dist/context/tokens.d.ts +19 -0
- package/dist/context/tokens.js +38 -0
- package/dist/conversations/conversations.d.ts +38 -0
- package/dist/conversations/conversations.js +64 -0
- package/dist/core/capabilities/evidence.d.ts +40 -0
- package/dist/core/capabilities/evidence.js +102 -0
- package/dist/core/capabilities/overlay.d.ts +15 -0
- package/dist/core/capabilities/overlay.js +0 -0
- package/dist/core/capabilities/taxonomy.d.ts +19 -0
- package/dist/core/capabilities/taxonomy.js +25 -0
- package/dist/core/fallback/errors.d.ts +30 -0
- package/dist/core/fallback/errors.js +80 -0
- package/dist/core/fallback/fallback.d.ts +40 -0
- package/dist/core/fallback/fallback.js +82 -0
- package/dist/core/fallback/retryPolicy.d.ts +11 -0
- package/dist/core/fallback/retryPolicy.js +14 -0
- package/dist/core/health/health.d.ts +3 -0
- package/dist/core/health/health.js +5 -0
- package/dist/core/health/monitor.d.ts +23 -0
- package/dist/core/health/monitor.js +82 -0
- package/dist/core/policies/budget.d.ts +19 -0
- package/dist/core/policies/budget.js +37 -0
- package/dist/core/registry/builtinTasks.d.ts +8 -0
- package/dist/core/registry/builtinTasks.js +54 -0
- package/dist/core/registry/registry.d.ts +18 -0
- package/dist/core/registry/registry.js +33 -0
- package/dist/core/registry/taskRegistry.d.ts +15 -0
- package/dist/core/registry/taskRegistry.js +30 -0
- package/dist/core/router/confidence.d.ts +7 -0
- package/dist/core/router/confidence.js +20 -0
- package/dist/core/router/dimensions.d.ts +16 -0
- package/dist/core/router/dimensions.js +60 -0
- package/dist/core/router/executor.d.ts +16 -0
- package/dist/core/router/executor.js +25 -0
- package/dist/core/router/filter.d.ts +34 -0
- package/dist/core/router/filter.js +113 -0
- package/dist/core/router/normalize.d.ts +30 -0
- package/dist/core/router/normalize.js +119 -0
- package/dist/core/router/request.d.ts +4 -0
- package/dist/core/router/request.js +21 -0
- package/dist/core/router/router.d.ts +32 -0
- package/dist/core/router/router.js +195 -0
- package/dist/core/router/routingPrefs.d.ts +11 -0
- package/dist/core/router/routingPrefs.js +30 -0
- package/dist/core/router/scorer.d.ts +19 -0
- package/dist/core/router/scorer.js +50 -0
- package/dist/core/router/weights.d.ts +9 -0
- package/dist/core/router/weights.js +31 -0
- package/dist/core/validation/validator.d.ts +16 -0
- package/dist/core/validation/validator.js +33 -0
- package/dist/discovery/modelCatalog.d.ts +28 -0
- package/dist/discovery/modelCatalog.js +105 -0
- package/dist/discovery/openapi.d.ts +25 -0
- package/dist/discovery/openapi.js +76 -0
- package/dist/executions/checkpoint.d.ts +26 -0
- package/dist/executions/checkpoint.js +114 -0
- package/dist/executions/execution.d.ts +51 -0
- package/dist/executions/execution.js +8 -0
- package/dist/executions/store.d.ts +52 -0
- package/dist/executions/store.js +124 -0
- package/dist/generation/generateAdapter.d.ts +17 -0
- package/dist/generation/generateAdapter.js +30 -0
- package/dist/index.d.ts +147 -0
- package/dist/index.js +107 -0
- package/dist/learning/feedback.d.ts +9 -0
- package/dist/learning/feedback.js +18 -0
- package/dist/learning/learningStore.d.ts +68 -0
- package/dist/learning/learningStore.js +138 -0
- package/dist/learning/performanceStore.d.ts +27 -0
- package/dist/learning/performanceStore.js +0 -0
- package/dist/marketplace/presets.d.ts +24 -0
- package/dist/marketplace/presets.js +52 -0
- package/dist/mcp/mcp.d.ts +31 -0
- package/dist/mcp/mcp.js +54 -0
- package/dist/memory/bm25.d.ts +16 -0
- package/dist/memory/bm25.js +56 -0
- package/dist/memory/classifier.d.ts +14 -0
- package/dist/memory/classifier.js +17 -0
- package/dist/memory/memory.d.ts +80 -0
- package/dist/memory/memory.js +191 -0
- package/dist/orchestration/executor.d.ts +35 -0
- package/dist/orchestration/executor.js +65 -0
- package/dist/orchestration/orchestrator.d.ts +42 -0
- package/dist/orchestration/orchestrator.js +63 -0
- package/dist/orchestration/plan.d.ts +37 -0
- package/dist/orchestration/plan.js +70 -0
- package/dist/orchestration/planner.d.ts +29 -0
- package/dist/orchestration/planner.js +69 -0
- package/dist/plugin/ai.d.ts +82 -0
- package/dist/plugin/ai.js +167 -0
- package/dist/probing/probe.d.ts +25 -0
- package/dist/probing/probe.js +63 -0
- package/dist/providers/factory.d.ts +18 -0
- package/dist/providers/factory.js +54 -0
- package/dist/providers/httpClient.d.ts +34 -0
- package/dist/providers/httpClient.js +80 -0
- package/dist/providers/httpProvider.d.ts +49 -0
- package/dist/providers/httpProvider.js +135 -0
- package/dist/providers/mock/demo.d.ts +13 -0
- package/dist/providers/mock/demo.js +58 -0
- package/dist/providers/mock/mockProvider.d.ts +35 -0
- package/dist/providers/mock/mockProvider.js +121 -0
- package/dist/providers/mock/scenarios.d.ts +44 -0
- package/dist/providers/mock/scenarios.js +30 -0
- package/dist/providers/provider.d.ts +26 -0
- package/dist/providers/provider.js +11 -0
- package/dist/providers/wire/anthropicWire.d.ts +6 -0
- package/dist/providers/wire/anthropicWire.js +83 -0
- package/dist/providers/wire/openaiWire.d.ts +7 -0
- package/dist/providers/wire/openaiWire.js +81 -0
- package/dist/providers/wire/registry.d.ts +8 -0
- package/dist/providers/wire/registry.js +20 -0
- package/dist/providers/wire/types.d.ts +39 -0
- package/dist/providers/wire/types.js +24 -0
- package/dist/runtime/config.d.ts +31 -0
- package/dist/runtime/config.js +121 -0
- package/dist/runtime/context.d.ts +34 -0
- package/dist/runtime/context.js +11 -0
- package/dist/runtime/events.d.ts +99 -0
- package/dist/runtime/events.js +82 -0
- package/dist/runtime/host.d.ts +27 -0
- package/dist/runtime/host.js +7 -0
- package/dist/runtime/intent/classifier.d.ts +30 -0
- package/dist/runtime/intent/classifier.js +60 -0
- package/dist/runtime/intent/signals.d.ts +19 -0
- package/dist/runtime/intent/signals.js +46 -0
- package/dist/runtime/modes/availability.d.ts +11 -0
- package/dist/runtime/modes/availability.js +17 -0
- package/dist/runtime/modes/chat.d.ts +18 -0
- package/dist/runtime/modes/chat.js +67 -0
- package/dist/runtime/modes/modeResolver.d.ts +43 -0
- package/dist/runtime/modes/modeResolver.js +78 -0
- package/dist/runtime/policy.d.ts +72 -0
- package/dist/runtime/policy.js +59 -0
- package/dist/runtime/providerView.d.ts +62 -0
- package/dist/runtime/providerView.js +105 -0
- package/dist/runtime/routing.d.ts +26 -0
- package/dist/runtime/routing.js +65 -0
- package/dist/runtime/runtime.d.ts +191 -0
- package/dist/runtime/runtime.js +718 -0
- package/dist/runtime/types.d.ts +153 -0
- package/dist/runtime/types.js +9 -0
- package/dist/runtime/workspace/detectors.d.ts +15 -0
- package/dist/runtime/workspace/detectors.js +57 -0
- package/dist/runtime/workspace/workspace.d.ts +29 -0
- package/dist/runtime/workspace/workspace.js +116 -0
- package/dist/security/credentials.d.ts +26 -0
- package/dist/security/credentials.js +34 -0
- package/dist/security/redact.d.ts +16 -0
- package/dist/security/redact.js +57 -0
- package/dist/skills/builtins/fileAnalyzer.d.ts +7 -0
- package/dist/skills/builtins/fileAnalyzer.js +47 -0
- package/dist/skills/builtins/repositoryAnalyzer.d.ts +6 -0
- package/dist/skills/builtins/repositoryAnalyzer.js +47 -0
- package/dist/skills/discovery.d.ts +61 -0
- package/dist/skills/discovery.js +211 -0
- package/dist/skills/manifest.d.ts +30 -0
- package/dist/skills/manifest.js +75 -0
- package/dist/skills/registry.d.ts +15 -0
- package/dist/skills/registry.js +22 -0
- package/dist/skills/skill.d.ts +64 -0
- package/dist/skills/skill.js +8 -0
- package/dist/store/area.d.ts +54 -0
- package/dist/store/area.js +164 -0
- package/dist/store/paths.d.ts +15 -0
- package/dist/store/paths.js +48 -0
- package/dist/store/store.d.ts +59 -0
- package/dist/store/store.js +140 -0
- package/dist/telemetry/sinks/file.d.ts +12 -0
- package/dist/telemetry/sinks/file.js +28 -0
- package/dist/telemetry/telemetry.d.ts +36 -0
- package/dist/telemetry/telemetry.js +63 -0
- package/dist/tools/builtins/filesystem.d.ts +7 -0
- package/dist/tools/builtins/filesystem.js +53 -0
- package/dist/tools/builtins/git.d.ts +10 -0
- package/dist/tools/builtins/git.js +66 -0
- package/dist/tools/builtins/shell.d.ts +17 -0
- package/dist/tools/builtins/shell.js +91 -0
- package/dist/tools/jail.d.ts +12 -0
- package/dist/tools/jail.js +98 -0
- package/dist/tools/permissions.d.ts +25 -0
- package/dist/tools/permissions.js +24 -0
- package/dist/tools/registry.d.ts +10 -0
- package/dist/tools/registry.js +20 -0
- package/dist/tools/runner.d.ts +23 -0
- package/dist/tools/runner.js +64 -0
- package/dist/tools/tool.d.ts +53 -0
- package/dist/tools/tool.js +24 -0
- package/dist/tools/untrusted.d.ts +13 -0
- package/dist/tools/untrusted.js +30 -0
- package/dist/types.d.ts +460 -0
- package/dist/types.js +12 -0
- package/dist/util/clock.d.ts +6 -0
- package/dist/util/clock.js +4 -0
- package/dist/util/extractJson.d.ts +8 -0
- package/dist/util/extractJson.js +54 -0
- package/dist/verification/verify.d.ts +26 -0
- package/dist/verification/verify.js +67 -0
- package/docs/GUIDE.md +358 -0
- package/docs/README.md +21 -0
- package/docs/architecture.md +78 -0
- package/docs/router.md +376 -0
- package/docs/security.md +55 -0
- package/package.json +67 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `ai-runtime` are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/), and the project adheres to [Semantic
|
|
5
|
+
Versioning](https://semver.org/). Development history and rationale live in
|
|
6
|
+
[docs/DECISIONS.md](docs/DECISIONS.md) and [docs/PROGRESS.md](docs/PROGRESS.md).
|
|
7
|
+
|
|
8
|
+
## [1.1.0] — 2026-08-29
|
|
9
|
+
|
|
10
|
+
Closes out the two items 1.0 deferred. Additive and backward compatible.
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **npm skill packs** — a skill pack is any npm package that exports `skills: Skill[]`. Name installed
|
|
15
|
+
packs under `skills.packages` in config and the Runtime loads them from `node_modules` as trusted
|
|
16
|
+
dependencies (not workspace-jailed, unlike local `.ai-runtime/skills/` files). Ships an example pack,
|
|
17
|
+
`packages/example-skills` (`ai-runtime-example-skills`), and turns the repo into an npm workspace.
|
|
18
|
+
- **Windows CI** — GitHub Actions now runs the typecheck/test/build matrix on `windows-latest` as well as
|
|
19
|
+
`ubuntu-latest` (`fail-fast: false`). Symlink-specific tests skip cleanly where symlink creation needs
|
|
20
|
+
elevation; a multi-hop symlink-chain jail test was added.
|
|
21
|
+
|
|
22
|
+
## [1.0.0] — 2026-08-29
|
|
23
|
+
|
|
24
|
+
First stable release. `ai-runtime` grew from a provider-agnostic AI **router** into a full **AI Runtime &
|
|
25
|
+
Orchestration Platform** — the `Runtime` facade sits on top of the unchanged router (every model call
|
|
26
|
+
still goes through `AI.run()`). The router's public API (`AI`, `AI.run()`, config, providers, tasks, CLI
|
|
27
|
+
commands) is preserved and backward compatible.
|
|
28
|
+
|
|
29
|
+
### Added — the Runtime
|
|
30
|
+
|
|
31
|
+
- **Modes** — `auto | chat | plan | execute | orchestrate | agent | compare | debug`, with
|
|
32
|
+
per-run > config > env > detection precedence; a mode is never overridden, and unavailable modes
|
|
33
|
+
degrade to chat with a notice.
|
|
34
|
+
- **Interactive terminal** — bare `ai-runtime` opens a REPL (natural language + slash commands); a
|
|
35
|
+
one-shot `run` for CI. Typed lifecycle events + a host contract.
|
|
36
|
+
- **Conversations & memory** — verbatim conversation history (recoverable, secret-scrubbed), and durable
|
|
37
|
+
scoped memory with local BM25 retrieval, conflict supersession, and cascading deletion. Stateless mode
|
|
38
|
+
for CI/ephemeral use; monorepo-isolated local state under `~/.ai-runtime/`.
|
|
39
|
+
- **Context compiler & token budgets** — budget-aware context assembly with retention levels, redundancy
|
|
40
|
+
removal, artifact references, and loss validation.
|
|
41
|
+
- **Tools, permissions & skills** — deny-by-default permissions, a workspace path jail, allowlist-first
|
|
42
|
+
shell, git gating, and an untrusted-data boundary; versioned skills that validate by evidence.
|
|
43
|
+
- **Planning & orchestration** — structured plans limited to registered skills/tools, an evidence-based
|
|
44
|
+
DAG executor, a replanning orchestrator, plan approval, and dry-run (zero mutations).
|
|
45
|
+
- **Persistent executions & resume** — executions persisted before they start, a best-effort ownership
|
|
46
|
+
lease with heartbeat, checkpoints, `requestId` idempotency, and drift-aware resume/reconciliation.
|
|
47
|
+
- **Comparison** — fan a task across models; agreement / differences / contradictions / missing info with
|
|
48
|
+
**evidence-first** ranking (a supplied validator beats a judge model).
|
|
49
|
+
- **Exclude / prefer routing** — a hard exclude filter (visible in the trace) and a soft prefer nudge,
|
|
50
|
+
resolved from env + config + per-run.
|
|
51
|
+
- **Learning & feedback** — provider/skill/workflow/plan outcome learning and `/feedback`, feeding only
|
|
52
|
+
soft provider preferences; a safety test proves learning can never override a hard gate.
|
|
53
|
+
- **Local skill discovery** — auto-load manifests and module skills from `.ai-runtime/skills/`, discover
|
|
54
|
+
more across the workspace (report-only), all path-jailed.
|
|
55
|
+
- **Bootstrap & maintenance** — `setup` (ask-before-mutation), `info`, an extended `doctor --json`, and
|
|
56
|
+
`cleanup` (opt-in retention + cache + integrity).
|
|
57
|
+
|
|
58
|
+
### Security
|
|
59
|
+
|
|
60
|
+
- Untrusted-data boundary; workspace path jail (tested against `..`, absolute paths, and symlinks);
|
|
61
|
+
allowlist-first shell with a destructive denylist; secrets named by env var only and redacted at every
|
|
62
|
+
egress. Every phase shipped an adversarial security review; the confirmed findings — including path-jail
|
|
63
|
+
escapes and resume/lease concurrency issues — were fixed and regression-tested.
|
|
64
|
+
|
|
65
|
+
### Engineering
|
|
66
|
+
|
|
67
|
+
- TypeScript, ESM, Node ≥ 22; offline-deterministic test suite; typecheck + full suite + build green at
|
|
68
|
+
every phase gate. GitHub Actions CI runs typecheck, tests, and build on every push and PR.
|
|
69
|
+
|
|
70
|
+
## [0.1.0] — 2026-08-26
|
|
71
|
+
|
|
72
|
+
Initial release: the provider-agnostic AI **router** — capability-based routing, filtering, seven-dimension
|
|
73
|
+
scoring, evidence validation, fallback, health tracking, learning-based scoring, multi-model verification,
|
|
74
|
+
budgets, MCP tools, OpenAPI-based adapter generation, and the `AI` class + CLI.
|
|
75
|
+
|
|
76
|
+
[1.1.0]: https://github.com/pavankhandelwal21/ai-runtime/releases/tag/v1.1.0
|
|
77
|
+
[1.0.0]: https://github.com/pavankhandelwal21/ai-runtime/releases/tag/v1.0.0
|
|
78
|
+
[0.1.0]: https://github.com/pavankhandelwal21/ai-runtime/releases/tag/v0.1.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 pavan
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
# ai-runtime
|
|
2
|
+
|
|
3
|
+
**A provider-agnostic AI runtime for building and running AI features — without locking yourself to one vendor.**
|
|
4
|
+
|
|
5
|
+
You point it at whatever AI providers you have (cloud APIs, a local model, or an internal endpoint). It
|
|
6
|
+
routes each request to the best available model, and gives you a whole runtime on top of that: modes,
|
|
7
|
+
an interactive terminal, memory, skills, tools, planning, orchestration, comparison, and learning.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { Runtime } from 'ai-runtime-engine';
|
|
11
|
+
|
|
12
|
+
const runtime = await Runtime.load(); // reads your config + .env
|
|
13
|
+
const result = await runtime.run({ input: 'Fix the failing tests' });
|
|
14
|
+
console.log(result.response?.text);
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
> **The idea:** providers are replaceable; capabilities are durable. You never have to know *which*
|
|
18
|
+
> provider handled a request — you describe what you want, and the runtime picks the right model and runs it.
|
|
19
|
+
|
|
20
|
+
> 📘 **New here?** Start with the **[hands-on Guide](docs/GUIDE.md)** — install to first run, with runnable
|
|
21
|
+
> examples you can try offline (no API key needed).
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Contents
|
|
26
|
+
|
|
27
|
+
- [What it is](#what-it-is)
|
|
28
|
+
- [Requirements](#requirements)
|
|
29
|
+
- [Install](#install)
|
|
30
|
+
- [Quick start](#quick-start)
|
|
31
|
+
- [How it works](#how-it-works)
|
|
32
|
+
- [How to use it](#how-to-use-it) — modes, terminal, memory, skills, orchestration, comparison, learning
|
|
33
|
+
- [Configuration](#configuration)
|
|
34
|
+
- [What you need to do](#what-you-need-to-do) — a getting-started checklist
|
|
35
|
+
- [CLI commands](#cli-commands)
|
|
36
|
+
- [Package & distribution](#package--distribution)
|
|
37
|
+
- [Security & privacy](#security--privacy)
|
|
38
|
+
- [Troubleshooting](#troubleshooting)
|
|
39
|
+
- [Further reading](#further-reading)
|
|
40
|
+
- [Development](#development)
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## What it is
|
|
45
|
+
|
|
46
|
+
Hardcoding one AI provider means vendor lock-in, availability risk, and painful migrations — and different
|
|
47
|
+
providers are better at different things (reasoning, speed, cost, privacy), while any of them can be
|
|
48
|
+
rate-limited, out of quota, or down.
|
|
49
|
+
|
|
50
|
+
`ai-runtime` separates **provider support** from **provider availability**. Configure whatever you have
|
|
51
|
+
once; then, on every request, the runtime:
|
|
52
|
+
|
|
53
|
+
1. figures out **what kind of work** it is (a quick answer, a plan, a multi-step task, a comparison…),
|
|
54
|
+
2. **routes** it to the best model you have that can actually do it (by capability, health, privacy, cost),
|
|
55
|
+
3. **executes** through one normalized interface and **validates** the result,
|
|
56
|
+
4. **falls back** to the next-best model if something fails, and
|
|
57
|
+
5. returns a clean result with a full trace of how it decided.
|
|
58
|
+
|
|
59
|
+
Around that router sits the **Runtime**: an interactive terminal, conversation history, durable memory,
|
|
60
|
+
context building, a skill/tool system with permissions, planning and orchestration, resumable long-running
|
|
61
|
+
tasks, model comparison, and learning from outcomes. Everything runs over native `fetch` — **no provider
|
|
62
|
+
SDKs**.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Requirements
|
|
67
|
+
|
|
68
|
+
- **Node.js 22 or newer.**
|
|
69
|
+
- Git is optional (used to detect your workspace).
|
|
70
|
+
- At least one AI provider — a cloud API key, or a local model via [Ollama](https://ollama.com) (no key needed).
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Install
|
|
75
|
+
|
|
76
|
+
The npm package is **`ai-runtime-engine`**. Installing it gives you both a **library** and the
|
|
77
|
+
**`ai-runtime`** command-line tool (the command name is `ai-runtime` — a package name need not match its
|
|
78
|
+
command name).
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# in your project (library + local CLI via `npx ai-runtime`)
|
|
82
|
+
npm install ai-runtime-engine
|
|
83
|
+
|
|
84
|
+
# or install globally to get the `ai-runtime` command on your PATH
|
|
85
|
+
npm install -g ai-runtime-engine
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Requires Node 22+. Use it as a library:
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
import { Runtime, AI } from 'ai-runtime-engine';
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
> **Naming:** the **product** is *AI Runtime*, the **npm package** is `ai-runtime-engine`, and the **CLI
|
|
95
|
+
> command** is `ai-runtime`. The main API is `Runtime`; the lower-level router is `AI`.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Quick start
|
|
100
|
+
|
|
101
|
+
### Option A — the terminal (fastest)
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npm install -g ai-runtime-engine # (or use `npx ai-runtime …` from a project that installed it)
|
|
105
|
+
|
|
106
|
+
ai-runtime setup # detects your workspace, generates config + .env.example (asks before each write)
|
|
107
|
+
# → add a provider key to .env, OR install Ollama for a local, no-key model
|
|
108
|
+
ai-runtime doctor # check that a provider is configured and reachable
|
|
109
|
+
ai-runtime # open the interactive terminal — just type what you want
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Option B — in code
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
import { Runtime } from 'ai-runtime-engine';
|
|
116
|
+
|
|
117
|
+
const runtime = await Runtime.load({ workspace: process.cwd() });
|
|
118
|
+
const r = await runtime.run({ input: 'Summarize what this repo does' });
|
|
119
|
+
console.log(r.response?.text);
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Try it with no keys (offline)
|
|
123
|
+
|
|
124
|
+
Use the built-in mock provider to see everything work without any credentials — great for tests and demos:
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
import { Runtime, MockProvider, makeModel } from 'ai-runtime-engine';
|
|
128
|
+
|
|
129
|
+
const runtime = new Runtime();
|
|
130
|
+
runtime.ai.registerProvider(new MockProvider({
|
|
131
|
+
id: 'demo',
|
|
132
|
+
models: [makeModel({ providerId: 'demo', id: 'demo-1', caps: { intelligence: ['reasoning'], output: ['text'] } })],
|
|
133
|
+
}));
|
|
134
|
+
const r = await runtime.run({ input: 'hello' });
|
|
135
|
+
console.log(r.response?.text, r.routing?.selected); // includes the full routing decision
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## How it works
|
|
141
|
+
|
|
142
|
+
A request goes through one vendor-agnostic path. You provide the capabilities (providers, tools, skills,
|
|
143
|
+
a workspace); the runtime decides *how* to use them.
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
runtime.run({ input })
|
|
147
|
+
│
|
|
148
|
+
▼ resolve MODE (auto-detected, or set by you): chat · plan · execute · orchestrate · agent · compare · debug
|
|
149
|
+
│
|
|
150
|
+
▼ build the model context under a token budget (workspace summary, memory, your request)
|
|
151
|
+
│
|
|
152
|
+
▼ route to the best model ──► the ONE router: filter (capability/health/privacy/cost) → score → pick
|
|
153
|
+
│ → execute → validate → fall back on failure
|
|
154
|
+
│
|
|
155
|
+
▼ for multi-step work: plan → run tools/skills as a DAG (succeed a step only on evidence) → replan on failure
|
|
156
|
+
│
|
|
157
|
+
▼ result { ok, response, routing trace, + plan / execution / comparison / memory as relevant }
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Two principles hold everywhere:
|
|
161
|
+
|
|
162
|
+
- **One router.** Every model call — chat, planning, comparison, a skill's own call — goes through the same
|
|
163
|
+
router. There's never a second, hidden selection engine.
|
|
164
|
+
- **Evidence over claims.** A step "succeeds" only when there's proof (a tool returned ok, a validator
|
|
165
|
+
passed) — never because a model said "done."
|
|
166
|
+
|
|
167
|
+
For the engine's internals (scoring dimensions, strategies, provider contracts, the `AI` API), see
|
|
168
|
+
[docs/router.md](docs/router.md).
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## How to use it
|
|
173
|
+
|
|
174
|
+
Load the runtime once, then `run()` requests. It resolves a **mode** and dispatches.
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
const runtime = await Runtime.load({ workspace: process.cwd() });
|
|
178
|
+
runtime.ai.registerProvider(myProvider); // register providers the same way as the router
|
|
179
|
+
const r = await runtime.run({ input: 'Explain this stack trace: …' });
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Modes
|
|
183
|
+
|
|
184
|
+
Every run resolves to one of eight modes. **`auto`** (the default) detects intent; you can force any mode
|
|
185
|
+
per run (`{ mode: 'plan' }`), in config (`runtime.defaultMode`), or via `AI_DEFAULT_MODE`. Precedence:
|
|
186
|
+
per-run > config > env > detection — an explicit mode is never overridden.
|
|
187
|
+
|
|
188
|
+
| Mode | What it does |
|
|
189
|
+
|---|---|
|
|
190
|
+
| `chat` | A single conversational answer (memory- and workspace-aware). |
|
|
191
|
+
| `plan` | Produce a structured plan; execute nothing. |
|
|
192
|
+
| `execute` | Run a planned sequence once. |
|
|
193
|
+
| `orchestrate` | Plan → execute → observe → replan until done or a limit is hit. |
|
|
194
|
+
| `agent` | A longer autonomous loop with hard stops (iterations, budget, permissions). |
|
|
195
|
+
| `debug` | Evidence-first investigation (gather → hypotheses → validate → conclude). |
|
|
196
|
+
| `compare` | Fan the same task across models and analyze the results. |
|
|
197
|
+
|
|
198
|
+
Mode is *what kind of work*; **autonomy** is *how much independent action* — `chat`/`plan` need no approval,
|
|
199
|
+
`execute`/`orchestrate` ask before acting, `agent` runs autonomously within limits.
|
|
200
|
+
|
|
201
|
+
### Interactive terminal
|
|
202
|
+
|
|
203
|
+
Bare `ai-runtime` opens a REPL: type natural language, or use slash commands to inspect and steer —
|
|
204
|
+
`/mode`, `/status`, `/info`, `/providers`, `/models`, `/skills [discover]`, `/tools`, `/permissions`,
|
|
205
|
+
`/memory`, `/conversations`, `/resume`, `/executions`, `/compare`, `/feedback`, `/learning`, `/doctor`,
|
|
206
|
+
`/cleanup`, `/dry-run`. For CI, `ai-runtime run "<input>" [--mode m] [--dry-run]` is the one-shot equivalent.
|
|
207
|
+
|
|
208
|
+
### Conversations & memory
|
|
209
|
+
|
|
210
|
+
Conversations are saved verbatim (recoverable, with secrets scrubbed). Memory is durable, scoped facts —
|
|
211
|
+
say "remember that we use Postgres" and it's kept, retrieved when relevant, and superseded when it changes.
|
|
212
|
+
Turn persistence off entirely with `Runtime.load({ persistence: 'disabled' })` (for CI/ephemeral use).
|
|
213
|
+
|
|
214
|
+
### Skills & tools (and your own)
|
|
215
|
+
|
|
216
|
+
**Tools** are concrete operations — `filesystem`, `shell`, and `git` are built in; add your own. They're
|
|
217
|
+
**deny-by-default**: reads are allowed and jailed to your workspace, but writes, shell, git commit/push,
|
|
218
|
+
and network are off until you grant them in config.
|
|
219
|
+
|
|
220
|
+
**Skills** are reusable capabilities that compose tools. Beyond the built-ins, the runtime **loads your
|
|
221
|
+
own local skills**:
|
|
222
|
+
|
|
223
|
+
- Drop a manifest (`*.skill.yaml`) or a JS module (`*.skill.mjs`) into **`.ai-runtime/skills/`** — auto-loaded.
|
|
224
|
+
- `ai-runtime skills --discover` scans the rest of your repo and **reports** other skill files without
|
|
225
|
+
loading them (you enable one deliberately).
|
|
226
|
+
- Install a **skill pack** (any npm package that exports `skills`) and name it under `skills.packages`.
|
|
227
|
+
|
|
228
|
+
```yaml
|
|
229
|
+
# .ai-runtime/skills/read-changelog.skill.yaml — a declarative skill (composes tools, no code)
|
|
230
|
+
id: read-changelog
|
|
231
|
+
version: 1.0.0
|
|
232
|
+
name: Read changelog
|
|
233
|
+
description: read CHANGELOG.md
|
|
234
|
+
steps:
|
|
235
|
+
- tool: filesystem
|
|
236
|
+
input: { op: read, path: CHANGELOG.md }
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Planning, orchestration & dry-run
|
|
240
|
+
|
|
241
|
+
For multi-step work, the runtime plans (using only your registered skills/tools), runs the plan as a DAG,
|
|
242
|
+
succeeds a step only on evidence, and replans on failure. **Dry-run** (`run --dry-run`, `/dry-run`) shows
|
|
243
|
+
the plan and what it *would* touch — with zero changes made.
|
|
244
|
+
|
|
245
|
+
### Persistent executions & resume
|
|
246
|
+
|
|
247
|
+
Longer runs are saved before they start and can be resumed. Resume never blindly continues: it re-checks
|
|
248
|
+
your workspace (git state, touched files, config) and replans if anything drifted. `/executions`,
|
|
249
|
+
`/resume-execution <id>`, `/pause`, `/cancel`.
|
|
250
|
+
|
|
251
|
+
### Comparison
|
|
252
|
+
|
|
253
|
+
`compare` mode (or `runtime.compare(...)`) runs the same task across models and shows where they agree,
|
|
254
|
+
differ, and contradict each other. If you supply a way to *check* each answer (e.g. run the tests), the one
|
|
255
|
+
that passes wins — evidence beats opinion.
|
|
256
|
+
|
|
257
|
+
### Steering which models get used
|
|
258
|
+
|
|
259
|
+
- **Exclude = a hard filter.** An excluded provider/model is **never** selected (it still shows in the
|
|
260
|
+
routing trace as `⊘ excluded by user configuration`).
|
|
261
|
+
- **Prefer = a soft preference.** A preferred model is nudged up, but a preferred-but-incapable/unhealthy
|
|
262
|
+
one still loses.
|
|
263
|
+
- **Neither configured = normal routing** across all eligible models.
|
|
264
|
+
|
|
265
|
+
Set them in config `routing:`, per run (`runtime.run({ input, routing: {…} })`), or via environment
|
|
266
|
+
variables — they combine, so an exclusion set anywhere always holds:
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
AI_EXCLUDE_PROVIDERS=ollama
|
|
270
|
+
AI_EXCLUDE_MODELS=gemini:model-a,groq:model-b # provider:model, or a bare model id
|
|
271
|
+
AI_PREFER_PROVIDERS=gemini
|
|
272
|
+
AI_PREFER_MODELS=groq:model-c
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
**Learning** — the runtime learns which providers/skills work from real outcomes and your `/feedback`, and
|
|
276
|
+
turns that into *soft* preferences only. **Learning can never override an exclusion** (nor a privacy rule,
|
|
277
|
+
a pin, a required capability, or the budget) — a guarantee proven by a dedicated test.
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## Configuration
|
|
282
|
+
|
|
283
|
+
Three places, and only these:
|
|
284
|
+
|
|
285
|
+
| Path | What | In git? |
|
|
286
|
+
|---|---|---|
|
|
287
|
+
| `.ai-runtime/config.yaml` | Project config — runtime settings + providers (env-var **names** only). Falls back to root `ai-runtime.yaml`. | ✅ commit it |
|
|
288
|
+
| `.env` | The secret **values** for the env vars your config names. | ❌ gitignored |
|
|
289
|
+
| `~/.ai-runtime/` | Local state — conversations, memory, executions, cache, learning. Override with `AI_RUNTIME_HOME`. | ❌ never in git |
|
|
290
|
+
|
|
291
|
+
A minimal config:
|
|
292
|
+
|
|
293
|
+
```yaml
|
|
294
|
+
# .ai-runtime/config.yaml
|
|
295
|
+
runtime:
|
|
296
|
+
defaultMode: auto
|
|
297
|
+
providers:
|
|
298
|
+
- id: gemini
|
|
299
|
+
kind: gemini
|
|
300
|
+
apiKeyEnv: GEMINI_API_KEY # the NAME of the env var — never the value
|
|
301
|
+
- id: ollama # local, no key required
|
|
302
|
+
kind: ollama
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
**Provider API keys** go in `.env` — the config names the variable, the value lives here. Each provider
|
|
306
|
+
kind has a default variable name (override with `apiKeyEnv`): `GEMINI_API_KEY`, `GROQ_API_KEY`,
|
|
307
|
+
`ANTHROPIC_API_KEY`, `OPENROUTER_API_KEY` (Ollama needs none).
|
|
308
|
+
|
|
309
|
+
**Optional runtime variables** — all optional; unset means the built-in default:
|
|
310
|
+
|
|
311
|
+
| Variable | Effect |
|
|
312
|
+
|---|---|
|
|
313
|
+
| `AI_DEFAULT_MODE` | Default mode when a run doesn't set one (`auto` by default). |
|
|
314
|
+
| `AI_DEFAULT_STRATEGY` | Default routing strategy. |
|
|
315
|
+
| `AI_CONTEXT_MAX_TOKENS` | Token budget for the compiled model context. |
|
|
316
|
+
| `AI_MAX_COST_USD` · `AI_MAX_CALLS` | Per-run spend / call guardrails. |
|
|
317
|
+
| `AI_MEMORY_ENABLED` | Set `false` to disable memory. |
|
|
318
|
+
| `AI_LEARNING_ENABLED` | Set `false` to disable outcome learning. |
|
|
319
|
+
| `AI_EXCLUDE_PROVIDERS` · `AI_EXCLUDE_MODELS` | Hard-exclude providers / models (see [steering](#steering-which-models-get-used)). |
|
|
320
|
+
| `AI_PREFER_PROVIDERS` · `AI_PREFER_MODELS` | Soft-prefer providers / models. |
|
|
321
|
+
| `AI_CONVERSATION_RETENTION_DAYS` · `AI_EXECUTION_RETENTION_DAYS` · `AI_ARTIFACT_RETENTION_DAYS` | Retention for `cleanup` (unset = keep everything). |
|
|
322
|
+
| `AI_RUNTIME_HOME` | Override the `~/.ai-runtime/` state directory. |
|
|
323
|
+
| `AI_TELEMETRY_ENABLED` | *Reserved — not yet honored by the runtime.* Telemetry is metadata-only and set in config. |
|
|
324
|
+
|
|
325
|
+
`ai-runtime setup` writes the config and `.env.example` for you (asking first), and `ai-runtime info` shows
|
|
326
|
+
everything resolved. For the full router config (routing strategies, scoring weights, privacy posture,
|
|
327
|
+
telemetry, self-declared providers), see [docs/router.md](docs/router.md).
|
|
328
|
+
|
|
329
|
+
### Providers
|
|
330
|
+
|
|
331
|
+
If no provider is configured, `ai-runtime setup` and `ai-runtime doctor` walk you through adding one.
|
|
332
|
+
Recommended starters:
|
|
333
|
+
|
|
334
|
+
| Provider | Type | Key | Where to get it |
|
|
335
|
+
|---|---|---|---|
|
|
336
|
+
| **Google Gemini** | Cloud API | `GEMINI_API_KEY` | https://aistudio.google.com/apikey |
|
|
337
|
+
| **Groq** | Cloud API | `GROQ_API_KEY` | https://console.groq.com/keys |
|
|
338
|
+
| **OpenRouter** | Cloud API (aggregator) | `OPENROUTER_API_KEY` | https://openrouter.ai/keys |
|
|
339
|
+
| **Ollama** | Local (no key) | — | https://ollama.com |
|
|
340
|
+
|
|
341
|
+
Cloud providers need an API key; **Ollama** runs models locally with no key. Availability, models, and any
|
|
342
|
+
free/paid tiers are set by each provider — check their site for current terms.
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## What you need to do
|
|
347
|
+
|
|
348
|
+
A getting-started checklist:
|
|
349
|
+
|
|
350
|
+
1. **Install** — Node 22+, then `npm install -g ai-runtime-engine` (or add it to a project). Verify with
|
|
351
|
+
`ai-runtime --help`.
|
|
352
|
+
2. **Scaffold** — run `ai-runtime setup`. It creates `.ai-runtime/config.yaml`, `.env.example`, and
|
|
353
|
+
`.gitignore` entries (asking before each write).
|
|
354
|
+
3. **Add a provider** — either put a real key in `.env` (e.g. `GEMINI_API_KEY=…`), or install
|
|
355
|
+
[Ollama](https://ollama.com) for a local model with no key.
|
|
356
|
+
4. **Check it** — `ai-runtime doctor` confirms a provider is configured and reachable.
|
|
357
|
+
5. **Use it** — `ai-runtime` (terminal), `ai-runtime run "…"` (one-shot), or `Runtime.load().run(…)` (code).
|
|
358
|
+
6. **Go further (optional)** — add skills to `.ai-runtime/skills/`, grant write/shell permissions under
|
|
359
|
+
`permissions:` when you want the runtime to act, and set `routing:` to steer model selection.
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## CLI commands
|
|
364
|
+
|
|
365
|
+
The commands you'll use day to day:
|
|
366
|
+
|
|
367
|
+
| Command | What it does |
|
|
368
|
+
|---|---|
|
|
369
|
+
| `ai-runtime` | Open the interactive terminal. |
|
|
370
|
+
| `ai-runtime setup` | Detect the workspace and scaffold config (asks before writing). |
|
|
371
|
+
| `ai-runtime run "<input>" [--mode m] [--dry-run] [--json]` | Run one request (one-shot, for scripts/CI). |
|
|
372
|
+
| `ai-runtime info [--json]` | Read-only summary: workspace, providers, skills, tools, memory, storage. |
|
|
373
|
+
| `ai-runtime doctor [--json]` | Diagnose config, `.env` (by name), providers, models, store, permissions, git. |
|
|
374
|
+
| `ai-runtime skills [--discover]` | List available skills; `--discover` reports skill files elsewhere in the repo. |
|
|
375
|
+
| `ai-runtime cleanup [--dry-run] [--yes]` | Enforce retention, drop the cache, validate the store. |
|
|
376
|
+
| `ai-runtime executions` · `resume-execution <id>` | List and resume persisted executions. |
|
|
377
|
+
|
|
378
|
+
The engine also ships lower-level commands (`route`, `providers`, `models`, `capabilities`, `probe`,
|
|
379
|
+
`discover`, `benchmark`, `presets`, `telemetry`) — see [docs/router.md](docs/router.md). Run any command
|
|
380
|
+
with `--help` for its flags.
|
|
381
|
+
|
|
382
|
+
### Inside the interactive terminal
|
|
383
|
+
|
|
384
|
+
Type a request in plain language, or use a slash command to inspect and steer. The commands that exist
|
|
385
|
+
today:
|
|
386
|
+
|
|
387
|
+
```
|
|
388
|
+
/help show all commands
|
|
389
|
+
/status /info workspace, mode, provider count · full runtime summary
|
|
390
|
+
/mode [name] show or set the mode (auto|chat|plan|…)
|
|
391
|
+
/providers list providers + access state
|
|
392
|
+
/providers/all models list every provider's models
|
|
393
|
+
/providers/<id> [models|capabilities|health] inspect one provider
|
|
394
|
+
/providers/setup how to add a provider (keys / Ollama)
|
|
395
|
+
/models list all known models
|
|
396
|
+
/skills [discover] /tools /permissions
|
|
397
|
+
/memory [list|search <q>|delete <id>|clear]
|
|
398
|
+
/conversations /resume <id>
|
|
399
|
+
/executions /resume-execution <id> /pause <id> /cancel <id>
|
|
400
|
+
/compare <request> compare across all providers
|
|
401
|
+
/feedback <text> /learning record feedback · show what was learned
|
|
402
|
+
/dry-run toggle dry-run (plan only, no changes)
|
|
403
|
+
/doctor /cleanup /config diagnostics · retention preview · resolved config
|
|
404
|
+
/clear /exit
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
## Package & distribution
|
|
410
|
+
|
|
411
|
+
| | |
|
|
412
|
+
|---|---|
|
|
413
|
+
| **Product** | AI Runtime |
|
|
414
|
+
| **npm package** | `ai-runtime-engine` |
|
|
415
|
+
| **CLI command** | `ai-runtime` |
|
|
416
|
+
| **Source repository** | private |
|
|
417
|
+
| **Project config** | `.ai-runtime/config.yaml` (committed) |
|
|
418
|
+
| **Secrets** | `.env` (gitignored) |
|
|
419
|
+
| **Runtime state** | `~/.ai-runtime/` (never committed) |
|
|
420
|
+
|
|
421
|
+
The public npm package contains the **distributed runtime code** (compiled `dist/`), this README, and the
|
|
422
|
+
changelog. It **does not** contain any of your data — no API keys, `.env`, memory, conversations, execution
|
|
423
|
+
state, local indexes, cache, or other runtime state; those live only on your machine under `~/.ai-runtime/`
|
|
424
|
+
and `.env`, and are never part of the package.
|
|
425
|
+
|
|
426
|
+
The **source repository is private**; the npm package is public. Note that a public npm package still ships
|
|
427
|
+
runnable code — publishing to npm distributes the compiled implementation to anyone who installs it. It
|
|
428
|
+
does not hide the implementation from package consumers; keeping the *repository* private only keeps the
|
|
429
|
+
source history and development materials private.
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
## Security & privacy
|
|
434
|
+
|
|
435
|
+
- Everything the runtime reads through tools, files, the web, or MCP is treated as **data, never
|
|
436
|
+
instructions** — it can't change permissions, obtain secrets, run commands, or bypass approvals.
|
|
437
|
+
- Filesystem access is **jailed to your workspace** (tested against `..`, absolute paths, and symlinks).
|
|
438
|
+
Shell is allowlist-first with a destructive-command denylist; writes, commit/push, and network are
|
|
439
|
+
each gated and off by default.
|
|
440
|
+
- **Secrets are named by env var only** in config; an inline key is rejected at load, and every value is
|
|
441
|
+
redacted at every egress — including the terminal and logs.
|
|
442
|
+
- **Privacy:** high-sensitivity input is kept off cloud providers unless you explicitly allow it.
|
|
443
|
+
|
|
444
|
+
Full details in [docs/security.md](docs/security.md).
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
## Troubleshooting
|
|
449
|
+
|
|
450
|
+
- **"No compatible AI provider is available"** — run `ai-runtime doctor`: it shows which provider keys are
|
|
451
|
+
set (by name), which providers authenticated, and how many models are usable. Add a key to `.env`, or a
|
|
452
|
+
provider to config; with none, `ai-runtime setup` lists free/local options (Ollama needs no key).
|
|
453
|
+
- **A provider is never chosen** — check `doctor` for its health and `/providers` for its access state; a
|
|
454
|
+
provider you excluded shows as `⊘ excluded by user configuration` in the routing trace.
|
|
455
|
+
- **Writes or shell are refused** — that's deny-by-default; grant them under `permissions:` in config
|
|
456
|
+
(destructive shell always asks). Use `--dry-run` to preview what a run would touch.
|
|
457
|
+
- **A local skill isn't loading** — `ai-runtime skills --discover` shows what was found and any load errors;
|
|
458
|
+
module skills load only from `.ai-runtime/skills/` or a configured `skills.paths`.
|
|
459
|
+
- **Nothing persists** — you may be in stateless mode (`persistence: 'disabled'`) or have `AI_*_ENABLED`
|
|
460
|
+
toggles off; `ai-runtime info` shows storage status.
|
|
461
|
+
|
|
462
|
+
---
|
|
463
|
+
|
|
464
|
+
## Further reading
|
|
465
|
+
|
|
466
|
+
- **[docs/GUIDE.md](docs/GUIDE.md)** — a hands-on, study-friendly guide: install → first run → how it works
|
|
467
|
+
→ worked examples, runnable offline.
|
|
468
|
+
- **[docs/architecture.md](docs/architecture.md)** — how the two layers fit together, the one-router
|
|
469
|
+
invariant, and the lifecycle of a request.
|
|
470
|
+
- **[docs/router.md](docs/router.md)** — the router engine reference: config keys, strategies, scoring,
|
|
471
|
+
providers, the `AI` API, and advanced features.
|
|
472
|
+
- **[docs/security.md](docs/security.md)** — the full security model.
|
|
473
|
+
- **[CHANGELOG.md](CHANGELOG.md)** — version history.
|
|
474
|
+
|
|
475
|
+
---
|
|
476
|
+
|
|
477
|
+
## Development
|
|
478
|
+
|
|
479
|
+
TypeScript, ESM, Node ≥ 22. The test suite is fully offline and deterministic.
|
|
480
|
+
|
|
481
|
+
```bash
|
|
482
|
+
npm install
|
|
483
|
+
npm run typecheck # tsc --noEmit (strict)
|
|
484
|
+
npm test # node:test — offline, no keys, no network
|
|
485
|
+
npm run build # tsc → dist/ (ESM + .d.ts)
|
|
486
|
+
npm run cli -- info # run the CLI from source
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
CI (GitHub Actions) runs typecheck, tests, and build on Linux and Windows for every push and pull request.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Artifact store — the content owner behind ArtifactRef. Large outputs (traces, diffs, logs, reports)
|
|
3
|
+
* are written here once and passed around the runtime as compact references; the context compiler
|
|
4
|
+
* decides if/when to inline the content. Backed by a store Area (checksummed, atomic). No-op when the
|
|
5
|
+
* store is disabled (stateless mode).
|
|
6
|
+
*/
|
|
7
|
+
import type { Clock } from '../util/clock.js';
|
|
8
|
+
import type { Area } from '../store/area.js';
|
|
9
|
+
import type { ArtifactRef } from '../runtime/types.js';
|
|
10
|
+
export interface PutArtifactInput {
|
|
11
|
+
type: string;
|
|
12
|
+
source: string;
|
|
13
|
+
content: string;
|
|
14
|
+
metadata?: Record<string, unknown>;
|
|
15
|
+
}
|
|
16
|
+
export declare class ArtifactStore {
|
|
17
|
+
private readonly area;
|
|
18
|
+
private readonly clock;
|
|
19
|
+
private counter;
|
|
20
|
+
constructor(area: Area, clock?: Clock);
|
|
21
|
+
get enabled(): boolean;
|
|
22
|
+
/** Store content and return a reference. The content lives here; callers pass the ref around. */
|
|
23
|
+
put(input: PutArtifactInput): ArtifactRef;
|
|
24
|
+
/** Resolve a reference back to its content (undefined if missing/corrupt). */
|
|
25
|
+
resolve(ref: ArtifactRef): string | undefined;
|
|
26
|
+
list(): string[];
|
|
27
|
+
delete(id: string): void;
|
|
28
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Artifact store — the content owner behind ArtifactRef. Large outputs (traces, diffs, logs, reports)
|
|
3
|
+
* are written here once and passed around the runtime as compact references; the context compiler
|
|
4
|
+
* decides if/when to inline the content. Backed by a store Area (checksummed, atomic). No-op when the
|
|
5
|
+
* store is disabled (stateless mode).
|
|
6
|
+
*/
|
|
7
|
+
import { createHash } from 'node:crypto';
|
|
8
|
+
import { systemClock } from '../util/clock.js';
|
|
9
|
+
export class ArtifactStore {
|
|
10
|
+
area;
|
|
11
|
+
clock;
|
|
12
|
+
counter = 0;
|
|
13
|
+
constructor(area, clock = systemClock) {
|
|
14
|
+
this.area = area;
|
|
15
|
+
this.clock = clock;
|
|
16
|
+
}
|
|
17
|
+
get enabled() {
|
|
18
|
+
return this.area.enabled;
|
|
19
|
+
}
|
|
20
|
+
/** Store content and return a reference. The content lives here; callers pass the ref around. */
|
|
21
|
+
put(input) {
|
|
22
|
+
const id = `art_${this.clock.now().toString(36)}_${(this.counter += 1).toString(36)}`;
|
|
23
|
+
const checksum = createHash('sha256').update(input.content).digest('hex');
|
|
24
|
+
this.area.writeJson(id, { content: input.content, type: input.type, source: input.source, checksum, ...(input.metadata ? { metadata: input.metadata } : {}) });
|
|
25
|
+
return {
|
|
26
|
+
id,
|
|
27
|
+
type: input.type,
|
|
28
|
+
source: input.source,
|
|
29
|
+
contentRef: id,
|
|
30
|
+
checksum,
|
|
31
|
+
size: input.content.length,
|
|
32
|
+
...(input.metadata ? { metadata: input.metadata } : {}),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** Resolve a reference back to its content (undefined if missing/corrupt). */
|
|
36
|
+
resolve(ref) {
|
|
37
|
+
const rec = this.area.tryReadJson(ref.contentRef);
|
|
38
|
+
return rec?.content;
|
|
39
|
+
}
|
|
40
|
+
list() {
|
|
41
|
+
return this.area.listIds();
|
|
42
|
+
}
|
|
43
|
+
delete(id) {
|
|
44
|
+
this.area.remove(id);
|
|
45
|
+
}
|
|
46
|
+
}
|