@pstdio/sdk 0.5.0 → 0.6.0

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.
@@ -1,8 +1,9 @@
1
- import type { CommandExecuteRequest, CommandExecuteResponse, EnableInstalledExtensionRequest, EnableInstalledExtensionResponse, ListExtensionCommandsResponse, UpdateInstalledExtensionTemplateInput, UpdateInstalledExtensionTemplateResponse } from "pstdio-api-contracts";
1
+ import type { CommandExecuteRequest, CommandExecuteResponse, EnableInstalledExtensionRequest, EnableInstalledExtensionResponse, ListExtensionAppearanceResponse, ListExtensionCommandsResponse, UpdateInstalledExtensionTemplateInput, UpdateInstalledExtensionTemplateResponse } from "pstdio-api-contracts";
2
2
  import type { RequestFn } from "./request";
3
3
  export type ExtensionClient = {
4
4
  enableInstalled(projectId: string, installName: string, request: EnableInstalledExtensionRequest): Promise<EnableInstalledExtensionResponse>;
5
5
  updateInstalledTemplate(installName: string, templateKey: string, input: UpdateInstalledExtensionTemplateInput): Promise<UpdateInstalledExtensionTemplateResponse>;
6
+ listAppearance(projectId: string): Promise<ListExtensionAppearanceResponse>;
6
7
  listCommands(projectId: string): Promise<ListExtensionCommandsResponse>;
7
8
  execute(commandId: string, request: CommandExecuteRequest): Promise<CommandExecuteResponse>;
8
9
  };
@@ -28,6 +28,7 @@ var createExtensionClient = (request) => ({
28
28
  method: "PUT",
29
29
  body
30
30
  }),
31
+ listAppearance: (projectId) => request(`/v1/projects/${projectId}/extensions/appearance`),
31
32
  listCommands: (projectId) => request(`/v1/projects/${projectId}/extensions/commands`),
