@signalcore/ui 1.0.0-beta.1 → 1.0.0-beta.2

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.
Files changed (108) hide show
  1. package/README.md +8 -1
  2. package/dist/AgentAbout.js +7 -4
  3. package/dist/AgentAbout.js.map +1 -1
  4. package/dist/AgentTasks.js +2 -1
  5. package/dist/AgentTasks.js.map +1 -1
  6. package/dist/VoiceCall.js +1 -1
  7. package/dist/VoiceCall.js.map +1 -1
  8. package/dist/about.d.ts +34 -144
  9. package/dist/about.js +6 -8
  10. package/dist/about.js.map +1 -1
  11. package/dist/automation/cron.d.ts +1 -1
  12. package/dist/automation/cron.js.map +1 -1
  13. package/dist/automation/marks.js +7 -3
  14. package/dist/automation/marks.js.map +1 -1
  15. package/dist/automation/messages.d.ts +2 -0
  16. package/dist/automation/messages.js +2 -0
  17. package/dist/automation/messages.js.map +1 -1
  18. package/dist/automation/types.d.ts +25 -128
  19. package/dist/automation/types.js +36 -0
  20. package/dist/automation/types.js.map +1 -0
  21. package/dist/automation/when.d.ts +1 -1
  22. package/dist/automation/when.js +5 -1
  23. package/dist/automation/when.js.map +1 -1
  24. package/dist/blocks.d.ts +23 -1
  25. package/dist/browser.js +2 -2
  26. package/dist/browser.js.map +1 -1
  27. package/dist/call.d.ts +1 -1
  28. package/dist/call.js.map +1 -1
  29. package/dist/contract.d.ts +262 -0
  30. package/dist/credentials.js.map +1 -1
  31. package/dist/dev.js +1 -1
  32. package/dist/dev.js.map +1 -1
  33. package/dist/es.js +9 -1
  34. package/dist/es.js.map +1 -1
  35. package/dist/index.d.ts +2 -2
  36. package/dist/index.js +2 -1
  37. package/dist/kit/AudioPlayer.js +1 -1
  38. package/dist/kit/AudioPlayer.js.map +1 -1
  39. package/dist/kit/Choices.js +1 -1
  40. package/dist/kit/Choices.js.map +1 -1
  41. package/dist/kit/FileField.js +1 -1
  42. package/dist/kit/FileField.js.map +1 -1
  43. package/dist/kit/Popover.js.map +1 -1
  44. package/dist/kit/Tile.d.ts +1 -1
  45. package/dist/kit/Tile.js +1 -1
  46. package/dist/kit/Tile.js.map +1 -1
  47. package/dist/kit/messages.d.ts +13 -0
  48. package/dist/kit/messages.js +7 -1
  49. package/dist/kit/messages.js.map +1 -1
  50. package/dist/kit/uploads.d.ts +2 -1
  51. package/dist/kit/uploads.js +1 -1
  52. package/dist/kit/uploads.js.map +1 -1
  53. package/dist/kit/waveform.js.map +1 -1
  54. package/dist/markdown.js.map +1 -1
  55. package/dist/marks.js +2 -3
  56. package/dist/marks.js.map +1 -1
  57. package/dist/surface/Markdown.js +1 -1
  58. package/dist/surface/Markdown.js.map +1 -1
  59. package/dist/surface/Surface.js +43 -4
  60. package/dist/surface/Surface.js.map +1 -1
  61. package/dist/surface/scope.d.ts +1 -1
  62. package/dist/surface/scope.js.map +1 -1
  63. package/dist/surface/values.js +1 -1
  64. package/dist/surface/values.js.map +1 -1
  65. package/dist/tint.d.ts +1 -1
  66. package/dist/tint.js +1 -1
  67. package/dist/tint.js.map +1 -1
  68. package/dist/usePolled.js +1 -1
  69. package/dist/usePolled.js.map +1 -1
  70. package/dist/voice/webgl.js +1 -1
  71. package/dist/voice/webgl.js.map +1 -1
  72. package/dist/widget.js +14 -14
  73. package/package.json +1 -1
  74. package/src/AgentAbout.tsx +10 -3
  75. package/src/AgentTasks.tsx +2 -2
  76. package/src/VoiceCall.tsx +1 -1
  77. package/src/about.ts +42 -144
  78. package/src/automation/cron.ts +1 -1
  79. package/src/automation/marks.tsx +6 -2
  80. package/src/automation/messages.ts +4 -0
  81. package/src/automation/types.ts +58 -118
  82. package/src/automation/when.ts +3 -1
  83. package/src/blocks.ts +25 -0
  84. package/src/browser.ts +4 -4
  85. package/src/call.ts +1 -1
  86. package/src/contract.ts +1720 -0
  87. package/src/credentials.ts +2 -2
  88. package/src/dev.ts +1 -1
  89. package/src/es.ts +8 -0
  90. package/src/index.ts +1 -0
  91. package/src/kit/AudioPlayer.tsx +1 -1
  92. package/src/kit/Choices.tsx +1 -1
  93. package/src/kit/FileField.tsx +1 -1
  94. package/src/kit/Popover.tsx +1 -1
  95. package/src/kit/Tile.tsx +1 -1
  96. package/src/kit/messages.ts +20 -0
  97. package/src/kit/uploads.ts +2 -2
  98. package/src/kit/waveform.ts +1 -1
  99. package/src/markdown.ts +1 -1
  100. package/src/marks.tsx +3 -123
  101. package/src/styles.css +15 -0
  102. package/src/surface/Markdown.tsx +1 -1
  103. package/src/surface/Surface.tsx +53 -4
  104. package/src/surface/scope.ts +3 -1
  105. package/src/surface/values.ts +5 -5
  106. package/src/tint.ts +1 -1
  107. package/src/usePolled.ts +2 -2
  108. package/src/voice/webgl.ts +1 -1
package/dist/about.d.ts CHANGED
@@ -1,85 +1,24 @@
1
+ import { About as About$1, AboutOut as AboutOut$1, ActionRowOut, Does as Does$1, FactAsk, FactAutomation, FactChannel, FactConnection, FactDevice, FactFile, FactKey, FactTable, Facts as Facts$1, MemoryOut } from "./contract.js";
1
2
  import { formatSize } from "./kit/numbers.js";
2
3
  //#region src/about.d.ts
3
- /**
4
- * Qué puede: what an agent says about itself and the facts it rests on (`GET /agents/{id}/about`,
5
- * `POST /agents/{id}/describe`). The words are the model's, written from the agent's folder and
6
- * stale the moment it changes; the facts are the platform's, read each time.
7
- */
8
4
  /** The marks the package draws (a topic's, an automation's kind, a note's tone). */
9
5
  export declare const ICONS: readonly ["message", "phone", "mail", "calendar", "clock", "search", "file", "table", "bell", "hand", "user", "globe", "code", "lock", "cart", "card", "map", "check", "warning", "sparkle"];
10
6
  export type Icon = (typeof ICONS)[number];
11
- /** One automation as the agent tells it: what it does then, and when. */
12
- export interface Does {
13
- /** The automation's id. */
14
- automation: string;
15
- text: string;
16
- /** When it runs, the way a person says it: "Cada día a las 8:00". */
17
- when: string;
18
- }
7
+ /** One automation as the agent tells it: what it does then, and when ("Cada día a las 8:00"). */
8
+ export type Does = Does$1;
19
9
  /** What the agent says about itself: a lead, what it does, what it asks leave for. */
20
- export interface About {
21
- /** Two or three sentences, first person, in the owner's language. */
22
- summary: string;
23
- does: Does[];
24
- asks: string[];
25
- }
26
- export type ActionSource = "default" | "library" | "own";
27
- export interface ActionFact {
28
- name: string;
29
- description: string;
30
- source: ActionSource;
31
- on: boolean;
32
- needs_approval: boolean;
33
- destructive: boolean;
34
- /** Its input as the model gets it (JSON Schema); left out by an API from before. */
35
- input_schema?: Readonly<Record<string, unknown>> | undefined;
36
- }
37
- export type AutomationKind = "schedule" | "webhook" | "event";
38
- /** Something the agent does on its own: at a time, when another system calls, on an event. */
39
- export interface AutomationFact {
40
- id: string;
41
- /** Its file's name, `automations/<name>.py`: how its page is reached. */
42
- name: string;
43
- kind: AutomationKind;
44
- title: string;
45
- /** What it does, in the owner's words. */
46
- summary: string;
47
- /** The same words, for a reader of the older shape. */
48
- say: string;
49
- /** A cron line and its time zone, for one that runs at a time. */
50
- schedule?: string | null | undefined;
51
- timezone?: string | null | undefined;
52
- /** Where another system calls it, for a webhook (a path on the API). */
53
- url?: string | null | undefined;
54
- /** For one on an app's event: the app (the connection's name), the event as its provider
55
- * names it, and the app as its mark is drawn (`composio:gmail`, the provider's logo). */
56
- app?: string | null | undefined;
57
- /** The app as people write it (`Google Calendar`). */
58
- app_title?: string | null | undefined;
59
- event?: string | null | undefined;
60
- provider?: string | undefined;
61
- icon?: string | null | undefined;
62
- /** Off: declared, but it doesn't run. */
63
- on: boolean;
64
- next_run_at?: string | null | undefined;
65
- }
10
+ export type About = About$1;
11
+ /** One of its actions: where it comes from, whether it is on and asks first, its input. */
12
+ export type ActionFact = ActionRowOut;
13
+ export type AutomationKind = FactAutomation["kind"];
14
+ /** Something the agent does on its own: at a time, when another system calls, on an app's event
15
+ * (with the app's name and mark), on a message. */
16
+ export type AutomationFact = FactAutomation;
17
+ /** Who brings an app: one of the providers, an MCP server, the business's own API. */
66
18
  export type Provider = "arcade" | "composio" | "mcp" | "api";
67
- export interface ConnectionFact {
68
- provider: Provider;
69
- name: string;
70
- /** The app, as the provider names it (`gmail`). */
71
- toolkit?: string | undefined;
72
- /** The app as people write it (`Google Calendar`). */
73
- title?: string | undefined;
74
- /** pending · active · error · disconnected */
75
- status?: string | undefined;
76
- /** The provider's names of what the agent may do in it (`Gmail.SendEmail`). */
77
- actions: string[];
78
- /** What the provider calls each of them for people (`List Events`), when it says. */
79
- titles?: Readonly<Record<string, string>> | undefined;
80
- /** A URL to the app's own mark, when the provider gives one. */
81
- icon?: string | null | undefined;
82
- }
19
+ /** An app it was given: its name and mark, and its tools, with their names for people
20
+ * (`titles`) and as the model calls them (`called`). */
21
+ export type ConnectionFact = FactConnection;
83
22
  /** An app of the agent's as people write it: its provider's name, else its alias made words. */
84
23
  export declare const appTitle: (connection: ConnectionFact) => string;
85
24
  /** A tool of an app as people read it: its provider's name for it, else its own made words. */
@@ -91,7 +30,10 @@ export declare function toolName(action: string): string;
91
30
  * as the model calls it, `gmail__GMAIL_SEND_EMAIL`, is "Send email (Gmail)".
92
31
  */
93
32
  export declare function actionWords(name: string): string;
94
- /** `gmail` + `Gmail.SendEmail` → `gmail__Gmail_SendEmail`: the tool the model is given. */
33
+ /**
34
+ * `gmail` + `Gmail.SendEmail` → `gmail__Gmail_SendEmail`: the tool the model is given.
35
+ * @deprecated The facts say it: `ConnectionFact.called`.
36
+ */
95
37
  export declare const generatedName: (alias: string, action: string) => string;
96
38
  /**
97
39
  * The tools the agent's apps give it, by the names the model calls them, in words: the
@@ -100,76 +42,24 @@ export declare const generatedName: (alias: string, action: string) => string;
100
42
  */
101
43
  export declare function appSteps(connections: readonly ConnectionFact[]): Record<string, string>;
102
44
  export type ChannelKind = "whatsapp" | "instagram" | "email" | "sms" | "web" | "phone";
103
- export interface ChannelFact {
104
- kind: ChannelKind;
105
- name: string;
106
- status: string;
107
- }
45
+ export type ChannelFact = FactChannel;
108
46
  /** A file the agent can read: its own, or one of the organization's, shared with every agent. */
