跳到內容

Types

以下 types 都由 @kaoruisaac/pedelec export。

import type {
PedelecOptions,
ProviderCode,
ProviderInfo,
PedelecSessionStatus,
PedelecSessionUsage,
ToolArgsSchema,
Asset,
AssetPath,
ReadAssetType,
CreateSessionWorkspaceInput,
WorkspaceFolderPickerResult,
} from "@kaoruisaac/pedelec";
type PedelecOptions = {
bridgeTimeoutMs?: number;
};
type ProviderCode =
| "codex"
| "antigravity"
| "opencode"
| "cursor"
| "claude"
| "ollama";
type CreateSessionInput<
TTools extends readonly ToolDefinition[] = readonly ToolDefinition[],
> =
| {
provider: ProviderCode;
effortLevel?: "default" | "low" | "high";
skills?: SkillsInput<TTools>;
workspace?: CreateSessionWorkspaceInput;
autoEndOnDisconnect?: boolean;
}
| {
provider?: undefined;
effortLevel?: "default" | "low" | "high";
skills?: SkillsInput<TTools>;
workspace?: CreateSessionWorkspaceInput;
autoEndOnDisconnect?: boolean;
};

effortLevel 不依賴 provider,可單獨使用。

type CreateSessionWorkspaceInput = {
path: string;
};

path 是 absolute、由 application 管理的 workspace path。Pedelec 會建立缺少的 workspace 子目錄,但永遠不會刪除這個 workspace。它可以由多個 active session 共用,且不得與 managed workspace root overlap。

interface WorkspaceFolderPickerResult {
path: string;
isEmptyFolder: boolean;
hasWorkspaceConfig: boolean;
}

這是 workspaceFolderPicker() 回傳的 read-only snapshot。hasWorkspaceConfig 只表示 .pedelec-workspace.json 是 regular file,不會驗證 marker 內容。

type ProviderInfo = {
name: string;
code: ProviderCode;
available: boolean;
isDefault: boolean;
error: string | null;
};
type PedelecSettings = {
defaultProvider: ProviderCode | null;
};
type ApprovalStatus = {
installed: boolean;
approved: 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 僅公開 namecodeavailableisDefaulterrorisDefault 反映目前 Desktop 的 default provider,與 available 無關。

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

type AssetPath = `/${string}`;

Session 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 SkillsInput<
TTools extends readonly ToolDefinition[] = readonly ToolDefinition[],
> = {
guidance: string;
tools: TTools;
};
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[];
};

Inline handler 不在 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[];
};
type ToolArgsOneOfSchema = ToolArgsSchemaMeta & {
oneOf: ToolArgsSchemaNode[];
};
type ToolArgsSchemaNode =
| ToolArgsStringSchema
| ToolArgsNumberSchema
| ToolArgsIntegerSchema
| ToolArgsBooleanSchema
| ToolArgsArraySchema
| ToolArgsObjectSchema
| ToolArgsOneOfSchema;
type ToolArgsSchema = ToolArgsObjectSchema;

Root alias 在 compile time 強制 object 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。