32
33
  execute: (commandId, input) => {
33
34
  const { projectId, ...body } = input;
@@ -1,16 +1,15 @@
1
1
  import type { ExtensionDefinition } from "./types/extension";
2
+ type ExactExtensionDefinition<TExtension extends ExtensionDefinition> = TExtension & Record<Exclude<keyof TExtension, keyof ExtensionDefinition>, never>;
2
3
  /**
3
- * Identity helper that preserves the literal type of the passed extension. Authors get
4
- * full autocomplete on contributions, and `commandsOf(ext)` can derive typed refs from
5
- * the returned definition.
4
+ * Identity helper that preserves the literal type of the passed contributions. Authors
5
+ * get full autocomplete on contributions, and `commandsOf(packageName, ext)` can derive typed refs
6
+ * from the returned definition. Extension identity (id, name, version, description,
7
+ * publisher, engines.pstdio) lives in package.json.
6
8
  *
7
9
  * @example
8
10
  * export default defineExtension({
9
- * id: "pstdio.example",
10
- * namespace: "example",
11
- * name: "Example",
12
- * apiVersion: "1",
13
11
  * commands: { ... },
14
12
  * });
15
13
  */
16
- export declare const defineExtension: <const TExtension extends ExtensionDefinition>(extension: TExtension) => TExtension;
14
+ export declare const defineExtension: <const TExtension extends ExtensionDefinition>(extension: ExactExtensionDefinition<TExtension>) => TExtension;
15
+ export {};
@@ -7,3 +7,5 @@ export { params } from "./params";
7
7
  export { commandEvent, commandRef, commandsOf, eventRef } from "./refs";
8
8
  export { defineSlot } from "./slots";
9
9
  export type * from "./types";
10
+ export { EXTENSION_API_VERSION } from "./types/extension";
11
+ export { ALWAYS_AVAILABLE_WEBVIEW_CAPABILITIES, WEBVIEW_DECLARABLE_CAPABILITIES, WEBVIEW_HOST_CAPABILITIES, WEBVIEW_HOST_CAPABILITY_VERSION, } from "./types/webview-capabilities";
@@ -17,11 +17,11 @@ var eventRef = (id) => ({ id });
17
17
  var commandEvent = (command, phase) => ({
18
18
  id: `command.${phase}:${command.id}`
19
19
  });
20
- var commandsOf = (extension) => {
20
+ var commandsOf = (packageName, extension) => {
21
21
  const refs = {};
22
22
  const commands = extension.commands ?? {};
23
23
  for (const key of Object.keys(commands)) {
24
- refs[key] = { id: `${extension.namespace}.${key}` };
24
+ refs[key] = { id: `${packageName}.${key}` };
25
25
  }
26
26
  return refs;
27
27
  };
@@ -98,6 +98,22 @@ var params = {
98
98
  resource: (options) => ({ type: "resource", ...options }),
99
99
  json: (options = {}) => ({ type: "json", ...options })
100
100
  };
101
+ // src/extensions/types/extension.ts
102
+ var EXTENSION_API_VERSION = "1.0.0";
103
+ // src/extensions/types/webview-capabilities.ts
104
+ var WEBVIEW_HOST_CAPABILITY_VERSION = 1;
105
+ var WEBVIEW_DECLARABLE_CAPABILITIES = [
106
+ "commands.execute",
107
+ "resource.open",
108
+ "notification.show",
109
+ "preferences.get",
110
+ "preferences.set"
111
+ ];
112
+ var ALWAYS_AVAILABLE_WEBVIEW_CAPABILITIES = ["host.dispatchKeyboardEvent"];
113
+ var WEBVIEW_HOST_CAPABILITIES = [
114
+ ...WEBVIEW_DECLARABLE_CAPABILITIES,
115
+ ...ALWAYS_AVAILABLE_WEBVIEW_CAPABILITIES
116
+ ];
101
117
  export {
102
118
  workspaceSlots,
103
119
  workspaceEvents,
@@ -116,5 +132,10 @@ export {
116
132
  defineCommand,
117
133
  commandsOf,
118
134
  commandRef,
119
- commandEvent
135
+ commandEvent,
136
+ WEBVIEW_HOST_CAPABILITY_VERSION,
137
+ WEBVIEW_HOST_CAPABILITIES,
138
+ WEBVIEW_DECLARABLE_CAPABILITIES,
139
+ EXTENSION_API_VERSION,
140
+ ALWAYS_AVAILABLE_WEBVIEW_CAPABILITIES
120
141
  };
@@ -5,6 +5,6 @@ import type { PackageAssetDescriptor } from "./types/resources";
5
5
  * so the runtime can locate the file no matter where the extension is installed.
6
6
  *
7
7
  * @example
8
- * webview: { entry: packageAsset("./dist/page.html", import.meta.url) }
8
+ * webview: { entry: packageAsset("./src/page.tsx", import.meta.url) }
9
9
  */
10
10
  export declare const packageAsset: (path: string, baseUrl: string) => PackageAssetDescriptor;
@@ -4,9 +4,9 @@ import type { CommandDefinition } from "./types/extension";
4
4
  import type { Struct } from "./types/json";
5
5
  import type { ParamObjectSchema, ParamsOf } from "./types/params";
6
6
  /**
7
- * Build a typed reference to a command by id. Authors generally prefer `commandsOf(ext)`,
8
- * which derives refs from the extension definition so a renamed command becomes a type
9
- * error at every call site.
7
+ * Build a typed reference to a command by id. Authors generally prefer
8
+ * `commandsOf(packageName, ext)`, which derives refs from the extension definition
9
+ * so a renamed command becomes a type error at every call site.
10
10
  */
11
11
  export declare const commandRef: <TParams extends Struct = Struct, TResult = unknown>(id: string) => CommandRef<TParams, TResult>;
12
12
  /** Build a typed reference to an event by id. */
@@ -23,16 +23,18 @@ type CommandsRefMap<TCommands extends CommandsRecord> = {
23
23
  [K in keyof TCommands]: CommandRefFromDefinition<TCommands[K]>;
24
24
  };
25
25
  /**
26
- * Derive typed `CommandRef`s from an extension. Renaming a command in the definition
27
- * surfaces as a type error wherever the ref is used.
26
+ * Derive typed `CommandRef`s from an extension contribution object. Renaming a
27
+ * command in the definition surfaces as a type error wherever the ref is used.
28
+ *
29
+ * The package name is explicit because identity now lives in package.json, not in
30
+ * `defineExtension()`.
28
31
  *
29
32
  * @example
30
- * const ext = defineExtension({ id: "lab", namespace: "lab", commands: { ... } });
31
- * const labCommands = commandsOf(ext);
33
+ * const ext = defineExtension({ commands: { ... } });
34
+ * const labCommands = commandsOf("extension-lab", ext);
32
35
  * labCommands.awaken; // CommandRef<{ title: string }, ...>
33
36
  */
34
37
  export declare const commandsOf: <TExtension extends {
35
- namespace: string;
36
38
  commands?: CommandsRecord;
37
- }>(extension: TExtension) => CommandsRefMap<NonNullable<TExtension["commands"]>>;
39
+ }>(packageName: string, extension: TExtension) => CommandsRefMap<NonNullable<TExtension["commands"]>>;
38
40
  export {};
@@ -151,7 +151,8 @@ export interface ExtensionSettingsApi<TSettings extends Struct = Struct> {
151
151
  export interface ExtensionContextBase {
152
152
  projectId: string;
153
153
  extensionId: string;
154
- namespace: string;
154
+ /** Extension package name. Used for grouping/prefixing user-facing references. */
155
+ name: string;
155
156
  repo?: RepoContext;
156
157
  source?: CommandSource;
157
158
  storage: ExtensionStorageApi;
@@ -2,6 +2,7 @@ import type { CommandRef, CommandSource } from "./commands";
2
2
  import type { JsonObject, Struct } from "./json";
3
3
  import type { PackageAssetDescriptor } from "./resources";
4
4
  import type { SlotRef } from "./slots";
5
+ import type { WebviewCapabilityDeclaration } from "./webview-capabilities";
5
6
  export interface CliContribution {
6
7
  path?: string[];
7
8
  globalAliases?: string[][];
@@ -40,7 +41,7 @@ export interface NavigationContribution<TSlotContext extends Struct = Struct, TP
40
41
  export interface WebviewContribution {
41
42
  entry: PackageAssetDescriptor;
42
43
  title?: string;
43
- sandbox?: "default" | "strict";
44
+ capabilities?: WebviewCapabilityDeclaration[];
44
45
  }
45
46
  export interface ViewContribution<TSlotContext extends Struct = Struct> {
46
47
  title: string;
@@ -65,7 +66,7 @@ export interface RendererContribution<TSlotContext extends Struct = Struct> {
65
66
  webview: WebviewContribution;
66
67
  }
67
68
  export interface ArtifactMountContribution {
68
- /** Relative path under .pstdio/<extension.namespace>/. */
69
+ /** Relative path under .pstdio/<extension.name>/. */
69
70
  path: string;
70
71
  label: string;
71
72
  repoRole?: "default" | "selected" | "workspace";
@@ -85,3 +86,17 @@ export interface SkillContribution {
85
86
  source: PackageAssetDescriptor;
86
87
  description?: string;
87
88
  }
89
+ export type ThemeMode = "light" | "dark";
90
+ export interface ThemeContribution {
91
+ title: string;
92
+ source: PackageAssetDescriptor;
93
+ format: "vscode-color-theme";
94
+ mode?: ThemeMode;
95
+ description?: string;
96
+ }
97
+ export interface FileIconThemeContribution {
98
+ title: string;
99
+ source: PackageAssetDescriptor;
100
+ format: "vscode-file-icon-theme";
101
+ description?: string;
102
+ }
@@ -1,12 +1,12 @@
1
1
  import type { CommandRef } from "./commands";
2
2
  import type { CommandMiddlewareHandler, CommandRunHandler, EventContext, ExtensionContextBase, MigrationContext, SetupContext } from "./context";
3
- import type { ArtifactMountContribution, CliContribution, MenuContribution, NavigationContribution, RendererContribution, RouteContribution, SettingsPanelContribution, SkillContribution, TemplateContribution, TemplateTypeContribution, ViewContribution } from "./contributions";
3
+ import type { ArtifactMountContribution, CliContribution, FileIconThemeContribution, MenuContribution, NavigationContribution, RendererContribution, RouteContribution, SettingsPanelContribution, SkillContribution, TemplateContribution, TemplateTypeContribution, ThemeContribution, ViewContribution } from "./contributions";
4
4
  import type { EventRef } from "./events";
5
5
  import type { JsonObject, MaybePromise, Struct } from "./json";
6
6
  import type { ParamObjectSchema, ParamsOf } from "./params";
7
7
  import type { SlotRef } from "./slots";
8
- /** API version of an extension's manifest. The runtime uses this to detect old extensions. */
9
- export type ExtensionApiVersion = "1";
8
+ /** Current host extension API version. `engines.pstdio` in package.json is a semver range checked against this. */
9
+ export declare const EXTENSION_API_VERSION = "1.0.0";
10
10
  type SchemaParams<TSchema extends ParamObjectSchema | undefined> = TSchema extends ParamObjectSchema ? ParamsOf<TSchema> : Struct;
11
11
  /**
12
12
  * A command exposed by an extension. The `params` schema (typed via `params.*`) drives
@@ -96,21 +96,29 @@ export interface LocalExtensionSource {
96
96
  export interface ProjectExtensionInstance {
97
97
  projectId: string;
98
98
  extensionId: string;
99
- namespace: string;
99
+ name: string;
100
100
  sourceName: string;
101
101
  enabled: boolean;
102
102
  config: JsonObject;
103
103
  }
104
- /** Identifying metadata for an extension. */
105
- export interface ExtensionMetadata {
106
- id: string;
107
- namespace: string;
104
+ /** Validated view of an extension's package.json identity fields. */
105
+ export interface PackageManifest {
106
+ /** Extension package name. Matches `^[a-z][a-z0-9-]*$`. */
108
107
  name: string;
109
- version?: string;
108
+ /** Package version (semver). */
109
+ version: string;
110
+ /** Optional human-friendly name. Falls back to `name`. */
111
+ displayName?: string;
112
+ /** Optional package description. */
110
113
  description?: string;
111
- /** Manifest API version. The runtime uses this to detect incompatible extensions. */
112
- apiVersion: ExtensionApiVersion;
113
- settings?: ParamObjectSchema;
114
+ /** Publisher segment of the extension id. Matches `^[a-z][a-z0-9-]*$`. */
115
+ publisher: string;
116
+ /** Relative path to the contributions entry module. */
117
+ main: string;
118
+ /** Semver range checked against the host extension API version. */
119
+ enginesPstdio: string;
120
+ /** Derived `${publisher}.${name}`. */
121
+ id: string;
114
122
  }
115
123
  /** UI surface contributions: slots, routes, panels, renderers. */
116
124
  export interface UiContributions {
@@ -135,6 +143,8 @@ export interface AssetContributions {
135
143
  templateTypes?: Record<string, TemplateTypeContribution>;
136
144
  templates?: Record<string, TemplateContribution>;
137
145
  skills?: Record<string, SkillContribution>;
146
+ themes?: Record<string, ThemeContribution>;
147
+ fileIconThemes?: Record<string, FileIconThemeContribution>;
138
148
  }
139
149
  /** Provider contributions: harnesses, workspace types. */
140
150
  export interface ProviderContributions {
@@ -147,10 +157,12 @@ export interface ExtensionLifecycle {
147
157
  migrate?: (ctx: MigrationContext, fromVersion: string | null) => MaybePromise<void>;
148
158
  }
149
159
  /**
150
- * The full shape of an extension manifest. Composed from focused capability mixins so
151
- * each surface is independently discoverable.
160
+ * The full shape of an extension's contributions module. Identity (id, name, version,
161
+ * description, etc.) lives in `package.json`; `defineExtension` only accepts
162
+ * contribution surfaces.
152
163
  */
153
- export interface ExtensionDefinition extends ExtensionMetadata, UiContributions, BehaviourContributions, AssetContributions, ProviderContributions, ExtensionLifecycle {
164
+ export interface ExtensionDefinition extends UiContributions, BehaviourContributions, AssetContributions, ProviderContributions, ExtensionLifecycle {
165
+ settings?: ParamObjectSchema;
154
166
  }
155
167
  export type ExtensionSourceKind = "local" | "package" | "builtin";
156
168
  export {};
@@ -7,3 +7,4 @@ export type * from "./json";
7
7
  export type * from "./params";
8
8
  export type * from "./resources";
9
9
  export type * from "./slots";
10
+ export * from "./webview-capabilities";
@@ -0,0 +1,55 @@
1
+ import type { JsonObject } from "./json";
2
+ import type { RepoContext, ResourceRef } from "./resources";
3
+ export declare const WEBVIEW_HOST_CAPABILITY_VERSION = 1;
4
+ export declare const WEBVIEW_DECLARABLE_CAPABILITIES: readonly ["commands.execute", "resource.open", "notification.show", "preferences.get", "preferences.set"];
5
+ export declare const ALWAYS_AVAILABLE_WEBVIEW_CAPABILITIES: readonly ["host.dispatchKeyboardEvent"];
6
+ export declare const WEBVIEW_HOST_CAPABILITIES: readonly ["commands.execute", "resource.open", "notification.show", "preferences.get", "preferences.set", "host.dispatchKeyboardEvent"];
7
+ export type WebviewHostCapability = (typeof WEBVIEW_HOST_CAPABILITIES)[number];
8
+ export type WebviewDeclarableCapability = (typeof WEBVIEW_DECLARABLE_CAPABILITIES)[number];
9
+ export type WebviewCapabilityDeclaration = WebviewDeclarableCapability | `${WebviewDeclarableCapability}@${typeof WEBVIEW_HOST_CAPABILITY_VERSION}`;
10
+ export interface WebviewCommandsExecuteParams {
11
+ commandId: string;
12
+ params?: JsonObject;
13
+ resource?: ResourceRef;
14
+ repo?: RepoContext;
15
+ metadata?: JsonObject;
16
+ }
17
+ export interface WebviewResourceOpenParams {
18
+ href?: string;
19
+ resource?: ResourceRef;
20
+ input?: {
21
+ replaceActive?: boolean;
22
+ };
23
+ }
24
+ export interface WebviewNotificationShowParams {
25
+ level: "info" | "success" | "warning" | "error";
26
+ title: string;
27
+ message?: string;
28
+ }
29
+ export interface WebviewPreferencesGetParams {
30
+ name: string;
31
+ scope?: {
32
+ scope: "default" | "user" | "project" | "repo" | "workspace" | "extension" | "session";
33
+ scopeId?: string;
34
+ };
35
+ }
36
+ export interface WebviewPreferencesSetParams extends WebviewPreferencesGetParams {
37
+ value: boolean | number | string | string[] | number[] | boolean[] | Record<string, unknown>;
38
+ }
39
+ export interface WebviewKeyboardEventParams {
40
+ key?: string;
41
+ code?: string;
42
+ ctrlKey?: boolean;
43
+ metaKey?: boolean;
44
+ altKey?: boolean;
45
+ shiftKey?: boolean;
46
+ repeat?: boolean;
47
+ }
48
+ export interface WebviewHostCapabilityParams {
49
+ "commands.execute": WebviewCommandsExecuteParams;
50
+ "resource.open": WebviewResourceOpenParams;
51
+ "notification.show": WebviewNotificationShowParams;
52
+ "preferences.get": WebviewPreferencesGetParams;
53
+ "preferences.set": WebviewPreferencesSetParams;
54
+ "host.dispatchKeyboardEvent": WebviewKeyboardEventParams;
55
+ }
@@ -2,7 +2,7 @@ import type { BaseHookContext } from "./base";
2
2
  import type { HookTicket, HookWorkspace } from "./entities";
3
3
  export type SessionHookContext = BaseHookContext & {
4
4
  sessionId: string;
5
- sessionStatus: "in_progress" | "awaiting_input" | "completed" | "failed" | "cancelled" | "disconnected";
5
+ sessionStatus: "in_progress" | "awaiting_input" | "queued" | "completed" | "failed" | "cancelled" | "disconnected";
6
6
  originalSessionId?: string;
7
7
  workspace?: HookWorkspace;
8
8
  workspaceId?: string;
@@ -5,7 +5,7 @@ export declare const createSession: (ctx: PluginHelperContext, input: CreateSess
5
5
  id: string;
6
6
  project_id: string | null;
7
7
  title: string;
8
- status: "in_progress" | "awaiting_input" | "completed" | "failed" | "cancelled" | "disconnected";
8
+ status: "in_progress" | "awaiting_input" | "queued" | "completed" | "failed" | "cancelled" | "disconnected";
9
9
  archived: boolean;
10
10
  last_request_started: string | null;
11
11
  last_request_ended: string | null;
@@ -7,7 +7,7 @@ export declare const followupSession: (ctx: PluginHelperContext, input: Followup
7
7
  id: string;
8
8
  project_id: string | null;
9
9
  title: string;
10
- status: "in_progress" | "awaiting_input" | "completed" | "failed" | "cancelled" | "disconnected";
10
+ status: "in_progress" | "awaiting_input" | "queued" | "completed" | "failed" | "cancelled" | "disconnected";
11
11
  archived: boolean;
12
12
  last_request_started: string | null;
13
13
  last_request_ended: string | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pstdio/sdk",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/pufflyai/prompt-studio"