@camerontaylor/paseo-plugin 0.11.0-beta.1.fork.1 → 0.11.1-fork.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/contracts.d.ts +5 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/sdk-specifiers.d.ts +3 -0
- package/dist/sdk-specifiers.js +18 -0
- package/dist/server/acp-internal/connection.js +5 -5
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +1 -1
- package/dist/server/lifecycle.d.ts +3 -0
- package/dist/server/process-internal/windows-command.d.ts +15 -0
- package/dist/server/process-internal/windows-command.js +41 -0
- package/dist/server/process.d.ts +25 -0
- package/dist/server/process.js +71 -0
- package/dist/server/provider.d.ts +2 -0
- package/dist/server/usage.d.ts +66 -11
- package/dist/server/usage.js +49 -7
- package/package.json +5 -5
|
@@ -103,6 +103,11 @@ interface PluginClientContextAliases {
|
|
|
103
103
|
addSidebarItem(contribution: PluginSidebarContribution): PluginCleanup;
|
|
104
104
|
}
|
|
105
105
|
export interface PluginClientContext extends PluginCommandCapabilities, PluginClientContextAliases {
|
|
106
|
+
/** Play a base64-encoded audio file on this client; resolves when playback ends. */
|
|
107
|
+
playAudio(source: {
|
|
108
|
+
base64: string;
|
|
109
|
+
mimeType: string;
|
|
110
|
+
}): Promise<void>;
|
|
106
111
|
addSettingsScreen(contribution: PluginSettingsScreenContribution): PluginCleanup;
|
|
107
112
|
addScreen(contribution: PluginScreenContribution): PluginCleanup;
|
|
108
113
|
addSidebarHeaderItem(contribution: PluginSidebarItemContribution): PluginCleanup;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { PLUGIN_SDK_PACKAGE_NAMES, pluginSdkEntry } from "./sdk-specifiers.js";
|
|
1
2
|
export type { PluginTheme, PluginWorkspaceSnapshot, PluginAgentSnapshot, PluginThemeColors, PluginThemeContribution, PluginAttachmentSourceContribution, PluginTimelineData, PluginTimelineItem, PluginTimelineTransformResult, PluginCleanup, } from "./contracts.js";
|
|
2
3
|
export { defineSettings, settingsRpc, type SettingsDefinition } from "./settings.js";
|
|
3
4
|
export { defineAttachmentSource, PluginAttachmentItemSchema, PluginAttachmentSearchPayloadSchema, type PluginAttachmentItem, type PluginAttachmentSearchPayload, } from "./attachments.js";
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// Shared SDK entry. Keep runtime-specific imports and re-exports on /client or /server.
|
|
2
|
+
export { PLUGIN_SDK_PACKAGE_NAMES, pluginSdkEntry } from "./sdk-specifiers.js";
|
|
1
3
|
export { defineSettings, settingsRpc } from "./settings.js";
|
|
2
4
|
export { defineAttachmentSource, PluginAttachmentItemSchema, PluginAttachmentSearchPayloadSchema, } from "./attachments.js";
|
|
3
5
|
export { defineRpc } from "./rpc.js";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Preserve the public import identity through fork packaging, which rewrites
|
|
2
|
+
// quoted @getpaseo/* module paths to the fork scope. Both names use host modules.
|
|
3
|
+
export const PLUGIN_SDK_PACKAGE_NAMES = [
|
|
4
|
+
["@getpaseo", "plugin"].join("/"),
|
|
5
|
+
"@camerontaylor/paseo-plugin",
|
|
6
|
+
// The release transform rewrites this entry to the installed host SDK name.
|
|
7
|
+
"@camerontaylor/paseo-plugin",
|
|
8
|
+
];
|
|
9
|
+
export function pluginSdkEntry(specifier) {
|
|
10
|
+
for (const name of PLUGIN_SDK_PACKAGE_NAMES) {
|
|
11
|
+
if (specifier === name)
|
|
12
|
+
return "";
|
|
13
|
+
if (specifier.startsWith(`${name}/`))
|
|
14
|
+
return specifier.slice(name.length);
|
|
15
|
+
}
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=sdk-specifiers.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { spawnProcess, terminateProcess } from "../process.js";
|
|
2
2
|
import { Readable, Writable } from "node:stream";
|
|
3
3
|
import { ClientSideConnection, CLIENT_METHODS, PROTOCOL_VERSION, ndJsonStream, } from "@agentclientprotocol/sdk";
|
|
4
4
|
import { z } from "zod";
|
|
@@ -269,9 +269,9 @@ class AcpRuntime {
|
|
|
269
269
|
args: options.options.command.slice(1),
|
|
270
270
|
env: process.env,
|
|
271
271
|
};
|
|
272
|
-
child =
|
|
272
|
+
child = spawnProcess(launch.command, launch.args, {
|
|
273
273
|
env: { ...launch.env, ...options.env },
|
|
274
|
-
stdio:
|
|
274
|
+
stdio: "pipe",
|
|
275
275
|
});
|
|
276
276
|
spawnFailure = new Promise((_resolve, reject) => child.once("error", reject));
|
|
277
277
|
child.stderr.on("data", () => undefined);
|
|
@@ -587,10 +587,10 @@ class AcpRuntime {
|
|
|
587
587
|
if (child.exitCode !== null || child.signalCode !== null)
|
|
588
588
|
return;
|
|
589
589
|
const closed = new Promise((resolve) => child.once("close", () => resolve()));
|
|
590
|
-
child
|
|
590
|
+
await terminateProcess(child, "SIGTERM");
|
|
591
591
|
if (await settlesWithin(closed, 1000))
|
|
592
592
|
return;
|
|
593
|
-
child
|
|
593
|
+
await terminateProcess(child);
|
|
594
594
|
if (!(await settlesWithin(closed, 1000))) {
|
|
595
595
|
throw new Error(`ACP provider ${this.options.options.id} did not terminate after SIGKILL`);
|
|
596
596
|
}
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export type { UsageSourceRegistration, UsageReport, UsageWindow, UsageBalance, UsageDetail, } from "./usage.js";
|
|
2
2
|
export type { PluginHandlerContext, PluginServerContext, PluginServerContribution, PluginSettings, PluginSettingsState, } from "./contracts.js";
|
|
3
3
|
export type { PluginHookContext, PluginHookWorkspace, PluginHookAgent, PluginSessionOpenRequest, PluginTurnOutcome, PluginLifecycleEvents, PluginBeforeRequests, PluginLifecycleRegistration, } from "./lifecycle.js";
|
|
4
|
+
export { spawnProcess, execCommand, terminateProcess } from "./process.js";
|
|
4
5
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/server/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {};
|
|
1
|
+
export { spawnProcess, execCommand, terminateProcess } from "./process.js";
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare function isWindowsCommandScript(executablePath: string): boolean;
|
|
2
|
+
/**
|
|
3
|
+
* When spawning with `shell: true` on Windows, the command is passed to
|
|
4
|
+
* `cmd.exe /d /s /c "command args"`. The `/s` strips outer quotes, so a
|
|
5
|
+
* command path with spaces (e.g. `C:\Program Files\...`) is split at the
|
|
6
|
+
* space. Wrapping it in quotes produces the correct `"C:\Program Files\..." args`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function quoteWindowsCommand(command: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* `spawn(..., { shell: true })` on Windows also passes argv through `cmd.exe`.
|
|
11
|
+
* Any argument containing spaces must be quoted or it will be split before the
|
|
12
|
+
* child process sees it.
|
|
13
|
+
*/
|
|
14
|
+
export declare function quoteWindowsArgument(argument: string): string;
|
|
15
|
+
//# sourceMappingURL=windows-command.d.ts.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { extname } from "node:path";
|
|
2
|
+
export function isWindowsCommandScript(executablePath) {
|
|
3
|
+
const extension = extname(executablePath).toLowerCase();
|
|
4
|
+
return process.platform === "win32" && (extension === ".cmd" || extension === ".bat");
|
|
5
|
+
}
|
|
6
|
+
function escapeWindowsCmdValue(value) {
|
|
7
|
+
if (process.platform !== "win32")
|
|
8
|
+
return value;
|
|
9
|
+
const isQuoted = value.startsWith('"') && value.endsWith('"');
|
|
10
|
+
const unquoted = isQuoted ? value.slice(1, -1) : value;
|
|
11
|
+
// Do NOT double `%` here. cmd.exe only collapses `%%` → `%` inside batch
|
|
12
|
+
// files; on the command line / `cmd /c "..."` `%%` stays literal, which
|
|
13
|
+
// breaks args like git's `--format=%(refname)` (git treats `%%` as the
|
|
14
|
+
// escape for a literal `%`, so the format atoms become literals).
|
|
15
|
+
const escaped = unquoted.replace(/([&|^<>()!])/g, "^$1");
|
|
16
|
+
if (isQuoted || /[\s"]/u.test(unquoted)) {
|
|
17
|
+
const quoted = escaped
|
|
18
|
+
.replace(/(\\*)"/g, (_match, slashes) => `${slashes}${slashes}\\"`)
|
|
19
|
+
.replace(/\\+$/u, (slashes) => `${slashes}${slashes}`);
|
|
20
|
+
return `"${quoted}"`;
|
|
21
|
+
}
|
|
22
|
+
return escaped;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* When spawning with `shell: true` on Windows, the command is passed to
|
|
26
|
+
* `cmd.exe /d /s /c "command args"`. The `/s` strips outer quotes, so a
|
|
27
|
+
* command path with spaces (e.g. `C:\Program Files\...`) is split at the
|
|
28
|
+
* space. Wrapping it in quotes produces the correct `"C:\Program Files\..." args`.
|
|
29
|
+
*/
|
|
30
|
+
export function quoteWindowsCommand(command) {
|
|
31
|
+
return escapeWindowsCmdValue(command);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* `spawn(..., { shell: true })` on Windows also passes argv through `cmd.exe`.
|
|
35
|
+
* Any argument containing spaces must be quoted or it will be split before the
|
|
36
|
+
* child process sees it.
|
|
37
|
+
*/
|
|
38
|
+
export function quoteWindowsArgument(argument) {
|
|
39
|
+
return escapeWindowsCmdValue(argument);
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=windows-command.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type ChildProcess, type ChildProcessWithoutNullStreams, type SpawnOptions } from "node:child_process";
|
|
2
|
+
export interface ExecCommandOptions {
|
|
3
|
+
env?: NodeJS.ProcessEnv;
|
|
4
|
+
cwd?: string;
|
|
5
|
+
encoding?: BufferEncoding;
|
|
6
|
+
killSignal?: NodeJS.Signals;
|
|
7
|
+
timeout?: number;
|
|
8
|
+
maxBuffer?: number;
|
|
9
|
+
shell?: boolean | string;
|
|
10
|
+
signal?: AbortSignal;
|
|
11
|
+
}
|
|
12
|
+
interface ExecCommandResult {
|
|
13
|
+
stdout: string;
|
|
14
|
+
stderr: string;
|
|
15
|
+
}
|
|
16
|
+
/** Launch a CLI with Windows command-script handling and argv quoting. The caller owns env. */
|
|
17
|
+
export declare function spawnProcess(command: string, args: string[], options: SpawnOptions & {
|
|
18
|
+
stdio: "pipe";
|
|
19
|
+
}): ChildProcessWithoutNullStreams;
|
|
20
|
+
export declare function spawnProcess(command: string, args: string[], options?: SpawnOptions): ChildProcess;
|
|
21
|
+
export declare function execCommand(command: string, args: string[], options?: ExecCommandOptions): Promise<ExecCommandResult>;
|
|
22
|
+
/** Force-stop a CLI, including descendants behind Windows command-script launchers. */
|
|
23
|
+
export declare function terminateProcess(child: ChildProcess, signal?: NodeJS.Signals): Promise<void>;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=process.d.ts.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { execFile, spawn, } from "node:child_process";
|
|
2
|
+
import { extname } from "node:path";
|
|
3
|
+
import { promisify } from "node:util";
|
|
4
|
+
import { isWindowsCommandScript, quoteWindowsArgument, quoteWindowsCommand, } from "./process-internal/windows-command.js";
|
|
5
|
+
const execFileAsync = promisify(execFile);
|
|
6
|
+
function hasPathSeparator(value) {
|
|
7
|
+
return value.includes("/") || value.includes("\\");
|
|
8
|
+
}
|
|
9
|
+
function shouldUseWindowsShell(command, requestedShell) {
|
|
10
|
+
if (isWindowsCommandScript(command)) {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
if (requestedShell !== undefined) {
|
|
14
|
+
return requestedShell;
|
|
15
|
+
}
|
|
16
|
+
return process.platform === "win32" && !hasPathSeparator(command) && !extname(command);
|
|
17
|
+
}
|
|
18
|
+
export function spawnProcess(command, args, options) {
|
|
19
|
+
const spawnOptions = options ?? {};
|
|
20
|
+
const isWindows = process.platform === "win32";
|
|
21
|
+
const shell = shouldUseWindowsShell(command, spawnOptions.shell);
|
|
22
|
+
const shouldQuoteForShell = isWindows && shell !== false;
|
|
23
|
+
const resolvedCommand = shouldQuoteForShell ? quoteWindowsCommand(command) : command;
|
|
24
|
+
const resolvedArgs = shouldQuoteForShell ? args.map(quoteWindowsArgument) : args;
|
|
25
|
+
return spawn(resolvedCommand, resolvedArgs, {
|
|
26
|
+
...spawnOptions,
|
|
27
|
+
env: options?.env,
|
|
28
|
+
shell,
|
|
29
|
+
signal: options?.signal,
|
|
30
|
+
windowsHide: true,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
export async function execCommand(command, args, options) {
|
|
34
|
+
const isWindows = process.platform === "win32";
|
|
35
|
+
const shell = shouldUseWindowsShell(command, options?.shell);
|
|
36
|
+
const shouldQuoteForShell = isWindows && shell !== false;
|
|
37
|
+
const resolvedCommand = shouldQuoteForShell ? quoteWindowsCommand(command) : command;
|
|
38
|
+
const resolvedArgs = shouldQuoteForShell ? args.map(quoteWindowsArgument) : args;
|
|
39
|
+
return execFileAsync(resolvedCommand, resolvedArgs, {
|
|
40
|
+
cwd: options?.cwd,
|
|
41
|
+
env: options?.env,
|
|
42
|
+
encoding: options?.encoding ?? "utf8",
|
|
43
|
+
signal: options?.signal,
|
|
44
|
+
killSignal: options?.killSignal,
|
|
45
|
+
timeout: options?.timeout,
|
|
46
|
+
maxBuffer: options?.maxBuffer,
|
|
47
|
+
shell,
|
|
48
|
+
windowsHide: true,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/** Force-stop a CLI, including descendants behind Windows command-script launchers. */
|
|
52
|
+
export async function terminateProcess(child, signal = "SIGKILL") {
|
|
53
|
+
if (process.platform !== "win32") {
|
|
54
|
+
child.kill(signal);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (child.pid === undefined)
|
|
58
|
+
return;
|
|
59
|
+
try {
|
|
60
|
+
await execCommand("taskkill.exe", ["/PID", String(child.pid), "/T", "/F"], {
|
|
61
|
+
shell: false,
|
|
62
|
+
timeout: 5000,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
// The process can finish between its close check and taskkill.
|
|
67
|
+
if (!(error instanceof Error && "code" in error && error.code === 128))
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=process.js.map
|
|
@@ -4,6 +4,8 @@ export declare const PROVIDER_PROTOCOL_VERSION: 1;
|
|
|
4
4
|
export declare const PROVIDER_CAPABILITIES: readonly ["prompt.message", "prompt.command", "prompt.image", "prompt.output_schema", "prompt.steer", "session.archive", "session.configure", "session.list", "session.persistence", "session.revert.both", "session.revert.conversation", "session.revert.files", "session.subsession", "session.unarchive", "permission", "permission.tool_policy", "timeline.plugin"];
|
|
5
5
|
export type ProviderCapability = (typeof PROVIDER_CAPABILITIES)[number];
|
|
6
6
|
export interface ProviderRegistration {
|
|
7
|
+
/** False rejects nonempty system instructions. Omission preserves the existing provider contract. */
|
|
8
|
+
supportsSystemPrompt?: boolean;
|
|
7
9
|
/** Equal keys share discovery within this provider. Include effective configuration and execution environment. */
|
|
8
10
|
getCatalogCacheKey?(options: ProviderCatalogOptions): Promise<string | undefined>;
|
|
9
11
|
/** Default executable and arguments; the daemon resolves overrides before status/connect. */
|
package/dist/server/usage.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { z, type ZodType } from "zod";
|
|
2
2
|
import type { JsonValue } from "@camerontaylor/paseo-protocol/agent-types";
|
|
3
3
|
export interface UsageWindow {
|
|
4
4
|
id: string;
|
|
@@ -33,26 +33,58 @@ export interface UsageDetail {
|
|
|
33
33
|
value: string;
|
|
34
34
|
tone?: UsageWindow["tone"];
|
|
35
35
|
}
|
|
36
|
-
export
|
|
37
|
-
|
|
36
|
+
export type UsageProblem = {
|
|
37
|
+
kind: "expired";
|
|
38
|
+
expiresAt: string;
|
|
39
|
+
refreshedBy?: string;
|
|
40
|
+
} | {
|
|
41
|
+
kind: "rejected";
|
|
42
|
+
status: number;
|
|
43
|
+
refreshedBy?: string;
|
|
44
|
+
} | {
|
|
45
|
+
kind: "no_quota";
|
|
46
|
+
detail: string;
|
|
47
|
+
};
|
|
48
|
+
export type UsageReport = {
|
|
49
|
+
status: "available";
|
|
38
50
|
planLabel?: string;
|
|
39
51
|
windows: UsageWindow[];
|
|
40
52
|
balances?: UsageBalance[];
|
|
41
53
|
details?: UsageDetail[];
|
|
42
|
-
|
|
54
|
+
} | {
|
|
55
|
+
status: "unavailable";
|
|
56
|
+
problem: UsageProblem;
|
|
57
|
+
} | {
|
|
58
|
+
status: "error";
|
|
59
|
+
error: string;
|
|
60
|
+
};
|
|
61
|
+
export interface UsageAccount {
|
|
62
|
+
/** Stable across token rotation; [A-Za-z0-9._-]{1,128}. Never a credential or raw email. */
|
|
63
|
+
key: string;
|
|
64
|
+
label?: string;
|
|
65
|
+
/** Harness owning this login, e.g. Codex, OpenCode, Pi or OMP. */
|
|
66
|
+
harness?: string;
|
|
67
|
+
/** Store locator, opaque to the daemon. */
|
|
68
|
+
input: JsonValue;
|
|
43
69
|
}
|
|
70
|
+
export declare const UsageScopeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
71
|
+
kind: z.ZodLiteral<"global">;
|
|
72
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
73
|
+
kind: z.ZodLiteral<"session">;
|
|
74
|
+
provider: z.ZodString;
|
|
75
|
+
model: z.ZodOptional<z.ZodString>;
|
|
76
|
+
env: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
77
|
+
}, z.core.$strip>], "kind">;
|
|
78
|
+
export type UsageScope = z.infer<typeof UsageScopeSchema>;
|
|
44
79
|
export interface UsageSourceRegistration {
|
|
45
80
|
id: string;
|
|
46
81
|
label: string;
|
|
47
82
|
icon?: string;
|
|
48
83
|
input: ZodType;
|
|
49
|
-
/**
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
label?: string;
|
|
53
|
-
} | null>;
|
|
84
|
+
/** Accounts for this scope only. The same key in any scope identifies the same account. */
|
|
85
|
+
discover(scope: UsageScope): Promise<UsageAccount[]>;
|
|
86
|
+
/** Re-reads the login store; never writes it. */
|
|
54
87
|
fetch(input: unknown): Promise<UsageReport>;
|
|
55
|
-
discover(): Promise<JsonValue[]>;
|
|
56
88
|
}
|
|
57
89
|
export declare function windowFromUsedPct(input: {
|
|
58
90
|
id: string;
|
|
@@ -63,6 +95,29 @@ export declare function windowFromUsedPct(input: {
|
|
|
63
95
|
resetsAt?: string | null;
|
|
64
96
|
tone?: UsageWindow["tone"];
|
|
65
97
|
}): UsageWindow;
|
|
98
|
+
/**
|
|
99
|
+
* Numeric provider windows have one identity and vocabulary, independent of response slots.
|
|
100
|
+
* Pass null when the provider omits the duration; reset countdowns are not window lengths.
|
|
101
|
+
* Named API fields (weekly, monthly, etc.) use windowFromUsedPct instead.
|
|
102
|
+
*/
|
|
103
|
+
export declare function windowFromReportedDuration(input: {
|
|
104
|
+
durationSeconds: number | null;
|
|
105
|
+
/** Stable quota identity and provider name for a model- or feature-scoped limit. */
|
|
106
|
+
scope?: {
|
|
107
|
+
id: string;
|
|
108
|
+
label: string;
|
|
109
|
+
};
|
|
110
|
+
/** Neutral identity and names when the provider does not report a positive duration. */
|
|
111
|
+
unknown: {
|
|
112
|
+
id: string;
|
|
113
|
+
label: string;
|
|
114
|
+
shortLabel: string;
|
|
115
|
+
};
|
|
116
|
+
utilizationPct: number | null | undefined;
|
|
117
|
+
resetsAt?: string | null;
|
|
118
|
+
summary?: boolean;
|
|
119
|
+
tone?: UsageWindow["tone"];
|
|
120
|
+
}): UsageWindow;
|
|
66
121
|
/**
|
|
67
122
|
* The tone scale for anything measured against a known limit, windows and balances alike.
|
|
68
123
|
*
|
|
@@ -81,5 +136,5 @@ export declare function balanceToneFromRemaining(remaining: number | null | unde
|
|
|
81
136
|
/** Percentage of a limit consumed, or null when either side is unknown. */
|
|
82
137
|
export declare function usedPctOf(used: number | null | undefined, limit: number | null | undefined): number | null;
|
|
83
138
|
export declare function hashAccountKey(value: string): string;
|
|
84
|
-
export declare function
|
|
139
|
+
export declare function unavailable(problem: UsageProblem): UsageReport;
|
|
85
140
|
//# sourceMappingURL=usage.d.ts.map
|
package/dist/server/usage.js
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
export const UsageScopeSchema = z.discriminatedUnion("kind", [
|
|
4
|
+
z.object({ kind: z.literal("global") }),
|
|
5
|
+
z.object({
|
|
6
|
+
kind: z.literal("session"),
|
|
7
|
+
provider: z.string(),
|
|
8
|
+
model: z.string().optional(),
|
|
9
|
+
env: z.record(z.string(), z.string()),
|
|
10
|
+
}),
|
|
11
|
+
]);
|
|
2
12
|
export function windowFromUsedPct(input) {
|
|
3
13
|
const usedPct = typeof input.utilizationPct === "number" ? input.utilizationPct : null;
|
|
4
14
|
const window = {
|
|
@@ -16,6 +26,43 @@ export function windowFromUsedPct(input) {
|
|
|
16
26
|
window.tone = input.tone;
|
|
17
27
|
return window;
|
|
18
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Numeric provider windows have one identity and vocabulary, independent of response slots.
|
|
31
|
+
* Pass null when the provider omits the duration; reset countdowns are not window lengths.
|
|
32
|
+
* Named API fields (weekly, monthly, etc.) use windowFromUsedPct instead.
|
|
33
|
+
*/
|
|
34
|
+
export function windowFromReportedDuration(input) {
|
|
35
|
+
const duration = input.durationSeconds;
|
|
36
|
+
const name = duration !== null && Number.isFinite(duration) && duration > 0
|
|
37
|
+
? durationWindowName(duration)
|
|
38
|
+
: input.unknown;
|
|
39
|
+
const scope = input.scope;
|
|
40
|
+
return windowFromUsedPct({
|
|
41
|
+
id: scope ? `${scope.id}:${name.id}` : name.id,
|
|
42
|
+
label: scope ? `${scope.label} · ${name.label}` : name.label,
|
|
43
|
+
shortLabel: scope
|
|
44
|
+
? `${scope.label}${name.shortLabel ? ` ${name.shortLabel}` : ""}`
|
|
45
|
+
: name.shortLabel,
|
|
46
|
+
utilizationPct: input.utilizationPct,
|
|
47
|
+
resetsAt: input.resetsAt,
|
|
48
|
+
summary: input.summary,
|
|
49
|
+
tone: input.tone,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
function durationWindowName(seconds) {
|
|
53
|
+
if (seconds === 604800)
|
|
54
|
+
return { id: "weekly", label: "Weekly", shortLabel: "wk" };
|
|
55
|
+
const id = seconds === 18000 ? "five_hour" : `${seconds}s`;
|
|
56
|
+
const units = [
|
|
57
|
+
[86400, "day", "d"],
|
|
58
|
+
[3600, "hour", "h"],
|
|
59
|
+
[60, "minute", "m"],
|
|
60
|
+
[1, "second", "s"],
|
|
61
|
+
];
|
|
62
|
+
const unit = units.find(([size]) => seconds % size === 0) ?? units[units.length - 1];
|
|
63
|
+
const amount = seconds / unit[0];
|
|
64
|
+
return { id, label: `${amount}-${unit[1]}`, shortLabel: `${amount}${unit[2]}` };
|
|
65
|
+
}
|
|
19
66
|
/**
|
|
20
67
|
* The tone scale for anything measured against a known limit, windows and balances alike.
|
|
21
68
|
*
|
|
@@ -54,12 +101,7 @@ export function usedPctOf(used, limit) {
|
|
|
54
101
|
export function hashAccountKey(value) {
|
|
55
102
|
return createHash("sha256").update(value).digest("hex");
|
|
56
103
|
}
|
|
57
|
-
export function
|
|
58
|
-
return {
|
|
59
|
-
status: "unavailable",
|
|
60
|
-
windows: [],
|
|
61
|
-
balances: [],
|
|
62
|
-
details: [],
|
|
63
|
-
};
|
|
104
|
+
export function unavailable(problem) {
|
|
105
|
+
return { status: "unavailable", problem };
|
|
64
106
|
}
|
|
65
107
|
//# sourceMappingURL=usage.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camerontaylor/paseo-plugin",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.1-fork.1",
|
|
4
4
|
"description": "Paseo plugin SDK package",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -70,8 +70,8 @@
|
|
|
70
70
|
"use-sync-external-store": "^1.6.0"
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
|
-
"@camerontaylor/paseo-client": "0.11.
|
|
74
|
-
"@camerontaylor/paseo-protocol": "0.11.
|
|
73
|
+
"@camerontaylor/paseo-client": "0.11.1-fork.1",
|
|
74
|
+
"@camerontaylor/paseo-protocol": "0.11.1-fork.1",
|
|
75
75
|
"@types/node": "^20.9.0",
|
|
76
76
|
"@types/react": "~19.2.0",
|
|
77
77
|
"react": "19.1.0",
|
|
@@ -81,8 +81,8 @@
|
|
|
81
81
|
"zod": "^4.4.3"
|
|
82
82
|
},
|
|
83
83
|
"peerDependencies": {
|
|
84
|
-
"@camerontaylor/paseo-client": "0.11.
|
|
85
|
-
"@camerontaylor/paseo-protocol": "0.11.
|
|
84
|
+
"@camerontaylor/paseo-client": "0.11.1-fork.1",
|
|
85
|
+
"@camerontaylor/paseo-protocol": "0.11.1-fork.1",
|
|
86
86
|
"react": "~19.1.0",
|
|
87
87
|
"react-native": ">=0.81.5",
|
|
88
88
|
"zod": "^4.4.3"
|