@oneie/sdk 0.10.0 → 0.11.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/dist/billing.d.ts +49 -0
- package/dist/billing.d.ts.map +1 -0
- package/dist/billing.js +49 -0
- package/dist/billing.js.map +1 -0
- package/dist/broadcast.d.ts +37 -0
- package/dist/broadcast.d.ts.map +1 -0
- package/dist/broadcast.js +7 -0
- package/dist/broadcast.js.map +1 -0
- package/dist/client.d.ts +1 -32
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +0 -25
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/market.d.ts +63 -0
- package/dist/market.d.ts.map +1 -0
- package/dist/market.js +92 -0
- package/dist/market.js.map +1 -0
- package/dist/meta.d.ts +1 -1
- package/dist/openapi.d.ts +1 -1
- package/dist/openapi.js +1 -1
- package/dist/receivers.d.ts +834 -80
- package/dist/receivers.d.ts.map +1 -1
- package/dist/receivers.js +890 -75
- package/dist/receivers.js.map +1 -1
- package/dist/schemas.d.ts +52 -0
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +40 -0
- package/dist/schemas.js.map +1 -1
- package/dist/types.d.ts +5 -5
- package/dist/types.d.ts.map +1 -1
- package/package.json +9 -1
package/dist/receivers.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { AgentActionResponseSchema, AgentStatusResponseSchema, CapabilityItemSchema, PayResponseSchema, RegisterResponseSchema, StatsSchema, } from "./schemas.js";
|
|
2
|
+
import { AgentActionResponseSchema, AgentStatusResponseSchema, CapabilityItemSchema, PayResponseSchema, RegisterResponseSchema, StatsSchema, StepKind, WorkflowDiffSchema, } from "./schemas.js";
|
|
3
3
|
/**
|
|
4
4
|
* Declare a receiver contract. Identity at runtime — its only job is to pin the
|
|
5
5
|
* `Req`/`Res` generics so the catalog infers payload + outcome types.
|
|
@@ -18,6 +18,13 @@ const ok = z.object({ ok: z.boolean() });
|
|
|
18
18
|
*/
|
|
19
19
|
export const RECEIVERS = {
|
|
20
20
|
// ── Spine (non-world) — contracts only this cycle; route-wiring lands in C4 ──
|
|
21
|
+
"agent:enroll": receiver({
|
|
22
|
+
receiver: "agent:enroll",
|
|
23
|
+
summary: "Self-enroll as an agent — mint identity + API key with no prior session",
|
|
24
|
+
request: z.object({ name: z.string(), capabilities: z.array(z.string()).optional() }),
|
|
25
|
+
response: z.object({ ok: z.literal(true), actorId: z.string(), slug: z.string(), apiKey: z.string(), credits: z.number() }),
|
|
26
|
+
effect: "ask", auth: "public", reversible: false, idempotent: false,
|
|
27
|
+
}),
|
|
21
28
|
"auth:agent": receiver({
|
|
22
29
|
receiver: "auth:agent",
|
|
23
30
|
summary: "Become an actor — mint a uid, wallet, and scoped API key",
|
|
@@ -150,6 +157,50 @@ export const RECEIVERS = {
|
|
|
150
157
|
request: z.object({ aid: z.string(), name: z.string().optional(), tags: z.array(z.string()).optional(), prompt: z.string().optional(), model: z.string().optional() }),
|
|
151
158
|
response: ok, effect: "ask", auth: "manage_actors",
|
|
152
159
|
}),
|
|
160
|
+
"world:update-contact": receiver({
|
|
161
|
+
receiver: "world:update-contact",
|
|
162
|
+
summary: "Update an actor's contact/profile attributes — identity, contact details, professional, personal, CRM metrics",
|
|
163
|
+
request: z.object({
|
|
164
|
+
aid: z.string(),
|
|
165
|
+
// identity
|
|
166
|
+
name: z.string().optional(),
|
|
167
|
+
firstName: z.string().optional(),
|
|
168
|
+
lastName: z.string().optional(),
|
|
169
|
+
nickname: z.string().optional(),
|
|
170
|
+
title: z.string().optional(),
|
|
171
|
+
avatar: z.string().optional(),
|
|
172
|
+
bio: z.string().optional(),
|
|
173
|
+
// contact
|
|
174
|
+
email: z.string().optional(),
|
|
175
|
+
phone: z.string().optional(),
|
|
176
|
+
website: z.string().optional(),
|
|
177
|
+
// professional
|
|
178
|
+
jobTitle: z.string().optional(),
|
|
179
|
+
company: z.string().optional(),
|
|
180
|
+
department: z.string().optional(),
|
|
181
|
+
role: z.string().optional(),
|
|
182
|
+
// personal
|
|
183
|
+
birthday: z.string().optional(),
|
|
184
|
+
gender: z.string().optional(),
|
|
185
|
+
nationality: z.string().optional(),
|
|
186
|
+
timezone: z.string().optional(),
|
|
187
|
+
// address
|
|
188
|
+
street: z.string().optional(),
|
|
189
|
+
city: z.string().optional(),
|
|
190
|
+
region: z.string().optional(),
|
|
191
|
+
postcode: z.string().optional(),
|
|
192
|
+
country: z.string().optional(),
|
|
193
|
+
// crm
|
|
194
|
+
lifecycle: z.string().optional(),
|
|
195
|
+
source: z.string().optional(),
|
|
196
|
+
// numeric crm metrics
|
|
197
|
+
value: z.number().optional(),
|
|
198
|
+
fitScore: z.number().optional(),
|
|
199
|
+
nps: z.number().optional(),
|
|
200
|
+
csat: z.number().optional(),
|
|
201
|
+
}),
|
|
202
|
+
response: ok, effect: "ask", auth: "manage_actors",
|
|
203
|
+
}),
|
|
153
204
|
"world:remove-actor": receiver({
|
|
154
205
|
receiver: "world:remove-actor",
|
|
155
206
|
summary: "Delete an actor",
|
|
@@ -157,15 +208,38 @@ export const RECEIVERS = {
|
|
|
157
208
|
}),
|
|
158
209
|
"world:create-key": receiver({
|
|
159
210
|
receiver: "world:create-key",
|
|
160
|
-
summary: "Mint a scoped API key for an actor",
|
|
161
|
-
request: z.object({
|
|
162
|
-
|
|
163
|
-
|
|
211
|
+
summary: "Mint a scoped API key (PAT) for an actor you own; scope is capped at the actor's role, optional expiresIn (seconds)",
|
|
212
|
+
request: z.object({
|
|
213
|
+
actor: z.string(),
|
|
214
|
+
scope: z.enum(["read", "write", "admin"]).optional(),
|
|
215
|
+
label: z.string().optional(),
|
|
216
|
+
expiresIn: z.number().int().positive().optional(),
|
|
217
|
+
}),
|
|
218
|
+
// Self-service: any authenticated member can mint a key for an actor they own
|
|
219
|
+
// (requireActorOwner is the gate). The scope ceiling prevents privilege escalation.
|
|
220
|
+
response: z.object({ key: z.string(), keyId: z.string(), scope: z.string() }),
|
|
221
|
+
effect: "ask", auth: "member", scope: "write", reversible: false,
|
|
222
|
+
examples: [{ actor: "01ABC", scope: "write", label: "cli" }],
|
|
223
|
+
}),
|
|
224
|
+
"world:list-keys": receiver({
|
|
225
|
+
receiver: "world:list-keys",
|
|
226
|
+
summary: "List active API keys (metadata only — never the secret) for an actor you own",
|
|
227
|
+
request: z.object({ actor: z.string() }),
|
|
228
|
+
response: z.object({
|
|
229
|
+
keys: z.array(z.object({
|
|
230
|
+
keyId: z.string(),
|
|
231
|
+
label: z.string().nullable(),
|
|
232
|
+
scope: z.string(),
|
|
233
|
+
createdAt: z.number(),
|
|
234
|
+
validTo: z.number().nullable(),
|
|
235
|
+
})),
|
|
236
|
+
}),
|
|
237
|
+
effect: "ask", auth: "member", scope: "read", cost: "free", idempotent: true,
|
|
164
238
|
}),
|
|
165
239
|
"world:revoke-key": receiver({
|
|
166
240
|
receiver: "world:revoke-key",
|
|
167
241
|
summary: "Revoke an API key",
|
|
168
|
-
request: z.object({ keyId: z.string() }), response: ok, effect: "ask", auth: "
|
|
242
|
+
request: z.object({ keyId: z.string() }), response: ok, effect: "ask", auth: "member", scope: "write", reversible: false,
|
|
169
243
|
}),
|
|
170
244
|
"world:create-thing": receiver({
|
|
171
245
|
receiver: "world:create-thing",
|
|
@@ -243,13 +317,7 @@ export const RECEIVERS = {
|
|
|
243
317
|
effect: "ask", cost: "free", idempotent: true,
|
|
244
318
|
}),
|
|
245
319
|
// ── auth (human session) ──
|
|
246
|
-
|
|
247
|
-
receiver: "auth:sign-in",
|
|
248
|
-
summary: "Sign in a human with email + password",
|
|
249
|
-
request: z.object({ email: z.string(), password: z.string() }),
|
|
250
|
-
response: z.object({ sessionId: z.string(), userId: z.string() }),
|
|
251
|
-
effect: "ask", reversible: false,
|
|
252
|
-
}),
|
|
320
|
+
// auth:sign-in killed (C7): Better Auth handles all human auth; signal/ask pipeline returns dissolved
|
|
253
321
|
"auth:sign-out": receiver({
|
|
254
322
|
receiver: "auth:sign-out",
|
|
255
323
|
summary: "End the current session",
|
|
@@ -257,29 +325,9 @@ export const RECEIVERS = {
|
|
|
257
325
|
response: ok,
|
|
258
326
|
effect: "signal", idempotent: true,
|
|
259
327
|
}),
|
|
260
|
-
//
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
summary: "Join the public board as an actor",
|
|
264
|
-
request: z.object({ uid: z.string(), group: z.string().optional() }),
|
|
265
|
-
response: z.object({ ok: z.boolean(), uid: z.string(), group: z.string(), role: z.string() }),
|
|
266
|
-
effect: "ask", idempotent: true,
|
|
267
|
-
}),
|
|
268
|
-
// ── agency (oo operator surface) ──
|
|
269
|
-
"agency:push:complete": receiver({
|
|
270
|
-
receiver: "agency:push:complete",
|
|
271
|
-
summary: "An agency finished pushing agents/skills — logs the sync event",
|
|
272
|
-
request: z.object({ agents: z.number().int().nonnegative(), skills: z.number().int().nonnegative() }),
|
|
273
|
-
response: ok,
|
|
274
|
-
effect: "signal", idempotent: true,
|
|
275
|
-
}),
|
|
276
|
-
"agency:friction": receiver({
|
|
277
|
-
receiver: "agency:friction",
|
|
278
|
-
summary: "A /do cycle stalled in an agency repo — surfaces the friction back to ONE",
|
|
279
|
-
request: z.object({ agency: z.string(), cycle: z.string().nullable(), wave: z.string().nullable(), reason: z.string() }),
|
|
280
|
-
response: ok,
|
|
281
|
-
effect: "signal",
|
|
282
|
-
}),
|
|
328
|
+
// board:join killed (C7): no resolver, no route, no caller
|
|
329
|
+
// agency:push:complete killed (C7): no resolver, no route, no caller
|
|
330
|
+
// agency:friction killed (C7): no resolver, no route, no caller
|
|
283
331
|
// ── groups ──
|
|
284
332
|
"groups:join": receiver({
|
|
285
333
|
receiver: "groups:join",
|
|
@@ -325,18 +373,7 @@ export const RECEIVERS = {
|
|
|
325
373
|
}),
|
|
326
374
|
effect: "ask", auth: "manage_clients", cost: "free", idempotent: true,
|
|
327
375
|
}),
|
|
328
|
-
//
|
|
329
|
-
"paths:bridge": receiver({
|
|
330
|
-
receiver: "paths:bridge",
|
|
331
|
-
summary: "Bridge two actors or groups with a path",
|
|
332
|
-
request: z.object({ from: z.string(), to: z.string() }),
|
|
333
|
-
response: z.object({
|
|
334
|
-
ok: z.boolean().optional(),
|
|
335
|
-
status: z.enum(["pending", "bridged"]).optional(),
|
|
336
|
-
key: z.string().optional(), gid: z.string().optional(), awaiting: z.string().optional(),
|
|
337
|
-
}),
|
|
338
|
-
effect: "ask",
|
|
339
|
-
}),
|
|
376
|
+
// paths:bridge killed (C7): no resolver, no route, no caller
|
|
340
377
|
// ── subscriptions ──
|
|
341
378
|
"subscriptions:register": receiver({
|
|
342
379
|
receiver: "subscriptions:register",
|
|
@@ -391,16 +428,7 @@ export const RECEIVERS = {
|
|
|
391
428
|
response: z.array(CapabilityItemSchema),
|
|
392
429
|
effect: "ask", cost: "free", idempotent: true,
|
|
393
430
|
}),
|
|
394
|
-
|
|
395
|
-
receiver: "agents:deploy-on-behalf",
|
|
396
|
-
summary: "Deploy an agent on behalf of an owner, inheriting their paths",
|
|
397
|
-
request: z.object({ owner: z.string(), spec: z.record(z.string(), z.unknown()) }),
|
|
398
|
-
response: z.object({
|
|
399
|
-
ok: z.boolean(), uid: z.string(), owner: z.string(),
|
|
400
|
-
inheritedPaths: z.array(z.object({ from: z.string(), to: z.string(), strength: z.number() })),
|
|
401
|
-
}),
|
|
402
|
-
effect: "ask", reversible: false, simulatable: true,
|
|
403
|
-
}),
|
|
431
|
+
// agents:deploy-on-behalf killed (C7): no resolver, no route, no caller
|
|
404
432
|
// ── pay (TRANSACT — onchain settlement) ──
|
|
405
433
|
"pay:weight": receiver({
|
|
406
434
|
receiver: "pay:weight",
|
|
@@ -409,6 +437,115 @@ export const RECEIVERS = {
|
|
|
409
437
|
response: PayResponseSchema,
|
|
410
438
|
effect: "ask", cost: "variable", settles: "onchain", reversible: false, simulatable: true,
|
|
411
439
|
}),
|
|
440
|
+
// ── market (A2A negotiation, C2) ──
|
|
441
|
+
"market:offer": receiver({
|
|
442
|
+
receiver: "market:offer",
|
|
443
|
+
summary: "Buyer creates a Deal at OFFER stage — initiates A2A negotiation",
|
|
444
|
+
request: z.object({
|
|
445
|
+
id: z.string().uuid().optional(),
|
|
446
|
+
seller: z.string().min(1),
|
|
447
|
+
skill: z.string().min(1),
|
|
448
|
+
price: z.number().nonnegative(),
|
|
449
|
+
currency: z.string().default("credits"),
|
|
450
|
+
deadline: z.string().datetime(),
|
|
451
|
+
}),
|
|
452
|
+
response: z.union([
|
|
453
|
+
z.object({ ok: z.literal(true), deal: z.object({ id: z.string(), stage: z.string(), version: z.number() }) }),
|
|
454
|
+
z.object({ ok: z.literal(false), error: z.string() }),
|
|
455
|
+
]),
|
|
456
|
+
effect: "ask", auth: "required", reversible: true, idempotent: false,
|
|
457
|
+
}),
|
|
458
|
+
"market:counter": receiver({
|
|
459
|
+
receiver: "market:counter",
|
|
460
|
+
summary: "Seller revises deal terms — stays at OFFER, bumps version",
|
|
461
|
+
request: z.object({
|
|
462
|
+
dealId: z.string().min(1),
|
|
463
|
+
price: z.number().nonnegative().optional(),
|
|
464
|
+
deadline: z.string().datetime().optional(),
|
|
465
|
+
skill: z.string().optional(),
|
|
466
|
+
}),
|
|
467
|
+
response: z.union([
|
|
468
|
+
z.object({ ok: z.literal(true), deal: z.object({ id: z.string(), stage: z.string(), version: z.number() }) }),
|
|
469
|
+
z.object({ ok: z.literal(false), error: z.string() }),
|
|
470
|
+
]),
|
|
471
|
+
effect: "ask", auth: "required", reversible: true, idempotent: false,
|
|
472
|
+
}),
|
|
473
|
+
"market:accept": receiver({
|
|
474
|
+
receiver: "market:accept",
|
|
475
|
+
summary: "Buyer accepts deal — OFFER → ESCROW",
|
|
476
|
+
request: z.object({ dealId: z.string().min(1) }),
|
|
477
|
+
response: z.union([
|
|
478
|
+
z.object({ ok: z.literal(true), deal: z.object({ id: z.string(), stage: z.string(), version: z.number() }) }),
|
|
479
|
+
z.object({ ok: z.literal(false), error: z.string() }),
|
|
480
|
+
]),
|
|
481
|
+
effect: "ask", auth: "required", reversible: false, idempotent: false,
|
|
482
|
+
}),
|
|
483
|
+
"market:reject": receiver({
|
|
484
|
+
receiver: "market:reject",
|
|
485
|
+
summary: "Buyer rejects deal — OFFER → FADE",
|
|
486
|
+
request: z.object({ dealId: z.string().min(1) }),
|
|
487
|
+
response: z.union([
|
|
488
|
+
z.object({ ok: z.literal(true), deal: z.object({ id: z.string(), stage: z.string(), version: z.number() }) }),
|
|
489
|
+
z.object({ ok: z.literal(false), error: z.string() }),
|
|
490
|
+
]),
|
|
491
|
+
effect: "ask", auth: "required", reversible: false, idempotent: false,
|
|
492
|
+
}),
|
|
493
|
+
"market:deliver": receiver({
|
|
494
|
+
receiver: "market:deliver",
|
|
495
|
+
summary: "Seller delivers work — EXECUTE → VERIFY",
|
|
496
|
+
request: z.object({ dealId: z.string().min(1), result: z.record(z.string(), z.unknown()).optional() }),
|
|
497
|
+
response: z.union([
|
|
498
|
+
z.object({ ok: z.literal(true), deal: z.object({ id: z.string(), stage: z.string(), version: z.number() }) }),
|
|
499
|
+
z.object({ ok: z.literal(false), error: z.string() }),
|
|
500
|
+
]),
|
|
501
|
+
effect: "ask", auth: "required", reversible: false, idempotent: false,
|
|
502
|
+
}),
|
|
503
|
+
"market:verify": receiver({
|
|
504
|
+
receiver: "market:verify",
|
|
505
|
+
summary: "Buyer scores delivered work — VERIFY → SETTLE (≥0.65) or DISPUTE (<0.65)",
|
|
506
|
+
request: z.object({
|
|
507
|
+
dealId: z.string().min(1),
|
|
508
|
+
fit: z.number().min(0).max(1),
|
|
509
|
+
form: z.number().min(0).max(1),
|
|
510
|
+
truth: z.number().min(0).max(1),
|
|
511
|
+
taste: z.number().min(0).max(1),
|
|
512
|
+
}),
|
|
513
|
+
response: z.union([
|
|
514
|
+
z.object({ ok: z.literal(true), deal: z.object({ id: z.string(), stage: z.string(), version: z.number() }), scores: z.object({ fit: z.number(), form: z.number(), truth: z.number(), taste: z.number() }) }),
|
|
515
|
+
z.object({ ok: z.literal(false), error: z.string() }),
|
|
516
|
+
]),
|
|
517
|
+
effect: "ask", auth: "required", reversible: false, idempotent: false,
|
|
518
|
+
}),
|
|
519
|
+
"market:settle": receiver({
|
|
520
|
+
receiver: "market:settle",
|
|
521
|
+
summary: "Release escrow payment — SETTLE → RECEIPT",
|
|
522
|
+
request: z.object({ dealId: z.string().min(1) }),
|
|
523
|
+
response: z.union([
|
|
524
|
+
z.object({ ok: z.literal(true), deal: z.object({ id: z.string(), stage: z.string(), version: z.number() }) }),
|
|
525
|
+
z.object({ ok: z.literal(false), error: z.string() }),
|
|
526
|
+
]),
|
|
527
|
+
effect: "ask", auth: "required", reversible: false, idempotent: false,
|
|
528
|
+
}),
|
|
529
|
+
"market:dispute": receiver({
|
|
530
|
+
receiver: "market:dispute",
|
|
531
|
+
summary: "Escalate an active deal to DISPUTE — either party may call",
|
|
532
|
+
request: z.object({ dealId: z.string().min(1) }),
|
|
533
|
+
response: z.union([
|
|
534
|
+
z.object({ ok: z.literal(true), deal: z.object({ id: z.string(), stage: z.string(), version: z.number() }) }),
|
|
535
|
+
z.object({ ok: z.literal(false), error: z.string() }),
|
|
536
|
+
]),
|
|
537
|
+
effect: "ask", auth: "required", reversible: false, idempotent: false,
|
|
538
|
+
}),
|
|
539
|
+
"market:escrow": receiver({
|
|
540
|
+
receiver: "market:escrow",
|
|
541
|
+
summary: "Buyer locks payment via pay.one.ie — ESCROW → EXECUTE on confirmed tx",
|
|
542
|
+
request: z.object({ dealId: z.string().min(1) }),
|
|
543
|
+
response: z.union([
|
|
544
|
+
z.object({ ok: z.literal(true), deal: z.object({ id: z.string(), stage: z.string(), version: z.number() }), escrowRef: z.string() }),
|
|
545
|
+
z.object({ ok: z.literal(false), error: z.string(), deal: z.object({ id: z.string(), stage: z.string() }).optional() }),
|
|
546
|
+
]),
|
|
547
|
+
effect: "ask", auth: "required", reversible: false, idempotent: false,
|
|
548
|
+
}),
|
|
412
549
|
// ── market (TRADE) ──
|
|
413
550
|
"market:hire": receiver({
|
|
414
551
|
receiver: "market:hire",
|
|
@@ -452,6 +589,16 @@ export const RECEIVERS = {
|
|
|
452
589
|
})),
|
|
453
590
|
effect: "ask", cost: "free", idempotent: true,
|
|
454
591
|
}),
|
|
592
|
+
"market:claim": receiver({
|
|
593
|
+
receiver: "market:claim",
|
|
594
|
+
summary: "Claim an open bounty — atomically marks it picked and binds the claimant",
|
|
595
|
+
request: z.object({ bountyId: z.string() }),
|
|
596
|
+
response: z.union([
|
|
597
|
+
z.object({ ok: z.literal(true), bountyId: z.string(), claimantUid: z.string() }),
|
|
598
|
+
z.object({ ok: z.literal(false), error: z.string() }),
|
|
599
|
+
]),
|
|
600
|
+
effect: "ask", cost: "free", reversible: false, idempotent: false,
|
|
601
|
+
}),
|
|
455
602
|
"market:list": receiver({
|
|
456
603
|
receiver: "market:list",
|
|
457
604
|
summary: "List the capability market",
|
|
@@ -475,22 +622,7 @@ export const RECEIVERS = {
|
|
|
475
622
|
response: z.object({ ok: z.literal(true), sid: z.string(), scope: z.string() }),
|
|
476
623
|
effect: "ask",
|
|
477
624
|
}),
|
|
478
|
-
//
|
|
479
|
-
"loop:close": receiver({
|
|
480
|
-
receiver: "loop:close",
|
|
481
|
-
summary: "Close a loop session with an outcome",
|
|
482
|
-
request: z.object({
|
|
483
|
-
session: z.string(),
|
|
484
|
-
outcome: z.enum(["result", "timeout", "dissolved", "failure"]),
|
|
485
|
-
rubric: z.number().optional(),
|
|
486
|
-
reason: z.string().optional(),
|
|
487
|
-
}),
|
|
488
|
-
response: z.object({
|
|
489
|
-
ok: z.literal(true), stages: z.array(z.unknown()),
|
|
490
|
-
highways: z.array(z.object({ path: z.string(), strength: z.number(), resistance: z.number(), net: z.number() })),
|
|
491
|
-
}),
|
|
492
|
-
effect: "ask",
|
|
493
|
-
}),
|
|
625
|
+
// loop:close killed (C7): no resolver, no route, no caller
|
|
494
626
|
// ── reads (free · idempotent) ──
|
|
495
627
|
"signals:list": receiver({
|
|
496
628
|
receiver: "signals:list",
|
|
@@ -606,12 +738,693 @@ export const RECEIVERS = {
|
|
|
606
738
|
response: z.object({ ok: z.boolean(), reply: z.string().optional(), error: z.string().optional() }),
|
|
607
739
|
effect: "ask", auth: "member",
|
|
608
740
|
}),
|
|
741
|
+
// ── booking — one calendar, two doors (text/booking-plan.md §5) ───────────────
|
|
742
|
+
// Both public-bookable: a customer with no account books a slot. The provider
|
|
743
|
+
// side (configure a service) is the separate, gated booking:configure.
|
|
744
|
+
"booking:list-slots": receiver({
|
|
745
|
+
receiver: "booking:list-slots",
|
|
746
|
+
summary: "List open slots for a workspace's service on a date (or next open days)",
|
|
747
|
+
request: z.object({
|
|
748
|
+
slug: z.string(), // provider workspace
|
|
749
|
+
service: z.string().optional(), // service_id; omitted → the workspace's first active
|
|
750
|
+
date: z.string().optional(), // 'YYYY-MM-DD'; omitted → next N open days
|
|
751
|
+
days: z.number().int().min(1).max(14).optional(), // window size when date omitted
|
|
752
|
+
}),
|
|
753
|
+
response: z.object({
|
|
754
|
+
service: z.object({
|
|
755
|
+
service_id: z.string(), name: z.string(), duration_min: z.number(),
|
|
756
|
+
price: z.number(), currency: z.string(),
|
|
757
|
+
}).nullable(),
|
|
758
|
+
slots: z.array(z.object({ date: z.string(), times: z.array(z.string()) })), // CalendarCard shape
|
|
759
|
+
error: z.string().optional(),
|
|
760
|
+
}),
|
|
761
|
+
effect: "ask", cost: "free", idempotent: true, simulatable: false,
|
|
762
|
+
examples: [{ slug: "clearwater", date: "2026-06-10" }],
|
|
763
|
+
}),
|
|
764
|
+
"booking:create": receiver({
|
|
765
|
+
receiver: "booking:create",
|
|
766
|
+
summary: "Hold a slot for a customer; returns a ref and a payment intent when price > 0",
|
|
767
|
+
request: z.object({
|
|
768
|
+
slug: z.string(),
|
|
769
|
+
service: z.string(),
|
|
770
|
+
slotDate: z.string(), // 'YYYY-MM-DD'
|
|
771
|
+
slotTime: z.string(), // 'HH:MM' 24h, slot start
|
|
772
|
+
customer: z.object({ name: z.string(), email: z.string().email().optional() }),
|
|
773
|
+
paymentRail: z.enum(["stripe", "sui"]).optional(), // resolver overrides by caller kind
|
|
774
|
+
}),
|
|
775
|
+
response: z.object({
|
|
776
|
+
ok: z.boolean(),
|
|
777
|
+
ref: z.string().optional(),
|
|
778
|
+
status: z.enum(["pending", "confirmed"]).optional(),
|
|
779
|
+
paymentRail: z.enum(["stripe", "sui"]).nullable().optional(),
|
|
780
|
+
paymentIntent: z.object({ clientSecret: z.string(), amount: z.number() }).optional(), // human, price>0
|
|
781
|
+
escrow: z.object({ escrowId: z.string(), bounty: z.number(), deadline: z.string() }).optional(), // agent
|
|
782
|
+
error: z.string().optional(), // 'slot_taken' | 'closed' | 'unknown_service'
|
|
783
|
+
}),
|
|
784
|
+
effect: "ask", cost: "variable", settles: "offchain", reversible: false,
|
|
785
|
+
simulatable: true, idempotent: true, // idempotencyKey dedupes a retried hold
|
|
786
|
+
examples: [{ slug: "clearwater", service: "svc_x", slotDate: "2026-06-10",
|
|
787
|
+
slotTime: "15:00", customer: { name: "Sarah", email: "s@ex.com" } }],
|
|
788
|
+
}),
|
|
789
|
+
// booking:configure — the ONE provider-gated booking receiver (§10). Unlike the
|
|
790
|
+
// two public-bookable receivers above, the resolver re-walks
|
|
791
|
+
// can(actor, group, "manage_clients") server-side and UPSERTs only the caller's
|
|
792
|
+
// own service rows. NOT public-bookable.
|
|
793
|
+
"booking:configure": receiver({
|
|
794
|
+
receiver: "booking:configure",
|
|
795
|
+
summary: "Provider-gated: create or update a bookable service (hours, slot length, price, currency, tz, active)",
|
|
796
|
+
request: z.object({
|
|
797
|
+
slug: z.string(), // the workspace; the write scope (re-walked)
|
|
798
|
+
actorId: z.string().optional(), // re-walk subject (gateway-forwarded)
|
|
799
|
+
service: z.string().optional(), // service_id to update; omitted → create
|
|
800
|
+
name: z.string(),
|
|
801
|
+
duration_min: z.number().int().positive(),
|
|
802
|
+
price: z.number().int().nonnegative().optional(),
|
|
803
|
+
currency: z.string().optional(),
|
|
804
|
+
hours_json: z.array(z.array(z.object({ start: z.string(), end: z.string() }))), // 7 entries, 0=Sun
|
|
805
|
+
tz: z.string().optional(),
|
|
806
|
+
active: z.boolean().optional(),
|
|
807
|
+
}),
|
|
808
|
+
response: z.object({ ok: z.boolean(), service_id: z.string().optional(), error: z.string().optional() }),
|
|
809
|
+
effect: "ask", cost: "free", idempotent: true, reversible: true, auth: "manage_clients",
|
|
810
|
+
examples: [{ slug: "clearwater", name: "Consultation", duration_min: 30, price: 4000, currency: "gbp",
|
|
811
|
+
hours_json: [[], [{ start: "09:00", end: "17:00" }], [], [], [], [], []] }],
|
|
812
|
+
}),
|
|
813
|
+
// booking:list-bookings — the provider's own appointment list for a month (§6
|
|
814
|
+
// web surface). Tenant-private read: the resolver scopes to the authenticated
|
|
815
|
+
// owner, never the body slug, so a caller only ever sees their own workspace.
|
|
816
|
+
"booking:list-bookings": receiver({
|
|
817
|
+
receiver: "booking:list-bookings",
|
|
818
|
+
summary: "Provider-gated: list a workspace's bookings for a month (customer, time, service, status)",
|
|
819
|
+
request: z.object({
|
|
820
|
+
slug: z.string(), // workspace (informational; gate re-scopes to caller)
|
|
821
|
+
month: z.string().optional(), // 'YYYY-MM'; omitted → current month
|
|
822
|
+
}),
|
|
823
|
+
response: z.object({
|
|
824
|
+
bookings: z.array(z.object({
|
|
825
|
+
id: z.string(), ref: z.string(), service_name: z.string(),
|
|
826
|
+
slot_date: z.string(), slot_time: z.string(),
|
|
827
|
+
customer_name: z.string(), status: z.string(),
|
|
828
|
+
})),
|
|
829
|
+
error: z.string().optional(),
|
|
830
|
+
}),
|
|
831
|
+
effect: "ask", cost: "free", idempotent: true, auth: "manage_clients",
|
|
832
|
+
examples: [{ slug: "clearwater", month: "2026-06" }],
|
|
833
|
+
}),
|
|
834
|
+
// booking:cancel — provider dissolves a booking by ref, releasing the slot
|
|
835
|
+
// immediately (the partial unique index drops dissolved rows from scope, §9).
|
|
836
|
+
// Tenant-private write: scoped to the authenticated owner. Idempotent.
|
|
837
|
+
"booking:cancel": receiver({
|
|
838
|
+
receiver: "booking:cancel",
|
|
839
|
+
summary: "Provider-gated: dissolve a booking by ref, releasing the slot",
|
|
840
|
+
request: z.object({
|
|
841
|
+
slug: z.string(),
|
|
842
|
+
ref: z.string(),
|
|
843
|
+
}),
|
|
844
|
+
response: z.object({ ok: z.boolean(), error: z.string().optional() }),
|
|
845
|
+
effect: "ask", cost: "free", idempotent: true, reversible: false, auth: "manage_clients",
|
|
846
|
+
examples: [{ slug: "clearwater", ref: "CLE-2026-4821" }],
|
|
847
|
+
}),
|
|
848
|
+
// ── workflows — define an SOP, run it, watch it learn (text/workflows-plan.md) ──
|
|
849
|
+
// Every workflow op is a typed receiver. No new REST routes. apply-diff is
|
|
850
|
+
// simulatable: simulate=true validates the WorkflowDiff (incl. DAG acyclicity)
|
|
851
|
+
// and commits nothing — the chat-authoring preview path.
|
|
852
|
+
"workflow:list": receiver({
|
|
853
|
+
receiver: "workflow:list",
|
|
854
|
+
summary: "List a workspace's workflows (D1 mirror); pass templates=true for the public SOP catalog",
|
|
855
|
+
request: z.object({
|
|
856
|
+
slug: z.string().optional(),
|
|
857
|
+
templates: z.boolean().optional(),
|
|
858
|
+
}),
|
|
859
|
+
response: z.object({
|
|
860
|
+
workflows: z.array(z.object({
|
|
861
|
+
id: z.string(), name: z.string(), description: z.string().optional(), step_count: z.number(),
|
|
862
|
+
status: z.string(), last_run_status: z.string().nullable(),
|
|
863
|
+
})),
|
|
864
|
+
error: z.string().optional(),
|
|
865
|
+
}),
|
|
866
|
+
effect: "ask", cost: "free", idempotent: true, simulatable: false, auth: "view_workflows",
|
|
867
|
+
examples: [{ slug: "acme" }, { templates: true }],
|
|
868
|
+
}),
|
|
869
|
+
"workflow:get": receiver({
|
|
870
|
+
receiver: "workflow:get",
|
|
871
|
+
summary: "Fetch one workflow's full graph — steps (kind, config, position) and edges (with conditions)",
|
|
872
|
+
request: z.object({ workflowId: z.string() }),
|
|
873
|
+
response: z.object({
|
|
874
|
+
id: z.string(), name: z.string(), status: z.string(),
|
|
875
|
+
steps: z.array(z.object({
|
|
876
|
+
id: z.string(), kind: StepKind, name: z.string(),
|
|
877
|
+
config: z.string(), position: z.string().optional(),
|
|
878
|
+
})),
|
|
879
|
+
edges: z.array(z.object({
|
|
880
|
+
source: z.string(), target: z.string(),
|
|
881
|
+
strength: z.number(), resistance: z.number(),
|
|
882
|
+
condition: z.string().optional(),
|
|
883
|
+
})),
|
|
884
|
+
error: z.string().optional(),
|
|
885
|
+
}),
|
|
886
|
+
effect: "ask", cost: "free", idempotent: true, simulatable: false, auth: "view_workflows",
|
|
887
|
+
examples: [{ workflowId: "wf_abc" }],
|
|
888
|
+
}),
|
|
889
|
+
"workflow:runs": receiver({
|
|
890
|
+
receiver: "workflow:runs",
|
|
891
|
+
summary: "List recent runs of a workflow (D1 workflow_run) for the monitor + history surfaces",
|
|
892
|
+
request: z.object({ workflowId: z.string(), runId: z.string().optional(), limit: z.number().int().min(1).max(200).optional() }),
|
|
893
|
+
response: z.object({
|
|
894
|
+
runs: z.array(z.object({
|
|
895
|
+
id: z.string(), status: z.string(),
|
|
896
|
+
started_at: z.number(), finished_at: z.number().nullable(),
|
|
897
|
+
})),
|
|
898
|
+
events: z.array(z.object({
|
|
899
|
+
step_id: z.string(), kind: z.string(), status: z.string().nullable(),
|
|
900
|
+
latency_ms: z.number().nullable(), at: z.number(),
|
|
901
|
+
})).optional(),
|
|
902
|
+
error: z.string().optional(),
|
|
903
|
+
}),
|
|
904
|
+
effect: "ask", cost: "free", idempotent: true, simulatable: false, auth: "view_workflows",
|
|
905
|
+
examples: [{ workflowId: "wf_abc", limit: 20 }, { workflowId: "wf_abc", runId: "run_1" }],
|
|
906
|
+
}),
|
|
907
|
+
"workflow:create": receiver({
|
|
908
|
+
receiver: "workflow:create",
|
|
909
|
+
summary: "Create a blank workflow (group group-type=workflow) — optionally cloned from a template",
|
|
910
|
+
request: z.object({
|
|
911
|
+
slug: z.string().optional(),
|
|
912
|
+
name: z.string(),
|
|
913
|
+
description: z.string().optional(), // defaults from the cloned template
|
|
914
|
+
fromTemplate: z.string().optional(),
|
|
915
|
+
simulate: z.boolean().optional(),
|
|
916
|
+
}),
|
|
917
|
+
response: z.object({ id: z.string(), workflowId: z.string() }),
|
|
918
|
+
effect: "ask", cost: "free", reversible: true, idempotent: false, simulatable: true,
|
|
919
|
+
auth: "manage_workflows",
|
|
920
|
+
examples: [{ name: "Client Onboarding" }, { name: "demo", simulate: true }],
|
|
921
|
+
}),
|
|
922
|
+
"workflow:apply-diff": receiver({
|
|
923
|
+
receiver: "workflow:apply-diff",
|
|
924
|
+
summary: "Apply a WorkflowDiff (add/remove/connect/disconnect/update). simulate=true validates the DAG without persisting",
|
|
925
|
+
request: z.object({
|
|
926
|
+
workflowId: z.string(),
|
|
927
|
+
diff: WorkflowDiffSchema,
|
|
928
|
+
simulate: z.boolean().optional(),
|
|
929
|
+
version: z.number().int().optional(), // optimistic lock — stale → conflict
|
|
930
|
+
}),
|
|
931
|
+
response: z.object({
|
|
932
|
+
ok: z.boolean(),
|
|
933
|
+
stepCount: z.number().optional(),
|
|
934
|
+
idMap: z.record(z.string(), z.string()).optional(), // tempId → persisted id
|
|
935
|
+
error: z.string().optional(), // 'cycle_detected' | 'conflict' | 'invalid_diff'
|
|
936
|
+
}),
|
|
937
|
+
effect: "ask", cost: "free", reversible: true, idempotent: false, simulatable: true,
|
|
938
|
+
auth: "manage_workflows",
|
|
939
|
+
examples: [{ workflowId: "wf_abc", diff: { add: [{ tempId: "s1", kind: "trigger", name: "On signup", config: "{}" }] }, simulate: true }],
|
|
940
|
+
}),
|
|
941
|
+
"workflow:run": receiver({
|
|
942
|
+
receiver: "workflow:run",
|
|
943
|
+
summary: "Start a run — spawns the WorkflowRun DO, executes each step, marks path strength on traversed edges",
|
|
944
|
+
request: z.object({
|
|
945
|
+
workflowId: z.string(),
|
|
946
|
+
triggerPayload: z.record(z.string(), z.unknown()).optional(),
|
|
947
|
+
idempotencyKey: z.string().optional(),
|
|
948
|
+
}),
|
|
949
|
+
response: z.object({ runId: z.string(), status: z.string(), error: z.string().optional() }),
|
|
950
|
+
effect: "ask", cost: "variable", reversible: false, idempotent: true, simulatable: false, settles: "none",
|
|
951
|
+
auth: "manage_workflows",
|
|
952
|
+
examples: [{ workflowId: "wf_abc" }],
|
|
953
|
+
}),
|
|
954
|
+
"human:resolve": receiver({
|
|
955
|
+
receiver: "human:resolve",
|
|
956
|
+
summary: "Resolve a suspended human step — carries { runId, stepId, decision | formPayload } to the run DO",
|
|
957
|
+
request: z.object({
|
|
958
|
+
runId: z.string(),
|
|
959
|
+
stepId: z.string(),
|
|
960
|
+
decision: z.enum(["approved", "rejected"]).optional(),
|
|
961
|
+
formPayload: z.record(z.string(), z.unknown()).optional(),
|
|
962
|
+
// System callers (a Telegram/Discord button via channels) attest the
|
|
963
|
+
// workspace; an authenticated session's slug always wins over this. The
|
|
964
|
+
// `slug` is trusted ONLY with a valid `attestation` — HMAC(IDENTITY_SECRET,
|
|
965
|
+
// "human:resolve:<runId>:<stepId>:<slug>") that only channels can mint after
|
|
966
|
+
// it re-walks the tapper's authority. Without it, slug is ignored.
|
|
967
|
+
slug: z.string().optional(),
|
|
968
|
+
attestation: z.string().optional(),
|
|
969
|
+
}),
|
|
970
|
+
response: z.object({ ok: z.boolean(), status: z.string().optional(), error: z.string().optional() }),
|
|
971
|
+
effect: "ask", cost: "free", idempotent: true, simulatable: false, auth: "manage_workflows",
|
|
972
|
+
examples: [{ runId: "run_1", stepId: "s2", decision: "approved" }],
|
|
973
|
+
}),
|
|
974
|
+
"checkout:create": receiver({
|
|
975
|
+
receiver: "checkout:create",
|
|
976
|
+
summary: "The `sell` step's binding — mint a Connect checkout session for the buyer, stamping { runId, stepId } into session metadata so checkout:resume can wake the run",
|
|
977
|
+
request: z.object({
|
|
978
|
+
workspace: z.string(),
|
|
979
|
+
ppid: z.string(),
|
|
980
|
+
// Set by the executor when a `sell` step dispatches this — the run's resume coordinates.
|
|
981
|
+
runId: z.string().optional(),
|
|
982
|
+
stepId: z.string().optional(),
|
|
983
|
+
}),
|
|
984
|
+
response: z.object({
|
|
985
|
+
clientSecret: z.string().nullable().optional(),
|
|
986
|
+
sessionId: z.string().optional(),
|
|
987
|
+
applicationFeeAmount: z.number().optional(),
|
|
988
|
+
stripeAccount: z.string().optional(),
|
|
989
|
+
error: z.string().optional(),
|
|
990
|
+
}),
|
|
991
|
+
effect: "ask", cost: "variable", reversible: false, idempotent: false, simulatable: false, settles: "offchain",
|
|
992
|
+
auth: "manage_workflows",
|
|
993
|
+
examples: [{ workspace: "acme", ppid: "pr_1" }],
|
|
994
|
+
}),
|
|
995
|
+
"checkout:resume": receiver({
|
|
996
|
+
receiver: "checkout:resume",
|
|
997
|
+
summary: "Wake a run suspended at a `sell` step — the storefront webhook fires this on checkout.session.completed with the (runId, stepId) it stamped at create. Sibling of human:resolve.",
|
|
998
|
+
request: z.object({
|
|
999
|
+
runId: z.string(),
|
|
1000
|
+
stepId: z.string(),
|
|
1001
|
+
// The run's own workspace (from the session metadata the webhook reads); the
|
|
1002
|
+
// runId is the resume capability, re-validated against the parked run server-side.
|
|
1003
|
+
slug: z.string().optional(),
|
|
1004
|
+
}),
|
|
1005
|
+
response: z.object({ ok: z.boolean(), status: z.string().optional(), error: z.string().optional() }),
|
|
1006
|
+
effect: "signal", cost: "free", idempotent: true, simulatable: false, auth: "manage_workflows",
|
|
1007
|
+
examples: [{ runId: "run_1", stepId: "s2", slug: "acme" }],
|
|
1008
|
+
}),
|
|
1009
|
+
"human:notify": receiver({
|
|
1010
|
+
receiver: "human:notify",
|
|
1011
|
+
summary: "Post a channel-shaped approval into a run's conversation when it suspends at a human step — web card · Telegram inline keys · Discord components. Sibling of chat:send.",
|
|
1012
|
+
request: z.object({
|
|
1013
|
+
runId: z.string(),
|
|
1014
|
+
stepId: z.string(),
|
|
1015
|
+
stepName: z.string().optional(),
|
|
1016
|
+
workflowName: z.string().optional(),
|
|
1017
|
+
group: z.string().optional(), // conversation group; falls back to the run's started_by
|
|
1018
|
+
}),
|
|
1019
|
+
response: z.object({ ok: z.boolean(), group: z.string().optional(), error: z.string().optional() }),
|
|
1020
|
+
effect: "signal", cost: "free", idempotent: true, simulatable: false, auth: "manage_workflows",
|
|
1021
|
+
examples: [{ runId: "run_1", stepId: "s2", stepName: "Approve contract" }],
|
|
1022
|
+
}),
|
|
1023
|
+
"workflow:stop": receiver({
|
|
1024
|
+
receiver: "workflow:stop",
|
|
1025
|
+
summary: "Park a live run at its current step (status → paused); preserves the resume cursor so human:resolve or a re-run continues it",
|
|
1026
|
+
request: z.object({ runId: z.string() }),
|
|
1027
|
+
response: z.object({ ok: z.boolean(), status: z.string().optional(), error: z.string().optional() }),
|
|
1028
|
+
effect: "ask", cost: "free", reversible: true, idempotent: true, simulatable: false, auth: "manage_workflows",
|
|
1029
|
+
examples: [{ runId: "run_1" }],
|
|
1030
|
+
}),
|
|
1031
|
+
"workflow:trigger": receiver({
|
|
1032
|
+
receiver: "workflow:trigger",
|
|
1033
|
+
summary: "Fire every workspace workflow whose trigger step matches a channel source (e.g. webhook:telegram)",
|
|
1034
|
+
request: z.object({
|
|
1035
|
+
source: z.string(),
|
|
1036
|
+
slug: z.string().optional(),
|
|
1037
|
+
triggerPayload: z.record(z.string(), z.unknown()).optional(),
|
|
1038
|
+
}),
|
|
1039
|
+
response: z.object({ ok: z.boolean(), started: z.number(), runIds: z.array(z.string()) }),
|
|
1040
|
+
effect: "signal", cost: "variable", reversible: false, idempotent: false, simulatable: false, auth: "manage_workflows",
|
|
1041
|
+
examples: [{ source: "webhook:telegram", slug: "acme" }],
|
|
1042
|
+
}),
|
|
1043
|
+
"workflow:delete": receiver({
|
|
1044
|
+
receiver: "workflow:delete",
|
|
1045
|
+
summary: "Delete a workflow and all its runs, steps, and edges",
|
|
1046
|
+
request: z.object({ workflowId: z.string() }),
|
|
1047
|
+
response: z.object({ ok: z.boolean(), error: z.string().optional() }),
|
|
1048
|
+
effect: "ask", cost: "free", reversible: false, idempotent: true, auth: "manage_workflows",
|
|
1049
|
+
examples: [{ workflowId: "wf_abc" }],
|
|
1050
|
+
}),
|
|
1051
|
+
"workflow:update": receiver({
|
|
1052
|
+
receiver: "workflow:update",
|
|
1053
|
+
summary: "Rename a workflow or change its status (draft|active|paused)",
|
|
1054
|
+
request: z.object({ workflowId: z.string(), name: z.string().optional(), status: z.enum(["draft", "active", "paused"]).optional() }),
|
|
1055
|
+
response: z.object({ ok: z.boolean(), error: z.string().optional() }),
|
|
1056
|
+
effect: "ask", cost: "free", reversible: true, idempotent: true, auth: "manage_workflows",
|
|
1057
|
+
examples: [{ workflowId: "wf_abc", name: "Renamed Workflow" }, { workflowId: "wf_abc", status: "paused" }],
|
|
1058
|
+
}),
|
|
1059
|
+
// ── The autonomy ladder's leaf runners — a workflow skill/agent step compiles
|
|
1060
|
+
// to one of these (workflow-executor.ts stepBinding). Both proxy to the
|
|
1061
|
+
// channels runtime; web owns the catalog + tenant authority (workflows-lock C2/C3).
|
|
1062
|
+
"skills:list": receiver({
|
|
1063
|
+
receiver: "skills:list",
|
|
1064
|
+
summary: "List the caller's workspace skill catalog (R2) — powers the canvas SkillPicker",
|
|
1065
|
+
request: z.object({}),
|
|
1066
|
+
response: z.object({
|
|
1067
|
+
skills: z.array(z.object({ name: z.string(), size: z.number() })),
|
|
1068
|
+
}),
|
|
1069
|
+
effect: "ask", cost: "free", idempotent: true, simulatable: false, auth: "view_workflows",
|
|
1070
|
+
examples: [{}],
|
|
1071
|
+
}),
|
|
1072
|
+
"skill:run": receiver({
|
|
1073
|
+
receiver: "skill:run",
|
|
1074
|
+
summary: "Run a workspace skill — loads its body from R2, runs one bounded turn via channels, returns { text }",
|
|
1075
|
+
request: z.object({ skill: z.string() }).catchall(z.unknown()), // extra keys = the skill's input
|
|
1076
|
+
response: z.object({ ok: z.boolean(), text: z.string().optional(), skill: z.string().optional(), error: z.string().optional() }),
|
|
1077
|
+
effect: "ask", cost: "variable", reversible: false, idempotent: false, simulatable: false, settles: "none", auth: "manage_workflows",
|
|
1078
|
+
examples: [{ skill: "copywriting", topic: "launch" }],
|
|
1079
|
+
}),
|
|
1080
|
+
"agent:run": receiver({
|
|
1081
|
+
receiver: "agent:run",
|
|
1082
|
+
summary: "Invoke a bound actor (optionally skill-constrained) for one bounded turn via channels; returns { text }",
|
|
1083
|
+
request: z.object({
|
|
1084
|
+
actorId: z.string(),
|
|
1085
|
+
skill: z.string().optional(),
|
|
1086
|
+
instructions: z.string().optional(),
|
|
1087
|
+
}).catchall(z.unknown()), // extra keys = the agent's input
|
|
1088
|
+
response: z.object({ ok: z.boolean(), text: z.string().optional(), actorId: z.string().optional(), error: z.string().optional() }),
|
|
1089
|
+
effect: "ask", cost: "variable", reversible: false, idempotent: false, simulatable: false, settles: "none", auth: "manage_workflows",
|
|
1090
|
+
examples: [{ actorId: "one:support", skill: "support", instructions: "Reply kindly." }],
|
|
1091
|
+
}),
|
|
1092
|
+
// ── video — room provisioning, sessions, invitations, recording (text/video-live-improve-plan.md) ──
|
|
1093
|
+
// Seven receivers already ship in receiver-resolvers.ts. These declarations expose
|
|
1094
|
+
// them to typed ask<R>/signal<R> callers, the MCP surface, and edge validation.
|
|
1095
|
+
// Four new receivers (quick-room, join-event, start-recording, start-stream) are
|
|
1096
|
+
// declared here and implemented in the same W1 batch.
|
|
1097
|
+
"video:create-room": receiver({
|
|
1098
|
+
receiver: "video:create-room",
|
|
1099
|
+
summary: "Create a 100ms video room for a workspace; returns the room slug and URL",
|
|
1100
|
+
request: z.object({
|
|
1101
|
+
workspace: z.string(),
|
|
1102
|
+
roomSlug: z.string(),
|
|
1103
|
+
name: z.string(),
|
|
1104
|
+
description: z.string().optional(),
|
|
1105
|
+
type: z.enum(["meeting", "classroom", "webinar"]).optional(),
|
|
1106
|
+
region: z.string().optional(),
|
|
1107
|
+
}),
|
|
1108
|
+
response: z.object({
|
|
1109
|
+
ok: z.boolean(),
|
|
1110
|
+
room: z.object({
|
|
1111
|
+
slug: z.string(), name: z.string(), description: z.string(),
|
|
1112
|
+
type: z.string(), hmsRoomId: z.string(), url: z.string(),
|
|
1113
|
+
}).optional(),
|
|
1114
|
+
error: z.string().optional(),
|
|
1115
|
+
}),
|
|
1116
|
+
effect: "ask", cost: "free", idempotent: false, auth: "manage_clients",
|
|
1117
|
+
examples: [{ workspace: "acme", roomSlug: "algebra-101", name: "Algebra 101", type: "classroom" }],
|
|
1118
|
+
}),
|
|
1119
|
+
"video:delete-room": receiver({
|
|
1120
|
+
receiver: "video:delete-room",
|
|
1121
|
+
summary: "Disable a video room and its 100ms counterpart; room is no longer joinable",
|
|
1122
|
+
request: z.object({ workspace: z.string(), roomSlug: z.string() }),
|
|
1123
|
+
response: z.object({ ok: z.boolean(), error: z.string().optional() }),
|
|
1124
|
+
effect: "ask", cost: "free", idempotent: true, reversible: false, auth: "manage_clients",
|
|
1125
|
+
examples: [{ workspace: "acme", roomSlug: "algebra-101" }],
|
|
1126
|
+
}),
|
|
1127
|
+
"video:contact-call": receiver({
|
|
1128
|
+
receiver: "video:contact-call",
|
|
1129
|
+
summary: "Provision a one-to-one video room for a contact; links the room thread to the contact CRM record",
|
|
1130
|
+
request: z.object({
|
|
1131
|
+
workspace: z.string(),
|
|
1132
|
+
actorId: z.string(),
|
|
1133
|
+
name: z.string().optional(),
|
|
1134
|
+
}),
|
|
1135
|
+
response: z.object({
|
|
1136
|
+
ok: z.boolean(),
|
|
1137
|
+
roomSlug: z.string().optional(),
|
|
1138
|
+
threadId: z.string().nullable().optional(),
|
|
1139
|
+
guestJoinUrl: z.string().optional(),
|
|
1140
|
+
hostJoinUrl: z.string().optional(),
|
|
1141
|
+
error: z.string().optional(),
|
|
1142
|
+
}),
|
|
1143
|
+
effect: "ask", cost: "free", idempotent: false, auth: "manage_clients",
|
|
1144
|
+
examples: [{ workspace: "acme", actorId: "actor_123", name: "Call with Sarah" }],
|
|
1145
|
+
}),
|
|
1146
|
+
"video:invite": receiver({
|
|
1147
|
+
receiver: "video:invite",
|
|
1148
|
+
summary: "Generate a tracked /go/ join link for an actor into an existing room",
|
|
1149
|
+
request: z.object({
|
|
1150
|
+
workspace: z.string(),
|
|
1151
|
+
roomSlug: z.string(),
|
|
1152
|
+
actorId: z.string().optional(),
|
|
1153
|
+
}),
|
|
1154
|
+
response: z.object({
|
|
1155
|
+
ok: z.boolean(),
|
|
1156
|
+
goUrl: z.string().optional(),
|
|
1157
|
+
destination: z.string().optional(),
|
|
1158
|
+
error: z.string().optional(),
|
|
1159
|
+
}),
|
|
1160
|
+
effect: "ask", cost: "free", idempotent: false, auth: "manage_clients",
|
|
1161
|
+
examples: [{ workspace: "acme", roomSlug: "algebra-101", actorId: "actor_456" }],
|
|
1162
|
+
}),
|
|
1163
|
+
"video:schedule-webinar": receiver({
|
|
1164
|
+
receiver: "video:schedule-webinar",
|
|
1165
|
+
summary: "Create a webinar room and send tracked invite links to N contacts in one call",
|
|
1166
|
+
request: z.object({
|
|
1167
|
+
workspace: z.string(),
|
|
1168
|
+
name: z.string().optional(),
|
|
1169
|
+
actorIds: z.array(z.string()).min(1).max(500),
|
|
1170
|
+
}),
|
|
1171
|
+
response: z.object({
|
|
1172
|
+
ok: z.boolean(),
|
|
1173
|
+
roomUrl: z.string().optional(),
|
|
1174
|
+
invited: z.number().optional(),
|
|
1175
|
+
links: z.array(z.object({ actorId: z.string(), goUrl: z.string() })).optional(),
|
|
1176
|
+
error: z.string().optional(),
|
|
1177
|
+
}),
|
|
1178
|
+
effect: "ask", cost: "free", idempotent: false, auth: "manage_clients",
|
|
1179
|
+
examples: [{ workspace: "acme", name: "Product Launch", actorIds: ["actor_1", "actor_2"] }],
|
|
1180
|
+
}),
|
|
1181
|
+
"video:create-session": receiver({
|
|
1182
|
+
receiver: "video:create-session",
|
|
1183
|
+
summary: "Create a video session with host + guest tracked join links; optionally schedules the call",
|
|
1184
|
+
request: z.object({
|
|
1185
|
+
workspace: z.string(),
|
|
1186
|
+
roomSlug: z.string(),
|
|
1187
|
+
name: z.string(),
|
|
1188
|
+
type: z.enum(["meeting", "classroom", "webinar"]).optional(),
|
|
1189
|
+
region: z.string().optional(),
|
|
1190
|
+
guestActorId: z.string().optional(),
|
|
1191
|
+
scheduledAt: z.number().optional(),
|
|
1192
|
+
}),
|
|
1193
|
+
response: z.object({
|
|
1194
|
+
ok: z.boolean(),
|
|
1195
|
+
room: z.object({ slug: z.string(), hmsRoomId: z.string(), url: z.string() }).optional(),
|
|
1196
|
+
hostJoinUrl: z.string().optional(),
|
|
1197
|
+
guestJoinUrl: z.string().optional(),
|
|
1198
|
+
error: z.string().optional(),
|
|
1199
|
+
}),
|
|
1200
|
+
effect: "ask", cost: "free", idempotent: false, auth: "manage_clients",
|
|
1201
|
+
examples: [{ workspace: "acme", roomSlug: "consult-abc", name: "Consultation", guestActorId: "actor_789" }],
|
|
1202
|
+
}),
|
|
1203
|
+
"video:summary": receiver({
|
|
1204
|
+
receiver: "video:summary",
|
|
1205
|
+
summary: "Run an AI summary of a call transcript and append it as a system message on the room thread",
|
|
1206
|
+
request: z.object({
|
|
1207
|
+
threadId: z.string(),
|
|
1208
|
+
transcript: z.string(),
|
|
1209
|
+
}),
|
|
1210
|
+
response: z.object({
|
|
1211
|
+
ok: z.boolean(),
|
|
1212
|
+
threadId: z.string().optional(),
|
|
1213
|
+
skipped: z.string().optional(),
|
|
1214
|
+
error: z.string().optional(),
|
|
1215
|
+
}),
|
|
1216
|
+
effect: "ask", cost: "variable", idempotent: false, auth: "manage_clients",
|
|
1217
|
+
examples: [{ threadId: "thr_abc", transcript: "Host: Hello... Guest: Hi..." }],
|
|
1218
|
+
}),
|
|
1219
|
+
"video:quick-room": receiver({
|
|
1220
|
+
receiver: "video:quick-room",
|
|
1221
|
+
summary: "Ad-hoc video room from any chat thread — creates the room, sends the join link into the thread",
|
|
1222
|
+
request: z.object({
|
|
1223
|
+
workspace: z.string(),
|
|
1224
|
+
threadId: z.string().optional(),
|
|
1225
|
+
name: z.string().optional(),
|
|
1226
|
+
}),
|
|
1227
|
+
response: z.object({
|
|
1228
|
+
ok: z.boolean(),
|
|
1229
|
+
roomSlug: z.string().optional(),
|
|
1230
|
+
guestJoinUrl: z.string().optional(),
|
|
1231
|
+
hostJoinUrl: z.string().optional(),
|
|
1232
|
+
threadId: z.string().nullable().optional(),
|
|
1233
|
+
error: z.string().optional(),
|
|
1234
|
+
}),
|
|
1235
|
+
effect: "ask", cost: "free", idempotent: false, auth: "manage_clients",
|
|
1236
|
+
examples: [{ workspace: "acme", threadId: "thr_xyz", name: "Quick sync" }],
|
|
1237
|
+
}),
|
|
1238
|
+
"video:join-event": receiver({
|
|
1239
|
+
receiver: "video:join-event",
|
|
1240
|
+
summary: "Record a peer join event for tracking and lifecycle; public — called from the /go/ link handler",
|
|
1241
|
+
request: z.object({
|
|
1242
|
+
workspace: z.string(),
|
|
1243
|
+
roomSlug: z.string(),
|
|
1244
|
+
role: z.string().optional(),
|
|
1245
|
+
actorId: z.string().optional(),
|
|
1246
|
+
}),
|
|
1247
|
+
response: z.object({ ok: z.boolean(), error: z.string().optional() }),
|
|
1248
|
+
effect: "signal", cost: "free", idempotent: true,
|
|
1249
|
+
examples: [{ workspace: "acme", roomSlug: "consult-abc", role: "guest" }],
|
|
1250
|
+
}),
|
|
1251
|
+
"video:start-recording": receiver({
|
|
1252
|
+
receiver: "video:start-recording",
|
|
1253
|
+
summary: "Start cloud recording for an active room via 100ms REST; inserts a video_recordings row",
|
|
1254
|
+
request: z.object({ workspace: z.string(), roomSlug: z.string() }),
|
|
1255
|
+
response: z.object({
|
|
1256
|
+
ok: z.boolean(),
|
|
1257
|
+
recordingId: z.string().optional(),
|
|
1258
|
+
error: z.string().optional(),
|
|
1259
|
+
}),
|
|
1260
|
+
effect: "ask", cost: "free", idempotent: false, auth: "manage_clients",
|
|
1261
|
+
examples: [{ workspace: "acme", roomSlug: "algebra-101" }],
|
|
1262
|
+
}),
|
|
1263
|
+
"video:start-stream": receiver({
|
|
1264
|
+
receiver: "video:start-stream",
|
|
1265
|
+
summary: "Start an HLS live stream for a room; returns the playback URL when the stream is ready",
|
|
1266
|
+
request: z.object({
|
|
1267
|
+
workspace: z.string(),
|
|
1268
|
+
roomSlug: z.string(),
|
|
1269
|
+
hlsConfig: z.record(z.string(), z.unknown()).optional(),
|
|
1270
|
+
}),
|
|
1271
|
+
response: z.object({
|
|
1272
|
+
ok: z.boolean(),
|
|
1273
|
+
hlsUrl: z.string().optional(),
|
|
1274
|
+
error: z.string().optional(),
|
|
1275
|
+
}),
|
|
1276
|
+
effect: "ask", cost: "free", idempotent: false, auth: "manage_clients",
|
|
1277
|
+
examples: [{ workspace: "acme", roomSlug: "product-launch" }],
|
|
1278
|
+
}),
|
|
1279
|
+
// connect:channel — token-paste connect for a channel (Connect plan C7). The
|
|
1280
|
+
// typed contract over the shipped /api/connect/telegram route: the caller pastes
|
|
1281
|
+
// a channel credential, web verifies it (getMe), points the webhook, then hands
|
|
1282
|
+
// the raw secret to channels' /connect sink under the owner gate. SECURITY: the
|
|
1283
|
+
// token rides the REQUEST only; the response NEVER echoes it. effect:ask,
|
|
1284
|
+
// auth:manage_clients re-walked server-side off locals.slug (never body actorId).
|
|
1285
|
+
"connect:channel": receiver({
|
|
1286
|
+
receiver: "connect:channel",
|
|
1287
|
+
summary: "Connect a channel (e.g. telegram) by pasting its bot token; verifies, sets the webhook, seals the credential under the owner gate",
|
|
1288
|
+
request: z.object({
|
|
1289
|
+
channel: z.string(), // 'telegram' (token-paste path)
|
|
1290
|
+
token: z.string(), // the bot credential — request-only, never returned/logged
|
|
1291
|
+
slug: z.string().optional(), // workspace; gate re-scopes to the authenticated owner
|
|
1292
|
+
}),
|
|
1293
|
+
response: z.object({
|
|
1294
|
+
ok: z.boolean(),
|
|
1295
|
+
status: z.string().optional(), // 'active' | 'updated' from the channels sink
|
|
1296
|
+
account: z.string().optional(), // public handle (e.g. bot username) — never the token
|
|
1297
|
+
error: z.string().optional(), // 'invalid token' | 'unauthorized' | 'duplicate'
|
|
1298
|
+
}),
|
|
1299
|
+
effect: "ask", cost: "free", reversible: false, idempotent: true, auth: "manage_clients",
|
|
1300
|
+
examples: [{ channel: "telegram", token: "<bot-token>" }],
|
|
1301
|
+
}),
|
|
1302
|
+
// connect:status — list the workspace's connected channels (Connect plan C8).
|
|
1303
|
+
// Read-only contract over /api/connect/status: rows come from the `connection`
|
|
1304
|
+
// table scoped to the authenticated owner (locals.slug — never a body slug).
|
|
1305
|
+
// SECURITY: the response carries channel + public account id + status only;
|
|
1306
|
+
// cred_ref and webhook_secret never leave the server.
|
|
1307
|
+
"connect:status": receiver({
|
|
1308
|
+
receiver: "connect:status",
|
|
1309
|
+
summary: "List connected channels for the workspace — channel, account, status, runtime; never the credential",
|
|
1310
|
+
request: z.object({}),
|
|
1311
|
+
response: z.object({
|
|
1312
|
+
ok: z.boolean(),
|
|
1313
|
+
connections: z
|
|
1314
|
+
.array(z.object({
|
|
1315
|
+
channel: z.string(), // 'telegram' | 'slack' | 'discord' | 'email'
|
|
1316
|
+
account: z.string(), // external_account_id (bot id / team id / inbound address)
|
|
1317
|
+
status: z.string(), // 'active' | 'revoked'
|
|
1318
|
+
runtime: z.string(), // 'webhook' | 'socket'
|
|
1319
|
+
connected_at: z.number(), // unix epoch seconds
|
|
1320
|
+
}))
|
|
1321
|
+
.optional(),
|
|
1322
|
+
error: z.string().optional(),
|
|
1323
|
+
}),
|
|
1324
|
+
effect: "ask", cost: "free", reversible: true, idempotent: true, auth: "manage_clients",
|
|
1325
|
+
examples: [{}],
|
|
1326
|
+
}),
|
|
1327
|
+
// ── Broadcast (newsletter) ────────────────────────────────────────────────
|
|
1328
|
+
"broadcast:create": receiver({
|
|
1329
|
+
receiver: "broadcast:create",
|
|
1330
|
+
summary: "Create a broadcast draft — subject, body_md, audience_tag, channel",
|
|
1331
|
+
request: z.object({ workspace: z.string(), subject: z.string().optional(), body_md: z.string().optional(), audience_tag: z.string().optional(), channel: z.enum(["email", "sms", "whatsapp"]).optional() }),
|
|
1332
|
+
response: z.object({ broadcastId: z.string() }),
|
|
1333
|
+
effect: "ask", cost: "free", reversible: true, idempotent: false, auth: "write",
|
|
1334
|
+
}),
|
|
1335
|
+
"broadcast:update": receiver({
|
|
1336
|
+
receiver: "broadcast:update",
|
|
1337
|
+
summary: "Update a broadcast draft — subject, body, audience, schedule",
|
|
1338
|
+
request: z.object({ workspace: z.string(), broadcastId: z.string(), subject: z.string().optional(), body_md: z.string().optional(), audience_tag: z.string().optional(), scheduled_at: z.number().optional() }),
|
|
1339
|
+
response: z.object({ ok: z.boolean() }),
|
|
1340
|
+
effect: "ask", cost: "free", reversible: true, idempotent: true, auth: "write",
|
|
1341
|
+
}),
|
|
1342
|
+
"broadcast:list": receiver({
|
|
1343
|
+
receiver: "broadcast:list",
|
|
1344
|
+
summary: "List broadcasts for a workspace with status and sent_at",
|
|
1345
|
+
request: z.object({ workspace: z.string(), status: z.enum(["draft", "scheduled", "sending", "sent", "cancelled"]).optional(), limit: z.number().int().max(100).optional() }),
|
|
1346
|
+
response: z.object({ broadcasts: z.array(z.object({ id: z.string(), subject: z.string(), status: z.string(), sent_at: z.number().nullable(), audience_tag: z.string().nullable() })) }),
|
|
1347
|
+
effect: "ask", cost: "free", reversible: false, idempotent: true, auth: "read",
|
|
1348
|
+
}),
|
|
1349
|
+
"broadcast:get": receiver({
|
|
1350
|
+
receiver: "broadcast:get",
|
|
1351
|
+
summary: "Get a single broadcast with recipient counts",
|
|
1352
|
+
request: z.object({ workspace: z.string(), broadcastId: z.string() }),
|
|
1353
|
+
response: z.object({ broadcast: z.record(z.string(), z.unknown()) }),
|
|
1354
|
+
effect: "ask", cost: "free", reversible: false, idempotent: true, auth: "read",
|
|
1355
|
+
}),
|
|
1356
|
+
"broadcast:test": receiver({
|
|
1357
|
+
receiver: "broadcast:test",
|
|
1358
|
+
summary: "Send a test email for a broadcast to one address",
|
|
1359
|
+
request: z.object({ workspace: z.string(), broadcastId: z.string(), to: z.string().email() }),
|
|
1360
|
+
response: z.object({ ok: z.boolean() }),
|
|
1361
|
+
effect: "signal", cost: "variable", reversible: false, idempotent: false, auth: "write",
|
|
1362
|
+
}),
|
|
1363
|
+
"broadcast:send": receiver({
|
|
1364
|
+
receiver: "broadcast:send",
|
|
1365
|
+
summary: "Seed recipients from audience tag, apply suppression, enqueue the send batch",
|
|
1366
|
+
request: z.object({ workspace: z.string(), broadcastId: z.string() }),
|
|
1367
|
+
response: z.object({ enqueued: z.number() }),
|
|
1368
|
+
effect: "signal", cost: "variable", reversible: false, idempotent: false, auth: "write",
|
|
1369
|
+
}),
|
|
1370
|
+
"broadcast:schedule": receiver({
|
|
1371
|
+
receiver: "broadcast:schedule",
|
|
1372
|
+
summary: "Schedule a broadcast to send at a future unix timestamp",
|
|
1373
|
+
request: z.object({ workspace: z.string(), broadcastId: z.string(), scheduled_at: z.number().int() }),
|
|
1374
|
+
response: z.object({ ok: z.boolean() }),
|
|
1375
|
+
effect: "ask", cost: "free", reversible: true, idempotent: true, auth: "write",
|
|
1376
|
+
}),
|
|
1377
|
+
"broadcast:cancel": receiver({
|
|
1378
|
+
receiver: "broadcast:cancel",
|
|
1379
|
+
summary: "Cancel a scheduled or in-progress broadcast",
|
|
1380
|
+
request: z.object({ workspace: z.string(), broadcastId: z.string() }),
|
|
1381
|
+
response: z.object({ ok: z.boolean() }),
|
|
1382
|
+
effect: "ask", cost: "free", reversible: false, idempotent: true, auth: "write",
|
|
1383
|
+
}),
|
|
1384
|
+
// ── Audience (public subscribe/unsubscribe) ────────────────────────────────
|
|
1385
|
+
"audience:subscribe": receiver({
|
|
1386
|
+
receiver: "audience:subscribe",
|
|
1387
|
+
summary: "Begin double opt-in for a contact — writes consent:email:pending tag, sends confirm email",
|
|
1388
|
+
request: z.object({ workspace: z.string(), address: z.string().email(), list: z.string().optional(), ref: z.string().optional() }),
|
|
1389
|
+
response: z.object({ ok: z.boolean() }),
|
|
1390
|
+
effect: "ask", cost: "free", reversible: false, idempotent: true, auth: "public",
|
|
1391
|
+
}),
|
|
1392
|
+
"audience:unsubscribe": receiver({
|
|
1393
|
+
receiver: "audience:unsubscribe",
|
|
1394
|
+
summary: "One-click unsubscribe — writes suppression row and flips consent tag; RFC 8058 safe",
|
|
1395
|
+
request: z.object({ workspace: z.string(), channel: z.enum(["email", "sms", "whatsapp"]).optional(), address: z.string(), token: z.string() }),
|
|
1396
|
+
response: z.object({ ok: z.boolean() }),
|
|
1397
|
+
effect: "ask", cost: "free", reversible: false, idempotent: true, auth: "public",
|
|
1398
|
+
}),
|
|
1399
|
+
"audience:confirm": receiver({
|
|
1400
|
+
receiver: "audience:confirm",
|
|
1401
|
+
summary: "Confirm email subscription via opt-in token — flips consent tag to subscribed",
|
|
1402
|
+
request: z.object({ token: z.string() }),
|
|
1403
|
+
response: z.object({ ok: z.boolean() }),
|
|
1404
|
+
effect: "ask", cost: "free", reversible: false, idempotent: true, auth: "public",
|
|
1405
|
+
}),
|
|
1406
|
+
// ── Winback batch ─────────────────────────────────────────────────────────
|
|
1407
|
+
"audience:winback": receiver({
|
|
1408
|
+
receiver: "audience:winback",
|
|
1409
|
+
summary: "Re-engage dormant subscribers (batch winback sequence tool) — queries contacts with no send in `days` days, sends one re-engage email each through the suppression-checked send path",
|
|
1410
|
+
request: z.object({ days: z.number().optional(), campaign: z.string().optional() }),
|
|
1411
|
+
response: z.object({ ok: z.boolean(), sent: z.number(), scanned: z.number() }),
|
|
1412
|
+
effect: "signal", cost: "variable", reversible: false, idempotent: false, auth: "write",
|
|
1413
|
+
}),
|
|
1414
|
+
// ── Workflow tool — channel-neutral send ──────────────────────────────────
|
|
1415
|
+
"message:send": receiver({
|
|
1416
|
+
receiver: "message:send",
|
|
1417
|
+
summary: "Send a message to one address via channel — suppression-checked; sms/whatsapp dissolve until adapters ship",
|
|
1418
|
+
request: z.object({ workspace: z.string(), channel: z.enum(["email", "sms", "whatsapp"]), to: z.string(), subject: z.string().optional(), body: z.string(), campaign: z.string().optional() }),
|
|
1419
|
+
response: z.object({ ok: z.boolean() }),
|
|
1420
|
+
effect: "signal", cost: "variable", reversible: false, idempotent: false, auth: "write",
|
|
1421
|
+
}),
|
|
609
1422
|
};
|
|
610
1423
|
/**
|
|
611
1424
|
* RECIPES — the four agent journeys as typed, ordered receiver sequences (C6).
|
|
612
1425
|
* Each entry is `readonly ReceiverName[]`, so a typo or a renamed receiver is a
|
|
613
1426
|
* compile error. `meta:catalog?goal=` returns one of these; the MCP server
|
|
614
|
-
* groups its tools by them. See `
|
|
1427
|
+
* groups its tools by them. See `text/agent-first-spec-plan.md`.
|
|
615
1428
|
*/
|
|
616
1429
|
export const RECIPES = {
|
|
617
1430
|
/** Onboard: become an actor → mint a key → join a group → declare capability. */
|
|
@@ -622,5 +1435,7 @@ export const RECIPES = {
|
|
|
622
1435
|
trade: ["capabilities:publish", "market:list", "market:hire", "pay:weight"],
|
|
623
1436
|
/** Transact: post a bounty → settle it onchain. */
|
|
624
1437
|
transact: ["market:bounty", "pay:weight"],
|
|
1438
|
+
/** SOP: define a workflow → shape it with a diff → run it. */
|
|
1439
|
+
sop: ["workflow:create", "workflow:apply-diff", "workflow:run"],
|
|
625
1440
|
};
|
|
626
1441
|
//# sourceMappingURL=receivers.js.map
|