跳到內容

Types

以下 types 都由 @kaoruisaac/pedelec export。

import type {
PedelecOptions,
ProviderCode,
EffortLevel,
Effort,
ProviderInfo,
PedelecSessionStatus,
PedelecSessionUsage,
ToolArgsSchema,
Asset,
AssetPath,
ReadAssetType,
PedelecWorkspace,
WorkspaceRunOptions,
WorkspaceRunResult,
} from "@kaoruisaac/pedelec";
type PedelecOptions = {
runtimeFullAccess?: boolean;
bridgeTimeoutMs?: number;
};
type ProviderCode =
| "codex"
| "antigravity"
| "opencode"
| "cursor"
| "claude"
| "ollama";
type EffortLevel = "default" | "low" | "high";

EffortLevel 是 Pedelec/Desktop profile selector。它會選擇一組完整的 Desktop profile,包含該 profile 設定的 model 與 provider-native effort。

type Effort = "low" | "medium" | "high" | "xhigh" | "max";

Effort 是 explicit model mode 使用的 provider-native reasoning effort。只有在提供 model 時才能使用,且本身是 optional;實際支援哪些值仍由 Core 依 provider 在 runtime 驗證。

type CreateSessionInput<
TTools extends readonly ToolDefinition[] = readonly ToolDefinition[],
> =
| {
provider?: ProviderCode;
effortLevel?: EffortLevel;
model?: never;
effort?: never;
skills?: SkillsInput<TTools>;
runtimeFullAccess?: boolean;
autoEndOnDisconnect?: boolean;
}
| {
provider?: ProviderCode;
model: string;
effort?: Effort;
effortLevel?: never;
skills?: SkillsInput<TTools>;
runtimeFullAccess?: boolean;
autoEndOnDisconnect?: boolean;
};

effortLevel 代表 Desktop profile mode;model 代表 explicit provider configuration,並可搭配 optional provider-native effort。兩種 mode 互斥,不能同時傳入。只傳 model 也是合法的,這時使用 provider 自己的 default effort;effort 不能脫離 model 單獨使用。

class PedelecWorkspace {
readonly path: string | null;
createSession(): Promise<PedelecSession<string>>;
createSession<const TTools extends readonly ToolDefinition[]>(
input: CreateSessionInput<TTools>,
): Promise<PedelecSession<ToolNameOf<TTools>>>;
listFiles(path?: string): Promise<string[]>;
listFolders(path?: string): Promise<string[]>;
uploadFile(file: File): Promise<string>;
uploadFile(file: File, targetPath: string): Promise<string>;
readFile(path: string, type: "text"): Promise<string>;
readFile<T = JsonValue>(path: string, type: "json"): Promise<T>;
readFile(path: string, type: "file"): Promise<File>;
run(script: string, options?: WorkspaceRunOptions): Promise<WorkspaceRunResult>;
}

PedelecWorkspace 會由 openWorkspace()、createSession().workspace 與 resumeSession().workspace 回傳。Workspace identity 是 opaque,刻意不公開。

type WorkspaceRunOptions = {
runtimeModules?: readonly RuntimeModuleDefinition[];
/** @deprecated Use runtimeModules. Do not provide both fields. */
denoModules?: readonly RuntimeModuleDefinition[];
timeoutMs?: number;
};
type WorkspaceRunResult = {
exitCode: number;
stdout: string;
stderr: string;
stdoutTruncated: boolean;
stderrTruncated: boolean;
}
type ProviderInfo = {
name: string;
code: ProviderCode;
available: boolean;
isDefault: boolean;
error: string | null;
};
type PedelecSettings = {
defaultProvider: ProviderCode | null;
};
type ApprovalStatus = {
installed: boolean;
approved: boolean;
agentSessionsApproved?: boolean;
runtimeFullAccessApproved?: boolean;
origin: string | null;
appConnected: boolean;
};
type PedelecAvailability = {
available: boolean;
extension: { available: boolean };
approval: { approved: boolean; origin: string | null };
desktop: { available: boolean; launchAttempted: boolean };
error?: PedelecError;
};

PedelecSettings 是只含預設值的公開 DTO,絕不包含 provider credentials。ProviderInfo 僅公開 name、code、available、isDefault、error。isDefault 反映目前 Desktop 的 default provider,與 available 無關。

available 需要所有 layer 都成功。launchAttempted 在非敏感 approval-status ping 送出後即可為 true,不代表已確認啟動 Desktop;appConnected 只表示該 ping 成功,不代表已 approval 或 provider ready。

