primitive-functions 0.3.0-alpha.1 → 0.3.0-alpha.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 (2) hide show
  1. package/index.d.ts +249 -13
  2. package/package.json +1 -1
package/index.d.ts CHANGED
@@ -94,7 +94,64 @@ export type FunctionTrigger =
94
94
  * attribution, never the principal the code runs as. `runKey` is the key
95
95
  * the admin's start named, or null (#3562).
96
96
  */
97
- | { kind: "manual"; userId: string; runKey: string | null };
97
+ | { kind: "manual"; userId: string; runKey: string | null }
98
+ /**
99
+ * An agent turn called this function as one of its tools.
100
+ *
101
+ * `ctx.user` is the turn's initiator, whose `access` gate the call
102
+ * passed, and `ctx.tool` carries the session's ids, members and
103
+ * variables. `callId` is the same on every attempt of the call, so use
104
+ * it as an idempotency key. `toolName` is the declared tool name, which
105
+ * may differ from the function's key.
106
+ */
107
+ | {
108
+ kind: "tool";
109
+ sessionId: string;
110
+ turnId: string;
111
+ callId: string;
112
+ toolName: string;
113
+ }
114
+ /** An agent turn asked this function for its turn context. */
115
+ | { kind: "context"; sessionId: string; turnId: string }
116
+ /** An agent turn asked this function for the history to send the model. */
117
+ | { kind: "history"; sessionId: string; turnId: string };
118
+
119
+ /**
120
+ * The agent session a tool call belongs to — `ctx.tool`, set only when
121
+ * `ctx.trigger.kind === "tool"`.
122
+ *
123
+ * Variables and members describe the session; they grant nothing. Check what
124
+ * `ctx.user` (the turn's initiator) may do before acting for them.
125
+ */
126
+ export interface FunctionToolContext {
127
+ readonly sessionId: string;
128
+ /** The session's document, which holds its messages. */
129
+ readonly documentId: string;
130
+ readonly turnId: string;
131
+ /** The call's id, the same on every attempt: an idempotency key. */
132
+ readonly callId: string;
133
+ /** The tool's declared name. */
134
+ readonly toolName: string;
135
+ /** The session's owner. */
136
+ readonly ownerUserId: string;
137
+ /** The session's members by role, besides the owner. */
138
+ readonly members: {
139
+ readonly viewerUserIds: string[];
140
+ readonly participantUserIds: string[];
141
+ };
142
+ /** The session's variables, set when it was created. */
143
+ readonly variables: Record<string, unknown>;
144
+ /**
145
+ * Attach an app-only artifact to this call's row, replacing any earlier
146
+ * one. The model never sees it; your app reads it from the call's row —
147
+ * `artifact`, or, for one over 64 KiB of JSON or past the agent's
148
+ * `maxRowBytes`, the blob on the session's document named by
149
+ * `artifactBlobId`. At most 4 MiB of JSON: a larger value rejects with
150
+ * `AGENT_ARTIFACT_TOO_LARGE`, and a call that already has its result with
151
+ * `AGENT_CALL_NOT_RUNNING`.
152
+ */
153
+ attachArtifact(value: unknown): Promise<void>;
154
+ }
98
155
 
99
156
  /** The result shape of an operation that answers in response headers. */
100
157
  export interface HeaderResult {
@@ -143,6 +200,23 @@ export interface FunctionApi {
143
200
  "sessionId": string | number;
144
201
  body: unknown;
145
202
  }): Promise<any>;
