@kaoruisaac/pedelec 0.2.11 → 0.2.12

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 CHANGED
@@ -28,7 +28,7 @@ A web application can use Pedelec to:
28
28
  - send user instructions and receive streamed assistant text;
29
29
  - expose narrowly scoped browser-side tools to the agent;
30
30
  - resume or end sessions; and
31
- - upload and list completed sandbox assets; and
31
+ - upload and list completed workspace assets; and
32
32
  - show connection, approval, provider, and lifecycle state in the UI.
33
33
 
34
34
  ## Why Pedelec exists
@@ -146,7 +146,7 @@ const path = await session.uploadAsset(file);
146
146
  const assets = await session.listAssets();
147
147
  ```
148
148
 
149
- The physical shared App/Agent directory is `.pedelec-sandbox/assets/`. In the SDK contract, `assets/` is its implicit root: `listAssets()` recursively lists regular files at every level as a flat array, ordered by filesystem modification time (newest first) and then by name; nested paths such as `/results/report.json` are returned in full. Directory entries and symlinks are excluded, as are `.pedelec-*` entries at every level; other dotfiles are included. It may run while the agent runs. One session can only upload one file at a time, but uploads can run alongside prepare or agent execution.
149
+ The physical shared App/Agent directory is `.pedelec-runtime/assets/`. In the SDK contract, `assets/` is its implicit root: `listAssets()` recursively lists regular files at every level as a flat array, ordered by filesystem modification time (newest first) and then by name; nested paths such as `/results/report.json` are returned in full. Directory entries and symlinks are excluded, as are `.pedelec-*` entries at every level; other dotfiles are included. It may run while the agent runs. One session can only upload one file at a time, but uploads can run alongside prepare or agent execution.
150
150
 
151
151
  ```ts
152
152
  const text = await session.readAsset("/report.txt", "text");
@@ -156,37 +156,39 @@ const result = await session.readAsset("/model.glb", "file");
156
156
 
157
157
  Public asset paths use `/...` with `assets/` as their implicit root; nested paths such as `/results/model.glb` are supported up to 100 MiB.
158
158
 
159
- ## Sandbox workspace
159
+ ## Workspace
160
160
 
161
- By default, each session receives a temporary Desktop-managed sandbox. To use an application-owned workspace that can persist across sessions, pass an absolute path:
161
+ Workspace is the filesystem root in which the Agent works. Pedelec stores its private runtime data under `<workspace>/.pedelec-runtime/`.
162
+
163
+ By default, each session receives a temporary Desktop-managed workspace. To use an application-owned workspace that can persist across sessions, pass an absolute path:
162
164
 
163
165
  ```ts
164
166
  const session = await pedelec.createSession({
165
167
  provider: "codex",
166
- sandbox: { path: "C:\\workspace\\project-a" },
168
+ workspace: { path: "C:\\workspace\\project-a" },
167
169
  });
168
170
  ```
169
171
 
170
- Pedelec creates `.pedelec-sandbox/` with missing `assets/`, `logs/`, `skills/`, and `tmp/` subdirectories, preserving existing project files and existing private data. It never deletes an explicit workspace, and multiple active sessions may share it. Filesystem write conflicts are the application's responsibility. An explicit path must not overlap Pedelec's managed sandbox root.
172
+ Pedelec creates `.pedelec-runtime/` with missing `assets/`, `logs/`, `skills/`, and `tmp/` subdirectories, preserving existing project files and existing private data. It never deletes an explicit workspace, and multiple active sessions may share it. Filesystem write conflicts are the application's responsibility. An explicit path must not overlap Pedelec's managed workspace root.
171
173
 
172
174
  ## Selecting an Application Workspace
173
175
 
174
- Use `sandboxFolderPicker()` when the application wants the user to choose a local workspace before creating a session:
176
+ Use `workspaceFolderPicker()` when the application wants the user to choose a local workspace before creating a session:
175
177
 
