@unicity-astrid/sdk 0.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/README.md +120 -0
- package/dist/approval.d.ts +23 -0
- package/dist/approval.d.ts.map +1 -0
- package/dist/approval.js +29 -0
- package/dist/approval.js.map +1 -0
- package/dist/capabilities.d.ts +14 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +19 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/capsule.d.ts +39 -0
- package/dist/capsule.d.ts.map +1 -0
- package/dist/capsule.js +67 -0
- package/dist/capsule.js.map +1 -0
- package/dist/contracts.d.ts +1104 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +4 -0
- package/dist/contracts.js.map +1 -0
- package/dist/elicit.d.ts +30 -0
- package/dist/elicit.d.ts.map +1 -0
- package/dist/elicit.js +103 -0
- package/dist/elicit.js.map +1 -0
- package/dist/env.d.ts +19 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +27 -0
- package/dist/env.js.map +1 -0
- package/dist/errors.d.ts +46 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +108 -0
- package/dist/errors.js.map +1 -0
- package/dist/fs.d.ts +135 -0
- package/dist/fs.d.ts.map +1 -0
- package/dist/fs.js +257 -0
- package/dist/fs.js.map +1 -0
- package/dist/http.d.ts +90 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +276 -0
- package/dist/http.js.map +1 -0
- package/dist/identity.d.ts +46 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +69 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/interceptors.d.ts +21 -0
- package/dist/interceptors.d.ts.map +1 -0
- package/dist/interceptors.js +22 -0
- package/dist/interceptors.js.map +1 -0
- package/dist/ipc.d.ts +143 -0
- package/dist/ipc.d.ts.map +1 -0
- package/dist/ipc.js +261 -0
- package/dist/ipc.js.map +1 -0
- package/dist/kv.d.ts +45 -0
- package/dist/kv.d.ts.map +1 -0
- package/dist/kv.js +91 -0
- package/dist/kv.js.map +1 -0
- package/dist/log.d.ts +17 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +40 -0
- package/dist/log.js.map +1 -0
- package/dist/net.d.ts +154 -0
- package/dist/net.d.ts.map +1 -0
- package/dist/net.js +421 -0
- package/dist/net.js.map +1 -0
- package/dist/process.d.ts +77 -0
- package/dist/process.d.ts.map +1 -0
- package/dist/process.js +128 -0
- package/dist/process.js.map +1 -0
- package/dist/runtime/bridge.d.ts +34 -0
- package/dist/runtime/bridge.d.ts.map +1 -0
- package/dist/runtime/bridge.js +326 -0
- package/dist/runtime/bridge.js.map +1 -0
- package/dist/runtime/index.d.ts +3 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +3 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/registry.d.ts +58 -0
- package/dist/runtime/registry.d.ts.map +1 -0
- package/dist/runtime/registry.js +129 -0
- package/dist/runtime/registry.js.map +1 -0
- package/dist/runtime.d.ts +36 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +50 -0
- package/dist/runtime.js.map +1 -0
- package/dist/time.d.ts +29 -0
- package/dist/time.d.ts.map +1 -0
- package/dist/time.js +43 -0
- package/dist/time.js.map +1 -0
- package/dist/tool.d.ts +48 -0
- package/dist/tool.d.ts.map +1 -0
- package/dist/tool.js +86 -0
- package/dist/tool.js.map +1 -0
- package/dist/uplink.d.ts +27 -0
- package/dist/uplink.d.ts.map +1 -0
- package/dist/uplink.js +36 -0
- package/dist/uplink.js.map +1 -0
- package/package.json +38 -0
- package/src/approval.ts +38 -0
- package/src/capabilities.ts +22 -0
- package/src/capsule.ts +90 -0
- package/src/contracts.ts +1189 -0
- package/src/elicit.ts +136 -0
- package/src/env.ts +31 -0
- package/src/errors.ts +122 -0
- package/src/fs.ts +357 -0
- package/src/http.ts +345 -0
- package/src/identity.ts +101 -0
- package/src/index.ts +83 -0
- package/src/interceptors.ts +25 -0
- package/src/ipc.ts +354 -0
- package/src/kv.ts +123 -0
- package/src/log.ts +43 -0
- package/src/net.ts +545 -0
- package/src/process.ts +205 -0
- package/src/runtime/bridge.ts +374 -0
- package/src/runtime/index.ts +11 -0
- package/src/runtime/registry.ts +178 -0
- package/src/runtime.ts +70 -0
- package/src/time.ts +48 -0
- package/src/tool.ts +125 -0
- package/src/uplink.ts +49 -0
- package/src/wit-imports.d.ts +689 -0
- package/wit-contracts/astrid-contracts.wit +1266 -0
|
@@ -0,0 +1,1266 @@
|
|
|
1
|
+
// AUTO-GENERATED — DO NOT EDIT.
|
|
2
|
+
//
|
|
3
|
+
// Concatenated from contracts/interfaces/*.wit by
|
|
4
|
+
// scripts/sync-contracts-wit.sh.
|
|
5
|
+
//
|
|
6
|
+
// Source of truth: unicity-astrid/wit (git submodule at contracts/).
|
|
7
|
+
// Run `scripts/sync-contracts-wit.sh` after pulling the submodule to
|
|
8
|
+
// regenerate this file.
|
|
9
|
+
|
|
10
|
+
package astrid:contracts@1.0.0;
|
|
11
|
+
|
|
12
|
+
// ── types ──────────────────────────────────────────────────────────
|
|
13
|
+
package astrid-bus:types@1.0.0;
|
|
14
|
+
|
|
15
|
+
/// Shared types used across Astrid interfaces.
|
|
16
|
+
///
|
|
17
|
+
/// Foundation types for messages, tool calls, and token usage.
|
|
18
|
+
/// Imported by llm, session, prompt, context, and tool interfaces.
|
|
19
|
+
interface types {
|
|
20
|
+
/// A conversation message.
|
|
21
|
+
record message {
|
|
22
|
+
role: message-role,
|
|
23
|
+
content: message-content,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
enum message-role {
|
|
27
|
+
system,
|
|
28
|
+
user,
|
|
29
|
+
assistant,
|
|
30
|
+
tool,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/// Message content — text, tool calls, tool results, or mixed.
|
|
34
|
+
variant message-content {
|
|
35
|
+
text(string),
|
|
36
|
+
tool-calls(list<tool-call>),
|
|
37
|
+
tool-result(tool-call-result),
|
|
38
|
+
multi-part(list<content-part>),
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
variant content-part {
|
|
42
|
+
text(string),
|
|
43
|
+
image(image-data),
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
record image-data {
|
|
47
|
+
data: string,
|
|
48
|
+
media-type: string,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/// A tool call requested by the model.
|
|
52
|
+
record tool-call {
|
|
53
|
+
/// Tool call identifier.
|
|
54
|
+
id: string,
|
|
55
|
+
/// Name of the tool to invoke.
|
|
56
|
+
name: string,
|
|
57
|
+
/// JSON-encoded arguments (serde_json::Value in Rust).
|
|
58
|
+
arguments: string,
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/// Result of executing a tool call.
|
|
62
|
+
record tool-call-result {
|
|
63
|
+
call-id: string,
|
|
64
|
+
content: string,
|
|
65
|
+
is-error: bool,
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/// A tool definition provided to the model.
|
|
69
|
+
record tool-definition {
|
|
70
|
+
name: string,
|
|
71
|
+
description: option<string>,
|
|
72
|
+
input-schema: string,
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/// Token usage statistics.
|
|
76
|
+
record usage {
|
|
77
|
+
input-tokens: u64,
|
|
78
|
+
output-tokens: u64,
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ── agent ──────────────────────────────────────────────────────────
|
|
83
|
+
package astrid-bus:agent@1.0.0;
|
|
84
|
+
|
|
85
|
+
/// Agent interface — runtime envelopes the agent loop publishes for uplinks.
|
|
86
|
+
///
|
|
87
|
+
/// The agent capsule publishes `agent.v1.response` with streaming and final
|
|
88
|
+
/// turn output, and `agent.v1.session_changed` whenever the active session
|
|
89
|
+
/// rolls over. Uplink capsules subscribe to surface these to the user.
|
|
90
|
+
interface agent {
|
|
91
|
+
/// A response generated by the agent for the user.
|
|
92
|
+
record response {
|
|
93
|
+
/// The text output (may be a streaming delta or a complete reply).
|
|
94
|
+
text: string,
|
|
95
|
+
/// True if this is the final response in the turn.
|
|
96
|
+
is-final: bool,
|
|
97
|
+
/// Session ID for multi-session attribution.
|
|
98
|
+
session-id: string,
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/// Notification that the active session has changed (e.g. cleared,
|
|
102
|
+
/// branched, restored). Uplinks use this to refresh their view.
|
|
103
|
+
record session-changed {
|
|
104
|
+
/// The session ID that is now active.
|
|
105
|
+
session-id: string,
|
|
106
|
+
/// Optional ID of the session that was previously active.
|
|
107
|
+
previous-session-id: option<string>,
|
|
108
|
+
/// Reason for the change (e.g. "clear", "restore", "branch").
|
|
109
|
+
reason: string,
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// ── approval ──────────────────────────────────────────────────────────
|
|
114
|
+
package astrid-bus:approval@1.0.0;
|
|
115
|
+
|
|
116
|
+
/// Approval interface — human-in-the-loop authorization envelopes.
|
|
117
|
+
///
|
|
118
|
+
/// A capsule publishes `astrid.v1.approval` when it needs user authorization
|
|
119
|
+
/// for a sensitive action that did not match a pre-approved allowance. The
|
|
120
|
+
/// TUI prompts, then publishes the decision on
|
|
121
|
+
/// `astrid.v1.approval.response.<request-id>`. Distinct from the host
|
|
122
|
+
/// `request-approval` syscall (in-capsule API) — these envelopes carry the
|
|
123
|
+
/// same flow over the IPC bus for uplink consumption.
|
|
124
|
+
interface approval {
|
|
125
|
+
/// An interceptor or capsule request for human authorization.
|
|
126
|
+
record required {
|
|
127
|
+
/// Correlation ID matching the response.
|
|
128
|
+
request-id: string,
|
|
129
|
+
/// The action being requested (e.g. `"git push"`).
|
|
130
|
+
action: string,
|
|
131
|
+
/// The resource target (e.g. full command string).
|
|
132
|
+
target-resource: string,
|
|
133
|
+
/// Justification shown to the user.
|
|
134
|
+
reason: string,
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/// Response to an approval request.
|
|
138
|
+
record response {
|
|
139
|
+
/// Must match the `request-id` from the originating request.
|
|
140
|
+
request-id: string,
|
|
141
|
+
/// The user's decision (e.g. `"approve"`, `"deny"`,
|
|
142
|
+
/// `"approve_session"`, `"approve_always"`, `"allowance"`).
|
|
143
|
+
decision: string,
|
|
144
|
+
/// Optional reason for the decision.
|
|
145
|
+
reason: option<string>,
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ── client ──────────────────────────────────────────────────────────
|
|
150
|
+
package astrid-bus:client@1.0.0;
|
|
151
|
+
|
|
152
|
+
/// Client interface — connection lifecycle envelopes for uplinks.
|
|
153
|
+
///
|
|
154
|
+
/// Uplinks publish `client.v1.connect` on attach and `client.v1.disconnect`
|
|
155
|
+
/// on detach so the kernel can update the active-connection count and
|
|
156
|
+
/// trigger idle-shutdown when the last client disconnects.
|
|
157
|
+
interface client {
|
|
158
|
+
/// A client has connected to an uplink.
|
|
159
|
+
record connect {
|
|
160
|
+
/// Optional client identifier (e.g. process name + PID).
|
|
161
|
+
client-id: option<string>,
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/// A client is disconnecting gracefully.
|
|
165
|
+
record disconnect {
|
|
166
|
+
/// Optional reason for disconnection (e.g. "quit", "timeout").
|
|
167
|
+
reason: option<string>,
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// ── context ──────────────────────────────────────────────────────────
|
|
172
|
+
package astrid-bus:context@1.0.0;
|
|
173
|
+
|
|
174
|
+
/// Context interface — conversation compaction and token management.
|
|
175
|
+
///
|
|
176
|
+
/// A capsule exporting this interface handles `context_engine.v1.*`
|
|
177
|
+
/// requests and publishes compaction responses and hooks for plugin
|
|
178
|
+
/// capsules to influence compaction behaviour.
|
|
179
|
+
interface context {
|
|
180
|
+
use astrid-bus:types/types.{message};
|
|
181
|
+
|
|
182
|
+
/// Request to compact messages within a token budget.
|
|
183
|
+
record compact-request {
|
|
184
|
+
session-id: string,
|
|
185
|
+
messages: list<message>,
|
|
186
|
+
max-tokens: u64,
|
|
187
|
+
target-tokens: u64,
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/// Result of compaction.
|
|
191
|
+
record compact-response {
|
|
192
|
+
messages: list<message>,
|
|
193
|
+
compacted: bool,
|
|
194
|
+
messages-removed: u32,
|
|
195
|
+
strategy: string,
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/// Request to estimate token count for messages.
|
|
199
|
+
record estimate-request {
|
|
200
|
+
messages: list<message>,
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/// Token count estimate.
|
|
204
|
+
record estimate-response {
|
|
205
|
+
estimated-tokens: u64,
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/// Hook payload sent before compaction (plugins can influence).
|
|
209
|
+
record before-compaction-hook {
|
|
210
|
+
session-id: string,
|
|
211
|
+
messages: list<message>,
|
|
212
|
+
message-count: u32,
|
|
213
|
+
estimated-tokens: u64,
|
|
214
|
+
max-tokens: u64,
|
|
215
|
+
response-topic: string,
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/// Plugin response to before-compaction hook.
|
|
219
|
+
record before-compaction-hook-response {
|
|
220
|
+
skip: option<bool>,
|
|
221
|
+
pinned-message-ids: list<string>,
|
|
222
|
+
custom-strategy: option<string>,
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/// Notification after compaction completes.
|
|
226
|
+
record after-compaction-event {
|
|
227
|
+
session-id: string,
|
|
228
|
+
messages-before: u32,
|
|
229
|
+
messages-after: u32,
|
|
230
|
+
tokens-before: u64,
|
|
231
|
+
tokens-after: u64,
|
|
232
|
+
strategy-used: string,
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// ── elicit ──────────────────────────────────────────────────────────
|
|
237
|
+
package astrid-bus:elicit@1.0.0;
|
|
238
|
+
|
|
239
|
+
/// Elicit interface — interactive user input during a capsule lifecycle hook.
|
|
240
|
+
///
|
|
241
|
+
/// A capsule publishes `astrid.v1.elicit.<key>` when its install / upgrade
|
|
242
|
+
/// hook needs a value from the user. The TUI prompts, then publishes the
|
|
243
|
+
/// answer on `astrid.v1.elicit.response.<key>`. Distinct from the host
|
|
244
|
+
/// `elicit` syscall (which is the in-capsule API) — these envelopes carry
|
|
245
|
+
/// the same flow over the IPC bus for uplink consumption.
|
|
246
|
+
interface elicit {
|
|
247
|
+
use astrid-bus:onboarding/onboarding.{field};
|
|
248
|
+
|
|
249
|
+
/// A lifecycle hook is requesting user input.
|
|
250
|
+
record request {
|
|
251
|
+
/// Correlation ID matching the response.
|
|
252
|
+
request-id: string,
|
|
253
|
+
/// The capsule requesting input.
|
|
254
|
+
capsule-id: string,
|
|
255
|
+
/// Field descriptor reusing the onboarding schema.
|
|
256
|
+
field: field,
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/// Response to an elicit request.
|
|
260
|
+
record response {
|
|
261
|
+
/// Must match the `request-id` from the originating request.
|
|
262
|
+
request-id: string,
|
|
263
|
+
/// The user's input. Absent if the user cancelled.
|
|
264
|
+
value: option<string>,
|
|
265
|
+
/// For `array`-type fields, the collected items.
|
|
266
|
+
values: option<list<string>>,
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// ── hook ──────────────────────────────────────────────────────────
|
|
271
|
+
package astrid-bus:hook@1.0.0;
|
|
272
|
+
|
|
273
|
+
/// Hook interface — maps kernel lifecycle events to semantic hooks.
|
|
274
|
+
///
|
|
275
|
+
/// A capsule exporting this interface intercepts `astrid.v1.lifecycle.*`
|
|
276
|
+
/// events and publishes `hook.v1.result.*` with merge strategy results.
|
|
277
|
+
/// Plugin capsules subscribe to specific hooks to extend behaviour.
|
|
278
|
+
interface hook {
|
|
279
|
+
/// Lifecycle events emitted by the kernel.
|
|
280
|
+
enum lifecycle-event {
|
|
281
|
+
session-created,
|
|
282
|
+
session-ended,
|
|
283
|
+
tool-call-started,
|
|
284
|
+
tool-call-completed,
|
|
285
|
+
tool-result-persisting,
|
|
286
|
+
message-received,
|
|
287
|
+
message-sending,
|
|
288
|
+
message-sent,
|
|
289
|
+
sub-agent-spawned,
|
|
290
|
+
sub-agent-completed,
|
|
291
|
+
sub-agent-failed,
|
|
292
|
+
sub-agent-cancelled,
|
|
293
|
+
context-compaction-started,
|
|
294
|
+
context-compaction-completed,
|
|
295
|
+
kernel-started,
|
|
296
|
+
kernel-shutdown,
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/// Merged result from hook fan-out.
|
|
300
|
+
record hook-result {
|
|
301
|
+
/// Whether the operation should be skipped.
|
|
302
|
+
skip: option<bool>,
|
|
303
|
+
/// Merged data from interceptor responses (opaque JSON).
|
|
304
|
+
data: option<string>,
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// ── llm ──────────────────────────────────────────────────────────
|
|
309
|
+
package astrid-bus:llm@1.0.0;
|
|
310
|
+
|
|
311
|
+
/// LLM interface — streaming text generation with tool use support.
|
|
312
|
+
///
|
|
313
|
+
/// A capsule exporting this interface handles `llm.v1.request.generate.*`
|
|
314
|
+
/// events and publishes `llm.v1.stream.*` streaming responses.
|
|
315
|
+
interface llm {
|
|
316
|
+
use astrid-bus:types/types.{message, tool-definition, usage};
|
|
317
|
+
use astrid-bus:registry/registry.{provider-entry};
|
|
318
|
+
|
|
319
|
+
/// Request asking an LLM-provider capsule to describe itself.
|
|
320
|
+
/// Topic: `llm.v1.request.describe`. The registry capsule fans this
|
|
321
|
+
/// out to discover available providers and their per-provider
|
|
322
|
+
/// request / stream topics.
|
|
323
|
+
record describe-request {
|
|
324
|
+
/// Correlation ID for the response. The provider replies on
|
|
325
|
+
/// `llm.v1.response.describe.<correlation-id>`.
|
|
326
|
+
correlation-id: string,
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/// Provider self-description response.
|
|
330
|
+
/// Topic: `llm.v1.response.describe.<correlation-id>`.
|
|
331
|
+
record describe-response {
|
|
332
|
+
/// Must match the `correlation-id` from the originating request.
|
|
333
|
+
correlation-id: string,
|
|
334
|
+
/// Provider entries the capsule offers (one capsule may expose
|
|
335
|
+
/// multiple models — e.g. an OpenAI-compatible front-end serving
|
|
336
|
+
/// several model IDs).
|
|
337
|
+
providers: list<provider-entry>,
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/// Request to generate a response.
|
|
341
|
+
record generate-request {
|
|
342
|
+
request-id: string,
|
|
343
|
+
model: string,
|
|
344
|
+
messages: list<message>,
|
|
345
|
+
tools: list<tool-definition>,
|
|
346
|
+
/// System prompt.
|
|
347
|
+
system: string,
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/// A streaming event from the provider.
|
|
351
|
+
variant stream-event {
|
|
352
|
+
text-delta(string),
|
|
353
|
+
tool-call-start(tool-call-start-event),
|
|
354
|
+
tool-call-delta(tool-call-delta-event),
|
|
355
|
+
tool-call-end(tool-call-end-event),
|
|
356
|
+
reasoning-delta(string),
|
|
357
|
+
usage(usage),
|
|
358
|
+
done,
|
|
359
|
+
error(string),
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
record tool-call-start-event {
|
|
363
|
+
id: string,
|
|
364
|
+
name: string,
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
record tool-call-delta-event {
|
|
368
|
+
id: string,
|
|
369
|
+
args-delta: string,
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
record tool-call-end-event {
|
|
373
|
+
id: string,
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/// Final (non-streaming) response.
|
|
377
|
+
record generate-response {
|
|
378
|
+
message: message,
|
|
379
|
+
has-tool-calls: bool,
|
|
380
|
+
stop-reason: stop-reason,
|
|
381
|
+
usage: usage,
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
enum stop-reason {
|
|
385
|
+
end-turn,
|
|
386
|
+
max-tokens,
|
|
387
|
+
tool-use,
|
|
388
|
+
stop-sequence,
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// ── onboarding ──────────────────────────────────────────────────────────
|
|
393
|
+
package astrid-bus:onboarding@1.0.0;
|
|
394
|
+
|
|
395
|
+
/// Onboarding interface — env-var collection at install / first-run.
|
|
396
|
+
///
|
|
397
|
+
/// A capsule publishes `astrid.v1.onboarding.required` when it cannot start
|
|
398
|
+
/// without configuration values that the operator has not yet supplied.
|
|
399
|
+
/// The TUI / installer subscribes, prompts the user per field, and writes
|
|
400
|
+
/// the collected values back to the capsule's `[env]` configuration.
|
|
401
|
+
interface onboarding {
|
|
402
|
+
/// A capsule needs environment variables to be provided by the user.
|
|
403
|
+
record required {
|
|
404
|
+
/// The ID of the capsule requiring onboarding.
|
|
405
|
+
capsule-id: string,
|
|
406
|
+
/// Rich field descriptors for each missing env var.
|
|
407
|
+
fields: list<field>,
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/// A field descriptor for capsule onboarding.
|
|
411
|
+
record field {
|
|
412
|
+
/// The environment variable key.
|
|
413
|
+
key: string,
|
|
414
|
+
/// The prompt shown to the user.
|
|
415
|
+
prompt: string,
|
|
416
|
+
/// Optional description for additional context.
|
|
417
|
+
description: option<string>,
|
|
418
|
+
/// The input type for this field.
|
|
419
|
+
field-type: field-type,
|
|
420
|
+
/// Optional default value.
|
|
421
|
+
default: option<string>,
|
|
422
|
+
/// Placeholder hint text shown when the input is empty (e.g. `"sk-..."`).
|
|
423
|
+
placeholder: option<string>,
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/// The type of input expected for an onboarding field.
|
|
427
|
+
variant field-type {
|
|
428
|
+
/// Free-form text input.
|
|
429
|
+
text,
|
|
430
|
+
/// Masked secret input (stored in the SecretStore).
|
|
431
|
+
secret,
|
|
432
|
+
/// Selection from a fixed set of choices.
|
|
433
|
+
choice(list<string>),
|
|
434
|
+
/// Multi-value array input (user adds items one at a time).
|
|
435
|
+
array,
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// ── prompt ──────────────────────────────────────────────────────────
|
|
440
|
+
package astrid-bus:prompt@1.0.0;
|
|
441
|
+
|
|
442
|
+
/// Prompt interface — assembles LLM prompts with plugin hooks.
|
|
443
|
+
///
|
|
444
|
+
/// A capsule exporting this interface handles `prompt_builder.v1.assemble`
|
|
445
|
+
/// and publishes assembled prompts, with before/after hooks for context
|
|
446
|
+
/// injection by plugin capsules.
|
|
447
|
+
interface prompt {
|
|
448
|
+
use astrid-bus:types/types.{message, tool-definition};
|
|
449
|
+
|
|
450
|
+
/// Request to assemble a prompt for LLM generation.
|
|
451
|
+
record assemble-request {
|
|
452
|
+
messages: list<message>,
|
|
453
|
+
system-prompt: string,
|
|
454
|
+
request-id: string,
|
|
455
|
+
model: string,
|
|
456
|
+
provider: string,
|
|
457
|
+
session-id: option<string>,
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/// Assembled prompt ready for LLM.
|
|
461
|
+
record assemble-response {
|
|
462
|
+
system-prompt: string,
|
|
463
|
+
user-context-prefix: string,
|
|
464
|
+
request-id: string,
|
|
465
|
+
session-id: option<string>,
|
|
466
|
+
/// Collected tool schemas from tool-providing capsules.
|
|
467
|
+
tools: list<tool-definition>,
|
|
468
|
+
/// Session conversation history messages.
|
|
469
|
+
messages: list<message>,
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/// Hook payload sent before prompt build (plugins inject context).
|
|
473
|
+
record before-build-hook {
|
|
474
|
+
messages: list<message>,
|
|
475
|
+
system-prompt: string,
|
|
476
|
+
request-id: string,
|
|
477
|
+
model: string,
|
|
478
|
+
provider: string,
|
|
479
|
+
response-topic: string,
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/// Plugin response to before-build hook.
|
|
483
|
+
record before-build-hook-response {
|
|
484
|
+
prepend-system-context: option<string>,
|
|
485
|
+
append-system-context: option<string>,
|
|
486
|
+
system-prompt: option<string>,
|
|
487
|
+
prepend-context: option<string>,
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/// Notification after prompt is built.
|
|
491
|
+
record after-build-event {
|
|
492
|
+
system-prompt: string,
|
|
493
|
+
user-context-prefix: string,
|
|
494
|
+
request-id: string,
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// ── registry ──────────────────────────────────────────────────────────
|
|
499
|
+
package astrid-bus:registry@1.0.0;
|
|
500
|
+
|
|
501
|
+
/// Registry interface — LLM provider discovery and model management.
|
|
502
|
+
///
|
|
503
|
+
/// A capsule exporting this interface handles `registry.v1.*` requests,
|
|
504
|
+
/// discovers available LLM providers from loaded capsule metadata, and
|
|
505
|
+
/// manages the active model selection.
|
|
506
|
+
interface registry {
|
|
507
|
+
/// An available LLM provider entry.
|
|
508
|
+
record provider-entry {
|
|
509
|
+
/// Model ID (e.g. "gpt-5.4", "claude-sonnet-4-20250514").
|
|
510
|
+
id: string,
|
|
511
|
+
/// Human-readable description.
|
|
512
|
+
description: string,
|
|
513
|
+
/// IPC topic to publish LLM requests to.
|
|
514
|
+
request-topic: string,
|
|
515
|
+
/// IPC topic the provider streams responses on.
|
|
516
|
+
stream-topic: string,
|
|
517
|
+
/// Model capabilities (e.g. "text", "vision", "tools").
|
|
518
|
+
capabilities: list<string>,
|
|
519
|
+
/// Provider's context window size in tokens.
|
|
520
|
+
context-window: option<u64>,
|
|
521
|
+
/// Provider's max output tokens per request.
|
|
522
|
+
max-output-tokens: option<u64>,
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/// A single option in a selection picker.
|
|
526
|
+
record selection-option {
|
|
527
|
+
/// Machine-readable identifier sent back on the callback.
|
|
528
|
+
id: string,
|
|
529
|
+
/// Human-readable label shown in the picker.
|
|
530
|
+
label: string,
|
|
531
|
+
/// Optional description shown alongside the label.
|
|
532
|
+
description: option<string>,
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/// Capsule asking the user to choose from a set of options. Used by
|
|
536
|
+
/// the registry to drive the LLM-provider picker UI in the TUI.
|
|
537
|
+
/// Topic: `registry.v1.selection.required`.
|
|
538
|
+
record selection-required {
|
|
539
|
+
/// Correlation ID for the callback.
|
|
540
|
+
request-id: string,
|
|
541
|
+
/// Title or prompt shown above the list.
|
|
542
|
+
title: string,
|
|
543
|
+
/// The selectable options.
|
|
544
|
+
options: list<selection-option>,
|
|
545
|
+
/// IPC topic to publish the user's choice back on.
|
|
546
|
+
callback-topic: string,
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/// User's selection sent back to the requesting capsule.
|
|
550
|
+
/// Topic: `registry.v1.selection.callback` (or the `callback-topic`
|
|
551
|
+
/// declared in the matching `selection-required`).
|
|
552
|
+
record selection-callback {
|
|
553
|
+
/// Must match the `request-id` from the originating
|
|
554
|
+
/// `selection-required`.
|
|
555
|
+
request-id: string,
|
|
556
|
+
/// `id` of the chosen `selection-option`.
|
|
557
|
+
selected-id: string,
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// ── session ──────────────────────────────────────────────────────────
|
|
562
|
+
package astrid-bus:session@1.0.0;
|
|
563
|
+
|
|
564
|
+
/// Session protocol — persistent conversation history management.
|
|
565
|
+
///
|
|
566
|
+
/// A capsule exporting this interface handles `session.v1.request.*`
|
|
567
|
+
/// events and publishes `session.v1.response.*` replies scoped by
|
|
568
|
+
/// correlation ID.
|
|
569
|
+
interface session {
|
|
570
|
+
use astrid-bus:types/types.{message};
|
|
571
|
+
|
|
572
|
+
/// Request to fetch conversation history.
|
|
573
|
+
record get-messages-request {
|
|
574
|
+
session-id: string,
|
|
575
|
+
correlation-id: string,
|
|
576
|
+
append-before-read: option<list<message>>,
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
/// Response containing conversation history.
|
|
580
|
+
record get-messages-response {
|
|
581
|
+
correlation-id: string,
|
|
582
|
+
messages: list<message>,
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
/// Request to clear a session and start fresh.
|
|
586
|
+
record clear-request {
|
|
587
|
+
session-id: string,
|
|
588
|
+
correlation-id: string,
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
/// Response confirming session cleared.
|
|
592
|
+
record clear-response {
|
|
593
|
+
correlation-id: string,
|
|
594
|
+
new-session-id: string,
|
|
595
|
+
old-session-id: string,
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/// Fire-and-forget append to conversation history.
|
|
599
|
+
record append-request {
|
|
600
|
+
session-id: string,
|
|
601
|
+
messages: list<message>,
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/// Broadcast notification that a session was cleared. Distinct from
|
|
605
|
+
/// `clear-request`/`clear-response` (the request/response pair the
|
|
606
|
+
/// session capsule handles): this is a fan-out event the agent loop
|
|
607
|
+
/// publishes after a successful clear so unrelated capsules can drop
|
|
608
|
+
/// any per-session ephemeral state. Topic: `session.v1.clear`.
|
|
609
|
+
record session-cleared {
|
|
610
|
+
/// Session ID that was cleared.
|
|
611
|
+
session-id: string,
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// ── spark ──────────────────────────────────────────────────────────
|
|
616
|
+
package astrid-bus:spark@1.0.0;
|
|
617
|
+
|
|
618
|
+
/// Spark interface — agent persona and system prompt construction.
|
|
619
|
+
///
|
|
620
|
+
/// A capsule exporting this interface handles `identity.v1.request.build`
|
|
621
|
+
/// and publishes `identity.v1.response.ready` with the assembled system
|
|
622
|
+
/// prompt for the current workspace and session.
|
|
623
|
+
///
|
|
624
|
+
/// Named "spark" to distinguish from user identity management (the host
|
|
625
|
+
/// ABI `identity-*` functions for principal/account resolution).
|
|
626
|
+
interface spark {
|
|
627
|
+
/// Request to build the agent's system prompt.
|
|
628
|
+
record build-request {
|
|
629
|
+
workspace-root: string,
|
|
630
|
+
session-id: option<string>,
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/// Response with the assembled system prompt.
|
|
634
|
+
record build-response {
|
|
635
|
+
prompt: string,
|
|
636
|
+
session-id: option<string>,
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// ── system ──────────────────────────────────────────────────────────
|
|
641
|
+
package astrid-bus:system@1.0.0;
|
|
642
|
+
|
|
643
|
+
/// System interface — kernel-emitted lifecycle, health, and CLI envelopes.
|
|
644
|
+
///
|
|
645
|
+
/// The kernel publishes these on the IPC bus so capsules can react to
|
|
646
|
+
/// boot-completion, shutdown, watchdog ticks, bus health warnings, and
|
|
647
|
+
/// inbound CLI slash-commands.
|
|
648
|
+
interface system {
|
|
649
|
+
/// Published once after every capsule has reported ready, signalling
|
|
650
|
+
/// that the agent stack is fully online. Topic: `astrid.v1.capsules_loaded`.
|
|
651
|
+
record capsules-loaded {
|
|
652
|
+
/// IDs of every capsule that successfully loaded.
|
|
653
|
+
capsule-ids: list<string>,
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
/// Periodic kernel watchdog tick, used by long-lived capsules to age
|
|
657
|
+
/// out stale state (timeouts, abandoned correlations, etc.).
|
|
658
|
+
/// Topic: `astrid.v1.watchdog.tick`.
|
|
659
|
+
record watchdog-tick {
|
|
660
|
+
/// Wall-clock time of the tick (UNIX epoch milliseconds).
|
|
661
|
+
timestamp-ms: u64,
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
/// Warning emitted when a subscriber falls behind and the bus had to
|
|
665
|
+
/// drop messages. Subscribers can use this as a signal to drain or
|
|
666
|
+
/// resubscribe. Topic: `astrid.v1.event_bus.lagged`.
|
|
667
|
+
record event-bus-lagged {
|
|
668
|
+
/// Topic that lagged.
|
|
669
|
+
topic: string,
|
|
670
|
+
/// Number of messages dropped.
|
|
671
|
+
dropped: u64,
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
/// Cooperative restart signal — the kernel asks long-lived capsules
|
|
675
|
+
/// to flush ephemeral state and re-arm. Topic: `system.v1.lifecycle.restart`.
|
|
676
|
+
record lifecycle-restart {
|
|
677
|
+
/// Reason for the restart (e.g. `"config-reload"`, `"upgrade"`).
|
|
678
|
+
reason: string,
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
/// A slash-command typed by a human in an uplink. The CLI capsule
|
|
682
|
+
/// publishes this when the user enters `/<command> [args]`. Routed
|
|
683
|
+
/// to the capsule that registered the command name via its manifest.
|
|
684
|
+
/// Topic: `cli.v1.command.execute`.
|
|
685
|
+
record command-execute {
|
|
686
|
+
/// The command name (without the leading slash).
|
|
687
|
+
name: string,
|
|
688
|
+
/// JSON-encoded arguments (parsed by the receiving capsule).
|
|
689
|
+
arguments: string,
|
|
690
|
+
/// Session ID the command was issued in.
|
|
691
|
+
session-id: string,
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
// ── tool ──────────────────────────────────────────────────────────
|
|
696
|
+
package astrid-bus:tool@1.0.0;
|
|
697
|
+
|
|
698
|
+
/// Tool interface — dispatches tool calls to capsule handlers.
|
|
699
|
+
///
|
|
700
|
+
/// A capsule exporting this interface handles `tool.v1.request.execute`,
|
|
701
|
+
/// routes to the appropriate tool capsule via `tool.v1.execute.<name>`,
|
|
702
|
+
/// and collects results on `tool.v1.execute.*.result`.
|
|
703
|
+
interface tool {
|
|
704
|
+
use astrid-bus:types/types.{tool-call, tool-call-result, tool-definition};
|
|
705
|
+
|
|
706
|
+
/// Request to cancel in-flight tool executions.
|
|
707
|
+
record cancel-request {
|
|
708
|
+
call-ids: list<string>,
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
/// Request asking a tool-providing capsule to enumerate its tools.
|
|
712
|
+
/// Topic: `tool.v1.request.describe`. Empty payload — every responder
|
|
713
|
+
/// returns its full tool list. Routed by the SDK macro from
|
|
714
|
+
/// `#[astrid::tool(...)]` attributes.
|
|
715
|
+
record describe-request {
|
|
716
|
+
/// Correlation ID for the response. The capsule replies on
|
|
717
|
+
/// `tool.v1.response.describe.<correlation-id>`.
|
|
718
|
+
correlation-id: string,
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
/// Response listing the tools a capsule provides.
|
|
722
|
+
/// Topic: `tool.v1.response.describe.<correlation-id>`.
|
|
723
|
+
record describe-response {
|
|
724
|
+
/// Must match the `correlation-id` from the originating request.
|
|
725
|
+
correlation-id: string,
|
|
726
|
+
/// The capsule's exposed tools.
|
|
727
|
+
tools: list<tool-definition>,
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
// ── user ──────────────────────────────────────────────────────────
|
|
732
|
+
package astrid-bus:user@1.0.0;
|
|
733
|
+
|
|
734
|
+
/// User interface — input envelopes from a human via an uplink.
|
|
735
|
+
///
|
|
736
|
+
/// Uplink capsules (CLI, Telegram, Discord, etc.) publish `user.v1.prompt`
|
|
737
|
+
/// when the human types a message. The agent loop subscribes to drive a
|
|
738
|
+
/// new turn.
|
|
739
|
+
interface user {
|
|
740
|
+
/// A prompt typed by a human via an uplink.
|
|
741
|
+
record prompt {
|
|
742
|
+
/// The raw text input.
|
|
743
|
+
text: string,
|
|
744
|
+
/// Session ID for conversation continuity. Defaults to `"default"`.
|
|
745
|
+
session-id: string,
|
|
746
|
+
/// Optional extra context (JSON-encoded) — e.g. attachments,
|
|
747
|
+
/// metadata, or per-turn flags the uplink wants to forward.
|
|
748
|
+
context: option<string>,
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
// ── users ──────────────────────────────────────────────────────────
|
|
753
|
+
package astrid-bus:users@1.0.0;
|
|
754
|
+
|
|
755
|
+
/// Users interface — within-principal user identity store.
|
|
756
|
+
///
|
|
757
|
+
/// Owns the cross-platform user identity mapping for a single Astrid
|
|
758
|
+
/// principal. A capsule exporting this interface (the `users` capsule)
|
|
759
|
+
/// handles `users.v1.<op>.request` events and publishes
|
|
760
|
+
/// `users.v1.<op>.response` replies correlated by `correlation-id`.
|
|
761
|
+
///
|
|
762
|
+
/// This is distinct from the `user` interface (`user.v1.prompt`), which
|
|
763
|
+
/// carries inbound human prompts from uplinks. Naming separation:
|
|
764
|
+
///
|
|
765
|
+
/// - `user` (singular) — a single human typing into an uplink.
|
|
766
|
+
/// - `users` (plural) — the identity directory that maps platform
|
|
767
|
+
/// IDs to canonical AstridUserIds.
|
|
768
|
+
///
|
|
769
|
+
/// Kernel-side principal tenancy is unaffected: this interface covers
|
|
770
|
+
/// user identity *within* one principal's KV scope only. Different
|
|
771
|
+
/// principals have independent stores.
|
|
772
|
+
///
|
|
773
|
+
/// ## Two-layer identity model
|
|
774
|
+
///
|
|
775
|
+
/// 1. **Identity layer** — `frontend-link` records map a platform's
|
|
776
|
+
/// stable opaque ID (Discord snowflake, Telegram user-id, Nostr
|
|
777
|
+
/// pubkey) to a canonical `astrid-user-id`. Global per
|
|
778
|
+
/// `(platform, platform-instance, platform-user-id)` triple.
|
|
779
|
+
/// 2. **Presentation layer** — `context-identity` records overlay a
|
|
780
|
+
/// per-context display name on a given identity link. `context-id`
|
|
781
|
+
/// is opaque to the capsule — uplinks define their own scheme
|
|
782
|
+
/// (`"guild:123"`, `"room:!abc:matrix.org"`, `"channel:C01234"`).
|
|
783
|
+
/// Used for "how should the agent address this user *right now*"
|
|
784
|
+
/// when the platform supports per-context names (Discord guild
|
|
785
|
+
/// nicknames, Matrix room display names, Slack channel profiles).
|
|
786
|
+
///
|
|
787
|
+
/// `resolve` is context-aware: it returns a layered `display-name`
|
|
788
|
+
/// in one round-trip — context override > link's platform name >
|
|
789
|
+
/// AstridUser's canonical Astrid name.
|
|
790
|
+
interface users {
|
|
791
|
+
// ── Envelope ──────────────────────────────────────────────────
|
|
792
|
+
|
|
793
|
+
/// Multi-tenant request envelope.
|
|
794
|
+
///
|
|
795
|
+
/// Carries provenance ("which uplink, on behalf of which end-user")
|
|
796
|
+
/// and a correlation token so the originating uplink can match the
|
|
797
|
+
/// response back to the inflight request among many concurrent
|
|
798
|
+
/// end-users on a single principal.
|
|
799
|
+
///
|
|
800
|
+
/// Pending the broader admin-API correlation convention (kernel
|
|
801
|
+
/// issue #748), `source` lives on this interface; once that
|
|
802
|
+
/// convention formalizes a shared envelope, this record migrates
|
|
803
|
+
/// to the shared location and the records below import it instead.
|
|
804
|
+
record source {
|
|
805
|
+
/// Originating uplink capsule — e.g. `"cli"`, `"sphere"`,
|
|
806
|
+
/// `"discord"`, `"telegram"`. Identifies the capsule making
|
|
807
|
+
/// the request (for audit and routing); distinct from
|
|
808
|
+
/// `frontend-link.platform`, which identifies the external
|
|
809
|
+
/// service being linked.
|
|
810
|
+
uplink: string,
|
|
811
|
+
/// AstridUserId of the requester when known. `None` for
|
|
812
|
+
/// system flows or pre-login pairing requests.
|
|
813
|
+
user-id: option<string>,
|
|
814
|
+
/// Correlation token. The requester subscribes to the response
|
|
815
|
+
/// topic and filters incoming responses by this string.
|
|
816
|
+
correlation-id: string,
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
// ── Domain records ────────────────────────────────────────────
|
|
820
|
+
|
|
821
|
+
/// Canonical Astrid user identity.
|
|
822
|
+
///
|
|
823
|
+
/// One record per human within the principal's user directory.
|
|
824
|
+
/// `id` is the stable UUID — every `frontend-link` points at this.
|
|
825
|
+
record astrid-user {
|
|
826
|
+
/// UUID v4 string (lowercase, hyphenated). Stable for the
|
|
827
|
+
/// lifetime of the user; never reused.
|
|
828
|
+
id: string,
|
|
829
|
+
/// Optional ed25519 public key (32 bytes raw). Set via
|
|
830
|
+
/// `set-public-key`; used by future verification flows.
|
|
831
|
+
public-key: option<list<u8>>,
|
|
832
|
+
/// Operator/canonical Astrid-side display name. Mutable via
|
|
833
|
+
/// `set-display-name`. Distinct from any platform-side name.
|
|
834
|
+
display-name: option<string>,
|
|
835
|
+
/// Creation timestamp, RFC 3339 string.
|
|
836
|
+
created-at: string,
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
/// A platform-to-Astrid-user identity link.
|
|
840
|
+
///
|
|
841
|
+
/// Composite key: `(platform, platform-instance?, platform-user-id)`.
|
|
842
|
+
/// Exactly one link may exist per triple; relinking overwrites.
|
|
843
|
+
record frontend-link {
|
|
844
|
+
/// Normalized platform name (lowercased, trimmed) —
|
|
845
|
+
/// e.g. `"discord"`, `"telegram"`, `"nostr"`, `"slack"`,
|
|
846
|
+
/// `"matrix"`, `"email"`, `"x"`, `"github"`.
|
|
847
|
+
platform: string,
|
|
848
|
+
/// Optional platform instance for federated / multi-tenant
|
|
849
|
+
/// platforms: Slack workspace, IRC network, XMPP server,
|
|
850
|
+
/// Mattermost instance. `None` for globally-scoped platforms
|
|
851
|
+
/// (Discord, Telegram, X) and for federated platforms whose
|
|
852
|
+
/// identifier already embeds the homeserver in the user-id
|
|
853
|
+
/// (Matrix `@alice:server.org`, Mastodon `@a@server.social`).
|
|
854
|
+
platform-instance: option<string>,
|
|
855
|
+
/// Platform-specific stable opaque user identifier
|
|
856
|
+
/// (Discord snowflake, Telegram int64, Slack `U...`, Nostr
|
|
857
|
+
/// npub, email address, E.164 phone). Never the user's
|
|
858
|
+
/// mutable handle.
|
|
859
|
+
platform-user-id: string,
|
|
860
|
+
/// The Astrid user UUID this platform identity maps to.
|
|
861
|
+
astrid-user-id: string,
|
|
862
|
+
/// When this link was created (RFC 3339). Refreshed on
|
|
863
|
+
/// upsert relink.
|
|
864
|
+
linked-at: string,
|
|
865
|
+
/// How this link was established — `"admin"`, `"system"`,
|
|
866
|
+
/// `"chat_command"`, `"passkey"`, `"self_declared"`, etc.
|
|
867
|
+
/// Recorded for audit. Free-form string.
|
|
868
|
+
method: string,
|
|
869
|
+
/// Platform's *global* display name at link time —
|
|
870
|
+
/// e.g. Discord global username `"alice"`, Telegram
|
|
871
|
+
/// `@alice`, X handle. Mutable: re-link to refresh.
|
|
872
|
+
/// Distinct from any per-context override
|
|
873
|
+
/// (see `context-identity`) and from `astrid-user.display-name`
|
|
874
|
+
/// (the operator-set canonical Astrid name).
|
|
875
|
+
display-name: option<string>,
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
/// Per-context display-name overlay on a `frontend-link`.
|
|
879
|
+
///
|
|
880
|
+
/// One row per `(platform, platform-instance?, platform-user-id, context-id)`
|
|
881
|
+
/// tuple. The capsule does NOT parse `context-id`; uplinks define
|
|
882
|
+
/// per-platform schemes. Common conventions:
|
|
883
|
+
///
|
|
884
|
+
/// - Discord per-guild nickname: `context-id = "guild:{guild-id}"`
|
|
885
|
+
/// - Matrix per-room display name: `context-id = "room:{room-id}"`
|
|
886
|
+
/// - Slack per-channel profile: `context-id = "channel:{channel-id}"`
|
|
887
|
+
/// (workspace lives in `platform-instance`)
|
|
888
|
+
/// - Mattermost per-team: `context-id = "team:{team-id}"`
|
|
889
|
+
/// - Single-context platforms (X, SMS): no rows ever created
|
|
890
|
+
///
|
|
891
|
+
/// Per-context attributes beyond `display-name` (roles, custom
|
|
892
|
+
/// fields, preferences) intentionally do NOT live here. They
|
|
893
|
+
/// belong in memory or a future authz capsule.
|
|
894
|
+
record context-identity {
|
|
895
|
+
platform: string,
|
|
896
|
+
platform-instance: option<string>,
|
|
897
|
+
platform-user-id: string,
|
|
898
|
+
/// Opaque per-platform context key.
|
|
899
|
+
context-id: string,
|
|
900
|
+
/// What this user is called *in this context*.
|
|
901
|
+
display-name: string,
|
|
902
|
+
/// Last update timestamp (RFC 3339).
|
|
903
|
+
updated-at: string,
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
// ── Pagination ─────────────────────────────────────────────────
|
|
907
|
+
//
|
|
908
|
+
// Paginated topics use opaque `cursor: option<string>` tokens.
|
|
909
|
+
// Callers treat the value as a black box — pass `None` on the
|
|
910
|
+
// first request, then loop while the response's `next-cursor`
|
|
911
|
+
// is `Some(token)`, passing that token back unchanged. The
|
|
912
|
+
// capsule defines the format. (Modelled as bare `option<string>`
|
|
913
|
+
// rather than a `type cursor = string` alias for codegen
|
|
914
|
+
// portability — wit-bindgen handles aliases but our JS codegen
|
|
915
|
+
// does not.)
|
|
916
|
+
|
|
917
|
+
// ── Resolve (context-aware) ───────────────────────────────────
|
|
918
|
+
|
|
919
|
+
/// Resolve a platform identity to an Astrid user, optionally
|
|
920
|
+
/// scoped to a context for display-name layering.
|
|
921
|
+
/// Topic: `users.v1.resolve.request`.
|
|
922
|
+
record resolve-request {
|
|
923
|
+
source: source,
|
|
924
|
+
platform: string,
|
|
925
|
+
platform-instance: option<string>,
|
|
926
|
+
platform-user-id: string,
|
|
927
|
+
/// Optional context. When set, the response's `display-name`
|
|
928
|
+
/// uses the per-context override if one exists. When None,
|
|
929
|
+
/// only the link-global and canonical fallbacks apply.
|
|
930
|
+
context-id: option<string>,
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
/// Response for resolve.
|
|
934
|
+
/// Topic: `users.v1.resolve.response`.
|
|
935
|
+
///
|
|
936
|
+
/// A clean "no link exists" is `user = none` with `error = none`.
|
|
937
|
+
/// Validation or storage failures populate `error` and leave the
|
|
938
|
+
/// other success fields empty.
|
|
939
|
+
record resolve-response {
|
|
940
|
+
correlation-id: string,
|
|
941
|
+
user: option<astrid-user>,
|
|
942
|
+
/// The right name to address this user. Resolution order
|
|
943
|
+
/// (first non-empty wins):
|
|
944
|
+
/// 1. `context-identity.display-name` (if `context-id` was
|
|
945
|
+
/// provided in the request and an override exists)
|
|
946
|
+
/// 2. `frontend-link.display-name` (the platform-side name)
|
|
947
|
+
/// 3. `astrid-user.display-name` (the canonical Astrid name)
|
|
948
|
+
/// `None` if none of the three layers carry a name.
|
|
949
|
+
display-name: option<string>,
|
|
950
|
+
/// Which layer produced `display-name`. One of `"context"`,
|
|
951
|
+
/// `"link"`, `"canonical"`. `None` when `display-name` is `None`.
|
|
952
|
+
display-name-source: option<string>,
|
|
953
|
+
error: option<string>,
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
// ── Link ───────────────────────────────────────────────────────
|
|
957
|
+
|
|
958
|
+
/// Link a platform identity to an existing Astrid user. Upsert
|
|
959
|
+
/// semantics: an existing link for the same
|
|
960
|
+
/// `(platform, platform-instance?, platform-user-id)` is overwritten.
|
|
961
|
+
/// Topic: `users.v1.link.request`.
|
|
962
|
+
record link-request {
|
|
963
|
+
source: source,
|
|
964
|
+
platform: string,
|
|
965
|
+
platform-instance: option<string>,
|
|
966
|
+
platform-user-id: string,
|
|
967
|
+
/// Target Astrid user UUID. Must already exist.
|
|
968
|
+
astrid-user-id: string,
|
|
969
|
+
/// Audit string — how this link was established.
|
|
970
|
+
method: string,
|
|
971
|
+
/// Optional platform-side global display name at link time.
|
|
972
|
+
/// Stored on the resulting `frontend-link` for later
|
|
973
|
+
/// resolution / display.
|
|
974
|
+
display-name: option<string>,
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
/// Response for link.
|
|
978
|
+
/// Topic: `users.v1.link.response`.
|
|
979
|
+
record link-response {
|
|
980
|
+
correlation-id: string,
|
|
981
|
+
link: option<frontend-link>,
|
|
982
|
+
error: option<string>,
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
// ── Unlink ─────────────────────────────────────────────────────
|
|
986
|
+
|
|
987
|
+
/// Remove a platform link. Also clears any
|
|
988
|
+
/// `context-identity` overlays attached to it (cascading).
|
|
989
|
+
/// Topic: `users.v1.unlink.request`.
|
|
990
|
+
record unlink-request {
|
|
991
|
+
source: source,
|
|
992
|
+
platform: string,
|
|
993
|
+
platform-instance: option<string>,
|
|
994
|
+
platform-user-id: string,
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
/// Response for unlink.
|
|
998
|
+
/// Topic: `users.v1.unlink.response`.
|
|
999
|
+
record unlink-response {
|
|
1000
|
+
correlation-id: string,
|
|
1001
|
+
/// `true` if a link existed and was removed; `false` for a
|
|
1002
|
+
/// no-op delete (link was already absent).
|
|
1003
|
+
removed: bool,
|
|
1004
|
+
error: option<string>,
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
// ── Create ─────────────────────────────────────────────────────
|
|
1008
|
+
|
|
1009
|
+
/// Create a new Astrid user.
|
|
1010
|
+
/// Topic: `users.v1.create.request`.
|
|
1011
|
+
record create-request {
|
|
1012
|
+
source: source,
|
|
1013
|
+
/// Optional canonical display name. Rejected if it contains
|
|
1014
|
+
/// `/` or `\0`.
|
|
1015
|
+
display-name: option<string>,
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
/// Response for create.
|
|
1019
|
+
/// Topic: `users.v1.create.response`.
|
|
1020
|
+
record create-response {
|
|
1021
|
+
correlation-id: string,
|
|
1022
|
+
user: option<astrid-user>,
|
|
1023
|
+
error: option<string>,
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
// ── Mutate canonical fields on an AstridUser ──────────────────
|
|
1027
|
+
|
|
1028
|
+
/// Change an `AstridUser`'s canonical `display-name` without
|
|
1029
|
+
/// rotating the UUID or breaking any links.
|
|
1030
|
+
/// Topic: `users.v1.set_display_name.request`.
|
|
1031
|
+
///
|
|
1032
|
+
/// `display-name = None` clears the name. To leave it unchanged,
|
|
1033
|
+
/// don't issue the request.
|
|
1034
|
+
record set-display-name-request {
|
|
1035
|
+
source: source,
|
|
1036
|
+
astrid-user-id: string,
|
|
1037
|
+
display-name: option<string>,
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
/// Response for set-display-name.
|
|
1041
|
+
/// Topic: `users.v1.set_display_name.response`.
|
|
1042
|
+
record set-display-name-response {
|
|
1043
|
+
correlation-id: string,
|
|
1044
|
+
user: option<astrid-user>,
|
|
1045
|
+
error: option<string>,
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
/// Set or clear an `AstridUser`'s `public-key` without rotating
|
|
1049
|
+
/// the UUID.
|
|
1050
|
+
/// Topic: `users.v1.set_public_key.request`.
|
|
1051
|
+
///
|
|
1052
|
+
/// `public-key = None` clears the key.
|
|
1053
|
+
record set-public-key-request {
|
|
1054
|
+
source: source,
|
|
1055
|
+
astrid-user-id: string,
|
|
1056
|
+
public-key: option<list<u8>>,
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
/// Response for set-public-key.
|
|
1060
|
+
/// Topic: `users.v1.set_public_key.response`.
|
|
1061
|
+
record set-public-key-response {
|
|
1062
|
+
correlation-id: string,
|
|
1063
|
+
user: option<astrid-user>,
|
|
1064
|
+
error: option<string>,
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
// ── Links (list every link for one user) ──────────────────────
|
|
1068
|
+
|
|
1069
|
+
/// List every platform link for one Astrid user.
|
|
1070
|
+
/// Topic: `users.v1.links.request`.
|
|
1071
|
+
record links-request {
|
|
1072
|
+
source: source,
|
|
1073
|
+
astrid-user-id: string,
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
/// Response for links.
|
|
1077
|
+
/// Topic: `users.v1.links.response`.
|
|
1078
|
+
record links-response {
|
|
1079
|
+
correlation-id: string,
|
|
1080
|
+
links: list<frontend-link>,
|
|
1081
|
+
error: option<string>,
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
// ── Get (lookup user by UUID) ─────────────────────────────────
|
|
1085
|
+
|
|
1086
|
+
/// Fetch a user record by UUID.
|
|
1087
|
+
/// Topic: `users.v1.get.request`.
|
|
1088
|
+
record get-request {
|
|
1089
|
+
source: source,
|
|
1090
|
+
astrid-user-id: string,
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
/// Response for get.
|
|
1094
|
+
/// Topic: `users.v1.get.response`.
|
|
1095
|
+
record get-response {
|
|
1096
|
+
correlation-id: string,
|
|
1097
|
+
user: option<astrid-user>,
|
|
1098
|
+
error: option<string>,
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
// ── Delete (admin) ────────────────────────────────────────────
|
|
1102
|
+
|
|
1103
|
+
/// Delete a user, every link pointing at it, and every
|
|
1104
|
+
/// per-context overlay tied to those links.
|
|
1105
|
+
/// Idempotent — deleting an absent UUID returns `deleted = false`.
|
|
1106
|
+
/// Topic: `users.v1.delete.request`.
|
|
1107
|
+
record delete-request {
|
|
1108
|
+
source: source,
|
|
1109
|
+
astrid-user-id: string,
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
/// Response for delete.
|
|
1113
|
+
/// Topic: `users.v1.delete.response`.
|
|
1114
|
+
record delete-response {
|
|
1115
|
+
correlation-id: string,
|
|
1116
|
+
/// `true` when a user record existed and was deleted.
|
|
1117
|
+
deleted: bool,
|
|
1118
|
+
error: option<string>,
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
// ── List users (paginated) ────────────────────────────────────
|
|
1122
|
+
|
|
1123
|
+
/// List every user record in the principal's store. Paginated.
|
|
1124
|
+
/// Topic: `users.v1.list.request`.
|
|
1125
|
+
record list-request {
|
|
1126
|
+
source: source,
|
|
1127
|
+
/// Cursor from a prior `list-response.next-cursor`. `None`
|
|
1128
|
+
/// on the first call.
|
|
1129
|
+
cursor: option<string>,
|
|
1130
|
+
/// Maximum users to return. `None` lets the capsule pick a
|
|
1131
|
+
/// sensible default (current impl: 100).
|
|
1132
|
+
limit: option<u32>,
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
/// Response for list.
|
|
1136
|
+
/// Topic: `users.v1.list.response`.
|
|
1137
|
+
record list-response {
|
|
1138
|
+
correlation-id: string,
|
|
1139
|
+
users: list<astrid-user>,
|
|
1140
|
+
/// Pass back as `list-request.cursor` to get the next page.
|
|
1141
|
+
/// `None` when no more pages remain.
|
|
1142
|
+
next-cursor: option<string>,
|
|
1143
|
+
error: option<string>,
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
// ── Context: per-context display-name overlay ─────────────────
|
|
1147
|
+
|
|
1148
|
+
/// Set (or upsert) a per-context display-name override for a
|
|
1149
|
+
/// linked platform identity. The underlying `frontend-link` must
|
|
1150
|
+
/// already exist — context overlays cannot dangle.
|
|
1151
|
+
/// Topic: `users.v1.context.set.request`.
|
|
1152
|
+
record context-set-request {
|
|
1153
|
+
source: source,
|
|
1154
|
+
platform: string,
|
|
1155
|
+
platform-instance: option<string>,
|
|
1156
|
+
platform-user-id: string,
|
|
1157
|
+
context-id: string,
|
|
1158
|
+
display-name: string,
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
/// Response for context-set.
|
|
1162
|
+
/// Topic: `users.v1.context.set.response`.
|
|
1163
|
+
record context-set-response {
|
|
1164
|
+
correlation-id: string,
|
|
1165
|
+
context-identity: option<context-identity>,
|
|
1166
|
+
error: option<string>,
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
/// Clear a per-context display-name override. Leaves the link
|
|
1170
|
+
/// itself and the global link-level display-name untouched.
|
|
1171
|
+
/// Topic: `users.v1.context.clear.request`.
|
|
1172
|
+
record context-clear-request {
|
|
1173
|
+
source: source,
|
|
1174
|
+
platform: string,
|
|
1175
|
+
platform-instance: option<string>,
|
|
1176
|
+
platform-user-id: string,
|
|
1177
|
+
context-id: string,
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
/// Response for context-clear.
|
|
1181
|
+
/// Topic: `users.v1.context.clear.response`.
|
|
1182
|
+
record context-clear-response {
|
|
1183
|
+
correlation-id: string,
|
|
1184
|
+
/// `true` if an overlay existed and was removed; `false` for
|
|
1185
|
+
/// a no-op clear.
|
|
1186
|
+
removed: bool,
|
|
1187
|
+
error: option<string>,
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
/// Fetch the per-context override for one
|
|
1191
|
+
/// `(link, context-id)` pair. Useful when the caller wants the
|
|
1192
|
+
/// raw override without the `resolve`-style fallback chain.
|
|
1193
|
+
/// Topic: `users.v1.context.get.request`.
|
|
1194
|
+
record context-get-request {
|
|
1195
|
+
source: source,
|
|
1196
|
+
platform: string,
|
|
1197
|
+
platform-instance: option<string>,
|
|
1198
|
+
platform-user-id: string,
|
|
1199
|
+
context-id: string,
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
/// Response for context-get.
|
|
1203
|
+
/// Topic: `users.v1.context.get.response`.
|
|
1204
|
+
record context-get-response {
|
|
1205
|
+
correlation-id: string,
|
|
1206
|
+
context-identity: option<context-identity>,
|
|
1207
|
+
/// The same user resolved through the underlying link, when
|
|
1208
|
+
/// it exists. Saves the caller a separate `resolve` call.
|
|
1209
|
+
astrid-user-id: option<string>,
|
|
1210
|
+
error: option<string>,
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
/// List every context overlay attached to one Astrid user, across
|
|
1214
|
+
/// platforms and contexts. Paginated.
|
|
1215
|
+
/// Topic: `users.v1.context.list_for_user.request`.
|
|
1216
|
+
record context-list-for-user-request {
|
|
1217
|
+
source: source,
|
|
1218
|
+
astrid-user-id: string,
|
|
1219
|
+
cursor: option<string>,
|
|
1220
|
+
limit: option<u32>,
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
/// Response for context-list-for-user.
|
|
1224
|
+
/// Topic: `users.v1.context.list_for_user.response`.
|
|
1225
|
+
record context-list-for-user-response {
|
|
1226
|
+
correlation-id: string,
|
|
1227
|
+
contexts: list<context-identity>,
|
|
1228
|
+
next-cursor: option<string>,
|
|
1229
|
+
error: option<string>,
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
/// List every user known in one specific context (e.g. every
|
|
1233
|
+
/// member of one Discord guild who has a per-guild nickname
|
|
1234
|
+
/// recorded). Returns the context overlay rows plus the resolved
|
|
1235
|
+
/// `astrid-user-id` for each, so the caller can build a member
|
|
1236
|
+
/// roster in one paginated call. Paginated.
|
|
1237
|
+
/// Topic: `users.v1.context.list_in_context.request`.
|
|
1238
|
+
record context-list-in-context-request {
|
|
1239
|
+
source: source,
|
|
1240
|
+
platform: string,
|
|
1241
|
+
platform-instance: option<string>,
|
|
1242
|
+
context-id: string,
|
|
1243
|
+
cursor: option<string>,
|
|
1244
|
+
limit: option<u32>,
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
/// One row of the context-list-in-context response.
|
|
1248
|
+
record context-member {
|
|
1249
|
+
context-identity: context-identity,
|
|
1250
|
+
/// Resolved Astrid user UUID via the underlying link, when
|
|
1251
|
+
/// the link still exists. `None` indicates a stale overlay
|
|
1252
|
+
/// (link was unlinked but overlay wasn't cleared — the
|
|
1253
|
+
/// capsule cleans these on unlink, so this should be rare).
|
|
1254
|
+
astrid-user-id: option<string>,
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
/// Response for context-list-in-context.
|
|
1258
|
+
/// Topic: `users.v1.context.list_in_context.response`.
|
|
1259
|
+
record context-list-in-context-response {
|
|
1260
|
+
correlation-id: string,
|
|
1261
|
+
members: list<context-member>,
|
|
1262
|
+
next-cursor: option<string>,
|
|
1263
|
+
error: option<string>,
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
|