type AssetPath = `/${string}`;

Workspace shared store 中 asset 的 SDK public path。Agent 可見的 shared store 實際位於 <workspace.path>/.pedelec-runtime/assets/;.pedelec-runtime 是 private runtime layout,不會出現在 SDK value 中。例如 /images/photo.png 對應到 <workspace.path>/.pedelec-runtime/assets/images/photo.png。Runtime validation 也會拒絕 backslash、空 path segment、. 與 ..。

type ReadAssetType = "text" | "json" | "file";

決定 PedelecSession.readAsset() 的轉換方式:strict UTF-8 text、parsed JSON,或 browser File。

type Asset = {
name: string;
path: AssetPath;
sizeBytes: number;
modifiedAt: number;
};

modifiedAt 是 workspace filesystem modification time。path 是 workspace-relative,不會揭露 browser 使用者的 absolute local path。

type PedelecError = {
code: string;
message: string;
details?: unknown;
};

不要假設 details 有一種 global shape;依 code narrow 並驗證後使用。

type PedelecSessionStatus =
| "idle"
| "running"
| "waiting_tool_result"
| "ended"
| "error";
type PedelecSessionUsage = {
totalTokens?: number;
};

totalTokens 是單一 session 已觀察到的 normalized cumulative token total。直到受支援的 provider 回報有效值以前都會省略。

type JsonPrimitive = string | number | boolean | null;
type JsonValue =
| JsonPrimitive
| JsonValue[]
| { [key: string]: JsonValue };

Tool schema metadata 使用此型別。Runtime tool result 的 TS return type 可能更廣,但實際也應遵守 JSON-compatible constraint。

type ToolSpecificHandler<TArgs = unknown, TResult = unknown> = (
args: TArgs,
ctx: ToolCallContext,
) => TResult | Promise<TResult>;
type ToolDefinition<
TArgs = unknown,
TResult = unknown,
TName extends string = string,
> = {
name: TName;
description: string;
argsSchema: ToolArgsSchema;
timeoutMs?: number;
handler?: ToolSpecificHandler<TArgs, TResult>;
};
type RuntimeModuleDefinition<TName extends string = string> = {
name: TName;
entry: string;
description?: string;
usage?: string;
preferStdinExecution?: boolean;
};

name 與 entry 是 intrinsic fields。entry 是 Vite build/dev authoring string,不是 Desktop filesystem instruction。description 與 usage 是 optional Agent-facing metadata;preferStdinExecution 仍是公開的 authoring preference。設為 true 時,Host Context 會以 preferredExecution: "stdin" 表示此 preference;Agent 應優先使用全域 runStdinCommand。File-backed execution 仍然有效,共用 Host Context contract 不包含 provider-specific shell syntax。此 preference 不會改變 bundling 或 artifact contents。請使用 pedelecVitePlugin() 準備 runtime 與 declaration artifact。

Session skills 使用較嚴格的 shape:description 與 usage 都必須是 non-empty string。Workspace run 可以使用 minimal base declaration,但每個 module 都必須包含 prepared Vite artifact。

type AgentModuleDefinition<TName extends string = string> =
RuntimeModuleDefinition<TName> & {
description: string;
usage: string;
};
type SkillsInput<
TTools extends readonly ToolDefinition[] = readonly ToolDefinition[],
> = {
guidance: string;
tools: TTools;
runtimeModules?: readonly AgentModuleDefinition[];
/** @deprecated Use runtimeModules. Do not provide both fields. */
denoModules?: readonly AgentModuleDefinition[];
};
type WebMcpSkillsInput<
TTools extends readonly ToolDefinition[] = readonly ToolDefinition[],
> = {
tools: TTools;
};
type WebMcpInput<
TTools extends readonly ToolDefinition[] = readonly ToolDefinition[],
> = {
skills: WebMcpSkillsInput<TTools>;
};
type WebMcpBinding = {
available: boolean;
dispose(): void;
};

pedelec.webmcp() 只接受 tools,不接受 guidance 或 runtimeModules。dispose() 會取消該 binding 的 WebMCP registrations。Availability 與 handler context 限制請見 Tools API。

type ToolNameOf<TTools extends readonly ToolDefinition[]> = Extract<
TTools[number]["name"],
string
>;
type SerializableToolManifest = {
name: string;
description: string;
argsSchema: ToolArgsSchema;
timeoutMs?: number;
};
type SerializableSkillsManifest = {
guidance: string;
tools: SerializableToolManifest[];
denoModules?: Array<{
name: string;
description: string;
usage: string;
preferStdinExecution?: boolean;
}>;
};