176
178
  ```ts
177
- const folder = await pedelec.sandboxFolderPicker();
179
+ const folder = await pedelec.workspaceFolderPicker();
178
180
  if (!folder) return; // The user cancelled the native picker.
179
181
 
180
- if (!folder.isEmptyFolder && !folder.hasSandboxConfig) {
182
+ if (!folder.isEmptyFolder && !folder.hasWorkspaceConfig) {
181
183
  // The application decides whether to warn the user.
182
184
  }
183
185
 
184
186
  const session = await pedelec.createSession({
185
- sandbox: { path: folder.path },
187
+ workspace: { path: folder.path },
186
188
  });
187
189
  ```
188
190
 
189
- `sandboxFolderPicker()` returns `Promise<SandboxFolderPickerResult | null>`. It is a read-only snapshot: it does not validate or initialize the selected folder, create workspace directories, or create the sandbox marker. `isEmptyFolder` only reports whether the selected folder root has any filesystem entry. `hasSandboxConfig` is true only when `.pedelec-lock.json` exists as a regular file; its JSON is not parsed. The picker requires the same origin approval as other sensitive Desktop APIs, and cancellation returns `null`. `createSession()` still applies the full sandbox rules and creates the marker after successful custom sandbox initialization. The marker currently records the SDK version and normalized caller origin but does not restrict reuse by origin or SDK version.
191
+ `workspaceFolderPicker()` returns `Promise<WorkspaceFolderPickerResult | null>`. It is a read-only snapshot: it does not validate or initialize the selected folder, create workspace directories, or create the workspace marker. `isEmptyFolder` only reports whether the selected folder root has any filesystem entry. `hasWorkspaceConfig` is true only when `.pedelec-workspace.json` exists as a regular file; its JSON is not parsed. The picker requires the same origin approval as other sensitive Desktop APIs, and cancellation returns `null`. `createSession()` still applies the full workspace rules and creates the marker after successful custom workspace initialization. The marker currently records the SDK version and normalized caller origin but does not restrict reuse by origin or SDK version.
190
192
 
191
193
  ---
192
194
 
package/dist/index.d.ts CHANGED
@@ -7,11 +7,11 @@ export type JsonPrimitive = string | number | boolean | null;
7
7
  export type JsonValue = JsonPrimitive | JsonValue[] | {
8
8
  [key: string]: JsonValue;
9
9
  };
10
- export type SandboxAssetPath = `/${string}`;
10
+ export type AssetPath = `/${string}`;
11
11
  export type ReadAssetType = "text" | "json" | "file";
