@rebon/cli-win32-x64 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +10 -0
- package/README.md +203 -144
- package/THIRD_PARTY_NOTICES.txt +1232 -128
- package/bin/rebon.js +22 -22
- package/lib/windows-managed.js +390 -390
- package/package.json +9 -2
- package/payload/compose-runtime/package.json +17 -17
- package/payload/compose-runtime/payload/compose/shims/dsh-anonymous-user-id.js +10 -10
- package/payload/compose-runtime/payload/compose/shims/dsh-credentials.js +13 -13
- package/payload/compose-runtime/payload/compose/shims/dsh-launch-environment.js +21 -21
- package/payload/compose-runtime/payload/compose/shims/dsh-llm.js +313 -313
- package/payload/compose-runtime/payload/compose/shims/dsh-settings.js +43 -43
- package/payload/compose-runtime/payload/compose/shims/dsh-tools.js +20 -20
- package/payload/compose-runtime/payload/compose/shims/dsh-web.js +10 -10
- package/payload/compose-runtime/payload/compose/shims/llm-adapter.js +32 -32
- package/payload/compose-runtime/payload/compose/shims/zod-lite.js +49 -49
- package/payload/compose-runtime/payload/vendor/cordis/LICENSE +21 -0
- package/payload/compose-runtime/payload/vendor/cordis/index.js +1530 -1530
- package/payload/compose-runtime/payload/vendor/cosmokit/LICENSE +21 -21
- package/payload/compose-runtime/payload/vendor/cosmokit/index.mjs +357 -357
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-agent +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-agent-loop +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-llm-core +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-llm-deepseek +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-logger-console +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-scope +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-session +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-system-prompt +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-timeout +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-timer +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-tool-todo +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-tool-web +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-tools-schema +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-turndown +21 -0
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-turndown-plugin-gfm +21 -0
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-web-search-exa +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/agent-loop.js +1193 -1193
- package/payload/compose-runtime/payload/vendor/dsh/agent.js +714 -714
- package/payload/compose-runtime/payload/vendor/dsh/llm-core.js +269 -269
- package/payload/compose-runtime/payload/vendor/dsh/llm-deepseek.js +672 -672
- package/payload/compose-runtime/payload/vendor/dsh/logger-console.js +83 -83
- package/payload/compose-runtime/payload/vendor/dsh/scope.js +287 -287
- package/payload/compose-runtime/payload/vendor/dsh/session.js +1668 -1668
- package/payload/compose-runtime/payload/vendor/dsh/system-prompt.js +309 -309
- package/payload/compose-runtime/payload/vendor/dsh/timeout.js +100 -100
- package/payload/compose-runtime/payload/vendor/dsh/timer.js +128 -128
- package/payload/compose-runtime/payload/vendor/dsh/tool-todo.js +143 -143
- package/payload/compose-runtime/payload/vendor/dsh/tool-web.js +1527 -1527
- package/payload/compose-runtime/payload/vendor/dsh/tools-schema.js +849 -849
- package/payload/compose-runtime/payload/vendor/dsh/web-search-exa.js +122 -122
- package/payload/compose-runtime/payload/vendor/eventsource-parser/LICENSE +21 -21
- package/payload/compose-runtime/payload/vendor/eventsource-parser/index.js +177 -177
- package/payload/compose-runtime/payload/vendor/eventsource-parser/stream.js +48 -48
- package/payload/compose-runtime/payload/vendor/schemastery/LICENSE +21 -0
- package/payload/compose-runtime/payload/vendor/schemastery/index.mjs +656 -656
- package/payload/compose-runtime/payload-manifests.json +48 -48
- package/payload/compose-runtime/src/bridge.mjs +193 -195
- package/payload/compose-runtime/src/credentials-runtime.mjs +50 -50
- package/payload/compose-runtime/src/eventsource-stream.mjs +48 -48
- package/payload/compose-runtime/src/index.mjs +7 -7
- package/payload/compose-runtime/src/llm-runtime.mjs +326 -326
- package/payload/compose-runtime/src/loader.mjs +78 -78
- package/payload/compose-runtime/src/loop-assembly.mjs +237 -237
- package/payload/compose-runtime/src/payload.mjs +49 -49
- package/payload/compose-runtime/src/plugin.mjs +59 -59
- package/payload/compose-runtime/src/realm.mjs +223 -223
- package/payload/compose-runtime/src/registry.mjs +191 -191
- package/payload/compose-runtime/src/resolve.mjs +115 -115
- package/payload/compose-runtime/src/systemprompt-runtime.mjs +67 -67
- package/payload/compose-runtime/src/tools-runtime.mjs +239 -239
- package/payload/compose-runtime/src/web-runtime.mjs +209 -209
- package/payload/plugin-host/package.json +11 -11
- package/payload/plugin-host/src/bridge.mjs +64 -64
- package/payload/plugin-host/src/cli.mjs +147 -147
- package/payload/plugin-host/src/framing.mjs +113 -113
- package/payload/plugin-host/src/host.mjs +691 -691
- package/payload/plugin-host/src/json.mjs +208 -208
- package/payload/plugin-host/src/lifecycle.mjs +114 -114
- package/payload/plugin-host/src/loader.mjs +183 -183
- package/payload/plugin-host/src/methods.mjs +377 -377
- package/payload/plugin-host/src/ownership.mjs +57 -57
- package/payload/plugin-host/src/protocol.mjs +129 -129
- package/payload/plugin-host/src/sdk.mjs +7 -7
- package/payload/rebon-boa-helper.exe +0 -0
- package/payload/rebon-browser-mcp.exe +0 -0
- package/payload/rebon-computer-use.exe +0 -0
- package/payload/rebon-lsp-mcp.exe +0 -0
- package/payload/rebon.exe +2 -2
- package/payload/sandbox-win.exe +0 -0
- package/scripts/postinstall.js +112 -112
- package/payload/compose-runtime/payload/compose/credentials-runtime.js +0 -38
- package/payload/compose-runtime/payload/compose/llm-runtime.js +0 -330
- package/payload/compose-runtime/payload/compose/loop-assembly.js +0 -149
- package/payload/compose-runtime/payload/compose/serve-dispatch.js +0 -82
- package/payload/compose-runtime/payload/compose/systemprompt-runtime.js +0 -74
- package/payload/compose-runtime/payload/compose/tools-runtime.js +0 -228
- package/payload/compose-runtime/payload/compose/web-runtime.js +0 -204
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 1,
|
|
3
|
-
"note": "What rebon declares on behalf of the packages it ships. Every plugin on the plane loads against a manifest — the ceiling on what it may register and reach — and a third-party package declares its own under `capabilities.kernelPlugins` in its `rebon-plugin.json`. These packages are vendored into rebon's payload, so rebon is the one that has to say what they do. `root` names which package the `entry` is relative to. It defaults to `package`, which in this table means the vendored JS tree an entry belongs to; `payload` says the same thing explicitly, and `runtime` names the composition runtime itself. `invokableTools: \"$rebon/tools\"` expands to every tool this build exposes to the plane — the honest declaration for a plugin that runs whatever tool a model picks.",
|
|
4
|
-
"packages": {
|
|
5
|
-
"cordis": { "entry": "vendor/cordis/index.js" },
|
|
6
|
-
"@deepseek-ai/cordis-plugin-timer": { "entry": "vendor/dsh/timer.js" },
|
|
7
|
-
"@deepseek-ai/cordis-plugin-logger-console": { "entry": "vendor/dsh/logger-console.js" },
|
|
8
|
-
|
|
9
|
-
"@deepseek-ai/dsh-llm-deepseek": {
|
|
10
|
-
"entry": "vendor/dsh/llm-deepseek.js",
|
|
11
|
-
"llmProviders": ["deepseek-official"],
|
|
12
|
-
"seats": ["credentials"]
|
|
13
|
-
},
|
|
14
|
-
"@deepseek-ai/dsh-tool-todo": {
|
|
15
|
-
"entry": "vendor/dsh/tool-todo.js",
|
|
16
|
-
"tools": ["todo_write"],
|
|
17
|
-
"publishedTopics": ["compose:session/append"]
|
|
18
|
-
},
|
|
19
|
-
"@deepseek-ai/dsh-tool-web": {
|
|
20
|
-
"entry": "vendor/dsh/tool-web.js",
|
|
21
|
-
"tools": ["web_search", "web_fetch"],
|
|
22
|
-
"invokableTools": ["WebSearch", "WebFetch"],
|
|
23
|
-
"publishedTopics": ["compose:session/append"]
|
|
24
|
-
},
|
|
25
|
-
"@deepseek-ai/dsh-web-search-exa": {
|
|
26
|
-
"entry": "vendor/dsh/web-search-exa.js",
|
|
27
|
-
"services": ["web:search:exa"],
|
|
28
|
-
"seats": ["credentials"]
|
|
29
|
-
},
|
|
30
|
-
|
|
31
|
-
"@deepseek-ai/dsh-session": { "entry": "vendor/dsh/session.js" },
|
|
32
|
-
"@deepseek-ai/dsh-agent": { "entry": "vendor/dsh/agent.js" },
|
|
33
|
-
"@deepseek-ai/dsh-system-prompt": { "entry": "vendor/dsh/system-prompt.js" },
|
|
34
|
-
"@deepseek-ai/dsh-agent-loop": {
|
|
35
|
-
"entry": "vendor/dsh/agent-loop.js",
|
|
36
|
-
"invokableTools": "$rebon/tools",
|
|
37
|
-
"seats": ["credentials"]
|
|
38
|
-
},
|
|
39
|
-
|
|
40
|
-
"rebon-loop-assembly": {
|
|
41
|
-
"root": "runtime",
|
|
42
|
-
"entry": "src/loop-assembly.mjs",
|
|
43
|
-
"services": ["loop:control"],
|
|
44
|
-
"publishedTopics": ["loop:event", "loop:agent-error", "loop:agent-created"],
|
|
45
|
-
"seats": ["logger"]
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"note": "What rebon declares on behalf of the packages it ships. Every plugin on the plane loads against a manifest — the ceiling on what it may register and reach — and a third-party package declares its own under `capabilities.kernelPlugins` in its `rebon-plugin.json`. These packages are vendored into rebon's payload, so rebon is the one that has to say what they do. `root` names which package the `entry` is relative to. It defaults to `package`, which in this table means the vendored JS tree an entry belongs to; `payload` says the same thing explicitly, and `runtime` names the composition runtime itself. `invokableTools: \"$rebon/tools\"` expands to every tool this build exposes to the plane — the honest declaration for a plugin that runs whatever tool a model picks.",
|
|
4
|
+
"packages": {
|
|
5
|
+
"cordis": { "entry": "vendor/cordis/index.js" },
|
|
6
|
+
"@deepseek-ai/cordis-plugin-timer": { "entry": "vendor/dsh/timer.js" },
|
|
7
|
+
"@deepseek-ai/cordis-plugin-logger-console": { "entry": "vendor/dsh/logger-console.js" },
|
|
8
|
+
|
|
9
|
+
"@deepseek-ai/dsh-llm-deepseek": {
|
|
10
|
+
"entry": "vendor/dsh/llm-deepseek.js",
|
|
11
|
+
"llmProviders": ["deepseek-official"],
|
|
12
|
+
"seats": ["credentials"]
|
|
13
|
+
},
|
|
14
|
+
"@deepseek-ai/dsh-tool-todo": {
|
|
15
|
+
"entry": "vendor/dsh/tool-todo.js",
|
|
16
|
+
"tools": ["todo_write"],
|
|
17
|
+
"publishedTopics": ["compose:session/append"]
|
|
18
|
+
},
|
|
19
|
+
"@deepseek-ai/dsh-tool-web": {
|
|
20
|
+
"entry": "vendor/dsh/tool-web.js",
|
|
21
|
+
"tools": ["web_search", "web_fetch"],
|
|
22
|
+
"invokableTools": ["WebSearch", "WebFetch"],
|
|
23
|
+
"publishedTopics": ["compose:session/append"]
|
|
24
|
+
},
|
|
25
|
+
"@deepseek-ai/dsh-web-search-exa": {
|
|
26
|
+
"entry": "vendor/dsh/web-search-exa.js",
|
|
27
|
+
"services": ["web:search:exa"],
|
|
28
|
+
"seats": ["credentials"]
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
"@deepseek-ai/dsh-session": { "entry": "vendor/dsh/session.js" },
|
|
32
|
+
"@deepseek-ai/dsh-agent": { "entry": "vendor/dsh/agent.js" },
|
|
33
|
+
"@deepseek-ai/dsh-system-prompt": { "entry": "vendor/dsh/system-prompt.js" },
|
|
34
|
+
"@deepseek-ai/dsh-agent-loop": {
|
|
35
|
+
"entry": "vendor/dsh/agent-loop.js",
|
|
36
|
+
"invokableTools": "$rebon/tools",
|
|
37
|
+
"seats": ["credentials"]
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
"rebon-loop-assembly": {
|
|
41
|
+
"root": "runtime",
|
|
42
|
+
"entry": "src/loop-assembly.mjs",
|
|
43
|
+
"services": ["loop:control"],
|
|
44
|
+
"publishedTopics": ["loop:event", "loop:agent-error", "loop:agent-created"],
|
|
45
|
+
"seats": ["logger"]
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -1,195 +1,193 @@
|
|
|
1
|
-
// The composition's doorway to rebon, on the plugin plane.
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
|
|
22
|
-
import {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
///
|
|
28
|
-
///
|
|
29
|
-
///
|
|
30
|
-
///
|
|
31
|
-
///
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
///
|
|
43
|
-
///
|
|
44
|
-
///
|
|
45
|
-
///
|
|
46
|
-
///
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
//
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
///
|
|
65
|
-
///
|
|
66
|
-
///
|
|
67
|
-
///
|
|
68
|
-
///
|
|
69
|
-
///
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
///
|
|
77
|
-
///
|
|
78
|
-
///
|
|
79
|
-
///
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
///
|
|
87
|
-
///
|
|
88
|
-
///
|
|
89
|
-
///
|
|
90
|
-
///
|
|
91
|
-
///
|
|
92
|
-
///
|
|
93
|
-
///
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
///
|
|
101
|
-
///
|
|
102
|
-
///
|
|
103
|
-
///
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
///
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
///
|
|
121
|
-
///
|
|
122
|
-
///
|
|
123
|
-
///
|
|
124
|
-
///
|
|
125
|
-
///
|
|
126
|
-
///
|
|
127
|
-
///
|
|
128
|
-
///
|
|
129
|
-
///
|
|
130
|
-
///
|
|
131
|
-
///
|
|
132
|
-
///
|
|
133
|
-
///
|
|
134
|
-
///
|
|
135
|
-
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
RATE.
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
bucket.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
bucket.
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
//
|
|
171
|
-
//
|
|
172
|
-
//
|
|
173
|
-
//
|
|
174
|
-
//
|
|
175
|
-
//
|
|
176
|
-
//
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
},
|
|
195
|
-
])));
|
|
1
|
+
// The composition's doorway to rebon, on the plugin plane.
|
|
2
|
+
//
|
|
3
|
+
// The plane is across a process boundary, so there are no synchronous ops
|
|
4
|
+
// into an in-process kernel here. Three consequences follow, and they are the
|
|
5
|
+
// protocol's rather than this module's:
|
|
6
|
+
//
|
|
7
|
+
// * **Everything is async.** `callService` returned a value from an op; a
|
|
8
|
+
// `seat/call` is a request that has to be answered. The one place this
|
|
9
|
+
// bites is a cordis disposer, which is synchronous and cannot await — see
|
|
10
|
+
// the note on `seat()` below.
|
|
11
|
+
// * **There is no ambient kernel.** A call is only meaningful inside the
|
|
12
|
+
// scope incarnation it was made for, so the doorway exists only inside a
|
|
13
|
+
// handler. `AsyncLocalStorage` is what carries the handler's context down
|
|
14
|
+
// to code that has no way to be handed it — a dsh credential provider is
|
|
15
|
+
// called by an adapter that knows nothing about rebon.
|
|
16
|
+
// * **Registration is not a call.** What a composition provides is
|
|
17
|
+
// reported once, in the `plugin/load` ready report, and revoked by
|
|
18
|
+
// `plugin/unload` draining. It has to be that shape: a compensating
|
|
19
|
+
// `unregister` would have to run from a cordis disposer, and a disposer
|
|
20
|
+
// cannot await the answer.
|
|
21
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
22
|
+
import { sessionOf } from './registry.mjs';
|
|
23
|
+
|
|
24
|
+
const calls = new AsyncLocalStorage();
|
|
25
|
+
|
|
26
|
+
/// Runs `fn` with `ctx` as the call everything underneath reaches through.
|
|
27
|
+
///
|
|
28
|
+
/// Every handler the composition serves — service, tool, llm adapter, event
|
|
29
|
+
/// delivery — is wrapped in this, so anything it calls can find its way back
|
|
30
|
+
/// to rebon without the call context being threaded through dsh code that has
|
|
31
|
+
/// no parameter for it.
|
|
32
|
+
export function withCall(ctx, fn) {
|
|
33
|
+
return calls.run(ctx, fn);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/// The call this code is running inside.
|
|
37
|
+
export function currentCall() {
|
|
38
|
+
return calls.getStore();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/// The call this code is running inside, or a refusal that says why not.
|
|
42
|
+
///
|
|
43
|
+
/// The refusal is worth its own code: "cannot read properties of undefined" at
|
|
44
|
+
/// the bottom of a dsh stack says nothing, whereas this names the actual rule —
|
|
45
|
+
/// rebon is reachable from inside a call, and a disposer or a module top level
|
|
46
|
+
/// is not inside one.
|
|
47
|
+
function require(what, via) {
|
|
48
|
+
const ctx = calls.getStore();
|
|
49
|
+
if (ctx !== undefined) return ctx;
|
|
50
|
+
// Nothing is being answered, so this is a plugin acting on its own schedule.
|
|
51
|
+
// `via` is the Cordis context of the plugin whose code is running, and the
|
|
52
|
+
// session it is attached to is the honest identity for what it does — the
|
|
53
|
+
// work is still that plugin's, in that session. Without a session there is
|
|
54
|
+
// no identity to use, and inventing one would make the ledger a guess.
|
|
55
|
+
const session = sessionOf(via);
|
|
56
|
+
if (session !== undefined) return session;
|
|
57
|
+
throw new Error(
|
|
58
|
+
`[NO_CALL_CONTEXT] ${what} is not reachable from here: no call rebon made is in flight, `
|
|
59
|
+
+ 'and this plugin is not attached to a session. Teardown paths must rely on unload draining instead',
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/// Calls a kernel seat: the composition's `credentials`, `settings`, `web` and
|
|
64
|
+
/// the rest of what rebon installs a plugin to use.
|
|
65
|
+
///
|
|
66
|
+
/// A request, therefore answerable, therefore **not** usable from a cordis
|
|
67
|
+
/// disposer: `dispose()` is synchronous and a cross-process call cannot be.
|
|
68
|
+
/// Nothing in the composition needs it to be — the calls that used to happen
|
|
69
|
+
/// on the way out were unregistrations, and those are the protocol's job now.
|
|
70
|
+
export function seat(name, method, params = null, options = {}) {
|
|
71
|
+
const { via, ...call } = options;
|
|
72
|
+
return require(`seat ${JSON.stringify(name)}`, via).seat(name, method, params, call);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/// Invokes one rebon core tool on the session this call belongs to.
|
|
76
|
+
///
|
|
77
|
+
/// Three gates stand in front of it and only the first is here: the plugin's
|
|
78
|
+
/// manifest must declare the tool, rebon's build must expose it, and the
|
|
79
|
+
/// embedder's broker decides whether this run is permitted.
|
|
80
|
+
export function invokeTool(tool, input = null, options = {}) {
|
|
81
|
+
const { via, ...call } = options;
|
|
82
|
+
return require(`tool ${JSON.stringify(tool)}`, via).invoke(tool, input, call);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/// Publishes one event onto rebon's event plane.
|
|
86
|
+
///
|
|
87
|
+
/// Not the same thing as `emit` below, and the difference is the audience: a
|
|
88
|
+
/// chunk is a piece of the answer the caller of *this* call is reading, an
|
|
89
|
+
/// event is a fact anyone listening may act on. The composition's runtime
|
|
90
|
+
/// events — a dsh tool body appending to the session log — are the second kind.
|
|
91
|
+
///
|
|
92
|
+
/// Declared as `publishedTopics` in the manifest, separately from what the
|
|
93
|
+
/// composition listens to.
|
|
94
|
+
export function publish(topic, event = null, options = {}) {
|
|
95
|
+
const { via, ...call } = options;
|
|
96
|
+
return require(`topic ${JSON.stringify(topic)}`, via).publish(topic, event, call);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/// Emits one piece of a streamed answer on the call this code is serving.
|
|
100
|
+
///
|
|
101
|
+
/// This is the transport `op_llm_emit` and `op_tool_serve_emit` used to be,
|
|
102
|
+
/// with the pumps gone: a chunk belongs to a call, and the call is the one the
|
|
103
|
+
/// handler was entered with rather than an id looked up in a table.
|
|
104
|
+
export function emit(piece) {
|
|
105
|
+
return require('emit').emit(piece);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/// The workspace root of the session this call belongs to, or undefined
|
|
109
|
+
/// outside a call.
|
|
110
|
+
export function workspaceRoot() {
|
|
111
|
+
return calls.getStore()?.workspaceRoot;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/// The abort signal rebon raises when it asks this call to stop.
|
|
115
|
+
export function callSignal() {
|
|
116
|
+
return calls.getStore()?.signal;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/// Diagnostics.
|
|
120
|
+
///
|
|
121
|
+
/// Best-effort on purpose, and never a reason for a call to fail: a log line
|
|
122
|
+
/// that cannot be delivered is not worth failing the work that produced it.
|
|
123
|
+
/// Inside a call it goes to the kernel's `logger` seat, so the line is
|
|
124
|
+
/// attributed to a scope; outside one it goes to stderr, which the supervisor
|
|
125
|
+
/// already collects as the host's diagnostic tail. stdout is never touched —
|
|
126
|
+
/// that is the protocol's channel.
|
|
127
|
+
/// A token bucket per level, so one plugin in a logging loop cannot fill the
|
|
128
|
+
/// worker's log.
|
|
129
|
+
///
|
|
130
|
+
/// Here rather than on rebon's side because the cheapest byte is the one that
|
|
131
|
+
/// never crosses the process boundary, and because this side already knows how
|
|
132
|
+
/// many it dropped. Drops are reported, at most once a second: replacing a
|
|
133
|
+
/// blind spot with a quieter blind spot is not an improvement, and a reader who
|
|
134
|
+
/// sees a gap deserves to know it is a gap.
|
|
135
|
+
const RATE = { perSecond: 20, burst: 100 };
|
|
136
|
+
const buckets = new Map();
|
|
137
|
+
|
|
138
|
+
function admit(level) {
|
|
139
|
+
const now = Date.now();
|
|
140
|
+
let bucket = buckets.get(level);
|
|
141
|
+
if (bucket === undefined) {
|
|
142
|
+
bucket = { tokens: RATE.burst, last: now, dropped: 0, reportedAt: 0 };
|
|
143
|
+
buckets.set(level, bucket);
|
|
144
|
+
}
|
|
145
|
+
bucket.tokens = Math.min(
|
|
146
|
+
RATE.burst,
|
|
147
|
+
bucket.tokens + ((now - bucket.last) / 1000) * RATE.perSecond,
|
|
148
|
+
);
|
|
149
|
+
bucket.last = now;
|
|
150
|
+
if (bucket.tokens >= 1) {
|
|
151
|
+
bucket.tokens -= 1;
|
|
152
|
+
return { allowed: true, dropped: 0 };
|
|
153
|
+
}
|
|
154
|
+
bucket.dropped += 1;
|
|
155
|
+
if (now - bucket.reportedAt >= 1000) {
|
|
156
|
+
bucket.reportedAt = now;
|
|
157
|
+
const dropped = bucket.dropped;
|
|
158
|
+
bucket.dropped = 0;
|
|
159
|
+
return { allowed: false, dropped };
|
|
160
|
+
}
|
|
161
|
+
return { allowed: false, dropped: 0 };
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const LEVELS = ['trace', 'debug', 'info', 'warn', 'error'];
|
|
165
|
+
export const logger = Object.freeze(Object.fromEntries(LEVELS.map((level) => [
|
|
166
|
+
level,
|
|
167
|
+
(message, options = {}) => {
|
|
168
|
+
const line = String(message);
|
|
169
|
+
// Inside a call, that call is who is speaking. Outside one — a timer, an
|
|
170
|
+
// agent loop driving its own turn — `via` names the plugin, and the
|
|
171
|
+
// session it is attached to is the handle that can still reach the seat.
|
|
172
|
+
//
|
|
173
|
+
// This is the same ladder `require()` climbs, with one difference that
|
|
174
|
+
// matters: it does not throw. A log line is not worth failing a plugin over,
|
|
175
|
+
// and a line that goes to stderr is only ever read when the host dies — the
|
|
176
|
+
// very silence this is fixing.
|
|
177
|
+
const ctx = calls.getStore() ?? sessionOf(options.via);
|
|
178
|
+
if (ctx === undefined) {
|
|
179
|
+
process.stderr.write(`[compose:${level}] ${line}\n`);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const { allowed, dropped } = admit(level);
|
|
183
|
+
if (dropped > 0) {
|
|
184
|
+
void ctx
|
|
185
|
+
.seat('logger', 'warn', { message: `${dropped} ${level} line(s) dropped: too many, too fast` })
|
|
186
|
+
.catch(() => {});
|
|
187
|
+
}
|
|
188
|
+
if (!allowed) return;
|
|
189
|
+
void ctx.seat('logger', level, { message: line }).catch(() => {
|
|
190
|
+
process.stderr.write(`[compose:${level}] ${line}\n`);
|
|
191
|
+
});
|
|
192
|
+
},
|
|
193
|
+
])));
|
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
// The composition's `ctx.credentials` seat, on the plugin plane.
|
|
2
|
-
//
|
|
3
|
-
// dsh configuration carries credential *references* (environment-variable
|
|
4
|
-
// names); the provider owns the values. This resolves a reference through
|
|
5
|
-
// rebon's `credentials` seat, whose `resolveEnv` runs the fail-closed
|
|
6
|
-
// authorize waterfall before touching the environment — so an unauthorized or
|
|
7
|
-
// unset reference is simply "absent", and the consumer's own missing-credential
|
|
8
|
-
// diagnosis fires (dsh-llm's `MISSING_CREDENTIAL`) instead of this seat
|
|
9
|
-
// inventing one.
|
|
10
|
-
//
|
|
11
|
-
// Ported from `js/compose/credentials-runtime.js`. The one change is that the
|
|
12
|
-
// seat call is now a request across a process boundary, which means it is
|
|
13
|
-
// awaited — and that it can only be made from inside a call rebon is waiting
|
|
14
|
-
// on, or by the plugin being attached to a session. Both hold where a
|
|
15
|
-
// credential is actually wanted: inside a model turn rebon asked for, or inside
|
|
16
|
-
// one an agent loop is running in a session of its own. `bridge.mjs` names the
|
|
17
|
-
// refusal if anything ever tries from a disposer or a module top level.
|
|
18
|
-
import { Service } from 'cordis';
|
|
19
|
-
import { seat } from './bridge.mjs';
|
|
20
|
-
|
|
21
|
-
export default class RebonCredentials extends Service {
|
|
22
|
-
constructor(ctx) {
|
|
23
|
-
super(ctx, 'credentials');
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/** dsh CredentialProvider.resolve: `{value, source}` or undefined. */
|
|
27
|
-
async resolve(ref) {
|
|
28
|
-
try {
|
|
29
|
-
// `via` is this seat's caller — the plugin whose code wants the
|
|
30
|
-
// credential. Inside a call that changes nothing; outside one it is what
|
|
31
|
-
// lets an agent loop's own model turn resolve a key at all, attributed to
|
|
32
|
-
// the plugin and session it belongs to.
|
|
33
|
-
const out = await seat('credentials', 'resolveEnv', { ref: String(ref) }, { via: this.ctx });
|
|
34
|
-
const value = out?.value;
|
|
35
|
-
if (typeof value === 'string' && value.length > 0) {
|
|
36
|
-
return { value, source: 'env' };
|
|
37
|
-
}
|
|
38
|
-
} catch {
|
|
39
|
-
// A refusal from the seat (no authorizer, unset variable, bad ref) and
|
|
40
|
-
// an absent value are the same fact to a consumer: not configured here.
|
|
41
|
-
}
|
|
42
|
-
return undefined;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/** dsh CredentialProvider.describe: facts only, never the value. */
|
|
46
|
-
async describe(ref) {
|
|
47
|
-
const hit = await this.resolve(ref);
|
|
48
|
-
return { configured: hit !== undefined, ...(hit ? { source: hit.source } : {}), writable: false };
|
|
49
|
-
}
|
|
50
|
-
}
|
|
1
|
+
// The composition's `ctx.credentials` seat, on the plugin plane.
|
|
2
|
+
//
|
|
3
|
+
// dsh configuration carries credential *references* (environment-variable
|
|
4
|
+
// names); the provider owns the values. This resolves a reference through
|
|
5
|
+
// rebon's `credentials` seat, whose `resolveEnv` runs the fail-closed
|
|
6
|
+
// authorize waterfall before touching the environment — so an unauthorized or
|
|
7
|
+
// unset reference is simply "absent", and the consumer's own missing-credential
|
|
8
|
+
// diagnosis fires (dsh-llm's `MISSING_CREDENTIAL`) instead of this seat
|
|
9
|
+
// inventing one.
|
|
10
|
+
//
|
|
11
|
+
// Ported from `js/compose/credentials-runtime.js`. The one change is that the
|
|
12
|
+
// seat call is now a request across a process boundary, which means it is
|
|
13
|
+
// awaited — and that it can only be made from inside a call rebon is waiting
|
|
14
|
+
// on, or by the plugin being attached to a session. Both hold where a
|
|
15
|
+
// credential is actually wanted: inside a model turn rebon asked for, or inside
|
|
16
|
+
// one an agent loop is running in a session of its own. `bridge.mjs` names the
|
|
17
|
+
// refusal if anything ever tries from a disposer or a module top level.
|
|
18
|
+
import { Service } from 'cordis';
|
|
19
|
+
import { seat } from './bridge.mjs';
|
|
20
|
+
|
|
21
|
+
export default class RebonCredentials extends Service {
|
|
22
|
+
constructor(ctx) {
|
|
23
|
+
super(ctx, 'credentials');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** dsh CredentialProvider.resolve: `{value, source}` or undefined. */
|
|
27
|
+
async resolve(ref) {
|
|
28
|
+
try {
|
|
29
|
+
// `via` is this seat's caller — the plugin whose code wants the
|
|
30
|
+
// credential. Inside a call that changes nothing; outside one it is what
|
|
31
|
+
// lets an agent loop's own model turn resolve a key at all, attributed to
|
|
32
|
+
// the plugin and session it belongs to.
|
|
33
|
+
const out = await seat('credentials', 'resolveEnv', { ref: String(ref) }, { via: this.ctx });
|
|
34
|
+
const value = out?.value;
|
|
35
|
+
if (typeof value === 'string' && value.length > 0) {
|
|
36
|
+
return { value, source: 'env' };
|
|
37
|
+
}
|
|
38
|
+
} catch {
|
|
39
|
+
// A refusal from the seat (no authorizer, unset variable, bad ref) and
|
|
40
|
+
// an absent value are the same fact to a consumer: not configured here.
|
|
41
|
+
}
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** dsh CredentialProvider.describe: facts only, never the value. */
|
|
46
|
+
async describe(ref) {
|
|
47
|
+
const hit = await this.resolve(ref);
|
|
48
|
+
return { configured: hit !== undefined, ...(hit ? { source: hit.source } : {}), writable: false };
|
|
49
|
+
}
|
|
50
|
+
}
|