@frockbot/applet-sdk 0.7.108 → 0.7.109
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/package.json +1 -1
- package/plugin/index.d.ts +147 -0
- package/plugin/template/plugin.json +1 -1
- package/src/build/plugin.ts +18 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frockbot/applet-sdk",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.109",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Authoring SDK for FrockBot Applets: schema-first Durable Object server, TanStack DB client, component kit, linter, and the build pipeline.",
|
package/plugin/index.d.ts
CHANGED
|
@@ -261,6 +261,34 @@ export interface PluginContext {
|
|
|
261
261
|
readonly connection?: (
|
|
262
262
|
connectionId: string,
|
|
263
263
|
) => Promise<ConnectionLease | CapabilityFailure>;
|
|
264
|
+
/**
|
|
265
|
+
* The `http` grant, second half: the deployment's own sender, sending for
|
|
266
|
+
* this Bot. The Plugin holds no credential and names no provider; a
|
|
267
|
+
* deployment that has bound no sender answers unavailable.
|
|
268
|
+
*/
|
|
269
|
+
readonly email?: (request: {
|
|
270
|
+
/**
|
|
271
|
+
* The Approval whose decision authorizes this send. The kernel refuses a
|
|
272
|
+
* send whose Approval is missing, undecided, denied, expired or already
|
|
273
|
+
* spent, so one decision sends at most one message.
|
|
274
|
+
*/
|
|
275
|
+
approvalId: string;
|
|
276
|
+
/**
|
|
277
|
+
* The Card that decision was given on. The Approval is bound to the
|
|
278
|
+
* surface and to the values it was showing, so a send whose message is
|
|
279
|
+
* not the one that was approved is refused.
|
|
280
|
+
*/
|
|
281
|
+
surfaceId: string;
|
|
282
|
+
to: string[];
|
|
283
|
+
cc?: string[];
|
|
284
|
+
subject: string;
|
|
285
|
+
body: string;
|
|
286
|
+
/** The `Message-Id` this answers, when it answers one. */
|
|
287
|
+
inReplyTo?: string;
|
|
288
|
+
}) => Promise<
|
|
289
|
+
| { status: "sent"; messageId: string; undelivered?: string[] }
|
|
290
|
+
| CapabilityFailure
|
|
291
|
+
>;
|
|
264
292
|
/** The `schedule` grant: a durable Routine operation attributed to this call. */
|
|
265
293
|
readonly schedule?: (request: {
|
|
266
294
|
callId: string;
|
|
@@ -429,6 +457,119 @@ export type PluginView = (
|
|
|
429
457
|
| undefined
|
|
430
458
|
| void;
|
|
431
459
|
|
|
460
|
+
/**
|
|
461
|
+
* One A2UI message a Card is made of: the envelope plus exactly one of
|
|
462
|
+
* `createSurface`, `updateComponents`, `updateDataModel` or `deleteSurface`.
|
|
463
|
+
* The kernel decodes and bounds it, so it is carried loosely here.
|
|
464
|
+
*/
|
|
465
|
+
export interface CardMessage {
|
|
466
|
+
version: "v1.0";
|
|
467
|
+
[key: string]: unknown;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/** What a card's `render` is handed: the surface the kernel minted and the Bot's values. */
|
|
471
|
+
export interface PluginCardRender {
|
|
472
|
+
/** The kernel's own surface id. A Plugin never chooses one. */
|
|
473
|
+
surfaceId: string;
|
|
474
|
+
/** The values the Bot sent, already validated against the card's `dataSchema`. */
|
|
475
|
+
data: { [key: string]: unknown };
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/** What a card action handler is handed: the press, as the person made it. */
|
|
479
|
+
export interface PluginCardPress {
|
|
480
|
+
/** The card this press is on — the one the pressed surface was drawn from. */
|
|
481
|
+
cardId: string;
|
|
482
|
+
surfaceId: string;
|
|
483
|
+
/** The `<action>` half of the `plugin/<pluginId>/<action>` that was pressed. */
|
|
484
|
+
action: string;
|
|
485
|
+
context?: { [key: string]: unknown };
|
|
486
|
+
/** The surface's data model, when the surface was created asking for it. */
|
|
487
|
+
dataModel?: { [key: string]: unknown };
|
|
488
|
+
/**
|
|
489
|
+
* The Card's data model as the kernel stores it: what the surface is made
|
|
490
|
+
* of, rather than what the client sent back. A handler reads the state of
|
|
491
|
+
* its own card here instead of keeping a second copy keyed by surface id.
|
|
492
|
+
*/
|
|
493
|
+
record?: { [key: string]: unknown };
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/** A card handler's refusal: the Card is left exactly as it was. */
|
|
497
|
+
export interface PluginCardDrop {
|
|
498
|
+
drop: true;
|
|
499
|
+
reason?: string;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* What a card handler answers with: the messages the kernel folds into the
|
|
504
|
+
* Card, on their own or with `input` — one line for the Bot's next Turn, the
|
|
505
|
+
* only thing a press may say to the Bot rather than to the card. `render`
|
|
506
|
+
* never carries `input`; a draw is not a press.
|
|
507
|
+
*/
|
|
508
|
+
export type PluginCardAnswer =
|
|
509
|
+
| CardMessage[]
|
|
510
|
+
| { messages: CardMessage[]; input?: string }
|
|
511
|
+
| PluginCardDrop
|
|
512
|
+
| undefined
|
|
513
|
+
| void;
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* What a card's `render` answers with. The same messages a press answers
|
|
517
|
+
* with, and beside them `covers`: the canonical values a decision on this
|
|
518
|
+
* card would authorize. The Plugin states them because the Plugin, not the
|
|
519
|
+
* model, decides what the card draws — a redraw that ignores the Bot's values
|
|
520
|
+
* and shows the draft it is holding covers that draft. A draw that puts an
|
|
521
|
+
* `ApprovalActions` on the card and declares no `covers`, or no `decision`,
|
|
522
|
+
* is refused, so a decision bound to nothing — or asked in no words — cannot
|
|
523
|
+
* exist.
|
|
524
|
+
*/
|
|
525
|
+
export type PluginCardDraw =
|
|
526
|
+
| CardMessage[]
|
|
527
|
+
| {
|
|
528
|
+
messages: CardMessage[];
|
|
529
|
+
covers?: { [key: string]: unknown };
|
|
530
|
+
decision?: PluginCardDecision;
|
|
531
|
+
}
|
|
532
|
+
| PluginCardDrop
|
|
533
|
+
| undefined
|
|
534
|
+
| void;
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* The words the decision a card asks for is recorded with. They are stated
|
|
538
|
+
* here rather than on the `ApprovalActions` component because the Frock
|
|
539
|
+
* catalog allows that component an `approvalId` and its two labels and
|
|
540
|
+
* nothing else: the host draws the labels, the kernel records the Approval
|
|
541
|
+
* with these, and a draw that asks for a decision and states none is refused.
|
|
542
|
+
*/
|
|
543
|
+
export interface PluginCardDecision {
|
|
544
|
+
/** What the person is asked, in their words: "Send an email to …". */
|
|
545
|
+
action: string;
|
|
546
|
+
/** What getting it wrong costs. */
|
|
547
|
+
risk: "low" | "medium" | "high";
|
|
548
|
+
/** Why, when the action does not say. */
|
|
549
|
+
rationale?: string;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* One Card the Plugin draws (ADR 0030). `render` composes the surface from
|
|
554
|
+
* the catalogs the client compiled in; `actions` are the handlers behind the
|
|
555
|
+
* names the surface's components raise. An action name is the Plugin's, not
|
|
556
|
+
* one card's — the namespace is `plugin/<pluginId>/<action>` — so two cards
|
|
557
|
+
* may not declare the same one.
|
|
558
|
+
*/
|
|
559
|
+
export interface PluginCard {
|
|
560
|
+
render(
|
|
561
|
+
payload: PluginCardRender,
|
|
562
|
+
ctx: PluginContext,
|
|
563
|
+
): Promise<PluginCardDraw> | PluginCardDraw;
|
|
564
|
+
actions?: Record<
|
|
565
|
+
string,
|
|
566
|
+
(
|
|
567
|
+
press: PluginCardPress,
|
|
568
|
+
ctx: PluginContext,
|
|
569
|
+
) => Promise<PluginCardAnswer> | PluginCardAnswer
|
|
570
|
+
>;
|
|
571
|
+
}
|
|
572
|
+
|
|
432
573
|
/**
|
|
433
574
|
* A tool call's answer. A string is handed to the Bot as it is; anything else
|
|
434
575
|
* is JSON-serialized. Throw to answer with an error the Bot can read — the
|
|
@@ -464,4 +605,10 @@ export interface PluginModule {
|
|
|
464
605
|
* with slot `settings.sections`: a section drawn on this Plugin's card.
|
|
465
606
|
*/
|
|
466
607
|
views?: Record<string, PluginView>;
|
|
608
|
+
/**
|
|
609
|
+
* One entry per card id declared under `cards` in `plugin.json`. The Bot
|
|
610
|
+
* calls the card's tool with the values, the kernel validates them against
|
|
611
|
+
* the card's `dataSchema` and `render` answers with the surface.
|
|
612
|
+
*/
|
|
613
|
+
cards?: Record<string, PluginCard>;
|
|
467
614
|
}
|
package/src/build/plugin.ts
CHANGED
|
@@ -52,6 +52,8 @@ export interface PluginDescriptionV1 {
|
|
|
52
52
|
services: string[];
|
|
53
53
|
triggers: string[];
|
|
54
54
|
views: string[];
|
|
55
|
+
/** The cards the module draws, by id (ADR 0030). */
|
|
56
|
+
cards: string[];
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
export interface PluginBuildManifestV1 extends PluginDescriptionV1 {
|
|
@@ -277,6 +279,20 @@ function names(value, label) {
|
|
|
277
279
|
});
|
|
278
280
|
}
|
|
279
281
|
|
|
282
|
+
function cardNames(value) {
|
|
283
|
+
if (value === undefined) return [];
|
|
284
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
285
|
+
throw new Error('"cards" must be an object');
|
|
286
|
+
}
|
|
287
|
+
return Object.keys(value).map(function (cardId) {
|
|
288
|
+
var card = value[cardId];
|
|
289
|
+
if (!card || typeof card.render !== "function") {
|
|
290
|
+
throw new Error('card "' + cardId + '" must export a render function');
|
|
291
|
+
}
|
|
292
|
+
return cardId;
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
|
|
280
296
|
function describe() {
|
|
281
297
|
if (!Array.isArray(plugin.tools)) {
|
|
282
298
|
throw new Error('the module must export a "tools" array');
|
|
@@ -303,6 +319,7 @@ function describe() {
|
|
|
303
319
|
services: names(plugin.services, "services"),
|
|
304
320
|
triggers: names(plugin.triggers, "triggers"),
|
|
305
321
|
views: names(plugin.views, "views"),
|
|
322
|
+
cards: cardNames(plugin.cards),
|
|
306
323
|
};
|
|
307
324
|
}
|
|
308
325
|
|
|
@@ -396,6 +413,7 @@ function validateDescription(input: PluginDescriptionV1): PluginDescriptionV1 {
|
|
|
396
413
|
services: [...input.services],
|
|
397
414
|
triggers: [...input.triggers],
|
|
398
415
|
views: [...input.views],
|
|
416
|
+
cards: [...(input.cards ?? [])],
|
|
399
417
|
};
|
|
400
418
|
}
|
|
401
419
|
|