203
+ /** `agentSessions.answer` — POST /agent-sessions/{sessionId}/calls/{callId}/answer. Answer a paused agent turn's call */
204
+ "answer"(args: {
205
+ "sessionId": string | number;
206
+ "callId": string | number;
207
+ body: unknown;
208
+ }): Promise<any>;
209
+ /** `agentSessions.attachArtifact` — POST /agent-sessions/{sessionId}/calls/{callId}/artifact. Attach an artifact to a running agent tool call (ctx.tool.attachArtifact) */
210
+ "attachArtifact"(args: {
211
+ "sessionId": string | number;
212
+ "callId": string | number;
213
+ body: unknown;
214
+ }): Promise<any>;
215
+ /** `agentSessions.cancel` — POST /agent-sessions/{sessionId}/cancel. Cancel an agent session's active turn */
216
+ "cancel"(args: {
217
+ "sessionId": string | number;
218
+ body: unknown;
219
+ }): Promise<any>;
146
220
  /** `agentSessions.create` — POST /agent-sessions. Create an agent session (ctx.agents.createSession) */
147
221
  "create"(args: {
148
222
  body: unknown;
@@ -163,6 +237,11 @@ export interface FunctionApi {
163
237
  "limit"?: string | number | boolean;
164
238
  "cursor"?: string | number | boolean;
165
239
  }): Promise<any>;
240
+ /** `agentSessions.recordEvent` — POST /agent-sessions/{sessionId}/events. Record an event in an agent session (ctx.agents.recordEvent) */
241
+ "recordEvent"(args: {
242
+ "sessionId": string | number;
243
+ body: unknown;
244
+ }): Promise<any>;
166
245
  /** `agentSessions.removeMember` — DELETE /agent-sessions/{sessionId}/members/{userId}. Remove a member from an agent session */
167
246
  "removeMember"(args: {
168
247
  "sessionId": string | number;
@@ -173,6 +252,11 @@ export interface FunctionApi {
173
252
  "sessionId": string | number;
174
253
  body: unknown;
175
254
  }): Promise<any>;
255
+ /** `agentSessions.send` — POST /agent-sessions/{sessionId}/messages. Send a message to an agent session */
256
+ "send"(args: {
257
+ "sessionId": string | number;
258
+ body: unknown;
259
+ }): Promise<any>;
176
260
  };
177
261
  "analytics": {
178
262
  /** `analytics.cohortRetention` — GET /analytics/cohort-retention. Cohort retention metrics */
@@ -421,6 +505,12 @@ export interface FunctionApi {
421
505
  "limit"?: string | number | boolean;
422
506
  "cursor"?: string | number | boolean;
423
507
  }): Promise<any>;
508
+ /** `collections.listForUser` — GET /users/{userId}/collections. List the collections an app user is a direct member of */
509
+ "listForUser"(args: {
510
+ "userId": string | number;
511
+ "limit"?: string | number | boolean;
512
+ "cursor"?: string | number | boolean;
513
+ }): Promise<any>;
424
514
  /** `collections.listPendingInvitations` — GET /collections/{collectionId}/pending-invitations. List a collection's pending invitations */
425
515
  "listPendingInvitations"(args: {
426
516
  "collectionId": string | number;
@@ -954,10 +1044,26 @@ export interface FunctionApi {
954
1044
  "limit"?: string | number | boolean;
955
1045
  "cursor"?: string | number | boolean;
956
1046
  }): Promise<any>;
1047
+ /** `documents.listOwnedByUser` — GET /users/{userId}/owned-documents. List the documents an app user owns */
1048
+ "listOwnedByUser"(args: {
1049
+ "userId": string | number;
1050
+ "limit"?: string | number | boolean;
1051
+ "cursor"?: string | number | boolean;
1052
+ "tag"?: string | number | boolean;
1053
+ "includeRoot"?: string | number | boolean;
1054
+ "forward"?: string | number | boolean;
1055
+ }): Promise<any>;
957
1056
  /** `documents.listPendingInvitations` — GET /documents/{documentId}/pending-invitations. List a document's pending (deferred) invitations */
958
1057
  "listPendingInvitations"(args: {
959
1058
  "documentId": string | number;
960
1059
  }): Promise<any>;
1060
+ /** `documents.listSharedWithUser` — GET /users/{userId}/shared-documents. List the documents directly shared with an app user */
1061
+ "listSharedWithUser"(args: {
1062
+ "userId": string | number;
1063
+ "limit"?: string | number | boolean;
1064
+ "cursor"?: string | number | boolean;
1065
+ "tag"?: string | number | boolean;
1066
+ }): Promise<any>;
961
1067
  /** `documents.listSnapshots` — GET /documents/{documentId}/snapshots. List a large document's snapshot builds, newest first */
962
1068
  "listSnapshots"(args: {
963
1069
  "documentId": string | number;
@@ -976,7 +1082,7 @@ export interface FunctionApi {
976
1082
  "documentFormat"?: string | number | boolean;
977
1083
  body: unknown;
978
1084
  }): Promise<any>;
979
- /** `documents.records.bulk` — POST /documents/{documentId}/records/bulk. Apply an atomic multi-model record blob to a document (create/patch/delete) */
1085
+ /** `documents.records.bulk` — POST /documents/{documentId}/records/bulk. Apply an atomic multi-model record blob to a document (create/patch/delete/upsert) */
980
1086
  "bulk"(args: {
981
1087
  "documentId": string | number;
982
1088
  "documentFormat"?: string | number | boolean;
@@ -1101,6 +1207,19 @@ export interface FunctionApi {
1101
1207
  "functionKey": string | number;
1102
1208
  body?: unknown;
1103
1209
  }): Promise<any>;
1210
+ /** `functions.listRunSteps` — GET /functions/runs/{runId}/steps. List a function run's steps, oldest first */
1211
+ "listRunSteps"(args: {
1212
+ "runId": string | number;
1213
+ }): Promise<any>;
1214
+ /** `functions.listRuns` — GET /functions/runs. List the caller's own function runs */
1215
+ "listRuns"(args?: {
1216
+ "functionKey"?: string | number | boolean;
1217
+ "contextDocId"?: string | number | boolean;
1218
+ "status"?: string | number | boolean;
1219
+ "limit"?: string | number | boolean;
1220
+ "cursor"?: string | number | boolean;
1221
+ "forward"?: string | number | boolean;
1222
+ }): Promise<any>;
1104
1223
  /** `functions.logs` — GET /functions/{functionKey}/logs. List a server function's invocation logs, newest first */
1105
1224
  "logs"(args: {
1106
1225
  "functionKey": string | number;
@@ -1341,6 +1460,11 @@ export interface FunctionApi {
1341
1460
  "userId": string | number;
1342
1461
  body: unknown;
1343
1462
  }): Promise<any>;
1463
+ /** `users.setProfile` — PATCH /users/{userId}/profile. Set a user's display name and avatar */
1464
+ "setProfile"(args: {
1465
+ "userId": string | number;
1466
+ body: unknown;
1467
+ }): Promise<any>;
1344
1468
  /** `users.setRole` — PUT /users/{userId}/role. Set a user's app role */
1345
1469
  "setRole"(args: {
1346
1470
  "userId": string | number;
@@ -1594,17 +1718,28 @@ export interface DocumentQueryOptions {
1594
1718
  * `model` is NOT a member: the handle already names it and assigns it last, so
1595
1719
  * a multi-model blob stays on the raw `ctx.api.documents.records.bulk`
1596
1720
  * operation rather than becoming a second way to say the same thing.
1721
+ *
1722
+ * `upsert` addresses the record by a unique constraint the model declares:
1723
+ * `data` carries every field of `constraint`, the record holding that key
1724
+ * gets `data` merged into it, and when none does one is created (at `id`
1725
+ * when given, else at a new id) with the model's defaults.
1597
1726
  */
1598
1727
  export type DocumentBatchOp<TRow> =
1599
1728
  | { action: "create" | "patch"; id: string; data: Partial<TRow>; precondition?: Record<string, unknown> }
1600
- | { action: "delete"; id: string; precondition?: Record<string, unknown> };
1729
+ | { action: "delete"; id: string; precondition?: Record<string, unknown> }
1730
+ | { action: "upsert"; constraint: string; id?: string; data: Partial<TRow>; precondition?: Record<string, unknown> };
1601
1731
 
1602
- /** What `documents.records.bulk` answers: the blob's aggregate effect. */
1732
+ /**
1733
+ * What `documents.records.bulk` answers: the blob's aggregate effect.
1734
+ * `upserted` has one entry per `upsert` op, in input order: the op's
1735
+ * `index`, the record's `id`, and whether the op `created` it.
1736
+ */
1603
1737
  export interface DocumentBulkResult {
1604
1738
  applied: number;
1605
1739
  added: Array<{ model: string; id: string }>;
1606
1740
  updated: Array<{ model: string; id: string }>;
1607
1741
  deleted: number;
1742
+ upserted: Array<{ index: number; model: string; id: string; created: boolean }>;
1608
1743
  }
1609
1744
 
1610
1745
  export interface DocumentModelHandle<TRow> {
@@ -1776,6 +1911,44 @@ export interface AgentSessionInfo {
1776
1911
  members: { viewers: string[]; participants: string[] };
1777
1912
  /** The invoking user's standing on the session. */
1778
1913
  role: "owner" | "participant" | "viewer" | "admin";
1914
+ /**
1915
+ * The session's status, decided from the session object (never the
1916
+ * session row): the active turn's phase, else how the last turn ended.
1917
+ */
1918
+ status: AgentSessionStatus;
1919
+ /** The active turn, or null when none runs. */
1920
+ turn: AgentSessionTurnSummary | null;
1921
+ }
1922
+
1923
+ /** A session's status: `idle` between turns, the active turn's phase, or how the last turn ended. */
1924
+ export type AgentSessionStatus =
1925
+ | "idle"
1926
+ | "thinking"
1927
+ | "running_tool"
1928
+ | "awaiting_answer"
1929
+ | "failed"
1930
+ | "expired"
1931
+ | "cancelled";
1932
+
1933
+ /** The active turn of a session, as `ctx.agents.getSession` answers it. */
1934
+ export interface AgentSessionTurnSummary {
1935
+ turnId: string;
1936
+ /** The member whose messages started the turn. */
1937
+ initiatorUserId: string;
1938
+ /** ISO-8601; null until the turn has started. */
1939
+ startedAt: string | null;
1940
+ /** `model` while a model call runs, `tools` while server tools run, `paused` while a call waits on a person. */
1941
+ phase: "model" | "tools" | "paused" | "draining";
1942
+ /** Model rounds begun. */
1943
+ rounds: number;
1944
+ /** ISO-8601; until when the turn's runner holds it. */
1945
+ leaseUntil: string | null;
1946
+ /** Who may answer the turn's calls, as pinned at the turn's start. */
1947
+ answeredBy: string | null;
1948
+ /** The calls waiting on a person and until when, or null. */
1949
+ pause: { callIds: string[]; since: string; expiresAt: string } | null;
1950
+ /** A transition being made, or null. */
1951
+ pending: { kind: "answer" | "end" } | null;
1779
1952
  }
1780
1953
 
1781
1954
  /** One session in `ctx.agents.listSessions` — #3805. */
@@ -1811,6 +1984,26 @@ export interface AgentSessionListPage {
1811
1984
  nextCursor?: string;
1812
1985
  }
1813
1986
 
1987
+ /** What `ctx.agents.recordEvent` takes — #3807. */
1988
+ export interface AgentSessionEvent {
1989
+ /** An event kind the session's agent declares. */
1990
+ kind: string;
1991
+ /** The payload, validated against the kind's schema; at most 64 KiB of JSON. */
1992
+ data: unknown;
1993
+ /** Your own id for the event, 1 to 128 characters: a repeat with the same content records nothing. */
1994
+ eventId?: string;
1995
+ /** A call of this session (`call_<ULID>`) the event is about. */
1996
+ refersTo?: string;
1997
+ }
1998
+
1999
+ /** What `ctx.agents.recordEvent` answers — #3807. */
2000
+ export interface AgentSessionEventResult {
2001
+ messageId: string;
2002
+ seq: number;
2003
+ /** Set when the `eventId` was already recorded with this content: the first event's ids. */
2004
+ duplicate?: boolean;
2005
+ }
2006
+
1814
2007
  /** One agent's client tools, by name: each one's `input` and `output` (#3798). */
1815
2008
  export type AgentClientTools<K extends AgentKeys> = PromptSchemas[K] extends {
1816
2009
  agent: { clientTools: infer T };
@@ -1833,22 +2026,32 @@ export type PromptOutput<K extends string> = K extends keyof PromptSchemas
1833
2026
  : unknown;
1834
2027
 
1835
2028
  /**
1836
- * Why a prompt's own answer was refused — #3330. Never set on a PROVIDER
1837
- * failure, which is what makes "the model returned the wrong shape"
1838
- * distinguishable from "the model failed".
2029
+ * Why a prompt's own answer was refused or incomplete — #3330, #4146. Never
2030
+ * set on a PROVIDER failure, which is what makes "the model returned the wrong
2031
+ * shape" distinguishable from "the model failed".
2032
+ *
2033
+ * `PROMPT_OUTPUT_TRUNCATED` is the answer cut off at the output token limit
2034
+ * (`truncated` is `true` beside it): a declared-JSON answer that stopped
2035
+ * before it was finished, whatever its shape, or a completion that spent the
2036
+ * whole limit and came back empty. Raise the config's `maxTokens` rather
2037
+ * than rewording the prompt.
1839
2038
  */
1840
2039
  export type PromptOutputErrorCode =
1841
2040
  | "PROMPT_OUTPUT_NOT_JSON"
1842
- | "PROMPT_OUTPUT_SCHEMA_VIOLATION";
2041
+ | "PROMPT_OUTPUT_SCHEMA_VIOLATION"
2042
+ | "PROMPT_OUTPUT_TRUNCATED";
1843
2043
 
1844
2044
  /**
1845
2045
  * Every code the envelope's `errorCode` can carry — #3663, #3813.
1846
2046
  *
1847
- * `PROMPT_UPSTREAM_TIMEOUT` is the one that is NOT about the prompt's own
1848
- * answer: the provider ran out of time, so there was no answer to refuse. It
1849
- * is the only provider failure that sets `errorCode` at all, which is what
1850
- * leaves "the model returned the wrong shape" distinguishable from "the model
1851
- * failed" while still letting a caller retry the one failure worth retrying.
2047
+ * `PROMPT_UPSTREAM_TIMEOUT` and `PROMPT_UPSTREAM_REJECTED` are NOT about the
2048
+ * prompt's own answer: the provider ran out of time, or refused the request as
2049
+ * invalid (`upstreamStatus` 400 — a setting the model does not support, such
2050
+ * as a reasoning level, with the provider's message in `error`), so there was
2051
+ * no answer to refuse. They are the only provider failures that set
2052
+ * `errorCode`, which is what leaves "the model returned the wrong shape"
2053
+ * distinguishable from "the model failed" while still letting a caller retry
2054
+ * a timeout and fix the config for a refusal.
1852
2055
  *
1853
2056
  * `PROMPT_CRITERIA_INVALID` is the run that never reached a provider: a
1854
2057
  * decisions run's `variables.criteria` was refused before the call, so
@@ -1861,6 +2064,7 @@ export type PromptOutputErrorCode =
1861
2064
  export type PromptRunErrorCode =
1862
2065
  | PromptOutputErrorCode
1863
2066
  | "PROMPT_UPSTREAM_TIMEOUT"
2067
+ | "PROMPT_UPSTREAM_REJECTED"
1864
2068
  | "PROMPT_CRITERIA_INVALID"
1865
2069
  | "PROMPT_STRICT_OUTPUT_SCHEMA_MISSING";
1866
2070
 
@@ -1874,6 +2078,12 @@ export interface PromptRunSuccess<TParsed> {
1874
2078
  errorCode?: null;
1875
2079
  metrics?: Record<string, unknown>;
1876
2080
  configId: string;
2081
+ /**
2082
+ * `true` when the provider stopped at the output token limit
2083
+ * (`maxTokens`) before the answer was finished; absent otherwise. On
2084
+ * Gemini, reasoning tokens count against the same limit.
2085
+ */
2086
+ truncated?: true;
1877
2087
  }
1878
2088
 
1879
2089
  /**
@@ -1902,6 +2112,12 @@ export interface PromptRunFailure {
1902
2112
  * empty — so a number here is always the provider's own.
1903
2113
  */
1904
2114
  upstreamStatus?: number;
2115
+ /**
2116
+ * `true` when the provider stopped at the output token limit
2117
+ * (`maxTokens`) before the answer was finished; absent otherwise. On
2118
+ * Gemini, reasoning tokens count against the same limit.
2119
+ */
2120
+ truncated?: true;
1905
2121
  }
1906
2122
 
1907
2123
  /** The envelope for a key whose declaration says nothing about its output. */
@@ -1919,6 +2135,12 @@ export interface PromptRunOpenResult {
1919
2135
  configId: string;
1920
2136
  /** The upstream provider's HTTP status on a provider failure — #3663. */
1921
2137
  upstreamStatus?: number;
2138
+ /**
2139
+ * `true` when the provider stopped at the output token limit
2140
+ * (`maxTokens`) before the answer was finished; absent otherwise. On
2141
+ * Gemini, reasoning tokens count against the same limit.
2142
+ */
2143
+ truncated?: true;
1922
2144
  }
1923
2145
 
1924
2146
  /**
@@ -2074,6 +2296,12 @@ export interface FunctionContext {
2074
2296
  /** The HTTP caller, or null for a webhook or cron fire. */
2075
2297
  user: FunctionUser | null;
2076
2298
  trigger: FunctionTrigger;
2299
+ /**
2300
+ * The agent session this tool call belongs to, when an agent turn called
2301
+ * the function as a tool (`ctx.trigger.kind === "tool"`); otherwise
2302
+ * absent.
2303
+ */
2304
+ tool?: FunctionToolContext;
2077
2305
  /**
2078
2306
  * Which RUNTIME is hosting this code — #3482.
2079
2307
  *
@@ -2213,6 +2441,13 @@ export interface FunctionContext {
2213
2441
  * `AGENT_SESSION_NOT_FOUND`. Both have the same origin rule as
2214
2442
  * `createSession`. Renaming, deleting and changing members are the
2215
2443
  * owner's, from a client.
2444
+ *
2445
+ * `recordEvent` (#3807) records an event in one of the invoking user's
2446
+ * sessions, as that member: they must be its owner or a participant, and
2447
+ * the origin rule is `createSession`'s. The kind must be one the agent
2448
+ * declares (`AGENT_EVENT_KIND_UNKNOWN`) and the data must match its schema
2449
+ * (`AGENT_EVENT_INVALID`). An event never starts a turn; the model reads
2450
+ * it in a later turn.
2216
2451
  */
2217
2452
  agents: {
2218
2453
  createSession<K extends SessionAgentKeys>(
@@ -2220,6 +2455,7 @@ export interface FunctionContext {
2220
2455
  ): Promise<AgentSessionCreateResult>;
2221
2456
  getSession(sessionId: string): Promise<AgentSessionInfo>;
2222
2457
  listSessions(options?: AgentSessionListOptions): Promise<AgentSessionListPage>;
2458
+ recordEvent(sessionId: string, event: AgentSessionEvent): Promise<AgentSessionEventResult>;
2223
2459
  };
2224
2460
  /**
2225
2461
  * The value of one app secret, under a `secret:<NAME>` grant (#3183).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "primitive-functions",
3
- "version": "0.3.0-alpha.1",
3
+ "version": "0.3.0-alpha.2",
4
4
  "description": "The module a Primitive server function imports. Supplied by the platform at invoke time; reserved here so the name is ours before the runtime lands.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "Primitive LLC",