@tomradex/plugin-sdk 0.0.0-stage → 0.2.16
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/LICENSE +204 -0
- package/README.md +62 -2
- package/dist/cli-hooks.d.ts +8 -0
- package/dist/cli-hooks.js +27 -0
- package/dist/contract.d.ts +624 -0
- package/dist/contract.js +2 -0
- package/dist/define.d.ts +27 -0
- package/dist/define.js +16 -0
- package/dist/exports.d.ts +10 -0
- package/dist/exports.js +73 -0
- package/dist/im-markdown.d.ts +10 -0
- package/dist/im-markdown.js +257 -0
- package/dist/im.d.ts +319 -0
- package/dist/im.js +55 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +13 -0
- package/dist/language.d.ts +48 -0
- package/dist/language.js +62 -0
- package/dist/manifest.d.ts +202 -0
- package/dist/manifest.js +168 -0
- package/dist/models.d.ts +219 -0
- package/dist/models.js +2 -0
- package/dist/semver.d.ts +9 -0
- package/dist/semver.js +67 -0
- package/dist/terminals.d.ts +72 -0
- package/dist/terminals.js +2 -0
- package/dist/web-search.d.ts +54 -0
- package/dist/web-search.js +2 -0
- package/package.json +33 -4
package/dist/models.d.ts
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import type { Disposer, Localized, ModelMessage, ModelTool } from "./contract.js";
|
|
2
|
+
type Maybe<T> = T | Promise<T>;
|
|
3
|
+
/** What a model reads besides text. */
|
|
4
|
+
export type ModelInput = "image" | "audio" | "video" | "pdf";
|
|
5
|
+
/** What a model can answer with besides text. */
|
|
6
|
+
export type ModelOutput = "image" | "audio";
|
|
7
|
+
/** SDK 0.2.16. One assistant turn a profile on the provider is asked for. */
|
|
8
|
+
export interface ModelChatRequest {
|
|
9
|
+
system: string;
|
|
10
|
+
messages: ModelMessage[];
|
|
11
|
+
tools?: ModelTool[];
|
|
12
|
+
toolChoice?: "auto" | "none" | {
|
|
13
|
+
name: string;
|
|
14
|
+
};
|
|
15
|
+
maxTokens?: number;
|
|
16
|
+
temperature?: number;
|
|
17
|
+
/** Reasoning effort ("low", "medium", "high"…) where the model has the knob; ignore it otherwise. */
|
|
18
|
+
effort?: string;
|
|
19
|
+
/** Answer with a single JSON document. */
|
|
20
|
+
json?: boolean;
|
|
21
|
+
/** Search the web yourself; asked only of a model whose capabilities say `nativeWebSearch`. */
|
|
22
|
+
webSearch?: boolean;
|
|
23
|
+
/** Media the reply should carry; asked only of a model whose capabilities list it in `mediaOutput`. */
|
|
24
|
+
mediaOutput?: ModelOutput[];
|
|
25
|
+
}
|
|
26
|
+
/** What a turn streams, in order, ending with `stop`. A `native` block comes back in later requests as the provider's own record (server-side tool calls, signatures). */
|
|
27
|
+
export type ModelChatEvent = {
|
|
28
|
+
type: "text";
|
|
29
|
+
delta: string;
|
|
30
|
+
} | {
|
|
31
|
+
type: "media";
|
|
32
|
+
media: {
|
|
33
|
+
mime: string;
|
|
34
|
+
base64: string;
|
|
35
|
+
name: string;
|
|
36
|
+
};
|
|
37
|
+
} | {
|
|
38
|
+
type: "tool_call";
|
|
39
|
+
id: string;
|
|
40
|
+
name: string;
|
|
41
|
+
args: unknown;
|
|
42
|
+
} | {
|
|
43
|
+
type: "native";
|
|
44
|
+
provider: string;
|
|
45
|
+
data: unknown;
|
|
46
|
+
}
|
|
47
|
+
/** `inputTokens` counts every prompt token read, cached ones included. */
|
|
48
|
+
| {
|
|
49
|
+
type: "usage";
|
|
50
|
+
inputTokens?: number;
|
|
51
|
+
outputTokens?: number;
|
|
52
|
+
cacheReadTokens?: number;
|
|
53
|
+
cacheWriteTokens?: number;
|
|
54
|
+
}
|
|
55
|
+
/** The request failed before anything streamed and is sent again after `delayMs`. */
|
|
56
|
+
| {
|
|
57
|
+
type: "retry";
|
|
58
|
+
attempt: number;
|
|
59
|
+
max: number;
|
|
60
|
+
reason: string;
|
|
61
|
+
delayMs: number;
|
|
62
|
+
} | {
|
|
63
|
+
type: "stop";
|
|
64
|
+
reason: "end" | "tool_use" | "max_tokens" | "refusal";
|
|
65
|
+
};
|
|
66
|
+
export interface ModelChatCapabilities {
|
|
67
|
+
/** MIME types it reads (`image/png`, `application/pdf`…). */
|
|
68
|
+
mediaInput?: string[];
|
|
69
|
+
mediaOutput?: string[];
|
|
70
|
+
tools: boolean;
|
|
71
|
+
streaming: boolean;
|
|
72
|
+
json: boolean;
|
|
73
|
+
/** It searches the web on its own when a request sets `webSearch`. */
|
|
74
|
+
nativeWebSearch?: boolean;
|
|
75
|
+
}
|
|
76
|
+
/** One model as Tomrade's conversations, worker and tools talk to it. Throw with what the provider said when a request fails. */
|
|
77
|
+
export interface ModelChat {
|
|
78
|
+
capabilities: ModelChatCapabilities;
|
|
79
|
+
chat(request: ModelChatRequest, signal?: AbortSignal): AsyncIterable<ModelChatEvent>;
|
|
80
|
+
}
|
|
81
|
+
/** A saved model profile naming the provider. */
|
|
82
|
+
export interface ModelProfileInfo {
|
|
83
|
+
id: string;
|
|
84
|
+
title: string;
|
|
85
|
+
provider: string;
|
|
86
|
+
/** Absent: the provider's default address. */
|
|
87
|
+
baseURL?: string;
|
|
88
|
+
apiKey: string;
|
|
89
|
+
model: string;
|
|
90
|
+
inputModalities?: ModelInput[];
|
|
91
|
+
outputModalities?: ModelOutput[];
|
|
92
|
+
}
|
|
93
|
+
/** A well-known service the provider serves, offered in the model setup. */
|
|
94
|
+
export interface ModelPresetSpec {
|
|
95
|
+
/** Namespaced like every id a plugin registers. */
|
|
96
|
+
id: string;
|
|
97
|
+
title: string;
|
|
98
|
+
/** Absent: the provider's own address. */
|
|
99
|
+
baseURL?: string;
|
|
100
|
+
/** The model to start with; otherwise the newest listed one matching `prefer`, then the first listed. */
|
|
101
|
+
model?: string;
|
|
102
|
+
prefer?: RegExp[];
|
|
103
|
+
/** Where people get a key. */
|
|
104
|
+
keyPage?: string;
|
|
105
|
+
/** The variable people export the key as, which Tomrade looks for on this computer. */
|
|
106
|
+
env?: string;
|
|
107
|
+
/** What its keys look like, so a pasted key picks this preset. */
|
|
108
|
+
keyShapes?: RegExp[];
|
|
109
|
+
/** Runs on this computer and needs no key. */
|
|
110
|
+
local?: boolean;
|
|
111
|
+
/** One line under the preset in the setup. */
|
|
112
|
+
hint?: Localized;
|
|
113
|
+
}
|
|
114
|
+
export interface ModelMedia {
|
|
115
|
+
inputModalities: ModelInput[];
|
|
116
|
+
outputModalities: ModelOutput[];
|
|
117
|
+
}
|
|
118
|
+
/** The models an endpoint lists (null: it has no listing), or why the key or address does not work. */
|
|
119
|
+
export type ModelListing = {
|
|
120
|
+
ok: true;
|
|
121
|
+
models: string[] | null;
|
|
122
|
+
capabilities?: Record<string, ModelMedia>;
|
|
123
|
+
} | {
|
|
124
|
+
ok: false;
|
|
125
|
+
status?: number;
|
|
126
|
+
detail: string;
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* A sign-in the provider allows third-party apps instead of pasting a key: an
|
|
130
|
+
* OAuth flow that ends in a key (OpenRouter's PKCE), or credentials already on
|
|
131
|
+
* this computer. Never a consumer subscription its terms keep to the vendor's own apps.
|
|
132
|
+
*/
|
|
133
|
+
export interface ModelSignIn {
|
|
134
|
+
/** The button, such as "Sign in with OpenRouter". */
|
|
135
|
+
title: Localized;
|
|
136
|
+
/** Runs the sign-in; `open` shows a page in the person's browser. What it answers is kept as the profile's key. */
|
|
137
|
+
run(helpers: {
|
|
138
|
+
open(url: string): void;
|
|
139
|
+
signal: AbortSignal;
|
|
140
|
+
}): Promise<{
|
|
141
|
+
apiKey: string;
|
|
142
|
+
}>;
|
|
143
|
+
}
|
|
144
|
+
/** SDK 0.2.16. One way to talk to models, as the app's own providers are: what a profile's `provider` names. */
|
|
145
|
+
export interface ModelProviderSpec {
|
|
146
|
+
/** Namespaced like every id a plugin registers; profiles store it. */
|
|
147
|
+
id: string;
|
|
148
|
+
title: Localized;
|
|
149
|
+
/** False for an endpoint that works without a key, such as a local one. Default true. */
|
|
150
|
+
keyRequired?: boolean;
|
|
151
|
+
/** Where a profile without its own address talks; `editable: false` leaves the address out of the form. */
|
|
152
|
+
baseURL: {
|
|
153
|
+
default: string;
|
|
154
|
+
editable?: boolean;
|
|
155
|
+
};
|
|
156
|
+
/** False for an endpoint that only makes images. Default true. */
|
|
157
|
+
chat?: boolean;
|
|
158
|
+
presets?: ModelPresetSpec[];
|
|
159
|
+
/** Doubles as the key check when a profile is saved. */
|
|
160
|
+
list(endpoint: {
|
|
161
|
+
baseURL?: string;
|
|
162
|
+
apiKey: string;
|
|
163
|
+
}, signal: AbortSignal): Maybe<ModelListing>;
|
|
164
|
+
/** Of what the endpoint lists, the models a profile can use, best first. Default: all of them, as listed. */
|
|
165
|
+
usable?(listed: string[]): string[];
|
|
166
|
+
/** What its models read besides text when a profile stores nothing. */
|
|
167
|
+
defaultInput?: ModelInput[];
|
|
168
|
+
/** A model's media: what its listing entry says, else what the provider knows; undefined keeps a profile's stored values. */
|
|
169
|
+
capabilities?(model: string, listed?: ModelMedia): ModelMedia | undefined;
|
|
170
|
+
signIn?: ModelSignIn;
|
|
171
|
+
/** Called synchronously when a profile on it is first used, and again once the profile changes. */
|
|
172
|
+
build(profile: ModelProfileInfo): ModelChat;
|
|
173
|
+
}
|
|
174
|
+
/** A model on the app's own OpenAI-compatible adapter. */
|
|
175
|
+
export interface CompatibleModelOptions {
|
|
176
|
+
baseURL: string;
|
|
177
|
+
apiKey: string;
|
|
178
|
+
model: string;
|
|
179
|
+
inputModalities?: ModelInput[];
|
|
180
|
+
outputModalities?: ModelOutput[];
|
|
181
|
+
/**
|
|
182
|
+
* The model searches the web on its own when a request asks: `"chat"` on chat/completions, with
|
|
183
|
+
* the vendor's own flag set by `body`; `"responses"` on the Responses API. Absent, it does not.
|
|
184
|
+
*/
|
|
185
|
+
webSearch?: "chat" | "responses";
|
|
186
|
+
/** The last word on each chat/completions body (a copy of the request beside it): a vendor's own fields. Throw to fail the request. */
|
|
187
|
+
body?(json: Record<string, unknown>, request: ModelChatRequest): Record<string, unknown>;
|
|
188
|
+
/** The last word on each Responses body, where a searching request goes with `webSearch: "responses"`: the vendor's effort scale, its limits. Throw to fail the request. */
|
|
189
|
+
responses?(json: Record<string, unknown>, request: ModelChatRequest): Record<string, unknown>;
|
|
190
|
+
/**
|
|
191
|
+
* The headers of each request in place of `Authorization: Bearer <apiKey>`: a vendor's own key
|
|
192
|
+
* header, a token that expires, a signature over `url` and the exact `body` sent. Asked again
|
|
193
|
+
* before every try, retries included. Throw to fail the request.
|
|
194
|
+
*/
|
|
195
|
+
headers?(request: {
|
|
196
|
+
url: string;
|
|
197
|
+
body: string;
|
|
198
|
+
}): Maybe<Record<string, string>>;
|
|
199
|
+
}
|
|
200
|
+
export interface ModelsApi {
|
|
201
|
+
/** Serves the profiles naming `provider.id` and offers its presets until disposed or the plugin unloads. */
|
|
202
|
+
registerProvider(provider: ModelProviderSpec): Promise<Disposer>;
|
|
203
|
+
/**
|
|
204
|
+
* Synchronous, like `build`: a model on the app's own OpenAI-compatible adapter — streaming, tool
|
|
205
|
+
* calls, retries, media, the token-field quirks — for a vendor that serves chat/completions.
|
|
206
|
+
*/
|
|
207
|
+
compatible(options: CompatibleModelOptions): ModelChat;
|
|
208
|
+
/**
|
|
209
|
+
* The app's own listing of a chat/completions endpoint (`GET /models`), media read from it; one
|
|
210
|
+
* without a listing answers `models: null`. `headers` go in place of the bearer key.
|
|
211
|
+
*/
|
|
212
|
+
listCompatible(endpoint: {
|
|
213
|
+
baseURL: string;
|
|
214
|
+
apiKey: string;
|
|
215
|
+
headers?: Record<string, string>;
|
|
216
|
+
}, signal?: AbortSignal): Promise<ModelListing>;
|
|
217
|
+
}
|
|
218
|
+
export {};
|
|
219
|
+
//# sourceMappingURL=models.d.ts.map
|
package/dist/models.js
ADDED
package/dist/semver.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type Version = [number, number, number];
|
|
2
|
+
export declare function parseVersion(text: string): Version | null;
|
|
3
|
+
export declare const isVersion: (text: string) => boolean;
|
|
4
|
+
export declare function compareVersions(a: string, b: string): number;
|
|
5
|
+
/** The subset of npm ranges plugins need: `^`, `~`, comparisons, `*`, spaces for AND and `||` for OR. */
|
|
6
|
+
export declare function satisfies(version: string, range: string): boolean;
|
|
7
|
+
export declare const isRange: (range: string) => boolean;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=semver.d.ts.map
|
package/dist/semver.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const VERSION = /^(\d+)\.(\d+)\.(\d+)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
2
|
+
export function parseVersion(text) {
|
|
3
|
+
const m = VERSION.exec(text.trim());
|
|
4
|
+
return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;
|
|
5
|
+
}
|
|
6
|
+
export const isVersion = (text) => parseVersion(text) !== null;
|
|
7
|
+
export function compareVersions(a, b) {
|
|
8
|
+
const x = parseVersion(a);
|
|
9
|
+
const y = parseVersion(b);
|
|
10
|
+
if (!x || !y)
|
|
11
|
+
throw new Error(`not a version: ${!x ? a : b}`);
|
|
12
|
+
for (let i = 0; i < 3; i++)
|
|
13
|
+
if (x[i] !== y[i])
|
|
14
|
+
return x[i] - y[i];
|
|
15
|
+
return 0;
|
|
16
|
+
}
|
|
17
|
+
function comparator(version, token) {
|
|
18
|
+
const cmp = (v) => {
|
|
19
|
+
for (let i = 0; i < 3; i++)
|
|
20
|
+
if (version[i] !== v[i])
|
|
21
|
+
return version[i] - v[i];
|
|
22
|
+
return 0;
|
|
23
|
+
};
|
|
24
|
+
if (token === "*" || token === "x")
|
|
25
|
+
return true;
|
|
26
|
+
const op = /^(\^|~|>=|<=|>|<|=)?(.+)$/.exec(token);
|
|
27
|
+
if (!op)
|
|
28
|
+
return false;
|
|
29
|
+
const base = parseVersion(op[2]);
|
|
30
|
+
if (!base)
|
|
31
|
+
return false;
|
|
32
|
+
switch (op[1]) {
|
|
33
|
+
case "^": {
|
|
34
|
+
if (cmp(base) < 0)
|
|
35
|
+
return false;
|
|
36
|
+
if (base[0] > 0)
|
|
37
|
+
return version[0] === base[0];
|
|
38
|
+
if (base[1] > 0)
|
|
39
|
+
return version[0] === 0 && version[1] === base[1];
|
|
40
|
+
return version[0] === 0 && version[1] === 0 && version[2] === base[2];
|
|
41
|
+
}
|
|
42
|
+
case "~":
|
|
43
|
+
return cmp(base) >= 0 && version[0] === base[0] && version[1] === base[1];
|
|
44
|
+
case ">=":
|
|
45
|
+
return cmp(base) >= 0;
|
|
46
|
+
case "<=":
|
|
47
|
+
return cmp(base) <= 0;
|
|
48
|
+
case ">":
|
|
49
|
+
return cmp(base) > 0;
|
|
50
|
+
case "<":
|
|
51
|
+
return cmp(base) < 0;
|
|
52
|
+
default:
|
|
53
|
+
return cmp(base) === 0;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** The subset of npm ranges plugins need: `^`, `~`, comparisons, `*`, spaces for AND and `||` for OR. */
|
|
57
|
+
export function satisfies(version, range) {
|
|
58
|
+
const v = parseVersion(version);
|
|
59
|
+
if (!v)
|
|
60
|
+
return false;
|
|
61
|
+
return range.split("||").some((part) => {
|
|
62
|
+
const tokens = part.trim().split(/\s+/).filter(Boolean);
|
|
63
|
+
return tokens.length > 0 && tokens.every((token) => comparator(v, token));
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
export const isRange = (range) => range.split("||").every((part) => part.trim().split(/\s+/).filter(Boolean).every((t) => t === "*" || t === "x" || /^(\^|~|>=|<=|>|<|=)?\d+\.\d+\.\d+/.test(t)));
|
|
67
|
+
//# sourceMappingURL=semver.js.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { Disposer } from "./contract.js";
|
|
2
|
+
/** SDK 0.2.10. Whether herdr can hand over a live terminal, and the command that fixes it when it cannot. */
|
|
3
|
+
export type TerminalBridgeState = {
|
|
4
|
+
state: "ready";
|
|
5
|
+
version: string;
|
|
6
|
+
} | {
|
|
7
|
+
state: "unsupported";
|
|
8
|
+
} | {
|
|
9
|
+
state: "notInstalled";
|
|
10
|
+
} | {
|
|
11
|
+
state: "notRunning";
|
|
12
|
+
version: string;
|
|
13
|
+
} | {
|
|
14
|
+
state: "tooOld";
|
|
15
|
+
version: string;
|
|
16
|
+
need: string;
|
|
17
|
+
fix: string;
|
|
18
|
+
} | {
|
|
19
|
+
state: "stale";
|
|
20
|
+
version: string;
|
|
21
|
+
server: string;
|
|
22
|
+
fix: string;
|
|
23
|
+
};
|
|
24
|
+
/** One picture of the terminal: ANSI bytes that paint it — the whole viewport when `full`, else only the cells that changed. */
|
|
25
|
+
export interface TerminalFrame {
|
|
26
|
+
seq: number;
|
|
27
|
+
width: number;
|
|
28
|
+
height: number;
|
|
29
|
+
full: boolean;
|
|
30
|
+
bytes: Uint8Array;
|
|
31
|
+
}
|
|
32
|
+
/** A live terminal of a herdr pane. The frames repaint the viewport only: scrolling back is asked for with `scroll`. */
|
|
33
|
+
export interface TerminalHandle {
|
|
34
|
+
readonly paneId: string;
|
|
35
|
+
readonly mode: "control" | "observe";
|
|
36
|
+
onFrame(listener: (frame: TerminalFrame) => void): Disposer;
|
|
37
|
+
/** Once, when the stream ends: herdr's reason, or what it said when it would not attach. */
|
|
38
|
+
onClose(listener: (reason: string | null) => void): Disposer;
|
|
39
|
+
/** Keys and pastes; a controller's only — an observer's input is dropped. */
|
|
40
|
+
input(data: string | Uint8Array): void;
|
|
41
|
+
resize(cols: number, rows: number): void;
|
|
42
|
+
scroll(scroll: {
|
|
43
|
+
direction: "up" | "down";
|
|
44
|
+
lines: number;
|
|
45
|
+
column?: number;
|
|
46
|
+
row?: number;
|
|
47
|
+
modifiers?: number;
|
|
48
|
+
}): void;
|
|
49
|
+
mouse(mouse: {
|
|
50
|
+
action: "down" | "up" | "drag" | "move";
|
|
51
|
+
button?: "left" | "middle" | "right" | "none";
|
|
52
|
+
column: number;
|
|
53
|
+
row: number;
|
|
54
|
+
modifiers?: number;
|
|
55
|
+
}): void;
|
|
56
|
+
/** Detach: the pane keeps running in herdr. Also done for every terminal the plugin left open when it unloads. */
|
|
57
|
+
close(): void;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* SDK 0.2.10. Terminals of the herdr panes code sessions run in, through the
|
|
61
|
+
* app: a plugin neither reaches herdr's socket nor starts its CLI itself.
|
|
62
|
+
*/
|
|
63
|
+
export interface TerminalsApi {
|
|
64
|
+
state(): Promise<TerminalBridgeState>;
|
|
65
|
+
/** `control` (the default) takes input and size from any other owner; `observe` watches beside others. Rejects when `state()` is not ready. */
|
|
66
|
+
open(paneId: string, opts: {
|
|
67
|
+
mode?: "control" | "observe";
|
|
68
|
+
cols: number;
|
|
69
|
+
rows: number;
|
|
70
|
+
}): Promise<TerminalHandle>;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=terminals.d.ts.map
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { Disposer } from "./contract.js";
|
|
2
|
+
type Maybe<T> = T | Promise<T>;
|
|
3
|
+
/** SDK 0.2.9. What the agent's `web_search` asks for; defaults are filled in before a provider sees it. */
|
|
4
|
+
export interface WebSearchRequest {
|
|
5
|
+
query: string;
|
|
6
|
+
maxResults: number;
|
|
7
|
+
topic: "general" | "news";
|
|
8
|
+
timeRange?: "day" | "week" | "month" | "year";
|
|
9
|
+
includeDomains?: string[];
|
|
10
|
+
excludeDomains?: string[];
|
|
11
|
+
}
|
|
12
|
+
export interface WebSearchHit {
|
|
13
|
+
title: string;
|
|
14
|
+
url: string;
|
|
15
|
+
/** An excerpt, not the page. */
|
|
16
|
+
content: string;
|
|
17
|
+
published?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface WebReadRequest {
|
|
20
|
+
urls: string[];
|
|
21
|
+
/** Keep only the passages relevant to this. */
|
|
22
|
+
query?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface WebReadResponse {
|
|
25
|
+
pages: {
|
|
26
|
+
url: string;
|
|
27
|
+
content: string;
|
|
28
|
+
}[];
|
|
29
|
+
failed: {
|
|
30
|
+
url: string;
|
|
31
|
+
error: string;
|
|
32
|
+
}[];
|
|
33
|
+
}
|
|
34
|
+
/** One search backend, as the app's own providers are: the first registered one that is available answers. */
|
|
35
|
+
export interface WebSearchProviderSpec {
|
|
36
|
+
/** Namespaced like every id a plugin registers. */
|
|
37
|
+
id: string;
|
|
38
|
+
title: string;
|
|
39
|
+
/** Why it cannot answer yet (no API key, say), or null when it can. Called often and synchronously: keep it cheap. The agent reads it as the tool's error. */
|
|
40
|
+
unavailable(): string | null;
|
|
41
|
+
search(request: WebSearchRequest, signal: AbortSignal): Maybe<{
|
|
42
|
+
results: WebSearchHit[];
|
|
43
|
+
}>;
|
|
44
|
+
/** Pages as Markdown. Without it, `web_fetch` is left to another provider. */
|
|
45
|
+
read?(request: WebReadRequest, signal: AbortSignal): Maybe<WebReadResponse>;
|
|
46
|
+
/** The settings pane where the person sets it up: the plugin's own section id, or an app pane such as "assistant" (models). */
|
|
47
|
+
settings?: string;
|
|
48
|
+
}
|
|
49
|
+
export interface WebSearchApi {
|
|
50
|
+
/** Answers the agent's `web_search` (and `web_fetch`, with `read`) until disposed or the plugin unloads. */
|
|
51
|
+
register(provider: WebSearchProviderSpec): Promise<Disposer>;
|
|
52
|
+
}
|
|
53
|
+
export {};
|
|
54
|
+
//# sourceMappingURL=web-search.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tomradex/plugin-sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.16",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"author": "Haoyuan Tang",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=22"
|
|
8
|
+
},
|
|
9
|
+
"publishConfig": {
|
|
10
|
+
"access": "public"
|
|
11
|
+
},
|
|
12
|
+
"license": "Apache-2.0",
|
|
13
|
+
"description": "The Tomrade plugin contract: definePlugin, the async PluginContext every extension receives, and the manifest schema",
|
|
14
|
+
"keywords": [
|
|
15
|
+
"tomrade",
|
|
16
|
+
"tomrade-plugin",
|
|
17
|
+
"plugin",
|
|
18
|
+
"sdk"
|
|
19
|
+
],
|
|
20
|
+
"main": "dist/index.js",
|
|
21
|
+
"types": "dist/index.d.ts",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"default": "./dist/index.js"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist"
|
|
30
|
+
],
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@tomradex/domain": "0.2.16",
|
|
33
|
+
"zod": "^4.4.3"
|
|
34
|
+
}
|
|
35
|
+
}
|