@pstdio/sdk 0.14.0 → 0.16.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.
@@ -0,0 +1,49 @@
1
+ export interface TerminalSessionRequest {
2
+ /** Command + args to run; defaults to the user's login shell when omitted. */
3
+ command?: string[];
4
+ /** Working directory; falls back to the extension's workspace root. */
5
+ cwd?: string;
6
+ /** Extra env vars merged over the inherited environment. */
7
+ env?: Record<string, string>;
8
+ /** Initial column count; the renderer can resize later. */
9
+ cols: number;
10
+ /** Initial row count; the renderer can resize later. */
11
+ rows: number;
12
+ }
13
+ export type TerminalSessionOperation = {
14
+ operation: "open";
15
+ request: TerminalSessionRequest;
16
+ } | {
17
+ operation: "write";
18
+ sessionId: string;
19
+ data: string | Uint8Array;
20
+ } | {
21
+ operation: "resize";
22
+ sessionId: string;
23
+ cols: number;
24
+ rows: number;
25
+ } | {
26
+ operation: "kill";
27
+ sessionId: string;
28
+ signal?: string;
29
+ } | {
30
+ operation: "subscribe";
31
+ sessionId: string;
32
+ };
33
+ export type TerminalSessionResult = {
34
+ operation: "open";
35
+ sessionId: string;
36
+ } | {
37
+ operation: "write" | "resize" | "kill" | "subscribe";
38
+ accepted: true;
39
+ };
40
+ export type TerminalHostEvent = {
41
+ sessionId: string;
42
+ kind: "data";
43
+ chunk: Uint8Array;
44
+ } | {
45
+ sessionId: string;
46
+ kind: "exit";
47
+ code: number | null;
48
+ signal: string | null;
49
+ };
@@ -10,6 +10,8 @@
10
10
  */
11
11
  export type GuestHost = {
12
12
  call: <TResult = unknown>(method: string, params?: unknown) => Promise<TResult>;
13
+ /** Subscribe to host-pushed events for a capability scope (e.g. "terminal.session"). */
14
+ onEvent: (scope: string, handler: (payload: unknown) => void) => () => void;
13
15
  };