109
- export interface FileFact {
110
- path: string;
111
- size: number;
112
- /** Text, Markdown, JSON, YAML or PDF, read by `search_files`; anything else is only kept. */
113
- searchable: boolean;
114
- /** The organization's, not the agent's own. */
115
- shared: boolean;
116
- }
117
- /** A line the agent kept with `remember`. */
118
- export interface MemoryFact {
119
- id: string;
120
- /** The agent that keeps it; the contact it is about, when it is about one. */
121
- agent_id?: string | undefined;
122
- contact_id?: string | null | undefined;
123
- text: string;
124
- created_at: string;
125
- }
126
- /** A key the agent may use: its own, or one of the organization's, shared with every agent. */
127
- export interface VaultFact {
128
- name: string;
129
- /** The hosts it may be sent to. */
130
- hosts?: string[] | undefined;
131
- /** The organization's, not the agent's own. */
132
- shared?: boolean | undefined;
133
- }
47
+ export type FileFact = FactFile;
48
+ /** A line the agent kept with `remember`: its own, or about the contact it names. */
49
+ export type MemoryFact = MemoryOut;
50
+ /** A key the agent may use: its own, or one of the organization's its access gives it. */
51
+ export type VaultFact = FactKey;
134
52
  /** A table of the organization's the agent may read or write (an agenda, the clients). */
135
- export interface DataFact {
136
- table: string;
137
- /** Its name for people, when it has one. */
138
- title?: string | null | undefined;
139
- can: string[];
140
- }
141
- export interface AskFact {
142
- agent_id: string;
143
- name: string;
144
- }
145
- export type DeviceKind = "extension" | "installer";
146
- export interface DeviceFact {
147
- kind: DeviceKind;
148
- name: string;
149
- status: string;
150
- }
151
- /** What the agent has, every list present from day one; one whose phase has not come is empty. */
152
- export interface Facts {
153
- actions: ActionFact[];
154
- automations: AutomationFact[];
155
- connections: ConnectionFact[];
156
- channels: ChannelFact[];
157
- /** Its own first, then the organization's shared. */
158
- files: FileFact[];
159
- /** Newest first. */
160
- memories: MemoryFact[];
161
- vault: VaultFact[];
162
- data: DataFact[];
163
- asks: AskFact[];
164
- devices: DeviceFact[];
165
- }
166
- export interface AboutOut {
167
- /** Null until the agent has written about itself once. */
168
- about: About | null;
169
- /** When the words were written; null when the folder changed since, so they are stale. */
170
- about_at: string | null;
171
- facts: Facts;
172
- }
53
+ export type DataFact = FactTable;
54
+ export type AskFact = FactAsk;
55
+ export type DeviceKind = FactDevice["kind"];
56
+ export type DeviceFact = FactDevice;
57
+ /** What the agent has, every list present from day one; one whose phase has not come is empty:
58
+ * its files its own first, its memories newest first. */
59
+ export type Facts = Facts$1;
60
+ /** What it says (null until written once; `about_at` null when the folder changed since, so the
61
+ * words are stale) and the facts. */
62
+ export type AboutOut = AboutOut$1;
173
63
  /**
174
64
  * What the panel lists of the facts beside what the agent does on its own, gathered into a few
175
65
  * things an owner reads at a glance: the apps it uses, its tools, what it knows (files and
package/dist/about.js CHANGED
@@ -1,10 +1,5 @@
1
1
  import { formatSize } from "./kit/numbers.js";
2
2
  //#region src/about.ts
3
- /**
4
- * Qué puede: what an agent says about itself and the facts it rests on (`GET /agents/{id}/about`,
5
- * `POST /agents/{id}/describe`). The words are the model's, written from the agent's folder and
6
- * stale the moment it changes; the facts are the platform's, read each time.
7
- */
8
3
  /** The marks the package draws (a topic's, an automation's kind, a note's tone). */
