@foir/sdk 0.29.0 → 0.30.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/auth.js CHANGED
@@ -1417,6 +1417,11 @@ async function signInWithOTP(adapter, env, vars) {
1417
1417
  async function resetPasswordAndSignIn(adapter, env, vars) {
1418
1418
  return saveSession(adapter, await resetPassword(env, vars));
1419
1419
  }
1420
+ async function deleteMyAccountAndSignOut(adapter, env, vars) {
1421
+ const result = await authedOp(adapter, env, AUTH_OPS.deleteMyAccount, vars);
1422
+ await clearSession(adapter);
1423
+ return result;
1424
+ }
1420
1425
  async function signOut(adapter, env) {
1421
1426
  const token = await getSessionToken(adapter);
1422
1427
  if (token) {
@@ -1564,6 +1569,12 @@ var GRANT_TABLE = [
1564
1569
  ["operations:write", "none", [], []],
1565
1570
  ["operations:complete", "none", [], []],
1566
1571
  ["status:write", "none", [], []],
1572
+ ["agents:read", "none", [], []],
1573
+ ["agents:execute", "agent", [], []],
1574
+ ["agents:write", "none", [], []],
1575
+ ["agenttools:execute", "agent_tool", [], []],
1576
+ ["brief:read", "none", [], []],
1577
+ ["brief:write", "none", [], []],
1567
1578
  ["appconfig:read", "none", [], []],
1568
1579
  ["schedules:read", "none", [], []],
1569
1580
  ["schedules:write", "none", [], []],
@@ -1613,7 +1624,7 @@ var GRANT_TABLE = [
1613
1624
  ["projects:read", "none", [], []],
1614
1625
  ["projects:write", "none", [], []],
1615
1626
  ["project:stand", "none", [], []],
1616
- ["project:manage", "none", [], ["project:stand", "records:read.all", "records:create", "records:write.all", "records:delete.all", "records:publish.all", "records:attribute", "search:read", "embeddings:read", "embeddings:write", "schemas:read", "drafts:read", "files:read.all", "files:write.all", "files:delete.all", "users:read.all", "identities:read", "users:create", "identities:delete", "users:write.all", "users:setup", "users:delete.all", "notifications:read.all", "notifications:write.all", "notifications:consent", "pushcredentials:read", "pushcredentials:write", "notes:read.all", "notes:write.all", "notes:create", "approvals:read", "approvals:write", "rooms:read", "rooms:write", "presence:read", "operations:read", "operations:execute", "operations:write", "appconfig:read", "schedules:read", "schedules:write", "hooks:read", "hooks:write", "authclients:read", "authclients:write", "domains:read", "domains:write", "loginpages:read", "loginpages:write", "secrets:read", "secrets:list", "secrets:put", "secrets:delete", "appsecrets:read", "appsecrets:list", "appsecrets:put", "appsecrets:delete", "usersecrets:read", "usersecrets:list", "usersecrets:put", "usersecrets:delete", "opsecrets:read", "opsecrets:write", "settings:read", "settings:write", "designtokens:read", "designtokens:write", "models:read", "models:write", "configs:read", "configs:write", "signinproviders:read", "signinproviders:write", "apps:read", "apps:write", "events:read", "targeting:debug", "visitors:forward", "apikeys:read", "apikeys:write", "organizations:read", "organizations:create", "organizations:delete", "organizations:write", "orgsettings:write", "organizations:reach", "members:read", "members:write", "roles:read", "roles:write", "projects:read", "projects:write", "audit:read"]],
1627
+ ["project:manage", "none", [], ["project:stand", "records:read.all", "records:create", "records:write.all", "records:delete.all", "records:publish.all", "records:attribute", "search:read", "embeddings:read", "embeddings:write", "schemas:read", "drafts:read", "files:read.all", "files:write.all", "files:delete.all", "users:read.all", "identities:read", "users:create", "identities:delete", "users:write.all", "users:setup", "users:delete.all", "notifications:read.all", "notifications:write.all", "notifications:consent", "pushcredentials:read", "pushcredentials:write", "notes:read.all", "notes:write.all", "notes:create", "approvals:read", "approvals:write", "rooms:read", "rooms:write", "presence:read", "operations:read", "operations:execute", "operations:write", "agents:read", "agents:execute", "agents:write", "agenttools:execute", "brief:read", "brief:write", "appconfig:read", "schedules:read", "schedules:write", "hooks:read", "hooks:write", "authclients:read", "authclients:write", "domains:read", "domains:write", "loginpages:read", "loginpages:write", "secrets:read", "secrets:list", "secrets:put", "secrets:delete", "appsecrets:read", "appsecrets:list", "appsecrets:put", "appsecrets:delete", "usersecrets:read", "usersecrets:list", "usersecrets:put", "usersecrets:delete", "opsecrets:read", "opsecrets:write", "settings:read", "settings:write", "designtokens:read", "designtokens:write", "models:read", "models:write", "configs:read", "configs:write", "signinproviders:read", "signinproviders:write", "apps:read", "apps:write", "events:read", "targeting:debug", "visitors:forward", "apikeys:read", "apikeys:write", "organizations:read", "organizations:create", "organizations:delete", "organizations:write", "orgsettings:write", "organizations:reach", "members:read", "members:write", "roles:read", "roles:write", "projects:read", "projects:write", "audit:read"]],
1617
1628
  ["projects:create", "none", [], []],
1618
1629
  ["projects:delete", "none", [], []],
1619
1630
  ["tenants:read", "none", [], []],
@@ -2237,6 +2248,7 @@ export {
2237
2248
  createPersonalAccessToken,
2238
2249
  currentUser,
2239
2250
  deleteMyAccount,
2251
+ deleteMyAccountAndSignOut,
2240
2252
  disconnectSignInMethod,
2241
2253
  endMySession,
2242
2254
  exportMyData,
@@ -21,7 +21,7 @@ export declare class PlatformClientError extends Error {
21
21
  * });
22
22
  *
23
23
  * const { data } = await client.query(
24
- * `query GetProduct($id: ID!) { product(id: $id) { title } }`,
24
+ * `query GetProduct($id: String!) { product(id: $id) { title } }`,
25
25
  * { id: '123' }
26
26
  * );
27
27
  * ```
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Talking to a project's agents from a site: send a message, follow the run as
3
+ * it answers, and keep a visitor's conversation theirs.
4
+ *
5
+ * ```ts
6
+ * const reply = await askAgent(foir, {
7
+ * agent: 'ask_about_foir',
8
+ * message: 'How do releases work?',
9
+ * visitorToken: visitorToken(),
10
+ * onText: (delta) => render(delta),
11
+ * });
12
+ * // reply.threadId continues the conversation
13
+ * ```
14
+ *
15
+ * The run is the platform's: it charges `agents:execute` for the agent to the
16
+ * caller, signed in or a visitor through a key that gives it, and a refusal
17
+ * (a message too long, a limit reached, the safety check) comes back as the
18
+ * run's answer, not as an error. Only a call the platform could not take at
19
+ * all throws.
20
+ */
21
+ import type { FoirAgentAttachment, FoirAgentAttachmentUpload, FoirAgentRun, FoirAgentRunStatus, FoirCreateAgentAttachmentArgs, FoirStartAgentRunArgs } from './builtins';
22
+ import type { FoirAgentRunEvent, FoirAgentRunSubscribeOptions } from './subscriptions';
23
+ import type { FoirSubscription } from './ws-transport';
24
+ /** What `askAgent` needs of a client: the agents namespace a key that runs an agent is given. */
25
+ export interface FoirAgentsClient {
26
+ ns: {
27
+ agents: {
28
+ startAgentRun(args: FoirStartAgentRunArgs): Promise<FoirAgentRun>;
29
+ onRun(options: FoirAgentRunSubscribeOptions): FoirSubscription;
30
+ };
31
+ };
32
+ }
33
+ /** What `uploadAgentFile` needs of a client. */
34
+ export interface FoirAgentFilesClient {
35
+ ns: {
36
+ agents: {
37
+ createAgentAttachment(args: FoirCreateAgentAttachmentArgs): Promise<FoirAgentAttachmentUpload>;
38
+ };
39
+ };
40
+ }
41
+ /**
42
+ * A file to send an agent: a `File` from an input or a paste, or bytes with
43
+ * their type. An image (PNG, JPEG, GIF or WebP) of at most 5 MB, or a PDF of
44
+ * at most 10 MB; a visitor may send images only.
45
+ */
46
+ export type FoirAgentFile = Blob | {
47
+ data: Blob | ArrayBuffer | Uint8Array;
48
+ mediaType: string;
49
+ filename?: string;
50
+ };
51
+ /**
52
+ * Upload a file to send an agent, and answer with the attachment to pass as
53
+ * one of `attachmentIds`. The bytes go straight to the project's storage; the
54
+ * attachment is read only through the conversation it is sent in.
55
+ */
56
+ export declare function uploadAgentFile(foir: FoirAgentFilesClient | {
57
+ readonly ns: object;
58
+ }, options: {
59
+ agent: string;
60
+ file: FoirAgentFile;
61
+ visitorToken?: string;
62
+ fetch?: typeof fetch;
63
+ }): Promise<FoirAgentAttachment>;
64
+ export interface AskAgentOptions extends FoirStartAgentRunArgs {
65
+ /** Files sent with the message: each is uploaded first, then sent by its id. At most 5. */
66
+ files?: FoirAgentFile[];
67
+ /** Each piece of the answer as it is written. */
68
+ onText?: (delta: string) => void;
69
+ /** Every event of the run, for a caller that renders its steps. */
70
+ onEvent?: (event: FoirAgentRunEvent) => void;
71
+ /** Stop following the run; the run itself goes on. */
72
+ signal?: AbortSignal;
73
+ }
74
+ export interface AgentReply {
75
+ runId: string;
76
+ /** Pass as `threadId` to go on with the conversation. */
77
+ threadId: string | null;
78
+ status: FoirAgentRunStatus;
79
+ /** The answer, or the reason the run was refused. */
80
+ answer: string;
81
+ error: string | null;
82
+ /** An agent with an output schema: its typed answer, a value that fits the schema. */
83
+ output?: unknown;
84
+ }
85
+ /**
86
+ * Send an agent a message and follow its run until it has answered, or holds
87
+ * an act for someone's decision.
88
+ *
89
+ * It takes any client `createFoirClient` makes, generated or not: the agents
90
+ * are offered by the key the client was made with, and a client whose key runs
91
+ * no agent is refused here, by name.
92
+ */
93
+ export declare function askAgent(foir: FoirAgentsClient | {
94
+ readonly ns: object;
95
+ }, options: AskAgentOptions): Promise<AgentReply>;
96
+ /**
97
+ * The secret a visitor's browser keeps for their runs and threads: made once
98
+ * and kept, so the conversation they start is theirs when they come back. The
99
+ * platform keeps only its hash.
100
+ *
101
+ * Where nothing can be kept (a private window, a server render), a fresh one
102
+ * is made for the page, and the conversation lasts as long as it does.
103
+ */
104
+ export declare function visitorToken(storage?: Pick<Storage, 'getItem' | 'setItem'> | null, key?: string): string;
@@ -678,3 +678,185 @@ export interface FoirResolveContext {
678
678
  longitude: number;
679
679
  } | null;
680
680
  }
681
+ /**
682
+ * Where a run, or one step of it, stands. HELD waits for a decision on an act
683
+ * it holds, or for an operation to answer; SKIPPED was refused or denied and
684
+ * never ran.
685
+ */
686
+ export type FoirAgentRunStatus = 'SCHEDULED' | 'STARTED' | 'HELD' | 'COMPLETED' | 'FAILED' | 'SKIPPED' | 'CANCELLED';
687
+ /** An act a run holds until someone decides it. */
688
+ export interface FoirAgentApproval {
689
+ /** What the act would do, in words. */
690
+ summary: string;
691
+ /** CALLER: the person who started the run decides it. TEAM: the project's team does. */
692
+ approver: 'CALLER' | 'TEAM';
693
+ decision: 'PENDING' | 'APPROVED' | 'DENIED' | 'EXPIRED';
694
+ reason?: string | null;
695
+ }
696
+ /** One step of a run: a model turn, a tool call, a check, or a child agent. */
697
+ export interface FoirAgentRunNode {
698
+ id: string;
699
+ parentId?: string | null;
700
+ /**
701
+ * PAGE_TOOL is a call to a tool the caller's page offered with the message,
702
+ * HELD until the page answers it with `answerPageTool`; DATA is data sent to
703
+ * the app's components, delivered as a DATA event.
704
+ */
705
+ kind: 'AGENT' | 'OPERATION' | 'VERB' | 'MCP_TOOL' | 'MODEL_TURN' | 'CHECK' | 'PAGE_TOOL' | 'DATA';
706
+ /** The tool, operation or agent the step is, by its key. */
707
+ key: string;
708
+ status: FoirAgentRunStatus;
709
+ error?: string | null;
710
+ input?: unknown;
711
+ result?: unknown;
712
+ approval?: FoirAgentApproval | null;
713
+ /** ISO-8601. */
714
+ startedAt?: string | null;
715
+ /** ISO-8601. */
716
+ completedAt?: string | null;
717
+ }
718
+ /**
719
+ * A run of an agent: its answer, once given, and every step it took. A refusal
720
+ * is an answer too: a message the agent will not take ends SKIPPED with the
721
+ * reason as its answer.
722
+ */
723
+ export interface FoirAgentRun {
724
+ id: string;
725
+ /** The agent's key. */
726
+ agent: string;
727
+ /** The thread the run answers in. Pass it as `threadId` to go on talking. */
728
+ threadId?: string | null;
729
+ status: FoirAgentRunStatus;
730
+ answer?: string | null;
731
+ error?: string | null;
732
+ /** What the run has spent so far, in credits. */
733
+ spentCredits: number;
734
+ nodes: FoirAgentRunNode[];
735
+ /** An agent with an output schema: its typed answer, once the run has finished. */
736
+ output?: unknown;
737
+ }
738
+ /** One message of a conversation with an agent. */
739
+ export interface FoirAgentThreadMessage {
740
+ id: string;
741
+ seq: number;
742
+ role: 'USER' | 'ASSISTANT';
743
+ /** Text, tool calls and their answers, as the run kept them. */
744
+ parts: unknown[];
745
+ runId?: string | null;
746
+ /** ISO-8601. */
747
+ createdAt?: string | null;
748
+ }
749
+ /** A conversation with an agent, kept for the agent's retention and then deleted. */
750
+ export interface FoirAgentThread {
751
+ id: string;
752
+ agent: string;
753
+ title: string;
754
+ messageCount: number;
755
+ createdAt?: string | null;
756
+ updatedAt?: string | null;
757
+ expiresAt?: string | null;
758
+ /** Present on `agentThread`; absent in a list of threads. */
759
+ messages?: FoirAgentThreadMessage[] | null;
760
+ /** A run still answering in the thread: follow it with `foir.ns.agents.onRun`. */
761
+ runningRunId?: string | null;
762
+ }
763
+ /**
764
+ * `startAgentRun` arguments. Requires `agents:execute` for the agent, held by
765
+ * the signed-in user's role or given by the key to whoever comes through it.
766
+ */
767
+ export interface FoirStartAgentRunArgs {
768
+ /** The agent's key. */
769
+ agent: string;
770
+ message: string;
771
+ /** Continue this conversation. Omitted starts a new one. */
772
+ threadId?: string;
773
+ /** Sent again after a lost answer, the same key answers with the same run. */
774
+ idempotencyKey?: string;
775
+ /**
776
+ * A visitor with nobody signed in: the secret their browser keeps, which
777
+ * makes the run and its thread theirs. Make it once per browser and keep it
778
+ * (see `visitorToken` in `@foir/sdk/agents`).
779
+ */
780
+ visitorToken?: string;
781
+ /**
782
+ * Files sent with the message, each uploaded first with
783
+ * `createAgentAttachment` (or `uploadAgentFile`). At most 5; the message
784
+ * may then be empty.
785
+ */
786
+ attachmentIds?: string[];
787
+ /**
788
+ * What the message points at, by id: the agent reads each with its own
789
+ * tools, as the caller, so a tag reaches nothing the caller could not. At
790
+ * most 20.
791
+ */
792
+ tags?: FoirMessageTag[];
793
+ /**
794
+ * Tools of the caller's own page the agent may call during this run, for
795
+ * an agent that allows the page's tools. A call is HELD until the page
796
+ * answers it with `answerPageTool`. At most 20. `foirChatTransport`'s
797
+ * `pageTools` sends these and answers the calls for you.
798
+ */
799
+ pageTools?: FoirPageToolOffer[];
800
+ }
801
+ /** A tool of the caller's page, offered to an agent for one run. */
802
+ export interface FoirPageToolOffer {
803
+ /** Lowercase letters, digits and _, starting with a letter; not the name of one of the agent's own tools. */
804
+ name: string;
805
+ /** What the tool does, as the model is told it. At most 1000 characters. */
806
+ description?: string;
807
+ /** The JSON Schema of the tool's input: an object schema. Left out, the tool takes no input. */
808
+ inputSchema?: Record<string, unknown>;
809
+ }
810
+ /** What a tag in a message points at. */
811
+ export type FoirMessageTagKind = 'RECORD' | 'MODEL' | 'PERSON' | 'FILE' | 'OPERATION' | 'AGENT' | 'HOOK' | 'SCHEDULE' | 'ORGANIZATION' | 'NOTE' | 'FIELD';
812
+ /** One thing a message points at. It is kept by id and never resolved into the message. */
813
+ export interface FoirMessageTag {
814
+ kind: FoirMessageTagKind;
815
+ /** The thing's id, or its key where it is addressed by one (a model, an operation, an agent, a schedule). */
816
+ id: string;
817
+ /** A record's or a field's model, by key. */
818
+ model?: string;
819
+ /** A field's path within its record. */
820
+ field?: string;
821
+ /** What the person saw when they picked it. */
822
+ label?: string;
823
+ }
824
+ /** A file sent an agent with a message: an image or a PDF. */
825
+ export interface FoirAgentAttachment {
826
+ id: string;
827
+ filename: string;
828
+ mediaType: string;
829
+ /** Its length in bytes. */
830
+ size: number;
831
+ }
832
+ /**
833
+ * `createAgentAttachment` arguments: a PNG, JPEG, GIF or WebP image of at most
834
+ * 5 MB, or a PDF of at most 10 MB. A visitor may send images only, 20 a day.
835
+ */
836
+ export interface FoirCreateAgentAttachmentArgs {
837
+ agent: string;
838
+ filename: string;
839
+ mediaType: string;
840
+ /** The file's exact length in bytes. */
841
+ size: number;
842
+ visitorToken?: string;
843
+ }
844
+ /** Where a file's bytes go before it is sent. */
845
+ export interface FoirAgentAttachmentUpload {
846
+ attachment: FoirAgentAttachment;
847
+ /** An HTTP PUT of exactly `size` bytes, with `mediaType` as its Content-Type. */
848
+ uploadUrl: string;
849
+ /** When `uploadUrl` stops taking bytes; an attachment not sent by then is removed. */
850
+ expiresAt: string;
851
+ }
852
+ /** `agentThreads` — your conversations with the project's agents, newest first. */
853
+ export type FoirAgentThreadsResult = FoirConnection<FoirAgentThread>;
854
+ /** Your own account at a remote server a project's agent calls for you. */
855
+ export interface FoirMcpConnection {
856
+ id: string;
857
+ agent: string;
858
+ server: string;
859
+ scopes: string[];
860
+ connectedAt?: string | null;
861
+ expiresAt?: string | null;
862
+ }
@@ -58,8 +58,8 @@ export type { FoirManifest, FoirManifestComposite, FoirManifestModel, FoirManife
58
58
  export { planFoirModelCall, planFoirNamespaceCall } from './document';
59
59
  export type { FoirCall, FoirDocumentPlan, FoirNamespaceCall, FoirNamespaceSelections, FoirRecordPath, FoirSelectionModel, FoirSelectionNamespace, FoirSelections, FoirSelectionSource, FoirSelectionUnions, } from './document';
60
60
  export { createFoirSubjectRegistry, recordFoirSubjects } from './subjects';
61
- export type { FoirSubject, FoirSubjectEntry, FoirSubjectOptions, FoirSubjectOrigin, FoirSubjectRegistry, } from './subjects';
62
- export type { CollabInfo, FileValue, FoirAccessGrant, FoirAccessLevel, FoirAccessSource, FoirAccessor, FoirCreateMyNoteArgs, FoirWriteNoteArgs, FoirUserNote, FoirUserNoteAttachment, FoirDegraded, FoirDepthBelow, FoirDepthLevel, FoirDeviceType, FoirGranteeKind, FoirJsonValue, FoirMyAccess, FoirMyNotesArgs, FoirMyNotesResult, FoirNoteConfig, FoirNoteReceipt, FoirNoteSubjectType, FoirPlatformType, FoirRecordOwner, FoirResolveContext, FoirResourceAccess, FoirUnexpandedRecord, FoirUpdateManyPayload, FoirVisibility, GeoPoint, Image, ImageFormat, ImageVariant, ImageVariantSet, MediaValue, Passage, Prose, ProseSpan, RecordAncestor, Reference, Richtext, Video, } from './builtins';
61
+ export type { FoirFieldMark, FoirFieldMarkAttributes, FoirSubject, FoirSubjectEntry, FoirSubjectOptions, FoirSubjectOrigin, FoirSubjectRegistry, } from './subjects';
62
+ export type { CollabInfo, FileValue, FoirAccessGrant, FoirAccessLevel, FoirAccessSource, FoirAccessor, FoirCreateMyNoteArgs, FoirWriteNoteArgs, FoirUserNote, FoirUserNoteAttachment, FoirDegraded, FoirDepthBelow, FoirDepthLevel, FoirDeviceType, FoirGranteeKind, FoirJsonValue, FoirMyAccess, FoirMyNotesArgs, FoirMyNotesResult, FoirAgentApproval, FoirAgentAttachment, FoirAgentAttachmentUpload, FoirAgentRun, FoirAgentRunNode, FoirAgentRunStatus, FoirAgentThread, FoirAgentThreadMessage, FoirAgentThreadsResult, FoirMcpConnection, FoirStartAgentRunArgs, FoirPageToolOffer, FoirCreateAgentAttachmentArgs, FoirMessageTag, FoirMessageTagKind, FoirNoteConfig, FoirNoteReceipt, FoirNoteSubjectType, FoirPlatformType, FoirRecordOwner, FoirResolveContext, FoirResourceAccess, FoirUnexpandedRecord, FoirUpdateManyPayload, FoirVisibility, GeoPoint, Image, ImageFormat, ImageVariant, ImageVariantSet, MediaValue, Passage, Prose, ProseSpan, RecordAncestor, Reference, Richtext, Video, } from './builtins';
63
63
  /**
64
64
  * Pre-rename spellings. The `<Name>Block` wrappers and the `<Name>Value`
65
65
  * split are the same thing as the types above — an item IS its value — so each
@@ -76,10 +76,12 @@ export { foirSocketEndpoint, FoirSocketTransport } from './ws-transport';
76
76
  export type { FoirReconnectPolicy, FoirSubscribeRequest, FoirSubscription, FoirSubscriptionHandlers, FoirWebSocketFactory, FoirWebSocketLike, } from './ws-transport';
77
77
  export { printSubscriptionDocument } from './subscription-document';
78
78
  export type { FoirSubscriptionArgument, PrintSubscriptionDocumentInput, } from './subscription-document';
79
- export type { FoirChangeSubscribeOptions, FoirExecutionSubscribeOptions, FoirJobProgressEvent, FoirModelSubscriptions, FoirNamespaceSubscriptions, FoirNotificationEvent, FoirOperationExecutionEvent, FoirRecordChangedEvent, } from './subscriptions';
79
+ export type { FoirChangeSubscribeOptions, FoirExecutionSubscribeOptions, FoirAgentRunEvent, FoirAgentRunSubscribeOptions, FoirJobProgressEvent, FoirModelSubscriptions, FoirNamespaceSubscriptions, FoirNotificationEvent, FoirOperationExecutionEvent, FoirRecordChangedEvent, } from './subscriptions';
80
80
  export type { FoirConnection, FoirFieldsShape, FoirModelDefinition, FoirNamespaceDefinition, FoirNamespaceOpDefinition, FoirOpDefinition, FoirRelationDefinition, FoirReturnDefinition, FoirSchemaDefinition, } from './schema';
81
81
  export type { FoirInclude, FoirModelOperation, FoirNamespaceOperation, FoirOmittableKey, FoirOpResult, FoirQuery, FoirRecordResult, FoirWriteResult, } from './selection';
82
82
  export { FoirDecimal, decimal } from './decimal';
83
83
  export type { FoirDecimalDivOptions, FoirDecimalInput, FoirDecimalRounding, } from './decimal';
84
84
  export { FoirRequestError, FoirAuthDowngradedError, FoirSessionExpiredError, FOIR_VISITOR_IP_HEADER, stepUpRequired, } from '../transport/foir-http';
85
85
  export type { FoirEnv, FoirGraphQLErrorItem, FoirTokenProvider, FoirAuthDowngrade, FoirStepUp, FoirVisitor, FoirVisitorSource, } from '../transport/foir-http';
86
+ export { askAgent, uploadAgentFile, visitorToken } from './agents';
87
+ export type { AgentReply, AskAgentOptions, FoirAgentFile, FoirAgentFilesClient, FoirAgentsClient } from './agents';
@@ -140,6 +140,19 @@ export interface FoirSubjectOptions {
140
140
  */
141
141
  label?: (record: Readonly<Record<string, unknown>>, subject: FoirSubject) => string | null | undefined;
142
142
  }
143
+ /** One field of one record, as an element on the page was marked with it. */
144
+ export interface FoirFieldMark {
145
+ /** The record the field belongs to. */
146
+ subject: FoirSubject;
147
+ /** The field's key on the model, e.g. `summary`, or a nested path. */
148
+ field: string;
149
+ /** What to call the field on screen, when the host named it. */
150
+ label?: string;
151
+ }
152
+ /** What `FoirSubjectRegistry.field` returns: spread it onto the element. */
153
+ export interface FoirFieldMarkAttributes {
154
+ 'data-foir-field': string;
155
+ }
143
156
  export interface FoirSubjectRegistry {
144
157
  /**
145
158
  * Record one subject.
@@ -190,6 +203,38 @@ export interface FoirSubjectRegistry {
190
203
  * failure is reported rather than dropped (see `recordFoirSubjects`).
191
204
  */
192
205
  subscribe(listener: () => void): () => void;
206
+ /**
207
+ * Mark an element as showing one field of a record, so a widget can let the
208
+ * reader point at what they mean. Spread the answer onto the element:
209
+ *
210
+ * ```tsx
211
+ * <h1 {...subjects.field(page, 'title', { label: 'Title' })}>{page.title}</h1>
212
+ * ```
213
+ *
214
+ * The attribute is an opaque token, not the model, record or field: the
215
+ * registry holds what it stands for, as it holds every subject, so the page
216
+ * does not print the project's vocabulary. It is the same token for the same
217
+ * field wherever it is computed, so a server-rendered mark hydrates to the
218
+ * attribute the server wrote. Call it where the browser renders too: a mark
219
+ * only a server component made has nothing in the browser to resolve it.
220
+ *
221
+ * `label` is the only thing about the field a widget shows. Without one, it
222
+ * names the record and not the field.
223
+ */
224
+ field(subject: Pick<FoirSubject, 'modelKey' | 'recordId'> & {
225
+ label?: string;
226
+ }, field: string, options?: {
227
+ label?: string;
228
+ }): FoirFieldMarkAttributes;
229
+ /**
230
+ * The field a marked element points at, by its `data-foir-field` token.
231
+ * Undefined for a token this registry did not mark.
232
+ *
233
+ * `clear()` keeps the marks. A single-page app clears on navigation, and the
234
+ * next page may already have rendered its marks by then; a stale mark points
235
+ * at nothing on screen, so it is never offered.
236
+ */
237
+ pointedAt(token: string): FoirFieldMark | undefined;
193
238
  }
194
239
  /**
195
240
  * Build a registry.
@@ -50,6 +50,7 @@
50
50
  * round trip in front of every query for good reason; in front of a socket that
51
51
  * will live for minutes it is noise.
52
52
  */
53
+ import type { FoirAgentRunNode, FoirAgentRunStatus, FoirAgentThreadMessage } from './builtins';
53
54
  import type { FoirManifest } from './manifest';
54
55
  import type { FoirClientConfig } from './transport';
55
56
  import { type FoirSubscription, type FoirSubscriptionHandlers } from './ws-transport';
@@ -108,6 +109,40 @@ export interface FoirOperationExecutionEvent {
108
109
  /** Present on `status: failed` or `timed_out`. */
109
110
  errorJson?: unknown;
110
111
  }
112
+ /**
113
+ * `agentRun` — one event of an agent's run as it answers.
114
+ *
115
+ * TEXT and REASONING carry new text; NODE a step that started, changed or
116
+ * ended (a tool call, a held act, a child agent); MESSAGE a message kept on
117
+ * the thread; STATUS where the run now stands. The stream ends after a STATUS
118
+ * that is final.
119
+ */
120
+ export interface FoirAgentRunEvent {
121
+ /** Resume a dropped stream from the last seq seen. */
122
+ seq: string;
123
+ kind: 'TEXT' | 'REASONING' | 'NODE' | 'MESSAGE' | 'STATUS' | 'DATA';
124
+ text?: string | null;
125
+ messageId?: string | null;
126
+ node?: FoirAgentRunNode | null;
127
+ message?: FoirAgentThreadMessage | null;
128
+ status?: FoirAgentRunStatus | null;
129
+ answer?: string | null;
130
+ error?: string | null;
131
+ /** DATA: which of the agent's data parts, and the data, which fits its schema. */
132
+ dataName?: string | null;
133
+ data?: unknown;
134
+ /** STATUS, once a run of an agent with an output schema has completed: its typed answer. */
135
+ output?: unknown;
136
+ }
137
+ /** Options for `foir.ns.agents.onRun`. */
138
+ export type FoirAgentRunSubscribeOptions = FoirSubscriptionHandlers<FoirAgentRunEvent> & {
139
+ /** The run's id, as `startAgentRun` answered it. */
140
+ id: string;
141
+ /** Only events after this seq, to resume a dropped stream. */
142
+ after?: string;
143
+ /** A visitor with nobody signed in: the secret their browser keeps. */
144
+ visitorToken?: string;
145
+ };
111
146
  /** Options for `foir.ns.operations.onExecution`. */
112
147
  export type FoirExecutionSubscribeOptions = FoirSubscriptionHandlers<FoirOperationExecutionEvent> & {
113
148
  /** Execution id, as returned by `execute<Op>`. */
@@ -168,6 +203,9 @@ export type FoirNamespaceSubscriptions<NK> = NK extends 'notifications' ? {
168
203
  onJobProgress(handlers: FoirSubscriptionHandlers<FoirJobProgressEvent>): FoirSubscription;
169
204
  /** Stream one operation execution's progress until it reaches a terminal state. */
170
205
  onExecution(options: FoirExecutionSubscribeOptions): FoirSubscription;
206
+ } : NK extends 'agents' ? {
207
+ /** Follow an agent's run as it answers, until its final status. */
208
+ onRun(options: FoirAgentRunSubscribeOptions): FoirSubscription;
171
209
  } : {};
172
210
  /** Does this (address, property) pair name a subscription rather than an op? */
173
211
  export declare function isModelSubscriptionMethod(name: string): boolean;