@repogo/plugins 0.1.34 → 0.1.37
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 +380 -26
- package/dist/cache.d.ts +27 -0
- package/dist/collections.d.ts +11 -1
- package/dist/context.d.ts +117 -1
- package/dist/cron.d.ts +21 -0
- package/dist/define.d.ts +36 -11
- package/dist/generated.d.ts +16 -0
- package/dist/index.d.ts +10 -3
- package/dist/index.js +100 -5
- package/dist/logs.d.ts +55 -0
- package/dist/runtime.d.ts +173 -0
- package/dist/self.d.ts +1 -0
- package/dist/testing.d.ts +53 -0
- package/dist/testing.js +3492 -0
- package/dist/tracking.d.ts +5 -0
- package/dist/uploads.d.ts +24 -0
- package/dist/workflow/attempts.d.ts +25 -0
- package/dist/workflow/availability.d.ts +8 -0
- package/dist/workflow/catalog.d.ts +21 -0
- package/dist/workflow/clock.d.ts +6 -0
- package/dist/workflow/contracts.d.ts +121 -0
- package/dist/workflow/definition.d.ts +35 -0
- package/dist/workflow/errors.d.ts +19 -0
- package/dist/workflow/events.d.ts +132 -0
- package/dist/workflow/interrupted.d.ts +3 -0
- package/dist/workflow/journal.d.ts +28 -0
- package/dist/workflow/lease.d.ts +2 -0
- package/dist/workflow/lifetime.d.ts +27 -0
- package/dist/workflow/policy.d.ts +36 -0
- package/dist/workflow/register.d.ts +11 -0
- package/dist/workflow/retry.d.ts +14 -0
- package/dist/workflow/runner.d.ts +29 -0
- package/dist/workflow/scope.d.ts +4 -0
- package/dist/workflow/service.d.ts +48 -0
- package/dist/workflow/sleep.d.ts +6 -0
- package/dist/workflow/state.d.ts +41 -0
- package/dist/workflow/storage.d.ts +22 -0
- package/dist/workflow/summary.d.ts +80 -0
- package/dist/workflow/testing.d.ts +12 -0
- package/dist/workflow-executor.js +22917 -0
- package/package.json +7 -3
package/dist/context.d.ts
CHANGED
|
@@ -2,16 +2,74 @@ import type { Bucket } from "./buckets";
|
|
|
2
2
|
import type { Collection } from "./collections";
|
|
3
3
|
import type { Kv } from "./kv";
|
|
4
4
|
import type { Stream } from "./streams";
|
|
5
|
-
import type { MethodKind } from "./define";
|
|
5
|
+
import type { HTTPAccess, MethodKind } from "./define";
|
|
6
|
+
import type { Duration } from "./duration";
|
|
6
7
|
/** An alert for the user's phones: what it says, and the page a tap opens. */
|
|
7
8
|
export type Notice = {
|
|
8
9
|
title: string;
|
|
9
10
|
body: string;
|
|
10
11
|
/** A page target, `.repogo/tabs/vercel.md?project=a`; a tap opens it. */
|
|
11
12
|
page?: string;
|
|
13
|
+
/** An `https` or `itms-services` link a tap opens instead of the page, such as a build's install. */
|
|
14
|
+
url?: string;
|
|
12
15
|
/** Alerts sharing a collapse id replace one another; defaults to the plugin and title. */
|
|
13
16
|
collapse?: string;
|
|
14
17
|
};
|
|
18
|
+
/** A Live Activity's color: the cards' named colors, less `secondary`. */
|
|
19
|
+
export type ActivityTint = "primary" | "accent" | "success" | "warning" | "danger" | "blue" | "green" | "orange" | "red" | "purple" | "pink" | "teal" | "yellow" | "gray";
|
|
20
|
+
/** A segment per step, or one bar. */
|
|
21
|
+
export type ActivityProgress = {
|
|
22
|
+
kind: "steps";
|
|
23
|
+
/** 1 to 8 names of at most 24 characters. */
|
|
24
|
+
steps: string[];
|
|
25
|
+
/** The active step, 0 to `steps.length`; the ones before it are complete. */
|
|
26
|
+
current: number;
|
|
27
|
+
} | {
|
|
28
|
+
kind: "bar";
|
|
29
|
+
/** 0 to 1. */
|
|
30
|
+
value: number;
|
|
31
|
+
};
|
|
32
|
+
/** The card's clock, which the phone ticks with no pushes. */
|
|
33
|
+
export type ActivityTimer = {
|
|
34
|
+
kind: "elapsed";
|
|
35
|
+
/** Unix ms; the activity's first start unless said. */
|
|
36
|
+
startedAt?: number;
|
|
37
|
+
} | {
|
|
38
|
+
kind: "countdown";
|
|
39
|
+
/** Unix ms; reaching it ends nothing. */
|
|
40
|
+
endsAt: number;
|
|
41
|
+
} | {
|
|
42
|
+
kind: "none";
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* A Live Activity on the user's phones, sent whole each time: the same `id`
|
|
46
|
+
* updates it, a field left out takes its default, and status `done` or
|
|
47
|
+
* `failed` ends it with this state.
|
|
48
|
+
*/
|
|
49
|
+
export type Activity = {
|
|
50
|
+
/** The activity's id within the plugin, at most 64 bytes. */
|
|
51
|
+
id: string;
|
|
52
|
+
/** At most 60 characters, as a notice's title. */
|
|
53
|
+
title: string;
|
|
54
|
+
/** At most 120 characters, as a notice's body. */
|
|
55
|
+
body?: string;
|
|
56
|
+
/** A page target of the calling project, `.repogo/tabs/deploys.ui?project=web`; a tap opens it. */
|
|
57
|
+
page?: string;
|
|
58
|
+
/** An SF Symbol name, `shippingbox`; `circle.dotted`, or a check or a cross once ended, unless said. */
|
|
59
|
+
symbol?: string;
|
|
60
|
+
/** Colors the symbol, the progress and the label; white, or green or red once ended, unless said. */
|
|
61
|
+
tint?: ActivityTint;
|
|
62
|
+
/** The card's value, at most 24 characters; "2 of 4", "40%" or the status unless said, and "" hides it. */
|
|
63
|
+
label?: string;
|
|
64
|
+
/** The Dynamic Island's value, at most 10 characters; the label, or "2/4", unless said. */
|
|
65
|
+
compactLabel?: string;
|
|
66
|
+
/** No progress unless said. */
|
|
67
|
+
progress?: ActivityProgress;
|
|
68
|
+
/** Elapsed since the first start unless said. */
|
|
69
|
+
timer?: ActivityTimer;
|
|
70
|
+
/** `running` unless said; `done` and `failed` end it. */
|
|
71
|
+
status?: "running" | "done" | "failed";
|
|
72
|
+
};
|
|
15
73
|
/** One method as `ctx.plugins()` and the agent's `plugins` tool list it. */
|
|
16
74
|
export type ManifestMethod = {
|
|
17
75
|
/** `<plugin>.<method>`, the name `ctx.call` takes. */
|
|
@@ -20,6 +78,8 @@ export type ManifestMethod = {
|
|
|
20
78
|
description: string | null;
|
|
21
79
|
/** What a card asks before running it; null runs on tap. */
|
|
22
80
|
confirm: string | null;
|
|
81
|
+
/** Who may call it at the environment's own address; null, no one. */
|
|
82
|
+
http: HTTPAccess | null;
|
|
23
83
|
/** JSON Schema of the input, and of the output when the method declares one. */
|
|
24
84
|
input: unknown;
|
|
25
85
|
output: unknown;
|
|
@@ -32,6 +92,8 @@ export type ManifestCron = {
|
|
|
32
92
|
nextRunAt: number | null;
|
|
33
93
|
lastRunAt: number | null;
|
|
34
94
|
lastError: string | null;
|
|
95
|
+
/** How long its last run took: a run far past its interval blocked or waited on something. */
|
|
96
|
+
lastDurationMs: number | null;
|
|
35
97
|
running: boolean;
|
|
36
98
|
runs: number;
|
|
37
99
|
};
|
|
@@ -49,6 +111,21 @@ export type ManifestStorage = {
|
|
|
49
111
|
path: string;
|
|
50
112
|
}[];
|
|
51
113
|
};
|
|
114
|
+
/**
|
|
115
|
+
* One schedule the host gives a Worker, from a line of `~/.repogo/crons.json`: call
|
|
116
|
+
* `<plugin>.<method>` with `{}` when `schedule` comes due in `timezone` (the environment's).
|
|
117
|
+
*/
|
|
118
|
+
export type CronEntry = {
|
|
119
|
+
plugin: string;
|
|
120
|
+
method: string;
|
|
121
|
+
schedule: string;
|
|
122
|
+
timezone?: string;
|
|
123
|
+
};
|
|
124
|
+
/** A schedule and how it's going; `error` says why it couldn't be set, and then nothing runs. */
|
|
125
|
+
export type CronStatus = ManifestCron & {
|
|
126
|
+
plugin: string;
|
|
127
|
+
error: string | null;
|
|
128
|
+
};
|
|
52
129
|
export type Manifest = {
|
|
53
130
|
plugins: {
|
|
54
131
|
name: string;
|
|
@@ -58,8 +135,27 @@ export type Manifest = {
|
|
|
58
135
|
storage: ManifestStorage;
|
|
59
136
|
}[];
|
|
60
137
|
};
|
|
138
|
+
/** Who started a call: a tap or a card's query, an agent's `plugin_call`, a cron, or plugin code with none of those behind it. */
|
|
139
|
+
export type Caller = "card" | "agent" | "cron" | "code" | "http";
|
|
140
|
+
/** How `ctx.agent` runs a chat: which agent, in which project, and how long to wait for its answer. */
|
|
141
|
+
export type AgentOptions = {
|
|
142
|
+
/** `claude` or `codex`, as `agents.list` names them. */
|
|
143
|
+
agent: string;
|
|
144
|
+
/** The project the chat runs in; the calling project unless said. */
|
|
145
|
+
project?: string;
|
|
146
|
+
title?: string;
|
|
147
|
+
/** How long to wait for the answer; 10 minutes unless said. */
|
|
148
|
+
timeout?: Duration;
|
|
149
|
+
};
|
|
150
|
+
/** What the agent answered, and the chat it answered in, to open or message later. */
|
|
151
|
+
export type AgentReply = {
|
|
152
|
+
chatId: string;
|
|
153
|
+
text: string;
|
|
154
|
+
};
|
|
61
155
|
export type Context = {
|
|
62
156
|
plugin: string;
|
|
157
|
+
/** Who started the outermost call; `ctx.call` passes it on. */
|
|
158
|
+
caller: Caller;
|
|
63
159
|
/** The project's checkout, for a plugin that reads the project's files. */
|
|
64
160
|
root: string;
|
|
65
161
|
collections: Record<string, Collection<any>>;
|
|
@@ -73,6 +169,13 @@ export type Context = {
|
|
|
73
169
|
* `ctx.host("git.status", { path: ctx.root })`. Its answer doesn't re-run a query.
|
|
74
170
|
*/
|
|
75
171
|
host: (method: string, params?: unknown) => Promise<unknown>;
|
|
172
|
+
/**
|
|
173
|
+
* Runs a tool of an MCP server the user switched on for the calling project:
|
|
174
|
+
* `ctx.mcp("stripe", "stripe_api_read", { … })`, answering the tool's result.
|
|
175
|
+
* A query may run only read-only tools; a destructive tool runs only from a
|
|
176
|
+
* method with a `confirm`. Its answer doesn't re-run a query.
|
|
177
|
+
*/
|
|
178
|
+
mcp: (server: string, tool: string, input?: unknown) => Promise<unknown>;
|
|
76
179
|
/**
|
|
77
180
|
* The plugins beside this one, in the same folder (the project's, or the
|
|
78
181
|
* environment's), with their methods: what `call` can reach.
|
|
@@ -82,5 +185,18 @@ export type Context = {
|
|
|
82
185
|
signal: AbortSignal;
|
|
83
186
|
/** Sends an alert to every phone paired with this environment. */
|
|
84
187
|
notify: (notice: Notice) => void;
|
|
188
|
+
/**
|
|
189
|
+
* Shows or updates a Live Activity on every paired phone:
|
|
190
|
+
* `await ctx.activity({ id: "deploy", title: "Deploying", progress: { kind: "steps", steps: ["Build", "Ship"], current: 0 } })`.
|
|
191
|
+
* A plugin shows at most two at once.
|
|
192
|
+
*/
|
|
193
|
+
activity: (activity: Activity) => Promise<void>;
|
|
194
|
+
/**
|
|
195
|
+
* Starts a chat with `prompt` and waits for the agent's whole answer:
|
|
196
|
+
* `await ctx.agent("Why is the build failing?", { agent: "claude" })`.
|
|
197
|
+
* Throws once `timeout` passes, naming the chat, which keeps running.
|
|
198
|
+
*/
|
|
199
|
+
agent: (prompt: string, options: AgentOptions) => Promise<AgentReply>;
|
|
200
|
+
/** The same as `console.log`: every console line is kept with the plugin and the call that wrote it. */
|
|
85
201
|
log: (...args: unknown[]) => void;
|
|
86
202
|
};
|
package/dist/cron.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type Schedule = {
|
|
2
|
+
seconds: Set<number> | null;
|
|
3
|
+
minutes: Set<number>;
|
|
4
|
+
hours: Set<number>;
|
|
5
|
+
days: Set<number>;
|
|
6
|
+
months: Set<number>;
|
|
7
|
+
weekdays: Set<number>;
|
|
8
|
+
/** Day fields given as other than `*`, for cron's either-day rule. */
|
|
9
|
+
daysRestricted: boolean;
|
|
10
|
+
weekdaysRestricted: boolean;
|
|
11
|
+
};
|
|
12
|
+
/** Reads a schedule, or throws saying what's wrong with it. */
|
|
13
|
+
export declare function parseSchedule(source: string): Schedule;
|
|
14
|
+
/** Throws unless `zone` is a time zone this machine knows, such as "America/New_York". */
|
|
15
|
+
export declare function checkTimezone(zone: string): void;
|
|
16
|
+
/**
|
|
17
|
+
* The first due time strictly after `after` (ms), in `zone`, or null when there
|
|
18
|
+
* is none within four years (`0 0 31 2 *`). A wall time that a fall-back night
|
|
19
|
+
* shows twice is due only the first time.
|
|
20
|
+
*/
|
|
21
|
+
export declare function nextDue(s: Schedule, after: number, zone: string): number | null;
|
package/dist/define.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { z } from "zod";
|
|
2
|
+
import type { CacheOptions } from "./cache";
|
|
2
3
|
import type { Context } from "./context";
|
|
4
|
+
import { type Duration } from "./duration";
|
|
5
|
+
import type { Workflow } from "./workflow/definition";
|
|
3
6
|
import type { Retain } from "./streams";
|
|
4
7
|
export type Collections = Record<string, z.ZodObject>;
|
|
5
8
|
/** A stream's lines' schema, or that and how long it keeps them (7 days or 50 MB a key unless it says). */
|
|
@@ -25,26 +28,25 @@ export type Method<I extends z.ZodType = z.ZodType, O extends z.ZodType = z.ZodT
|
|
|
25
28
|
* runs, such as "Delete every item?". Methods without one run on tap.
|
|
26
29
|
*/
|
|
27
30
|
confirm?: string;
|
|
31
|
+
/** Who may call it at the environment's own address; unset, no one. */
|
|
32
|
+
http?: HTTPAccess;
|
|
33
|
+
/** Set by `cached`: the query answers from what it saved, and checks again when that's old. */
|
|
34
|
+
cache?: CacheOptions;
|
|
28
35
|
run: (input: z.infer<I>, ctx: Context) => unknown | Promise<unknown>;
|
|
29
36
|
};
|
|
30
|
-
export type Handler = (payload: any, ctx: Context) => unknown | Promise<unknown>;
|
|
31
37
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* five fields or six with seconds first; `timezone` defaults to the environment's.
|
|
38
|
+
* `key`: the host checks a key the caller sends. `none`: anyone reaches the
|
|
39
|
+
* method, which checks the caller itself, such as a provider's signature.
|
|
35
40
|
*/
|
|
36
|
-
export type
|
|
37
|
-
|
|
38
|
-
schedule: string;
|
|
39
|
-
timezone?: string;
|
|
40
|
-
};
|
|
41
|
+
export type HTTPAccess = "key" | "none";
|
|
42
|
+
export type Handler = (payload: any, ctx: Context) => unknown | Promise<unknown>;
|
|
41
43
|
export type PluginDefinition = {
|
|
42
44
|
/** One line, shown to the agent in the index of plugins. */
|
|
43
45
|
description?: string;
|
|
44
46
|
/**
|
|
45
47
|
* Where the plugin's data lives: `<namespace>/` in the data dir, holding `data.db`
|
|
46
48
|
* and its buckets' and streams' files. Plugins naming the same namespace share its
|
|
47
|
-
* data.
|
|
49
|
+
* data. Required once the plugin keeps data; by convention a project's own is
|
|
48
50
|
* `<project>.<name>` (`repogo.plans`) and data for every project a bare name (`todos`).
|
|
49
51
|
*/
|
|
50
52
|
namespace?: string;
|
|
@@ -56,8 +58,13 @@ export type PluginDefinition = {
|
|
|
56
58
|
/** Append-only JSONL per key, in `<namespace>/streams/<name>/`, kept as `retain` says. */
|
|
57
59
|
streams?: Record<string, StreamDefinition>;
|
|
58
60
|
methods?: Record<string, Method<any, any>>;
|
|
61
|
+
workflows?: Record<string, Workflow<any, any>>;
|
|
59
62
|
on?: Record<string, Handler>;
|
|
60
|
-
|
|
63
|
+
/**
|
|
64
|
+
* Data named here gets no generated methods (list, create, delete…), so cards
|
|
65
|
+
* and agents reach it only through the plugin's own: an audit log, say.
|
|
66
|
+
*/
|
|
67
|
+
private?: string[];
|
|
61
68
|
};
|
|
62
69
|
export declare function definePlugin<T extends PluginDefinition>(plugin: T): T;
|
|
63
70
|
export declare function method<I extends z.ZodType, O extends z.ZodType = z.ZodType>(input: I, run: (input: z.infer<I>, ctx: Context) => unknown | Promise<unknown>, options?: {
|
|
@@ -65,6 +72,24 @@ export declare function method<I extends z.ZodType, O extends z.ZodType = z.ZodT
|
|
|
65
72
|
output?: O;
|
|
66
73
|
description?: string;
|
|
67
74
|
confirm?: string;
|
|
75
|
+
http?: true | {
|
|
76
|
+
auth: HTTPAccess;
|
|
77
|
+
};
|
|
78
|
+
}): Method<I, O>;
|
|
79
|
+
/**
|
|
80
|
+
* A query that answers at once from what it saved last time, for answers that
|
|
81
|
+
* are slow to get: a CLI's list, another service's API. When the saved answer
|
|
82
|
+
* is older than `fresh`, `run` goes again in the background, and cards showing
|
|
83
|
+
* it redraw only if the answer changed. With nothing saved, the first call
|
|
84
|
+
* waits for `run`. Each project keeps its own answers unless `shared`.
|
|
85
|
+
* `run` is read-only, like a query's; it has `timeout` (a minute unless it says).
|
|
86
|
+
*/
|
|
87
|
+
export declare function cached<I extends z.ZodType, O extends z.ZodType = z.ZodType>(input: I, run: (input: z.infer<I>, ctx: Context) => unknown | Promise<unknown>, options: {
|
|
88
|
+
fresh: Duration;
|
|
89
|
+
shared?: boolean;
|
|
90
|
+
timeout?: Duration;
|
|
91
|
+
output?: O;
|
|
92
|
+
description?: string;
|
|
68
93
|
}): Method<I, O>;
|
|
69
94
|
/**
|
|
70
95
|
* A method that sends items as they happen: a log tail, a build's output. Each
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { Bucket } from "./buckets";
|
|
3
|
+
import type { MethodKind } from "./define";
|
|
4
|
+
import type { Kv } from "./kv";
|
|
5
|
+
import type { Stream } from "./streams";
|
|
6
|
+
export type Generated = {
|
|
7
|
+
kind: MethodKind;
|
|
8
|
+
description: string;
|
|
9
|
+
input: z.ZodType;
|
|
10
|
+
output?: z.ZodType;
|
|
11
|
+
confirm?: string;
|
|
12
|
+
run: (input: any, signal: AbortSignal) => unknown;
|
|
13
|
+
};
|
|
14
|
+
export declare function kvMethods(name: string, kv: Kv<any>, schema: z.ZodType): Record<string, Generated>;
|
|
15
|
+
export declare function streamMethods(name: string, stream: Stream<any>, schema: z.ZodType): Record<string, Generated>;
|
|
16
|
+
export declare function bucketMethods(name: string, bucket: Bucket<any>, schema: z.ZodObject): Record<string, Generated>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
|
-
export { definePlugin, method, stream } from "./define";
|
|
2
|
-
export
|
|
3
|
-
export type {
|
|
1
|
+
export { cached, definePlugin, method, stream } from "./define";
|
|
2
|
+
export { upload, type UploadedFile } from "./uploads";
|
|
3
|
+
export type { PluginDefinition, Method, MethodKind, HTTPAccess, StreamDefinition } from "./define";
|
|
4
|
+
export type { Activity, ActivityProgress, ActivityTimer, ActivityTint, AgentOptions, AgentReply, Caller, Context, CronEntry, CronStatus, Manifest, ManifestCron, ManifestMethod, ManifestStorage } from "./context";
|
|
5
|
+
export type { LogLevel, LogRecord } from "./logs";
|
|
4
6
|
export type { BucketFile, FileStatus, PutFile } from "./buckets";
|
|
5
7
|
export type { KvEntry, SetOptions } from "./kv";
|
|
6
8
|
export type { Retain, StreamEntry, StreamKey } from "./streams";
|
|
7
9
|
export type { Duration } from "./duration";
|
|
8
10
|
export { MethodError, toCallError, type CallError } from "./errors";
|
|
9
11
|
export { z } from "zod";
|
|
12
|
+
export { workflow, type Workflow, type WorkflowContext, type WorkflowOptions } from "./workflow/definition";
|
|
13
|
+
export { NonRetryable } from "./workflow/errors";
|
|
14
|
+
export type { StepContext } from "./workflow/definition";
|
|
15
|
+
export type { StepOptions } from "./workflow/policy";
|
|
16
|
+
export type { RunSummary } from "./workflow/contracts";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,47 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __export = (target, all) => {
|
|
4
|
+
for (var name in all)
|
|
5
|
+
__defProp(target, name, {
|
|
6
|
+
get: all[name],
|
|
7
|
+
enumerable: true,
|
|
8
|
+
configurable: true,
|
|
9
|
+
set: (newValue) => all[name] = () => newValue
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// src/index.ts
|
|
14
|
+
var exports_src = {};
|
|
15
|
+
__export(exports_src, {
|
|
16
|
+
z: () => z3,
|
|
17
|
+
workflow: () => workflow,
|
|
18
|
+
upload: () => upload,
|
|
19
|
+
toCallError: () => toCallError,
|
|
20
|
+
stream: () => stream,
|
|
21
|
+
method: () => method,
|
|
22
|
+
definePlugin: () => definePlugin,
|
|
23
|
+
cached: () => cached,
|
|
24
|
+
NonRetryable: () => NonRetryable,
|
|
25
|
+
MethodError: () => MethodError
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// src/duration.ts
|
|
29
|
+
var unitMs = { s: 1000, m: 60000, h: 3600000, d: 86400000 };
|
|
30
|
+
function parseDuration(duration) {
|
|
31
|
+
if (typeof duration === "number") {
|
|
32
|
+
if (!Number.isFinite(duration) || duration <= 0)
|
|
33
|
+
throw new Error(`a duration is a positive number of ms: ${duration}`);
|
|
34
|
+
return duration;
|
|
35
|
+
}
|
|
36
|
+
const match = /^(\d+(?:\.\d+)?)([smhd])$/.exec(duration);
|
|
37
|
+
if (!match)
|
|
38
|
+
throw new Error(`a duration is like "30s", "5m", "1h" or "7d": ${duration}`);
|
|
39
|
+
const ms = Number(match[1]) * unitMs[match[2]];
|
|
40
|
+
if (ms <= 0)
|
|
41
|
+
throw new Error(`a duration is longer than zero: ${duration}`);
|
|
42
|
+
return ms;
|
|
43
|
+
}
|
|
44
|
+
|
|
2
45
|
// src/define.ts
|
|
3
46
|
function definePlugin(plugin) {
|
|
4
47
|
return plugin;
|
|
@@ -10,14 +53,34 @@ function method(input, run, options = {}) {
|
|
|
10
53
|
kind: options.kind ?? "mutation",
|
|
11
54
|
output: options.output,
|
|
12
55
|
description: options.description,
|
|
13
|
-
confirm: options.confirm
|
|
56
|
+
confirm: options.confirm,
|
|
57
|
+
http: options.http === true ? "key" : options.http?.auth
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function cached(input, run, options) {
|
|
61
|
+
return {
|
|
62
|
+
input,
|
|
63
|
+
run,
|
|
64
|
+
kind: "query",
|
|
65
|
+
output: options.output,
|
|
66
|
+
description: options.description,
|
|
67
|
+
cache: { fresh: parseDuration(options.fresh), shared: options.shared ?? false, timeout: parseDuration(options.timeout ?? "1m") }
|
|
14
68
|
};
|
|
15
69
|
}
|
|
16
70
|
function stream(input, run, options = {}) {
|
|
17
71
|
return { input, run, kind: "stream", description: options.description };
|
|
18
72
|
}
|
|
19
|
-
// src/
|
|
73
|
+
// src/uploads.ts
|
|
74
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
20
75
|
import { z } from "zod";
|
|
76
|
+
var callFiles = new AsyncLocalStorage;
|
|
77
|
+
function upload() {
|
|
78
|
+
return z.object({ id: z.string(), name: z.string(), type: z.string(), size: z.number(), path: z.string() }).refine((file) => (callFiles.getStore() ?? []).some((held) => held.id === file.id && held.path === file.path), {
|
|
79
|
+
message: "Not a file uploaded for this call."
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
// src/errors.ts
|
|
83
|
+
import { z as z2 } from "zod";
|
|
21
84
|
|
|
22
85
|
class MethodError extends Error {
|
|
23
86
|
code;
|
|
@@ -32,7 +95,7 @@ function toCallError(error) {
|
|
|
32
95
|
if (error instanceof MethodError) {
|
|
33
96
|
return { code: error.code, message: error.message, ...error.fieldErrors ? { fieldErrors: error.fieldErrors } : {} };
|
|
34
97
|
}
|
|
35
|
-
if (error instanceof
|
|
98
|
+
if (error instanceof z2.ZodError) {
|
|
36
99
|
const fieldErrors = {};
|
|
37
100
|
for (const issue of error.issues)
|
|
38
101
|
fieldErrors["/" + issue.path.join("/")] ??= issue.message;
|
|
@@ -44,12 +107,44 @@ function toCallError(error) {
|
|
|
44
107
|
}
|
|
45
108
|
|
|
46
109
|
// src/index.ts
|
|
47
|
-
import { z as
|
|
110
|
+
import { z as z3 } from "zod";
|
|
111
|
+
|
|
112
|
+
// src/workflow/scope.ts
|
|
113
|
+
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
114
|
+
var attemptScope = new AsyncLocalStorage2;
|
|
115
|
+
var workflowScope = new AsyncLocalStorage2;
|
|
116
|
+
|
|
117
|
+
// src/workflow/definition.ts
|
|
118
|
+
function workflowContext(base, run) {
|
|
119
|
+
return {
|
|
120
|
+
...base,
|
|
121
|
+
...run,
|
|
122
|
+
get signal() {
|
|
123
|
+
return attemptScope.getStore()?.signal ?? run.signal;
|
|
124
|
+
},
|
|
125
|
+
step: { run: (name, callback, options) => run.step.run(name, (context) => callback({ ...context, runId: run.runId, idempotencyKey: `${run.runId}:${name}` }), options) }
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function workflow(input, run, options = {}) {
|
|
129
|
+
return { input, run, ...options };
|
|
130
|
+
}
|
|
131
|
+
// src/workflow/errors.ts
|
|
132
|
+
class NonRetryable extends Error {
|
|
133
|
+
constructor(message) {
|
|
134
|
+
super(message);
|
|
135
|
+
this.name = "NonRetryable";
|
|
136
|
+
}
|
|
137
|
+
}
|
|
48
138
|
export {
|
|
49
|
-
|
|
139
|
+
z3 as z,
|
|
140
|
+
workflow,
|
|
141
|
+
upload,
|
|
50
142
|
toCallError,
|
|
51
143
|
stream,
|
|
52
144
|
method,
|
|
53
145
|
definePlugin,
|
|
146
|
+
cached,
|
|
147
|
+
NonRetryable,
|
|
54
148
|
MethodError
|
|
55
149
|
};
|
|
150
|
+
export { parseDuration, callFiles, MethodError, toCallError, attemptScope, workflowScope, workflowContext, exports_src };
|
package/dist/logs.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
import type { Caller } from "./context";
|
|
3
|
+
export type LogLevel = "debug" | "info" | "warn" | "error";
|
|
4
|
+
export type LogRecord = {
|
|
5
|
+
/** ms since the epoch. */
|
|
6
|
+
at: number;
|
|
7
|
+
plugin: string;
|
|
8
|
+
level: LogLevel;
|
|
9
|
+
/** `<plugin>.<method>` of the run the line was written in; empty outside a run. */
|
|
10
|
+
method: string;
|
|
11
|
+
caller: Caller | "";
|
|
12
|
+
/** One id per outermost call, so a call's lines read together. */
|
|
13
|
+
callId: string;
|
|
14
|
+
/** The chat whose agent made the call, for `caller: "agent"`. */
|
|
15
|
+
chatId: string;
|
|
16
|
+
/** The arguments formatted as the console prints them, at most `textLimit` characters. */
|
|
17
|
+
text: string;
|
|
18
|
+
/** The arguments as given, as JSON can carry them. */
|
|
19
|
+
data: unknown[];
|
|
20
|
+
};
|
|
21
|
+
/** What a line is attributed to: the plugin, and the run when there is one. */
|
|
22
|
+
export type LogContext = {
|
|
23
|
+
plugin: string;
|
|
24
|
+
method?: string;
|
|
25
|
+
caller?: Caller;
|
|
26
|
+
callId?: string;
|
|
27
|
+
chatId?: string;
|
|
28
|
+
};
|
|
29
|
+
/** The run the code writing a line is in; the runtime sets it around every method, handler and cron. */
|
|
30
|
+
export declare const logContext: AsyncLocalStorage<LogContext>;
|
|
31
|
+
/**
|
|
32
|
+
* Runs `work` as an outermost run under `context`. An error nothing catches
|
|
33
|
+
* reaches its handler with no async context, so the newest run going is the
|
|
34
|
+
* best guess at whose it is.
|
|
35
|
+
*/
|
|
36
|
+
export declare function runWith<T>(context: LogContext, work: () => Promise<T>): Promise<T>;
|
|
37
|
+
/** A line longer than this is cut: a dumped payload is read in the plugin's own data, not its log. */
|
|
38
|
+
export declare const textLimit: number;
|
|
39
|
+
type Sink = (record: LogRecord) => void;
|
|
40
|
+
/**
|
|
41
|
+
* Replaces `console.log`, `info`, `debug`, `warn` and `error` with ones that
|
|
42
|
+
* record each call. `passThrough` keeps printing them too, for tests.
|
|
43
|
+
*/
|
|
44
|
+
export declare function captureConsole(to: Sink, options?: {
|
|
45
|
+
passThrough?: boolean;
|
|
46
|
+
}): void;
|
|
47
|
+
/** Puts the console back and stops recording. */
|
|
48
|
+
export declare function releaseConsole(): void;
|
|
49
|
+
/**
|
|
50
|
+
* Records one line under `context`, else the current run, else the newest run
|
|
51
|
+
* going, as an error nothing caught lands in. With no capture installed the
|
|
52
|
+
* line prints as the console would.
|
|
53
|
+
*/
|
|
54
|
+
export declare function record(level: LogLevel, args: unknown[], context?: LogContext): void;
|
|
55
|
+
export {};
|