@cellarnode/ui 0.201.1 → 0.202.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/agent/composer.d.ts +6 -1
- package/dist/agent/composer.d.ts.map +1 -1
- package/dist/agent/composer.js +43 -9
- package/dist/agent/composer.js.map +1 -1
- package/dist/agent/conversation.d.ts +20 -2
- package/dist/agent/conversation.d.ts.map +1 -1
- package/dist/agent/conversation.js +37 -5
- package/dist/agent/conversation.js.map +1 -1
- package/dist/agent/copy.d.ts +7 -0
- package/dist/agent/copy.d.ts.map +1 -1
- package/dist/agent/copy.js +9 -0
- package/dist/agent/copy.js.map +1 -1
- package/dist/agent/fixtures.d.ts +34 -0
- package/dist/agent/fixtures.d.ts.map +1 -1
- package/dist/agent/fixtures.js +77 -0
- package/dist/agent/fixtures.js.map +1 -1
- package/dist/agent/index.d.ts +18 -1
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +18 -1
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/markdown.d.ts +64 -0
- package/dist/agent/markdown.d.ts.map +1 -0
- package/dist/agent/markdown.js +220 -0
- package/dist/agent/markdown.js.map +1 -0
- package/dist/agent/masked-value.d.ts +1 -0
- package/dist/agent/masked-value.d.ts.map +1 -1
- package/dist/agent/masked-value.js +4 -1
- package/dist/agent/masked-value.js.map +1 -1
- package/dist/agent/message.d.ts +26 -6
- package/dist/agent/message.d.ts.map +1 -1
- package/dist/agent/message.js +47 -11
- package/dist/agent/message.js.map +1 -1
- package/dist/agent/panel-frame.js +1 -1
- package/dist/agent/panel-frame.js.map +1 -1
- package/dist/agent/role-cards/card-kit.d.ts +111 -0
- package/dist/agent/role-cards/card-kit.d.ts.map +1 -0
- package/dist/agent/role-cards/card-kit.js +68 -0
- package/dist/agent/role-cards/card-kit.js.map +1 -0
- package/dist/agent/role-cards/data-table-card.d.ts +80 -0
- package/dist/agent/role-cards/data-table-card.d.ts.map +1 -0
- package/dist/agent/role-cards/data-table-card.js +214 -0
- package/dist/agent/role-cards/data-table-card.js.map +1 -0
- package/dist/agent/role-cards/fixtures.d.ts +124 -0
- package/dist/agent/role-cards/fixtures.d.ts.map +1 -0
- package/dist/agent/role-cards/fixtures.js +401 -0
- package/dist/agent/role-cards/fixtures.js.map +1 -0
- package/dist/agent/role-cards/host-contract.d.ts +214 -0
- package/dist/agent/role-cards/host-contract.d.ts.map +1 -0
- package/dist/agent/role-cards/host-contract.js +348 -0
- package/dist/agent/role-cards/host-contract.js.map +1 -0
- package/dist/agent/role-cards/inspector-drawer.d.ts +42 -0
- package/dist/agent/role-cards/inspector-drawer.d.ts.map +1 -0
- package/dist/agent/role-cards/inspector-drawer.js +68 -0
- package/dist/agent/role-cards/inspector-drawer.js.map +1 -0
- package/dist/agent/role-cards/inspector-fixtures.d.ts +84 -0
- package/dist/agent/role-cards/inspector-fixtures.d.ts.map +1 -0
- package/dist/agent/role-cards/inspector-fixtures.js +162 -0
- package/dist/agent/role-cards/inspector-fixtures.js.map +1 -0
- package/dist/agent/role-cards/inspector-record.d.ts +109 -0
- package/dist/agent/role-cards/inspector-record.d.ts.map +1 -0
- package/dist/agent/role-cards/inspector-record.js +346 -0
- package/dist/agent/role-cards/inspector-record.js.map +1 -0
- package/dist/agent/role-cards/inspector-view.d.ts +137 -0
- package/dist/agent/role-cards/inspector-view.d.ts.map +1 -0
- package/dist/agent/role-cards/inspector-view.js +261 -0
- package/dist/agent/role-cards/inspector-view.js.map +1 -0
- package/dist/agent/role-cards/match-card.d.ts +21 -0
- package/dist/agent/role-cards/match-card.d.ts.map +1 -0
- package/dist/agent/role-cards/match-card.js +30 -0
- package/dist/agent/role-cards/match-card.js.map +1 -0
- package/dist/agent/role-cards/offer-card.d.ts +27 -0
- package/dist/agent/role-cards/offer-card.d.ts.map +1 -0
- package/dist/agent/role-cards/offer-card.js +68 -0
- package/dist/agent/role-cards/offer-card.js.map +1 -0
- package/dist/agent/role-cards/opportunity-card.d.ts +26 -0
- package/dist/agent/role-cards/opportunity-card.d.ts.map +1 -0
- package/dist/agent/role-cards/opportunity-card.js +50 -0
- package/dist/agent/role-cards/opportunity-card.js.map +1 -0
- package/dist/agent/role-cards/product-card.d.ts +32 -0
- package/dist/agent/role-cards/product-card.d.ts.map +1 -0
- package/dist/agent/role-cards/product-card.js +50 -0
- package/dist/agent/role-cards/product-card.js.map +1 -0
- package/dist/agent/role-cards/proposal-diff.d.ts +38 -0
- package/dist/agent/role-cards/proposal-diff.d.ts.map +1 -0
- package/dist/agent/role-cards/proposal-diff.js +74 -0
- package/dist/agent/role-cards/proposal-diff.js.map +1 -0
- package/dist/agent/role-cards/registry.d.ts +43 -0
- package/dist/agent/role-cards/registry.d.ts.map +1 -0
- package/dist/agent/role-cards/registry.js +46 -0
- package/dist/agent/role-cards/registry.js.map +1 -0
- package/dist/agent/role-cards/score-meter.d.ts +12 -0
- package/dist/agent/role-cards/score-meter.d.ts.map +1 -0
- package/dist/agent/role-cards/score-meter.js +17 -0
- package/dist/agent/role-cards/score-meter.js.map +1 -0
- package/dist/agent/role-cards/surface-links.d.ts +54 -0
- package/dist/agent/role-cards/surface-links.d.ts.map +1 -0
- package/dist/agent/role-cards/surface-links.js +149 -0
- package/dist/agent/role-cards/surface-links.js.map +1 -0
- package/dist/agent/role-cards/text-safety.d.ts +24 -0
- package/dist/agent/role-cards/text-safety.d.ts.map +1 -0
- package/dist/agent/role-cards/text-safety.js +61 -0
- package/dist/agent/role-cards/text-safety.js.map +1 -0
- package/dist/agent/schema.d.ts +7 -0
- package/dist/agent/schema.d.ts.map +1 -1
- package/dist/agent/schema.js +25 -2
- package/dist/agent/schema.js.map +1 -1
- package/dist/agent/states.d.ts +1 -0
- package/dist/agent/states.d.ts.map +1 -1
- package/dist/agent/states.js +1 -1
- package/dist/agent/states.js.map +1 -1
- package/dist/agent/thinking.d.ts +13 -4
- package/dist/agent/thinking.d.ts.map +1 -1
- package/dist/agent/thinking.js +15 -6
- package/dist/agent/thinking.js.map +1 -1
- package/dist/agent/thread-list.d.ts +33 -2
- package/dist/agent/thread-list.d.ts.map +1 -1
- package/dist/agent/thread-list.js +158 -8
- package/dist/agent/thread-list.js.map +1 -1
- package/dist/agent/tool-activity-model.d.ts +136 -0
- package/dist/agent/tool-activity-model.d.ts.map +1 -0
- package/dist/agent/tool-activity-model.js +288 -0
- package/dist/agent/tool-activity-model.js.map +1 -0
- package/dist/agent/tool-activity.d.ts +55 -0
- package/dist/agent/tool-activity.d.ts.map +1 -0
- package/dist/agent/tool-activity.js +159 -0
- package/dist/agent/tool-activity.js.map +1 -0
- package/dist/agent/tool-call-card.d.ts +9 -1
- package/dist/agent/tool-call-card.d.ts.map +1 -1
- package/dist/agent/tool-call-card.js +7 -1
- package/dist/agent/tool-call-card.js.map +1 -1
- package/dist/agent/ui.js +1 -1
- package/dist/agent/ui.js.map +1 -1
- package/dist/agent/use-motion.d.ts +15 -0
- package/dist/agent/use-motion.d.ts.map +1 -0
- package/dist/agent/use-motion.js +52 -0
- package/dist/agent/use-motion.js.map +1 -0
- package/dist/chat/use-stick-to-bottom.d.ts +5 -0
- package/dist/chat/use-stick-to-bottom.d.ts.map +1 -1
- package/dist/chat/use-stick-to-bottom.js +11 -1
- package/dist/chat/use-stick-to-bottom.js.map +1 -1
- package/dist/components/sheet.d.ts +3 -1
- package/dist/components/sheet.d.ts.map +1 -1
- package/dist/components/sheet.js +2 -2
- package/dist/components/sheet.js.map +1 -1
- package/dist/portfolio-import/import-job-panels.d.ts +6 -0
- package/dist/portfolio-import/import-job-panels.d.ts.map +1 -1
- package/dist/portfolio-import/import-job-panels.js +11 -4
- package/dist/portfolio-import/import-job-panels.js.map +1 -1
- package/dist/portfolio-import/job-error-copy.d.ts +62 -0
- package/dist/portfolio-import/job-error-copy.d.ts.map +1 -0
- package/dist/portfolio-import/job-error-copy.js +78 -0
- package/dist/portfolio-import/job-error-copy.js.map +1 -0
- package/dist/realtime/organisation-events/schemas.d.ts +2 -2
- package/package.json +4 -1
- package/src/theme/tokens.css +66 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import type { CardAction, CardDetail, CardProposal, DataTableData, MatchCardData, OfferCardData, OpportunityCardData, ProductCardData } from "@cellarnode/agent-cards/zod4";
|
|
2
|
+
/**
|
|
3
|
+
* @internal The HOST side of the card contract (CEL-2445, `@cellarnode/agent-cards` README "Host contract (MUST)").
|
|
4
|
+
* A card's `actions` and `proposal` are claims by the model. These pure helpers are where a host turns a claim into
|
|
5
|
+
* something it may act on, or refuses. The card composites call them THEMSELVES, so the safe path is the only path:
|
|
6
|
+
* `AgentCardActions` hands the host a `CardConfirmPlan` (never the raw action) and `AgentProposalDiff` hands it the result of
|
|
7
|
+
* `planProposalApply` (never the raw proposal).
|
|
8
|
+
*
|
|
9
|
+
* 1. the tier comes ONLY from the host catalog, by `tool` (`card.tier` is advisory; a mismatch or unknown tool drops the action);
|
|
10
|
+
* 2. the confirm plan is built from the catalog's tool title and the ACTUAL validated args, never the model's `label`;
|
|
11
|
+
* 3. `open` and `navigate` never run a tool;
|
|
12
|
+
* 4. a proposal's Apply re-fetches the record, diffs server truth against `after`, binds the tool's target-id arg to `proposal.id`,
|
|
13
|
+
* and binds the proposal to the card's subject (`expected`) and to the tool's `targetKind`;
|
|
14
|
+
* 5. args go through the tool's own input schema.
|
|
15
|
+
*
|
|
16
|
+
* No I/O except the host-supplied `fetchRecord`; nothing here runs a tool.
|
|
17
|
+
*/
|
|
18
|
+
export type CatalogTier = "read" | "reversible" | "destructive" | "costly";
|
|
19
|
+
export type DetailKind = CardProposal["kind"];
|
|
20
|
+
export interface AgentToolCatalogEntry {
|
|
21
|
+
name: string;
|
|
22
|
+
/** What the confirm UI calls the tool. Comes from the catalog, never from a card. */
|
|
23
|
+
title: string;
|
|
24
|
+
tier: CatalogTier;
|
|
25
|
+
/** The tool's own input schema (any zod 3.25 or 4 schema, or anything with `safeParse`). */
|
|
26
|
+
inputSchema: {
|
|
27
|
+
safeParse: (value: unknown) => {
|
|
28
|
+
success: true;
|
|
29
|
+
data: unknown;
|
|
30
|
+
} | {
|
|
31
|
+
success: false;
|
|
32
|
+
error?: unknown;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
/** The argument that carries the id of the record the tool acts on. Required for any tool a proposal may name. */
|
|
36
|
+
targetArg?: string;
|
|
37
|
+
/** The kind of record the tool acts on. Required for any tool a proposal may name; a proposal of another kind is refused. */
|
|
38
|
+
targetKind?: DetailKind;
|
|
39
|
+
/** How a proposal's changes become this tool's args. Default: one arg per change path. `targetArg` is bound to `proposal.id` AFTER this runs. */
|
|
40
|
+
argsFromChanges?: (changes: CardProposal["changes"], id: string) => Record<string, unknown>;
|
|
41
|
+
/** The human label of a fetched record for the confirm title. Default: its `name`, `title` or `label` string. */
|
|
42
|
+
recordLabel?: (record: Record<string, unknown>) => string | undefined;
|
|
43
|
+
}
|
|
44
|
+
export type AgentToolCatalog = Readonly<Record<string, AgentToolCatalogEntry>>;
|
|
45
|
+
export type DropReason = "unknown_tool" | "tier_mismatch" | "tool_on_navigation" | "tool_missing";
|
|
46
|
+
export interface DroppedAction {
|
|
47
|
+
id: string;
|
|
48
|
+
reason: DropReason;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Rules 1 and 3 over a card's actions. Keeps an action only when it is safe to offer: an `open`/`navigate` carries no tool,
|
|
52
|
+
* an `edit`/`propose` names a tool the catalog knows, and a declared `tier` equals the catalog's. Everything else is dropped
|
|
53
|
+
* (never "corrected"), and the reasons are returned for logging.
|
|
54
|
+
*/
|
|
55
|
+
export declare function resolveCardActions(actions: readonly CardAction[] | undefined, catalog: AgentToolCatalog): {
|
|
56
|
+
actions: CardAction[];
|
|
57
|
+
dropped: DroppedAction[];
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* `resolveCardActions`, then what the person SEES comes from the catalog, not the model: a write is labelled with the catalog
|
|
61
|
+
* title ("Tidy up" cannot front a delete) and its `tier` is stamped from the catalog, so danger styling and the confirm hint
|
|
62
|
+
* never depend on what the model declared. A read tool keeps the model's caption and carries no tier.
|
|
63
|
+
*/
|
|
64
|
+
export declare function actionsForDisplay(actions: readonly CardAction[] | undefined, catalog: AgentToolCatalog | undefined): CardAction[];
|
|
65
|
+
/**
|
|
66
|
+
* The actions a card actually OFFERS the person: what `actionsForDisplay` accepts, and then only what the host can act on. A tool
|
|
67
|
+
* action needs the host's `onAction` (`canRunTools`); a link needs the host's `allowLink` to accept its `href`. The one rule behind
|
|
68
|
+
* both the action row and anything that decides whether to draw a row at all.
|
|
69
|
+
*/
|
|
70
|
+
export declare function offeredActions(actions: readonly CardAction[] | undefined, catalog: AgentToolCatalog | undefined, host: {
|
|
71
|
+
canRunTools: boolean;
|
|
72
|
+
allowLink?: (path: string) => boolean;
|
|
73
|
+
}): CardAction[];
|
|
74
|
+
export interface ConfirmRow {
|
|
75
|
+
/** The argument name. */
|
|
76
|
+
label: string;
|
|
77
|
+
value: string;
|
|
78
|
+
}
|
|
79
|
+
export interface CardConfirmPlan {
|
|
80
|
+
tool: string;
|
|
81
|
+
/** The catalog's title for the tool, followed by the fetched record's name when there is one. NEVER the card's `label`. */
|
|
82
|
+
title: string;
|
|
83
|
+
/** The catalog's tier. */
|
|
84
|
+
tier: CatalogTier;
|
|
85
|
+
/** Every non-read tool confirms. */
|
|
86
|
+
requiresConfirm: boolean;
|
|
87
|
+
/** The validated arguments the tool would receive. */
|
|
88
|
+
args: Record<string, unknown>;
|
|
89
|
+
/** The same arguments, one row each, for the confirm UI. */
|
|
90
|
+
rows: ConfirmRow[];
|
|
91
|
+
/** The fetched record's label (a proposal's subject), when it has one. */
|
|
92
|
+
subject?: string;
|
|
93
|
+
}
|
|
94
|
+
export type BuildConfirmFailure = "not_a_tool_action" | "unknown_tool" | "tier_mismatch" | "invalid_args";
|
|
95
|
+
/**
|
|
96
|
+
* Rules 1, 2, 3 and 5 for one action: the plan the confirm UI renders. Its title, tier and rows come from the catalog and
|
|
97
|
+
* the tool's validated args; the action's `label` is not read.
|
|
98
|
+
*/
|
|
99
|
+
export declare function buildConfirm(action: CardAction, catalog: AgentToolCatalog): {
|
|
100
|
+
ok: true;
|
|
101
|
+
plan: CardConfirmPlan;
|
|
102
|
+
} | {
|
|
103
|
+
ok: false;
|
|
104
|
+
reason: BuildConfirmFailure;
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Find a dotted or bracketed path (`a.b[0].c`) in a record. `found` is false for a missing key, so "absent" is not confused with
|
|
108
|
+
* a present `null`. Refuses prototype keys and array `length`.
|
|
109
|
+
*/
|
|
110
|
+
export declare function lookupPath(record: unknown, path: string): {
|
|
111
|
+
found: boolean;
|
|
112
|
+
value: unknown;
|
|
113
|
+
};
|
|
114
|
+
/** The value at a path, or `undefined` when absent. */
|
|
115
|
+
export declare function readPath(record: unknown, path: string): unknown;
|
|
116
|
+
/** The record's own name: the first of `name`, `title`, `label` that is a string. Not yet cleaned. */
|
|
117
|
+
export declare const recordName: (record: Record<string, unknown>) => string | undefined;
|
|
118
|
+
/**
|
|
119
|
+
* The host's own label for a fetched record, when its catalog has one: the `recordLabel` of a tool that acts on this kind of record
|
|
120
|
+
* (the tools a card names come first). Cleaned like a confirm title. `undefined` when no tool has one or it yields nothing. A
|
|
121
|
+
* `recordLabel` is host code: one that throws is skipped, never allowed to take the drawer down.
|
|
122
|
+
*/
|
|
123
|
+
export declare function catalogRecordLabel(catalog: AgentToolCatalog | undefined, kind: DetailKind, record: Record<string, unknown>, toolsNamedByCard?: readonly (string | undefined)[]): string | undefined;
|
|
124
|
+
export interface ProposalDiffRow {
|
|
125
|
+
path: string;
|
|
126
|
+
/** What the SERVER has now (from the re-fetched record). The model's `before` is never shown as truth. */
|
|
127
|
+
before: unknown;
|
|
128
|
+
after: CardProposal["changes"][number]["after"];
|
|
129
|
+
/** What the model claimed `before` was ("proposed from"); kept so a stale refusal can show the mismatch. */
|
|
130
|
+
claimedBefore: CardProposal["changes"][number]["before"];
|
|
131
|
+
/** `already_applied`: the server already has `after`. `pending`: the server still has what the model said. */
|
|
132
|
+
state: "pending" | "already_applied";
|
|
133
|
+
}
|
|
134
|
+
export type ApplyProposalFailure = "unknown_tool" | "tier_mismatch" | "no_target_arg" | "no_target_kind" | "kind_mismatch" | "subject_mismatch" | "target_override" | "record_unavailable" | "unknown_path" | "stale" | "nothing_to_apply" | "invalid_args";
|
|
135
|
+
export interface ProposalApplyPlan {
|
|
136
|
+
plan: CardConfirmPlan;
|
|
137
|
+
/** Server truth against `after`, one row per change (already-applied rows included, marked). */
|
|
138
|
+
diff: ProposalDiffRow[];
|
|
139
|
+
/** The proposal this plan was built for. */
|
|
140
|
+
proposal: CardProposal;
|
|
141
|
+
}
|
|
142
|
+
export type PlanProposalResult = ({
|
|
143
|
+
ok: true;
|
|
144
|
+
} & ProposalApplyPlan) | {
|
|
145
|
+
ok: false;
|
|
146
|
+
reason: ApplyProposalFailure;
|
|
147
|
+
conflicts?: ProposalDiffRow[];
|
|
148
|
+
paths?: string[];
|
|
149
|
+
};
|
|
150
|
+
/**
|
|
151
|
+
* Rule 4 (with 1, 2 and 5): what a proposal's Apply may do. `expected` is the subject the CARD is about (its `detail`, or its
|
|
152
|
+
* offerId or matchId): a proposal for any other record is refused, as is one whose `kind` is not the tool's `targetKind`.
|
|
153
|
+
* Re-fetches the record by `kind` + `id`; a change whose path is absent from it is refused, a change whose `before` no longer
|
|
154
|
+
* matches is STALE and refuses the whole proposal, one already at `after` is skipped; the tool's `targetArg` is bound to
|
|
155
|
+
* `proposal.id` (a change that tries to set it is refused); the args go through the tool's input schema; the plan title names
|
|
156
|
+
* the fetched record.
|
|
157
|
+
*/
|
|
158
|
+
export declare function planProposalApply(proposal: CardProposal, catalog: AgentToolCatalog, fetchRecord: (kind: DetailKind, id: string) => Promise<unknown>, expected: Pick<CardDetail, "kind" | "id">): Promise<PlanProposalResult>;
|
|
159
|
+
/** The subject a card is about: its `detail` pointer. Cards that carry an id of their own (offer, match) pass it explicitly. */
|
|
160
|
+
export declare const subjectOf: (detail: CardDetail | undefined, fallback?: Pick<CardDetail, "kind" | "id">) => Pick<CardDetail, "kind" | "id"> | undefined;
|
|
161
|
+
/**
|
|
162
|
+
* Rules 1 and 3 over a whole parsed card: keeps only the actions `actionsForDisplay` accepts and drops a `proposal` whose tool is
|
|
163
|
+
* unknown, whose tier differs from the catalog's or whose tool lacks a `targetArg` or `targetKind`. With NO catalog every
|
|
164
|
+
* tool-bearing action and every proposal is dropped (secure default): only `open`/`navigate`/tool-less actions remain.
|
|
165
|
+
*/
|
|
166
|
+
export declare function sanitizeCardForHost<T extends {
|
|
167
|
+
actions?: CardAction[];
|
|
168
|
+
proposal?: CardProposal;
|
|
169
|
+
}>(card: T, catalog: AgentToolCatalog | undefined): T;
|
|
170
|
+
export declare const ROLE_AGENT_CARD_TYPES: readonly ["OfferCard", "ProductCard", "OpportunityCard", "MatchCard", "DataTable"];
|
|
171
|
+
export type RoleAgentCardType = (typeof ROLE_AGENT_CARD_TYPES)[number];
|
|
172
|
+
/** The cards that are about ONE record. A `DataTable` is a list: it has no subject, and `readRoleCard` drops any pointer it carries. */
|
|
173
|
+
type RecordCardType = Exclude<RoleAgentCardType, "DataTable">;
|
|
174
|
+
/**
|
|
175
|
+
* Does the card's `detail` pointer name what the card is about? An offer's or a match's must name its own id, a product's must be a
|
|
176
|
+
* product or a variant, an opportunity's an opportunity. A card with no pointer agrees (nothing to disagree with). The cards and
|
|
177
|
+
* `readRoleCard` both call this, so a disagreeing card is refused the same way everywhere, never reconciled.
|
|
178
|
+
*/
|
|
179
|
+
export declare function detailAgrees(cardType: RecordCardType, data: {
|
|
180
|
+
detail?: CardDetail;
|
|
181
|
+
offerId?: string;
|
|
182
|
+
matchId?: string;
|
|
183
|
+
}): boolean;
|
|
184
|
+
type Subject = Pick<CardDetail, "kind" | "id">;
|
|
185
|
+
export type RoleCardRead = {
|
|
186
|
+
cardType: "OfferCard";
|
|
187
|
+
data: OfferCardData;
|
|
188
|
+
subject: Subject;
|
|
189
|
+
} | {
|
|
190
|
+
cardType: "MatchCard";
|
|
191
|
+
data: MatchCardData;
|
|
192
|
+
subject: Subject;
|
|
193
|
+
} | {
|
|
194
|
+
cardType: "ProductCard";
|
|
195
|
+
data: ProductCardData;
|
|
196
|
+
subject: Subject | undefined;
|
|
197
|
+
} | {
|
|
198
|
+
cardType: "OpportunityCard";
|
|
199
|
+
data: OpportunityCardData;
|
|
200
|
+
subject: Subject | undefined;
|
|
201
|
+
} | {
|
|
202
|
+
cardType: "DataTable";
|
|
203
|
+
data: DataTableData;
|
|
204
|
+
subject: undefined;
|
|
205
|
+
};
|
|
206
|
+
/**
|
|
207
|
+
* The ONE way a host turns what an agent sent into a role card it may draw: parse against the agent-cards schema, refuse a card
|
|
208
|
+
* whose `detail` disagrees with it (`detailAgrees`), then `sanitizeCardForHost` against the host catalog. `null` for an unknown
|
|
209
|
+
* type, data that fails the schema, or a disagreeing card. `subject` is the record THIS card is about (its offerId or matchId, or its
|
|
210
|
+
* `detail`), what a proposal is bound to. `renderRoleAgentCard` and the inspector drawer both read through here.
|
|
211
|
+
*/
|
|
212
|
+
export declare function readRoleCard(cardType: string, data: unknown, catalog: AgentToolCatalog | undefined): RoleCardRead | null;
|
|
213
|
+
export {};
|
|
214
|
+
//# sourceMappingURL=host-contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-contract.d.ts","sourceRoot":"","sources":["../../../src/agent/role-cards/host-contract.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,YAAY,EACZ,aAAa,EACb,aAAa,EACb,aAAa,EACb,mBAAmB,EACnB,eAAe,EAChB,MAAM,8BAA8B,CAAC;AAGtC;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,YAAY,GAAG,aAAa,GAAG,QAAQ,CAAC;AAC3E,MAAM,MAAM,UAAU,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;AAE9C,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,qFAAqF;IACrF,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,WAAW,CAAC;IAClB,4FAA4F;IAC5F,WAAW,EAAE;QACX,SAAS,EAAE,CACT,KAAK,EAAE,OAAO,KACX;YAAE,OAAO,EAAE,IAAI,CAAC;YAAC,IAAI,EAAE,OAAO,CAAA;SAAE,GAAG;YAAE,OAAO,EAAE,KAAK,CAAC;YAAC,KAAK,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC;KAC7E,CAAC;IACF,kHAAkH;IAClH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6HAA6H;IAC7H,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,iJAAiJ;IACjJ,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5F,iHAAiH;IACjH,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,GAAG,SAAS,CAAC;CACvE;AAED,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC,CAAC;AAQ/E,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,eAAe,GAAG,oBAAoB,GAAG,cAAc,CAAC;AAClG,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,UAAU,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,SAAS,EAC1C,OAAO,EAAE,gBAAgB,GACxB;IAAE,OAAO,EAAE,UAAU,EAAE,CAAC;IAAC,OAAO,EAAE,aAAa,EAAE,CAAA;CAAE,CAuBrD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,SAAS,EAC1C,OAAO,EAAE,gBAAgB,GAAG,SAAS,GACpC,UAAU,EAAE,CAQd;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,SAAS,EAC1C,OAAO,EAAE,gBAAgB,GAAG,SAAS,EACrC,IAAI,EAAE;IAAE,WAAW,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAA;CAAE,GACpE,UAAU,EAAE,CAId;AAED,MAAM,WAAW,UAAU;IACzB,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AACD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,2HAA2H;IAC3H,KAAK,EAAE,MAAM,CAAC;IACd,0BAA0B;IAC1B,IAAI,EAAE,WAAW,CAAC;IAClB,oCAAoC;IACpC,eAAe,EAAE,OAAO,CAAC;IACzB,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,4DAA4D;IAC5D,IAAI,EAAE,UAAU,EAAE,CAAC;IACnB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,MAAM,mBAAmB,GAC3B,mBAAmB,GACnB,cAAc,GACd,eAAe,GACf,cAAc,CAAC;AA8BnB;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,gBAAgB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,eAAe,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,mBAAmB,CAAA;CAAE,CAUlF;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAW5F;AAED,uDAAuD;AACvD,wBAAgB,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE/D;AA4BD,sGAAsG;AACtG,eAAO,MAAM,UAAU,GAAI,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MAAM,GAAG,SACqB,CAAC;AAE5F;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,gBAAgB,GAAG,SAAS,EACrC,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,gBAAgB,GAAE,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC,EAAO,GACrD,MAAM,GAAG,SAAS,CAapB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,0GAA0G;IAC1G,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC;IAChD,4GAA4G;IAC5G,aAAa,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC;IACzD,8GAA8G;IAC9G,KAAK,EAAE,SAAS,GAAG,iBAAiB,CAAC;CACtC;AACD,MAAM,MAAM,oBAAoB,GAC5B,cAAc,GACd,eAAe,GACf,eAAe,GACf,gBAAgB,GAChB,eAAe,GACf,kBAAkB,GAClB,iBAAiB,GACjB,oBAAoB,GACpB,cAAc,GACd,OAAO,GACP,kBAAkB,GAClB,cAAc,CAAC;AAEnB,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,eAAe,CAAC;IACtB,gGAAgG;IAChG,IAAI,EAAE,eAAe,EAAE,CAAC;IACxB,4CAA4C;IAC5C,QAAQ,EAAE,YAAY,CAAC;CACxB;AACD,MAAM,MAAM,kBAAkB,GAC1B,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG,iBAAiB,CAAC,GAClC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,oBAAoB,CAAC;IAAC,SAAS,CAAC,EAAE,eAAe,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAEjG;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,gBAAgB,EACzB,WAAW,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EAC/D,QAAQ,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC,GACxC,OAAO,CAAC,kBAAkB,CAAC,CAoD7B;AAED,gIAAgI;AAChI,eAAO,MAAM,SAAS,GACpB,QAAQ,UAAU,GAAG,SAAS,EAC9B,WAAW,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC,KACzC,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,SACqB,CAAC;AAE3D;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS;IAAE,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,YAAY,CAAA;CAAE,EAC/F,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,gBAAgB,GAAG,SAAS,GACpC,CAAC,CAcH;AAED,eAAO,MAAM,qBAAqB,oFAMxB,CAAC;AACX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC;AAKvE,wIAAwI;AACxI,KAAK,cAAc,GAAG,OAAO,CAAC,iBAAiB,EAAE,WAAW,CAAC,CAAC;AAU9D;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,cAAc,EACxB,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,UAAU,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAChE,OAAO,CAOT;AAED,KAAK,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;AAC/C,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAChE;IAAE,QAAQ,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAChE;IAAE,QAAQ,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,OAAO,GAAG,SAAS,CAAA;CAAE,GAChF;IAAE,QAAQ,EAAE,iBAAiB,CAAC;IAAC,IAAI,EAAE,mBAAmB,CAAC;IAAC,OAAO,EAAE,OAAO,GAAG,SAAS,CAAA;CAAE,GACxF;IAAE,QAAQ,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,SAAS,CAAA;CAAE,CAAC;AAEvE;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,gBAAgB,GAAG,SAAS,GACpC,YAAY,GAAG,IAAI,CAmDrB"}
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
import { parseCard } from "@cellarnode/agent-cards/zod4";
|
|
2
|
+
import { cleanInline } from "./text-safety.js";
|
|
3
|
+
const lookup = (catalog, tool) => tool !== undefined && Object.hasOwn(catalog, tool) ? catalog[tool] : undefined;
|
|
4
|
+
/**
|
|
5
|
+
* Rules 1 and 3 over a card's actions. Keeps an action only when it is safe to offer: an `open`/`navigate` carries no tool,
|
|
6
|
+
* an `edit`/`propose` names a tool the catalog knows, and a declared `tier` equals the catalog's. Everything else is dropped
|
|
7
|
+
* (never "corrected"), and the reasons are returned for logging.
|
|
8
|
+
*/
|
|
9
|
+
export function resolveCardActions(actions, catalog) {
|
|
10
|
+
const kept = [];
|
|
11
|
+
const dropped = [];
|
|
12
|
+
for (const a of actions ?? []) {
|
|
13
|
+
if (a.kind === "open" || a.kind === "navigate") {
|
|
14
|
+
if (a.tool !== undefined || a.args !== undefined)
|
|
15
|
+
dropped.push({ id: a.id, reason: "tool_on_navigation" });
|
|
16
|
+
else
|
|
17
|
+
kept.push(a);
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
if (a.tool === undefined) {
|
|
21
|
+
if (a.kind === "edit" || a.kind === "propose")
|
|
22
|
+
dropped.push({ id: a.id, reason: "tool_missing" });
|
|
23
|
+
else
|
|
24
|
+
kept.push(a);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const entry = lookup(catalog, a.tool);
|
|
28
|
+
if (!entry)
|
|
29
|
+
dropped.push({ id: a.id, reason: "unknown_tool" });
|
|
30
|
+
else if (a.tier !== undefined && a.tier !== entry.tier)
|
|
31
|
+
dropped.push({ id: a.id, reason: "tier_mismatch" });
|
|
32
|
+
else
|
|
33
|
+
kept.push(a);
|
|
34
|
+
}
|
|
35
|
+
return { actions: kept, dropped };
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* `resolveCardActions`, then what the person SEES comes from the catalog, not the model: a write is labelled with the catalog
|
|
39
|
+
* title ("Tidy up" cannot front a delete) and its `tier` is stamped from the catalog, so danger styling and the confirm hint
|
|
40
|
+
* never depend on what the model declared. A read tool keeps the model's caption and carries no tier.
|
|
41
|
+
*/
|
|
42
|
+
export function actionsForDisplay(actions, catalog) {
|
|
43
|
+
const cat = catalog ?? {};
|
|
44
|
+
return resolveCardActions(actions, cat).actions.map((a) => {
|
|
45
|
+
const entry = lookup(cat, a.tool);
|
|
46
|
+
if (!entry)
|
|
47
|
+
return a;
|
|
48
|
+
if (entry.tier === "read")
|
|
49
|
+
return { ...a, tier: undefined };
|
|
50
|
+
return { ...a, label: entry.title, tier: entry.tier };
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The actions a card actually OFFERS the person: what `actionsForDisplay` accepts, and then only what the host can act on. A tool
|
|
55
|
+
* action needs the host's `onAction` (`canRunTools`); a link needs the host's `allowLink` to accept its `href`. The one rule behind
|
|
56
|
+
* both the action row and anything that decides whether to draw a row at all.
|
|
57
|
+
*/
|
|
58
|
+
export function offeredActions(actions, catalog, host) {
|
|
59
|
+
return actionsForDisplay(actions, catalog).filter((a) => (a.tool && host.canRunTools) || (a.href && host.allowLink?.(a.href)));
|
|
60
|
+
}
|
|
61
|
+
const show = (v) => v === null || v === undefined ? "" : typeof v === "object" ? JSON.stringify(v) : String(v);
|
|
62
|
+
function plan(entry, args, subject) {
|
|
63
|
+
return {
|
|
64
|
+
tool: entry.name,
|
|
65
|
+
title: subject ? `${entry.title}: ${subject}` : entry.title,
|
|
66
|
+
tier: entry.tier,
|
|
67
|
+
requiresConfirm: entry.tier !== "read",
|
|
68
|
+
args,
|
|
69
|
+
rows: Object.entries(args).map(([label, value]) => ({ label, value: show(value) })),
|
|
70
|
+
...(subject ? { subject } : {}),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
const validated = (entry, args) => {
|
|
74
|
+
const parsed = entry.inputSchema.safeParse(args);
|
|
75
|
+
if (!parsed.success)
|
|
76
|
+
return null;
|
|
77
|
+
const data = parsed.data;
|
|
78
|
+
return typeof data === "object" && data !== null && !Array.isArray(data)
|
|
79
|
+
? data
|
|
80
|
+
: {};
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Rules 1, 2, 3 and 5 for one action: the plan the confirm UI renders. Its title, tier and rows come from the catalog and
|
|
84
|
+
* the tool's validated args; the action's `label` is not read.
|
|
85
|
+
*/
|
|
86
|
+
export function buildConfirm(action, catalog) {
|
|
87
|
+
if (action.kind === "open" || action.kind === "navigate" || action.tool === undefined)
|
|
88
|
+
return { ok: false, reason: "not_a_tool_action" };
|
|
89
|
+
const entry = lookup(catalog, action.tool);
|
|
90
|
+
if (!entry)
|
|
91
|
+
return { ok: false, reason: "unknown_tool" };
|
|
92
|
+
if (action.tier !== undefined && action.tier !== entry.tier)
|
|
93
|
+
return { ok: false, reason: "tier_mismatch" };
|
|
94
|
+
const args = validated(entry, action.args ?? {});
|
|
95
|
+
if (!args)
|
|
96
|
+
return { ok: false, reason: "invalid_args" };
|
|
97
|
+
return { ok: true, plan: plan(entry, args) };
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Find a dotted or bracketed path (`a.b[0].c`) in a record. `found` is false for a missing key, so "absent" is not confused with
|
|
101
|
+
* a present `null`. Refuses prototype keys and array `length`.
|
|
102
|
+
*/
|
|
103
|
+
export function lookupPath(record, path) {
|
|
104
|
+
let cur = record;
|
|
105
|
+
for (const seg of path.split(/[.[\]]/).filter((s) => s !== "")) {
|
|
106
|
+
if (seg === "__proto__" || seg === "constructor" || seg === "prototype")
|
|
107
|
+
return { found: false, value: undefined };
|
|
108
|
+
if (typeof cur !== "object" || cur === null || !Object.hasOwn(cur, seg))
|
|
109
|
+
return { found: false, value: undefined };
|
|
110
|
+
if (Array.isArray(cur) && !/^\d+$/.test(seg))
|
|
111
|
+
return { found: false, value: undefined };
|
|
112
|
+
cur = cur[seg];
|
|
113
|
+
}
|
|
114
|
+
return { found: true, value: cur };
|
|
115
|
+
}
|
|
116
|
+
/** The value at a path, or `undefined` when absent. */
|
|
117
|
+
export function readPath(record, path) {
|
|
118
|
+
return lookupPath(record, path).value;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Value equality for the server-vs-proposal diff. Deliberately lenient about number vs string (`12.5` vs `"12.5"`): the backend
|
|
122
|
+
* returns decimals as strings, the model writes numbers. Two non-null scalars are the same when their String forms match;
|
|
123
|
+
* `null` and absent are the same; objects are never the same as anything but themselves.
|
|
124
|
+
*/
|
|
125
|
+
const same = (a, b) => {
|
|
126
|
+
const x = a ?? null;
|
|
127
|
+
const y = b ?? null;
|
|
128
|
+
return (x === y ||
|
|
129
|
+
(x !== null &&
|
|
130
|
+
y !== null &&
|
|
131
|
+
typeof x !== "object" &&
|
|
132
|
+
typeof y !== "object" &&
|
|
133
|
+
String(x) === String(y)));
|
|
134
|
+
};
|
|
135
|
+
/** A fetched record's label for the confirm title: short, single-line text, or nothing (never the uuid). */
|
|
136
|
+
function subjectLabel(entry, record) {
|
|
137
|
+
return cleanInline(entry.recordLabel?.(record) ?? recordName(record), 80);
|
|
138
|
+
}
|
|
139
|
+
/** The record's own name: the first of `name`, `title`, `label` that is a string. Not yet cleaned. */
|
|
140
|
+
export const recordName = (record) => [record.name, record.title, record.label].find((v) => typeof v === "string");
|
|
141
|
+
/**
|
|
142
|
+
* The host's own label for a fetched record, when its catalog has one: the `recordLabel` of a tool that acts on this kind of record
|
|
143
|
+
* (the tools a card names come first). Cleaned like a confirm title. `undefined` when no tool has one or it yields nothing. A
|
|
144
|
+
* `recordLabel` is host code: one that throws is skipped, never allowed to take the drawer down.
|
|
145
|
+
*/
|
|
146
|
+
export function catalogRecordLabel(catalog, kind, record, toolsNamedByCard = []) {
|
|
147
|
+
const cat = catalog ?? {};
|
|
148
|
+
const entries = [...toolsNamedByCard.map((t) => lookup(cat, t)), ...Object.values(cat)];
|
|
149
|
+
for (const entry of entries) {
|
|
150
|
+
if (!entry?.recordLabel || entry.targetKind !== kind)
|
|
151
|
+
continue;
|
|
152
|
+
try {
|
|
153
|
+
const label = cleanInline(entry.recordLabel(record), 120, true);
|
|
154
|
+
if (label)
|
|
155
|
+
return label;
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
// host code: fall through to the next tool, then to the record's own name
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return undefined;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Rule 4 (with 1, 2 and 5): what a proposal's Apply may do. `expected` is the subject the CARD is about (its `detail`, or its
|
|
165
|
+
* offerId or matchId): a proposal for any other record is refused, as is one whose `kind` is not the tool's `targetKind`.
|
|
166
|
+
* Re-fetches the record by `kind` + `id`; a change whose path is absent from it is refused, a change whose `before` no longer
|
|
167
|
+
* matches is STALE and refuses the whole proposal, one already at `after` is skipped; the tool's `targetArg` is bound to
|
|
168
|
+
* `proposal.id` (a change that tries to set it is refused); the args go through the tool's input schema; the plan title names
|
|
169
|
+
* the fetched record.
|
|
170
|
+
*/
|
|
171
|
+
export async function planProposalApply(proposal, catalog, fetchRecord, expected) {
|
|
172
|
+
const entry = lookup(catalog, proposal.tool);
|
|
173
|
+
if (!entry)
|
|
174
|
+
return { ok: false, reason: "unknown_tool" };
|
|
175
|
+
if (proposal.tier !== entry.tier)
|
|
176
|
+
return { ok: false, reason: "tier_mismatch" };
|
|
177
|
+
const targetArg = entry.targetArg;
|
|
178
|
+
if (!targetArg)
|
|
179
|
+
return { ok: false, reason: "no_target_arg" };
|
|
180
|
+
if (!entry.targetKind)
|
|
181
|
+
return { ok: false, reason: "no_target_kind" };
|
|
182
|
+
if (proposal.kind !== entry.targetKind)
|
|
183
|
+
return { ok: false, reason: "kind_mismatch" };
|
|
184
|
+
if (proposal.kind !== expected.kind || proposal.id !== expected.id)
|
|
185
|
+
return { ok: false, reason: "subject_mismatch" };
|
|
186
|
+
if (proposal.changes.some((c) => c.path === targetArg))
|
|
187
|
+
return { ok: false, reason: "target_override" };
|
|
188
|
+
let fetched;
|
|
189
|
+
try {
|
|
190
|
+
fetched = await fetchRecord(proposal.kind, proposal.id);
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
return { ok: false, reason: "record_unavailable" };
|
|
194
|
+
}
|
|
195
|
+
if (fetched === null ||
|
|
196
|
+
fetched === undefined ||
|
|
197
|
+
typeof fetched !== "object" ||
|
|
198
|
+
Array.isArray(fetched))
|
|
199
|
+
return { ok: false, reason: "record_unavailable" };
|
|
200
|
+
const record = fetched;
|
|
201
|
+
const absent = proposal.changes
|
|
202
|
+
.filter((c) => !lookupPath(record, c.path).found)
|
|
203
|
+
.map((c) => c.path);
|
|
204
|
+
if (absent.length > 0)
|
|
205
|
+
return { ok: false, reason: "unknown_path", paths: absent };
|
|
206
|
+
const diff = [];
|
|
207
|
+
const conflicts = [];
|
|
208
|
+
for (const c of proposal.changes) {
|
|
209
|
+
const current = readPath(record, c.path);
|
|
210
|
+
const row = { path: c.path, before: current, after: c.after, claimedBefore: c.before };
|
|
211
|
+
if (same(current, c.after))
|
|
212
|
+
diff.push({ ...row, state: "already_applied" });
|
|
213
|
+
else if (same(current, c.before))
|
|
214
|
+
diff.push({ ...row, state: "pending" });
|
|
215
|
+
else
|
|
216
|
+
conflicts.push({ ...row, state: "pending" });
|
|
217
|
+
}
|
|
218
|
+
if (conflicts.length > 0)
|
|
219
|
+
return { ok: false, reason: "stale", conflicts };
|
|
220
|
+
const pending = proposal.changes.filter((_, i) => diff[i].state === "pending");
|
|
221
|
+
if (pending.length === 0)
|
|
222
|
+
return { ok: false, reason: "nothing_to_apply" };
|
|
223
|
+
const base = entry.argsFromChanges
|
|
224
|
+
? entry.argsFromChanges(pending, proposal.id)
|
|
225
|
+
: Object.fromEntries(pending.map((c) => [c.path, c.after]));
|
|
226
|
+
const args = validated(entry, { ...base, [targetArg]: proposal.id });
|
|
227
|
+
if (!args)
|
|
228
|
+
return { ok: false, reason: "invalid_args" };
|
|
229
|
+
return { ok: true, plan: plan(entry, args, subjectLabel(entry, record)), diff, proposal };
|
|
230
|
+
}
|
|
231
|
+
/** The subject a card is about: its `detail` pointer. Cards that carry an id of their own (offer, match) pass it explicitly. */
|
|
232
|
+
export const subjectOf = (detail, fallback) => detail ? { kind: detail.kind, id: detail.id } : fallback;
|
|
233
|
+
/**
|
|
234
|
+
* Rules 1 and 3 over a whole parsed card: keeps only the actions `actionsForDisplay` accepts and drops a `proposal` whose tool is
|
|
235
|
+
* unknown, whose tier differs from the catalog's or whose tool lacks a `targetArg` or `targetKind`. With NO catalog every
|
|
236
|
+
* tool-bearing action and every proposal is dropped (secure default): only `open`/`navigate`/tool-less actions remain.
|
|
237
|
+
*/
|
|
238
|
+
export function sanitizeCardForHost(card, catalog) {
|
|
239
|
+
const actions = actionsForDisplay(card.actions, catalog);
|
|
240
|
+
const entry = card.proposal ? lookup(catalog ?? {}, card.proposal.tool) : undefined;
|
|
241
|
+
const proposalOk = card.proposal !== undefined &&
|
|
242
|
+
entry !== undefined &&
|
|
243
|
+
entry.tier === card.proposal.tier &&
|
|
244
|
+
entry.targetArg !== undefined &&
|
|
245
|
+
entry.targetKind === card.proposal.kind;
|
|
246
|
+
return {
|
|
247
|
+
...card,
|
|
248
|
+
actions: actions.length > 0 ? actions : undefined,
|
|
249
|
+
proposal: proposalOk ? card.proposal : undefined,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
export const ROLE_AGENT_CARD_TYPES = [
|
|
253
|
+
"OfferCard",
|
|
254
|
+
"ProductCard",
|
|
255
|
+
"OpportunityCard",
|
|
256
|
+
"MatchCard",
|
|
257
|
+
"DataTable",
|
|
258
|
+
];
|
|
259
|
+
const isRoleCardType = (t) => ROLE_AGENT_CARD_TYPES.includes(t);
|
|
260
|
+
/** The record kinds a card's `detail` pointer may name, per card type. A pointer to any other kind is a steered or broken card. */
|
|
261
|
+
const DETAIL_KINDS_BY_CARD = {
|
|
262
|
+
OfferCard: ["offer"],
|
|
263
|
+
MatchCard: ["match"],
|
|
264
|
+
ProductCard: ["product", "variant"],
|
|
265
|
+
OpportunityCard: ["opportunity"],
|
|
266
|
+
};
|
|
267
|
+
/**
|
|
268
|
+
* Does the card's `detail` pointer name what the card is about? An offer's or a match's must name its own id, a product's must be a
|
|
269
|
+
* product or a variant, an opportunity's an opportunity. A card with no pointer agrees (nothing to disagree with). The cards and
|
|
270
|
+
* `readRoleCard` both call this, so a disagreeing card is refused the same way everywhere, never reconciled.
|
|
271
|
+
*/
|
|
272
|
+
export function detailAgrees(cardType, data) {
|
|
273
|
+
const d = data.detail;
|
|
274
|
+
if (!d)
|
|
275
|
+
return true;
|
|
276
|
+
if (!DETAIL_KINDS_BY_CARD[cardType].includes(d.kind))
|
|
277
|
+
return false;
|
|
278
|
+
if (cardType === "OfferCard")
|
|
279
|
+
return d.id === data.offerId;
|
|
280
|
+
if (cardType === "MatchCard")
|
|
281
|
+
return d.id === data.matchId;
|
|
282
|
+
return true;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* The ONE way a host turns what an agent sent into a role card it may draw: parse against the agent-cards schema, refuse a card
|
|
286
|
+
* whose `detail` disagrees with it (`detailAgrees`), then `sanitizeCardForHost` against the host catalog. `null` for an unknown
|
|
287
|
+
* type, data that fails the schema, or a disagreeing card. `subject` is the record THIS card is about (its offerId or matchId, or its
|
|
288
|
+
* `detail`), what a proposal is bound to. `renderRoleAgentCard` and the inspector drawer both read through here.
|
|
289
|
+
*/
|
|
290
|
+
export function readRoleCard(cardType, data, catalog) {
|
|
291
|
+
if (!isRoleCardType(cardType))
|
|
292
|
+
return null;
|
|
293
|
+
switch (cardType) {
|
|
294
|
+
case "OfferCard": {
|
|
295
|
+
const parsed = parseCard("OfferCard", data);
|
|
296
|
+
if (!parsed || !detailAgrees(cardType, parsed))
|
|
297
|
+
return null;
|
|
298
|
+
return {
|
|
299
|
+
cardType,
|
|
300
|
+
data: sanitizeCardForHost(parsed, catalog),
|
|
301
|
+
subject: { kind: "offer", id: parsed.offerId },
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
case "MatchCard": {
|
|
305
|
+
const parsed = parseCard("MatchCard", data);
|
|
306
|
+
if (!parsed || !detailAgrees(cardType, parsed))
|
|
307
|
+
return null;
|
|
308
|
+
return {
|
|
309
|
+
cardType,
|
|
310
|
+
data: sanitizeCardForHost(parsed, catalog),
|
|
311
|
+
subject: { kind: "match", id: parsed.matchId },
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
case "ProductCard": {
|
|
315
|
+
const parsed = parseCard("ProductCard", data);
|
|
316
|
+
if (!parsed || !detailAgrees(cardType, parsed))
|
|
317
|
+
return null;
|
|
318
|
+
return {
|
|
319
|
+
cardType,
|
|
320
|
+
data: sanitizeCardForHost(parsed, catalog),
|
|
321
|
+
subject: subjectOf(parsed.detail),
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
case "OpportunityCard": {
|
|
325
|
+
const parsed = parseCard("OpportunityCard", data);
|
|
326
|
+
if (!parsed || !detailAgrees(cardType, parsed))
|
|
327
|
+
return null;
|
|
328
|
+
return {
|
|
329
|
+
cardType,
|
|
330
|
+
data: sanitizeCardForHost(parsed, catalog),
|
|
331
|
+
subject: subjectOf(parsed.detail),
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
case "DataTable": {
|
|
335
|
+
const parsed = parseCard("DataTable", data);
|
|
336
|
+
if (!parsed)
|
|
337
|
+
return null;
|
|
338
|
+
// A table is a list, not one record: no pointer to open and nothing a proposal could be bound to. Only its `actions` survive,
|
|
339
|
+
// and only the ones the host catalog accepts (a link is checked against the host's `allowLink` when the card is drawn).
|
|
340
|
+
return {
|
|
341
|
+
cardType,
|
|
342
|
+
data: { ...sanitizeCardForHost(parsed, catalog), detail: undefined, proposal: undefined },
|
|
343
|
+
subject: undefined,
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
//# sourceMappingURL=host-contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-contract.js","sourceRoot":"","sources":["../../../src/agent/role-cards/host-contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAWzD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AA6C5C,MAAM,MAAM,GAAG,CACb,OAAyB,EACzB,IAAwB,EACW,EAAE,CACrC,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAQjF;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAA0C,EAC1C,OAAyB;IAEzB,MAAM,IAAI,GAAiB,EAAE,CAAC;IAC9B,MAAM,OAAO,GAAoB,EAAE,CAAC;IACpC,KAAK,MAAM,CAAC,IAAI,OAAO,IAAI,EAAE,EAAE,CAAC;QAC9B,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC/C,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS;gBAC9C,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC,CAAC;;gBACtD,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,SAAS;QACX,CAAC;QACD,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YACzB,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS;gBAC3C,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;;gBAChD,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC,KAAK;YAAE,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;aAC1D,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI;YACpD,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC,CAAC;;YACjD,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AACpC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAA0C,EAC1C,OAAqC;IAErC,MAAM,GAAG,GAAG,OAAO,IAAI,EAAE,CAAC;IAC1B,OAAO,kBAAkB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACxD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK;YAAE,OAAO,CAAC,CAAC;QACrB,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QAC5D,OAAO,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,OAA0C,EAC1C,OAAqC,EACrC,IAAqE;IAErE,OAAO,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,MAAM,CAC/C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAC5E,CAAC;AACJ,CAAC;AA4BD,MAAM,IAAI,GAAG,CAAC,CAAU,EAAU,EAAE,CAClC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAE7F,SAAS,IAAI,CACX,KAA4B,EAC5B,IAA6B,EAC7B,OAAgB;IAEhB,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK;QAC3D,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,eAAe,EAAE,KAAK,CAAC,IAAI,KAAK,MAAM;QACtC,IAAI;QACJ,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACnF,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAChC,CAAC;AACJ,CAAC;AAED,MAAM,SAAS,GAAG,CAAC,KAA4B,EAAE,IAAa,EAAkC,EAAE;IAChG,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACjD,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IACjC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IACzB,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QACtE,CAAC,CAAE,IAAgC;QACnC,CAAC,CAAC,EAAE,CAAC;AACT,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,MAAkB,EAClB,OAAyB;IAEzB,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS;QACnF,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IACpD,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3C,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IACzD,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI;QACzD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAChD,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IACjD,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IACxD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC;AAC/C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,MAAe,EAAE,IAAY;IACtD,IAAI,GAAG,GAAY,MAAM,CAAC;IAC1B,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC;QAC/D,IAAI,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,aAAa,IAAI,GAAG,KAAK,WAAW;YACrE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAC5C,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC;YACrE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAC5C,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QACxF,GAAG,GAAI,GAA+B,CAAC,GAAG,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AACrC,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,QAAQ,CAAC,MAAe,EAAE,IAAY;IACpD,OAAO,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC;AACxC,CAAC;AAED;;;;GAIG;AACH,MAAM,IAAI,GAAG,CAAC,CAAU,EAAE,CAAU,EAAW,EAAE;IAC/C,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;IACpB,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;IACpB,OAAO,CACL,CAAC,KAAK,CAAC;QACP,CAAC,CAAC,KAAK,IAAI;YACT,CAAC,KAAK,IAAI;YACV,OAAO,CAAC,KAAK,QAAQ;YACrB,OAAO,CAAC,KAAK,QAAQ;YACrB,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAC3B,CAAC;AACJ,CAAC,CAAC;AAEF,4GAA4G;AAC5G,SAAS,YAAY,CACnB,KAA4B,EAC5B,MAA+B;IAE/B,OAAO,WAAW,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;AAC5E,CAAC;AAED,sGAAsG;AACtG,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,MAA+B,EAAsB,EAAE,CAChF,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;AAE5F;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAAqC,EACrC,IAAgB,EAChB,MAA+B,EAC/B,mBAAoD,EAAE;IAEtD,MAAM,GAAG,GAAG,OAAO,IAAI,EAAE,CAAC;IAC1B,MAAM,OAAO,GAAG,CAAC,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACxF,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,EAAE,WAAW,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI;YAAE,SAAS;QAC/D,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YAChE,IAAI,KAAK;gBAAE,OAAO,KAAK,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,0EAA0E;QAC5E,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAqCD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,QAAsB,EACtB,OAAyB,EACzB,WAA+D,EAC/D,QAAyC;IAEzC,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7C,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IACzD,IAAI,QAAQ,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAChF,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;IAClC,IAAI,CAAC,SAAS;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAC9D,IAAI,CAAC,KAAK,CAAC,UAAU;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACtE,IAAI,QAAQ,CAAC,IAAI,KAAK,KAAK,CAAC,UAAU;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IACtF,IAAI,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,EAAE,KAAK,QAAQ,CAAC,EAAE;QAChE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;IACnD,IAAI,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC;QACpD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAElD,IAAI,OAAgB,CAAC;IACrB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC;IACrD,CAAC;IACD,IACE,OAAO,KAAK,IAAI;QAChB,OAAO,KAAK,SAAS;QACrB,OAAO,OAAO,KAAK,QAAQ;QAC3B,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAEtB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC;IACrD,MAAM,MAAM,GAAG,OAAkC,CAAC;IAElD,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO;SAC5B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC;SAChD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACtB,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAEnF,MAAM,IAAI,GAAsB,EAAE,CAAC;IACnC,MAAM,SAAS,GAAsB,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,GAAG,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;QACvF,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC;YAAE,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,GAAG,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC;aACvE,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC;YAAE,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;;YACrE,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IACpD,CAAC;IACD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;IAC3E,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;IAChF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAE3E,MAAM,IAAI,GAAG,KAAK,CAAC,eAAe;QAChC,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC7C,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC9D,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;IACrE,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IACxD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AAC5F,CAAC;AAED,gIAAgI;AAChI,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,MAA8B,EAC9B,QAA0C,EACG,EAAE,CAC/C,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;AAE3D;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAAO,EACP,OAAqC;IAErC,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACpF,MAAM,UAAU,GACd,IAAI,CAAC,QAAQ,KAAK,SAAS;QAC3B,KAAK,KAAK,SAAS;QACnB,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,QAAQ,CAAC,IAAI;QACjC,KAAK,CAAC,SAAS,KAAK,SAAS;QAC7B,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC1C,OAAO;QACL,GAAG,IAAI;QACP,OAAO,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;QACjD,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;KACjD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,WAAW;IACX,aAAa;IACb,iBAAiB;IACjB,WAAW;IACX,WAAW;CACH,CAAC;AAGX,MAAM,cAAc,GAAG,CAAC,CAAS,EAA0B,EAAE,CAC1D,qBAA2C,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAK3D,mIAAmI;AACnI,MAAM,oBAAoB,GAAkD;IAC1E,SAAS,EAAE,CAAC,OAAO,CAAC;IACpB,SAAS,EAAE,CAAC,OAAO,CAAC;IACpB,WAAW,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;IACnC,eAAe,EAAE,CAAC,aAAa,CAAC;CACjC,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAC1B,QAAwB,EACxB,IAAiE;IAEjE,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;IACtB,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACnE,IAAI,QAAQ,KAAK,WAAW;QAAE,OAAO,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,OAAO,CAAC;IAC3D,IAAI,QAAQ,KAAK,WAAW;QAAE,OAAO,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,OAAO,CAAC;IAC3D,OAAO,IAAI,CAAC;AACd,CAAC;AAUD;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAC1B,QAAgB,EAChB,IAAa,EACb,OAAqC;IAErC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3C,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,MAAM,MAAM,GAAG,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;YAC5C,IAAI,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAAE,OAAO,IAAI,CAAC;YAC5D,OAAO;gBACL,QAAQ;gBACR,IAAI,EAAE,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC;gBAC1C,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,OAAO,EAAE;aAC/C,CAAC;QACJ,CAAC;QACD,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,MAAM,MAAM,GAAG,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;YAC5C,IAAI,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAAE,OAAO,IAAI,CAAC;YAC5D,OAAO;gBACL,QAAQ;gBACR,IAAI,EAAE,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC;gBAC1C,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,OAAO,EAAE;aAC/C,CAAC;QACJ,CAAC;QACD,KAAK,aAAa,CAAC,CAAC,CAAC;YACnB,MAAM,MAAM,GAAG,SAAS,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;YAC9C,IAAI,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAAE,OAAO,IAAI,CAAC;YAC5D,OAAO;gBACL,QAAQ;gBACR,IAAI,EAAE,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC;gBAC1C,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC;aAClC,CAAC;QACJ,CAAC;QACD,KAAK,iBAAiB,CAAC,CAAC,CAAC;YACvB,MAAM,MAAM,GAAG,SAAS,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;YAClD,IAAI,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAAE,OAAO,IAAI,CAAC;YAC5D,OAAO;gBACL,QAAQ;gBACR,IAAI,EAAE,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC;gBAC1C,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC;aAClC,CAAC;QACJ,CAAC;QACD,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,MAAM,MAAM,GAAG,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;YAC5C,IAAI,CAAC,MAAM;gBAAE,OAAO,IAAI,CAAC;YACzB,8HAA8H;YAC9H,wHAAwH;YACxH,OAAO;gBACL,QAAQ;gBACR,IAAI,EAAE,EAAE,GAAG,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE;gBACzF,OAAO,EAAE,SAAS;aACnB,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type AgentInspectorViewCopyOverride, type AgentInspectorViewProps } from "./inspector-view.js";
|
|
2
|
+
export declare const DEFAULT_INSPECTOR_CLOSE = "Close details";
|
|
3
|
+
/** Handed to `onCloseAutoFocus`: call `preventDefault()` to take over focus instead of the drawer returning it to its opener. */
|
|
4
|
+
export interface AgentInspectorCloseFocusEvent {
|
|
5
|
+
preventDefault: () => void;
|
|
6
|
+
}
|
|
7
|
+
export type AgentInspectorDrawerCopy = AgentInspectorViewCopyOverride & {
|
|
8
|
+
/** The accessible name of the built-in close button. */
|
|
9
|
+
close?: string;
|
|
10
|
+
};
|
|
11
|
+
export interface AgentInspectorDrawerProps extends Omit<AgentInspectorViewProps, "heading" | "onHandOff" | "active" | "copy" | "className"> {
|
|
12
|
+
open: boolean;
|
|
13
|
+
onOpenChange: (open: boolean) => void;
|
|
14
|
+
/**
|
|
15
|
+
* Where focus goes when the drawer closes: the button that opened it. Hand it the `opener` that `onOpenDetail(detail, opener)`
|
|
16
|
+
* received. Without it the drawer returns focus to whatever was focused when it opened, which is nothing in a browser that does
|
|
17
|
+
* not focus a button on click (Safari) and is lost if the card re-rendered in between.
|
|
18
|
+
*/
|
|
19
|
+
returnFocus?: HTMLElement | null;
|
|
20
|
+
/**
|
|
21
|
+
* Called as the drawer finishes closing, before it returns focus. Call `event.preventDefault()` to take focus yourself: a host
|
|
22
|
+
* that has just rendered a confirm card for a hand-off should focus that card here, since the drawer closes on every hand-off.
|
|
23
|
+
*/
|
|
24
|
+
onCloseAutoFocus?: (event: AgentInspectorCloseFocusEvent) => void;
|
|
25
|
+
copy?: AgentInspectorDrawerCopy;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* @internal The inspector drawer (CEL-2487, tier 2 of inline card, drawer, canvas): `AgentInspectorView` in a right-hand side
|
|
29
|
+
* drawer on desktop and a full-width, full-height sheet on a narrow screen. Built on the shared `Sheet` (Radix Dialog): focus lands
|
|
30
|
+
* on the drawer, is trapped, Escape and the scrim close it, and focus returns to the control that opened it.
|
|
31
|
+
*
|
|
32
|
+
* The view owns the content and the host contract (see `AgentInspectorView`); this owns the chrome. The confirm UI is the host's
|
|
33
|
+
* (the conversation's confirm card), so the drawer CLOSES once the view has handed something to the host: a modal drawer would
|
|
34
|
+
* otherwise sit on top of the confirmation it is waiting for. A refused action stays open and says so. Hosts that want focus to go
|
|
35
|
+
* to the confirm card use `onCloseAutoFocus`.
|
|
36
|
+
*
|
|
37
|
+
* Opening: the host renders `AgentCardActions` (inside any role card) with `onOpenDetail(detail, opener)`, remembers which card was
|
|
38
|
+
* clicked and its opener, and opens this with that card's `cardType` and `data`. A card with no `detail` pointer (or one that
|
|
39
|
+
* disagrees with the card) cannot be inspected: the drawer asks to close instead of showing an empty dialog.
|
|
40
|
+
*/
|
|
41
|
+
export declare function AgentInspectorDrawer({ open, onOpenChange, returnFocus, onCloseAutoFocus, copy, ...view }: AgentInspectorDrawerProps): import("react/jsx-runtime").JSX.Element | null;
|
|
42
|
+
//# sourceMappingURL=inspector-drawer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspector-drawer.d.ts","sourceRoot":"","sources":["../../../src/agent/role-cards/inspector-drawer.tsx"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,8BAA8B,EACnC,KAAK,uBAAuB,EAC7B,MAAM,kBAAkB,CAAC;AAE1B,eAAO,MAAM,uBAAuB,kBAAkB,CAAC;AAGvD,iIAAiI;AACjI,MAAM,WAAW,6BAA6B;IAC5C,cAAc,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED,MAAM,MAAM,wBAAwB,GAAG,8BAA8B,GAAG;IACtE,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,WAAW,yBAA0B,SAAQ,IAAI,CACrD,uBAAuB,EACvB,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAC1D;IACC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC;;;;OAIG;IACH,WAAW,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACjC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,6BAA6B,KAAK,IAAI,CAAC;IAClE,IAAI,CAAC,EAAE,wBAAwB,CAAC;CACjC;AAeD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,IAAI,EACJ,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,IAAI,EACJ,GAAG,IAAI,EACR,EAAE,yBAAyB,kDA2D3B"}
|