14
16
  export type PropsStore<TProps = unknown> = {
15
17
  get: () => TProps;
@@ -1,11 +1,12 @@
1
1
  export type { CreateNotificationInput, ListNotificationsQuery, ListNotificationsResponse, Notification, NotificationAction, NotificationActionResult, NotificationActorType, NotificationKind, NotificationOrigin, NotificationPriority, NotificationStatus, UpdateNotificationInput, } from "pstdio-api-contracts";
2
2
  export type * from "pstdio-api-contracts/extension-kernel";
3
- export type { CommitPayload, ConflictPayload, MergePayload, RebasePayload, SessionLifecyclePayload, WorktreeCreatedEventPayload, WorktreeRemovedPayload, } from "pstdio-api-contracts/extension-kernel";
4
- export { ALWAYS_AVAILABLE_WEBVIEW_CAPABILITIES, EXTENSION_API_VERSION, getWorkbenchTargetDefinition, gitEvents, isLocalizedString, type Localizable, type LocalizedString, l10n, packageAsset, projectEvents, projectSlots, sessionEvents, sessionSlots, WEBVIEW_DECLARABLE_CAPABILITIES, WEBVIEW_HOST_CAPABILITIES, WEBVIEW_HOST_CAPABILITY_VERSION, type WorkbenchAttachmentTarget, type WorkbenchContributionKind, type WorkbenchLayoutTarget, type WorkbenchMenuTarget, type WorkbenchModeLayoutTarget, type WorkbenchSettingsScope, type WorkbenchSettingsTarget, type WorkbenchTargetDefinition, type WorkbenchTargetGranularity, type WorkbenchTreeTarget, type WorkbenchViewTarget, workbenchMenuTargets, workbenchModeLayoutTargets, workbenchSettingsScopes, workbenchSettingsTargets, workbenchTargets, workbenchTreeTargets, workbenchViewTargets, workspaceEvents, workspaceSlots, worktreeEvents, } from "pstdio-api-contracts/extension-kernel";
3
+ export type { CommitPayload, ConflictPayload, MergePayload, RebasePayload, SessionLifecyclePayload, WorkspaceProvisionPayload, WorkspaceType, WorktreeRemovedPayload, } from "pstdio-api-contracts/extension-kernel";
4
+ export { ALWAYS_AVAILABLE_WEBVIEW_CAPABILITIES, EXTENSION_API_VERSION, getWorkbenchModeLayoutTargetPanel, getWorkbenchTargetDefinition, gitEvents, isLocalizedString, type Localizable, type LocalizedString, l10n, packageAsset, projectEvents, projectSlots, sessionEvents, sessionSlots, WEBVIEW_DECLARABLE_CAPABILITIES, WEBVIEW_HOST_CAPABILITIES, WEBVIEW_HOST_CAPABILITY_VERSION, type WorkbenchAttachmentTarget, type WorkbenchContributionKind, type WorkbenchLayoutTarget, type WorkbenchMenuTarget, type WorkbenchModeLayoutTarget, type WorkbenchModePanel, type WorkbenchSettingsScope, type WorkbenchSettingsTarget, type WorkbenchTargetDefinition, type WorkbenchTargetGranularity, type WorkbenchTreeTarget, type WorkbenchViewTarget, workbenchMenuTargets, workbenchModeLayoutTargets, workbenchModePanels, workbenchSettingsScopes, workbenchSettingsTargets, workbenchTargets, workbenchTreeTargets, workbenchViewTargets, workspaceEvents, workspaceSlots, worktreeEvents, } from "pstdio-api-contracts/extension-kernel";
5
5
  export { type CommandResponse, unwrapCommandOutcome } from "./command-outcome";
6
6
  export { defineCommand, defineHook, defineMiddleware } from "./define-command";
7
7
  export { defineExtension } from "./define-extension";
8
8
  export { defineExtensionView, type ExtensionViewModule, type ExtensionViewRender, type ExtensionViewRenderContext, type GuestHost, type PropsStore, type WebviewFilesClient, } from "./define-extension-view";
9
9
  export { params } from "./params";
10
10
  export { commandEvent, commandRef, commandsOf, eventRef } from "./refs";
11
+ export { createTerminalSessionBridge, type TerminalSessionAdapter, type TerminalSessionBridge, type TerminalSessionExit, } from "./terminal-session-bridge";
11
12
  export { matchesResourceWhen } from "./when";
@@ -28,7 +28,7 @@ var defineSlot = (id, options) => ({
28
28
 
29
29
  // ../pstdio-api-contracts/src/extension-kernel/kernel-slots.ts
30
30
  var projectSlots = {
31
- sidebar: defineSlot("project.sidebar", { kind: "view" }),
31
+ sidenav: defineSlot("project.sidenav", { kind: "panel" }),
32
32
  headerPrimary: defineSlot("project.headerPrimary", { kind: "menu" }),
33
33
  headerOverflow: defineSlot("project.headerOverflow", { kind: "menu" }),
34
34
  settingsPanels: defineSlot("project.settingsPanels", { kind: "settings" })
@@ -41,7 +41,7 @@ var sessionSlots = {
41
41
  var workspaceSlots = {
42
42
  headerPrimary: defineSlot("workspace.headerPrimary", { kind: "menu" }),
43
43
  headerOverflow: defineSlot("workspace.headerOverflow", { kind: "menu" }),
44
- sidebar: defineSlot("workspace.sidebar", { kind: "view" })
44
+ sidenav: defineSlot("workspace.sidenav", { kind: "panel" })
45
45
  };
46
46
  var projectEvents = {
47
47
  opened: eventRef("project.opened")
@@ -56,11 +56,12 @@ var sessionEvents = {
56
56
  };
57
57
  var workspaceEvents = {
58
58
  created: eventRef("workspace.created"),
59
+ provision: eventRef("workspace.provision"),
60
+ ready: eventRef("workspace.ready"),
59
61
  archived: eventRef("workspace.archived"),
60
62
  deleted: eventRef("workspace.deleted")
61
63
  };
62
64
  var worktreeEvents = {
63
- created: eventRef("worktree.created"),
64
65
  removed: eventRef("worktree.removed")
65
66
  };
66
67
  var gitEvents = {
@@ -98,6 +99,7 @@ var WEBVIEW_DECLARABLE_CAPABILITIES = [
98
99
  "extension.settings.get",
99
100
  "extension.settings.set",
100
101
  "extension.settings.delete",
102
+ "terminal.session",
101
103
  "files.upload",
102
104
  "files.list",
103
105
  "files.delete"
@@ -114,6 +116,20 @@ var workbenchTreeTargets = [
114
116
  "workbench.main.left.tree",
115
117
  "workbench.main.right.tree"
116
118
  ];
119
+ var workbenchRegions = [
120
+ "nav",
121
+ "activity",
122
+ "sidenav-header",
123
+ "sidenav",
124
+ "main-header",
125
+ "main",
126
+ "secondary-header",
127
+ "secondary",
128
+ "side-header",
129
+ "side",
130
+ "status",
131
+ "overlay"
132
+ ];
117
133
  var workbenchViewTargets = [
118
134
  "workbench.main",
119
135
  "workbench.main.left",
@@ -122,6 +138,7 @@ var workbenchViewTargets = [
122
138
  ];
123
139
  var workbenchSettingsTargets = ["workbench.settings"];
124
140
  var workbenchSettingsScopes = ["project", "global"];
141
+ var workbenchModePanels = ["main", "secondary", "side"];
125
142
  var workbenchModeLayoutTargets = [
126
143
  "workbench.left",
127
144
  "workbench.main.left",
@@ -129,6 +146,14 @@ var workbenchModeLayoutTargets = [
129
146
  "workbench.main.right",
130
147
  "workbench.secondary"
131
148
  ];
149
+ var workbenchModeLayoutTargetPanels = {
150
+ "workbench.left": undefined,
151
+ "workbench.main.left": "main",
152
+ "workbench.main": "main",
153
+ "workbench.main.right": "main",
154
+ "workbench.secondary": "secondary"
155
+ };
156
+ var getWorkbenchModeLayoutTargetPanel = (target) => workbenchModeLayoutTargetPanels[target];
132
157
  var workbenchTargets = [
133
158
  {
134
159
  id: "workbench.nav.actions",
@@ -160,30 +185,6 @@ var workbenchTargets = [
160
185
  granularity: "areaTree",
161
186
  rationale: "Tree entries for the active tree renderer mounted in the main-right area."
162
187
  },
163
- {
164
- id: "workbench.main",
165
- allowedKinds: ["view"],
166
- granularity: "area",
167
- rationale: "Direct extension view placement in the main area."
168
- },
169
- {
170
- id: "workbench.main.left",
171
- allowedKinds: ["view"],
172
- granularity: "area",
173
- rationale: "Direct extension view placement in the main-left area."
174
- },
175
- {
176
- id: "workbench.main.right",
177
- allowedKinds: ["view"],
178
- granularity: "area",
179
- rationale: "Direct extension view placement in the main-right area."
180
- },
181
- {
182
- id: "workbench.secondary",
183
- allowedKinds: ["view"],
184
- granularity: "area",
185
- rationale: "Direct extension view placement in the secondary area."
186
- },
187
188
  {
188
189
  id: "workbench.settings",
189
190
  allowedKinds: ["settings"],
@@ -274,6 +275,8 @@ var defineExtensionView = (definition) => ({
274
275
  var params = {
275
276
  text: (options) => ({ type: "text", ...options }),
276
277
  longText: (options) => ({ type: "longtext", ...options }),
278
+ markdown: (options) => ({ type: "markdown", ...options }),
279
+ files: (options) => ({ type: "files", ...options }),
277
280
  number: (options) => ({ type: "number", ...options }),
278
281
  boolean: (options) => ({ type: "boolean", ...options }),
279
282
  select: (options) => ({ type: "select", ...options }),
@@ -308,6 +311,78 @@ var commandsOf = (packageName, extension) => {
308
311
  }
309
312
  return refs;
310
313
  };
314
+ // src/extensions/terminal-session-bridge.ts
315
+ var TERMINAL_SESSION_CAPABILITY = "terminal.session";
316
+ var createTerminalSessionBridge = (host) => ({
317
+ async openSession(request) {
318
+ const call = (operation) => host.call(TERMINAL_SESSION_CAPABILITY, operation);
319
+ const opened = await call({ operation: "open", request });
320
+ const sessionId = opened.sessionId;
321
+ const dataHandlers = new Set;
322
+ const exitHandlers = new Set;
323
+ const errorHandlers = new Set;
324
+ const callDetached = (operation) => {
325
+ call(operation).catch((error) => {
326
+ const message = error instanceof Error ? error.message : String(error);
327
+ for (const handler of errorHandlers)
328
+ handler({ message });
329
+ });
330
+ };
331
+ const pendingData = [];
332
+ let pendingExit = null;
333
+ const unsubscribeHostEvents = host.onEvent(TERMINAL_SESSION_CAPABILITY, (payload) => {
334
+ const event = payload;
335
+ if (event.sessionId !== sessionId)
336
+ return;
337
+ if (event.kind === "data") {
338
+ if (dataHandlers.size === 0) {
339
+ pendingData.push(event.chunk);
340
+ return;
341
+ }
342
+ for (const handler of dataHandlers)
343
+ handler(event.chunk);
344
+ return;
345
+ }
346
+ const exit = { code: event.code, signal: event.signal };
347
+ if (exitHandlers.size === 0)
348
+ pendingExit = exit;
349
+ for (const handler of exitHandlers)
350
+ handler(exit);
351
+ unsubscribeHostEvents();
352
+ });
353
+ await call({ operation: "subscribe", sessionId });
354
+ return {
355
+ id: sessionId,
356
+ write(data) {
357
+ callDetached({ operation: "write", sessionId, data });
358
+ },
359
+ resize(cols, rows) {
360
+ callDetached({ operation: "resize", sessionId, cols, rows });
361
+ },
362
+ async kill(signal) {
363
+ await call({ operation: "kill", sessionId, signal });
364
+ },
365
+ onData(handler) {
366
+ dataHandlers.add(handler);
367
+ while (pendingData.length > 0)
368
+ handler(pendingData.shift());
369
+ return () => dataHandlers.delete(handler);
370
+ },
371
+ onExit(handler) {
372
+ exitHandlers.add(handler);
373
+ if (pendingExit) {
374
+ handler(pendingExit);
375
+ pendingExit = null;
376
+ }
377
+ return () => exitHandlers.delete(handler);
378
+ },
379
+ onError(handler) {
380
+ errorHandlers.add(handler);
381
+ return () => errorHandlers.delete(handler);
382
+ }
383
+ };
384
+ }
385
+ });
311
386
  // src/extensions/when.ts
312
387
  var matchesResourceWhen = (when, resourceType) => {
313
388
  const resourceTypes = when?.resourceType;
@@ -324,6 +399,7 @@ export {
324
399
  workbenchTargets,
325
400
  workbenchSettingsTargets,
326
401
  workbenchSettingsScopes,
402
+ workbenchModePanels,
327
403
  workbenchModeLayoutTargets,
328
404
  workbenchMenuTargets,
329
405
  unwrapCommandOutcome,
@@ -338,12 +414,14 @@ export {
338
414
  isLocalizedString,
339
415
  gitEvents,
340
416
  getWorkbenchTargetDefinition,
417
+ getWorkbenchModeLayoutTargetPanel,
341
418
  eventRef,
342
419
  defineMiddleware,
343
420
  defineHook,
344
421
  defineExtensionView,
345
422
  defineExtension,
346
423
  defineCommand,
424
+ createTerminalSessionBridge,
347
425
  commandsOf,
348
426
  commandRef,
349
427
  commandEvent,
@@ -1,4 +1,4 @@
1
- import type { BooleanParam, HarnessParam, JsonParam, ListParam, LongTextParam, MultiSelectParam, NumberParam, RepoParam, ResourceParam, SelectParam, TemplateParam, TextParam } from "pstdio-api-contracts/extension-kernel";
1
+ import type { BooleanParam, FilesParam, HarnessParam, JsonParam, ListParam, LongTextParam, MarkdownParam, MultiSelectParam, NumberParam, RepoParam, ResourceParam, SelectParam, TemplateParam, TextParam } from "pstdio-api-contracts/extension-kernel";
2
2
  type RequiredOf<TOptions> = TOptions extends {
3
3
  required: infer TRequired extends boolean;
4
4
  } ? TRequired : undefined;
@@ -18,6 +18,8 @@ type ParamOptions<TParam extends {
18
18
  export declare const params: {
19
19
  text: <const TOptions extends ParamOptions<TextParam> | undefined = undefined>(options?: TOptions) => TextParam<RequiredOf<TOptions>>;
20
20
  longText: <const TOptions extends ParamOptions<LongTextParam> | undefined = undefined>(options?: TOptions) => LongTextParam<RequiredOf<TOptions>>;
21
+ markdown: <const TOptions extends ParamOptions<MarkdownParam> | undefined = undefined>(options?: TOptions) => MarkdownParam<RequiredOf<TOptions>>;
22
+ files: <const TOptions extends ParamOptions<FilesParam> | undefined = undefined>(options?: TOptions) => FilesParam<RequiredOf<TOptions>>;
21
23
  number: <const TOptions extends ParamOptions<NumberParam> | undefined = undefined>(options?: TOptions) => NumberParam<RequiredOf<TOptions>>;
22
24
  boolean: <const TOptions extends ParamOptions<BooleanParam> | undefined = undefined>(options?: TOptions) => BooleanParam<RequiredOf<TOptions>>;
23
25
  select: <const TOptions extends ParamOptions<SelectParam>>(options: TOptions) => SelectParam<RequiredOf<TOptions>>;
@@ -0,0 +1,32 @@
1
+ import type { TerminalSessionRequest } from "../api/terminal";
2
+ import type { GuestHost } from "./define-extension-view";
3
+ export interface TerminalSessionExit {
4
+ code: number | null;
5
+ signal: string | null;
6
+ }
7
+ /**
8
+ * Renderer-side session over the `terminal.session` capability. Structurally
9
+ * compatible with the `TerminalSessionAdapter` contract of `@pstdio/ui/terminal`,
10
+ * so it plugs straight into the `Terminal` component's `bridge` prop.
11
+ */
12
+ export interface TerminalSessionAdapter {
13
+ readonly id: string;
14
+ write(data: string | Uint8Array): void;
15
+ resize(cols: number, rows: number): void;
16
+ kill(signal?: string): Promise<void>;
17
+ onData(handler: (chunk: Uint8Array) => void): () => void;
18
+ onExit(handler: (exit: TerminalSessionExit) => void): () => void;
19
+ onError(handler: (error: {
20
+ message: string;
21
+ }) => void): () => void;
22
+ }
23
+ export interface TerminalSessionBridge {
24
+ openSession(request: TerminalSessionRequest): Promise<TerminalSessionAdapter>;
25
+ }
26
+ /**
27
+ * Builds a terminal bridge for an extension webview from its `GuestHost`.
28
+ * Operations go through `host.call("terminal.session", ...)`; output and exit
29
+ * events arrive through the host event channel. The webview must declare the
30
+ * `terminal.session` capability or every call is rejected by the host gate.
31
+ */
32
+ export declare const createTerminalSessionBridge: (host: GuestHost) => TerminalSessionBridge;