12
- export type SandboxAsset = {
12
+ export type Asset = {
13
13
  name: string;
14
- path: SandboxAssetPath;
14
+ path: AssetPath;
15
15
  sizeBytes: number;
16
16
  modifiedAt: number;
17
17
  };
@@ -83,26 +83,26 @@ export type SerializableSkillsManifest = {
83
83
  guidance: string;
84
84
  tools: SerializableToolManifest[];
85
85
  };
86
- export type CreateSessionSandboxInput = {
86
+ export type CreateSessionWorkspaceInput = {
87
87
  path: string;
88
88
  };
89
- export interface SandboxFolderPickerResult {
89
+ export interface WorkspaceFolderPickerResult {
90
90
  path: string;
91
91
  isEmptyFolder: boolean;
92
- hasSandboxConfig: boolean;
92
+ hasWorkspaceConfig: boolean;
93
93
  }
94
94
  type CreateSessionInputWithProvider<TTools extends readonly ToolDefinition[] = readonly ToolDefinition[]> = {
95
95
  provider: ProviderCode;
96
96
  effortLevel?: EffortLevel;
97
97
  skills?: SkillsInput<TTools>;
98
- sandbox?: CreateSessionSandboxInput;
98
+ workspace?: CreateSessionWorkspaceInput;
99
99
  autoEndOnDisconnect?: boolean;
100
100
  };
101
101
  type CreateSessionInputWithDefaults<TTools extends readonly ToolDefinition[] = readonly ToolDefinition[]> = {
102
102
  provider?: undefined;
103
103
  effortLevel?: EffortLevel;
104
104
  skills?: SkillsInput<TTools>;
105
- sandbox?: CreateSessionSandboxInput;
105
+ workspace?: CreateSessionWorkspaceInput;
106
106
  autoEndOnDisconnect?: boolean;
107
107
  };
108
108
  export type CreateSessionInput<TTools extends readonly ToolDefinition[] = readonly ToolDefinition[]> = CreateSessionInputWithProvider<TTools> | CreateSessionInputWithDefaults<TTools>;
@@ -238,7 +238,7 @@ export declare class Pedelec {
238
238
  constructor(options?: PedelecOptions);
239
239
  createSession(): Promise<PedelecSession<string>>;
240
240
  createSession<const TTools extends readonly ToolDefinition[]>(input: CreateSessionInput<TTools>): Promise<PedelecSession<ToolNameOf<TTools>>>;
241
- sandboxFolderPicker(): Promise<SandboxFolderPickerResult | null>;
241
+ workspaceFolderPicker(): Promise<WorkspaceFolderPickerResult | null>;
242
242
  listProviders(): Promise<ProviderInfo[]>;
243
243
  getSettings(): Promise<PedelecSettings>;
244
244
  getApprovalStatus(): Promise<ApprovalStatus>;
@@ -288,12 +288,12 @@ export declare class PedelecSession<TToolName extends string = string> {
288
288
  onChat(handler: ChatHandler): () => void;
289
289
  onTool(handler: GenericToolHandler<TToolName>): () => void;
290
290
  onTool<TArgs = unknown, TResult = unknown>(toolName: TToolName, handler: ToolSpecificHandler<TArgs, TResult>): () => void;
291
- uploadAsset(file: File): Promise<SandboxAssetPath>;
292
- uploadAsset(file: File, targetPath: SandboxAssetPath): Promise<SandboxAssetPath>;
293
- listAssets(): Promise<SandboxAsset[]>;
294
- readAsset(path: SandboxAssetPath, type: "text"): Promise<string>;
295
- readAsset<T = JsonValue>(path: SandboxAssetPath, type: "json"): Promise<T>;
296
- readAsset(path: SandboxAssetPath, type: "file"): Promise<File>;
291
+ uploadAsset(file: File): Promise<AssetPath>;
292
+ uploadAsset(file: File, targetPath: AssetPath): Promise<AssetPath>;
293
+ listAssets(): Promise<Asset[]>;
294
+ readAsset(path: AssetPath, type: "text"): Promise<string>;
295
+ readAsset<T = JsonValue>(path: AssetPath, type: "json"): Promise<T>;
296
+ readAsset(path: AssetPath, type: "file"): Promise<File>;
297
297
  onError(handler: ErrorHandler): () => void;
298
298
  onStatus(handler: StatusHandler): () => void;
299
299
  onEnded(handler: EndedHandler): () => void;
package/dist/index.js CHANGED
@@ -141,7 +141,7 @@ export class Pedelec {
141
141
  provider: resolvedInput.provider,
142
142
  effortLevel: resolvedInput.effortLevel,
143
143
  skills: resolvedInput.skills,
144
- sandbox: resolvedInput.sandbox,
144
+ workspace: resolvedInput.workspace,
145
145
  autoEndOnDisconnect: resolvedInput.autoEndOnDisconnect,
146
146
  },
147
147
  });
@@ -150,9 +150,9 @@ export class Pedelec {
150
150
  }
151
151
  return this.registerSession(result.sessionId, resolvedInput.provider, resolvedInput.effortLevel, resolvedInput.inlineToolHandlers);
152
152
  }
153
- async sandboxFolderPicker() {
154
- const result = await this.requestWithOptions("pick_sandbox_folder", {}, { timeoutMs: null });
155
- return normalizeSandboxFolderPickerResponse(result);
153
+ async workspaceFolderPicker() {
154
+ const result = await this.requestWithOptions("pick_workspace_folder", {}, { timeoutMs: null });
155
+ return normalizeWorkspaceFolderPickerResponse(result);
156
156
  }
157
157
  async listProviders() {
158
158
  return normalizeProviderInfoList(await this.request("list_providers"));
@@ -258,15 +258,15 @@ export class Pedelec {
258
258
  }
259
259
  const autoEndOnDisconnect = raw.autoEndOnDisconnect !== false;
260
260
  const normalizedSkills = normalizeSkillsInput(raw.skills);
261
- const sandbox = normalizeCreateSessionSandboxInput(raw.sandbox);
261
+ const workspace = normalizeCreateSessionWorkspaceInput(raw.workspace);
262
262
  if (!hasProvider) {
263
- return this.resolveDefaultCreateSessionInput(effortLevel, normalizedSkills, sandbox, autoEndOnDisconnect);
263
+ return this.resolveDefaultCreateSessionInput(effortLevel, normalizedSkills, workspace, autoEndOnDisconnect);
264
264
  }
265
265
  return {
266
266
  provider: provider,
267
267
  effortLevel,
268
268
  skills: normalizedSkills.manifest,
269
- sandbox,
269
+ workspace,
270
270
  inlineToolHandlers: normalizedSkills.handlers,
271
271
  autoEndOnDisconnect,
272
272
  };
@@ -323,7 +323,7 @@ export class Pedelec {
323
323
  };
324
324
  }
325
325
  }
326
- async resolveDefaultCreateSessionInput(effortLevel, normalizedSkills, sandbox, autoEndOnDisconnect) {
326
+ async resolveDefaultCreateSessionInput(effortLevel, normalizedSkills, workspace, autoEndOnDisconnect) {
327
327
  const settings = await this.getSettings();
328
328
  if (!settings.defaultProvider) {
329
329
  throw makeError("DEFAULT_PROVIDER_NOT_SET", "Default provider is not set. Open the Pedelec desktop app Settings page and choose a default provider.");
@@ -333,7 +333,7 @@ export class Pedelec {
333
333
  provider: settings.defaultProvider,
334
334
  effortLevel,
335
335
  skills: normalizedSkills.manifest,
336
- sandbox,
336
+ workspace,
337
337
  inlineToolHandlers: normalizedSkills.handlers,
338
338
  autoEndOnDisconnect,
339
339
  };
@@ -462,18 +462,18 @@ export class Pedelec {
462
462
  }
463
463
  }
464
464
  }
465
- function normalizeCreateSessionSandboxInput(value) {
465
+ function normalizeCreateSessionWorkspaceInput(value) {
466
466
  if (value === undefined)
467
467
  return undefined;
468
468
  if (!value || typeof value !== "object" || Array.isArray(value)) {
469
- throw makeError("INVALID_INPUT", "sandbox must be an object");
469
+ throw makeError("INVALID_INPUT", "workspace must be an object");
470
470
  }
471
471
  const path = value.path;
472
472
  if (typeof path !== "string") {
473
- throw makeError("INVALID_INPUT", "sandbox.path must be a string");
473
+ throw makeError("INVALID_INPUT", "workspace.path must be a string");
474
474
  }
475
475
  if (path.trim().length === 0) {
476
- throw makeError("INVALID_INPUT", "sandbox.path must not be empty");
476
+ throw makeError("INVALID_INPUT", "workspace.path must not be empty");
477
477
  }
478
478
  return { path };
479
479
  }
@@ -1033,21 +1033,21 @@ function normalizePedelecSettings(value) {
1033
1033
  }
1034
1034
  return { defaultProvider: value.defaultProvider };
1035
1035
  }
1036
- function normalizeSandboxFolderPickerResponse(value) {
1036
+ function normalizeWorkspaceFolderPickerResponse(value) {
1037
1037
  if (!isPlainObject(value) || !("path" in value)) {
1038
- throw makeError("SDK_PROTOCOL_ERROR", "pick_sandbox_folder response had an invalid shape");
1038
+ throw makeError("SDK_PROTOCOL_ERROR", "pick_workspace_folder response had an invalid shape");
1039
1039
  }
1040
1040
  const path = value.path;
1041
1041
  if (path === null)
1042
1042
  return null;
1043
1043
  if (typeof path !== "string" || path.length === 0 ||
1044
- typeof value.isEmptyFolder !== "boolean" || typeof value.hasSandboxConfig !== "boolean") {
1045
- throw makeError("SDK_PROTOCOL_ERROR", "pick_sandbox_folder response had an invalid shape");
1044
+ typeof value.isEmptyFolder !== "boolean" || typeof value.hasWorkspaceConfig !== "boolean") {
1045
+ throw makeError("SDK_PROTOCOL_ERROR", "pick_workspace_folder response had an invalid shape");
1046
1046
  }
1047
1047
  return {
1048
1048
  path,
1049
1049
  isEmptyFolder: value.isEmptyFolder,
1050
- hasSandboxConfig: value.hasSandboxConfig,
1050
+ hasWorkspaceConfig: value.hasWorkspaceConfig,
1051
1051
  };
1052
1052
  }
1053
1053
  function normalizeProviderInfoList(value) {
@@ -1,5 +1,5 @@
1
1
  import { Pedelec, defineTool, } from "./index";
2
- function sandboxInputHasPublicType() {
2
+ function workspaceInputHasPublicType() {
3
3
  return { path: "C:\\workspace\\project" };
4
4
  }
5
5
  async function typedOnToolNameFromCreateSession() {
@@ -84,10 +84,10 @@ async function noSkillsFallsBackToString() {
84
84
  const pedelec = new Pedelec();
85
85
  const session = await pedelec.createSession({
86
86
  provider: "codex",
87
- sandbox: { path: "C:\\workspace\\project" },
87
+ workspace: { path: "C:\\workspace\\project" },
88
88
  });
89
- const typedSandbox = sandboxInputHasPublicType();
90
- void typedSandbox;
89
+ const typedWorkspace = workspaceInputHasPublicType();
90
+ void typedWorkspace;
91
91
  session.onTool((name) => {
92
92
  const anyString = name;
93
93
  return anyString;
@@ -100,6 +100,10 @@ async function effortLevelPublicTypeContract() {
100
100
  const pedelec = new Pedelec();
101
101
  await pedelec.createSession({ effortLevel: "high" });
102
102
  const session = await pedelec.createSession({ provider: "codex", effortLevel: "low" });
103
+ // @ts-expect-error the removed sandbox input is not part of the public contract
104
+ pedelec.createSession({ provider: "codex", sandbox: { path: "C:\\workspace\\legacy" } });
105
+ // @ts-expect-error the removed sandbox picker is not part of the public contract
106
+ pedelec.sandboxFolderPicker();
103
107
  // @ts-expect-error model is no longer a createSession option
104
108
  pedelec.createSession({ provider: "codex", model: "gpt-5" });
105
109
  // @ts-expect-error session no longer exposes provider model
@@ -136,14 +140,14 @@ async function availabilityHasPublicType() {
136
140
  void availability;
137
141
  void promise;
138
142
  }
139
- async function sandboxFolderPickerHasPublicType() {
143
+ async function workspaceFolderPickerHasPublicType() {
140
144
  const pedelec = new Pedelec();
141
- const result = pedelec.sandboxFolderPicker();
145
+ const result = pedelec.workspaceFolderPicker();
142
146
  void result;
143
147
  }
144
148
  function directoryPickerIsRemoved() {
145
149
  const pedelec = new Pedelec();
146
- // @ts-expect-error directoryPicker was removed in favor of sandboxFolderPicker
150
+ // @ts-expect-error directoryPicker was removed in favor of workspaceFolderPicker
147
151
  pedelec.directoryPicker();
148
152
  }
149
153
  function publicSecurityTypesAreRestricted() {
@@ -164,7 +168,7 @@ void noSkillsFallsBackToString;
164
168
  void effortLevelPublicTypeContract;
165
169
  void listAssetsHasPublicTypes;
166
170
  void availabilityHasPublicType;
167
- void sandboxFolderPickerHasPublicType;
171
+ void workspaceFolderPickerHasPublicType;
168
172
  void directoryPickerIsRemoved;
169
173
  void publicSecurityTypesAreRestricted;
170
174
  const baseContext = {
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "0.2.11";
1
+ export declare const SDK_VERSION = "0.2.12";
@@ -1,2 +1,2 @@
1
1
  // Generated from sdk/package.json. Do not edit manually.
2
- export const SDK_VERSION = "0.2.11";
2
+ export const SDK_VERSION = "0.2.12";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaoruisaac/pedelec",
3
- "version": "0.2.11",
3
+ "version": "0.2.12",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",