@cleocode/runtime 2026.4.7 → 2026.4.10
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/README.md +185 -0
- package/package.json +3 -3
package/README.md
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# @cleocode/runtime
|
|
2
|
+
|
|
3
|
+
Long-running process layer for CLEO. Provides the daemon services that
|
|
4
|
+
let an agent stay resident on a host: message polling, SSE connection
|
|
5
|
+
management, heartbeat reporting, and credential key rotation.
|
|
6
|
+
|
|
7
|
+
This package powers `cleo agent start` — when an operator starts an
|
|
8
|
+
autonomous agent, this is the runtime that keeps it alive between
|
|
9
|
+
human interactions.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm add @cleocode/runtime
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Public API
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import {
|
|
21
|
+
createRuntime,
|
|
22
|
+
type RuntimeConfig,
|
|
23
|
+
type RuntimeHandle,
|
|
24
|
+
AgentPoller,
|
|
25
|
+
HeartbeatService,
|
|
26
|
+
KeyRotationService,
|
|
27
|
+
SseConnectionService,
|
|
28
|
+
} from '@cleocode/runtime';
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### `createRuntime(registry, config)`
|
|
32
|
+
|
|
33
|
+
Top-level entry point. Resolves an agent credential from the registry,
|
|
34
|
+
configures the poller and ancillary services, opens the transport, and
|
|
35
|
+
starts polling. Returns a `RuntimeHandle` for registering message
|
|
36
|
+
handlers and stopping the runtime cleanly.
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
import { createRuntime } from '@cleocode/runtime';
|
|
40
|
+
import { AgentRegistryAPI } from '@cleocode/core/internal';
|
|
41
|
+
|
|
42
|
+
const registry = new AgentRegistryAPI(/* ... */);
|
|
43
|
+
const handle = await createRuntime(registry, {
|
|
44
|
+
agentId: 'cleo-prime',
|
|
45
|
+
pollIntervalMs: 5000,
|
|
46
|
+
heartbeatIntervalMs: 30000,
|
|
47
|
+
groupConversationIds: ['general', 'announcements'],
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
handle.poller.onMessage(async (msg) => {
|
|
51
|
+
// handle inbound messages
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// later
|
|
55
|
+
handle.stop();
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### `RuntimeConfig`
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
interface RuntimeConfig {
|
|
62
|
+
agentId?: string; // defaults to most recently active agent
|
|
63
|
+
pollIntervalMs?: number; // default: 5000
|
|
64
|
+
groupConversationIds?: string[];
|
|
65
|
+
groupPollLimit?: number; // default: 15
|
|
66
|
+
heartbeatIntervalMs?: number; // default: 30000, 0 to disable
|
|
67
|
+
maxKeyAgeMs?: number; // default: 30 days, 0 to disable
|
|
68
|
+
sseEndpoint?: string;
|
|
69
|
+
createSseTransport?: () => Transport;
|
|
70
|
+
transport?: Transport; // pre-created, bypasses auto-resolution
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### `RuntimeHandle`
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
interface RuntimeHandle {
|
|
78
|
+
poller: AgentPoller;
|
|
79
|
+
heartbeat: HeartbeatService | null;
|
|
80
|
+
keyRotation: KeyRotationService | null;
|
|
81
|
+
sseConnection: SseConnectionService | null;
|
|
82
|
+
transport: Transport;
|
|
83
|
+
agentId: string;
|
|
84
|
+
stop: () => void;
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
`stop()` cleanly shuts down all services in order: SSE connection,
|
|
89
|
+
heartbeat, key rotation, poller, transport.
|
|
90
|
+
|
|
91
|
+
## Services
|
|
92
|
+
|
|
93
|
+
### `AgentPoller`
|
|
94
|
+
|
|
95
|
+
The core polling loop. Fetches direct messages and group-mention
|
|
96
|
+
messages on a configurable interval, deduplicates against a high-water
|
|
97
|
+
mark, and dispatches each new message to registered handlers.
|
|
98
|
+
|
|
99
|
+
### `HeartbeatService`
|
|
100
|
+
|
|
101
|
+
Periodic agent presence reporting. Tells the SignalDock backend that
|
|
102
|
+
the agent is alive so other agents can route messages to it without
|
|
103
|
+
hitting offline timeouts. Disabled when `heartbeatIntervalMs === 0`.
|
|
104
|
+
|
|
105
|
+
### `KeyRotationService`
|
|
106
|
+
|
|
107
|
+
Watches the agent's transport credential age and rotates the API key
|
|
108
|
+
before it expires. Maintains zero-downtime rotation by overlapping the
|
|
109
|
+
old and new keys for one poll cycle. Disabled when `maxKeyAgeMs === 0`.
|
|
110
|
+
|
|
111
|
+
### `SseConnectionService`
|
|
112
|
+
|
|
113
|
+
Optional persistent Server-Sent Events connection for sub-second
|
|
114
|
+
message delivery. When configured, the poller throttles down to a
|
|
115
|
+
slower interval and SSE handles the realtime path. Falls back
|
|
116
|
+
automatically to pure polling on connection loss.
|
|
117
|
+
|
|
118
|
+
## Architecture
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
┌──────────────────────────────────────────┐
|
|
122
|
+
│ cleo agent start (CLI entry) │
|
|
123
|
+
└────────────────┬─────────────────────────┘
|
|
124
|
+
│
|
|
125
|
+
▼
|
|
126
|
+
┌──────────────────────────────────────────┐
|
|
127
|
+
│ @cleocode/runtime createRuntime() │
|
|
128
|
+
│ ┌────────────────────────────────┐ │
|
|
129
|
+
│ │ AgentPoller (poll loop) │ │
|
|
130
|
+
│ │ HeartbeatService (presence) │ │
|
|
131
|
+
│ │ KeyRotationService (creds) │ │
|
|
132
|
+
│ │ SseConnectionService (realtime)│ │
|
|
133
|
+
│ └────────────────────────────────┘ │
|
|
134
|
+
└────────────────┬─────────────────────────┘
|
|
135
|
+
│
|
|
136
|
+
▼
|
|
137
|
+
┌──────────────────────────────────────────┐
|
|
138
|
+
│ @cleocode/contracts Transport interface │
|
|
139
|
+
│ resolves to Local | SSE | HTTP │
|
|
140
|
+
└────────────────┬─────────────────────────┘
|
|
141
|
+
│
|
|
142
|
+
▼
|
|
143
|
+
┌──────────────────────────────────────────┐
|
|
144
|
+
│ SignalDock backend (local or cloud) │
|
|
145
|
+
└──────────────────────────────────────────┘
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
The runtime is **transport-agnostic**: it works with the local
|
|
149
|
+
napi-rs SignalDock binding (in-process), SSE realtime, or HTTP polling
|
|
150
|
+
against `api.signaldock.io`. The transport layer is selected by
|
|
151
|
+
`createRuntime()` based on whether `sseEndpoint` and `transport` are
|
|
152
|
+
present in the config.
|
|
153
|
+
|
|
154
|
+
## CANT profile execution
|
|
155
|
+
|
|
156
|
+
`createRuntime()` does **not** execute `.cant` workflow profiles
|
|
157
|
+
directly. Profile-driven workflow execution lives in the
|
|
158
|
+
[`cant-bridge.ts`](../cleo/templates/cleoos-hub/pi-extensions/cant-bridge.ts)
|
|
159
|
+
Pi extension and runs inside a Pi session, not the daemon. Operators
|
|
160
|
+
who want profile-driven behaviour should start a Pi session and use
|
|
161
|
+
`/cant:load <file>` followed by `/cant:run <file> <workflow>`.
|
|
162
|
+
|
|
163
|
+
This boundary was set in [ADR-035 §D5](../../.cleo/adrs/ADR-035-pi-v2-v3-harness.md)
|
|
164
|
+
"single engine, cant-bridge.ts as canonical" — runtime stays simple
|
|
165
|
+
and profile semantics live in one place.
|
|
166
|
+
|
|
167
|
+
## Testing
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
pnpm --filter @cleocode/runtime test
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Tests use mocked transports from `@cleocode/contracts` to exercise the
|
|
174
|
+
poller and service lifecycle without hitting a real backend.
|
|
175
|
+
|
|
176
|
+
## Related
|
|
177
|
+
|
|
178
|
+
- [`@cleocode/contracts`](../contracts) — Transport interface and message types
|
|
179
|
+
- [`@cleocode/core`](../core) — agent registry, credential storage, message persistence
|
|
180
|
+
- [`packages/cleo/src/cli/commands/agent.ts`](../cleo/src/cli/commands/agent.ts) — `cleo agent start` CLI entry that calls `createRuntime`
|
|
181
|
+
- [`.cleo/adrs/ADR-035-pi-v2-v3-harness.md`](../../.cleo/adrs/ADR-035-pi-v2-v3-harness.md) — runtime/Pi boundary decisions
|
|
182
|
+
|
|
183
|
+
## License
|
|
184
|
+
|
|
185
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cleocode/runtime",
|
|
3
|
-
"version": "2026.4.
|
|
3
|
+
"version": "2026.4.10",
|
|
4
4
|
"description": "Long-running process layer for CLEO — agent polling, SSE connections, heartbeat, key rotation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@cleocode/contracts": "2026.4.
|
|
16
|
-
"@cleocode/core": "2026.4.
|
|
15
|
+
"@cleocode/contracts": "2026.4.10",
|
|
16
|
+
"@cleocode/core": "2026.4.10"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"tsup": "^8.0.0",
|