9
4
  const ICONS = [
10
5
  "message",
@@ -29,7 +24,7 @@ const ICONS = [
29
24
  "sparkle"
30
25
  ];
31
26
  /** An app of the agent's as people write it: its provider's name, else its alias made words. */
32
- const appTitle = (connection) => connection.title ?? toolName(connection.name);
27
+ const appTitle = (connection) => connection.title || toolName(connection.name);
33
28
  /** A tool of an app as people read it: its provider's name for it, else its own made words. */
34
29
  const toolTitle = (connection, action) => connection.titles?.[action] ?? toolName(action);
35
30
  /** A tool of an app as a person reads it: `Gmail.SendEmail` is "Send email". */
@@ -49,7 +44,10 @@ function actionWords(name) {
49
44
  }
50
45
  /** The longest name the model takes for a tool (`app/connections` cuts there too). */
51
46
  const MAX_TOOL_NAME = 64;
52
- /** `gmail` + `Gmail.SendEmail` → `gmail__Gmail_SendEmail`: the tool the model is given. */
47
+ /**
48
+ * `gmail` + `Gmail.SendEmail` → `gmail__Gmail_SendEmail`: the tool the model is given.
49
+ * @deprecated The facts say it: `ConnectionFact.called`.
50
+ */
53
51
  const generatedName = (alias, action) => `${alias}__${action.replace(/[^A-Za-z0-9_]/g, "_")}`.slice(0, MAX_TOOL_NAME);
54
52
  /**
55
53
  * The tools the agent's apps give it, by the names the model calls them, in words: the
@@ -57,7 +55,7 @@ const generatedName = (alias, action) => `${alias}__${action.replace(/[^A-Za-z0-
57
55
  * read them (`ChatMessages.steps`).
58
56
  */
59
57
  function appSteps(connections) {
60
- return Object.fromEntries(connections.flatMap((connection) => connection.actions.map((action) => [generatedName(connection.name, action), `${toolTitle(connection, action)} (${appTitle(connection)})`])));
58
+ return Object.fromEntries(connections.flatMap((connection) => connection.actions.map((action) => [connection.called[action] ?? generatedName(connection.name, action), `${toolTitle(connection, action)} (${appTitle(connection)})`])));
61
59
  }
62
60
  /** The topics in the order the panel lists them. */
63
61
  const TOPICS = [
package/dist/about.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"about.js","names":[],"sources":["../src/about.ts"],"sourcesContent":["/**\n * Qué puede: what an agent says about itself and the facts it rests on (`GET /agents/{id}/about`,\n * `POST /agents/{id}/describe`). The words are the model's, written from the agent's folder and\n * stale the moment it changes; the facts are the platform's, read each time.\n */\n\n/** The marks the package draws (a topic's, an automation's kind, a note's tone). */\nexport const ICONS = [\n \"message\",\n \"phone\",\n \"mail\",\n \"calendar\",\n \"clock\",\n \"search\",\n \"file\",\n \"table\",\n \"bell\",\n \"hand\",\n \"user\",\n \"globe\",\n \"code\",\n \"lock\",\n \"cart\",\n \"card\",\n \"map\",\n \"check\",\n \"warning\",\n \"sparkle\",\n] as const;\n\nexport type Icon = (typeof ICONS)[number];\n\n/** One automation as the agent tells it: what it does then, and when. */\nexport interface Does {\n /** The automation's id. */\n automation: string;\n text: string;\n /** When it runs, the way a person says it: \"Cada día a las 8:00\". */\n when: string;\n}\n\n/** What the agent says about itself: a lead, what it does, what it asks leave for. */\nexport interface About {\n /** Two or three sentences, first person, in the owner's language. */\n summary: string;\n does: Does[];\n asks: string[];\n}\n\nexport type ActionSource = \"default\" | \"library\" | \"own\";\n\nexport interface ActionFact {\n name: string;\n description: string;\n source: ActionSource;\n on: boolean;\n needs_approval: boolean;\n destructive: boolean;\n /** Its input as the model gets it (JSON Schema); left out by an API from before. */\n input_schema?: Readonly<Record<string, unknown>> | undefined;\n}\n\nexport type AutomationKind = \"schedule\" | \"webhook\" | \"event\";\n\n/** Something the agent does on its own: at a time, when another system calls, on an event. */\nexport interface AutomationFact {\n id: string;\n /** Its file's name, `automations/<name>.py`: how its page is reached. */\n name: string;\n kind: AutomationKind;\n title: string;\n /** What it does, in the owner's words. */\n summary: string;\n /** The same words, for a reader of the older shape. */\n say: string;\n /** A cron line and its time zone, for one that runs at a time. */\n schedule?: string | null | undefined;\n timezone?: string | null | undefined;\n /** Where another system calls it, for a webhook (a path on the API). */\n url?: string | null | undefined;\n /** For one on an app's event: the app (the connection's name), the event as its provider\n * names it, and the app as its mark is drawn (`composio:gmail`, the provider's logo). */\n app?: string | null | undefined;\n /** The app as people write it (`Google Calendar`). */\n app_title?: string | null | undefined;\n event?: string | null | undefined;\n provider?: string | undefined;\n icon?: string | null | undefined;\n /** Off: declared, but it doesn't run. */\n on: boolean;\n next_run_at?: string | null | undefined;\n}\n\nexport type Provider = \"arcade\" | \"composio\" | \"mcp\" | \"api\";\n\nexport interface ConnectionFact {\n provider: Provider;\n name: string;\n /** The app, as the provider names it (`gmail`). */\n toolkit?: string | undefined;\n /** The app as people write it (`Google Calendar`). */\n title?: string | undefined;\n /** pending · active · error · disconnected */\n status?: string | undefined;\n /** The provider's names of what the agent may do in it (`Gmail.SendEmail`). */\n actions: string[];\n /** What the provider calls each of them for people (`List Events`), when it says. */\n titles?: Readonly<Record<string, string>> | undefined;\n /** A URL to the app's own mark, when the provider gives one. */\n icon?: string | null | undefined;\n}\n\n/** An app of the agent's as people write it: its provider's name, else its alias made words. */\nexport const appTitle = (connection: ConnectionFact): string =>\n connection.title ?? toolName(connection.name);\n\n/** A tool of an app as people read it: its provider's name for it, else its own made words. */\nexport const toolTitle = (connection: ConnectionFact, action: string): string =>\n connection.titles?.[action] ?? toolName(action);\n\n/** A tool of an app as a person reads it: `Gmail.SendEmail` is \"Send email\". */\nexport function toolName(action: string): string {\n const bare = action.slice(action.lastIndexOf(\".\") + 1);\n const words = bare\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .replace(/_/g, \" \")\n .toLowerCase();\n return words.charAt(0).toUpperCase() + words.slice(1);\n}\n\n/**\n * An action's name made words, for one nobody named: `ver_hoja` is \"Ver hoja\"; an app's tool\n * as the model calls it, `gmail__GMAIL_SEND_EMAIL`, is \"Send email (Gmail)\".\n */\nexport function actionWords(name: string): string {\n const split = name.indexOf(\"__\");\n if (split < 0) return toolName(name);\n const tool = name.slice(split + 2);\n const bare = tool.slice(tool.indexOf(\"_\") + 1) || tool;\n return `${toolName(bare)} (${toolName(name.slice(0, split))})`;\n}\n\n/** The longest name the model takes for a tool (`app/connections` cuts there too). */\nconst MAX_TOOL_NAME = 64;\n\n/** `gmail` + `Gmail.SendEmail` → `gmail__Gmail_SendEmail`: the tool the model is given. */\nexport const generatedName = (alias: string, action: string): string =>\n `${alias}__${action.replace(/[^A-Za-z0-9_]/g, \"_\")}`.slice(0, MAX_TOOL_NAME);\n\n/**\n * The tools the agent's apps give it, by the names the model calls them, in words: the\n * provider's for the tool and the app's (\"List Events (Google Calendar)\"), as a chat's steps\n * read them (`ChatMessages.steps`).\n */\nexport function appSteps(connections: readonly ConnectionFact[]): Record<string, string> {\n return Object.fromEntries(\n connections.flatMap((connection) =>\n connection.actions.map((action) => [\n generatedName(connection.name, action),\n `${toolTitle(connection, action)} (${appTitle(connection)})`,\n ]),\n ),\n );\n}\n\nexport type ChannelKind = \"whatsapp\" | \"instagram\" | \"email\" | \"sms\" | \"web\" | \"phone\";\n\nexport interface ChannelFact {\n kind: ChannelKind;\n name: string;\n status: string;\n}\n\n/** A file the agent can read: its own, or one of the organization's, shared with every agent. */\nexport interface FileFact {\n path: string;\n size: number;\n /** Text, Markdown, JSON, YAML or PDF, read by `search_files`; anything else is only kept. */\n searchable: boolean;\n /** The organization's, not the agent's own. */\n shared: boolean;\n}\n\n/** A line the agent kept with `remember`. */\nexport interface MemoryFact {\n id: string;\n /** The agent that keeps it; the contact it is about, when it is about one. */\n agent_id?: string | undefined;\n contact_id?: string | null | undefined;\n text: string;\n created_at: string;\n}\n\n/** A key the agent may use: its own, or one of the organization's, shared with every agent. */\nexport interface VaultFact {\n name: string;\n /** The hosts it may be sent to. */\n hosts?: string[] | undefined;\n /** The organization's, not the agent's own. */\n shared?: boolean | undefined;\n}\n\n/** A table of the organization's the agent may read or write (an agenda, the clients). */\nexport interface DataFact {\n table: string;\n /** Its name for people, when it has one. */\n title?: string | null | undefined;\n can: string[];\n}\n\nexport interface AskFact {\n agent_id: string;\n name: string;\n}\n\nexport type DeviceKind = \"extension\" | \"installer\";\n\nexport interface DeviceFact {\n kind: DeviceKind;\n name: string;\n status: string;\n}\n\n/** What the agent has, every list present from day one; one whose phase has not come is empty. */\nexport interface Facts {\n actions: ActionFact[];\n automations: AutomationFact[];\n connections: ConnectionFact[];\n channels: ChannelFact[];\n /** Its own first, then the organization's shared. */\n files: FileFact[];\n /** Newest first. */\n memories: MemoryFact[];\n vault: VaultFact[];\n data: DataFact[];\n asks: AskFact[];\n devices: DeviceFact[];\n}\n\nexport interface AboutOut {\n /** Null until the agent has written about itself once. */\n about: About | null;\n /** When the words were written; null when the folder changed since, so they are stale. */\n about_at: string | null;\n facts: Facts;\n}\n\n/**\n * What the panel lists of the facts beside what the agent does on its own, gathered into a few\n * things an owner reads at a glance: the apps it uses, its tools, what it knows (files and\n * tables), what it has learned, where it works (channels and devices), and its keys.\n */\nexport type Topic = \"apps\" | \"tools\" | \"knowledge\" | \"learning\" | \"channels\" | \"keys\";\n\n/** The topics in the order the panel lists them. */\nexport const TOPICS: readonly Topic[] = [\n \"apps\",\n \"tools\",\n \"knowledge\",\n \"learning\",\n \"channels\",\n \"keys\",\n];\n\n/** An automation with what the agent said about it, when it said something. */\nexport interface Told {\n automation: AutomationFact;\n line: Does | undefined;\n}\n\n/**\n * The agent's automations, in their order, each with the agent's line about it (matched by id):\n * one added since the words were written has none yet, and a line for one since removed is\n * dropped.\n */\nexport function automationsOf(about: About | null, facts: Facts): Told[] {\n const lines = new Map((about?.does ?? []).map((line) => [line.automation, line]));\n return facts.automations.map((automation) => ({ automation, line: lines.get(automation.id) }));\n}\n\n/** How many things a topic holds: the tools that are on, the rest whole. */\nexport function countOf(topic: Topic, facts: Facts): number {\n return namesOf(topic, facts, (action) => action.name).length;\n}\n\n/**\n * The names of what a topic holds, in order, as its row in the panel previews them: an app by its\n * name, a tool by `label` (the host's words for the shipped ones), a file by its path and a table\n * by its title, what it learned by the line itself.\n */\nexport function namesOf(\n topic: Topic,\n facts: Facts,\n label: (action: ActionFact) => string,\n): string[] {\n switch (topic) {\n case \"apps\":\n return facts.connections.map(appTitle);\n case \"tools\":\n return facts.actions.filter((action) => action.on).map(label);\n case \"knowledge\":\n return [\n ...facts.files.map((file) => file.path),\n ...facts.data.map((table) => table.title ?? table.table),\n ];\n case \"learning\":\n return facts.memories.map((memory) => memory.text);\n case \"channels\":\n return [\n ...facts.channels.map((channel) => channel.name),\n ...facts.devices.map((device) => device.name),\n ];\n case \"keys\":\n return facts.vault.map((secret) => secret.name);\n }\n}\n\nexport type AboutState = \"writing\" | \"stale\" | \"fresh\";\n\n/**\n * Which state the words are in: `writing` while there are none yet or the agent is writing them\n * anew (`loading`), `stale` when the agent changed since it wrote them, `fresh` otherwise.\n */\nexport function aboutState(\n about: About | null,\n aboutAt: string | null,\n loading: boolean,\n): AboutState {\n if (about === null || loading) return \"writing\";\n return aboutAt === null ? \"stale\" : \"fresh\";\n}\n\n/** A file's size as people read it (the kit's, where the file chips draw it). */\nexport { formatSize } from \"./kit/numbers\";\n\n/** How a status reads beside its words: working, broken, or neither. */\nexport type StatusTone = \"on\" | \"off\" | \"quiet\";\n\nconst ON: ReadonlySet<string> = new Set([\"live\", \"active\", \"connected\", \"on\", \"ready\", \"online\"]);\nconst OFF: ReadonlySet<string> = new Set([\n \"failed\",\n \"error\",\n \"disconnected\",\n \"off\",\n \"expired\",\n \"broken\",\n]);\n\n/** The tone of a channel's or a device's status, from the words the platform uses for it. */\nexport function toneOf(status: string): StatusTone {\n const word = status.trim().toLowerCase();\n if (ON.has(word)) return \"on\";\n if (OFF.has(word)) return \"off\";\n return \"quiet\";\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"about.js","names":[],"sources":["../src/about.ts"],"sourcesContent":["/**\n * Qué puede: what an agent says about itself and the facts it rests on (`GET /agents/{id}/about`,\n * `POST /agents/{id}/describe`). The words are the model's, written from the agent's folder and\n * stale the moment it changes; the facts are the platform's, read each time. Their types are the\n * contract's (`contract.ts`).\n */\n\nimport type * as C from \"./contract\";\n\n/** The marks the package draws (a topic's, an automation's kind, a note's tone). */\nexport const ICONS = [\n \"message\",\n \"phone\",\n \"mail\",\n \"calendar\",\n \"clock\",\n \"search\",\n \"file\",\n \"table\",\n \"bell\",\n \"hand\",\n \"user\",\n \"globe\",\n \"code\",\n \"lock\",\n \"cart\",\n \"card\",\n \"map\",\n \"check\",\n \"warning\",\n \"sparkle\",\n] as const;\n\nexport type Icon = (typeof ICONS)[number];\n\n/** One automation as the agent tells it: what it does then, and when (\"Cada día a las 8:00\"). */\nexport type Does = C.Does;\n\n/** What the agent says about itself: a lead, what it does, what it asks leave for. */\nexport type About = C.About;\n\nexport type ActionSource = C.ActionRowOut[\"source\"];\n\n/** One of its actions: where it comes from, whether it is on and asks first, its input. */\nexport type ActionFact = C.ActionRowOut;\n\nexport type AutomationKind = C.FactAutomation[\"kind\"];\n\n/** Something the agent does on its own: at a time, when another system calls, on an app's event\n * (with the app's name and mark), on a message. */\nexport type AutomationFact = C.FactAutomation;\n\n/** Who brings an app: one of the providers, an MCP server, the business's own API. */\nexport type Provider = \"arcade\" | \"composio\" | \"mcp\" | \"api\";\n\n/** An app it was given: its name and mark, and its tools, with their names for people\n * (`titles`) and as the model calls them (`called`). */\nexport type ConnectionFact = C.FactConnection;\n\n/** An app of the agent's as people write it: its provider's name, else its alias made words. */\nexport const appTitle = (connection: ConnectionFact): string =>\n connection.title || toolName(connection.name);\n\n/** A tool of an app as people read it: its provider's name for it, else its own made words. */\nexport const toolTitle = (connection: ConnectionFact, action: string): string =>\n connection.titles?.[action] ?? toolName(action);\n\n/** A tool of an app as a person reads it: `Gmail.SendEmail` is \"Send email\". */\nexport function toolName(action: string): string {\n const bare = action.slice(action.lastIndexOf(\".\") + 1);\n const words = bare\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .replace(/_/g, \" \")\n .toLowerCase();\n return words.charAt(0).toUpperCase() + words.slice(1);\n}\n\n/**\n * An action's name made words, for one nobody named: `ver_hoja` is \"Ver hoja\"; an app's tool\n * as the model calls it, `gmail__GMAIL_SEND_EMAIL`, is \"Send email (Gmail)\".\n */\nexport function actionWords(name: string): string {\n const split = name.indexOf(\"__\");\n if (split < 0) return toolName(name);\n const tool = name.slice(split + 2);\n const bare = tool.slice(tool.indexOf(\"_\") + 1) || tool;\n return `${toolName(bare)} (${toolName(name.slice(0, split))})`;\n}\n\n/** The longest name the model takes for a tool (`app/connections` cuts there too). */\nconst MAX_TOOL_NAME = 64;\n\n/**\n * `gmail` + `Gmail.SendEmail` → `gmail__Gmail_SendEmail`: the tool the model is given.\n * @deprecated The facts say it: `ConnectionFact.called`.\n */\nexport const generatedName = (alias: string, action: string): string =>\n `${alias}__${action.replace(/[^A-Za-z0-9_]/g, \"_\")}`.slice(0, MAX_TOOL_NAME);\n\n/**\n * The tools the agent's apps give it, by the names the model calls them, in words: the\n * provider's for the tool and the app's (\"List Events (Google Calendar)\"), as a chat's steps\n * read them (`ChatMessages.steps`).\n */\nexport function appSteps(connections: readonly ConnectionFact[]): Record<string, string> {\n return Object.fromEntries(\n connections.flatMap((connection) =>\n connection.actions.map((action) => [\n connection.called[action] ?? generatedName(connection.name, action),\n `${toolTitle(connection, action)} (${appTitle(connection)})`,\n ]),\n ),\n );\n}\n\nexport type ChannelKind = \"whatsapp\" | \"instagram\" | \"email\" | \"sms\" | \"web\" | \"phone\";\n\nexport type ChannelFact = C.FactChannel;\n\n/** A file the agent can read: its own, or one of the organization's, shared with every agent. */\nexport type FileFact = C.FactFile;\n\n/** A line the agent kept with `remember`: its own, or about the contact it names. */\nexport type MemoryFact = C.MemoryOut;\n\n/** A key the agent may use: its own, or one of the organization's its access gives it. */\nexport type VaultFact = C.FactKey;\n\n/** A table of the organization's the agent may read or write (an agenda, the clients). */\nexport type DataFact = C.FactTable;\n\nexport type AskFact = C.FactAsk;\n\nexport type DeviceKind = C.FactDevice[\"kind\"];\n\nexport type DeviceFact = C.FactDevice;\n\n/** What the agent has, every list present from day one; one whose phase has not come is empty:\n * its files its own first, its memories newest first. */\nexport type Facts = C.Facts;\n\n/** What it says (null until written once; `about_at` null when the folder changed since, so the\n * words are stale) and the facts. */\nexport type AboutOut = C.AboutOut;\n\n/**\n * What the panel lists of the facts beside what the agent does on its own, gathered into a few\n * things an owner reads at a glance: the apps it uses, its tools, what it knows (files and\n * tables), what it has learned, where it works (channels and devices), and its keys.\n */\nexport type Topic = \"apps\" | \"tools\" | \"knowledge\" | \"learning\" | \"channels\" | \"keys\";\n\n/** The topics in the order the panel lists them. */\nexport const TOPICS: readonly Topic[] = [\n \"apps\",\n \"tools\",\n \"knowledge\",\n \"learning\",\n \"channels\",\n \"keys\",\n];\n\n/** An automation with what the agent said about it, when it said something. */\nexport interface Told {\n automation: AutomationFact;\n line: Does | undefined;\n}\n\n/**\n * The agent's automations, in their order, each with the agent's line about it (matched by id):\n * one added since the words were written has none yet, and a line for one since removed is\n * dropped.\n */\nexport function automationsOf(about: About | null, facts: Facts): Told[] {\n const lines = new Map((about?.does ?? []).map((line) => [line.automation, line]));\n return facts.automations.map((automation) => ({ automation, line: lines.get(automation.id) }));\n}\n\n/** How many things a topic holds: the tools that are on, the rest whole. */\nexport function countOf(topic: Topic, facts: Facts): number {\n return namesOf(topic, facts, (action) => action.name).length;\n}\n\n/**\n * The names of what a topic holds, in order, as its row in the panel previews them: an app by its\n * name, a tool by `label` (the host's words for the shipped ones), a file by its path and a table\n * by its title, what it learned by the line itself.\n */\nexport function namesOf(\n topic: Topic,\n facts: Facts,\n label: (action: ActionFact) => string,\n): string[] {\n switch (topic) {\n case \"apps\":\n return facts.connections.map(appTitle);\n case \"tools\":\n return facts.actions.filter((action) => action.on).map(label);\n case \"knowledge\":\n return [\n ...facts.files.map((file) => file.path),\n ...facts.data.map((table) => table.title ?? table.table),\n ];\n case \"learning\":\n return facts.memories.map((memory) => memory.text);\n case \"channels\":\n return [\n ...facts.channels.map((channel) => channel.name),\n ...facts.devices.map((device) => device.name),\n ];\n case \"keys\":\n return facts.vault.map((secret) => secret.name);\n }\n}\n\nexport type AboutState = \"writing\" | \"stale\" | \"fresh\";\n\n/**\n * Which state the words are in: `writing` while there are none yet or the agent is writing them\n * anew (`loading`), `stale` when the agent changed since it wrote them, `fresh` otherwise.\n */\nexport function aboutState(\n about: About | null,\n aboutAt: string | null,\n loading: boolean,\n): AboutState {\n if (about === null || loading) return \"writing\";\n return aboutAt === null ? \"stale\" : \"fresh\";\n}\n\n/** A file's size as people read it (the kit's, where the file chips draw it). */\nexport { formatSize } from \"./kit/numbers\";\n\n/** How a status reads beside its words: working, broken, or neither. */\nexport type StatusTone = \"on\" | \"off\" | \"quiet\";\n\nconst ON: ReadonlySet<string> = new Set([\"live\", \"active\", \"connected\", \"on\", \"ready\", \"online\"]);\nconst OFF: ReadonlySet<string> = new Set([\n \"failed\",\n \"error\",\n \"disconnected\",\n \"off\",\n \"expired\",\n \"broken\",\n]);\n\n/** The tone of a channel's or a device's status, from the words the platform uses for it. */\nexport function toneOf(status: string): StatusTone {\n const word = status.trim().toLowerCase();\n if (ON.has(word)) return \"on\";\n if (OFF.has(word)) return \"off\";\n return \"quiet\";\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  //#region src/automation/cron.d.ts
2
2
  /**
3
- * A schedule's cron line, read into what it fires at: the moments of a day (a squad's day, an
3
+ * A schedule's cron line, read into what it fires at: the moments of a day (the agents' day, an
4
4
  * automation's next runs) and the sentence that says it (`whenOf`). Five fields (minute, hour,
5
5
  * day of the month, month, day of the week) with `*`, lists, ranges, steps and English names, as
6
6
  * the API's croniter reads them; anything past that is not read (null).
@@ -1 +1 @@
1
- {"version":3,"file":"cron.js","names":[],"sources":["../../src/automation/cron.ts"],"sourcesContent":["/**\n * A schedule's cron line, read into what it fires at: the moments of a day (a squad's day, an\n * automation's next runs) and the sentence that says it (`whenOf`). Five fields (minute, hour,\n * day of the month, month, day of the week) with `*`, lists, ranges, steps and English names, as\n * the API's croniter reads them; anything past that is not read (null).\n */\n\nexport interface Cron {\n minutes: ReadonlySet<number>;\n hours: ReadonlySet<number>;\n /** Day of the month, 1–31. */\n days: ReadonlySet<number>;\n /** 1–12. */\n months: ReadonlySet<number>;\n /** 0–6, Sunday 0. */\n weekdays: ReadonlySet<number>;\n /** Left open (`*`): cron's rule for days reads which of the two narrows them. */\n anyDay: boolean;\n anyWeekday: boolean;\n}\n\ninterface Field {\n min: number;\n max: number;\n names?: readonly string[];\n}\n\nconst MONTH_NAMES = [\n \"jan\",\n \"feb\",\n \"mar\",\n \"apr\",\n \"may\",\n \"jun\",\n \"jul\",\n \"aug\",\n \"sep\",\n \"oct\",\n \"nov\",\n \"dec\",\n] as const;\nconst WEEKDAY_NAMES = [\"sun\", \"mon\", \"tue\", \"wed\", \"thu\", \"fri\", \"sat\"] as const;\n\nconst FIELDS: readonly Field[] = [\n { min: 0, max: 59 },\n { min: 0, max: 23 },\n { min: 1, max: 31 },\n { min: 1, max: 12, names: MONTH_NAMES },\n { min: 0, max: 7, names: WEEKDAY_NAMES },\n];\n\n/** One value of a field: a number in its bounds, or one of its names (`mon`, `jan`). */\nfunction valueOf(text: string, field: Field): number | null {\n const named = field.names?.indexOf(text.toLowerCase()) ?? -1;\n if (named >= 0) return named + field.min;\n if (!/^\\d+$/.test(text)) return null;\n const value = Number(text);\n return value >= field.min && value <= field.max ? value : null;\n}\n\n/** A field's values: `*`, `5`, `1-5`, `*` every 15, `8-18` every 2, `mon-fri`, and lists of them. */\nfunction parseField(text: string, field: Field): number[] | null {\n const values = new Set<number>();\n for (const part of text.split(\",\")) {\n const [range = \"\", stepText] = part.split(\"/\");\n const step = stepText === undefined ? 1 : Number(stepText);\n if (!Number.isInteger(step) || step < 1) return null;\n let from: number | null;\n let to: number | null;\n if (range === \"*\") {\n [from, to] = [field.min, field.max];\n } else {\n const [first = \"\", last] = range.split(\"-\");\n from = valueOf(first, field);\n // \"8/2\" runs from 8 to the end of the field, as cron reads it.\n to = last !== undefined ? valueOf(last, field) : stepText !== undefined ? field.max : from;\n }\n if (from === null || to === null || from > to) return null;\n for (let value = from; value <= to; value += step) values.add(value);\n }\n return [...values];\n}\n\n/** A cron line of five fields, or null when it is anything else. */\nexport function parseCron(line: string): Cron | null {\n const texts = line.trim().split(/\\s+/);\n if (texts.length !== 5) return null;\n const [minutes, hours, days, months, weekdays] = texts.map((text, at) => {\n const field = FIELDS[at];\n return field ? parseField(text, field) : null;\n });\n if (!minutes || !hours || !days || !months || !weekdays) return null;\n return {\n minutes: new Set(minutes),\n hours: new Set(hours),\n days: new Set(days),\n months: new Set(months),\n // 7 is Sunday too.\n weekdays: new Set(weekdays.map((day) => day % 7)),\n anyDay: texts[2]?.startsWith(\"*\") ?? false,\n anyWeekday: texts[4]?.startsWith(\"*\") ?? false,\n };\n}\n\n/** A moment as a zone's clock reads it. */\nexport interface Wall {\n minute: number;\n hour: number;\n day: number;\n month: number;\n weekday: number;\n}\n\n/**\n * Whether the line fires at that minute. Days follow cron's rule: when both the day of the month\n * and the day of the week are narrowed, either one is enough.\n */\nexport function fires(cron: Cron, at: Wall): boolean {\n if (!cron.minutes.has(at.minute) || !cron.hours.has(at.hour) || !cron.months.has(at.month)) {\n return false;\n }\n const day = cron.days.has(at.day);\n const weekday = cron.weekdays.has(at.weekday);\n if (cron.anyDay && cron.anyWeekday) return true;\n if (cron.anyDay) return weekday;\n if (cron.anyWeekday) return day;\n return day || weekday;\n}\n\nconst MINUTE = 60_000;\n/** How often the zone's offset is read again: a quarter of an hour meets every zone's changes. */\nconst QUARTER = 15 * MINUTE;\n\nconst clocks = new Map<string, Intl.DateTimeFormat>();\n\n/** The zone's clock, kept; an unknown zone reads as UTC, the API's default. */\nfunction clockOf(zone: string): Intl.DateTimeFormat {\n let clock = clocks.get(zone);\n if (!clock) {\n const options: Intl.DateTimeFormatOptions = {\n hourCycle: \"h23\",\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"numeric\",\n second: \"numeric\",\n };\n try {\n clock = new Intl.DateTimeFormat(\"en-US\", { ...options, timeZone: zone });\n } catch {\n clock = new Intl.DateTimeFormat(\"en-US\", { ...options, timeZone: \"UTC\" });\n }\n clocks.set(zone, clock);\n }\n return clock;\n}\n\n/** How far the zone's clock is ahead of UTC at a moment, in milliseconds. */\nexport function offsetOf(zone: string, at: Date): number {\n const parts = clockOf(zone).formatToParts(at);\n const part = (type: Intl.DateTimeFormatPartTypes) =>\n Number(parts.find((each) => each.type === type)?.value ?? 0);\n const wall = Date.UTC(\n part(\"year\"),\n part(\"month\") - 1,\n part(\"day\"),\n part(\"hour\") % 24,\n part(\"minute\"),\n part(\"second\"),\n );\n return wall - Math.floor(at.getTime() / 1000) * 1000;\n}\n\n/** Every moment in [from, to) the line fires at, read on the clock of `zone`. */\nexport function occurrences(cron: Cron, zone: string, from: Date, to: Date): Date[] {\n const out: Date[] = [];\n let quarter = Number.NaN;\n let offset = 0;\n for (let at = Math.ceil(from.getTime() / MINUTE) * MINUTE; at < to.getTime(); at += MINUTE) {\n if (Math.floor(at / QUARTER) !== quarter) {\n quarter = Math.floor(at / QUARTER);\n offset = offsetOf(zone, new Date(at));\n }\n const wall = new Date(at + offset);\n const fired = fires(cron, {\n minute: wall.getUTCMinutes(),\n hour: wall.getUTCHours(),\n day: wall.getUTCDate(),\n month: wall.getUTCMonth() + 1,\n weekday: wall.getUTCDay(),\n });\n if (fired) out.push(new Date(at));\n }\n return out;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"cron.js","names":[],"sources":["../../src/automation/cron.ts"],"sourcesContent":["/**\n * A schedule's cron line, read into what it fires at: the moments of a day (the agents' day, an\n * automation's next runs) and the sentence that says it (`whenOf`). Five fields (minute, hour,\n * day of the month, month, day of the week) with `*`, lists, ranges, steps and English names, as\n * the API's croniter reads them; anything past that is not read (null).\n */\n\nexport interface Cron {\n minutes: ReadonlySet<number>;\n hours: ReadonlySet<number>;\n /** Day of the month, 1–31. */\n days: ReadonlySet<number>;\n /** 1–12. */\n months: ReadonlySet<number>;\n /** 0–6, Sunday 0. */\n weekdays: ReadonlySet<number>;\n /** Left open (`*`): cron's rule for days reads which of the two narrows them. */\n anyDay: boolean;\n anyWeekday: boolean;\n}\n\ninterface Field {\n min: number;\n max: number;\n names?: readonly string[];\n}\n\nconst MONTH_NAMES = [\n \"jan\",\n \"feb\",\n \"mar\",\n \"apr\",\n \"may\",\n \"jun\",\n \"jul\",\n \"aug\",\n \"sep\",\n \"oct\",\n \"nov\",\n \"dec\",\n] as const;\nconst WEEKDAY_NAMES = [\"sun\", \"mon\", \"tue\", \"wed\", \"thu\", \"fri\", \"sat\"] as const;\n\nconst FIELDS: readonly Field[] = [\n { min: 0, max: 59 },\n { min: 0, max: 23 },\n { min: 1, max: 31 },\n { min: 1, max: 12, names: MONTH_NAMES },\n { min: 0, max: 7, names: WEEKDAY_NAMES },\n];\n\n/** One value of a field: a number in its bounds, or one of its names (`mon`, `jan`). */\nfunction valueOf(text: string, field: Field): number | null {\n const named = field.names?.indexOf(text.toLowerCase()) ?? -1;\n if (named >= 0) return named + field.min;\n if (!/^\\d+$/.test(text)) return null;\n const value = Number(text);\n return value >= field.min && value <= field.max ? value : null;\n}\n\n/** A field's values: `*`, `5`, `1-5`, `*` every 15, `8-18` every 2, `mon-fri`, and lists of them. */\nfunction parseField(text: string, field: Field): number[] | null {\n const values = new Set<number>();\n for (const part of text.split(\",\")) {\n const [range = \"\", stepText] = part.split(\"/\");\n const step = stepText === undefined ? 1 : Number(stepText);\n if (!Number.isInteger(step) || step < 1) return null;\n let from: number | null;\n let to: number | null;\n if (range === \"*\") {\n [from, to] = [field.min, field.max];\n } else {\n const [first = \"\", last] = range.split(\"-\");\n from = valueOf(first, field);\n // \"8/2\" runs from 8 to the end of the field, as cron reads it.\n to = last !== undefined ? valueOf(last, field) : stepText !== undefined ? field.max : from;\n }\n if (from === null || to === null || from > to) return null;\n for (let value = from; value <= to; value += step) values.add(value);\n }\n return [...values];\n}\n\n/** A cron line of five fields, or null when it is anything else. */\nexport function parseCron(line: string): Cron | null {\n const texts = line.trim().split(/\\s+/);\n if (texts.length !== 5) return null;\n const [minutes, hours, days, months, weekdays] = texts.map((text, at) => {\n const field = FIELDS[at];\n return field ? parseField(text, field) : null;\n });\n if (!minutes || !hours || !days || !months || !weekdays) return null;\n return {\n minutes: new Set(minutes),\n hours: new Set(hours),\n days: new Set(days),\n months: new Set(months),\n // 7 is Sunday too.\n weekdays: new Set(weekdays.map((day) => day % 7)),\n anyDay: texts[2]?.startsWith(\"*\") ?? false,\n anyWeekday: texts[4]?.startsWith(\"*\") ?? false,\n };\n}\n\n/** A moment as a zone's clock reads it. */\nexport interface Wall {\n minute: number;\n hour: number;\n day: number;\n month: number;\n weekday: number;\n}\n\n/**\n * Whether the line fires at that minute. Days follow cron's rule: when both the day of the month\n * and the day of the week are narrowed, either one is enough.\n */\nexport function fires(cron: Cron, at: Wall): boolean {\n if (!cron.minutes.has(at.minute) || !cron.hours.has(at.hour) || !cron.months.has(at.month)) {\n return false;\n }\n const day = cron.days.has(at.day);\n const weekday = cron.weekdays.has(at.weekday);\n if (cron.anyDay && cron.anyWeekday) return true;\n if (cron.anyDay) return weekday;\n if (cron.anyWeekday) return day;\n return day || weekday;\n}\n\nconst MINUTE = 60_000;\n/** How often the zone's offset is read again: a quarter of an hour meets every zone's changes. */\nconst QUARTER = 15 * MINUTE;\n\nconst clocks = new Map<string, Intl.DateTimeFormat>();\n\n/** The zone's clock, kept; an unknown zone reads as UTC, the API's default. */\nfunction clockOf(zone: string): Intl.DateTimeFormat {\n let clock = clocks.get(zone);\n if (!clock) {\n const options: Intl.DateTimeFormatOptions = {\n hourCycle: \"h23\",\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"numeric\",\n second: \"numeric\",\n };\n try {\n clock = new Intl.DateTimeFormat(\"en-US\", { ...options, timeZone: zone });\n } catch {\n clock = new Intl.DateTimeFormat(\"en-US\", { ...options, timeZone: \"UTC\" });\n }\n clocks.set(zone, clock);\n }\n return clock;\n}\n\n/** How far the zone's clock is ahead of UTC at a moment, in milliseconds. */\nexport function offsetOf(zone: string, at: Date): number {\n const parts = clockOf(zone).formatToParts(at);\n const part = (type: Intl.DateTimeFormatPartTypes) =>\n Number(parts.find((each) => each.type === type)?.value ?? 0);\n const wall = Date.UTC(\n part(\"year\"),\n part(\"month\") - 1,\n part(\"day\"),\n part(\"hour\") % 24,\n part(\"minute\"),\n part(\"second\"),\n );\n return wall - Math.floor(at.getTime() / 1000) * 1000;\n}\n\n/** Every moment in [from, to) the line fires at, read on the clock of `zone`. */\nexport function occurrences(cron: Cron, zone: string, from: Date, to: Date): Date[] {\n const out: Date[] = [];\n let quarter = Number.NaN;\n let offset = 0;\n for (let at = Math.ceil(from.getTime() / MINUTE) * MINUTE; at < to.getTime(); at += MINUTE) {\n if (Math.floor(at / QUARTER) !== quarter) {\n quarter = Math.floor(at / QUARTER);\n offset = offsetOf(zone, new Date(at));\n }\n const wall = new Date(at + offset);\n const fired = fires(cron, {\n minute: wall.getUTCMinutes(),\n hour: wall.getUTCHours(),\n day: wall.getUTCDate(),\n month: wall.getUTCMonth() + 1,\n weekday: wall.getUTCDay(),\n });\n if (fired) out.push(new Date(at));\n }\n return out;\n}\n"],"mappings":"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"}
@@ -27,9 +27,11 @@ function AppMark({ name, icon, size, apps }) {
27
27
  }
28
28
  const KINDS = {
29
29
  schedule: ClockIcon,
30
- webhook: WebhooksLogoIcon
30
+ webhook: WebhooksLogoIcon,
31
+ platform: ChatCircleIcon
31
32
  };
32
- /** What starts an automation, as a mark: a clock, a webhook, the app whose event it waits for. */
33
+ /** What starts an automation, as a mark: a clock, a webhook, a message, the app whose event it
34
+ * waits for. */
33
35
  function TriggerMark({ trigger, size, apps }) {
34
36
  if (trigger.kind !== "event") return /* @__PURE__ */ jsx(Mark, {
35
37
  icon: KINDS[trigger.kind],
@@ -47,10 +49,12 @@ function TriggerMark({ trigger, size, apps }) {
47
49
  apps
48
50
  });
49
51
  }
50
- /** What started a run: its time, a call, its app's event, a chat with the agent, a test. */
52
+ /** What started a run: its time, a call, its app's event, a message, a chat with the agent, a
53
+ * test. */
51
54
  const BY = {
52
55
  schedule: ClockIcon,
53
56
  webhook: WebhooksLogoIcon,
57
+ platform: ChatCircleIcon,
54
58
  agent: ChatCircleIcon,
55
59
  test: FlaskIcon
56
60
  };
@@ -1 +1 @@
1
- {"version":3,"file":"marks.js","names":[],"sources":["../../src/automation/marks.tsx"],"sourcesContent":["import {\n BellIcon,\n BrainIcon,\n ChatCircleIcon,\n ChatTextIcon,\n ChatsCircleIcon,\n ClockIcon,\n FileTextIcon,\n FlaskIcon,\n GlobeIcon,\n LightningIcon,\n SparkleIcon,\n TableIcon,\n WebhooksLogoIcon,\n type Icon,\n} from \"@phosphor-icons/react\";\nimport type { ReactNode } from \"react\";\n\nimport type { AppDirectory } from \"../AgentAbout\";\nimport { Mark } from \"../kit/Mark\";\nimport { sentOn } from \"./record\";\nimport type { RunBy, RunStep, Trigger, Use } from \"./types\";\n\n/** Only an https logo is loaded: never a script, never a local file. */\nconst https = (url: string | null): url is string => url !== null && /^https:\\/\\//i.test(url);\n\n/**\n * An app's mark: the host's logo when it draws apps (`apps`), else the logo the API gives, else\n * the app's initial; each bare, as `Mark` draws it.\n */\nexport function AppMark({\n name,\n icon,\n size,\n apps,\n}: {\n name: string;\n icon: string | null;\n size: number;\n apps: AppDirectory | undefined;\n}) {\n if (apps !== undefined) return <>{apps.logo({ provider: \"\", name, icon, size })}</>;\n if (https(icon)) return <Mark src={icon} size={size} />;\n return (\n <Mark size={size}>\n <span>{name.trim().charAt(0).toUpperCase() || \"?\"}</span>\n </Mark>\n );\n}\n\nconst KINDS: Readonly<Record<Exclude<Trigger[\"kind\"], \"event\">, Icon>> = {\n schedule: ClockIcon,\n webhook: WebhooksLogoIcon,\n};\n\n/** What starts an automation, as a mark: a clock, a webhook, the app whose event it waits for. */\nexport function TriggerMark({\n trigger,\n size,\n apps,\n}: {\n trigger: Trigger;\n size: number;\n apps: AppDirectory | undefined;\n}) {\n if (trigger.kind !== \"event\") return <Mark icon={KINDS[trigger.kind]} size={size} />;\n const name = trigger.app_title ?? trigger.app;\n if (name === null) return <Mark icon={LightningIcon} size={size} />;\n return <AppMark name={name} icon={trigger.icon} size={size} apps={apps} />;\n}\n\n/** What started a run: its time, a call, its app's event, a chat with the agent, a test. */\nconst BY: Readonly<Record<Exclude<RunBy, \"event\">, Icon>> = {\n schedule: ClockIcon,\n webhook: WebhooksLogoIcon,\n agent: ChatCircleIcon,\n test: FlaskIcon,\n};\n\nexport function ByMark({\n by,\n trigger,\n size,\n apps,\n}: {\n by: RunBy;\n /** The automation's, for an event's app; none, a plain mark. */\n trigger: Trigger | null;\n size: number;\n apps: AppDirectory | undefined;\n}) {\n if (by !== \"event\") return <Mark icon={BY[by]} size={size} />;\n return trigger === null ? (\n <Mark icon={LightningIcon} size={size} />\n ) : (\n <TriggerMark trigger={trigger} size={size} apps={apps} />\n );\n}\n\n/**\n * What a step uses, other than an app: the model, the agent, the inbox, a message on a channel, a\n * table, the web.\n */\nexport const USES: Readonly<Record<Exclude<Use[\"kind\"], \"app\">, Icon>> = {\n ai: SparkleIcon,\n agent: ChatsCircleIcon,\n notify: BellIcon,\n send: ChatTextIcon,\n data: TableIcon,\n http: GlobeIcon,\n};\n\n/** A call of a run's record, by what it reached; an app's tool by the app's mark. */\nconst CALLS: Readonly<Record<string, Icon>> = {\n ai: SparkleIcon,\n notify: BellIcon,\n send: ChatTextIcon,\n \"agent.start\": ChatsCircleIcon,\n \"data.find\": TableIcon,\n \"data.add\": TableIcon,\n \"data.update\": TableIcon,\n http: GlobeIcon,\n \"files.search\": FileTextIcon,\n \"files.read\": FileTextIcon,\n \"files.write\": FileTextIcon,\n \"files.list\": FileTextIcon,\n \"memory.remember\": BrainIcon,\n \"memory.recall\": BrainIcon,\n};\n\nexport function callMark(\n step: RunStep,\n app: { name: string; icon: string | null } | null,\n apps: AppDirectory | undefined,\n size: number,\n): ReactNode {\n if (app !== null) return <AppMark name={app.name} icon={app.icon} size={size} apps={apps} />;\n // A message sent on a channel: the channel's brand, when the host draws brands and it is known.\n const channel = step.call === \"send\" ? sentOn(step) : null;\n if (channel !== null && apps !== undefined) {\n return apps.logo({ provider: channel, name: channel, size });\n }\n return <Mark icon={CALLS[step.call] ?? LightningIcon} size={size} />;\n}\n"],"mappings":";;;;;;AAwBA,MAAM,SAAS,QAAsC,QAAQ,QAAQ,eAAe,KAAK,GAAG;;;;;AAM5F,SAAgB,QAAQ,EACtB,MACA,MACA,MACA,QAMC;CACD,IAAI,SAAS,KAAA,GAAW,OAAO,oBAAA,UAAA,EAAA,UAAG,KAAK,KAAK;EAAE,UAAU;EAAI;EAAM;EAAM;CAAK,CAAC,EAAI,CAAA;CAClF,IAAI,MAAM,IAAI,GAAG,OAAO,oBAAC,MAAD;EAAM,KAAK;EAAY;CAAO,CAAA;CACtD,OACE,oBAAC,MAAD;EAAY;EACV,UAAA,oBAAC,QAAD,EAAA,UAAO,KAAK,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,KAAK,IAAU,CAAA;CACpD,CAAA;AAEV;AAEA,MAAM,QAAmE;CACvE,UAAU;CACV,SAAS;AACX;;AAGA,SAAgB,YAAY,EAC1B,SACA,MACA,QAKC;CACD,IAAI,QAAQ,SAAS,SAAS,OAAO,oBAAC,MAAD;EAAM,MAAM,MAAM,QAAQ;EAAa;CAAO,CAAA;CACnF,MAAM,OAAO,QAAQ,aAAa,QAAQ;CAC1C,IAAI,SAAS,MAAM,OAAO,oBAAC,MAAD;EAAM,MAAM;EAAqB;CAAO,CAAA;CAClE,OAAO,oBAAC,SAAD;EAAe;EAAM,MAAM,QAAQ;EAAY;EAAY;CAAO,CAAA;AAC3E;;AAGA,MAAM,KAAsD;CAC1D,UAAU;CACV,SAAS;CACT,OAAO;CACP,MAAM;AACR;AAEA,SAAgB,OAAO,EACrB,IACA,SACA,MACA,QAOC;CACD,IAAI,OAAO,SAAS,OAAO,oBAAC,MAAD;EAAM,MAAM,GAAG;EAAW;CAAO,CAAA;CAC5D,OAAO,YAAY,OACjB,oBAAC,MAAD;EAAM,MAAM;EAAqB;CAAO,CAAA,IAExC,oBAAC,aAAD;EAAsB;EAAe;EAAY;CAAO,CAAA;AAE5D;;;;;AAMA,MAAa,OAA4D;CACvE,IAAI;CACJ,OAAO;CACP,QAAQ;CACR,MAAM;CACN,MAAM;CACN,MAAM;AACR;;AAGA,MAAM,QAAwC;CAC5C,IAAI;CACJ,QAAQ;CACR,MAAM;CACN,eAAe;CACf,aAAa;CACb,YAAY;CACZ,eAAe;CACf,MAAM;CACN,gBAAgB;CAChB,cAAc;CACd,eAAe;CACf,cAAc;CACd,mBAAmB;CACnB,iBAAiB;AACnB;AAEA,SAAgB,SACd,MACA,KACA,MACA,MACW;CACX,IAAI,QAAQ,MAAM,OAAO,oBAAC,SAAD;EAAS,MAAM,IAAI;EAAM,MAAM,IAAI;EAAY;EAAY;CAAO,CAAA;CAE3F,MAAM,UAAU,KAAK,SAAS,SAAS,OAAO,IAAI,IAAI;CACtD,IAAI,YAAY,QAAQ,SAAS,KAAA,GAC/B,OAAO,KAAK,KAAK;EAAE,UAAU;EAAS,MAAM;EAAS;CAAK,CAAC;CAE7D,OAAO,oBAAC,MAAD;EAAM,MAAM,MAAM,KAAK,SAAS;EAAqB;CAAO,CAAA;AACrE"}
1
+ {"version":3,"file":"marks.js","names":[],"sources":["../../src/automation/marks.tsx"],"sourcesContent":["import {\n BellIcon,\n BrainIcon,\n ChatCircleIcon,\n ChatTextIcon,\n ChatsCircleIcon,\n ClockIcon,\n FileTextIcon,\n FlaskIcon,\n GlobeIcon,\n LightningIcon,\n SparkleIcon,\n TableIcon,\n WebhooksLogoIcon,\n type Icon,\n} from \"@phosphor-icons/react\";\nimport type { ReactNode } from \"react\";\n\nimport type { AppDirectory } from \"../AgentAbout\";\nimport { Mark } from \"../kit/Mark\";\nimport { sentOn } from \"./record\";\nimport type { RunBy, RunStep, Trigger, Use } from \"./types\";\n\n/** Only an https logo is loaded: never a script, never a local file. */\nconst https = (url: string | null): url is string => url !== null && /^https:\\/\\//i.test(url);\n\n/**\n * An app's mark: the host's logo when it draws apps (`apps`), else the logo the API gives, else\n * the app's initial; each bare, as `Mark` draws it.\n */\nexport function AppMark({\n name,\n icon,\n size,\n apps,\n}: {\n name: string;\n icon: string | null;\n size: number;\n apps: AppDirectory | undefined;\n}) {\n if (apps !== undefined) return <>{apps.logo({ provider: \"\", name, icon, size })}</>;\n if (https(icon)) return <Mark src={icon} size={size} />;\n return (\n <Mark size={size}>\n <span>{name.trim().charAt(0).toUpperCase() || \"?\"}</span>\n </Mark>\n );\n}\n\nconst KINDS: Readonly<Record<Exclude<Trigger[\"kind\"], \"event\">, Icon>> = {\n schedule: ClockIcon,\n webhook: WebhooksLogoIcon,\n platform: ChatCircleIcon,\n};\n\n/** What starts an automation, as a mark: a clock, a webhook, a message, the app whose event it\n * waits for. */\nexport function TriggerMark({\n trigger,\n size,\n apps,\n}: {\n trigger: Trigger;\n size: number;\n apps: AppDirectory | undefined;\n}) {\n if (trigger.kind !== \"event\") return <Mark icon={KINDS[trigger.kind]} size={size} />;\n const name = trigger.app_title ?? trigger.app;\n if (name === null) return <Mark icon={LightningIcon} size={size} />;\n return <AppMark name={name} icon={trigger.icon} size={size} apps={apps} />;\n}\n\n/** What started a run: its time, a call, its app's event, a message, a chat with the agent, a\n * test. */\nconst BY: Readonly<Record<Exclude<RunBy, \"event\">, Icon>> = {\n schedule: ClockIcon,\n webhook: WebhooksLogoIcon,\n platform: ChatCircleIcon,\n agent: ChatCircleIcon,\n test: FlaskIcon,\n};\n\nexport function ByMark({\n by,\n trigger,\n size,\n apps,\n}: {\n by: RunBy;\n /** The automation's, for an event's app; none, a plain mark. */\n trigger: Trigger | null;\n size: number;\n apps: AppDirectory | undefined;\n}) {\n if (by !== \"event\") return <Mark icon={BY[by]} size={size} />;\n return trigger === null ? (\n <Mark icon={LightningIcon} size={size} />\n ) : (\n <TriggerMark trigger={trigger} size={size} apps={apps} />\n );\n}\n\n/**\n * What a step uses, other than an app: the model, the agent, the inbox, a message on a channel, a\n * table, the web.\n */\nexport const USES: Readonly<Record<Exclude<Use[\"kind\"], \"app\">, Icon>> = {\n ai: SparkleIcon,\n agent: ChatsCircleIcon,\n notify: BellIcon,\n send: ChatTextIcon,\n data: TableIcon,\n http: GlobeIcon,\n};\n\n/** A call of a run's record, by what it reached; an app's tool by the app's mark. */\nconst CALLS: Readonly<Record<string, Icon>> = {\n ai: SparkleIcon,\n notify: BellIcon,\n send: ChatTextIcon,\n \"agent.start\": ChatsCircleIcon,\n \"data.find\": TableIcon,\n \"data.add\": TableIcon,\n \"data.update\": TableIcon,\n http: GlobeIcon,\n \"files.search\": FileTextIcon,\n \"files.read\": FileTextIcon,\n \"files.write\": FileTextIcon,\n \"files.list\": FileTextIcon,\n \"memory.remember\": BrainIcon,\n \"memory.recall\": BrainIcon,\n};\n\nexport function callMark(\n step: RunStep,\n app: { name: string; icon: string | null } | null,\n apps: AppDirectory | undefined,\n size: number,\n): ReactNode {\n if (app !== null) return <AppMark name={app.name} icon={app.icon} size={size} apps={apps} />;\n // A message sent on a channel: the channel's brand, when the host draws brands and it is known.\n const channel = step.call === \"send\" ? sentOn(step) : null;\n if (channel !== null && apps !== undefined) {\n return apps.logo({ provider: channel, name: channel, size });\n }\n return <Mark icon={CALLS[step.call] ?? LightningIcon} size={size} />;\n}\n"],"mappings":";;;;;;AAwBA,MAAM,SAAS,QAAsC,QAAQ,QAAQ,eAAe,KAAK,GAAG;;;;;AAM5F,SAAgB,QAAQ,EACtB,MACA,MACA,MACA,QAMC;CACD,IAAI,SAAS,KAAA,GAAW,OAAO,oBAAA,UAAA,EAAA,UAAG,KAAK,KAAK;EAAE,UAAU;EAAI;EAAM;EAAM;CAAK,CAAC,EAAI,CAAA;CAClF,IAAI,MAAM,IAAI,GAAG,OAAO,oBAAC,MAAD;EAAM,KAAK;EAAY;CAAO,CAAA;CACtD,OACE,oBAAC,MAAD;EAAY;EACV,UAAA,oBAAC,QAAD,EAAA,UAAO,KAAK,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,KAAK,IAAU,CAAA;CACpD,CAAA;AAEV;AAEA,MAAM,QAAmE;CACvE,UAAU;CACV,SAAS;CACT,UAAU;AACZ;;;AAIA,SAAgB,YAAY,EAC1B,SACA,MACA,QAKC;CACD,IAAI,QAAQ,SAAS,SAAS,OAAO,oBAAC,MAAD;EAAM,MAAM,MAAM,QAAQ;EAAa;CAAO,CAAA;CACnF,MAAM,OAAO,QAAQ,aAAa,QAAQ;CAC1C,IAAI,SAAS,MAAM,OAAO,oBAAC,MAAD;EAAM,MAAM;EAAqB;CAAO,CAAA;CAClE,OAAO,oBAAC,SAAD;EAAe;EAAM,MAAM,QAAQ;EAAY;EAAY;CAAO,CAAA;AAC3E;;;AAIA,MAAM,KAAsD;CAC1D,UAAU;CACV,SAAS;CACT,UAAU;CACV,OAAO;CACP,MAAM;AACR;AAEA,SAAgB,OAAO,EACrB,IACA,SACA,MACA,QAOC;CACD,IAAI,OAAO,SAAS,OAAO,oBAAC,MAAD;EAAM,MAAM,GAAG;EAAW;CAAO,CAAA;CAC5D,OAAO,YAAY,OACjB,oBAAC,MAAD;EAAM,MAAM;EAAqB;CAAO,CAAA,IAExC,oBAAC,aAAD;EAAsB;EAAe;EAAY;CAAO,CAAA;AAE5D;;;;;AAMA,MAAa,OAA4D;CACvE,IAAI;CACJ,OAAO;CACP,QAAQ;CACR,MAAM;CACN,MAAM;CACN,MAAM;AACR;;AAGA,MAAM,QAAwC;CAC5C,IAAI;CACJ,QAAQ;CACR,MAAM;CACN,eAAe;CACf,aAAa;CACb,YAAY;CACZ,eAAe;CACf,MAAM;CACN,gBAAgB;CAChB,cAAc;CACd,eAAe;CACf,cAAc;CACd,mBAAmB;CACnB,iBAAiB;AACnB;AAEA,SAAgB,SACd,MACA,KACA,MACA,MACW;CACX,IAAI,QAAQ,MAAM,OAAO,oBAAC,SAAD;EAAS,MAAM,IAAI;EAAM,MAAM,IAAI;EAAY;EAAY;CAAO,CAAA;CAE3F,MAAM,UAAU,KAAK,SAAS,SAAS,OAAO,IAAI,IAAI;CACtD,IAAI,YAAY,QAAQ,SAAS,KAAA,GAC/B,OAAO,KAAK,KAAK;EAAE,UAAU;EAAS,MAAM;EAAS;CAAK,CAAC;CAE7D,OAAO,oBAAC,MAAD;EAAM,MAAM,MAAM,KAAK,SAAS;EAAqB;CAAO,CAAA;AACrE"}
@@ -67,6 +67,8 @@ export interface AutomationMessages {
67
67
  /** What another kind of trigger waits for. */
68
68
  webhook: string;
69
69
  event: (app: string | null, event: string | null) => string;
70
+ /** One of the platform's events: a contact's message stored on a channel. */
71
+ platform: string;
70
72
  /** When it runs next, after when it runs: the day, and the time when the line doesn't say it. */
71
73
  next: (day: DayRef, time: string | null) => string;
72
74
  /** How it stands, on its pill. */
@@ -13,6 +13,7 @@ const AUTOMATION_MESSAGES = {
13
13
  on: (often, days) => `${often}, ${days.charAt(0).toLowerCase()}${days.slice(1)}`,
14
14
  custom: "On a schedule of its own",
15
15
  webhook: "When another system calls it",
16
+ platform: "When a message arrives",
16
17
  event: (app, event) => event ? `When ${event} in ${app ?? "an app"}` : `On an event in ${app ?? "an app"}`,
17
18
  next: (day, time) => {
18
19
  const at = time === null ? "" : ` at ${time}`;
@@ -54,6 +55,7 @@ const AUTOMATION_MESSAGES = {
54
55
  schedule: "scheduled",
55
56
  webhook: "webhook",
56
57
  event: app ? `${app} event` : "event",
58
+ platform: "a message",
57
59
  agent: "you asked in the chat",
58
60
  test: "test"
59
61
  })[by],
@@ -1 +1 @@
1
- {"version":3,"file":"messages.js","names":[],"sources":["../../src/automation/messages.ts"],"sourcesContent":["import type { AutomationState, RunBy, RunStatus, Use } from \"./types\";\n\n/**\n * A day as a person says it beside a time: today, yesterday, tomorrow, a weekday within the\n * week (`name` as the locale names it, short or long), or a date further away.\n */\nexport type DayRef =\n { kind: \"today\" | \"yesterday\" | \"tomorrow\" } | { kind: \"weekday\" | \"date\"; name: string };\n\n/** A tool's call by what it does, read from its name: what a run's record says it did. */\nexport type Verb = \"search\" | \"send\" | \"create\" | \"update\" | \"remove\" | \"use\";\n\n/** What a run did, call by call, in words; `would` is a test's write, recorded and not done. */\nexport interface CallMessages {\n /** An app's tool, by what its name says it does, with the app's name. */\n tool: (verb: Verb, app: string, would: boolean) => string;\n /** One model call: it reads and writes for real in a test too. */\n ai: string;\n /** A line in the owner's inbox. */\n notify: (would: boolean) => string;\n /**\n * A message to a contact on one of the agent's channels: the channel's kind when the record\n * says it (`whatsapp`, `instagram`, `sms`), and who to (a number; \"\" for a contact by its id).\n */\n send: (channel: string | null, to: string, would: boolean) => string;\n /** A conversation of the agent opened for what needs judgement or a person. */\n start: (would: boolean) => string;\n /** A table's rows looked up, added, changed, by the table's title. */\n find: (table: string) => string;\n add: (table: string, would: boolean) => string;\n change: (table: string, would: boolean) => string;\n /** A call to another system, by its host. */\n http: (host: string, would: boolean) => string;\n /** The organization's files searched. */\n files: string;\n /** One of its files read, kept, or its files listed, by the file's name. */\n read: (file: string) => string;\n wrote: (file: string, would: boolean) => string;\n listed: string;\n /** A line kept in, and one looked up from, what the agent learned. */\n remember: (would: boolean) => string;\n recall: string;\n}\n\n/** The words of an automation and its runs: the trigger in words, its state, its runs. */\nexport interface AutomationMessages {\n /** When it runs, from its cron line (`whenOf`): the days, then the times. */\n daily: string;\n /** Monday to Friday. */\n weekdays: string;\n /** Saturday and Sunday. */\n weekends: string;\n /** Some days of the week, by their names. */\n weekly: (days: string[]) => string;\n /** Some days of the month. */\n monthly: (days: number[]) => string;\n /** The times it runs at, after the days (\"9:00\", as the locale writes it). */\n at: (times: string[]) => string;\n /** Every few minutes or hours, all day or `between` two times. */\n every: (count: number, unit: \"minute\" | \"hour\") => string;\n between: (from: string, to: string) => string;\n /** A frequency on some days only: \"every 15 minutes\" and \"on weekdays\". */\n on: (often: string, days: string) => string;\n /** A schedule the sentence can't say. */\n custom: string;\n /** What another kind of trigger waits for. */\n webhook: string;\n event: (app: string | null, event: string | null) => string;\n /** When it runs next, after when it runs: the day, and the time when the line doesn't say it. */\n next: (day: DayRef, time: string | null) => string;\n /** How it stands, on its pill. */\n states: Readonly<Record<AutomationState, string>>;\n /** Its switch, for screen readers. */\n switchLabel: string;\n /** Over its steps, the table it moves, its runs. */\n steps: string;\n runs: string;\n /** In the place of its runs, when there are none yet. */\n noRuns: string;\n /** What a step uses, other than an app (which goes by its name). */\n uses: Readonly<Record<Exclude<Use[\"kind\"], \"app\">, string>>;\n /** The values of the table past the ones shown: \"+3\". */\n more: (count: number) => string;\n /** An automation the agent named that is not there (removed, renamed). */\n gone: string;\n /** When a run started, beside what started it. */\n moment: (day: DayRef, time: string) => string;\n /** What started a run; an event's by its app's name, when known. */\n by: (by: RunBy, app: string | null) => string;\n /** How a run stands. */\n statuses: Readonly<Record<RunStatus, string>>;\n /** A test's line: what the run returned, though it changed nothing. */\n dry: (summary: string) => string;\n /** How long a run took. */\n took: (ms: number) => string;\n /** Over the conversations a run opened, and each one's link. */\n opened: string;\n conversation: (index: number) => string;\n /** The conversation the agent was asked in, for a run it started. */\n askedIn: string;\n /** A run that called nothing. */\n noCalls: string;\n /** Over the calls made outside any step. */\n outside: string;\n /** A call made several times in a row: \"×12\". */\n times: (count: number) => string;\n calls: CallMessages;\n}\n\nconst plural = (count: number, one: string, many: string) =>\n count === 1 ? one : `${count} ${many}`;\n\n/** English: what the package says until a host gives its own words. */\nexport const AUTOMATION_MESSAGES: AutomationMessages = {\n daily: \"Every day\",\n weekdays: \"Every weekday\",\n weekends: \"Every weekend\",\n weekly: (days) =>\n days.length === 1 ? `Every ${days[0] ?? \"\"}` : `On ${new Intl.ListFormat(\"en\").format(days)}`,\n monthly: (days) => `On day ${new Intl.ListFormat(\"en\").format(days.map(String))} of every month`,\n at: (times) => `at ${new Intl.ListFormat(\"en\").format(times)}`,\n every: (count, unit) => `Every ${plural(count, unit, `${unit}s`)}`,\n between: (from, to) => `from ${from} to ${to}`,\n on: (often, days) => `${often}, ${days.charAt(0).toLowerCase()}${days.slice(1)}`,\n custom: \"On a schedule of its own\",\n webhook: \"When another system calls it\",\n event: (app, event) =>\n event ? `When ${event} in ${app ?? \"an app\"}` : `On an event in ${app ?? \"an app\"}`,\n next: (day, time) => {\n const at = time === null ? \"\" : ` at ${time}`;\n switch (day.kind) {\n case \"today\":\n return `next today${at}`;\n case \"tomorrow\":\n return `next tomorrow${at}`;\n case \"yesterday\":\n return `next${at}`;\n default:\n return `next on ${day.name}${at}`;\n }\n },\n states: { active: \"On\", paused: \"Paused\", failing: \"Last run failed\" },\n switchLabel: \"On\",\n steps: \"Steps\",\n runs: \"Runs\",\n noRuns: \"It hasn't run yet.\",\n uses: {\n ai: \"AI\",\n agent: \"Agent\",\n notify: \"Inbox\",\n send: \"Message\",\n data: \"Table\",\n http: \"Web\",\n },\n more: (count) => `+${count}`,\n gone: \"This automation is no longer there.\",\n moment: (day, time) => {\n switch (day.kind) {\n case \"today\":\n return `Today ${time}`;\n case \"yesterday\":\n return `Yesterday ${time}`;\n case \"tomorrow\":\n return `Tomorrow ${time}`;\n default:\n return `${day.name} ${time}`;\n }\n },\n by: (by, app) =>\n ({\n schedule: \"scheduled\",\n webhook: \"webhook\",\n event: app ? `${app} event` : \"event\",\n agent: \"you asked in the chat\",\n test: \"test\",\n })[by],\n statuses: {\n running: \"Running\",\n waiting: \"Waiting\",\n done: \"Done\",\n failed: \"Failed\",\n skipped: \"Skipped\",\n },\n dry: (summary) => `Test: ${summary}`,\n took: (ms) =>\n ms < 60_000 ? `${Math.max(1, Math.round(ms / 1000))} s` : `${Math.round(ms / 60_000)} min`,\n opened: \"Conversations it opened\",\n conversation: (index) => `Conversation ${index}`,\n askedIn: \"The conversation you asked in\",\n noCalls: \"It didn't call anything.\",\n outside: \"Outside the steps\",\n times: (count) => `×${count}`,\n calls: {\n tool: (verb, app, would) => {\n const done = {\n search: `Searched ${app}`,\n send: `Sent with ${app}`,\n create: `Created in ${app}`,\n update: `Changed in ${app}`,\n remove: `Removed in ${app}`,\n use: `Used ${app}`,\n }[verb];\n return would && verb !== \"search\"\n ? `Would have ${done.charAt(0).toLowerCase()}${done.slice(1)}`\n : done;\n },\n ai: \"Used AI\",\n notify: (would) => (would ? \"Would have told you in the inbox\" : \"Told you in the inbox\"),\n send: (channel, to, would) => {\n const what =\n { whatsapp: \"a WhatsApp\", sms: \"an SMS\", instagram: \"an Instagram message\" }[\n channel ?? \"\"\n ] ?? \"a message\";\n const sent = `${what} to ${to || \"a contact\"}`;\n return would ? `Would have sent ${sent}` : `Sent ${sent}`;\n },\n start: (would) => (would ? \"Would have opened a conversation\" : \"Opened a conversation\"),\n find: (table) => `Looked up ${table}`,\n add: (table, would) =>\n would ? `Would have added a row to ${table}` : `Added a row to ${table}`,\n change: (table, would) =>\n would ? `Would have changed a row of ${table}` : `Changed a row of ${table}`,\n http: (host, would) => (would ? `Would have called ${host}` : `Called ${host}`),\n files: \"Searched the files\",\n read: (file) => `Read ${file}`,\n wrote: (file, would) => (would ? `Would have saved ${file}` : `Saved ${file}`),\n listed: \"Looked through its files\",\n remember: (would) => (would ? \"Would have kept a memory\" : \"Kept a memory\"),\n recall: \"Searched what it learned\",\n },\n};\n"],"mappings":";AA6GA,MAAM,UAAU,OAAe,KAAa,SAC1C,UAAU,IAAI,MAAM,GAAG,MAAM,GAAG;;AAGlC,MAAa,sBAA0C;CACrD,OAAO;CACP,UAAU;CACV,UAAU;CACV,SAAS,SACP,KAAK,WAAW,IAAI,SAAS,KAAK,MAAM,OAAO,MAAM,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,OAAO,IAAI;CAC5F,UAAU,SAAS,UAAU,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI,MAAM,CAAC,EAAE;CAChF,KAAK,UAAU,MAAM,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,OAAO,KAAK;CAC3D,QAAQ,OAAO,SAAS,SAAS,OAAO,OAAO,MAAM,GAAG,KAAK,EAAE;CAC/D,UAAU,MAAM,OAAO,QAAQ,KAAK,MAAM;CAC1C,KAAK,OAAO,SAAS,GAAG,MAAM,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,KAAK,MAAM,CAAC;CAC7E,QAAQ;CACR,SAAS;CACT,QAAQ,KAAK,UACX,QAAQ,QAAQ,MAAM,MAAM,OAAO,aAAa,kBAAkB,OAAO;CAC3E,OAAO,KAAK,SAAS;EACnB,MAAM,KAAK,SAAS,OAAO,KAAK,OAAO;EACvC,QAAQ,IAAI,MAAZ;GACE,KAAK,SACH,OAAO,aAAa;GACtB,KAAK,YACH,OAAO,gBAAgB;GACzB,KAAK,aACH,OAAO,OAAO;GAChB,SACE,OAAO,WAAW,IAAI,OAAO;EACjC;CACF;CACA,QAAQ;EAAE,QAAQ;EAAM,QAAQ;EAAU,SAAS;CAAkB;CACrE,aAAa;CACb,OAAO;CACP,MAAM;CACN,QAAQ;CACR,MAAM;EACJ,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,MAAM;EACN,MAAM;EACN,MAAM;CACR;CACA,OAAO,UAAU,IAAI;CACrB,MAAM;CACN,SAAS,KAAK,SAAS;EACrB,QAAQ,IAAI,MAAZ;GACE,KAAK,SACH,OAAO,SAAS;GAClB,KAAK,aACH,OAAO,aAAa;GACtB,KAAK,YACH,OAAO,YAAY;GACrB,SACE,OAAO,GAAG,IAAI,KAAK,GAAG;EAC1B;CACF;CACA,KAAK,IAAI,SACN;EACC,UAAU;EACV,SAAS;EACT,OAAO,MAAM,GAAG,IAAI,UAAU;EAC9B,OAAO;EACP,MAAM;CACR,EAAA,CAAG;CACL,UAAU;EACR,SAAS;EACT,SAAS;EACT,MAAM;EACN,QAAQ;EACR,SAAS;CACX;CACA,MAAM,YAAY,SAAS;CAC3B,OAAO,OACL,KAAK,MAAS,GAAG,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,GAAI,CAAC,EAAE,MAAM,GAAG,KAAK,MAAM,KAAK,GAAM,EAAE;CACvF,QAAQ;CACR,eAAe,UAAU,gBAAgB;CACzC,SAAS;CACT,SAAS;CACT,SAAS;CACT,QAAQ,UAAU,IAAI;CACtB,OAAO;EACL,OAAO,MAAM,KAAK,UAAU;GAC1B,MAAM,OAAO;IACX,QAAQ,YAAY;IACpB,MAAM,aAAa;IACnB,QAAQ,cAAc;IACtB,QAAQ,cAAc;IACtB,QAAQ,cAAc;IACtB,KAAK,QAAQ;GACf,EAAE;GACF,OAAO,SAAS,SAAS,WACrB,cAAc,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,KAAK,MAAM,CAAC,MACzD;EACN;EACA,IAAI;EACJ,SAAS,UAAW,QAAQ,qCAAqC;EACjE,OAAO,SAAS,IAAI,UAAU;GAK5B,MAAM,OAAO,GAHX;IAAE,UAAU;IAAc,KAAK;IAAU,WAAW;GAAuB,EACzE,WAAW,OACR,YACc,MAAM,MAAM;GACjC,OAAO,QAAQ,mBAAmB,SAAS,QAAQ;EACrD;EACA,QAAQ,UAAW,QAAQ,qCAAqC;EAChE,OAAO,UAAU,aAAa;EAC9B,MAAM,OAAO,UACX,QAAQ,6BAA6B,UAAU,kBAAkB;EACnE,SAAS,OAAO,UACd,QAAQ,+BAA+B,UAAU,oBAAoB;EACvE,OAAO,MAAM,UAAW,QAAQ,qBAAqB,SAAS,UAAU;EACxE,OAAO;EACP,OAAO,SAAS,QAAQ;EACxB,QAAQ,MAAM,UAAW,QAAQ,oBAAoB,SAAS,SAAS;EACvE,QAAQ;EACR,WAAW,UAAW,QAAQ,6BAA6B;EAC3D,QAAQ;CACV;AACF"}
1
+ {"version":3,"file":"messages.js","names":[],"sources":["../../src/automation/messages.ts"],"sourcesContent":["import type { AutomationState, RunBy, RunStatus, Use } from \"./types\";\n\n/**\n * A day as a person says it beside a time: today, yesterday, tomorrow, a weekday within the\n * week (`name` as the locale names it, short or long), or a date further away.\n */\nexport type DayRef =\n { kind: \"today\" | \"yesterday\" | \"tomorrow\" } | { kind: \"weekday\" | \"date\"; name: string };\n\n/** A tool's call by what it does, read from its name: what a run's record says it did. */\nexport type Verb = \"search\" | \"send\" | \"create\" | \"update\" | \"remove\" | \"use\";\n\n/** What a run did, call by call, in words; `would` is a test's write, recorded and not done. */\nexport interface CallMessages {\n /** An app's tool, by what its name says it does, with the app's name. */\n tool: (verb: Verb, app: string, would: boolean) => string;\n /** One model call: it reads and writes for real in a test too. */\n ai: string;\n /** A line in the owner's inbox. */\n notify: (would: boolean) => string;\n /**\n * A message to a contact on one of the agent's channels: the channel's kind when the record\n * says it (`whatsapp`, `instagram`, `sms`), and who to (a number; \"\" for a contact by its id).\n */\n send: (channel: string | null, to: string, would: boolean) => string;\n /** A conversation of the agent opened for what needs judgement or a person. */\n start: (would: boolean) => string;\n /** A table's rows looked up, added, changed, by the table's title. */\n find: (table: string) => string;\n add: (table: string, would: boolean) => string;\n change: (table: string, would: boolean) => string;\n /** A call to another system, by its host. */\n http: (host: string, would: boolean) => string;\n /** The organization's files searched. */\n files: string;\n /** One of its files read, kept, or its files listed, by the file's name. */\n read: (file: string) => string;\n wrote: (file: string, would: boolean) => string;\n listed: string;\n /** A line kept in, and one looked up from, what the agent learned. */\n remember: (would: boolean) => string;\n recall: string;\n}\n\n/** The words of an automation and its runs: the trigger in words, its state, its runs. */\nexport interface AutomationMessages {\n /** When it runs, from its cron line (`whenOf`): the days, then the times. */\n daily: string;\n /** Monday to Friday. */\n weekdays: string;\n /** Saturday and Sunday. */\n weekends: string;\n /** Some days of the week, by their names. */\n weekly: (days: string[]) => string;\n /** Some days of the month. */\n monthly: (days: number[]) => string;\n /** The times it runs at, after the days (\"9:00\", as the locale writes it). */\n at: (times: string[]) => string;\n /** Every few minutes or hours, all day or `between` two times. */\n every: (count: number, unit: \"minute\" | \"hour\") => string;\n between: (from: string, to: string) => string;\n /** A frequency on some days only: \"every 15 minutes\" and \"on weekdays\". */\n on: (often: string, days: string) => string;\n /** A schedule the sentence can't say. */\n custom: string;\n /** What another kind of trigger waits for. */\n webhook: string;\n event: (app: string | null, event: string | null) => string;\n /** One of the platform's events: a contact's message stored on a channel. */\n platform: string;\n /** When it runs next, after when it runs: the day, and the time when the line doesn't say it. */\n next: (day: DayRef, time: string | null) => string;\n /** How it stands, on its pill. */\n states: Readonly<Record<AutomationState, string>>;\n /** Its switch, for screen readers. */\n switchLabel: string;\n /** Over its steps, the table it moves, its runs. */\n steps: string;\n runs: string;\n /** In the place of its runs, when there are none yet. */\n noRuns: string;\n /** What a step uses, other than an app (which goes by its name). */\n uses: Readonly<Record<Exclude<Use[\"kind\"], \"app\">, string>>;\n /** The values of the table past the ones shown: \"+3\". */\n more: (count: number) => string;\n /** An automation the agent named that is not there (removed, renamed). */\n gone: string;\n /** When a run started, beside what started it. */\n moment: (day: DayRef, time: string) => string;\n /** What started a run; an event's by its app's name, when known. */\n by: (by: RunBy, app: string | null) => string;\n /** How a run stands. */\n statuses: Readonly<Record<RunStatus, string>>;\n /** A test's line: what the run returned, though it changed nothing. */\n dry: (summary: string) => string;\n /** How long a run took. */\n took: (ms: number) => string;\n /** Over the conversations a run opened, and each one's link. */\n opened: string;\n conversation: (index: number) => string;\n /** The conversation the agent was asked in, for a run it started. */\n askedIn: string;\n /** A run that called nothing. */\n noCalls: string;\n /** Over the calls made outside any step. */\n outside: string;\n /** A call made several times in a row: \"×12\". */\n times: (count: number) => string;\n calls: CallMessages;\n}\n\nconst plural = (count: number, one: string, many: string) =>\n count === 1 ? one : `${count} ${many}`;\n\n/** English: what the package says until a host gives its own words. */\nexport const AUTOMATION_MESSAGES: AutomationMessages = {\n daily: \"Every day\",\n weekdays: \"Every weekday\",\n weekends: \"Every weekend\",\n weekly: (days) =>\n days.length === 1 ? `Every ${days[0] ?? \"\"}` : `On ${new Intl.ListFormat(\"en\").format(days)}`,\n monthly: (days) => `On day ${new Intl.ListFormat(\"en\").format(days.map(String))} of every month`,\n at: (times) => `at ${new Intl.ListFormat(\"en\").format(times)}`,\n every: (count, unit) => `Every ${plural(count, unit, `${unit}s`)}`,\n between: (from, to) => `from ${from} to ${to}`,\n on: (often, days) => `${often}, ${days.charAt(0).toLowerCase()}${days.slice(1)}`,\n custom: \"On a schedule of its own\",\n webhook: \"When another system calls it\",\n platform: \"When a message arrives\",\n event: (app, event) =>\n event ? `When ${event} in ${app ?? \"an app\"}` : `On an event in ${app ?? \"an app\"}`,\n next: (day, time) => {\n const at = time === null ? \"\" : ` at ${time}`;\n switch (day.kind) {\n case \"today\":\n return `next today${at}`;\n case \"tomorrow\":\n return `next tomorrow${at}`;\n case \"yesterday\":\n return `next${at}`;\n default:\n return `next on ${day.name}${at}`;\n }\n },\n states: { active: \"On\", paused: \"Paused\", failing: \"Last run failed\" },\n switchLabel: \"On\",\n steps: \"Steps\",\n runs: \"Runs\",\n noRuns: \"It hasn't run yet.\",\n uses: {\n ai: \"AI\",\n agent: \"Agent\",\n notify: \"Inbox\",\n send: \"Message\",\n data: \"Table\",\n http: \"Web\",\n },\n more: (count) => `+${count}`,\n gone: \"This automation is no longer there.\",\n moment: (day, time) => {\n switch (day.kind) {\n case \"today\":\n return `Today ${time}`;\n case \"yesterday\":\n return `Yesterday ${time}`;\n case \"tomorrow\":\n return `Tomorrow ${time}`;\n default:\n return `${day.name} ${time}`;\n }\n },\n by: (by, app) =>\n ({\n schedule: \"scheduled\",\n webhook: \"webhook\",\n event: app ? `${app} event` : \"event\",\n platform: \"a message\",\n agent: \"you asked in the chat\",\n test: \"test\",\n })[by],\n statuses: {\n running: \"Running\",\n waiting: \"Waiting\",\n done: \"Done\",\n failed: \"Failed\",\n skipped: \"Skipped\",\n },\n dry: (summary) => `Test: ${summary}`,\n took: (ms) =>\n ms < 60_000 ? `${Math.max(1, Math.round(ms / 1000))} s` : `${Math.round(ms / 60_000)} min`,\n opened: \"Conversations it opened\",\n conversation: (index) => `Conversation ${index}`,\n askedIn: \"The conversation you asked in\",\n noCalls: \"It didn't call anything.\",\n outside: \"Outside the steps\",\n times: (count) => `×${count}`,\n calls: {\n tool: (verb, app, would) => {\n const done = {\n search: `Searched ${app}`,\n send: `Sent with ${app}`,\n create: `Created in ${app}`,\n update: `Changed in ${app}`,\n remove: `Removed in ${app}`,\n use: `Used ${app}`,\n }[verb];\n return would && verb !== \"search\"\n ? `Would have ${done.charAt(0).toLowerCase()}${done.slice(1)}`\n : done;\n },\n ai: \"Used AI\",\n notify: (would) => (would ? \"Would have told you in the inbox\" : \"Told you in the inbox\"),\n send: (channel, to, would) => {\n const what =\n { whatsapp: \"a WhatsApp\", sms: \"an SMS\", instagram: \"an Instagram message\" }[\n channel ?? \"\"\n ] ?? \"a message\";\n const sent = `${what} to ${to || \"a contact\"}`;\n return would ? `Would have sent ${sent}` : `Sent ${sent}`;\n },\n start: (would) => (would ? \"Would have opened a conversation\" : \"Opened a conversation\"),\n find: (table) => `Looked up ${table}`,\n add: (table, would) =>\n would ? `Would have added a row to ${table}` : `Added a row to ${table}`,\n change: (table, would) =>\n would ? `Would have changed a row of ${table}` : `Changed a row of ${table}`,\n http: (host, would) => (would ? `Would have called ${host}` : `Called ${host}`),\n files: \"Searched the files\",\n read: (file) => `Read ${file}`,\n wrote: (file, would) => (would ? `Would have saved ${file}` : `Saved ${file}`),\n listed: \"Looked through its files\",\n remember: (would) => (would ? \"Would have kept a memory\" : \"Kept a memory\"),\n recall: \"Searched what it learned\",\n },\n};\n"],"mappings":"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"}