palbase 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai/index.js +2 -2
- package/dist/backend/engine.js +2 -2
- package/dist/backend/env.js +1 -1
- package/dist/backend/index.js +9 -9
- package/dist/backend/stack.js +1 -1
- package/dist/backend/test.js +2 -2
- package/dist/chunks/5VTGMNPL.js +20 -0
- package/dist/chunks/{ZBOJEH7K.js → BO5KR2EQ.js} +2 -2
- package/dist/chunks/{PJVWGUIT.js → BRBCWPR3.js} +1 -1
- package/dist/chunks/DB3SIBKB.js +2 -0
- package/dist/chunks/EGNEXFTZ.js +2 -0
- package/dist/chunks/{HEXIIGWS.js → FZ3MQOVA.js} +2 -2
- package/dist/chunks/{SU7BP6VF.js → JSJVV43D.js} +1 -1
- package/dist/chunks/K6RRNI23.js +4 -0
- package/dist/chunks/{KDSWK3XW.js → KDWDPSL2.js} +1 -1
- package/dist/chunks/P4Z5E6ZI.js +2 -0
- package/dist/chunks/PDOHT46N.js +2 -0
- package/dist/chunks/PGPQGKH2.js +18 -0
- package/dist/chunks/{G3BK7L3J.js → RBA6V3UO.js} +2 -2
- package/dist/chunks/{X3MTLJRV.js → RO5Y5YU4.js} +1 -1
- package/dist/chunks/{BKVU4I5R.js → TUGRIOFX.js} +2 -2
- package/dist/chunks/WEI32SAJ.js +13 -0
- package/dist/chunks/{5ZJCEQV5.js → WINBISC2.js} +3 -3
- package/dist/chunks/Z5JVQNAZ.js +2 -0
- package/dist/cli.js +121 -120
- package/dist/refuse/ai.js +1 -1
- package/dist/refuse/backend.js +1 -1
- package/dist/refuse/server.js +1 -1
- package/dist/server/index.js +2 -2
- package/dist/server/testing.js +2 -2
- package/dist/web/index.js +2 -2
- package/dist/web/palbe.js +2 -2
- package/dist/web/paywall.js +2 -2
- package/dist/web/ssr.js +2 -2
- package/dist/web/vite.js +2 -2
- package/package.json +2 -2
- package/types/ai/src/ai.d.ts +44 -15
- package/types/ai/src/chats.d.ts +442 -12
- package/types/ai/src/index.d.ts +4 -4
- package/types/ai/src/tools.d.ts +158 -21
- package/types/backend/src/bootstrap.d.ts +8 -0
- package/types/backend/src/container.d.ts +9 -0
- package/types/backend/src/database.d.ts +17 -2
- package/types/backend/src/engine.d.ts +2 -0
- package/types/backend/src/gateways.d.ts +19 -0
- package/types/backend/src/index.d.ts +1 -0
- package/types/backend/src/runtime.d.ts +12 -0
- package/types/backend/src/testing/unit.d.ts +3 -1
- package/types/internal/src/chat.d.ts +168 -3
- package/types/internal/src/modules/ai.d.ts +1305 -57
- package/types/internal/src/modules/auth.d.ts +14 -2
- package/types/internal/src/modules/events.d.ts +2 -2
- package/types/internal/src/modules/machines.d.ts +57 -1
- package/types/internal/src/modules/notify.d.ts +6 -6
- package/types/internal/src/modules/purchases.d.ts +357 -13
- package/types/internal/src/modules/realtime.d.ts +36 -0
- package/types/internal/src/modules/stores.d.ts +259 -22
- package/types/internal/src/transport.d.ts +5 -0
- package/types/server/src/auth/jwt.d.ts +1 -6
- package/types/web/src/auth.d.ts +15 -4
- package/types/web/src/backends.d.ts +1 -1
- package/types/web/src/chat.d.ts +215 -4
- package/types/web/src/client.d.ts +28 -0
- package/types/web/src/gateways.d.ts +4 -3
- package/types/web/src/index.d.ts +3 -2
- package/types/web/src/session.d.ts +11 -1
- package/types/web/src/voice.d.ts +36 -0
- package/dist/chunks/3ALGILOX.js +0 -2
- package/dist/chunks/AIIKXCWN.js +0 -2
- package/dist/chunks/ELEE7XO2.js +0 -18
- package/dist/chunks/G7E26S3Y.js +0 -13
- package/dist/chunks/H2EPK74V.js +0 -20
- package/dist/chunks/JS3TTUHS.js +0 -2
- package/dist/chunks/L3NTI4AZ.js +0 -2
- package/dist/chunks/LEBVOSG6.js +0 -4
- package/dist/chunks/OIA7KLRW.js +0 -2
package/types/ai/src/tools.d.ts
CHANGED
|
@@ -25,12 +25,58 @@ export interface ChatContext {
|
|
|
25
25
|
metadata: Record<string, string>;
|
|
26
26
|
/** Ended when the platform stops waiting for the answer. */
|
|
27
27
|
signal: AbortSignal;
|
|
28
|
+
/**
|
|
29
|
+
* The app's instance of a provider — a class a module of the app lists in
|
|
30
|
+
* its providers, built once by its container with its constructor's
|
|
31
|
+
* dependencies — as a constructor's parameter of that type is given it:
|
|
32
|
+
* ctx.inject(Orders). The app that serves the call gives it; a class no
|
|
33
|
+
* module provides is refused, by name.
|
|
34
|
+
*/
|
|
35
|
+
inject<T extends object>(provider: abstract new (...args: never[]) => T): T;
|
|
28
36
|
}
|
|
29
37
|
export interface ToolContext extends ChatContext {
|
|
30
38
|
/** The call's id: the same call is the same id, whatever copy of the machine it reaches. */
|
|
31
39
|
callId: string;
|
|
40
|
+
/** The turn the call is made in: its own response's id — a subagent's call's too. */
|
|
41
|
+
turnId: string;
|
|
42
|
+
/**
|
|
43
|
+
* The run that made the call: the agent's own, or a subagent's at work. A
|
|
44
|
+
* tool that answers later — it asks a person, and gives their answer to
|
|
45
|
+
* whoever asked — answers that run: chats.sendToSubagent(chatId, runId, …).
|
|
46
|
+
*/
|
|
47
|
+
runId: string;
|
|
48
|
+
/** The subagent that made the call, by its name; null: the agent itself. */
|
|
49
|
+
subagent: string | null;
|
|
50
|
+
}
|
|
51
|
+
/** The message that opened a turn, as the backend that defines its agent is told of it. */
|
|
52
|
+
export interface TurnMessage {
|
|
53
|
+
id: string;
|
|
54
|
+
clientId: string;
|
|
55
|
+
/** The member who wrote it; null: the project's server. */
|
|
56
|
+
author: string | null;
|
|
57
|
+
authorName: string;
|
|
58
|
+
text: string;
|
|
59
|
+
delivery: 'next' | 'now' | (string & {});
|
|
60
|
+
/**
|
|
61
|
+
* Its writer's labels for it (chats.send({ metadata })) — what an app's
|
|
62
|
+
* choice for the turn rides on: a model, an effort, the files it names. A
|
|
63
|
+
* member may write them: the caller's word, not an authority.
|
|
64
|
+
*/
|
|
65
|
+
metadata: Record<string, string>;
|
|
66
|
+
}
|
|
67
|
+
/** What the backend that defines an agent is told of the turn: the chat's context, and what opened the turn. */
|
|
68
|
+
export interface AgentContext extends ChatContext {
|
|
69
|
+
/** The message that opened the turn; null: a turn of no message (the chat's voice, its goal). */
|
|
70
|
+
message: TurnMessage | null;
|
|
71
|
+
/**
|
|
72
|
+
* The chat's goal the agent is defined for (chats.goal.set): every turn the
|
|
73
|
+
* goal opens is the agent defined now. Null: a turn of a message.
|
|
74
|
+
*/
|
|
75
|
+
goal: {
|
|
76
|
+
objective: string;
|
|
77
|
+
rubric: string;
|
|
78
|
+
} | null;
|
|
32
79
|
}
|
|
33
|
-
export type AgentContext = ChatContext;
|
|
34
80
|
export interface BackendToolOptions<S extends StandardSchema> {
|
|
35
81
|
/** What the agent calls it by: letters, digits, _ and -, starting with a letter, at most 64. */
|
|
36
82
|
name: string;
|
|
@@ -43,9 +89,11 @@ export interface BackendToolOptions<S extends StandardSchema> {
|
|
|
43
89
|
* (`{ mediaType, bytes }`), or a list of them — 4 MiB at most in all. A
|
|
44
90
|
* throw is the tool's failure: a ToolError's message (or the framework's
|
|
45
91
|
* own refusals', NotFound('…')) is told to the agent, anything else as
|
|
46
|
-
* "The tool failed".
|
|
92
|
+
* "The tool failed". A tool answers within 110 seconds; one whose work
|
|
93
|
+
* takes longer returns ai.deferred() at once — a chat's call waits, and the
|
|
94
|
+
* project's server answers it later with chats.answer(ctx.chatId, ctx.callId, output).
|
|
47
95
|
*/
|
|
48
|
-
run(input: Infer<S>, ctx: ToolContext): ToolResult | Promise<ToolResult>;
|
|
96
|
+
run(input: Infer<S>, ctx: ToolContext): ToolResult | DeferredAnswer | Promise<ToolResult | DeferredAnswer>;
|
|
49
97
|
/** Every call waits for a person's yes (a member of the chat, or the server). */
|
|
50
98
|
approval?: boolean;
|
|
51
99
|
/** The project's machine it runs on (default backend). */
|
|
@@ -60,12 +108,34 @@ export interface BackendTool<S extends StandardSchema = StandardSchema> {
|
|
|
60
108
|
readonly parameters: Record<string, unknown>;
|
|
61
109
|
readonly approval: boolean;
|
|
62
110
|
readonly machine?: string;
|
|
63
|
-
/** The run, its input checked first: what the framework answers the platform's call with. */
|
|
64
|
-
call(input: unknown, ctx: ToolContext): Promise<
|
|
65
|
-
output: ToolContent[];
|
|
66
|
-
is_error: boolean;
|
|
67
|
-
}>;
|
|
111
|
+
/** The run, its input checked first: what the framework answers the platform's call with — an answer, or one to come (deferred). */
|
|
112
|
+
call(input: unknown, ctx: ToolContext): Promise<ToolAnswer>;
|
|
68
113
|
}
|
|
114
|
+
/** A backend tool's answer as the platform takes it: now (output), or later — the project's server gives it (chats.answer). */
|
|
115
|
+
export type ToolAnswer = {
|
|
116
|
+
output: ToolContent[];
|
|
117
|
+
is_error: boolean;
|
|
118
|
+
} | {
|
|
119
|
+
deferred: true;
|
|
120
|
+
expires_in_seconds?: number;
|
|
121
|
+
};
|
|
122
|
+
declare const DEFERRED: unique symbol;
|
|
123
|
+
/** What a backend tool's run returns when its answer comes later: ai.deferred(). */
|
|
124
|
+
export interface DeferredAnswer {
|
|
125
|
+
readonly [DEFERRED]: true;
|
|
126
|
+
/** How long the call waits for its answer: a minute to a day; left out, an hour. */
|
|
127
|
+
readonly expiresInSeconds?: number;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* The answer comes later: a chat's call waits for it — the turn too, as for
|
|
131
|
+
* an app's tool — and the project's server gives it with chats.answer(chatId,
|
|
132
|
+
* callId, output) within expiresInSeconds (a minute to a day; an hour). A
|
|
133
|
+
* call nobody answers by then is told to the agent as unanswered; no member
|
|
134
|
+
* answers it. A one-shot answer (ai.ask with tools) waits for no call.
|
|
135
|
+
*/
|
|
136
|
+
export declare function deferred(options?: {
|
|
137
|
+
expiresInSeconds?: number;
|
|
138
|
+
}): DeferredAnswer;
|
|
69
139
|
export interface ClientToolOptions<S extends StandardSchema> {
|
|
70
140
|
name: string;
|
|
71
141
|
description: string;
|
|
@@ -94,7 +164,23 @@ export interface McpToolRef {
|
|
|
94
164
|
only?: string[];
|
|
95
165
|
approval?: boolean;
|
|
96
166
|
}
|
|
97
|
-
|
|
167
|
+
/** One of the platform's own tools, by name. */
|
|
168
|
+
export type PlatformToolName = 'web.search' | 'web.fetch' | 'workspace.fetch_archive';
|
|
169
|
+
/**
|
|
170
|
+
* One of the platform's own tools: web.search (the web searched), web.fetch
|
|
171
|
+
* (a page of it read), workspace.fetch_archive (an archive at a URL unpacked
|
|
172
|
+
* into the chat's workspace — a workspace's chat has it already). The
|
|
173
|
+
* agent's alone: its subagents work with the agent's; a one-shot answer has none.
|
|
174
|
+
*/
|
|
175
|
+
export interface PlatformToolRef {
|
|
176
|
+
source: 'platform';
|
|
177
|
+
name: PlatformToolName;
|
|
178
|
+
}
|
|
179
|
+
export type Tool = BackendTool<StandardSchema> | ClientTool | HttpsToolRef | McpToolRef | PlatformToolRef;
|
|
180
|
+
/** How hard a model thinks; which rungs a model takes is its catalogue entry's (ai.models(): chat[].efforts). */
|
|
181
|
+
export type Effort = NonNullable<AgentDefinition['effort']>;
|
|
182
|
+
/** Whether a model's reasoning is shown in the chat's stream (thinking parts) or not asked for at all. */
|
|
183
|
+
export type Thinking = NonNullable<AgentDefinition['thinking']>;
|
|
98
184
|
export interface SubagentDefinition {
|
|
99
185
|
/** Unique among the agent's subagents. */
|
|
100
186
|
name: string;
|
|
@@ -105,6 +191,12 @@ export interface SubagentDefinition {
|
|
|
105
191
|
tools?: Tool[];
|
|
106
192
|
/** The turn fails if this subagent's part fails. */
|
|
107
193
|
required?: boolean;
|
|
194
|
+
/** Left out: the agent's, when it runs on the agent's model (another model's rungs mean other things). */
|
|
195
|
+
effort?: Effort;
|
|
196
|
+
/** The window, in tokens, it works in. Left out: the agent's, when it runs on the agent's model. */
|
|
197
|
+
contextWindow?: number;
|
|
198
|
+
/** Left out: the agent's. Its reasoning is never in the chat's stream: only the turn's own is. */
|
|
199
|
+
thinking?: Thinking;
|
|
108
200
|
}
|
|
109
201
|
/** What an agent is for a turn. */
|
|
110
202
|
export interface AgentDefinitionInput {
|
|
@@ -114,8 +206,22 @@ export interface AgentDefinitionInput {
|
|
|
114
206
|
tools?: Tool[];
|
|
115
207
|
/** 16 at most. */
|
|
116
208
|
subagents?: SubagentDefinition[];
|
|
117
|
-
/**
|
|
209
|
+
/**
|
|
210
|
+
* How many tool calls a turn makes at most (1–10 000, the engine's own bound): past it the agent is told it has no
|
|
211
|
+
* tools left and answers. What a turn spends is its budget's to bound (chats.send({ budget })), not this.
|
|
212
|
+
*/
|
|
118
213
|
maxToolCalls?: number;
|
|
214
|
+
/** How hard the model thinks (none … max). Left out: the platform's. */
|
|
215
|
+
effort?: Effort;
|
|
216
|
+
/**
|
|
217
|
+
* The window, in tokens, the turn works in: the model's standard one unless said; more is billed as its provider
|
|
218
|
+
* bills it (ai.models(): chat[].context_window and max_input_tokens).
|
|
219
|
+
*/
|
|
220
|
+
contextWindow?: number;
|
|
221
|
+
/** visible: the model's reasoning is in the chat's stream, as thinking parts (the turn's own); hidden: not asked for. Left out: the platform's. */
|
|
222
|
+
thinking?: Thinking;
|
|
223
|
+
/** The language of the person the turn works for, a BCP 47 tag (tr, en-GB): the model writes to them in it on every step, and so do its subagents. */
|
|
224
|
+
language?: string;
|
|
119
225
|
}
|
|
120
226
|
/** What a backend's agent is for one turn. */
|
|
121
227
|
export type TurnDefinition = AgentDefinitionInput;
|
|
@@ -131,6 +237,24 @@ export interface BackendAgent {
|
|
|
131
237
|
tools: BackendTool[];
|
|
132
238
|
}>;
|
|
133
239
|
}
|
|
240
|
+
/** What one clone or one push of a chat's workspace asks a repository's token with: an ai.repo's token, ai.repoTokens' give. */
|
|
241
|
+
export interface RepoTokenContext {
|
|
242
|
+
/** The repository's name in the project (ai.repos.put). */
|
|
243
|
+
repo: string;
|
|
244
|
+
/** The GitHub repository, owner/name. */
|
|
245
|
+
repository: string;
|
|
246
|
+
/** Ended when the platform stops waiting for the token. */
|
|
247
|
+
signal: AbortSignal;
|
|
248
|
+
/**
|
|
249
|
+
* The app's instance of a provider, as a tool's run is given it
|
|
250
|
+
* (ChatContext.inject): a token a service of the app's mints — its GitHub
|
|
251
|
+
* App's, its sealed credentials' — from the container of the app that
|
|
252
|
+
* serves the ask. A class no module provides is refused, by name.
|
|
253
|
+
*/
|
|
254
|
+
inject<T extends object>(provider: abstract new (...args: never[]) => T): T;
|
|
255
|
+
}
|
|
256
|
+
/** What gives a repository's token when no ai.repo of its name was made: ai.repoTokens(give). */
|
|
257
|
+
export type RepoTokens = (ctx: RepoTokenContext) => string | null | undefined | Promise<string | null | undefined>;
|
|
134
258
|
/** A repository a chat's workspace works in, whose tokens the backend gives (ai.repo). */
|
|
135
259
|
export interface BackendRepo {
|
|
136
260
|
readonly kind: 'repo';
|
|
@@ -141,18 +265,16 @@ export interface BackendRepo {
|
|
|
141
265
|
/** The project's machine that gives its tokens (default backend). */
|
|
142
266
|
readonly machine?: string;
|
|
143
267
|
/** A token for one clone or one push of it: asked at each — a GitHub App's installation token, minted then. */
|
|
144
|
-
token(ctx:
|
|
145
|
-
repo: string;
|
|
146
|
-
repository: string;
|
|
147
|
-
signal: AbortSignal;
|
|
148
|
-
}): Promise<string>;
|
|
268
|
+
token(ctx: RepoTokenContext): Promise<string>;
|
|
149
269
|
}
|
|
150
270
|
/** What this process declared, for the framework to serve. */
|
|
151
271
|
export interface DeclaredAI {
|
|
152
272
|
tools: Map<string, BackendTool>;
|
|
153
273
|
agents: Map<string, BackendAgent>;
|
|
154
274
|
repos: Map<string, BackendRepo>;
|
|
155
|
-
/**
|
|
275
|
+
/** The tokens of a repository put by name at run time, which no ai.repo of this process names. */
|
|
276
|
+
repoTokens?: RepoTokens;
|
|
277
|
+
/** Names declared twice (tool:<name>, agent:<name>, repoTokens): the framework refuses to start with one. */
|
|
156
278
|
twice: Set<string>;
|
|
157
279
|
}
|
|
158
280
|
/**
|
|
@@ -181,17 +303,32 @@ export declare function backendRepo(options: {
|
|
|
181
303
|
repository: string;
|
|
182
304
|
defaultBranch?: string;
|
|
183
305
|
machine?: string;
|
|
184
|
-
token: (ctx:
|
|
185
|
-
repo: string;
|
|
186
|
-
repository: string;
|
|
187
|
-
signal: AbortSignal;
|
|
188
|
-
}) => string | Promise<string>;
|
|
306
|
+
token: (ctx: RepoTokenContext) => string | Promise<string>;
|
|
189
307
|
}): BackendRepo;
|
|
308
|
+
/**
|
|
309
|
+
* The tokens of the project's repositories put by name at run time
|
|
310
|
+
* (ai.repos.put(name, { repository, backend })) — one a product makes for
|
|
311
|
+
* itself — which no ai.repo of this backend names: each clone and each push
|
|
312
|
+
* of a chat's workspace asks this machine, and give answers with a token for
|
|
313
|
+
* that one operation, or null for a repository it gives none for (the
|
|
314
|
+
* workspace is refused it). An ai.repo of the name answers for its own
|
|
315
|
+
* repository first. Given once, at a module's top level.
|
|
316
|
+
*/
|
|
317
|
+
export declare function repoTokens(give: RepoTokens): void;
|
|
190
318
|
export declare function backendAgent(name: string, define: (ctx: AgentContext) => TurnDefinition | Promise<TurnDefinition>, options?: {
|
|
191
319
|
machine?: string;
|
|
192
320
|
}): BackendAgent;
|
|
321
|
+
/** A backend's agent (an ai.agent's value) — its name and machine — or undefined for anything else. */
|
|
322
|
+
export declare function backendAgentOf(v: unknown): {
|
|
323
|
+
readonly name: string;
|
|
324
|
+
readonly machine?: string;
|
|
325
|
+
} | undefined;
|
|
193
326
|
/** A tool as the platform takes it (ToolRef). */
|
|
194
327
|
export declare function toolRef(t: Tool, what: string): ToolRef;
|
|
328
|
+
/** The most tool calls a turn or a one-shot answer makes: the engine's own bound. */
|
|
329
|
+
export declare const MAX_TOOL_CALLS = 10000;
|
|
330
|
+
/** A definition's bound on its tool calls, refused here as the module would refuse it. */
|
|
331
|
+
export declare function maxToolCallsOf(n: unknown, what: string): number;
|
|
195
332
|
/** A definition as the platform takes it (AgentDefinition). */
|
|
196
333
|
export declare function definitionOf(d: AgentDefinitionInput, what: string): AgentDefinition;
|
|
197
334
|
export {};
|
|
@@ -70,3 +70,11 @@ export declare class MigrationRunEnded extends Error {
|
|
|
70
70
|
readonly code: number;
|
|
71
71
|
constructor(code: number);
|
|
72
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* The app's CORS joined to the origins of its project's web apps, as the
|
|
75
|
+
* platform starts it with them (PALBASE_WEB_ORIGINS, comma-separated): a
|
|
76
|
+
* browser on one of them may call it without the app naming it. Any origin
|
|
77
|
+
* ("*") stays any. An origin CORS cannot hold (an address in brackets) is
|
|
78
|
+
* left out, and said.
|
|
79
|
+
*/
|
|
80
|
+
export declare function withWebOrigins(own: CorsOptions | undefined, given: string | undefined, warn?: (message: string) => void): CorsOptions | undefined;
|
|
@@ -14,6 +14,8 @@ export declare class Container {
|
|
|
14
14
|
private readonly owner;
|
|
15
15
|
private readonly defs;
|
|
16
16
|
private readonly instances;
|
|
17
|
+
/** The classes the modules list as providers (not controllers): what ctx.inject may be given. */
|
|
18
|
+
private readonly providers;
|
|
17
19
|
/** Construction order: dependencies before their dependents. */
|
|
18
20
|
readonly order: object[];
|
|
19
21
|
readonly controllers: {
|
|
@@ -41,6 +43,13 @@ export declare class Container {
|
|
|
41
43
|
* a route's @Resolve, by its controller — under a constructor's rules.
|
|
42
44
|
*/
|
|
43
45
|
dependencyOf<T extends object>(consumer: abstract new (...args: never[]) => object, dep: abstract new (...args: never[]) => T, at: string): T;
|
|
46
|
+
/**
|
|
47
|
+
* The built instance of a provider, asked for by code no module owns — a
|
|
48
|
+
* tool's run, an agent's function (ctx.inject) — so any module's provider,
|
|
49
|
+
* exported or not: the class itself, or the one provider that extends it,
|
|
50
|
+
* as a constructor's parameter of that type finds it. `at` says who asked.
|
|
51
|
+
*/
|
|
52
|
+
provider<T extends object>(cls: abstract new (...args: never[]) => T, at: string): T;
|
|
44
53
|
private reachable;
|
|
45
54
|
private target;
|
|
46
55
|
/** onStart() of every instance, in construction order; a throw stops the boot after the started ones are shut down. */
|
|
@@ -54,7 +54,7 @@ export interface DatabaseConfig {
|
|
|
54
54
|
* nothing — `palbase db:plan` and `db:status` ask the app's own Palgres what a
|
|
55
55
|
* start would do and what the database's ledger says.
|
|
56
56
|
*/
|
|
57
|
-
export type MigrateMode = 'start' | 'complete' | 'rollback' | 'plan' | 'status';
|
|
57
|
+
export type MigrateMode = 'start' | 'complete' | 'rollback' | 'plan' | 'status' | 'types';
|
|
58
58
|
/** What the deploy asked of this run: a migration step, or nothing (serve). */
|
|
59
59
|
export declare function migrateModeOf(env: Record<string, string | undefined>): MigrateMode | undefined;
|
|
60
60
|
/**
|
|
@@ -106,9 +106,24 @@ export type MigrationExit = 0 | 1 | 75;
|
|
|
106
106
|
* given to such a machine with its migrations on is refused as its release
|
|
107
107
|
* starts, and the release's rollback then ends — the machine is not held by it.
|
|
108
108
|
*/
|
|
109
|
-
export declare function migrateWithoutDatabase(mode: MigrateMode): MigrationExit
|
|
109
|
+
export declare function migrateWithoutDatabase(mode: MigrateMode): Promise<MigrationExit>;
|
|
110
|
+
/**
|
|
111
|
+
* The app's tables as types (palbase db:types): each table's row, insert, unique keys and relations both ways —
|
|
112
|
+
* across its schema files, which a schema's own type cannot see (TablesOf) — as the block the CLI writes into
|
|
113
|
+
* palbase/palbase-env.d.ts. No database is asked: the schema files say it all.
|
|
114
|
+
*/
|
|
115
|
+
export declare function writeTypes(config: DatabaseConfig | undefined, out?: AnswerOut): Promise<MigrationExit>;
|
|
110
116
|
/** The deploy's migration step. */
|
|
111
117
|
export declare function runMigration(config: DatabaseConfig, env: Record<string, string | undefined>, mode: MigrateMode): Promise<MigrationExit>;
|
|
118
|
+
/** Where the step's answer is written: the standard output's stream, done once what it was given is out. */
|
|
119
|
+
export type AnswerOut = (text: string, done: () => void) => void;
|
|
120
|
+
/**
|
|
121
|
+
* The step's answer, as one line on stdout the CLI reads: {"palbase_migrate": mode, "result": …} — out, and every
|
|
122
|
+
* log line before it, when this resolves: the run exits right after, and on a pipe what the stream still held went
|
|
123
|
+
* with the process (a large plan's line was cut at what the pipe took: the CLI read "Unterminated string in JSON at
|
|
124
|
+
* position 131072"). One stream, in order: a log line is never cut by it.
|
|
125
|
+
*/
|
|
126
|
+
export declare function said(mode: MigrateMode, result: unknown, out?: AnswerOut): Promise<void>;
|
|
112
127
|
export interface OpenDatabase {
|
|
113
128
|
model: Schema;
|
|
114
129
|
binding: Binding;
|
|
@@ -138,3 +138,5 @@ export interface App {
|
|
|
138
138
|
}
|
|
139
139
|
export declare const MAX_BODY_BYTES: number;
|
|
140
140
|
export declare function createApp(opts: AppOptions): App;
|
|
141
|
+
/** An origin CORS holds: https://host[:port], http only for localhost, no path. */
|
|
142
|
+
export declare function corsOrigin(origin: string): boolean;
|
|
@@ -205,6 +205,21 @@ export declare function matchChannel(pattern: string, channel: string): Record<s
|
|
|
205
205
|
export declare function channelOf(pattern: string, params: Readonly<Record<string, unknown>>): string | {
|
|
206
206
|
problem: string;
|
|
207
207
|
};
|
|
208
|
+
/** Whose memberships of a gateway's channel are decided again, and whether the channel is over. */
|
|
209
|
+
export interface RevalidateOptions {
|
|
210
|
+
/** Only this user's membership: the member taken out. */
|
|
211
|
+
user?: string;
|
|
212
|
+
/** The channel is over: every member dropped without being asked, its log forgotten — one channel's, every value given. */
|
|
213
|
+
end?: boolean;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* What realtime is asked to decide again for a gateway's channels: the one channel when every capture of its pattern
|
|
217
|
+
* has a value, every channel of the pattern with the values given when some do not — or what is wrong with it, as
|
|
218
|
+
* realtime would refuse it.
|
|
219
|
+
*/
|
|
220
|
+
export declare function revalidationOf(pattern: string, params: Readonly<Record<string, unknown>>, options: RevalidateOptions): realtime.Revalidation | {
|
|
221
|
+
problem: string;
|
|
222
|
+
};
|
|
208
223
|
/** One event to a gateway's members, as realtime's broadcast takes it: its channel (topic), and conn_id for one membership alone. */
|
|
209
224
|
type GatewayBroadcast = realtime.BroadcastMessage;
|
|
210
225
|
export interface GatewayDeps {
|
|
@@ -216,6 +231,8 @@ export interface GatewayDeps {
|
|
|
216
231
|
run<T>(user: SignedUser | undefined, where: string, signal: AbortSignal | undefined, work: () => Promise<T>): Promise<T>;
|
|
217
232
|
/** realtime's POST /realtime/broadcast, as the app (its secret key). */
|
|
218
233
|
broadcast(messages: GatewayBroadcast[]): Promise<unknown>;
|
|
234
|
+
/** realtime's POST /realtime/revalidate, as the app: the memberships it names decided again, on every replica. */
|
|
235
|
+
revalidate(body: realtime.Revalidation): Promise<unknown>;
|
|
219
236
|
/** The platform's infrastructure, not the method, failed: the call is answered 503, and realtime asks again. */
|
|
220
237
|
isOutage(e: unknown): boolean;
|
|
221
238
|
}
|
|
@@ -239,6 +256,8 @@ export interface Gateways {
|
|
|
239
256
|
emit(cls: Function, params: Readonly<Record<string, unknown>>, event: string, payload: unknown): void;
|
|
240
257
|
/** A source piped into a gateway's channel from anywhere in the app (Palbase.gateways.to(…).pipe). */
|
|
241
258
|
pipe(cls: Function, params: Readonly<Record<string, unknown>>, source: PipeSource): Promise<void>;
|
|
259
|
+
/** A gateway's channel — or its channels of the values given — decided again (Palbase.gateways.to(…).revalidate). */
|
|
260
|
+
revalidate(cls: Function, params: Readonly<Record<string, unknown>>, options?: RevalidateOptions): Promise<void>;
|
|
242
261
|
/** Every channel let go: what was held is aborted (the app is stopping). */
|
|
243
262
|
close(): void;
|
|
244
263
|
}
|
|
@@ -4,6 +4,7 @@ export { Task, TaskFailure, Tasks, type EnqueueOptions, type PayloadOf, type Que
|
|
|
4
4
|
export { Upload, UploadedObject, type UploadConfig } from './upload.js';
|
|
5
5
|
export { Authorize, ChatPart, Gateway, GatewayRefusal, OnConnect, OnDisconnect, OnEmpty, OnFirst, Subscribe, type GatewayAuthorizeContext, type GatewayContext, type GatewayEvents, type GatewayGrant, type GatewayMessageContext, type GatewayOptions, type GatewayUser, type PipeSource, } from './gateways.js';
|
|
6
6
|
export type { GatewaysApi, GatewayTarget } from './runtime.js';
|
|
7
|
+
export type { AgentContext, ToolContext, TurnDefinition, TurnMessage } from '../../ai/src/index.js';
|
|
7
8
|
export { getWebhookManifest, type WebhookEventHandler, type WebhookMeta } from './webhooks.js';
|
|
8
9
|
export { DiError, type DiErrorKind } from './container.js';
|
|
9
10
|
export { BadRequest, Conflict, DeadlockDetected, Forbidden, HttpError, NotFound, PalError, SerializationFailure, TooManyRequests, Unauthorized, UniqueViolation, defineError, type DefinedError, type DefinedErrorWithData, type Envelope, type FieldIssue, } from './errors.js';
|
|
@@ -52,9 +52,21 @@ export interface GatewayTarget<G> {
|
|
|
52
52
|
pipe(source: {
|
|
53
53
|
pipe(topic: string): Promise<void>;
|
|
54
54
|
}): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Who may be on the channel is decided again now, on every replica of realtime — a decision the gateway made may no
|
|
57
|
+
* longer hold: a member taken out of a chat, a team changed. A member it would no longer let in (its access, its
|
|
58
|
+
* @Authorize) is dropped, their client told the channel closed; their rejoin is decided on the merits. Params may
|
|
59
|
+
* leave captures out: every channel of the gateway with the values given. user: only that user's membership. end:
|
|
60
|
+
* the channel is over — every member dropped without being asked, its log forgotten (one channel, no user).
|
|
61
|
+
*/
|
|
62
|
+
revalidate(options?: {
|
|
63
|
+
user?: string;
|
|
64
|
+
end?: boolean;
|
|
65
|
+
}): Promise<void>;
|
|
55
66
|
}
|
|
56
67
|
/** The app's gateways, from any service: Palbase.gateways.to(ChatGateway, { chatId }).emit('token', { text }). */
|
|
57
68
|
export interface GatewaysApi {
|
|
69
|
+
/** A gateway's channel, by its pattern's values — some left out, for revalidate alone: the gateway's channels of the values given. */
|
|
58
70
|
to<G extends Function>(gateway: G, params: Readonly<Record<string, string>>): GatewayTarget<G>;
|
|
59
71
|
}
|
|
60
72
|
/**
|
|
@@ -4,7 +4,7 @@ import { type FakeClient, type RecordedQuery } from 'palgres/testing';
|
|
|
4
4
|
import type { CacheClient } from '../cache.js';
|
|
5
5
|
import type { Schemas, Tables } from '../db-env.js';
|
|
6
6
|
import type { Token } from '../decorators.js';
|
|
7
|
-
import { type Logger } from '../runtime.js';
|
|
7
|
+
import { type GatewaysApi, type Logger } from '../runtime.js';
|
|
8
8
|
import type { Flags, Notifications, Realtime, Secrets, StorageService } from '../services.js';
|
|
9
9
|
import { type StringsTable } from '../i18n.js';
|
|
10
10
|
export type { RecordedQuery };
|
|
@@ -18,6 +18,8 @@ export interface RuntimeServices {
|
|
|
18
18
|
Notifications: typeof Notifications;
|
|
19
19
|
Flags: typeof Flags;
|
|
20
20
|
Realtime: typeof Realtime;
|
|
21
|
+
/** Palbase.gateways: what a service sends a gateway's channel through (to(Gateway, params).emit, .pipe). */
|
|
22
|
+
Gateways: GatewaysApi;
|
|
21
23
|
}
|
|
22
24
|
/**
|
|
23
25
|
* Runs `fn` with these stand-ins: Database is the client given (its typed
|
|
@@ -1,7 +1,28 @@
|
|
|
1
|
-
import type { ChatMessage } from './modules/ai.js';
|
|
1
|
+
import type { ChatMessage, MessageAttachment } from './modules/ai.js';
|
|
2
2
|
export type TurnStatus = 'running' | 'waiting' | 'completed' | 'failed' | 'canceled' | 'timed_out' | 'budget_exceeded';
|
|
3
3
|
export type WaitingReason = 'approval' | 'tool_output' | 'subagents' | 'message';
|
|
4
4
|
export type ToolStatus = 'running' | 'awaiting_output' | 'awaiting_approval' | 'approved' | 'denied' | 'expired' | 'completed' | 'failed' | 'canceled';
|
|
5
|
+
/** How a turn ended, in the chat's words — as its event (ai.response.completed / failed) says it. */
|
|
6
|
+
export type TurnEnd = 'completed' | 'failed' | 'stopped' | 'budget_exceeded';
|
|
7
|
+
/**
|
|
8
|
+
* A push, a pull request or a merge the agent asked for (a tool part named push, pull_request or merge), and what a
|
|
9
|
+
* person decides it by: the repository, the branch it writes, the base it targets, the commit it carries.
|
|
10
|
+
*/
|
|
11
|
+
export interface Publication {
|
|
12
|
+
/** The engine's word: push_branch, open_pull_request, merge_pull_request. */
|
|
13
|
+
operation: string;
|
|
14
|
+
/** owner/name. */
|
|
15
|
+
repository: string;
|
|
16
|
+
/** The remote as the engine names it. */
|
|
17
|
+
remote: string;
|
|
18
|
+
branch: string;
|
|
19
|
+
/** The branch a pull request targets, or a merge goes into ('' for a push). */
|
|
20
|
+
base: string;
|
|
21
|
+
/** The commit it carries. */
|
|
22
|
+
commit: string;
|
|
23
|
+
/** The engine's own sentence of it. */
|
|
24
|
+
display: string;
|
|
25
|
+
}
|
|
5
26
|
/** A member's (or the server's) message, as the agent got it. */
|
|
6
27
|
export interface MessageEvent {
|
|
7
28
|
type: 'message';
|
|
@@ -19,7 +40,16 @@ export interface TurnEvent {
|
|
|
19
40
|
/** On running and waiting: the chat has had one member all its life, as it is now (once a second has been added, never again). */
|
|
20
41
|
solo?: boolean;
|
|
21
42
|
status: TurnStatus;
|
|
22
|
-
/**
|
|
43
|
+
/** A turn the chat's goal opened: the goal, the turn's role (work, or verify: the check of a claimed completion) and its number. */
|
|
44
|
+
goal?: {
|
|
45
|
+
goal_id: string;
|
|
46
|
+
role: 'work' | 'verify' | (string & {});
|
|
47
|
+
seq: number;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Why it waits, and where in its answer — and, for a tool call, which: null unless status is waiting. A publication
|
|
51
|
+
* waiting on a person's yes names its part (tool_call_id, tool_name push|pull_request|merge) and what it does.
|
|
52
|
+
*/
|
|
23
53
|
waiting: {
|
|
24
54
|
reason: WaitingReason;
|
|
25
55
|
text_offset: number;
|
|
@@ -27,8 +57,17 @@ export interface TurnEvent {
|
|
|
27
57
|
tool_call_id?: string;
|
|
28
58
|
tool_name?: string;
|
|
29
59
|
input?: unknown;
|
|
60
|
+
expires_at?: string;
|
|
61
|
+
publication?: Publication;
|
|
30
62
|
} | null;
|
|
63
|
+
/** How it ended, once it has: completed, failed, stopped (a member or the server, or the chat went), budget_exceeded. */
|
|
64
|
+
end?: TurnEnd | (string & {});
|
|
65
|
+
/** Why, when it did not complete and was not stopped — and whether asking again may go otherwise. */
|
|
31
66
|
error: {
|
|
67
|
+
code: string;
|
|
68
|
+
message: string;
|
|
69
|
+
retryable: boolean;
|
|
70
|
+
} | {
|
|
32
71
|
code?: string;
|
|
33
72
|
message?: string;
|
|
34
73
|
} | string | null;
|
|
@@ -47,6 +86,92 @@ export interface ResetEvent {
|
|
|
47
86
|
response_id: string;
|
|
48
87
|
offset: number;
|
|
49
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* The model's reasoning as it thinks, when the agent shows it (thinking: visible): a window of a step's at a time,
|
|
91
|
+
* each after the one before — the turn's own, never a subagent's.
|
|
92
|
+
*/
|
|
93
|
+
export interface ThinkingEvent {
|
|
94
|
+
type: 'thinking';
|
|
95
|
+
seq: number;
|
|
96
|
+
response_id: string;
|
|
97
|
+
run_id: string;
|
|
98
|
+
/** The model step it is of: its windows go together, its reasoning before what the step writes. */
|
|
99
|
+
step_id?: string;
|
|
100
|
+
text: string;
|
|
101
|
+
/**
|
|
102
|
+
* The model's provider would not give its reasoning (an OpenAI organization not verified for reasoning
|
|
103
|
+
* summaries): said once for the turn, with the model and the provider's reason — and no text.
|
|
104
|
+
*/
|
|
105
|
+
unavailable?: true;
|
|
106
|
+
model?: string;
|
|
107
|
+
reason?: string;
|
|
108
|
+
}
|
|
109
|
+
export type GoalKind = 'set' | 'updated' | 'turn_started' | 'judged' | 'verified' | 'status_changed' | 'cleared';
|
|
110
|
+
/** A word of the chat's goal: set, changed, a turn of it begun, a turn judged, a claimed completion checked, its status, cleared. */
|
|
111
|
+
export interface GoalEvent {
|
|
112
|
+
type: 'goal';
|
|
113
|
+
/** The journal's sequence. */
|
|
114
|
+
seq: number;
|
|
115
|
+
goal_id: string;
|
|
116
|
+
kind: GoalKind | (string & {});
|
|
117
|
+
/** set and updated: the goal as it is now. */
|
|
118
|
+
goal?: {
|
|
119
|
+
objective: string;
|
|
120
|
+
rubric: string;
|
|
121
|
+
status: string;
|
|
122
|
+
stop_code: string;
|
|
123
|
+
stop_reason: string;
|
|
124
|
+
phase: string;
|
|
125
|
+
max_turns?: number | null;
|
|
126
|
+
max_cost_usd?: number | null;
|
|
127
|
+
};
|
|
128
|
+
/** updated: what changed. */
|
|
129
|
+
changed?: unknown;
|
|
130
|
+
/** turn_started: the turn's role (work, verify), its number among the goal's turns (the part's seq), its response. */
|
|
131
|
+
role?: string;
|
|
132
|
+
turn?: number;
|
|
133
|
+
response_id?: string;
|
|
134
|
+
run_id?: string;
|
|
135
|
+
/** judged and verified: the evaluator's word, and why; verified: what is missing. */
|
|
136
|
+
verdict?: string;
|
|
137
|
+
reason?: string;
|
|
138
|
+
missing?: unknown;
|
|
139
|
+
/** status_changed: from what to what, and the stop's code (cleared: reason too). */
|
|
140
|
+
from?: string;
|
|
141
|
+
to?: string;
|
|
142
|
+
code?: string;
|
|
143
|
+
}
|
|
144
|
+
/** One message or answer of what a fork began with. */
|
|
145
|
+
export interface HistoryItem {
|
|
146
|
+
/** user: a member's message, or the server's; assistant: the agent's answer. */
|
|
147
|
+
role: 'user' | 'assistant';
|
|
148
|
+
message_id?: string;
|
|
149
|
+
client_id?: string;
|
|
150
|
+
author?: string | null;
|
|
151
|
+
author_name?: string;
|
|
152
|
+
text: string;
|
|
153
|
+
metadata?: Record<string, string>;
|
|
154
|
+
created_at?: string;
|
|
155
|
+
/** An answer's response, in the chat it was forked from. */
|
|
156
|
+
response_id?: string;
|
|
157
|
+
/** Its text here is the first of a longer one: the fork's model read it whole. */
|
|
158
|
+
text_truncated?: boolean;
|
|
159
|
+
/** A message's pictures and files ([] or absent for none), as the chat it was forked from had them. */
|
|
160
|
+
attachments?: MessageAttachment[];
|
|
161
|
+
}
|
|
162
|
+
/** What a fork began with: the chat's messages and its agent's answers before the message it was cut before, a few to a part — written first in the fork's channel. */
|
|
163
|
+
export interface HistoryEvent {
|
|
164
|
+
type: 'history';
|
|
165
|
+
/** The chat it was forked from, and the message it was cut before. */
|
|
166
|
+
forked_from: {
|
|
167
|
+
chat_id: string;
|
|
168
|
+
before_message: string;
|
|
169
|
+
} | null;
|
|
170
|
+
/** This part's place among the history's parts, and how many there are. */
|
|
171
|
+
part: number;
|
|
172
|
+
parts: number;
|
|
173
|
+
items: HistoryItem[];
|
|
174
|
+
}
|
|
50
175
|
/** A tool call, each time its state changes. */
|
|
51
176
|
export interface ToolEvent {
|
|
52
177
|
type: 'tool';
|
|
@@ -68,6 +193,16 @@ export interface ToolEvent {
|
|
|
68
193
|
is_error?: boolean;
|
|
69
194
|
/** The subagent's response that made the call, when one did. */
|
|
70
195
|
agent_response_id?: string | null;
|
|
196
|
+
/** A publication's part (named push, pull_request or merge, its call_id the publication's id): what it does and where. */
|
|
197
|
+
publication?: Publication;
|
|
198
|
+
/** When its approval lapses, while it waits for one. */
|
|
199
|
+
expires_at?: string;
|
|
200
|
+
/**
|
|
201
|
+
* Its answer is shown by its end (output: its last 16 KiB): how many bytes before it were left out, and that the
|
|
202
|
+
* part was cut to fit the channel — the whole answer is read by its call (chatToolCall).
|
|
203
|
+
*/
|
|
204
|
+
omittedBytes: number;
|
|
205
|
+
outputTruncated: boolean;
|
|
71
206
|
[field: string]: unknown;
|
|
72
207
|
}
|
|
73
208
|
/** A subagent at work — or one the agent asked for and was refused (status denied, with its reason). */
|
|
@@ -88,7 +223,37 @@ export interface AgentEvent {
|
|
|
88
223
|
reason?: string;
|
|
89
224
|
[field: string]: unknown;
|
|
90
225
|
}
|
|
91
|
-
|
|
226
|
+
/** The chat's live voice began, or ended: whose it is, what becomes of what is asked of it, how long it lasted, why it ended. */
|
|
227
|
+
export interface VoiceEvent {
|
|
228
|
+
type: 'voice';
|
|
229
|
+
/** The journal's sequence of its start; 0 for its end, told from the module's record under the voice's id. */
|
|
230
|
+
seq: number;
|
|
231
|
+
voice_id: string;
|
|
232
|
+
/** Its member; null: the server's own. */
|
|
233
|
+
user_id: string | null;
|
|
234
|
+
/** chat: what the person asks for is a turn of the chat; events: the backend's to do (ai.voice.delegated). */
|
|
235
|
+
delegation: 'chat' | 'events' | (string & {});
|
|
236
|
+
status: 'started' | 'closed' | (string & {});
|
|
237
|
+
/** On closed: how long it lasted, and why it ended (close_requested, member_removed, chat_deleted, replaced, lost, …). */
|
|
238
|
+
seconds?: number;
|
|
239
|
+
close_reason?: string;
|
|
240
|
+
}
|
|
241
|
+
/** A line said in the chat's voice — the person's (user) or the voice's (assistant): a message of kind voice of its history. */
|
|
242
|
+
export interface TranscriptEvent {
|
|
243
|
+
type: 'transcript';
|
|
244
|
+
seq: number;
|
|
245
|
+
/** The line's id: its message's in the chat's history. */
|
|
246
|
+
id: string;
|
|
247
|
+
voice_id: string;
|
|
248
|
+
role: 'user' | 'assistant' | (string & {});
|
|
249
|
+
/** The member who said it; null: the voice. */
|
|
250
|
+
user_id: string | null;
|
|
251
|
+
author_name: string;
|
|
252
|
+
text: string;
|
|
253
|
+
final: boolean;
|
|
254
|
+
created_at: string;
|
|
255
|
+
}
|
|
256
|
+
export type ChatEvent = MessageEvent | TurnEvent | TextEvent | ResetEvent | ThinkingEvent | ToolEvent | AgentEvent | GoalEvent | HistoryEvent | VoiceEvent | TranscriptEvent;
|
|
92
257
|
/** A chat refusal of the module's, said in words its caller can act on; anything else (or one said already) as it was. */
|
|
93
258
|
export declare function chatRefusal(e: unknown): unknown;
|
|
94
259
|
/** The same promise, its chat refusals said as chatRefusal says them. */
|