@oneie/sdk 0.14.3 → 0.14.5
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/generated/schemas.d.ts +122 -31
- package/dist/generated/schemas.d.ts.map +1 -1
- package/dist/generated/schemas.js +75 -34
- package/dist/generated/schemas.js.map +1 -1
- package/dist/market.d.ts +57 -0
- package/dist/market.d.ts.map +1 -1
- package/dist/market.js +74 -1
- package/dist/market.js.map +1 -1
- package/dist/receivers.d.ts +368 -0
- package/dist/receivers.d.ts.map +1 -1
- package/dist/receivers.js +367 -4
- package/dist/receivers.js.map +1 -1
- package/dist/types.d.ts +3 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/wallet.d.ts +43 -0
- package/dist/wallet.d.ts.map +1 -0
- package/dist/wallet.js +237 -0
- package/dist/wallet.js.map +1 -0
- package/dist/work-contract-grammar.json +459 -0
- package/dist/work-contract.d.ts +44 -0
- package/dist/work-contract.d.ts.map +1 -0
- package/dist/work-contract.js +208 -0
- package/dist/work-contract.js.map +1 -0
- package/package.json +13 -1
package/dist/receivers.js
CHANGED
|
@@ -257,6 +257,30 @@ export const RECEIVERS = {
|
|
|
257
257
|
idempotent: true,
|
|
258
258
|
examples: [{ visitorHash: "9f2a1c7b4e0d8a3f5c6b" }],
|
|
259
259
|
}),
|
|
260
|
+
"visitor:identify": receiver({
|
|
261
|
+
receiver: "visitor:identify",
|
|
262
|
+
summary: "Every surface's front door to identify a visitor — mines free text, enriches by email, climbs the ladder, merges tenant-walled candidates, upserts the vCard.",
|
|
263
|
+
request: z.object({
|
|
264
|
+
email: z.string().optional(),
|
|
265
|
+
phone: z.string().optional(),
|
|
266
|
+
name: z.string().optional(),
|
|
267
|
+
handle: z.string().optional(),
|
|
268
|
+
channel: z.string().optional(),
|
|
269
|
+
sender: z.string().optional(),
|
|
270
|
+
visitorHash: z.string().optional(),
|
|
271
|
+
freeText: z.string().optional(),
|
|
272
|
+
source: z.enum(["door", "chat", "asked", "event"]),
|
|
273
|
+
}),
|
|
274
|
+
response: z.object({
|
|
275
|
+
ok: z.boolean(),
|
|
276
|
+
aid: z.string().optional(),
|
|
277
|
+
merged: z.boolean().optional(),
|
|
278
|
+
reason: z.string().optional(),
|
|
279
|
+
}),
|
|
280
|
+
effect: "ask",
|
|
281
|
+
auth: "manage_actors",
|
|
282
|
+
examples: [{ email: "sam@acme.com", source: "chat" }],
|
|
283
|
+
}),
|
|
260
284
|
"world:update-contact": receiver({
|
|
261
285
|
receiver: "world:update-contact",
|
|
262
286
|
summary: "Update an actor's contact/profile attributes — identity, contact details, professional, personal, CRM metrics",
|
|
@@ -339,6 +363,13 @@ export const RECEIVERS = {
|
|
|
339
363
|
summary: "Revoke an API key",
|
|
340
364
|
request: z.object({ keyId: z.string() }), response: ok, effect: "ask", auth: "member", reversible: false,
|
|
341
365
|
}),
|
|
366
|
+
"world:mint-owner-key": receiver({
|
|
367
|
+
receiver: "world:mint-owner-key",
|
|
368
|
+
summary: "Staff-only: mint a slug-based (human-class) owner key for a workspace — full authority, no UI session required",
|
|
369
|
+
request: z.object({ slug: z.string().optional(), label: z.string().optional(), validDays: z.number().optional() }),
|
|
370
|
+
response: z.object({ key: z.string(), keyId: z.string(), slug: z.string() }),
|
|
371
|
+
effect: "ask", auth: "manage_clients", cost: "free", idempotent: false,
|
|
372
|
+
}),
|
|
342
373
|
"world:declare-types": receiver({
|
|
343
374
|
receiver: "world:declare-types",
|
|
344
375
|
summary: "Persist a resource-type manifest for the caller's workspace; pass a template name (e.g. ecommerce) to seed from a built-in, or explicit types",
|
|
@@ -392,6 +423,13 @@ export const RECEIVERS = {
|
|
|
392
423
|
summary: "Delete a thing",
|
|
393
424
|
request: z.object({ tid: z.string() }), response: ok, effect: "ask", auth: "manage_things", reversible: false,
|
|
394
425
|
}),
|
|
426
|
+
"world:publish-agent": receiver({
|
|
427
|
+
receiver: "world:publish-agent",
|
|
428
|
+
summary: "Publish an agent.md to a workspace's R2 bucket so it can be loaded by the chat UI",
|
|
429
|
+
request: z.object({ slug: z.string(), name: z.string(), content: z.string() }),
|
|
430
|
+
response: z.object({ ok: z.boolean(), url: z.string(), name: z.string(), bytes: z.number() }),
|
|
431
|
+
effect: "ask", auth: "update_group",
|
|
432
|
+
}),
|
|
395
433
|
"world:list-things": receiver({
|
|
396
434
|
receiver: "world:list-things",
|
|
397
435
|
summary: "List things of a given type — relation pickers (browse, first 100 by name) and name resolution (pass `ids` to resolve exactly those, uncapped)",
|
|
@@ -478,6 +516,54 @@ export const RECEIVERS = {
|
|
|
478
516
|
response: z.object({ ok: z.boolean(), target: z.string().optional() }),
|
|
479
517
|
effect: "ask", auth: "session", reversible: true,
|
|
480
518
|
}),
|
|
519
|
+
"world:in": receiver({
|
|
520
|
+
receiver: "world:in",
|
|
521
|
+
summary: "The one front door: a message enters the world inbox, a guard quarantines toxic content, the router classifies the destination (private/fanout/public), and delivers into each destined workspace. Opt-in delivery — a workspace receives only tags it subscribed.",
|
|
522
|
+
request: z.object({
|
|
523
|
+
content: z.string().min(1),
|
|
524
|
+
tags: z.array(z.string()).optional(),
|
|
525
|
+
to: z.string().optional(),
|
|
526
|
+
from: z.string().optional(),
|
|
527
|
+
}),
|
|
528
|
+
response: z.object({
|
|
529
|
+
ok: z.boolean(),
|
|
530
|
+
decision: z.enum(["private", "fanout", "public", "quarantine"]).optional(),
|
|
531
|
+
targets: z.array(z.string()).optional(),
|
|
532
|
+
delivered: z.array(z.string()).optional(),
|
|
533
|
+
guard: z.object({ toxic: z.boolean(), score: z.number(), reason: z.string() }).optional(),
|
|
534
|
+
note: z.string().optional(),
|
|
535
|
+
error: z.string().optional(),
|
|
536
|
+
}),
|
|
537
|
+
effect: "ask", auth: "session", reversible: false,
|
|
538
|
+
}),
|
|
539
|
+
"world:subscribe": receiver({
|
|
540
|
+
receiver: "world:subscribe",
|
|
541
|
+
summary: "Opt into a tag so the world:in front door routes matching messages to you. An agent self-subscribes (omit workspace/actor); a workspace you own via `workspace`; a trusted relay may register an agent via `actor`. Writes claw_paths world:sub:<tag>.",
|
|
542
|
+
request: z.object({ tag: z.string().min(1), workspace: z.string().optional(), actor: z.string().optional() }),
|
|
543
|
+
response: z.object({ ok: z.boolean(), subscriber: z.string().optional(), tag: z.string().optional(), error: z.string().optional() }),
|
|
544
|
+
effect: "ask", auth: "session", reversible: true,
|
|
545
|
+
}),
|
|
546
|
+
"world:unsubscribe": receiver({
|
|
547
|
+
receiver: "world:unsubscribe",
|
|
548
|
+
summary: "Leave a tag — the symmetric op to world:subscribe. Removes the claw_paths world:sub:<tag> row so the front door stops routing it to you. Same authority as subscribe.",
|
|
549
|
+
request: z.object({ tag: z.string().min(1), workspace: z.string().optional(), actor: z.string().optional() }),
|
|
550
|
+
response: z.object({ ok: z.boolean(), subscriber: z.string().optional(), tag: z.string().optional(), removed: z.number().optional(), error: z.string().optional() }),
|
|
551
|
+
effect: "ask", auth: "session", reversible: false,
|
|
552
|
+
}),
|
|
553
|
+
"world:subscribers": receiver({
|
|
554
|
+
receiver: "world:subscribers",
|
|
555
|
+
summary: "Discovery — who follows this tag? Returns the subscribers (agents + workspaces) of one or more tags from the world space. The world's subscriber directory: agents find each other by shared interest, then peer:message or broadcast to them. Read-only; not gated by inbox tenancy.",
|
|
556
|
+
request: z.object({ tag: z.string().optional(), tags: z.array(z.string()).optional() }),
|
|
557
|
+
response: z.object({
|
|
558
|
+
ok: z.boolean(),
|
|
559
|
+
tags: z.array(z.string()).optional(),
|
|
560
|
+
count: z.number().optional(),
|
|
561
|
+
subscribers: z.array(z.string()).optional(),
|
|
562
|
+
byTag: z.record(z.string(), z.array(z.string())).optional(),
|
|
563
|
+
error: z.string().optional(),
|
|
564
|
+
}),
|
|
565
|
+
effect: "ask", auth: "session", reversible: true,
|
|
566
|
+
}),
|
|
481
567
|
// ════════════════════════════════════════════════════════════════════════
|
|
482
568
|
// C4 — remaining families (sequenced by recipe: identity → groups → BUILD
|
|
483
569
|
// → TRADE → TRANSACT → reads). Request schemas mirror the exact client.ts
|
|
@@ -540,7 +626,7 @@ export const RECEIVERS = {
|
|
|
540
626
|
summary: "Agency P&L — per-client funded · burned · margin · balance · cap (margin from the ledger)",
|
|
541
627
|
request: z.object({ slug: z.string().optional() }).optional(),
|
|
542
628
|
response: z.object({
|
|
543
|
-
agency: z.object({ slug: z.string(), name: z.string().nullable(), markup_pct: z.number(), pool: z.number() }).nullable(),
|
|
629
|
+
agency: z.object({ slug: z.string(), name: z.string().nullable(), markup_pct: z.number(), plan: z.string(), pool: z.number() }).nullable(),
|
|
544
630
|
clients: z.array(z.object({
|
|
545
631
|
slug: z.string(), name: z.string().nullable(), plan: z.string(),
|
|
546
632
|
funded: z.number(), burned: z.number(), margin: z.number(), balance: z.number(), cap: z.number().nullable(),
|
|
@@ -564,6 +650,18 @@ export const RECEIVERS = {
|
|
|
564
650
|
receiver: z.string(),
|
|
565
651
|
tags: z.array(z.string()),
|
|
566
652
|
scope: z.enum(["private", "public"]).optional(),
|
|
653
|
+
// Shared cross-tenant board — the one workspace two different ctx.ownerSlug
|
|
654
|
+
// identities can both land in (subscriptions.ts fanOut never delivers to its
|
|
655
|
+
// own sender, so a self-follow needs a distinct board+actor pairing).
|
|
656
|
+
board: z.literal("marketplace").optional(),
|
|
657
|
+
delivery: z.enum(["inbox", "telegram", "discord", "webhook"]).optional(),
|
|
658
|
+
delivery_target: z.string().optional(),
|
|
659
|
+
match: z.enum(["any", "all"]).optional(),
|
|
660
|
+
// Service-caller nomination only (Bearer === GATEWAY_API_KEY / X-Gateway-Key ===
|
|
661
|
+
// GATEWAY_SERVICE_SECRET) — a session/browser caller's value here is ignored in
|
|
662
|
+
// favor of their attested locals.slug. See one.ie/web/src/pages/api/ask/[...receiver].ts.
|
|
663
|
+
slug: z.string().optional(),
|
|
664
|
+
workspace: z.string().optional(),
|
|
567
665
|
}),
|
|
568
666
|
response: ok,
|
|
569
667
|
effect: "signal", idempotent: true,
|
|
@@ -574,16 +672,81 @@ export const RECEIVERS = {
|
|
|
574
672
|
request: z.object({
|
|
575
673
|
tags: z.array(z.string()),
|
|
576
674
|
content: z.string().optional(),
|
|
675
|
+
board: z.literal("marketplace").optional(),
|
|
676
|
+
slug: z.string().optional(),
|
|
677
|
+
workspace: z.string().optional(),
|
|
577
678
|
}),
|
|
578
679
|
response: z.object({ ok: z.boolean(), matched: z.number().optional(), actors: z.array(z.string()).optional() }),
|
|
579
680
|
effect: "ask",
|
|
580
681
|
}),
|
|
682
|
+
"world": receiver({
|
|
683
|
+
receiver: "world",
|
|
684
|
+
summary: "THE door — say it once, the world decides. Routes a tagged signal via the ladder (learned path → staked subscribers → CEO); fan:'all' broadcasts to every matching subscriber instead. Address form world:<tag-expr> carries tags in the receiver",
|
|
685
|
+
request: z.object({
|
|
686
|
+
tags: z.array(z.string()).optional(),
|
|
687
|
+
fan: z.enum(["one", "all"]).optional(),
|
|
688
|
+
deliver: z.boolean().optional(),
|
|
689
|
+
board: z.literal("marketplace").optional(),
|
|
690
|
+
slug: z.string().optional(),
|
|
691
|
+
workspace: z.string().optional(),
|
|
692
|
+
}),
|
|
693
|
+
response: z.object({
|
|
694
|
+
ok: z.boolean(),
|
|
695
|
+
routed: z.enum(["learned", "staked", "explore", "ceo"]).optional(),
|
|
696
|
+
actor: z.string().optional(),
|
|
697
|
+
matched: z.number().optional(),
|
|
698
|
+
actors: z.array(z.string()).optional(),
|
|
699
|
+
tags: z.array(z.string()).optional(),
|
|
700
|
+
}),
|
|
701
|
+
effect: "ask",
|
|
702
|
+
}),
|
|
703
|
+
"world:outcome": receiver({
|
|
704
|
+
receiver: "world:outcome",
|
|
705
|
+
summary: "Close the routing loop with the RESULT: whoever consumed a route reports success/failure, moving the same tag→receiver paths the router reads — success marks, failure warns. Pass the actor id the route returned",
|
|
706
|
+
request: z.object({
|
|
707
|
+
tags: z.array(z.string()),
|
|
708
|
+
actor: z.string(),
|
|
709
|
+
success: z.boolean().optional(),
|
|
710
|
+
weight: z.number().optional(),
|
|
711
|
+
slug: z.string().optional(),
|
|
712
|
+
workspace: z.string().optional(),
|
|
713
|
+
}),
|
|
714
|
+
response: z.object({
|
|
715
|
+
ok: z.boolean(),
|
|
716
|
+
outcome: z.enum(["marked", "warned"]).optional(),
|
|
717
|
+
actor: z.string().optional(),
|
|
718
|
+
tags: z.array(z.string()).optional(),
|
|
719
|
+
weight: z.number().optional(),
|
|
720
|
+
}),
|
|
721
|
+
effect: "ask", idempotent: false,
|
|
722
|
+
}),
|
|
723
|
+
"world:route": receiver({
|
|
724
|
+
receiver: "world:route",
|
|
725
|
+
summary: "Route a tagged signal to THE handler via the ladder: learned tag-node path (follow_route) → staked subscribers (reputation-ranked) → CEO standing workflow; marks the delivery path so the next route is smarter",
|
|
726
|
+
request: z.object({
|
|
727
|
+
tags: z.array(z.string()),
|
|
728
|
+
deliver: z.boolean().optional(),
|
|
729
|
+
board: z.literal("marketplace").optional(),
|
|
730
|
+
slug: z.string().optional(),
|
|
731
|
+
workspace: z.string().optional(),
|
|
732
|
+
}),
|
|
733
|
+
response: z.object({
|
|
734
|
+
ok: z.boolean(),
|
|
735
|
+
routed: z.enum(["learned", "staked", "explore", "ceo"]).optional(),
|
|
736
|
+
actor: z.string().optional(),
|
|
737
|
+
tags: z.array(z.string()).optional(),
|
|
738
|
+
}),
|
|
739
|
+
effect: "ask",
|
|
740
|
+
}),
|
|
581
741
|
"tasks:announce": receiver({
|
|
582
742
|
receiver: "tasks:announce",
|
|
583
743
|
summary: "Announce a task into the world by its tags — the first caller of world:announce",
|
|
584
744
|
request: z.object({
|
|
585
745
|
taskId: z.string(),
|
|
586
746
|
tags: z.array(z.string()),
|
|
747
|
+
board: z.literal("marketplace").optional(),
|
|
748
|
+
slug: z.string().optional(),
|
|
749
|
+
workspace: z.string().optional(),
|
|
587
750
|
}),
|
|
588
751
|
response: z.object({ ok: z.boolean(), taskId: z.string().optional(), matched: z.number().optional(), actors: z.array(z.string()).optional() }),
|
|
589
752
|
effect: "ask",
|
|
@@ -992,6 +1155,48 @@ export const RECEIVERS = {
|
|
|
992
1155
|
effect: "ask", cost: "free", idempotent: true,
|
|
993
1156
|
examples: [{}],
|
|
994
1157
|
}),
|
|
1158
|
+
"plugins:buy": receiver({
|
|
1159
|
+
receiver: "plugins:buy",
|
|
1160
|
+
summary: "Buy a plugin for the caller's workspace. method:'stripe' (default) returns a hosted-checkout url; method:'credits' spends the workspace credit pool and grants the entitlement synchronously. Pay with ONE coin by topping up credits on the one-token rail first, then buy with credits. Price is looked up server-side from the plugin name.",
|
|
1161
|
+
request: z.object({
|
|
1162
|
+
name: z.string(),
|
|
1163
|
+
method: z.enum(["stripe", "credits"]).optional(),
|
|
1164
|
+
}),
|
|
1165
|
+
response: z.object({
|
|
1166
|
+
method: z.enum(["stripe", "credits"]),
|
|
1167
|
+
// stripe rail
|
|
1168
|
+
sessionId: z.string().optional(),
|
|
1169
|
+
clientSecret: z.string().nullable().optional(),
|
|
1170
|
+
url: z.string().nullable().optional(),
|
|
1171
|
+
price_usd: z.number().optional(),
|
|
1172
|
+
// credits rail
|
|
1173
|
+
entitled: z.boolean().optional(),
|
|
1174
|
+
already: z.boolean().optional(),
|
|
1175
|
+
credits_spent: z.number().optional(),
|
|
1176
|
+
plugin: z.string(),
|
|
1177
|
+
feature: z.string(),
|
|
1178
|
+
}),
|
|
1179
|
+
effect: "ask", auth: "owner", cost: "variable", idempotent: false,
|
|
1180
|
+
examples: [{ name: "shop" }, { name: "shop", method: "credits" }],
|
|
1181
|
+
}),
|
|
1182
|
+
"plugins:grant": receiver({
|
|
1183
|
+
receiver: "plugins:grant",
|
|
1184
|
+
summary: "Agency resale — grant a plugin to a client workspace the caller controls. Two gates, no money: the caller must itself be entitled to the plugin (you can only resell what you own) and must control the target client via the owners walk-up. The client's entitlement is granted idempotently; nobody is charged. Billing the client is a separate concern.",
|
|
1185
|
+
request: z.object({
|
|
1186
|
+
name: z.string(),
|
|
1187
|
+
for: z.string().describe("the client workspace slug to grant the plugin to"),
|
|
1188
|
+
}),
|
|
1189
|
+
response: z.object({
|
|
1190
|
+
granted: z.boolean().optional(),
|
|
1191
|
+
already: z.boolean().optional(),
|
|
1192
|
+
plugin: z.string(),
|
|
1193
|
+
feature: z.string(),
|
|
1194
|
+
client: z.string().optional(),
|
|
1195
|
+
reseller: z.string().optional(),
|
|
1196
|
+
}),
|
|
1197
|
+
effect: "ask", auth: "owner", cost: "free", idempotent: true,
|
|
1198
|
+
examples: [{ name: "shop", for: "acme-client" }],
|
|
1199
|
+
}),
|
|
995
1200
|
"plugins:source": receiver({
|
|
996
1201
|
receiver: "plugins:source",
|
|
997
1202
|
summary: "Get the install reference for a plugin — 402 when the workspace is not entitled. Use meta:entitlements to check first; this doubles as the delivery gate.",
|
|
@@ -1494,6 +1699,42 @@ export const RECEIVERS = {
|
|
|
1494
1699
|
}),
|
|
1495
1700
|
effect: "ask", cost: "free", reversible: true, idempotent: true, auth: "member",
|
|
1496
1701
|
}),
|
|
1702
|
+
// ── view:* — saved views (custom-views C1). A view is a workspace-scoped Thing (world_things type 'view'). ──
|
|
1703
|
+
"view:create": receiver({
|
|
1704
|
+
receiver: "view:create",
|
|
1705
|
+
summary: "Save a named view — dimension × tags × kind × config — as a workspace Thing",
|
|
1706
|
+
request: z.object({ slug: z.string(), name: z.string(), kind: z.string().optional(), query: z.object({ dimension: z.string().optional(), type: z.string().optional(), tags: z.array(z.string()).optional(), stage: z.string().optional() }), config: z.record(z.string(), z.unknown()).optional(), pinned: z.boolean().optional() }),
|
|
1707
|
+
response: z.object({ ok: z.boolean(), id: z.string().optional(), name: z.string().optional(), error: z.string().optional() }),
|
|
1708
|
+
effect: "ask", cost: "free", reversible: true, idempotent: false, auth: "member",
|
|
1709
|
+
}),
|
|
1710
|
+
"view:list": receiver({
|
|
1711
|
+
receiver: "view:list",
|
|
1712
|
+
summary: "List a workspace's saved views (cold flag derived at read time)",
|
|
1713
|
+
request: z.object({ slug: z.string() }),
|
|
1714
|
+
response: z.object({ views: z.array(z.object({ id: z.string(), name: z.string(), kind: z.string().optional(), pinned: z.boolean(), cold: z.boolean() })) }),
|
|
1715
|
+
effect: "ask", cost: "free", reversible: true, idempotent: true, auth: "member",
|
|
1716
|
+
}),
|
|
1717
|
+
"view:get": receiver({
|
|
1718
|
+
receiver: "view:get",
|
|
1719
|
+
summary: "Read a saved view and resolve its live rows",
|
|
1720
|
+
request: z.object({ slug: z.string(), id: z.string() }),
|
|
1721
|
+
response: z.object({ ok: z.boolean(), rows: z.array(z.record(z.string(), z.unknown())).optional(), error: z.string().optional() }),
|
|
1722
|
+
effect: "ask", cost: "free", reversible: true, idempotent: true, auth: "member",
|
|
1723
|
+
}),
|
|
1724
|
+
"view:update": receiver({
|
|
1725
|
+
receiver: "view:update",
|
|
1726
|
+
summary: "Update a saved view's name / query / kind / config / pinned",
|
|
1727
|
+
request: z.object({ slug: z.string(), id: z.string(), name: z.string().optional(), kind: z.string().optional(), query: z.object({ dimension: z.string().optional(), type: z.string().optional(), tags: z.array(z.string()).optional(), stage: z.string().optional() }).optional(), config: z.record(z.string(), z.unknown()).optional(), pinned: z.boolean().optional() }),
|
|
1728
|
+
response: z.object({ ok: z.boolean(), id: z.string().optional(), error: z.string().optional() }),
|
|
1729
|
+
effect: "ask", cost: "free", reversible: true, idempotent: false, auth: "member",
|
|
1730
|
+
}),
|
|
1731
|
+
"view:delete": receiver({
|
|
1732
|
+
receiver: "view:delete",
|
|
1733
|
+
summary: "Delete a saved view (the prune)",
|
|
1734
|
+
request: z.object({ slug: z.string(), id: z.string() }),
|
|
1735
|
+
response: z.object({ ok: z.boolean(), id: z.string().optional(), error: z.string().optional() }),
|
|
1736
|
+
effect: "ask", cost: "free", reversible: true, idempotent: true, auth: "member",
|
|
1737
|
+
}),
|
|
1497
1738
|
// ── pages + workspace settings — handlers in resolvers/pages.ts ────────────────
|
|
1498
1739
|
"pages:create": receiver({
|
|
1499
1740
|
receiver: "pages:create",
|
|
@@ -1590,21 +1831,21 @@ export const RECEIVERS = {
|
|
|
1590
1831
|
"playbook:save": receiver({
|
|
1591
1832
|
receiver: "playbook:save",
|
|
1592
1833
|
summary: "Save a learner's playbook entry for a course lesson (upsert)",
|
|
1593
|
-
request: z.object({ course: z.string(), lesson: z.string(), content: z.string().optional() }),
|
|
1834
|
+
request: z.object({ course: z.string(), lesson: z.string(), content: z.string().optional(), slug: z.string().optional(), workspace: z.string().optional() }),
|
|
1594
1835
|
response: z.object({ ok: z.boolean() }),
|
|
1595
1836
|
effect: "ask", cost: "free", reversible: true, idempotent: true, auth: "public",
|
|
1596
1837
|
}),
|
|
1597
1838
|
"playbook:get": receiver({
|
|
1598
1839
|
receiver: "playbook:get",
|
|
1599
1840
|
summary: "Get the caller's playbook entries (optionally scoped to one course)",
|
|
1600
|
-
request: z.object({ course: z.string().optional() }),
|
|
1841
|
+
request: z.object({ course: z.string().optional(), slug: z.string().optional(), workspace: z.string().optional() }),
|
|
1601
1842
|
response: z.object({ entries: z.array(z.record(z.string(), z.unknown())).optional() }),
|
|
1602
1843
|
effect: "ask", cost: "free", reversible: true, idempotent: true, auth: "public",
|
|
1603
1844
|
}),
|
|
1604
1845
|
"playbook:promote": receiver({
|
|
1605
1846
|
receiver: "playbook:promote",
|
|
1606
1847
|
summary: "Promote a completed playbook into a reusable skill in the workspace's content repo",
|
|
1607
|
-
request: z.object({ course: z.string() }),
|
|
1848
|
+
request: z.object({ course: z.string(), slug: z.string().optional(), workspace: z.string().optional() }),
|
|
1608
1849
|
response: z.object({ ok: z.boolean(), skillRef: z.string().optional() }),
|
|
1609
1850
|
effect: "ask", cost: "free", reversible: true, idempotent: false, auth: "member",
|
|
1610
1851
|
}),
|
|
@@ -1864,6 +2105,23 @@ export const RECEIVERS = {
|
|
|
1864
2105
|
auth: "manage_workflows",
|
|
1865
2106
|
examples: [{ name: "Client Onboarding" }, { name: "demo", simulate: true }],
|
|
1866
2107
|
}),
|
|
2108
|
+
"workflow:webhook-subscribe": receiver({
|
|
2109
|
+
receiver: "workflow:webhook-subscribe",
|
|
2110
|
+
summary: "Register a URL that receives every future run's events for one workflow as signed, retried POSTs. Mints a signing secret server-side, returned once.",
|
|
2111
|
+
request: z.object({
|
|
2112
|
+
workflowId: z.string(),
|
|
2113
|
+
url: z.string().url(),
|
|
2114
|
+
}),
|
|
2115
|
+
response: z.object({
|
|
2116
|
+
ok: z.boolean(),
|
|
2117
|
+
subId: z.string().optional(),
|
|
2118
|
+
secret: z.string().optional(),
|
|
2119
|
+
error: z.string().optional(),
|
|
2120
|
+
}),
|
|
2121
|
+
effect: "ask", cost: "free", reversible: true, idempotent: false, simulatable: false,
|
|
2122
|
+
auth: "manage_workflows",
|
|
2123
|
+
examples: [{ workflowId: "wf_abc", url: "https://example.com/hooks/one" }],
|
|
2124
|
+
}),
|
|
1867
2125
|
"workflow:apply-diff": receiver({
|
|
1868
2126
|
receiver: "workflow:apply-diff",
|
|
1869
2127
|
summary: "Apply a WorkflowDiff (add/remove/connect/disconnect/update). simulate=true validates the DAG without persisting",
|
|
@@ -2022,6 +2280,14 @@ export const RECEIVERS = {
|
|
|
2022
2280
|
effect: "ask", cost: "free", reversible: true, idempotent: true, auth: "manage_workflows",
|
|
2023
2281
|
examples: [{ workflowId: "wf_abc", name: "Renamed Workflow" }, { workflowId: "wf_abc", status: "paused" }],
|
|
2024
2282
|
}),
|
|
2283
|
+
"workflow:fade": receiver({
|
|
2284
|
+
receiver: "workflow:fade",
|
|
2285
|
+
summary: "Decay edge weights (strength & resistance) on one workflow — or all of the caller's workflows when workflowId is omitted — so stale bottlenecks stop glowing; multiplies both by (1-rate), default 0.05",
|
|
2286
|
+
request: z.object({ workflowId: z.string().optional(), rate: z.number().optional() }),
|
|
2287
|
+
response: z.object({ ok: z.boolean(), faded: z.number().optional(), error: z.string().optional() }),
|
|
2288
|
+
effect: "ask", cost: "free", reversible: false, idempotent: false, auth: "manage_workflows",
|
|
2289
|
+
examples: [{ workflowId: "wf_abc" }, { rate: 0.1 }, {}],
|
|
2290
|
+
}),
|
|
2025
2291
|
// ── The autonomy ladder's leaf runners — a workflow skill/agent step compiles
|
|
2026
2292
|
// to one of these (workflow-executor.ts stepBinding). Both proxy to the
|
|
2027
2293
|
// channels runtime; web owns the catalog + tenant authority (workflows-lock C2/C3).
|
|
@@ -2081,6 +2347,9 @@ export const RECEIVERS = {
|
|
|
2081
2347
|
}),
|
|
2082
2348
|
effect: "ask", cost: "free", idempotent: false, auth: "manage_clients",
|
|
2083
2349
|
examples: [{ workspace: "acme", roomSlug: "algebra-101", name: "Algebra 101", type: "classroom" }],
|
|
2350
|
+
// Fan-out pilot (actions-fan-out C2): offered to chat via chatToolsFor — no
|
|
2351
|
+
// curated workspace tool needed; the registry derivation is the whole tool.
|
|
2352
|
+
surfaces: { chat: true },
|
|
2084
2353
|
}),
|
|
2085
2354
|
"video:delete-room": receiver({
|
|
2086
2355
|
receiver: "video:delete-room",
|
|
@@ -2143,6 +2412,7 @@ export const RECEIVERS = {
|
|
|
2143
2412
|
}),
|
|
2144
2413
|
effect: "ask", cost: "free", idempotent: false, auth: "manage_clients",
|
|
2145
2414
|
examples: [{ workspace: "acme", name: "Product Launch", actorIds: ["actor_1", "actor_2"] }],
|
|
2415
|
+
surfaces: { chat: true }, // fan-out: registry-derived chat tool (actions-fan-out C5)
|
|
2146
2416
|
}),
|
|
2147
2417
|
"video:create-session": receiver({
|
|
2148
2418
|
receiver: "video:create-session",
|
|
@@ -2181,6 +2451,7 @@ export const RECEIVERS = {
|
|
|
2181
2451
|
}),
|
|
2182
2452
|
effect: "ask", cost: "variable", idempotent: false, auth: "manage_clients",
|
|
2183
2453
|
examples: [{ threadId: "thr_abc", transcript: "Host: Hello... Guest: Hi..." }],
|
|
2454
|
+
surfaces: { chat: true }, // fan-out: registry-derived chat tool (actions-fan-out C5)
|
|
2184
2455
|
}),
|
|
2185
2456
|
"video:quick-room": receiver({
|
|
2186
2457
|
receiver: "video:quick-room",
|
|
@@ -2200,6 +2471,8 @@ export const RECEIVERS = {
|
|
|
2200
2471
|
}),
|
|
2201
2472
|
effect: "ask", cost: "free", idempotent: false, auth: "manage_clients",
|
|
2202
2473
|
examples: [{ workspace: "acme", threadId: "thr_xyz", name: "Quick sync" }],
|
|
2474
|
+
// Fan-out pilot (actions-fan-out C2).
|
|
2475
|
+
surfaces: { chat: true },
|
|
2203
2476
|
}),
|
|
2204
2477
|
"video:join-event": receiver({
|
|
2205
2478
|
receiver: "video:join-event",
|
|
@@ -2225,6 +2498,7 @@ export const RECEIVERS = {
|
|
|
2225
2498
|
}),
|
|
2226
2499
|
effect: "ask", cost: "free", idempotent: false, auth: "manage_clients",
|
|
2227
2500
|
examples: [{ workspace: "acme", roomSlug: "algebra-101" }],
|
|
2501
|
+
surfaces: { chat: true }, // fan-out: registry-derived chat tool (actions-fan-out C5)
|
|
2228
2502
|
}),
|
|
2229
2503
|
"video:start-stream": receiver({
|
|
2230
2504
|
receiver: "video:start-stream",
|
|
@@ -2241,6 +2515,7 @@ export const RECEIVERS = {
|
|
|
2241
2515
|
}),
|
|
2242
2516
|
effect: "ask", cost: "free", idempotent: false, auth: "manage_clients",
|
|
2243
2517
|
examples: [{ workspace: "acme", roomSlug: "product-launch" }],
|
|
2518
|
+
surfaces: { chat: true }, // fan-out: registry-derived chat tool (actions-fan-out C5)
|
|
2244
2519
|
}),
|
|
2245
2520
|
// connect:channel — token-paste connect for a channel (Connect plan C7). The
|
|
2246
2521
|
// typed contract over the shipped /api/connect/telegram route: the caller pastes
|
|
@@ -2535,6 +2810,94 @@ export const RECEIVERS = {
|
|
|
2535
2810
|
}),
|
|
2536
2811
|
effect: "signal", auth: "read_corpus", cost: "free", reversible: false, idempotent: false,
|
|
2537
2812
|
}),
|
|
2813
|
+
// -- rag:connect + brain: family — the phase-2 ingestion edge (brain C5 catalog; C7 handlers) --
|
|
2814
|
+
"rag:connect": receiver({
|
|
2815
|
+
receiver: "rag:connect",
|
|
2816
|
+
summary: "Register a knowledge source (e.g. a Google Drive folder) to sync into a workspace brain. Records the source in workspace_settings.sources; ingest-tick pulls changes on a schedule. Provision the brain (brain:provision) first.",
|
|
2817
|
+
request: z.object({
|
|
2818
|
+
provider: z.enum(["google-drive"]).optional().default("google-drive"),
|
|
2819
|
+
folder_id: z.string().describe("Drive folder id to sync (read-only)."),
|
|
2820
|
+
corpus: z.string().optional().describe("Target brain @-pointer; defaults to your workspace brain @<slug>-brain. Authority-walked (write_corpus)."),
|
|
2821
|
+
}),
|
|
2822
|
+
response: z.object({
|
|
2823
|
+
ok: z.boolean(),
|
|
2824
|
+
corpus: z.string().optional(),
|
|
2825
|
+
provider: z.string().optional(),
|
|
2826
|
+
folder_id: z.string().optional(),
|
|
2827
|
+
sources: z.number().optional().describe("Count of registered sources after this connect."),
|
|
2828
|
+
reason: z.string().optional(),
|
|
2829
|
+
}),
|
|
2830
|
+
effect: "ask", auth: "write_corpus", cost: { fixed: 1 }, reversible: true, idempotent: true,
|
|
2831
|
+
}),
|
|
2832
|
+
"brain:ingest": receiver({
|
|
2833
|
+
receiver: "brain:ingest",
|
|
2834
|
+
summary: "Ingest one document (Drive file, URL, or inline text) into a corpus: fetch -> markdown -> chunk -> hash-gate -> embed -> upsert with document provenance. Idempotent on content_hash.",
|
|
2835
|
+
request: z.object({
|
|
2836
|
+
corpus: z.string().describe("Target brain @-pointer. Authority-walked (write_corpus)."),
|
|
2837
|
+
source_ref: z.string().optional().describe("Drive file id or URL — the stable key for tombstones + hash-gate."),
|
|
2838
|
+
document_url: z.string().optional().describe("Fetch URL for the document."),
|
|
2839
|
+
raw_text: z.string().optional().describe("Inline markdown/text/html."),
|
|
2840
|
+
mime_type: z.string().optional(),
|
|
2841
|
+
content_hash: z.string().optional(),
|
|
2842
|
+
title: z.string().optional(),
|
|
2843
|
+
tags: z.array(z.string()).optional(),
|
|
2844
|
+
}),
|
|
2845
|
+
response: z.object({
|
|
2846
|
+
ok: z.boolean(),
|
|
2847
|
+
corpus: z.string().optional(),
|
|
2848
|
+
source_ref: z.string().optional(),
|
|
2849
|
+
content_hash: z.string().optional(),
|
|
2850
|
+
chunks: z.number().optional(),
|
|
2851
|
+
skipped: z.boolean().optional().describe("True when content_hash matched (no re-embed)."),
|
|
2852
|
+
reason: z.string().optional(),
|
|
2853
|
+
}),
|
|
2854
|
+
effect: "ask", auth: "write_corpus", cost: { fixed: 1 }, reversible: false, idempotent: true,
|
|
2855
|
+
}),
|
|
2856
|
+
"brain:provision": receiver({
|
|
2857
|
+
receiver: "brain:provision",
|
|
2858
|
+
summary: "Idempotently create a workspace or personal brain: a corpus thing @<slug>-brain contained by the owning group. Safe to call repeatedly (put). Auth walks the workspace group (the corpus does not exist yet).",
|
|
2859
|
+
request: z.object({
|
|
2860
|
+
slug: z.string().describe("Target workspace or personal slug."),
|
|
2861
|
+
kind: z.enum(["workspace", "personal"]).optional().default("workspace"),
|
|
2862
|
+
actorId: z.string().optional(),
|
|
2863
|
+
}),
|
|
2864
|
+
response: z.object({
|
|
2865
|
+
ok: z.boolean(),
|
|
2866
|
+
corpus: z.string().optional().describe("The provisioned @-pointer, e.g. @acme-brain."),
|
|
2867
|
+
slug: z.string().optional(),
|
|
2868
|
+
kind: z.string().optional(),
|
|
2869
|
+
reason: z.string().optional(),
|
|
2870
|
+
}),
|
|
2871
|
+
effect: "ask", auth: "write_corpus", cost: "free", reversible: false, idempotent: true,
|
|
2872
|
+
}),
|
|
2873
|
+
"brain:tombstone": receiver({
|
|
2874
|
+
receiver: "brain:tombstone",
|
|
2875
|
+
summary: "Remove a deleted source document's chunks from a corpus, keyed by source_ref (Drive file id or URL). Fired by ingest-tick when a previously-known file no longer appears in a folder listing.",
|
|
2876
|
+
request: z.object({
|
|
2877
|
+
corpus: z.string().describe("Target brain @-pointer. Authority-walked (write_corpus)."),
|
|
2878
|
+
source_ref: z.string().describe("The stable key used at ingest — Drive file id or URL."),
|
|
2879
|
+
}),
|
|
2880
|
+
response: z.object({
|
|
2881
|
+
ok: z.boolean(),
|
|
2882
|
+
corpus: z.string().optional(),
|
|
2883
|
+
source_ref: z.string().optional(),
|
|
2884
|
+
removed: z.number().optional().describe("Chunk rows deleted."),
|
|
2885
|
+
reason: z.string().optional(),
|
|
2886
|
+
}),
|
|
2887
|
+
effect: "ask", auth: "write_corpus", cost: "free", reversible: false, idempotent: true,
|
|
2888
|
+
}),
|
|
2889
|
+
"rag:promote": receiver({
|
|
2890
|
+
receiver: "rag:promote",
|
|
2891
|
+
summary: "Distill repeat retrieval winners into typed fact. Sweeps retrieval_outcomes for chunks with >=5 mark and 0 warn in a 14-day window, extracts a verbatim statement (no synthesis), and writes it via memory:remember into the chunk's owning group. Fired by the promote-tick cron trigger; safe to call anonymously — the target group is derived from data, never a caller-supplied workspace.",
|
|
2892
|
+
request: z.object({}),
|
|
2893
|
+
response: z.object({
|
|
2894
|
+
ok: z.boolean(),
|
|
2895
|
+
promoted: z.number().optional(),
|
|
2896
|
+
skipped: z.number().optional(),
|
|
2897
|
+
reason: z.string().optional(),
|
|
2898
|
+
}),
|
|
2899
|
+
effect: "ask", auth: "public", cost: "free", reversible: false, idempotent: true,
|
|
2900
|
+
}),
|
|
2538
2901
|
// ── seo — handlers in resolvers/seo.ts (C1 live; C2 async) ─────────────────
|
|
2539
2902
|
"seo:backlinks-summary": receiver({
|
|
2540
2903
|
receiver: "seo:backlinks-summary",
|