Inline handler 與 build-time entry 不在 serialized manifest。

type ToolArgsSchemaMeta<
TDefault extends JsonValue = JsonValue,
> = {
description?: string;
default?: TDefault;
examples?: TDefault[];
};
type ToolArgsStringSchema = ToolArgsSchemaMeta<string> & {
type: "string";
enum?: string[];
minLength?: number;
maxLength?: number;
pattern?: string;
};
type ToolArgsNumberSchema = ToolArgsSchemaMeta<number> & {
type: "number";
enum?: number[];
minimum?: number;
maximum?: number;
};
type ToolArgsIntegerSchema = ToolArgsSchemaMeta<number> & {
type: "integer";
enum?: number[];
minimum?: number;
maximum?: number;
};
type ToolArgsBooleanSchema = ToolArgsSchemaMeta<boolean> & {
type: "boolean";
enum?: boolean[];
};
type ToolArgsArraySchema = ToolArgsSchemaMeta<JsonValue[]> & {
type: "array";
items: ToolArgsSchemaNode;
minItems?: number;
maxItems?: number;
uniqueItems?: boolean;
};
type ToolArgsObjectSchema = ToolArgsSchemaMeta<
Record<string, JsonValue>
> & {
type: "object";
properties?: Record<string, ToolArgsSchemaNode>;
required?: string[];
additionalProperties?: boolean;
};
type ToolArgsOneOfSchema = ToolArgsSchemaMeta & {
oneOf: ToolArgsSchemaNode[];
};
type ToolArgsSchemaNode =
| ToolArgsStringSchema
| ToolArgsNumberSchema
| ToolArgsIntegerSchema
| ToolArgsBooleanSchema
| ToolArgsArraySchema
| ToolArgsObjectSchema
| ToolArgsOneOfSchema;
type ToolArgsSchema = ToolArgsObjectSchema;

Root alias 在 compile time 強制 object schema。Root 與巢狀 object 的 additionalProperties 預設允許額外欄位;設定 false 會拒絕。Agent 傳入的 timeoutMs 也只是一般業務欄位,依原始 Args Schema 驗證。

type PedelecEventContext = {
sessionId: string;
provider: string;
effortLevel?: "default" | "low" | "high";
sessionCreatedAt: number;
eventReceivedAt?: number;
eventEmittedAt: number;
turnId?: string;
turnStartedAt?: number;
turnKind?: "user" | "prepare";
source: "core" | "sdk";
};

onChat() completed message 的 context。

type ChatEventContext = PedelecEventContext & {
type: "chat_message";
turnId: string;
turnStartedAt: number;
eventReceivedAt: number;
};

onChatDelta() best-effort incremental fragment 的 context。

type ChatDeltaEventContext = PedelecEventContext & {
type: "chat_delta";
turnId: string;
turnStartedAt: number;
eventReceivedAt: number;
};
type ToolCallContext = PedelecEventContext & {
type: "tool_call";
toolRequestId: string;
tool: string;
turnId: string;
turnStartedAt: number;
eventReceivedAt: number;
};
type StatusEventContext = PedelecEventContext & {
type: "status_changed" | "sdk_status_changed";
status: PedelecSessionStatus;
previousStatus: PedelecSessionStatus;
};
type ErrorEventContext = PedelecEventContext & {
type: "error" | "sdk_error";
};
type EndedEventContext = PedelecEventContext & {
type: "ended" | "sdk_ended";
};

Base context optional field 只在 relevant event 存在。ID 要視為 opaque;timestamp 是 browser diagnostics,不是 security claim。

DenoModuleDefinition、defineDenoModule() 與 denoModules 仍可使用,TypeScript 以 @deprecated 提示。請改用 RuntimeModuleDefinition、defineRuntimeModule() 與 runtimeModules。同一個 skills/options 物件只能指定其中一種欄位;即使是空陣列,同時帶兩個欄位也會回 INVALID_INPUT。內部 SerializableSkillsManifest.denoModules wire 欄位維持不變。

import { defineDenoModule, defineRuntimeModule, type DenoModuleDefinition } from "@kaoruisaac/pedelec";
const legacy: DenoModuleDefinition = defineDenoModule({ name: "project-tools", entry: "./agent/project-tools.ts" });
await workspace.run('import "project-tools";', { denoModules: [legacy] });
const modern = defineRuntimeModule({ name: "project-tools", entry: "./agent/project-tools.ts" });
await workspace.run('import "project-tools";', { runtimeModules: [modern] });