@kaoruisaac/pedelec 0.4.9 → 0.4.11

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
@@ -91,9 +91,9 @@ npm install ../path/to/pedelec/sdk
91
91
 
92
92
  ---
93
93
 
94
- ## Deno Modules
94
+ ## Runtime Modules
95
95
 
96
- Vite applications can package local or installed JavaScript/TypeScript libraries for Agent-authored `pedelec-deno` scripts.
96
+ Vite applications can package local or installed JavaScript/TypeScript libraries for Agent-authored `pedelec-ts-runtime` scripts.
97
97
 
98
98
  ### Setup
99
99
 
@@ -110,15 +110,15 @@ export default defineConfig({
110
110
  ### Authoring
111
111
 
112
112
  ```ts
113
- import { Pedelec, defineDenoModule } from "@kaoruisaac/pedelec";
113
+ import { Pedelec, defineRuntimeModule } from "@kaoruisaac/pedelec";
114
114
 
115
115
  const pedelec = new Pedelec();
116
116
  const session = await pedelec.createSession({
117
117
  skills: {
118
118
  guidance: "Use sprite-tools for sprite authoring tasks.",
119
119
  tools: [],
120
- denoModules: [
121
- defineDenoModule({
120
+ runtimeModules: [
121
+ defineRuntimeModule({
122
122
  name: "sprite-tools",
123
123
  description: "Sprite authoring and preview utilities.",
124
124
  entry: "./agent/sprite-tools.ts",
@@ -133,7 +133,7 @@ const session = await pedelec.createSession({
133
133
  For an installed package, use its package specifier as the build-time entry:
134
134
 
135
135
  ```ts
136
- defineDenoModule({
136
+ defineRuntimeModule({
137
137
  name: "gsap",
138
138
  description: "Animation utilities.",
139
139
  entry: "gsap",
@@ -145,9 +145,9 @@ defineDenoModule({
145
145
 
146
146
  The generated declaration describes the module's Agent-facing API, so implementation-only dependency types are omitted. Module-owned types are supported; packages that expose dependency-owned or Node-specific external types directly in their public API are not guaranteed to produce a standalone declaration in V1. `name` is the Agent import specifier, and `usage` is required common-case guidance. `createSession()` transfers the prepared artifact automatically; a session keeps an immutable module snapshot, and `session.end()`/`session.resume()` reuse it while Core still knows the thread.
147
147
 
148
- Deno Modules are imported inside JavaScript/TypeScript run with `pedelec-deno`. They are different from `skills.tools`, whose browser/App RPC capabilities use `pedelec-cli` tool-spec and tool-call commands.
148
+ Runtime Modules are imported inside JavaScript/TypeScript run with `pedelec-ts-runtime`. They are different from `skills.tools`, whose browser/App RPC capabilities use `pedelec-cli` tool-spec and tool-call commands.
149
149
 
150
- Set the optional `preferStdinExecution: true` when short scripts primarily use a module and should be steered toward stdin execution. Host Context then adds that module's concrete `runCommandTemplate` (`@'\n<typescript-source>\n'@ | pedelec-deno --thread-id <thread-id> run -`), so the Agent only needs to replace the TypeScript source placeholder instead of deciding how to serialize stdin. This is a preference, not a restriction: file-backed execution remains valid, and omitting the field or setting it to `false` preserves the default behavior. It does not change bundling, artifact contents, or runtime permissions.
150
+ Set optional `preferStdinExecution: true` when short scripts primarily use a module. Host Context then exposes `preferredExecution: "stdin"` for that module; the Agent uses the global `runStdinCommand` with `pedelec-ts-runtime`. This is a preference: file-backed execution remains valid. Omitting the field or setting it to `false` preserves default authoring behavior. It does not change bundling, artifacts, or permissions.
151
151
 
152
152
  ---
153
153
 
@@ -311,7 +311,7 @@ const session = await workspace.createSession({
311
311
  const workspace = await pedelec.openWorkspace("C:\\workspace\\project-a");
312
312
  ```
313
313
 
314
- Pedelec initializes `.pedelec-runtime` for Workspace-owned runtime data without clearing project files or existing private data. Assets, logs, and temporary data are Workspace-level, while generated Session skills and Deno Module state are isolated per Thread. Applications should not depend on the private `.pedelec-runtime` subdirectory layout. Explicit Workspaces are application-managed, are never deleted by Pedelec, and can own multiple Sessions. An explicit path must not overlap Pedelec's managed workspace root.
314
+ Pedelec initializes `.pedelec-runtime` for Workspace-owned runtime data without clearing project files or existing private data. Assets, logs, and temporary data are Workspace-level, while generated Session skills and Runtime Module state are isolated per Thread. Applications should not depend on the private `.pedelec-runtime` subdirectory layout. Explicit Workspaces are application-managed, are never deleted by Pedelec, and can own multiple Sessions. An explicit path must not overlap Pedelec's managed workspace root.
315
315
 
316
316
  ### Managed convenience
317
317
 
@@ -339,7 +339,7 @@ const text = await workspace.readFile("README.md", "text");
339
339
 
340
340
  `session.uploadAsset()`, `readAsset()`, and `listAssets()` stay available as Session-scoped conveniences. Their root is `.pedelec-runtime/assets`, which suits provider artifacts and Agent-shared assets. Use the Workspace methods for general filesystem access.
341
341
 
342
- `workspace.run(script, options?)` executes application-supplied Deno code in the Workspace:
342
+ `workspace.run(script, options?)` executes application-supplied TypeScript code in the Workspace:
343
343
 
344
344
  ```ts
345
345
  const result = await workspace.run(
@@ -359,21 +359,21 @@ The default timeout is 60 seconds; `timeoutMs` must be a positive integer. The r
359
359
 
360
360
  Multiple Sessions, Agent/provider operations, and `workspace.run()` executions may operate concurrently in the same Workspace. A second turn on the same Session is still rejected while that Session is busy. Pedelec does not provide filesystem-level locking, snapshots, transactions, or conflict resolution between concurrent Workspace actors. Applications are responsible for coordinating shared file access when required.
361
361
 
362
- Session `skills.denoModules` belong to the Session/Thread that declares them and are available only to Agent-side `pedelec-deno` execution for that Thread. Workspace runs accept the same Vite-prepared declarations explicitly:
362
+ Session `skills.runtimeModules` belong to the Session/Thread that declares them and are available only to Agent-side `pedelec-ts-runtime` execution for that Thread. Workspace runs accept the same Vite-prepared declarations explicitly:
363
363
 
364
364
  ```ts
365
- const sceneTools = defineDenoModule({
365
+ const sceneTools = defineRuntimeModule({
366
366
  name: "scene-tools",
367
367
  entry: "./deno/scene-tools.ts",
368
368
  });
369
369
 
370
370
  const result = await workspace.run(
371
371
  `import { buildScene } from "scene-tools";\nawait buildScene();`,
372
- { denoModules: [sceneTools] },
372
+ { runtimeModules: [sceneTools] },
373
373
  );
374
374
  ```
375
375
 
376
- `workspace.run()` does not inherit any Session Deno Modules, and Sessions do not inherit modules used by Workspace runs. The Vite-prepared package is cached privately per Workspace and authorized SDK origin; each run receives an import map containing exactly its requested names. A ready module name is immutable for the lifetime of the Core process, and Workspace-run modules never appear in Agent Host Context. The private Workspace-run cache is reset when Core restarts; project files, assets, and Thread module snapshots are preserved.
376
+ `workspace.run()` does not inherit any Session Runtime Modules, and Sessions do not inherit modules used by Workspace runs. The Vite-prepared package is cached privately per Workspace and authorized SDK origin; each run receives an import map containing exactly its requested names. A ready module name is immutable for the lifetime of the Core process, and Workspace-run modules never appear in Agent Host Context. The private Workspace-run cache is reset when Core restarts; project files, assets, and Thread module snapshots are preserved.
377
377
 
378
378
  The Workspace handle outlives an individual Session conceptually. Ending a Session does not close or delete a custom Workspace, and Pedelec does not delete it during app cleanup. Managed Workspaces remain under Desktop cleanup ownership and are not promised to disappear immediately when a Thread ends. The browser capability is runtime-scoped; reopen the custom Workspace after a Desktop/Core restart when necessary. `pedelec.resumeSession(sessionId)` returns a Session that already includes `session.workspace`; the application does not need to call `openWorkspace()` separately. Same-handle `session.resume()` preserves the existing Workspace handle, subject to the existing Core/thread and transport caveats.
379
379
 
@@ -449,7 +449,7 @@ const modelSession = await pedelec.createSession({
449
449
 
450
450
  Model-only requests are valid and use the provider's default effort behavior. `effort` requires `model`; `model` cannot be combined with `effortLevel`. The SDK does not expose or maintain a model catalog, and it does not translate the identifier into provider CLI flags. Model validity, effort support, and account entitlement remain provider-dependent, so an invalid or unavailable configuration may fail when the provider starts.
451
451
 
452
- Explicit model requests require an `explicitModelConfigApplied` acknowledgment from Core before the SDK exposes the session or starts Deno Module setup. If the connected Extension/Desktop is too old to provide that acknowledgment, the SDK aborts the newly created setup and reports a compatibility error instead of silently using a different configuration.
452
+ Explicit model requests require an `explicitModelConfigApplied` acknowledgment from Core before the SDK exposes the session or starts Runtime Module setup. If the connected Extension/Desktop is too old to provide that acknowledgment, the SDK aborts the newly created setup and reports a compatibility error instead of silently using a different configuration.
453
453
 
454
454
  Currently supported provider codes in the SDK:
455
455
 
@@ -465,3 +465,27 @@ Currently supported provider codes in the SDK:
465
465
  Ollama sessions are executed by the bundled `pedelec-agent`. In profile mode, the selected Ollama effort profile must contain a model; otherwise Core returns `MODEL_REQUIRED`. In explicit model mode, `{ model }` supplies the model directly. Ollama currently does not accept an explicit `effort`. Low and high profiles are optional, but there is no fallback between profiles.
466
466
 
467
467
  `getSettings()` returns only `{ defaultProvider }`. It never exposes provider settings, effort arguments, credentials, or model names.
468
+
469
+
470
+ ## Explicit Full Runtime Access
471
+
472
+ Sandbox is the default. Full Access requires three separate conditions: an Instance created with `runtimeFullAccess: true`, explicit user approval of both **Allow Agent Sessions** and **Allow Full Runtime Access** in the Extension, and `runtimeFullAccess: true` on session creation.
473
+
474
+ The first `createSession()` automatically opens the approval Popup when required grants are missing. Choosing only Agent Sessions leaves a Full Instance incomplete and rejects either Session mode with `CREATE_SESSION_NOT_APPROVED`. `getApprovalStatus()` and `checkAvailability()` only read approval state.
475
+
476
+ ```ts
477
+ const privileged = new Pedelec({ runtimeFullAccess: true });
478
+ // After the user explicitly grants both permissions in the Extension:
479
+ const sandbox = await privileged.createSession({ runtimeFullAccess: false });
480
+ const full = await privileged.createSession({ runtimeFullAccess: true });
481
+ ```
482
+
483
+ Review the Extension permissions before creating sessions. An Instance requesting Full Access cannot create any session with only the Agent Sessions grant, including a Sandbox session. A standard Instance cannot request a Full Access session, even if another Instance on the same Origin has permission. Ordinary Origin approval never substitutes for the Full Access grant; the Popup offers an additional permission review with Full Access unchecked by default. `getApprovalStatus()` only reads status and does not open that review.
484
+
485
+ The Thread mode is fixed at creation and preserved on resume. Instances on the same Origin and Threads in the same Workspace retain their own requested modes. `workspace.run()` always stays Sandbox, and Provider sandbox settings are unchanged. Full Access changes the TypeScript Runtime's OS permissions only. Revoking the Full Access grant rejects subsequent high-privilege execution and attempts to cancel affected running processes; unrelated Origins retain their grants.
486
+
487
+ Upgrade the SDK, Extension, and Desktop together when using Full Access. Missing mode acknowledgment is an error, never a successful downgrade. See [Error Codes](https://kaoruisaac.github.io/pedelec/reference/error-codes/) for authorization and protocol failures.
488
+
489
+ ## Runtime compatibility
490
+
491
+ New code uses `defineRuntimeModule`, `RuntimeModuleDefinition`, and `runtimeModules`. `defineDenoModule`, `DenoModuleDefinition`, and `denoModules` remain supported deprecated aliases. Never pass both module fields in one options object (`INVALID_INPUT`). `pedelec-ts-runtime --thread-id <id> run scripts/task.ts` and stdin `run -` are the standard CLI; `pedelec-deno` is a legal legacy alias with identical behavior. Actual `Deno.*` APIs, `DENO_DIR`, Deno flags, and `DENO_*` error codes retain their existing meanings.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export type PedelecOptions = {
2
+ runtimeFullAccess?: boolean;
2
3
  bridgeTimeoutMs?: number;
3
4
  };
4
5
  export type ProviderCode = "codex" | "antigravity" | "opencode" | "cursor" | "claude" | "ollama";
@@ -32,14 +33,16 @@ export type ProviderArtifact = {
32
33
  providerArtifactId?: string;
33
34
  toolCallId?: string;
34
35
  };
35
- export type DenoModuleDefinition<TName extends string = string> = {
36
+ export type RuntimeModuleDefinition<TName extends string = string> = {
36
37
  name: TName;
37
38
  description?: string;
38
39
  entry: string;
39
40
  usage?: string;
40
41
  preferStdinExecution?: boolean;
41
42
  };
42
- type AgentDenoModuleDefinition<TName extends string = string> = DenoModuleDefinition<TName> & {
43
+ /** @deprecated Use RuntimeModuleDefinition. */
44
+ export type DenoModuleDefinition<TName extends string = string> = RuntimeModuleDefinition<TName>;
45
+ type AgentRuntimeModuleDefinition<TName extends string = string> = RuntimeModuleDefinition<TName> & {
43
46
  description: string;
44
47
  usage: string;
45
48
  };
@@ -99,7 +102,9 @@ export type ToolDefinition<TArgs = unknown, TResult = unknown, TName extends str
99
102
  export type SkillsInput<TTools extends readonly ToolDefinition[] = readonly ToolDefinition[]> = {
100
103
  guidance: string;
101
104
  tools: TTools;
102
- denoModules?: readonly AgentDenoModuleDefinition[];
105
+ runtimeModules?: readonly AgentRuntimeModuleDefinition[];
106
+ /** @deprecated Use runtimeModules. */
107
+ denoModules?: readonly AgentRuntimeModuleDefinition[];
103
108
  };
104
109
  export type WebMcpSkillsInput<TTools extends readonly ToolDefinition[] = readonly ToolDefinition[]> = {
105
110
  tools: TTools;
@@ -118,7 +123,7 @@ export type SerializableToolManifest = {
118
123
  argsSchema: ToolArgsSchema;
119
124
  timeoutMs?: number;
120
125
  };
121
- type SerializableDenoModuleManifest = {
126
+ type SerializableRuntimeModuleManifest = {
122
127
  name: string;
123
128
  description: string;
124
129
  usage: string;
@@ -127,10 +132,14 @@ type SerializableDenoModuleManifest = {
127
132
  export type SerializableSkillsManifest = {
128
133
  guidance: string;
129
134
  tools: SerializableToolManifest[];
130
- denoModules?: SerializableDenoModuleManifest[];
135
+ runtimeModules?: SerializableRuntimeModuleManifest[];
136
+ /** @deprecated Use runtimeModules. Legacy wire field. */
137
+ denoModules?: SerializableRuntimeModuleManifest[];
131
138
  };
132
139
  export type WorkspaceRunOptions = {
133
140
  timeoutMs?: number;
141
+ runtimeModules?: readonly RuntimeModuleDefinition[];
142
+ /** @deprecated Use runtimeModules. */
134
143
  denoModules?: readonly DenoModuleDefinition[];
135
144
  };
136
145
  export type WorkspaceRunResult = {
@@ -141,6 +150,7 @@ export type WorkspaceRunResult = {
141
150
  stderrTruncated: boolean;
142
151
  };
143
152
  type CreateSessionSharedInput<TTools extends readonly ToolDefinition[] = readonly ToolDefinition[]> = {
153
+ runtimeFullAccess?: boolean;
144
154
  skills?: SkillsInput<TTools>;
145
155
  autoEndOnDisconnect?: boolean;
146
156
  };
@@ -170,6 +180,8 @@ export type PedelecSettings = {
170
180
  defaultProvider: ProviderCode | null;
171
181
  };
172
182
  export type ApprovalStatus = {
183
+ /** Explicit Full Runtime Access user grant reported by the Extension. */
184
+ runtimeFullAccessApproved?: boolean;
173
185
  installed: boolean;
174
186
  approved: boolean;
175
187
  origin: string | null;
@@ -356,8 +368,10 @@ type ErrorHandler = (error: PedelecError, ctx: ErrorEventContext) => void;
356
368
  type StatusHandler = (status: PedelecSessionStatus, ctx: StatusEventContext) => void;
357
369
  type EndedHandler = (ctx: EndedEventContext) => void;
358
370
  export declare function defineTool<TArgs = unknown, TResult = unknown, const TName extends string = string>(tool: ToolDefinition<TArgs, TResult, TName>): ToolDefinition<TArgs, TResult, TName>;
359
- export declare function defineDenoModule<const TModule extends DenoModuleDefinition>(module: TModule): TModule;
360
- type PreparedWorkspaceDenoModule = {
371
+ export declare function defineRuntimeModule<const TModule extends RuntimeModuleDefinition>(module: TModule): TModule;
372
+ /** @deprecated Use defineRuntimeModule. */
373
+ export declare const defineDenoModule: typeof defineRuntimeModule;
374
+ type PreparedWorkspaceRuntimeModule = {
361
375
  name: string;
362
376
  runtimeSource: string;
363
377
  typesSource: string;
@@ -388,6 +402,7 @@ export declare class Pedelec {
388
402
  private readonly pageWindow;
389
403
  private readonly channelId;
390
404
  private readonly bridgeTimeoutMs;
405
+ private readonly runtimeFullAccess;
391
406
  private readonly pendingRequests;
392
407
  private readonly sessions;
393
408
  private readonly lastSeqBySession;
@@ -403,7 +418,7 @@ export declare class Pedelec {
403
418
  createSessionInternal<const TTools extends readonly ToolDefinition[]>(input?: CreateSessionInput<TTools>, workspace?: PedelecWorkspace): Promise<PedelecSession<ToolNameOf<TTools>>>;
404
419
  private uploadDenoModuleArtifact;
405
420
  /** @internal */
406
- uploadWorkspaceDenoModuleArtifact(workspaceId: string, module: PreparedWorkspaceDenoModule): Promise<void>;
421
+ uploadWorkspaceDenoModuleArtifact(workspaceId: string, module: PreparedWorkspaceRuntimeModule): Promise<void>;
407
422
  private uploadDenoModuleArtifactWithTicket;
408
423
  private abortSessionSetup;
409
424
  private completeSessionSetup;
package/dist/index.js CHANGED
@@ -149,9 +149,23 @@ const WEBMCP_TOOL_NAME_MAX_LENGTH = 128;
149
149
  export function defineTool(tool) {
150
150
  return tool;
151
151
  }
152
- export function defineDenoModule(module) {
152
+ export function defineRuntimeModule(module) {
153
153
  return module;
154
154
  }
155
+ /** @deprecated Use defineRuntimeModule. */
156
+ export const defineDenoModule = defineRuntimeModule;
157
+ function resolveRuntimeModules(options) {
158
+ if ("runtimeModules" in options && "denoModules" in options) {
159
+ throw makeError("INVALID_INPUT", "runtimeModules and denoModules cannot be combined");
160
+ }
161
+ return "runtimeModules" in options ? options.runtimeModules : options.denoModules;
162
+ }
163
+ function normalizeRuntimeFullAccess(value) {
164
+ if (value !== undefined && typeof value !== "boolean") {
165
+ throw makeError("INVALID_INPUT", "runtimeFullAccess must be a boolean");
166
+ }
167
+ return value === true;
168
+ }
155
169
  function normalizeWorkspaceDenoModules(value) {
156
170
  if (value === undefined)
157
171
  return [];
@@ -254,7 +268,7 @@ function normalizeToolDefinitions(value, options = {}) {
254
268
  }
255
269
  function normalizeSkillsInput(value) {
256
270
  if (value === undefined)
257
- return { handlers: new Map(), denoModules: [] };
271
+ return { handlers: new Map(), runtimeModules: [] };
258
272
  if (!value || typeof value !== "object" || Array.isArray(value)) {
259
273
  throw makeError("INVALID_INPUT", "skills must be an object");
260
274
  }
@@ -265,12 +279,13 @@ function normalizeSkillsInput(value) {
265
279
  if (!Array.isArray(skills.tools)) {
266
280
  throw makeError("INVALID_INPUT", "skills.tools must be an array");
267
281
  }
268
- if (skills.denoModules !== undefined && !Array.isArray(skills.denoModules)) {
282
+ const modules = resolveRuntimeModules(skills);
283
+ if (modules !== undefined && !Array.isArray(modules)) {
269
284
  throw makeError("INVALID_INPUT", "skills.denoModules must be an array");
270
285
  }
271
286
  const { tools, handlers } = normalizeToolDefinitions(skills.tools);
272
- const seenDenoModuleNames = new Set();
273
- const denoModules = (skills.denoModules ?? []).map((module, index) => {
287
+ const seenRuntimeModuleNames = new Set();
288
+ const runtimeModules = (modules ?? []).map((module, index) => {
274
289
  if (!module || typeof module !== "object" || Array.isArray(module)) {
275
290
  throw makeError("INVALID_INPUT", "skills.denoModules entries must be objects", { index });
276
291
  }
@@ -281,12 +296,12 @@ function normalizeSkillsInput(value) {
281
296
  moduleName: rawModule.name,
282
297
  });
283
298
  }
284
- if (seenDenoModuleNames.has(rawModule.name)) {
299
+ if (seenRuntimeModuleNames.has(rawModule.name)) {
285
300
  throw makeError("INVALID_INPUT", "duplicate Deno Module name", {
286
301
  moduleName: rawModule.name,
287
302
  });
288
303
  }
289
- seenDenoModuleNames.add(rawModule.name);
304
+ seenRuntimeModuleNames.add(rawModule.name);
290
305
  if (typeof rawModule.description !== "string" || rawModule.description.trim().length === 0) {
291
306
  throw makeError("INVALID_INPUT", "Deno Module description must be a non-empty string", {
292
307
  moduleName: rawModule.name,
@@ -324,9 +339,10 @@ function normalizeSkillsInput(value) {
324
339
  manifest: {
325
340
  guidance: skills.guidance,
326
341
  tools,
327
- ...(denoModules.length > 0
342
+ ...(runtimeModules.length > 0
328
343
  ? {
329
- denoModules: denoModules.map(({ name, description, usage, preferStdinExecution }) => ({
344
+ // Legacy Extension wire field; normalized data uses Runtime names.
345
+ denoModules: runtimeModules.map(({ name, description, usage, preferStdinExecution }) => ({
330
346
  name,
331
347
  description,
332
348
  usage,
@@ -336,7 +352,7 @@ function normalizeSkillsInput(value) {
336
352
  : {}),
337
353
  },
338
354
  handlers,
339
- denoModules: denoModules.map(({ name, artifact }) => ({
355
+ runtimeModules: runtimeModules.map(({ name, artifact }) => ({
340
356
  name,
341
357
  runtimeSource: artifact.runtimeSource,
342
358
  typesSource: artifact.typesSource,
@@ -478,7 +494,7 @@ export class PedelecWorkspace {
478
494
  }
479
495
  let modules;
480
496
  try {
481
- modules = normalizeWorkspaceDenoModules(options.denoModules);
497
+ modules = normalizeWorkspaceDenoModules(resolveRuntimeModules(options));
482
498
  }
483
499
  catch (error) {
484
500
  return Promise.reject(error);
@@ -534,6 +550,7 @@ export class Pedelec {
534
550
  pageWindow;
535
551
  channelId;
536
552
  bridgeTimeoutMs;
553
+ runtimeFullAccess;
537
554
  pendingRequests = new Map();
538
555
  sessions = new Map();
539
556
  lastSeqBySession = new Map();
@@ -542,6 +559,7 @@ export class Pedelec {
542
559
  pageActivityListenersAttached = false;
543
560
  lastReportedPageActive = null;
544
561
  constructor(options = {}) {
562
+ this.runtimeFullAccess = normalizeRuntimeFullAccess(options.runtimeFullAccess);
545
563
  this.pageWindow = typeof window === "undefined" ? null : window;
546
564
  this.channelId = createChannelId();
547
565
  this.bridgeTimeoutMs = Math.max(1, options.bridgeTimeoutMs ?? DEFAULT_BRIDGE_TIMEOUT_MS);
@@ -591,10 +609,17 @@ export class Pedelec {
591
609
  }
592
610
  /** @internal */
593
611
  async createSessionInternal(input = {}, workspace) {
612
+ const runtimeFullAccess = normalizeRuntimeFullAccess(input?.runtimeFullAccess);
613
+ if (runtimeFullAccess && !this.runtimeFullAccess) {
614
+ throw makeError("INVALID_INPUT", "Session runtimeFullAccess requires an Instance with runtimeFullAccess enabled");
615
+ }
616
+ // Admission belongs to the Extension: create_session must reach its pending
617
+ // approval queue so the first Full Instance request can open the Popup.
594
618
  const resolvedOrPromise = this.resolveCreateSessionInput(input);
595
619
  const resolvedInput = resolvedOrPromise instanceof Promise ? await resolvedOrPromise : resolvedOrPromise;
596
620
  const result = await this.request("create_session", {
597
621
  input: {
622
+ runtimeFullAccess,
598
623
  provider: resolvedInput.provider,
599
624
  model: resolvedInput.model,
600
625
  effort: resolvedInput.effort,
@@ -604,6 +629,14 @@ export class Pedelec {
604
629
  autoEndOnDisconnect: resolvedInput.autoEndOnDisconnect,
605
630
  },
606
631
  });
632
+ // Check the raw acknowledgment before other response validation so a known
633
+ // thread can still be cleaned up when a peer returns an invalid mode flag.
634
+ if (runtimeFullAccess && (!isPlainObject(result) || result.runtimeFullAccessApplied !== true)) {
635
+ if (isPlainObject(result) && typeof result.sessionId === "string" && result.sessionId.trim()) {
636
+ await this.abortSessionSetup(result.sessionId);
637
+ }
638
+ throw makeError("SDK_PROTOCOL_ERROR", "The connected Pedelec Extension/Desktop did not confirm Full Runtime Access", { feature: "runtimeFullAccess" });
639
+ }
607
640
  const normalizedResult = normalizeCreateSessionResponse(result);
608
641
  if (workspace && normalizedResult.workspace.workspaceId !== workspace.workspaceIdInternal) {
609
642
  throw makeError("SDK_PROTOCOL_ERROR", "create_session response returned a different Workspace", {
@@ -617,10 +650,10 @@ export class Pedelec {
617
650
  throw error;
618
651
  }
619
652
  try {
620
- for (const module of resolvedInput.denoModules) {
653
+ for (const module of resolvedInput.runtimeModules) {
621
654
  await this.uploadDenoModuleArtifact(normalizedResult.sessionId, module);
622
655
  }
623
- if (resolvedInput.denoModules.length > 0) {
656
+ if (resolvedInput.runtimeModules.length > 0) {
624
657
  await this.completeSessionSetup(normalizedResult.sessionId);
625
658
  }
626
659
  }
@@ -730,7 +763,7 @@ export class Pedelec {
730
763
  async getApprovalStatus() {
731
764
  try {
732
765
  const result = await this.request("get_approval_status");
733
- return result;
766
+ return { ...result, approved: result.approved === true && (!this.runtimeFullAccess || result.runtimeFullAccessApproved === true) };
734
767
  }
735
768
  catch (err) {
736
769
  const error = normalizeError(err, "EXTENSION_UNAVAILABLE", "Pedelec extension is unavailable.");
@@ -885,7 +918,7 @@ export class Pedelec {
885
918
  }
886
919
  postSdkHello(port) {
887
920
  try {
888
- port.postMessage({ type: SDK_HELLO_MESSAGE_TYPE, sdkVersion: SDK_VERSION });
921
+ port.postMessage({ type: SDK_HELLO_MESSAGE_TYPE, sdkVersion: SDK_VERSION, runtimeFullAccess: this.runtimeFullAccess });
889
922
  }
890
923
  catch (err) {
891
924
  const error = normalizeError(err, "EXTENSION_DISCONNECTED", "Pedelec extension disconnected.");
@@ -927,7 +960,7 @@ export class Pedelec {
927
960
  effort,
928
961
  skills: normalizedSkills.manifest,
929
962
  inlineToolHandlers: normalizedSkills.handlers,
930
- denoModules: normalizedSkills.denoModules,
963
+ runtimeModules: normalizedSkills.runtimeModules,
931
964
  autoEndOnDisconnect,
932
965
  };
933
966
  }
@@ -948,7 +981,7 @@ export class Pedelec {
948
981
  effortLevel,
949
982
  skills: normalizedSkills.manifest,
950
983
  inlineToolHandlers: normalizedSkills.handlers,
951
- denoModules: normalizedSkills.denoModules,
984
+ runtimeModules: normalizedSkills.runtimeModules,
952
985
  autoEndOnDisconnect,
953
986
  };
954
987
  }
@@ -1017,7 +1050,7 @@ export class Pedelec {
1017
1050
  effortLevel,
1018
1051
  skills: normalizedSkills.manifest,
1019
1052
  inlineToolHandlers: normalizedSkills.handlers,
1020
- denoModules: normalizedSkills.denoModules,
1053
+ runtimeModules: normalizedSkills.runtimeModules,
1021
1054
  autoEndOnDisconnect,
1022
1055
  };
1023
1056
  }
@@ -1,4 +1,4 @@
1
- import { Pedelec, defineTool, defineDenoModule, } from "./index";
1
+ import { Pedelec, defineTool, defineDenoModule, defineRuntimeModule, } from "./index";
2
2
  const spriteTools = defineDenoModule({
3
3
  name: "sprite-tools",
4
4
  description: "Sprite authoring utilities.",
@@ -347,3 +347,24 @@ const baseContext = {
347
347
  source: "sdk",
348
348
  };
349
349
  void baseContext;
350
+ const runtimeTools = defineRuntimeModule({
351
+ name: "runtime-tools", entry: "./helpers.ts", description: "Helpers", usage: 'import "runtime-tools";',
352
+ });
353
+ const runtimeName = runtimeTools.name;
354
+ const runtimeDefinition = runtimeTools;
355
+ void runtimeName;
356
+ void runtimeDefinition;
357
+ // @ts-expect-error Runtime Module entry is required
358
+ defineRuntimeModule({ name: "missing-entry" });
359
+ // @ts-expect-error Instance flag must be boolean
360
+ new Pedelec({ runtimeFullAccess: "true" });
361
+ async function runtimePublicContracts(workspace) {
362
+ const client = new Pedelec({ runtimeFullAccess: true });
363
+ await client.createSession({ runtimeFullAccess: true, skills: { guidance: "", tools: [], runtimeModules: [runtimeTools] } });
364
+ await client.createSession({ model: "model", runtimeFullAccess: true });
365
+ await workspace.createSession({ provider: "codex", runtimeFullAccess: true, skills: { guidance: "", tools: [], runtimeModules: [runtimeTools] } });
366
+ await workspace.run("", { runtimeModules: [runtimeTools] });
367
+ // @ts-expect-error Session flag must be boolean
368
+ await client.createSession({ runtimeFullAccess: 1 });
369
+ }
370
+ void runtimePublicContracts;
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "0.4.9";
1
+ export declare const SDK_VERSION = "0.4.11";
@@ -1,2 +1,2 @@
1
1
  // Generated from sdk/package.json. Do not edit manually.
2
- export const SDK_VERSION = "0.4.9";
2
+ export const SDK_VERSION = "0.4.11";
package/dist/vite.js CHANGED
@@ -5,7 +5,7 @@ import * as ts from "typescript";
5
5
  import { build } from "vite";
6
6
  import { PREPARED_DENO_MODULE_ARTIFACT_PROPERTY, } from "./deno-module-internal.js";
7
7
  const PACKAGE_NAME = "@kaoruisaac/pedelec";
8
- const DEFINE_DENO_MODULE_NAME = "defineDenoModule";
8
+ const DEFINE_RUNTIME_MODULE_NAMES = new Set(["defineRuntimeModule", "defineDenoModule"]);
9
9
  const ARTIFACT_HASH_VERSION = "pedelec-deno-module-artifact-v1";
10
10
  const SCRIPT_EXTENSIONS = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
11
11
  const DECLARATION_LIKE_EXTENSIONS = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".d.ts", ".json"]);
@@ -913,10 +913,10 @@ function findDenoModuleImportNames(sourceFile) {
913
913
  if (!namedBindings || !ts.isNamedImports(namedBindings))
914
914
  continue;
915
915
  for (const element of namedBindings.elements) {
916
- if (element.isTypeOnly || element.propertyName?.text !== DEFINE_DENO_MODULE_NAME && element.name.text !== DEFINE_DENO_MODULE_NAME)
916
+ if (element.isTypeOnly)
917
917
  continue;
918
918
  const importedName = element.propertyName?.text ?? element.name.text;
919
- if (importedName === DEFINE_DENO_MODULE_NAME)
919
+ if (DEFINE_RUNTIME_MODULE_NAMES.has(importedName))
920
920
  names.add(element.name.text);
921
921
  }
922
922
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaoruisaac/pedelec",
3
- "version": "0.4.9",
3
+ "version": "0.4.11",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",