@cerebro-labs/agentnava-sdk 0.26.0 → 0.46.1
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/README.md +212 -23
- package/account.d.ts +154 -0
- package/account.js +219 -0
- package/account.js.map +1 -0
- package/agent.d.ts +229 -87
- package/agent.js +310 -125
- package/agent.js.map +1 -1
- package/apps.generated.d.ts +154 -0
- package/apps.generated.js +152 -0
- package/apps.generated.js.map +1 -0
- package/attach.d.ts +25 -26
- package/attach.js +53 -66
- package/attach.js.map +1 -1
- package/connection.d.ts +79 -82
- package/connection.js +67 -134
- package/connection.js.map +1 -1
- package/conversation.d.ts +55 -35
- package/conversation.js +70 -50
- package/conversation.js.map +1 -1
- package/database.d.ts +53 -0
- package/database.js +69 -0
- package/database.js.map +1 -0
- package/end-user.d.ts +58 -47
- package/end-user.js +62 -72
- package/end-user.js.map +1 -1
- package/errors.d.ts +2 -1
- package/errors.js +2 -1
- package/errors.js.map +1 -1
- package/http.d.ts +5 -0
- package/http.js +109 -8
- package/http.js.map +1 -1
- package/import-tools.d.ts +54 -33
- package/import-tools.js +526 -124
- package/import-tools.js.map +1 -1
- package/index.d.ts +5 -2
- package/index.js +9 -2
- package/index.js.map +1 -1
- package/load-agent-dir.js +28 -5
- package/load-agent-dir.js.map +1 -1
- package/package.json +5 -1
- package/secret.d.ts +1 -1
- package/secret.js +1 -1
- package/secret.js.map +1 -1
- package/templates-inline.js +1 -1
- package/templates-inline.js.map +1 -1
- package/turn.d.ts +1 -1
- package/turn.js +77 -29
- package/turn.js.map +1 -1
- package/types.d.ts +462 -83
- package/types.js.map +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.js.map +1 -1
- package/workflows.d.ts +10 -0
- package/workflows.js +16 -0
- package/workflows.js.map +1 -1
- package/workspace.d.ts +80 -62
- package/workspace.js +92 -75
- package/workspace.js.map +1 -1
- package/connection-status.d.ts +0 -28
- package/connection-status.js +0 -61
- package/connection-status.js.map +0 -1
package/agent.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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","sourcesContent":["// An agent: a configuration you start conversations from.\n\nimport { type Attachable, isBindings, providersOf, secretIdsOf, splitAttachments } from './attach.ts';\nimport type { Connection } from './connection.ts';\nimport { toConnectionStatus, type WireConnection } from './connection-status.ts';\nimport { Conversation } from './conversation.ts';\nimport type { Http } from './http.ts';\nimport type {\n\tAgentConversationData,\n\tAgentData,\n\tAgentFields,\n\tBindings,\n\tConnectionStatus,\n\tFileEntry,\n\tTrigger,\n\tWorkflow,\n} from './types.ts';\n\n/**\n * Turn the accounts a caller is holding into the `{ provider: id }` map the\n * wire speaks.\n *\n * Shared by `start`, `agent.attach` and `conversation.attach` so the three\n * cannot drift. A handle you created carries its provider already; one you\n * addressed by id has to read it, which is the only request here and only when\n * it is unavoidable.\n */\nexport interface StartOptions {\n\t/**\n\t * Accounts to attach AS THE CONVERSATION STARTS.\n\t *\n\t * The common shape for an application with many end users: the person\n\t * connected Gmail once, and this thread should act as them from its first\n\t * turn.\n\t *\n\t * ```ts\n\t * const gmail = await ws.endUser(row.userId).connections.list();\n\t * const c = await agent.start({ endUserId: row.userId, attach: gmail });\n\t * ```\n\t *\n\t * Doing it here rather than with a second `conversation.attach()` call\n\t * closes a real window: between `start` and the attach, the conversation\n\t * exists and can be asked something, and it would answer without the\n\t * account.\n\t *\n\t * STILL EXPLICIT. Naming `endUserId` does not attach their accounts; this\n\t * line does, and you can read it.\n\t *\n\t * TAKES SECRETS TOO. A `Secret` from `ws.endUser(id).secrets.create(...)`\n\t * attaches by id, which is the only way a stored per-person credential can\n\t * reach a turn: you never hold its value. Mix them freely, they are split by\n\t * type before the launch.\n\t */\n\tattach?: Attachable | Attachable[];\n\n\t/**\n\t * Secret VALUES for this conversation only.\n\t *\n\t * Not `attach`, because a secret has no id you can hand over: binding one\n\t * takes the value itself. That asymmetry is in the product, not in this\n\t * naming, and hiding it behind the same word would not remove it.\n\t */\n\tsecrets?: Record<string, string>;\n\n\t/** Pin a specific version. Defaults to the latest at the moment of starting.\n\t *\n\t * A conversation pins its version for life: publishing afterwards does not\n\t * move a conversation that is already open. */\n\tversion?: number;\n\tparameters?: Record<string, string | number>;\n\n\t/**\n\t * WHO this conversation is for: one of YOUR users, not one of ours.\n\t *\n\t * REQUIRED, and nullable. You must say, and `null` is a real answer: a\n\t * nightly report belongs to nobody. Optional would let it be forgotten,\n\t * which is the mistake worth designing against, because a conversation\n\t * without an owner cannot be listed back to the person it was for.\n\t *\n\t * It is a LABEL on the conversation, and nothing else. It does not decide\n\t * which conversation you get, because `start` always starts a new one.\n\t * Later you can ask for everything belonging to that person:\n\t *\n\t * ```ts\n\t * const conversation = await agent.start({ endUserId: row.userId });\n\t * const nobody = await agent.start({ endUserId: null }); // a nightly job\n\t * const theirs = await agent.conversations({ endUser: row.userId });\n\t * ```\n\t *\n\t * To CONTINUE a conversation, keep its id and address it directly. That is\n\t * the only way to continue one, on purpose:\n\t *\n\t * ```ts\n\t * await ws.agent(AGENT).conversation(row.conversationId).ask('and the rest?');\n\t * ```\n\t *\n\t * The id is YOURS and opaque to us: a row id from your database, not an\n\t * email and not something we authenticate. We never verify it, so it is\n\t * exactly as trustworthy as whatever holds your API key.\n\t *\n\t * NOT A WORKSPACE MEMBER'S ID. `ws.members()` lists the colleagues who share\n\t * this account, and their `userId` is a platform id we issued. This field is\n\t * a different namespace entirely. Both were once spelled `userId`, so\n\t * passing a member id here was a call that could not fail: there is nothing\n\t * for an end-user id to be checked against, so it just labelled the\n\t * conversation with a colleague's internal id and looked fine.\n\t */\n\tendUserId: string | null;\n}\n\n/**\n * An agent you can configure and start conversations from.\n *\n * Holding one makes NO request: `ws.agent(id)` is free and the first call on it\n * is the first round trip.\n *\n * EVERY METHOD THAT CHANGES THE AGENT PUBLISHES A VERSION. There is no separate\n * save. What you do not send is inherited from the current version, which is the\n * only reason changing one field is safe: a resend that rebuilt the whole\n * configuration would drop whatever the caller forgot, and that bug has shipped\n * here four separate times.\n */\nexport class Agent {\n\treadonly id: string;\n\treadonly #http: Http;\n\tprivate snapshot?: AgentData;\n\n\tconstructor(http: Http, id: string, snapshot?: AgentData) {\n\t\tthis.#http = http;\n\t\tthis.id = id;\n\t\tif (snapshot) this.snapshot = snapshot;\n\t}\n\n\tprivate get base(): string {\n\t\treturn `/v1/agents/${encodeURIComponent(this.id)}`;\n\t}\n\n\t/** The last-known configuration, from whatever call produced this object.\n\t * Undefined on an agent you addressed by id and have not read. */\n\tget data(): AgentData | undefined {\n\t\treturn this.snapshot;\n\t}\n\n\tasync get(options: { version?: number } = {}): Promise<AgentData> {\n\t\tconst data = await this.#http.get<AgentData>(\n\t\t\tthis.base,\n\t\t\toptions.version !== undefined ? { version: options.version } : undefined,\n\t\t);\n\t\t// Only cache the CURRENT configuration. Caching a historical version would\n\t\t// make `agent.data` mean different things depending on the last call.\n\t\tif (options.version === undefined) this.snapshot = data;\n\t\treturn data;\n\t}\n\n\t/** Every version, newest first. */\n\tasync versions(): Promise<AgentData[]> {\n\t\tconst res = await this.#http.get<{ versions: AgentData[] }>(`${this.base}/versions`);\n\t\treturn res.versions ?? [];\n\t}\n\n\t/** Publish a new version with these fields changed and everything else kept. */\n\tasync update(fields: AgentFields): Promise<Agent> {\n\t\tconst data = await this.#http.post<AgentData>(`${this.base}/versions`, fields);\n\t\tthis.snapshot = data;\n\t\treturn new Agent(this.#http, this.id, data);\n\t}\n\n\tasync delete(): Promise<void> {\n\t\tawait this.#http.delete(this.base);\n\t}\n\n\t// --------------------------------------------------------------- workflows\n\n\t/**\n\t * Add a workflow, or replace the one with the same name.\n\t *\n\t * Reads the current list and sends it back with this one in place, because\n\t * the API replaces the whole list: a workflow set is a list, and there is no\n\t * \"merge one item\" that does not have to decide what a duplicate name means.\n\t * Deciding it here, once, is better than every caller deciding it.\n\t */\n\tasync setWorkflow(workflow: Workflow): Promise<Agent> {\n\t\tconst current = this.snapshot?.workflows ?? (await this.get()).workflows;\n\t\tconst next = current.filter((w) => w.name !== workflow.name).concat(workflow);\n\t\treturn this.update({ workflows: next });\n\t}\n\n\tasync removeWorkflow(name: string): Promise<Agent> {\n\t\tconst current = this.snapshot?.workflows ?? (await this.get()).workflows;\n\t\treturn this.update({ workflows: current.filter((w) => w.name !== name) });\n\t}\n\n\t/** Replace the trigger list. Sending `[]` removes every trigger, including\n\t * `chat`, which is what leaves an agent that only runs on a schedule. */\n\tasync setTriggers(triggers: Trigger[]): Promise<Agent> {\n\t\treturn this.update({ triggers });\n\t}\n\n\t// --------------------------------------------------------------- knowledge\n\n\t/**\n\t * The agent's knowledge: files every conversation can read.\n\t *\n\t * BY REFERENCE, not by copy. A conversation reads the knowledge as it is now,\n\t * so replacing a file changes what open conversations see on their next turn.\n\t * That is the opposite of how a version works, and it is deliberate: a price\n\t * list that could not be corrected without republishing the agent would be\n\t * useless.\n\t */\n\treadonly knowledge = {\n\t\tput: async (path: string, bytes: Uint8Array | ArrayBuffer, contentType?: string): Promise<FileEntry> =>\n\t\t\tthis.#http.request<FileEntry>(`${this.base}/knowledge/files`, {\n\t\t\t\tmethod: 'PUT',\n\t\t\t\tbytes,\n\t\t\t\tquery: { path },\n\t\t\t\t...(contentType && { contentType }),\n\t\t\t}),\n\t\tlist: async (path = '/'): Promise<FileEntry[]> => {\n\t\t\t// The route returns EVERY knowledge file for the agent; it takes no\n\t\t\t// directory parameter. Filtering here rather than sending one the server\n\t\t\t// ignores, because a call that looks filtered and is not is worse than\n\t\t\t// no filter at all. Knowledge sets are small, so one read is right.\n\t\t\tconst res = await this.#http.get<{ files: (FileEntry & { path: string })[] }>(\n\t\t\t\t`${this.base}/knowledge/files`,\n\t\t\t);\n\t\t\tconst prefix = path === '/' ? '/' : `${path.replace(/\\/+$/, '')}/`;\n\t\t\treturn (res.files ?? []).filter((f) => f.path?.startsWith(prefix));\n\t\t},\n\t\tremove: async (path: string): Promise<void> => {\n\t\t\tawait this.#http.delete(`${this.base}/knowledge/files`, { path });\n\t\t},\n\t};\n\n\t// -------------------------------------------------------- knowledge bases\n\n\t/**\n\t * The WORKSPACE knowledge bases this agent reads.\n\t *\n\t * Different from `knowledge` above, and the distinction is the whole point.\n\t * `agent.knowledge` is files this agent owns; nobody else has them. A\n\t * knowledge base is shared: one price list, attached to nine agents, corrected\n\t * in one place.\n\t *\n\t * Each attached base is mounted read-only at `/knowledge/<key>/` when a turn\n\t * starts, so the agent reads it with `ls`, `grep` and `cat`.\n\t *\n\t * ATTACHING PUBLISHES A VERSION. Which bases an agent reads is part of its\n\t * configuration, so the change is diffable and reversible like any other\n\t * configuration change. The CONTENTS of a base are not versioned: correcting\n\t * a file changes what every attached agent sees on its next turn.\n\t */\n\treadonly knowledgeBases = {\n\t\t/**\n\t\t * Attach one base by key.\n\t\t *\n\t\t * One call, not read-modify-write, deliberately. Two attaches racing\n\t\t * through a read of the current list and a write of the whole list would\n\t\t * lose one of them silently, and losing an attachment looks exactly like\n\t\t * an agent that cannot find its knowledge. The server appends.\n\t\t *\n\t\t * Attaching a key that names no base is refused, naming the key. Attaching\n\t\t * one that is already attached is a no-op, not an error.\n\t\t */\n\t\tattach: async (key: string): Promise<Agent> => {\n\t\t\tconst res = await this.#http.post<AgentData>(`${this.base}/knowledge-bases`, { key });\n\t\t\tthis.snapshot = res;\n\t\t\treturn this;\n\t\t},\n\n\t\t/** Detach one base. The base itself and its files are untouched: this only\n\t\t * stops THIS agent from reading it. Detaching one that is not attached is\n\t\t * a no-op. */\n\t\tdetach: async (key: string): Promise<Agent> => {\n\t\t\tconst res = await this.#http.delete<AgentData>(\n\t\t\t\t`${this.base}/knowledge-bases/${encodeURIComponent(key)}`,\n\t\t\t);\n\t\t\tif (res) this.snapshot = res;\n\t\t\treturn this;\n\t\t},\n\n\t\t/** The keys this agent currently reads, in configuration order. */\n\t\tlist: async (): Promise<string[]> => {\n\t\t\tconst current = this.snapshot ?? (await this.get());\n\t\t\treturn current.knowledgeBases ?? [];\n\t\t},\n\t};\n\n\t// ------------------------------------------------- credentials, agent tier\n\n\t/**\n\t * Supply the credentials declared at 'fixed' scope: set once, used by every\n\t * conversation. This does NOT satisfy a declaration scoped 'conversation'.\n\t *\n\t * A secret is written to this agent's own scope, so it is readable by this\n\t * agent and nothing else in the workspace, and it overrides a workspace\n\t * secret of the same name. Writing one twice replaces the value rather than\n\t * failing, because `bind` means \"this is the credential now\".\n\t *\n\t * A connection value is the id of an account already attached to the\n\t * workspace; use `authorize()` when there is no account yet, since that is\n\t * the flow where a person signs in and no token passes through your code.\n\t *\n\t * This used to POST the whole `{secrets, connections}` object to\n\t * `/v1/agents/:id/bindings`, which answers only to `{kind, decl}` and records\n\t * a DECLARATION, never a value. So the call 400'd, and had it not, it would\n\t * have stored the fact that a secret is wanted rather than the secret.\n\t */\n\tasync #applyBindings(bindings: Bindings): Promise<Agent> {\n\t\tfor (const [name, value] of Object.entries(bindings.secrets ?? {})) {\n\t\t\tconst mine = (await this.#http.get<{ secrets: { id: string; name: string; agentId?: string | null }[] }>(\n\t\t\t\t'/v1/secrets',\n\t\t\t\t{ agentId: this.id },\n\t\t\t)).secrets ?? [];\n\t\t\tconst existing = mine.find((s) => s.name === name && s.agentId);\n\t\t\tif (existing) await this.#http.patch(`/v1/secrets/${encodeURIComponent(existing.id)}`, { value });\n\t\t\telse await this.#http.post('/v1/secrets', { name, value, agentId: this.id });\n\t\t}\n\t\tfor (const [provider, connectionId] of Object.entries(bindings.connections ?? {})) {\n\t\t\tawait this.#http.post(`${this.base}/bindings`, {\n\t\t\t\tkind: 'connection',\n\t\t\t\tdecl: { provider, connectionId, scope: 'fixed' },\n\t\t\t});\n\t\t}\n\t\tconst data = await this.get();\n\t\tthis.snapshot = data;\n\t\treturn new Agent(this.#http, this.id, data);\n\t}\n\n\t/**\n\t * Give this agent a credential, so every conversation with it can use one.\n\t *\n\t * ```ts\n\t * await agent.attach(gmail); // one account\n\t * await agent.attach([gmail, calendar]); // several\n\t * await agent.attach({ secrets: { KEY: value } }); // a secret VALUE\n\t * ```\n\t *\n\t * ONE VERB, NOT TWO. This and `bind` used to both exist and do the same job\n\t * through different shapes, which is how a surface becomes hard to learn:\n\t * two names for one idea means every reader has to work out whether the\n\t * difference is meaningful. It is not, so `bind` is gone.\n\t *\n\t * \"Attach\" rather than \"bind\" because it is the plainer word, it is the one\n\t * that pairs with `detach`, and `knowledgeBases.attach/detach` already uses\n\t * it for the same shape of operation.\n\t *\n\t * ACCOUNTS TAKE THE OBJECT, SECRETS TAKE A VALUE, and that asymmetry is in\n\t * the product rather than in the naming. An account has an id you can hand\n\t * over; a secret does not, because binding one means supplying the value\n\t * itself. Hiding that behind one shape would not make it go away.\n\t *\n\t * The counterpart to `authorize()`, which creates an account AND attaches it\n\t * in one step. Use this when the account already exists: one team mailbox\n\t * connected once and attached to nine agents, rather than nine sign-ins.\n\t */\n\tasync attach(what: Attachable | Attachable[] | Bindings): Promise<Agent> {\n\t\tif (isBindings(what)) return this.#applyBindings(what as Bindings);\n\t\tconst split = splitAttachments(what as Attachable | Attachable[]);\n\t\tconst connections = await providersOf(split.connections);\n\t\tconst secretIds = await secretIdsOf(split.secrets);\n\t\treturn this.#applyBindings({\n\t\t\t...(connections && { connections }),\n\t\t\t...(secretIds && { secretIds }),\n\t\t});\n\t}\n\n\t/** What each declared provider's actual state is: DECLARED IS NOT CONNECTED.\n\t *\n\t * An agent can require Gmail with nobody signed in, and that is the state a\n\t * setup checklist has to show. Without this the only way to find the gap is\n\t * to start a conversation and watch the agent fail. */\n\tasync connections(): Promise<ConnectionStatus[]> {\n\t\t// The MERGED view, not the raw connection rows. /v1/connections?agentId=\n\t\t// lists rows that exist, so a provider the agent declares and nobody has\n\t\t// connected is simply absent from it, which is the one case this method is\n\t\t// most often asked about. The server merges declared against live with the\n\t\t// same function the agent's own check_connections tool uses.\n\t\tconst res = await this.#http.get<{ connections: ConnectionStatus[] }>(\n\t\t\t`${this.base}/connections`,\n\t\t);\n\t\treturn res.connections ?? [];\n\t}\n\n\t/**\n\t * Attach a third-party account to this agent, at `fixed` scope: one account,\n\t * used by every conversation.\n\t *\n\t * Returns a url to send a person to. They sign in there, in their own\n\t * browser, and the account attaches when they finish. YOU NEVER SEE A TOKEN,\n\t * which is the entire point: nobody should be pasting a Gmail credential into\n\t * a config field.\n\t *\n\t * This does NOT satisfy a declaration scoped 'conversation'. Use\n\t * `conversation.authorize()` for those, which attaches the account to that\n\t * one conversation and cannot overwrite this shared one.\n\t */\n\tasync authorize(provider: string): Promise<{ url: string; connectionId: string }> {\n\t\tconst res = await this.#http.post<{ authUrl: string; connectionId: string }>(\n\t\t\t'/v1/connections/connect',\n\t\t\t{ provider, agentId: this.id },\n\t\t);\n\t\t// `url` on the way out, `authUrl` on the wire. The SDK's name is the one\n\t\t// the reference documents and reads better at a call site.\n\t\treturn { url: res.authUrl, connectionId: res.connectionId };\n\t}\n\n\t/** Detach the account connected for this provider.\n\t *\n\t * Reads the raw ROWS rather than the merged status, because revoking needs\n\t * the connection's id and the merged view is keyed by provider: it answers\n\t * \"is Gmail connected\", not \"which row is it\". */\n\tasync disconnect(provider: string): Promise<void> {\n\t\tconst res = await this.#http.get<{ connections: WireConnection[] }>('/v1/connections', {\n\t\t\tagentId: this.id,\n\t\t});\n\t\tconst match = (res.connections ?? [])\n\t\t\t.map(toConnectionStatus)\n\t\t\t.find((c) => c.provider === provider && c.connected);\n\t\t// Nothing connected is not an error: the caller wanted this provider\n\t\t// detached, and it is.\n\t\tif (!match?.id) return;\n\t\tawait this.#http.post(`/v1/connections/${encodeURIComponent(match.id)}/revoke`);\n\t}\n\n\t// ----------------------------------------------------------- conversations\n\n\t/** Start a conversation. It pins the agent's version now and keeps it. */\n\tasync start(options: StartOptions): Promise<Conversation> {\n\t\t// Resolved BEFORE the launch, because an account is named on the wire by\n\t\t// its provider and a handle addressed by id may not know its own yet.\n\t\t// Split first: a Connection is named on the wire by its PROVIDER and a\n\t\t// Secret by the declared NAME it fills, so the two cannot share a map.\n\t\tconst split = splitAttachments(options.attach);\n\t\tconst connections = await providersOf(split.connections);\n\t\tconst secretIds = await secretIdsOf(split.secrets);\n\t\tconst bindings =\n\t\t\toptions.secrets || connections || secretIds\n\t\t\t\t? {\n\t\t\t\t\t\t...(options.secrets && { secrets: options.secrets }),\n\t\t\t\t\t\t...(secretIds && { secretIds }),\n\t\t\t\t\t\t...(connections && { connections }),\n\t\t\t\t\t}\n\t\t\t\t: undefined;\n\t\tconst data = await this.#http.post<AgentConversationData>('/v1/conversations', {\n\t\t\tagentId: this.id,\n\t\t\t...(options.version !== undefined && { version: options.version }),\n\t\t\t...(options.parameters && { parameters: options.parameters }),\n\t\t\t// `sessionBindings`, NOT `secrets` and `connections` at the top level.\n\t\t\t//\n\t\t\t// This sent them at the top level and the launch route reads\n\t\t\t// `body.sessionBindings`, so they were dropped in silence: the route's\n\t\t\t// own body type has no top-level `secrets` or `connections` to read.\n\t\t\t// A conversation started with a credential began without it, and the\n\t\t\t// first turn failed somewhere else entirely.\n\t\t\t//\n\t\t\t// Third place this exact envelope mistake was found in one afternoon,\n\t\t\t// after `agent.bind` and `conversation.bind`. The shape of the bug is\n\t\t\t// always the same: the SDK agrees with itself, the route agrees with\n\t\t\t// itself, and nothing compares the two.\n\t\t\t...(bindings && { sessionBindings: bindings }),\n\t\t\t// `!= null`, catching undefined as well as null. The field is REQUIRED\n\t\t\t// in TypeScript, but a JavaScript caller can still omit it, and\n\t\t\t// `!== null` alone then sent `user: {}`: an owner object with no id,\n\t\t\t// which is neither \"nobody\" nor a person.\n\t\t\t...(options.endUserId != null && { user: { id: options.endUserId } }),\n\t\t\t// ALWAYS a new conversation, even when a user is named.\n\t\t\t//\n\t\t\t// The route resumes that user's most recent conversation when it is\n\t\t\t// given an identity and not told otherwise. That default exists for\n\t\t\t// our own web app, where a page reload must not leave a trail of empty\n\t\t\t// conversations, and it is wrong for a method called `start`: a verb\n\t\t\t// that sometimes does not do the thing is worse than two verbs. It is\n\t\t\t// also ambiguous the moment a user has more than one conversation,\n\t\t\t// since it silently picks the newest.\n\t\t\t//\n\t\t\t// So the SDK does not rely on that default. `start` starts. To\n\t\t\t// continue a conversation, hold its id: `agent.conversation(id)`.\n\t\t\tfresh: true,\n\t\t});\n\t\treturn new Conversation(this.#http, data.id, data);\n\t}\n\n\t/**\n\t * Address one of this agent's conversations by id. No request.\n\t *\n\t * Here rather than on the workspace because a conversation belongs to an\n\t * agent. You already hold the agent: it is a constant in your own code, not\n\t * a per-row value, so naming it costs nothing and the ownership is visible.\n\t *\n\t * ```ts\n\t * await ws.agent(AGENT).conversation(row.conversationId).ask('carry on');\n\t * ```\n\t */\n\tconversation(conversationId: string): Conversation {\n\t\treturn new Conversation(this.#http, conversationId);\n\t}\n\n\t/**\n\t * This agent's most recent conversations, newest first.\n\t *\n\t * NOT ALL OF THEM, and the previous sentence here said \"every\", which was\n\t * wrong in the way that costs someone an afternoon. The server returns the\n\t * newest 50 unless you ask for more, and refuses to return more than 200 on\n\t * any single call (apps/api/src/state.ts listAgentSessions, and the Durable\n\t * Object twin beside it, clamp identically).\n\t *\n\t * There is no cursor on this route yet, so an agent with more than 200\n\t * conversations CANNOT be fully enumerated through this method. If you are\n\t * counting or exporting, do not build on it; that needs a paginated route we\n\t * have not added. `ws.endUser(id).conversations()` DOES have a cursor, if\n\t * the question is one person's history rather than one agent's.\n\t *\n\t * `endUser` narrows to one of YOUR end users, which is what you want for a\n\t * \"your conversations\" list. Leaving it out returns everyone's, so leave it\n\t * out only for an operator view.\n\t *\n\t * ```ts\n\t * const mine = await agent.conversations({ endUser: row.userId });\n\t * ```\n\t */\n\tasync conversations(options: { limit?: number; endUser?: string } = {}): Promise<Conversation[]> {\n\t\tconst res = await this.#http.get<{ conversations: AgentConversationData[] }>('/v1/conversations', {\n\t\t\tagentId: this.id,\n\t\t\t...(options.limit !== undefined && { limit: options.limit }),\n\t\t\t// One end user's history. Sending this used to be silently ignored on\n\t\t\t// this route, which answered with everyone's conversations, so an\n\t\t\t// application rendering \"your chats\" showed somebody else's.\n\t\t\t...(options.endUser !== undefined && { end_user_id: options.endUser }),\n\t\t});\n\t\treturn (res.conversations ?? []).map((c) => new Conversation(this.#http, c.id, c));\n\t}\n}\n\n/** A connection row as `GET /v1/connections` returns it (toConnectionMeta in\n * apps/api/src/connections/store.ts). */\n\n"]}
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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","sourcesContent":["// An agent: a configuration you start conversations from.\n\nimport { type Account, accountIdOf } from './account.ts';\nimport { isBindings, refuseConnections, secretIdsOf, secretsIn } from './attach.ts';\nimport { Conversation } from './conversation.ts';\nimport { AgentNavaError } from './errors.ts';\nimport type { Http } from './http.ts';\nimport type { Secret } from './secret.ts';\nimport { type Connection, connectionForWire } from './connection.ts';\nimport type {\n\tAgentConversationData,\n\tAgentData,\n\tAgentFields,\n\tBindings,\n\tConnectionStatus,\n\tFileEntry,\n\tTrigger,\n\tWebsiteChat,\n\tWorkflow,\n\tWebhookDelivery,\n} from './types.ts';\n\nexport interface StartOptions {\n\t/**\n\t * Stored secrets to attach AS THE CONVERSATION STARTS.\n\t *\n\t * A `Secret` from `ws.endUser(id).secrets.create(...)` attaches by id, which\n\t * is the only way a stored per-person credential can reach a turn: you never\n\t * hold its value.\n\t *\n\t * ```ts\n\t * const key = await ws.endUser(row.userId).secrets.create({ name: 'ZENDESK_TOKEN', value });\n\t * const conversation = await agent.start({ endUserId: row.userId, attach: key });\n\t * ```\n\t *\n\t * Doing it here rather than with a second `conversation.attach()` call\n\t * closes a real window: between `start` and the attach, the conversation\n\t * exists and can be asked something, and it would answer without it.\n\t *\n\t * ACCOUNTS ARE NOT ATTACHED HERE any more (0.44), and one handed in is\n\t * refused. The agent's setup names the account each connection uses; for a\n\t * connection to the end user's account (`Connection.endUserAccount`), the\n\t * turn uses the account of the person this conversation is for, found by\n\t * `endUserId`. Ask\n\t * `conversation.accountsNeeded()` for the ones they have not connected yet.\n\t */\n\tattach?: Secret | Secret[];\n\n\t/**\n\t * Secret VALUES for this conversation only.\n\t *\n\t * Not `attach`, because a secret has no id you can hand over: binding one\n\t * takes the value itself. That asymmetry is in the product, not in this\n\t * naming, and hiding it behind the same word would not remove it.\n\t */\n\tsecrets?: Record<string, string>;\n\n\t/** Pin a specific version. Defaults to the latest at the moment of starting.\n\t *\n\t * A conversation pins its version for life: publishing afterwards does not\n\t * move a conversation that is already open. The one exception is a schedule\n\t * or webhook that names the conversation (`conversationId`): each firing\n\t * moves it to the latest version, so a fix you publish reaches it. */\n\tversion?: number;\n\tparameters?: Record<string, string | number>;\n\n\t/**\n\t * WHO this conversation is for: one of YOUR users, not one of ours.\n\t *\n\t * REQUIRED, and never null. Every conversation belongs to someone. The id\n\t * is yours to choose: a user's row id, an anonymous visitor's random id, or\n\t * a name for a job such as `'nightly-report'`. Only a non-empty string is\n\t * accepted; anything else throws before a request is sent. (Decided\n\t * 2026-09-26, AGE-161: a conversation with no owner cannot be listed back to\n\t * the person it was for, and the accounts connected inside it could not be\n\t * revoked with that person.)\n\t *\n\t * It LABELS the conversation, and it decides one thing more: a connection\n\t * to the end user's account (`Connection.endUserAccount`) uses THIS\n\t * person's account for that app.\n\t * It does not decide which conversation you get, because `start` always\n\t * starts a new one. Later you can ask for everything belonging to that\n\t * person:\n\t *\n\t * ```ts\n\t * const conversation = await agent.start({ endUserId: row.userId });\n\t * const nightly = await agent.start({ endUserId: 'nightly-report' }); // a job has an id too\n\t * const theirs = await agent.conversations({ endUser: row.userId });\n\t * ```\n\t *\n\t * To CONTINUE a conversation, keep its id and address it directly. That is\n\t * the only way to continue one, on purpose:\n\t *\n\t * ```ts\n\t * await ws.agent(AGENT).conversation(row.conversationId).ask('and the rest?');\n\t * ```\n\t *\n\t * The id is YOURS and opaque to us: a row id from your database, not an\n\t * email and not something we authenticate. We never verify it, so it is\n\t * exactly as trustworthy as whatever holds your API key.\n\t *\n\t * The platform's prefixes are refused with a 400 (`end_user_reserved`):\n\t * `member:`, `visitor:` and `job:`, which name a member in the web app, an\n\t * embed visitor and work nobody is typing, and the older `webhook:`,\n\t * `builder:` and `librarian:`. Case and spacing do not matter to the check\n\t * (`MEMBER:x` is refused too). An id you chose must never be mistaken for\n\t * one of ours.\n\t *\n\t * NOT A WORKSPACE MEMBER'S ID. `ws.members()` lists the colleagues who share\n\t * this account, and their `userId` is a platform id we issued. This field is\n\t * a different namespace entirely. Both were once spelled `userId`, so\n\t * passing a member id here was a call that could not fail: there is nothing\n\t * for an end-user id to be checked against, so it just labelled the\n\t * conversation with a colleague's internal id and looked fine.\n\t */\n\tendUserId: string;\n}\n\n/**\n * An agent you can configure and start conversations from.\n *\n * Holding one makes NO request: `ws.agent(id)` is free and the first call on it\n * is the first round trip.\n *\n * EVERY METHOD THAT CHANGES THE AGENT PUBLISHES A VERSION. There is no separate\n * save. What you do not send is inherited from the current version, which is the\n * only reason changing one field is safe: a resend that rebuilt the whole\n * configuration would drop whatever the caller forgot, and that bug has shipped\n * here four separate times.\n */\nexport class Agent {\n\treadonly id: string;\n\treadonly #http: Http;\n\tprivate snapshot?: AgentData;\n\n\tconstructor(http: Http, id: string, snapshot?: AgentData) {\n\t\tthis.#http = http;\n\t\tthis.id = id;\n\t\tif (snapshot) this.snapshot = snapshot;\n\t}\n\n\tprivate get base(): string {\n\t\treturn `/v1/agents/${encodeURIComponent(this.id)}`;\n\t}\n\n\t/** The last-known configuration, from whatever call produced this object.\n\t * Undefined on an agent you addressed by id and have not read. */\n\tget data(): AgentData | undefined {\n\t\treturn this.snapshot;\n\t}\n\n\tasync get(options: { version?: number } = {}): Promise<AgentData> {\n\t\tconst data = await this.#http.get<AgentData>(\n\t\t\tthis.base,\n\t\t\toptions.version !== undefined ? { version: options.version } : undefined,\n\t\t);\n\t\t// Only cache the CURRENT configuration. Caching a historical version would\n\t\t// make `agent.data` mean different things depending on the last call.\n\t\tif (options.version === undefined) this.snapshot = data;\n\t\treturn data;\n\t}\n\n\t/** Every version, newest first. */\n\tasync versions(): Promise<AgentData[]> {\n\t\tconst res = await this.#http.get<{ versions: AgentData[] }>(`${this.base}/versions`);\n\t\treturn res.versions ?? [];\n\t}\n\n\t/** Publish a new version with these fields changed and everything else kept.\n\t * `connections`, when sent, replaces the whole list; an `Account` in it goes\n\t * over the wire as its id (`Account.toJSON`). */\n\tasync update(fields: AgentFields): Promise<Agent> {\n\t\tconst data = await this.#http.post<AgentData>(`${this.base}/versions`, fields);\n\t\tthis.snapshot = data;\n\t\treturn new Agent(this.#http, this.id, data);\n\t}\n\n\tasync delete(): Promise<void> {\n\t\tawait this.#http.delete(this.base);\n\t}\n\n\t// --------------------------------------------------------------- workflows\n\n\t/**\n\t * Add a workflow, or replace the one with the same name.\n\t *\n\t * Reads the current list and sends it back with this one in place, because\n\t * the API replaces the whole list: a workflow set is a list, and there is no\n\t * \"merge one item\" that does not have to decide what a duplicate name means.\n\t * Deciding it here, once, is better than every caller deciding it.\n\t */\n\tasync setWorkflow(workflow: Workflow): Promise<Agent> {\n\t\tconst current = this.snapshot?.workflows ?? (await this.get()).workflows;\n\t\tconst next = current.filter((w) => w.name !== workflow.name).concat(workflow);\n\t\treturn this.update({ workflows: next });\n\t}\n\n\tasync removeWorkflow(name: string): Promise<Agent> {\n\t\tconst current = this.snapshot?.workflows ?? (await this.get()).workflows;\n\t\treturn this.update({ workflows: current.filter((w) => w.name !== name) });\n\t}\n\n\t/** Replace the trigger list. Sending `[]` removes every trigger, including\n\t * `chat`, which is what leaves an agent that only runs on a schedule. */\n\tasync setTriggers(triggers: Trigger[]): Promise<Agent> {\n\t\treturn this.update({ triggers });\n\t}\n\n\t/**\n\t * Replace the webhook's URL and return the new one.\n\t *\n\t * The old URL stops working the moment this returns, so update the system\n\t * that calls it. Use it when a URL leaked. The webhook's `message` and who it\n\t * runs for are kept. Publishes a version. Throws `no_webhook` (409) when the\n\t * agent has no webhook trigger.\n\t */\n\tasync rotateWebhookUrl(): Promise<string> {\n\t\tconst data = await this.#http.post<AgentData>(`${this.base}/webhook/rotate`, {});\n\t\tthis.snapshot = data;\n\t\tconst webhook = data.triggers.find((t) => t.kind === 'webhook');\n\t\tif (webhook?.kind !== 'webhook' || !webhook.url) {\n\t\t\tthrow new AgentNavaError({\n\t\t\t\tmessage: 'The webhook was rotated but no URL came back. Read it with agent.get().',\n\t\t\t\tcode: 'webhook_url_missing',\n\t\t\t\tstatus: 502,\n\t\t\t});\n\t\t}\n\t\treturn webhook.url;\n\t}\n\n\t/** What the webhook received, newest first: accepted, refused (and why), a\n\t * sender's retry recognised as a repeat, or a test. Up to `limit` (200). */\n\tasync webhookDeliveries(options: { limit?: number } = {}): Promise<WebhookDelivery[]> {\n\t\tconst res = await this.#http.get<{ deliveries: WebhookDelivery[] }>(\n\t\t\t`${this.base}/webhook/deliveries`,\n\t\t\toptions.limit !== undefined ? { limit: options.limit } : undefined,\n\t\t);\n\t\treturn res.deliveries ?? [];\n\t}\n\n\t/**\n\t * Send the webhook a sample event and run the agent on it, the way a real\n\t * delivery would (the signature check aside). A real turn, charged like\n\t * one. Returns the conversation it ran in.\n\t */\n\tasync sendTestWebhook(): Promise<{ conversationId?: string }> {\n\t\tconst res = await this.#http.post<{ conversationId?: string }>(`${this.base}/webhook/test`, {});\n\t\treturn res.conversationId ? { conversationId: res.conversationId } : {};\n\t}\n\n\t// ------------------------------------------------------------ website chat\n\n\t/**\n\t * The agent's website chat: a public chat page, and the embed script that\n\t * puts it on your website. ON from the moment the agent is created, for\n\t * every agent, however it was made (here, through the API, or in the portal),\n\t * until you turn it off. The one exception is an agent that needs each\n\t * user's own account or secret, which a visitor cannot bring: it has none.\n\t *\n\t * You never need it to use the agent from code: the agent answers your API\n\t * key, and the portal's Test, as soon as it exists.\n\t *\n\t * Anyone with the page link can talk to the agent, and each of their turns is\n\t * charged to your workspace, so turn it off for an agent only your own code\n\t * should reach. `turnOn()` on a new agent changes nothing and hands back what\n\t * to put on a website. The portal has no switch for it; its Website chat panel\n\t * holds the share link and the allowed websites (`allowedWebsites` below).\n\t * Publishing a newer version does not move the page: call `turnOn()` while it\n\t * is on to serve the newer one. Turned off and on again, it serves the\n\t * version it served before.\n\t */\n\treadonly websiteChat = {\n\t\t/** Turn it on and get what to put on a website. The first time, and when\n\t\t * it is already on, the page serves the current version; after\n\t\t * `turnOff()`, the version it served before. Refused (400) for an agent\n\t\t * that needs each user's own account or secret, which a visitor cannot\n\t\t * bring. */\n\t\tturnOn: async (): Promise<WebsiteChat> => {\n\t\t\tconst res = await this.#http.post<{\n\t\t\t\tagentId: string;\n\t\t\t\tversionNumber: number;\n\t\t\t\tpublicToken: string;\n\t\t\t\tchatUrl: string;\n\t\t\t}>(`${this.base}/activate`, {});\n\t\t\treturn {\n\t\t\t\tchatUrl: res.chatUrl,\n\t\t\t\tpublicToken: res.publicToken,\n\t\t\t\tembedAgentId: res.agentId,\n\t\t\t\tversionNumber: res.versionNumber,\n\t\t\t};\n\t\t},\n\t\t/** Turn it off. Visitors are refused from the next message, follow-ups a\n\t\t * visitor's conversation booked are cancelled, and nothing more is\n\t\t * charged for them. The agent keeps answering your API key, its schedules\n\t\t * and its webhooks. The publishable token is kept, so turning it on again\n\t\t * revives a snippet already on a website. Turning off a chat that is\n\t\t * already off is not an error. */\n\t\tturnOff: async (): Promise<void> => {\n\t\t\tawait this.#http.post(`${this.base}/deactivate`, {});\n\t\t},\n\t\t/** The websites the chat may be shown on through the embed script. A\n\t\t * domain covers its subdomains; an empty list means no other website.\n\t\t * The share link opened directly always works. */\n\t\tallowedWebsites: {\n\t\t\t/** The list as it stands. */\n\t\t\tget: async (): Promise<string[]> =>\n\t\t\t\t(await this.#http.get<{ websites: string[] }>(`${this.base}/allowed-websites`)).websites,\n\t\t\t/** Replace the list. Each entry is normalised (\"https://acme.com/page\"\n\t\t\t * becomes \"acme.com\"; \"localhost\" is allowed for testing), and one that\n\t\t\t * is not a website is refused (400). Returns the list as stored. */\n\t\t\tset: async (websites: string[]): Promise<string[]> =>\n\t\t\t\t(await this.#http.put<{ websites: string[] }>(`${this.base}/allowed-websites`, { websites })).websites,\n\t\t},\n\t};\n\n\t// --------------------------------------------------------------- knowledge\n\n\t#readKnowledgeResponse(path: string): Promise<Response> {\n\t\treturn this.#http.send(`${this.base}/knowledge/files/content`, { query: { path } });\n\t}\n\n\t/**\n\t * The agent's knowledge: files every conversation can read.\n\t *\n\t * BY REFERENCE, not by copy. A conversation reads the knowledge as it is now,\n\t * so replacing a file changes what open conversations see on their next turn.\n\t * That is the opposite of how a version works, and it is deliberate: a price\n\t * list that could not be corrected without republishing the agent would be\n\t * useless.\n\t */\n\treadonly knowledge = {\n\t\tput: async (path: string, bytes: Uint8Array | ArrayBuffer, contentType?: string): Promise<FileEntry> =>\n\t\t\tthis.#http.request<FileEntry>(`${this.base}/knowledge/files`, {\n\t\t\t\tmethod: 'PUT',\n\t\t\t\tbytes,\n\t\t\t\tquery: { path },\n\t\t\t\t...(contentType && { contentType }),\n\t\t\t}),\n\t\t/** Read an agent-owned knowledge file as bytes, without starting a turn. */\n\t\tget: async (path: string): Promise<Uint8Array> => {\n\t\t\tconst res = await this.#readKnowledgeResponse(path);\n\t\t\treturn new Uint8Array(await res.arrayBuffer());\n\t\t},\n\t\t/** Read UTF-8 text. JSON files remain text rather than being parsed. */\n\t\ttext: async (path: string): Promise<string> => {\n\t\t\tconst res = await this.#readKnowledgeResponse(path);\n\t\t\treturn res.text();\n\t\t},\n\t\tlist: async (path = '/'): Promise<FileEntry[]> => {\n\t\t\t// The route returns EVERY knowledge file for the agent; it takes no\n\t\t\t// directory parameter. Filtering here rather than sending one the server\n\t\t\t// ignores, because a call that looks filtered and is not is worse than\n\t\t\t// no filter at all. Knowledge sets are small, so one read is right.\n\t\t\tconst res = await this.#http.get<{ files: (FileEntry & { path: string })[] }>(\n\t\t\t\t`${this.base}/knowledge/files`,\n\t\t\t);\n\t\t\tconst prefix = path === '/' ? '/' : `${path.replace(/\\/+$/, '')}/`;\n\t\t\treturn (res.files ?? []).filter((f) => f.path?.startsWith(prefix));\n\t\t},\n\t\tremove: async (path: string): Promise<void> => {\n\t\t\tawait this.#http.delete(`${this.base}/knowledge/files`, { path });\n\t\t},\n\t};\n\n\t// -------------------------------------------------------- knowledge bases\n\n\t/**\n\t * The WORKSPACE knowledge bases this agent reads.\n\t *\n\t * Different from `knowledge` above, and the distinction is the whole point.\n\t * `agent.knowledge` is files this agent owns; nobody else has them. A\n\t * knowledge base is shared: one price list, attached to nine agents, corrected\n\t * in one place.\n\t *\n\t * Each attached base is mounted read-only at `/knowledge/<key>/` when a turn\n\t * starts, so the agent reads it with `ls`, `grep` and `cat`.\n\t *\n\t * ATTACHING PUBLISHES A VERSION. Which bases an agent reads is part of its\n\t * configuration, so the change is diffable and reversible like any other\n\t * configuration change. The CONTENTS of a base are not versioned: correcting\n\t * a file changes what every attached agent sees on its next turn.\n\t */\n\treadonly knowledgeBases = {\n\t\t/**\n\t\t * Attach one base by key.\n\t\t *\n\t\t * One call, not read-modify-write, deliberately. Two attaches racing\n\t\t * through a read of the current list and a write of the whole list would\n\t\t * lose one of them silently, and losing an attachment looks exactly like\n\t\t * an agent that cannot find its knowledge. The server appends.\n\t\t *\n\t\t * Attaching a key that names no base is refused, naming the key. Attaching\n\t\t * one that is already attached is a no-op, not an error.\n\t\t */\n\t\tattach: async (key: string): Promise<Agent> => {\n\t\t\tconst res = await this.#http.post<AgentData>(`${this.base}/knowledge-bases`, { key });\n\t\t\tthis.snapshot = res;\n\t\t\treturn this;\n\t\t},\n\n\t\t/** Detach one base. The base itself and its files are untouched: this only\n\t\t * stops THIS agent from reading it. Detaching one that is not attached is\n\t\t * a no-op. */\n\t\tdetach: async (key: string): Promise<Agent> => {\n\t\t\tconst res = await this.#http.delete<AgentData>(\n\t\t\t\t`${this.base}/knowledge-bases/${encodeURIComponent(key)}`,\n\t\t\t);\n\t\t\tif (res) this.snapshot = res;\n\t\t\treturn this;\n\t\t},\n\n\t\t/** The keys this agent currently reads, in configuration order. */\n\t\tlist: async (): Promise<string[]> => {\n\t\t\tconst current = this.snapshot ?? (await this.get());\n\t\t\treturn current.knowledgeBases ?? [];\n\t\t},\n\t};\n\n\t// -------------------------------------------------------------- databases\n\n\t/**\n\t * The WORKSPACE databases this agent may query, by key.\n\t *\n\t * Register a database first with `ws.databases.create()`, which gives it its\n\t * key; attaching names that key in this agent's configuration. Naming it is\n\t * the grant: the database answers this agent's `sql_*` calls and no agent\n\t * that does not name it, and the agent's prompt lists it by key.\n\t *\n\t * ATTACHING PUBLISHES A VERSION, like a knowledge base: which databases an\n\t * agent reaches is part of its configuration, so the change is diffable and\n\t * reversible. Detaching takes effect on the agent's next query, including in\n\t * a conversation already under way.\n\t */\n\treadonly databases = {\n\t\t/** Attach one database by key. The server appends, so two attaches cannot\n\t\t * lose each other. A key that names no database is refused; one already\n\t\t * attached is a no-op. */\n\t\tattach: async (key: string): Promise<Agent> => {\n\t\t\tconst res = await this.#http.post<AgentData>(`${this.base}/databases`, { key });\n\t\t\tthis.snapshot = res;\n\t\t\treturn this;\n\t\t},\n\n\t\t/** Stop this agent querying one database. The database stays registered\n\t\t * for every other agent that names it. */\n\t\tdetach: async (key: string): Promise<Agent> => {\n\t\t\tconst res = await this.#http.delete<AgentData>(`${this.base}/databases/${encodeURIComponent(key)}`);\n\t\t\tif (res) this.snapshot = res;\n\t\t\treturn this;\n\t\t},\n\n\t\t/** The keys this agent may query, in configuration order. */\n\t\tlist: async (): Promise<string[]> => {\n\t\t\tconst current = this.snapshot ?? (await this.get());\n\t\t\treturn current.databases ?? [];\n\t\t},\n\t};\n\n\t// ------------------------------------------------------------ connections\n\n\t/**\n\t * The apps this agent uses: each a NAMED connection that says WHOSE ACCOUNT\n\t * it uses, built the way the portal's Add a connection screen asks.\n\t *\n\t * | built with | whose account | the person signs in |\n\t * |---|---|---|\n\t * | `Connection.creatorAccount(app, account)` | the agent creator's, from `ws.accounts.connect()` | once, and every conversation uses it |\n\t * | `Connection.endUserAccount(app)` | the end user's: each person talking to the agent | once each, remembered for them |\n\t *\n\t * ```ts\n\t * const { account: work } = await ws.accounts.connect({ app: App.GMAIL, nickname: 'Work' });\n\t * await agent.connections.add(Connection.creatorAccount(App.GMAIL, work, { name: 'work-gmail' }));\n\t * await agent.connections.add(Connection.endUserAccount(App.GOOGLE_CALENDAR));\n\t * ```\n\t *\n\t * A turn uses EXACTLY the account the setup names, and never another one.\n\t * There is no fallback to whichever account of that app happens to exist:\n\t * that fallback is what this replaced, and it meant reading an agent's code\n\t * told you nothing about whose mailbox it read.\n\t *\n\t * EVERY CHANGE PUBLISHES A VERSION, like `databases`: which accounts an\n\t * agent reaches is part of its configuration, so the change is diffable and\n\t * reversible. A conversation uses the connections of the version it runs.\n\t * The ACCOUNTS are not versioned: signing one in again reaches every agent\n\t * that names it, from the next turn.\n\t *\n\t * Removing a connection never touches the account. Disconnecting an account\n\t * is the other operation, on the account: `account.disconnect()`.\n\t */\n\treadonly connections = {\n\t\t/**\n\t\t * Add one connection. One call that publishes, not read-modify-write, so\n\t\t * two adds racing cannot lose each other.\n\t\t *\n\t\t * Takes what `Connection.creatorAccount()` or `Connection.endUserAccount()`\n\t\t * builds, or the same plain object. Refused, naming the problem, when the\n\t\t * name is taken on this agent (`connection_name_taken`), when the account\n\t\t * is of a different app (`account_app_mismatch`), or when no account has\n\t\t * that id (`account_not_found`).\n\t\t */\n\t\tadd: async (connection: Connection): Promise<Agent> => {\n\t\t\tconst res = await this.#http.post<AgentData>(`${this.base}/connections`, connectionForWire(connection));\n\t\t\tthis.snapshot = res;\n\t\t\treturn this;\n\t\t},\n\n\t\t/**\n\t\t * Point one connection at another account: `{ account }` for the agent\n\t\t * creator's (the `Account` you hold, or its id), or `{ endUser: true }`\n\t\t * for each end user's own. The name and the app stay; an account of a\n\t\t * different app is refused (`account_app_mismatch`).\n\t\t *\n\t\t * READ-MODIFY-WRITE, unlike `add` and `remove`, because there is no\n\t\t * route that changes one connection in place: this reads the current\n\t\t * version and publishes it again with the one connection changed. Two\n\t\t * changes racing can therefore lose one, so make them one after the\n\t\t * other. A name the agent does not have throws\n\t\t * (`connection_not_found`) before anything is sent.\n\t\t */\n\t\tchange: async (\n\t\t\tname: string,\n\t\t\tchange: { account: Account | string; endUser?: never } | { endUser: true; account?: never },\n\t\t): Promise<Agent> => {\n\t\t\t// Read FRESH, never from the snapshot. A stale list sent back whole\n\t\t\t// would silently undo whatever changed since it was read.\n\t\t\tconst current = (await this.get()).connections ?? [];\n\t\t\tif (!current.some((c) => c.name === name)) {\n\t\t\t\tthrow new AgentNavaError({\n\t\t\t\t\tmessage: `This agent has no connection named \"${name}\". It has: ${\n\t\t\t\t\t\tcurrent.map((c) => c.name).join(', ') || 'none'\n\t\t\t\t\t}.`,\n\t\t\t\t\tcode: 'connection_not_found',\n\t\t\t\t\tstatus: 404,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst whose =\n\t\t\t\tchange.endUser === true ? { endUser: true as const } : { account: accountIdOf(change.account as Account | string) };\n\t\t\t// Every other connection goes back exactly as it was read: this changes\n\t\t\t// one, and must not reinterpret the rest.\n\t\t\tconst connections = current.map((c) => (c.name === name ? { name: c.name, app: c.app, ...whose } : c));\n\t\t\tconst data = await this.#http.post<AgentData>(`${this.base}/versions`, { connections });\n\t\t\tthis.snapshot = data;\n\t\t\treturn this;\n\t\t},\n\n\t\t/** Remove one connection by name. Publishes a version. NEVER touches the\n\t\t * account: it stays connected for every other agent that names it, and\n\t\t * for this one if you add it back. */\n\t\tremove: async (name: string): Promise<Agent> => {\n\t\t\tconst res = await this.#http.delete<AgentData>(`${this.base}/connections/${encodeURIComponent(name)}`);\n\t\t\tif (res) this.snapshot = res;\n\t\t\treturn this;\n\t\t},\n\n\t\t/**\n\t\t * Each connection with the account it uses and whether that account works\n\t\t * now: DECLARED IS NOT CONNECTED. An agent can name an account nobody has\n\t\t * finished signing in to, or one that was disconnected since, and that is\n\t\t * the state a setup checklist has to show.\n\t\t *\n\t\t * Includes what an unpublished draft adds (`inDraft`) and removes\n\t\t * (`removedInDraft`), so it matches the portal.\n\t\t */\n\t\tlist: async (): Promise<ConnectionStatus[]> => {\n\t\t\tconst res = await this.#http.get<{ connections: ConnectionStatus[] }>(`${this.base}/connections`);\n\t\t\treturn res.connections ?? [];\n\t\t},\n\t};\n\n\t// ------------------------------------------------------ secrets, agent tier\n\n\t/**\n\t * Write secret VALUES to this agent's own scope: readable by this agent and\n\t * nothing else in the workspace, overriding a workspace secret of the same\n\t * name. Writing one twice replaces the value rather than failing, because\n\t * attaching means \"this is the credential now\".\n\t *\n\t * This used to POST the whole object to `/v1/agents/:id/bindings`, which\n\t * answers only to `{kind, decl}` and records a DECLARATION, never a value. So\n\t * the call 400'd, and had it not, it would have stored the fact that a secret\n\t * is wanted rather than the secret.\n\t */\n\tasync #applyBindings(bindings: Bindings): Promise<Agent> {\n\t\tfor (const [name, value] of Object.entries(bindings.secrets ?? {})) {\n\t\t\tconst mine = (await this.#http.get<{ secrets: { id: string; name: string; agentId?: string | null }[] }>(\n\t\t\t\t'/v1/secrets',\n\t\t\t\t{ agentId: this.id },\n\t\t\t)).secrets ?? [];\n\t\t\tconst existing = mine.find((s) => s.name === name && s.agentId);\n\t\t\tif (existing) await this.#http.patch(`/v1/secrets/${encodeURIComponent(existing.id)}`, { value });\n\t\t\telse await this.#http.post('/v1/secrets', { name, value, agentId: this.id });\n\t\t}\n\t\tconst data = await this.get();\n\t\tthis.snapshot = data;\n\t\treturn new Agent(this.#http, this.id, data);\n\t}\n\n\t/**\n\t * Give this agent secret values, so every conversation with it can use them.\n\t *\n\t * ```ts\n\t * await agent.attach({ secrets: { APOLLO_API_KEY: value } });\n\t * ```\n\t *\n\t * SECRETS ONLY, since 0.44. Accounts used to be attached here, and a turn\n\t * then had to guess which of the accounts attached and owned around it to\n\t * use. The agent's setup now names them: `agent.connections.add()`. One\n\t * handed in here is refused by name (`not_a_secret`) rather than dropped.\n\t *\n\t * A stored `Secret` is not attached to an agent either. It never was: one\n\t * was accepted here and nothing was done with it. Store one for the agent\n\t * with `ws.secrets.create({ name, value, agentId })`, or attach one of your\n\t * end user's to their conversation with `conversation.attach(secret)`.\n\t */\n\tasync attach(bindings: Bindings): Promise<Agent> {\n\t\tif (!isBindings(bindings)) {\n\t\t\tthrow new AgentNavaError({\n\t\t\t\tmessage:\n\t\t\t\t\t'agent.attach takes { secrets: { NAME: value } }. Accounts go in the agent\\'s setup ' +\n\t\t\t\t\t'(agent.connections.add), and a stored secret attaches to a conversation ' +\n\t\t\t\t\t'(conversation.attach).',\n\t\t\t\tcode: 'not_a_secret',\n\t\t\t\tstatus: 400,\n\t\t\t});\n\t\t}\n\t\trefuseConnections(bindings);\n\t\treturn this.#applyBindings(bindings);\n\t}\n\n\t// ----------------------------------------------------------- conversations\n\n\t/** Start a conversation. It pins the agent's version now and keeps it.\n\t *\n\t * Nothing about accounts is passed here: the version's connections name\n\t * them, and a connection to the end user's account uses the account of\n\t * the person named by `endUserId`. */\n\tasync start(options: StartOptions): Promise<Conversation> {\n\t\tconst endUserId = requireEndUserId(options?.endUserId);\n\t\t// Resolved BEFORE the launch: a Secret is named on the wire by the\n\t\t// declared NAME it fills, and a handle addressed by id may not know its\n\t\t// own yet. Anything that is not a Secret is refused here, by name.\n\t\tconst secretIds = await secretIdsOf(secretsIn(options.attach));\n\t\tconst bindings =\n\t\t\toptions.secrets || secretIds\n\t\t\t\t? {\n\t\t\t\t\t\t...(options.secrets && { secrets: options.secrets }),\n\t\t\t\t\t\t...(secretIds && { secretIds }),\n\t\t\t\t\t}\n\t\t\t\t: undefined;\n\t\tconst data = await this.#http.post<AgentConversationData>('/v1/conversations', {\n\t\t\tagentId: this.id,\n\t\t\t...(options.version !== undefined && { version: options.version }),\n\t\t\t...(options.parameters && { parameters: options.parameters }),\n\t\t\t// `sessionBindings`, NOT `secrets` at the top level.\n\t\t\t//\n\t\t\t// This sent them at the top level and the launch route reads\n\t\t\t// `body.sessionBindings`, so they were dropped in silence: the route's\n\t\t\t// own body type has no top-level `secrets` to read. A conversation\n\t\t\t// started with a credential began without it, and the first turn\n\t\t\t// failed somewhere else entirely.\n\t\t\t//\n\t\t\t// Third place this exact envelope mistake was found in one afternoon,\n\t\t\t// after `agent.bind` and `conversation.bind`. The shape of the bug is\n\t\t\t// always the same: the SDK agrees with itself, the route agrees with\n\t\t\t// itself, and nothing compares the two.\n\t\t\t...(bindings && { sessionBindings: bindings }),\n\t\t\t// Always present: requireEndUserId() above has already refused\n\t\t\t// anything that is not a non-empty string.\n\t\t\tuser: { id: endUserId },\n\t\t\t// ALWAYS a new conversation, even when a user is named.\n\t\t\t//\n\t\t\t// The route resumes that user's most recent conversation when it is\n\t\t\t// given an identity and not told otherwise. That default exists for\n\t\t\t// our own web app, where a page reload must not leave a trail of empty\n\t\t\t// conversations, and it is wrong for a method called `start`: a verb\n\t\t\t// that sometimes does not do the thing is worse than two verbs. It is\n\t\t\t// also ambiguous the moment a user has more than one conversation,\n\t\t\t// since it silently picks the newest.\n\t\t\t//\n\t\t\t// So the SDK does not rely on that default. `start` starts. To\n\t\t\t// continue a conversation, hold its id: `agent.conversation(id)`.\n\t\t\tfresh: true,\n\t\t});\n\t\treturn new Conversation(this.#http, data.id, data);\n\t}\n\n\t/**\n\t * Address one of this agent's conversations by id. No request.\n\t *\n\t * Here rather than on the workspace because a conversation belongs to an\n\t * agent. You already hold the agent: it is a constant in your own code, not\n\t * a per-row value, so naming it costs nothing and the ownership is visible.\n\t *\n\t * ```ts\n\t * await ws.agent(AGENT).conversation(row.conversationId).ask('carry on');\n\t * ```\n\t */\n\tconversation(conversationId: string): Conversation {\n\t\treturn new Conversation(this.#http, conversationId);\n\t}\n\n\t/**\n\t * This agent's most recent conversations, newest first.\n\t *\n\t * NOT ALL OF THEM, and the previous sentence here said \"every\", which was\n\t * wrong in the way that costs someone an afternoon. The server returns the\n\t * newest 50 unless you ask for more, and refuses to return more than 200 on\n\t * any single call (apps/api/src/state.ts listAgentSessions, and the Durable\n\t * Object twin beside it, clamp identically).\n\t *\n\t * There is no cursor on this route yet, so an agent with more than 200\n\t * conversations CANNOT be fully enumerated through this method. If you are\n\t * counting or exporting, do not build on it; that needs a paginated route we\n\t * have not added. `ws.endUser(id).conversations()` DOES have a cursor, if\n\t * the question is one person's history rather than one agent's.\n\t *\n\t * `endUser` narrows to one of YOUR end users, which is what you want for a\n\t * \"your conversations\" list. Leaving it out returns everyone's, so leave it\n\t * out only for an operator view.\n\t *\n\t * ```ts\n\t * const mine = await agent.conversations({ endUser: row.userId });\n\t * ```\n\t */\n\tasync conversations(options: { limit?: number; endUser?: string } = {}): Promise<Conversation[]> {\n\t\tconst res = await this.#http.get<{ conversations: AgentConversationData[] }>('/v1/conversations', {\n\t\t\tagentId: this.id,\n\t\t\t...(options.limit !== undefined && { limit: options.limit }),\n\t\t\t// One end user's history. Sending this used to be silently ignored on\n\t\t\t// this route, which answered with everyone's conversations, so an\n\t\t\t// application rendering \"your chats\" showed somebody else's.\n\t\t\t...(options.endUser !== undefined && { end_user_id: options.endUser }),\n\t\t});\n\t\treturn (res.conversations ?? []).map((c) => new Conversation(this.#http, c.id, c));\n\t}\n}\n\n/** The end user a conversation belongs to: a non-empty string, or a thrown error before any request. */\nfunction requireEndUserId(value: unknown): string {\n\t// Checked at RUNTIME as well as in the type: a JavaScript caller, or a\n\t// TypeScript one reading a nullable column, can still pass null, a number or\n\t// ''. Each used to start an ownerless conversation that looked fine.\n\tif (typeof value === 'string' && value.trim()) return value.trim();\n\tthrow new AgentNavaError({\n\t\tmessage: 'agent.start() needs endUserId: a non-empty string naming who the conversation is for (your user id, a visitor id, or a job name).',\n\t\tcode: 'end_user_required',\n\t\tstatus: 400,\n\t});\n}\n"]}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every app the platform can connect, as constants, so an app is picked from a
|
|
3
|
+
* list instead of typed by hand.
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { App, Connection } from '@cerebro-labs/agentnava-sdk';
|
|
7
|
+
*
|
|
8
|
+
* const { account, url } = await ws.accounts.connect({ app: App.GMAIL });
|
|
9
|
+
* await agent.connections.add(Connection.endUserAccount(App.GOOGLE_CALENDAR));
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* Each value is the app's id, and each name is that id in UPPER_SNAKE:
|
|
13
|
+
* `App.GOOGLE_CALENDAR === 'google-calendar'`. A plain string works anywhere
|
|
14
|
+
* one of these does, so an app the platform adds after your SDK version needs no
|
|
15
|
+
* upgrade: pass its id.
|
|
16
|
+
*/
|
|
17
|
+
export declare const App: {
|
|
18
|
+
readonly AIRTABLE: "airtable";
|
|
19
|
+
readonly APALEO: "apaleo";
|
|
20
|
+
readonly APOLLO: "apollo";
|
|
21
|
+
readonly ASANA: "asana";
|
|
22
|
+
readonly ATTIO: "attio";
|
|
23
|
+
readonly BAMBOOHR: "bamboohr";
|
|
24
|
+
readonly BASECAMP: "basecamp";
|
|
25
|
+
readonly BITBUCKET: "bitbucket";
|
|
26
|
+
readonly BLACKBAUD: "blackbaud";
|
|
27
|
+
readonly BOLDSIGN: "boldsign";
|
|
28
|
+
readonly BOX: "box";
|
|
29
|
+
readonly BREX: "brex";
|
|
30
|
+
readonly CAL: "cal";
|
|
31
|
+
readonly CALENDLY: "calendly";
|
|
32
|
+
readonly CANVA: "canva";
|
|
33
|
+
readonly CAPSULE_CRM: "capsule_crm";
|
|
34
|
+
readonly CLICKUP: "clickup";
|
|
35
|
+
readonly CONFLUENCE: "confluence";
|
|
36
|
+
readonly CONTENTFUL: "contentful";
|
|
37
|
+
readonly CROWDIN: "crowdin";
|
|
38
|
+
readonly DART: "dart";
|
|
39
|
+
readonly DATADOG: "datadog";
|
|
40
|
+
readonly DAYTONA: "daytona";
|
|
41
|
+
readonly DIALPAD: "dialpad";
|
|
42
|
+
readonly DISCORD: "discord";
|
|
43
|
+
readonly DISCORDBOT: "discordbot";
|
|
44
|
+
readonly DROPBOX: "dropbox";
|
|
45
|
+
readonly DUB: "dub";
|
|
46
|
+
readonly DYNAMICS365: "dynamics365";
|
|
47
|
+
readonly EVENTBRITE: "eventbrite";
|
|
48
|
+
readonly EXCEL: "excel";
|
|
49
|
+
readonly EXIST: "exist";
|
|
50
|
+
readonly FACEBOOK: "facebook";
|
|
51
|
+
readonly FATHOM: "fathom";
|
|
52
|
+
readonly FIGMA: "figma";
|
|
53
|
+
readonly FREEAGENT: "freeagent";
|
|
54
|
+
readonly FRESHBOOKS: "freshbooks";
|
|
55
|
+
readonly GITHUB: "github";
|
|
56
|
+
readonly GITLAB: "gitlab";
|
|
57
|
+
readonly GMAIL: "gmail";
|
|
58
|
+
readonly GONG: "gong";
|
|
59
|
+
readonly GOOGLEBIGQUERY: "googlebigquery";
|
|
60
|
+
readonly GOOGLEDOCS: "googledocs";
|
|
61
|
+
readonly GOOGLEMEET: "googlemeet";
|
|
62
|
+
readonly GOOGLEPHOTOS: "googlephotos";
|
|
63
|
+
readonly GOOGLESLIDES: "googleslides";
|
|
64
|
+
readonly GOOGLESUPER: "googlesuper";
|
|
65
|
+
readonly GOOGLETASKS: "googletasks";
|
|
66
|
+
readonly GOOGLE_ADS: "google-ads";
|
|
67
|
+
readonly GOOGLE_ANALYTICS: "google-analytics";
|
|
68
|
+
readonly GOOGLE_CALENDAR: "google-calendar";
|
|
69
|
+
readonly GOOGLE_CLASSROOM: "google_classroom";
|
|
70
|
+
readonly GOOGLE_DRIVE: "google-drive";
|
|
71
|
+
readonly GOOGLE_MAPS: "google_maps";
|
|
72
|
+
readonly GOOGLE_SEARCH_CONSOLE: "google_search_console";
|
|
73
|
+
readonly GOOGLE_SHEETS: "google-sheets";
|
|
74
|
+
readonly GORGIAS: "gorgias";
|
|
75
|
+
readonly GREENHOUSE: "greenhouse";
|
|
76
|
+
readonly GUMROAD: "gumroad";
|
|
77
|
+
readonly HARVEST: "harvest";
|
|
78
|
+
readonly HUBSPOT: "hubspot";
|
|
79
|
+
readonly HUGGING_FACE: "hugging_face";
|
|
80
|
+
readonly INSTAGRAM: "instagram";
|
|
81
|
+
readonly INTERCOM: "intercom";
|
|
82
|
+
readonly JIRA: "jira";
|
|
83
|
+
readonly KIT: "kit";
|
|
84
|
+
readonly LEVER: "lever";
|
|
85
|
+
readonly LINEAR: "linear";
|
|
86
|
+
readonly LINKEDIN: "linkedin";
|
|
87
|
+
readonly LINKHUT: "linkhut";
|
|
88
|
+
readonly MAILCHIMP: "mailchimp";
|
|
89
|
+
readonly META_ADS: "meta-ads";
|
|
90
|
+
readonly MICROSOFT_OUTLOOK: "microsoft-outlook";
|
|
91
|
+
readonly MICROSOFT_TEAMS: "microsoft-teams";
|
|
92
|
+
readonly MIRO: "miro";
|
|
93
|
+
readonly MONDAY: "monday";
|
|
94
|
+
readonly MONEYBIRD: "moneybird";
|
|
95
|
+
readonly MURAL: "mural";
|
|
96
|
+
readonly NOTEBOOK_LM: "notebook_lm";
|
|
97
|
+
readonly NOTION: "notion";
|
|
98
|
+
readonly OMNISEND: "omnisend";
|
|
99
|
+
readonly ONEDRIVE: "onedrive";
|
|
100
|
+
readonly PAGERDUTY: "pagerduty";
|
|
101
|
+
readonly PINTEREST: "pinterest";
|
|
102
|
+
readonly PINTEREST_ADS: "pinterest_ads";
|
|
103
|
+
readonly PRISMA: "prisma";
|
|
104
|
+
readonly PRODUCTBOARD: "productboard";
|
|
105
|
+
readonly PUSHBULLET: "pushbullet";
|
|
106
|
+
readonly QUICKBOOKS: "quickbooks";
|
|
107
|
+
readonly REDDIT: "reddit";
|
|
108
|
+
readonly REDDIT_ADS: "reddit_ads";
|
|
109
|
+
readonly ROAM: "roam";
|
|
110
|
+
readonly SALESFORCE: "salesforce";
|
|
111
|
+
readonly SEMRUSH: "semrush";
|
|
112
|
+
readonly SENTRY: "sentry";
|
|
113
|
+
readonly SERVICEM8: "servicem8";
|
|
114
|
+
readonly SHAREPOINT: "sharepoint";
|
|
115
|
+
readonly SHIPPO: "shippo";
|
|
116
|
+
readonly SHOPIFY: "shopify";
|
|
117
|
+
readonly SLACK: "slack";
|
|
118
|
+
readonly SLACKBOT: "slackbot";
|
|
119
|
+
readonly SPLITWISE: "splitwise";
|
|
120
|
+
readonly SQUARE: "square";
|
|
121
|
+
readonly STACK_EXCHANGE: "stack_exchange";
|
|
122
|
+
readonly STRIPE: "stripe";
|
|
123
|
+
readonly SUPABASE: "supabase";
|
|
124
|
+
readonly TICKETMASTER: "ticketmaster";
|
|
125
|
+
readonly TICKTICK: "ticktick";
|
|
126
|
+
readonly TIMELY: "timely";
|
|
127
|
+
readonly TODOIST: "todoist";
|
|
128
|
+
readonly TRELLO: "trello";
|
|
129
|
+
readonly TWITCH: "twitch";
|
|
130
|
+
readonly TYPEFORM: "typeform";
|
|
131
|
+
readonly WAKATIME: "wakatime";
|
|
132
|
+
readonly WEBEX: "webex";
|
|
133
|
+
readonly WHATSAPP: "whatsapp";
|
|
134
|
+
readonly WRIKE: "wrike";
|
|
135
|
+
readonly YANDEX: "yandex";
|
|
136
|
+
readonly YNAB: "ynab";
|
|
137
|
+
readonly YOUTUBE: "youtube";
|
|
138
|
+
readonly ZENDESK: "zendesk";
|
|
139
|
+
readonly ZEPLIN: "zeplin";
|
|
140
|
+
readonly ZOHO: "zoho";
|
|
141
|
+
readonly ZOHO_BIGIN: "zoho_bigin";
|
|
142
|
+
readonly ZOHO_BOOKS: "zoho_books";
|
|
143
|
+
readonly ZOHO_DESK: "zoho_desk";
|
|
144
|
+
readonly ZOHO_INVENTORY: "zoho_inventory";
|
|
145
|
+
readonly ZOHO_INVOICE: "zoho_invoice";
|
|
146
|
+
readonly ZOHO_MAIL: "zoho_mail";
|
|
147
|
+
readonly ZOOM: "zoom";
|
|
148
|
+
};
|
|
149
|
+
/**
|
|
150
|
+
* An app's id, as every `app` field takes it. One of `App`'s values
|
|
151
|
+
* autocompletes; any other string is accepted too, for an app newer than this
|
|
152
|
+
* SDK.
|
|
153
|
+
*/
|
|
154
|
+
export type AppId = (typeof App)[keyof typeof App] | (string & {});
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// GENERATED by scripts/regen-apps.mjs from packages/connections-catalog. Do not
|
|
2
|
+
// edit: run `bun run regen:apps`, then bump the version and relock.
|
|
3
|
+
// tests/apps-match-the-catalog.test.ts fails when this drifts from the catalog.
|
|
4
|
+
/**
|
|
5
|
+
* Every app the platform can connect, as constants, so an app is picked from a
|
|
6
|
+
* list instead of typed by hand.
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { App, Connection } from '@cerebro-labs/agentnava-sdk';
|
|
10
|
+
*
|
|
11
|
+
* const { account, url } = await ws.accounts.connect({ app: App.GMAIL });
|
|
12
|
+
* await agent.connections.add(Connection.endUserAccount(App.GOOGLE_CALENDAR));
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* Each value is the app's id, and each name is that id in UPPER_SNAKE:
|
|
16
|
+
* `App.GOOGLE_CALENDAR === 'google-calendar'`. A plain string works anywhere
|
|
17
|
+
* one of these does, so an app the platform adds after your SDK version needs no
|
|
18
|
+
* upgrade: pass its id.
|
|
19
|
+
*/
|
|
20
|
+
export const App = {
|
|
21
|
+
AIRTABLE: 'airtable',
|
|
22
|
+
APALEO: 'apaleo',
|
|
23
|
+
APOLLO: 'apollo',
|
|
24
|
+
ASANA: 'asana',
|
|
25
|
+
ATTIO: 'attio',
|
|
26
|
+
BAMBOOHR: 'bamboohr',
|
|
27
|
+
BASECAMP: 'basecamp',
|
|
28
|
+
BITBUCKET: 'bitbucket',
|
|
29
|
+
BLACKBAUD: 'blackbaud',
|
|
30
|
+
BOLDSIGN: 'boldsign',
|
|
31
|
+
BOX: 'box',
|
|
32
|
+
BREX: 'brex',
|
|
33
|
+
CAL: 'cal',
|
|
34
|
+
CALENDLY: 'calendly',
|
|
35
|
+
CANVA: 'canva',
|
|
36
|
+
CAPSULE_CRM: 'capsule_crm',
|
|
37
|
+
CLICKUP: 'clickup',
|
|
38
|
+
CONFLUENCE: 'confluence',
|
|
39
|
+
CONTENTFUL: 'contentful',
|
|
40
|
+
CROWDIN: 'crowdin',
|
|
41
|
+
DART: 'dart',
|
|
42
|
+
DATADOG: 'datadog',
|
|
43
|
+
DAYTONA: 'daytona',
|
|
44
|
+
DIALPAD: 'dialpad',
|
|
45
|
+
DISCORD: 'discord',
|
|
46
|
+
DISCORDBOT: 'discordbot',
|
|
47
|
+
DROPBOX: 'dropbox',
|
|
48
|
+
DUB: 'dub',
|
|
49
|
+
DYNAMICS365: 'dynamics365',
|
|
50
|
+
EVENTBRITE: 'eventbrite',
|
|
51
|
+
EXCEL: 'excel',
|
|
52
|
+
EXIST: 'exist',
|
|
53
|
+
FACEBOOK: 'facebook',
|
|
54
|
+
FATHOM: 'fathom',
|
|
55
|
+
FIGMA: 'figma',
|
|
56
|
+
FREEAGENT: 'freeagent',
|
|
57
|
+
FRESHBOOKS: 'freshbooks',
|
|
58
|
+
GITHUB: 'github',
|
|
59
|
+
GITLAB: 'gitlab',
|
|
60
|
+
GMAIL: 'gmail',
|
|
61
|
+
GONG: 'gong',
|
|
62
|
+
GOOGLEBIGQUERY: 'googlebigquery',
|
|
63
|
+
GOOGLEDOCS: 'googledocs',
|
|
64
|
+
GOOGLEMEET: 'googlemeet',
|
|
65
|
+
GOOGLEPHOTOS: 'googlephotos',
|
|
66
|
+
GOOGLESLIDES: 'googleslides',
|
|
67
|
+
GOOGLESUPER: 'googlesuper',
|
|
68
|
+
GOOGLETASKS: 'googletasks',
|
|
69
|
+
GOOGLE_ADS: 'google-ads',
|
|
70
|
+
GOOGLE_ANALYTICS: 'google-analytics',
|
|
71
|
+
GOOGLE_CALENDAR: 'google-calendar',
|
|
72
|
+
GOOGLE_CLASSROOM: 'google_classroom',
|
|
73
|
+
GOOGLE_DRIVE: 'google-drive',
|
|
74
|
+
GOOGLE_MAPS: 'google_maps',
|
|
75
|
+
GOOGLE_SEARCH_CONSOLE: 'google_search_console',
|
|
76
|
+
GOOGLE_SHEETS: 'google-sheets',
|
|
77
|
+
GORGIAS: 'gorgias',
|
|
78
|
+
GREENHOUSE: 'greenhouse',
|
|
79
|
+
GUMROAD: 'gumroad',
|
|
80
|
+
HARVEST: 'harvest',
|
|
81
|
+
HUBSPOT: 'hubspot',
|
|
82
|
+
HUGGING_FACE: 'hugging_face',
|
|
83
|
+
INSTAGRAM: 'instagram',
|
|
84
|
+
INTERCOM: 'intercom',
|
|
85
|
+
JIRA: 'jira',
|
|
86
|
+
KIT: 'kit',
|
|
87
|
+
LEVER: 'lever',
|
|
88
|
+
LINEAR: 'linear',
|
|
89
|
+
LINKEDIN: 'linkedin',
|
|
90
|
+
LINKHUT: 'linkhut',
|
|
91
|
+
MAILCHIMP: 'mailchimp',
|
|
92
|
+
META_ADS: 'meta-ads',
|
|
93
|
+
MICROSOFT_OUTLOOK: 'microsoft-outlook',
|
|
94
|
+
MICROSOFT_TEAMS: 'microsoft-teams',
|
|
95
|
+
MIRO: 'miro',
|
|
96
|
+
MONDAY: 'monday',
|
|
97
|
+
MONEYBIRD: 'moneybird',
|
|
98
|
+
MURAL: 'mural',
|
|
99
|
+
NOTEBOOK_LM: 'notebook_lm',
|
|
100
|
+
NOTION: 'notion',
|
|
101
|
+
OMNISEND: 'omnisend',
|
|
102
|
+
ONEDRIVE: 'onedrive',
|
|
103
|
+
PAGERDUTY: 'pagerduty',
|
|
104
|
+
PINTEREST: 'pinterest',
|
|
105
|
+
PINTEREST_ADS: 'pinterest_ads',
|
|
106
|
+
PRISMA: 'prisma',
|
|
107
|
+
PRODUCTBOARD: 'productboard',
|
|
108
|
+
PUSHBULLET: 'pushbullet',
|
|
109
|
+
QUICKBOOKS: 'quickbooks',
|
|
110
|
+
REDDIT: 'reddit',
|
|
111
|
+
REDDIT_ADS: 'reddit_ads',
|
|
112
|
+
ROAM: 'roam',
|
|
113
|
+
SALESFORCE: 'salesforce',
|
|
114
|
+
SEMRUSH: 'semrush',
|
|
115
|
+
SENTRY: 'sentry',
|
|
116
|
+
SERVICEM8: 'servicem8',
|
|
117
|
+
SHAREPOINT: 'sharepoint',
|
|
118
|
+
SHIPPO: 'shippo',
|
|
119
|
+
SHOPIFY: 'shopify',
|
|
120
|
+
SLACK: 'slack',
|
|
121
|
+
SLACKBOT: 'slackbot',
|
|
122
|
+
SPLITWISE: 'splitwise',
|
|
123
|
+
SQUARE: 'square',
|
|
124
|
+
STACK_EXCHANGE: 'stack_exchange',
|
|
125
|
+
STRIPE: 'stripe',
|
|
126
|
+
SUPABASE: 'supabase',
|
|
127
|
+
TICKETMASTER: 'ticketmaster',
|
|
128
|
+
TICKTICK: 'ticktick',
|
|
129
|
+
TIMELY: 'timely',
|
|
130
|
+
TODOIST: 'todoist',
|
|
131
|
+
TRELLO: 'trello',
|
|
132
|
+
TWITCH: 'twitch',
|
|
133
|
+
TYPEFORM: 'typeform',
|
|
134
|
+
WAKATIME: 'wakatime',
|
|
135
|
+
WEBEX: 'webex',
|
|
136
|
+
WHATSAPP: 'whatsapp',
|
|
137
|
+
WRIKE: 'wrike',
|
|
138
|
+
YANDEX: 'yandex',
|
|
139
|
+
YNAB: 'ynab',
|
|
140
|
+
YOUTUBE: 'youtube',
|
|
141
|
+
ZENDESK: 'zendesk',
|
|
142
|
+
ZEPLIN: 'zeplin',
|
|
143
|
+
ZOHO: 'zoho',
|
|
144
|
+
ZOHO_BIGIN: 'zoho_bigin',
|
|
145
|
+
ZOHO_BOOKS: 'zoho_books',
|
|
146
|
+
ZOHO_DESK: 'zoho_desk',
|
|
147
|
+
ZOHO_INVENTORY: 'zoho_inventory',
|
|
148
|
+
ZOHO_INVOICE: 'zoho_invoice',
|
|
149
|
+
ZOHO_MAIL: 'zoho_mail',
|
|
150
|
+
ZOOM: 'zoom',
|
|
151
|
+
};
|
|
152
|
+
//# sourceMappingURL=apps.generated.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apps.generated.js","sourceRoot":"","sources":["../src/apps.generated.ts"],"names":[],"mappings":"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","sourcesContent":["// GENERATED by scripts/regen-apps.mjs from packages/connections-catalog. Do not\n// edit: run `bun run regen:apps`, then bump the version and relock.\n// tests/apps-match-the-catalog.test.ts fails when this drifts from the catalog.\n\n/**\n * Every app the platform can connect, as constants, so an app is picked from a\n * list instead of typed by hand.\n *\n * ```ts\n * import { App, Connection } from '@cerebro-labs/agentnava-sdk';\n *\n * const { account, url } = await ws.accounts.connect({ app: App.GMAIL });\n * await agent.connections.add(Connection.endUserAccount(App.GOOGLE_CALENDAR));\n * ```\n *\n * Each value is the app's id, and each name is that id in UPPER_SNAKE:\n * `App.GOOGLE_CALENDAR === 'google-calendar'`. A plain string works anywhere\n * one of these does, so an app the platform adds after your SDK version needs no\n * upgrade: pass its id.\n */\nexport const App = {\n\tAIRTABLE: 'airtable',\n\tAPALEO: 'apaleo',\n\tAPOLLO: 'apollo',\n\tASANA: 'asana',\n\tATTIO: 'attio',\n\tBAMBOOHR: 'bamboohr',\n\tBASECAMP: 'basecamp',\n\tBITBUCKET: 'bitbucket',\n\tBLACKBAUD: 'blackbaud',\n\tBOLDSIGN: 'boldsign',\n\tBOX: 'box',\n\tBREX: 'brex',\n\tCAL: 'cal',\n\tCALENDLY: 'calendly',\n\tCANVA: 'canva',\n\tCAPSULE_CRM: 'capsule_crm',\n\tCLICKUP: 'clickup',\n\tCONFLUENCE: 'confluence',\n\tCONTENTFUL: 'contentful',\n\tCROWDIN: 'crowdin',\n\tDART: 'dart',\n\tDATADOG: 'datadog',\n\tDAYTONA: 'daytona',\n\tDIALPAD: 'dialpad',\n\tDISCORD: 'discord',\n\tDISCORDBOT: 'discordbot',\n\tDROPBOX: 'dropbox',\n\tDUB: 'dub',\n\tDYNAMICS365: 'dynamics365',\n\tEVENTBRITE: 'eventbrite',\n\tEXCEL: 'excel',\n\tEXIST: 'exist',\n\tFACEBOOK: 'facebook',\n\tFATHOM: 'fathom',\n\tFIGMA: 'figma',\n\tFREEAGENT: 'freeagent',\n\tFRESHBOOKS: 'freshbooks',\n\tGITHUB: 'github',\n\tGITLAB: 'gitlab',\n\tGMAIL: 'gmail',\n\tGONG: 'gong',\n\tGOOGLEBIGQUERY: 'googlebigquery',\n\tGOOGLEDOCS: 'googledocs',\n\tGOOGLEMEET: 'googlemeet',\n\tGOOGLEPHOTOS: 'googlephotos',\n\tGOOGLESLIDES: 'googleslides',\n\tGOOGLESUPER: 'googlesuper',\n\tGOOGLETASKS: 'googletasks',\n\tGOOGLE_ADS: 'google-ads',\n\tGOOGLE_ANALYTICS: 'google-analytics',\n\tGOOGLE_CALENDAR: 'google-calendar',\n\tGOOGLE_CLASSROOM: 'google_classroom',\n\tGOOGLE_DRIVE: 'google-drive',\n\tGOOGLE_MAPS: 'google_maps',\n\tGOOGLE_SEARCH_CONSOLE: 'google_search_console',\n\tGOOGLE_SHEETS: 'google-sheets',\n\tGORGIAS: 'gorgias',\n\tGREENHOUSE: 'greenhouse',\n\tGUMROAD: 'gumroad',\n\tHARVEST: 'harvest',\n\tHUBSPOT: 'hubspot',\n\tHUGGING_FACE: 'hugging_face',\n\tINSTAGRAM: 'instagram',\n\tINTERCOM: 'intercom',\n\tJIRA: 'jira',\n\tKIT: 'kit',\n\tLEVER: 'lever',\n\tLINEAR: 'linear',\n\tLINKEDIN: 'linkedin',\n\tLINKHUT: 'linkhut',\n\tMAILCHIMP: 'mailchimp',\n\tMETA_ADS: 'meta-ads',\n\tMICROSOFT_OUTLOOK: 'microsoft-outlook',\n\tMICROSOFT_TEAMS: 'microsoft-teams',\n\tMIRO: 'miro',\n\tMONDAY: 'monday',\n\tMONEYBIRD: 'moneybird',\n\tMURAL: 'mural',\n\tNOTEBOOK_LM: 'notebook_lm',\n\tNOTION: 'notion',\n\tOMNISEND: 'omnisend',\n\tONEDRIVE: 'onedrive',\n\tPAGERDUTY: 'pagerduty',\n\tPINTEREST: 'pinterest',\n\tPINTEREST_ADS: 'pinterest_ads',\n\tPRISMA: 'prisma',\n\tPRODUCTBOARD: 'productboard',\n\tPUSHBULLET: 'pushbullet',\n\tQUICKBOOKS: 'quickbooks',\n\tREDDIT: 'reddit',\n\tREDDIT_ADS: 'reddit_ads',\n\tROAM: 'roam',\n\tSALESFORCE: 'salesforce',\n\tSEMRUSH: 'semrush',\n\tSENTRY: 'sentry',\n\tSERVICEM8: 'servicem8',\n\tSHAREPOINT: 'sharepoint',\n\tSHIPPO: 'shippo',\n\tSHOPIFY: 'shopify',\n\tSLACK: 'slack',\n\tSLACKBOT: 'slackbot',\n\tSPLITWISE: 'splitwise',\n\tSQUARE: 'square',\n\tSTACK_EXCHANGE: 'stack_exchange',\n\tSTRIPE: 'stripe',\n\tSUPABASE: 'supabase',\n\tTICKETMASTER: 'ticketmaster',\n\tTICKTICK: 'ticktick',\n\tTIMELY: 'timely',\n\tTODOIST: 'todoist',\n\tTRELLO: 'trello',\n\tTWITCH: 'twitch',\n\tTYPEFORM: 'typeform',\n\tWAKATIME: 'wakatime',\n\tWEBEX: 'webex',\n\tWHATSAPP: 'whatsapp',\n\tWRIKE: 'wrike',\n\tYANDEX: 'yandex',\n\tYNAB: 'ynab',\n\tYOUTUBE: 'youtube',\n\tZENDESK: 'zendesk',\n\tZEPLIN: 'zeplin',\n\tZOHO: 'zoho',\n\tZOHO_BIGIN: 'zoho_bigin',\n\tZOHO_BOOKS: 'zoho_books',\n\tZOHO_DESK: 'zoho_desk',\n\tZOHO_INVENTORY: 'zoho_inventory',\n\tZOHO_INVOICE: 'zoho_invoice',\n\tZOHO_MAIL: 'zoho_mail',\n\tZOOM: 'zoom',\n} as const;\n\n/**\n * An app's id, as every `app` field takes it. One of `App`'s values\n * autocompletes; any other string is accepted too, for an app newer than this\n * SDK.\n */\nexport type AppId = (typeof App)[keyof typeof App] | (string & {});\n"]}
|
package/attach.d.ts
CHANGED
|
@@ -1,23 +1,36 @@
|
|
|
1
|
-
import type { Connection } from './connection.ts';
|
|
2
1
|
import { Secret } from './secret.ts';
|
|
3
2
|
import type { Bindings } from './types.ts';
|
|
3
|
+
/** What the launch and the conversation's bindings route take: secret VALUES
|
|
4
|
+
* by declared name, and stored secrets by id. */
|
|
5
|
+
export interface SessionBindings {
|
|
6
|
+
secrets?: Record<string, string>;
|
|
7
|
+
secretIds?: Record<string, string>;
|
|
8
|
+
}
|
|
4
9
|
/**
|
|
5
|
-
*
|
|
6
|
-
* wire speaks.
|
|
10
|
+
* Distinguish `attach({ secrets })` from `attach(secret)`.
|
|
7
11
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* only
|
|
12
|
+
* Structural rather than `instanceof`, so a plain object built anywhere is
|
|
13
|
+
* still recognised. A Secret always has an `id`; a Bindings object does not.
|
|
14
|
+
* `connections` is recognised too, only so it can be refused by name below.
|
|
11
15
|
*/
|
|
12
|
-
export declare function
|
|
16
|
+
export declare function isBindings(what: unknown): what is Bindings;
|
|
17
|
+
/** Refuse `{ connections }`. A JavaScript caller still holding 0.43 code would
|
|
18
|
+
* otherwise have it dropped in silence, and the agent would answer without the
|
|
19
|
+
* account it was plainly given. */
|
|
20
|
+
export declare function refuseConnections(bindings: Bindings): void;
|
|
13
21
|
/**
|
|
14
|
-
*
|
|
22
|
+
* Check that everything handed to `attach` is a Secret, and hand back the list.
|
|
23
|
+
*
|
|
24
|
+
* BY `instanceof`, not by duck-typing: a Secret addressed with `ws.secret(id)`
|
|
25
|
+
* has no `name` until it reads one, so "has a name" answers wrongly for exactly
|
|
26
|
+
* the handles that need it most.
|
|
15
27
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
28
|
+
* Refused rather than ignored. Silently dropping an unrecognised attachment is
|
|
29
|
+
* how a conversation starts without the credential its caller plainly
|
|
30
|
+
* attached, and the failure then appears one layer down as a tool that cannot
|
|
31
|
+
* authenticate.
|
|
19
32
|
*/
|
|
20
|
-
export declare function
|
|
33
|
+
export declare function secretsIn(what: Secret | Secret[] | undefined): Secret[];
|
|
21
34
|
/**
|
|
22
35
|
* Turn stored secrets into the `{ DECLARED_NAME: secretId }` map the wire
|
|
23
36
|
* speaks.
|
|
@@ -33,17 +46,3 @@ export declare function isBindings(what: unknown): what is Bindings;
|
|
|
33
46
|
* you addressed by id has to read it, and that read is the only request here.
|
|
34
47
|
*/
|
|
35
48
|
export declare function secretIdsOf(what: Secret | Secret[] | undefined): Promise<Record<string, string> | undefined>;
|
|
36
|
-
/** What a caller may hand to `attach`, or to `start({ attach })`. */
|
|
37
|
-
export type Attachable = Connection | Secret;
|
|
38
|
-
/**
|
|
39
|
-
* Split a mixed list into the accounts and the credentials.
|
|
40
|
-
*
|
|
41
|
-
* BY `instanceof`, not by duck-typing. A `Connection` addressed with
|
|
42
|
-
* `ws.connection(id)` has no `provider` until it reads one, and a `Secret` from
|
|
43
|
-
* `ws.secret(id)` has no `name`, so "has a provider" and "has a name" both
|
|
44
|
-
* answer wrongly for exactly the handles that need splitting most.
|
|
45
|
-
*/
|
|
46
|
-
export declare function splitAttachments(what: Attachable | Attachable[] | undefined): {
|
|
47
|
-
connections: Connection[];
|
|
48
|
-
secrets: Secret[];
|
|
49
|
-
};
|