@pstdio/sdk 0.22.1 → 0.23.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.
package/README.md CHANGED
@@ -32,6 +32,32 @@ Page targets change location. Panel targets preserve it. Compound targets contai
32
32
 
33
33
  Use `qualifyRef(owner, ref)` in provider contract modules. Keep definitions local and pass qualified refs between extensions. For webviews, declare capabilities and call the typed `GuestHost`; `placement.close` closes the calling placement through the normal tab controller.
34
34
 
35
+ ## Dashboard URLs
36
+
37
+ Use `serializePageUrl({ projectId, page, resource })` to return a dashboard link from a command. The page descriptor contains its `id`, qualified `ref`, and declared `path`; `resource` is optional. The workbench uses the same route and resource codec.
38
+
39
+ Use `parsePageUrl({ url, projectId, pages })` to resolve a saved link against the expected project and allowed page descriptors. It accepts root-relative URLs and returns a page ID and optional resource, or `undefined` for an unsupported destination. It never fetches the URL. The caller still checks its supported resource kind and owner. A URL grants no access.
40
+
41
+ Page and panel navigation targets remain the API for opening views and tabs.
42
+
43
+ ## Webview change subscriptions
44
+
45
+ Use the typed client's `events.subscribe(event, listener)` to refetch after a command changes data:
46
+
47
+ ```ts
48
+ const client = createWebviewClient<typeof commands>(host);
49
+ const stop = client.events.subscribe(
50
+ { kind: "event", id: "notes.changed" },
51
+ () => void reloadNotes(),
52
+ );
53
+ // Dispose when the view unmounts.
54
+ stop();
55
+ ```
56
+
57
+ Local event refs use the client's extension owner: `{ kind: "event", id: "notes.changed" }` resolves to `<extensionId>.event.notes.changed`. Qualified event refs can name another extension in the same project. String IDs are already resolved and stay unchanged. Host-owned and command-lifecycle refs follow the runtime's rules through the shared `resolveEventReferenceId` helper. Commands emit events after committing their changes through `ctx.events.emit`.
58
+
59
+ The host delivers only events matching the view's project. Projectless events reach global views only. Listeners also run when host sync connects or reconnects, so a mounted view can reconcile missed changes. Load current data when mounting, then subscribe; events are invalidations, not stored records or an exactly-once stream. Duplicate refetches must be safe. The subscription does not reload the webview document or grant new permissions.
60
+
35
61
  ## Package delivery
36
62
 
37
63
  Development and installed consumers both load built SDK entries. Repository development builds this package before starting the source CLI. Builds stage release files under `.publish` through the shared release script. Package verification installs those same staged artifacts into a temporary directory outside the monorepo and checks every entry point.
@@ -499,21 +499,26 @@ var createSyncClient = (clientOptions) => ({
499
499
  if (event === "init")
500
500
  setConnected();
501
501
  };
502
+ const readConnection = async (signal) => {
503
+ const response = await resolveFetch(clientOptions)(resolveClientUrl(resolveBaseUrl(clientOptions), buildSyncStreamPath(lastSeq)), {
504
+ headers: Object.fromEntries(createRequestHeaders(clientOptions).entries()),
505
+ signal,
506
+ credentials: "same-origin"
507
+ });
508
+ if (!response.ok || !response.body)
509
+ throw new Error("SSE connection failed");
510
+ if (closed)
511
+ return;
512
+ if (lastSeq > 0)
513
+ setConnected();
514
+ await readSseStream(response.body, ({ event, data }) => handleEvent(event, data), { signal });
515
+ };
502
516
  const connect = async () => {
503
517
  if (closed)
504
518
  return;
505
519
  abortController = new AbortController;
506
520
  try {
507
- const response = await resolveFetch(clientOptions)(resolveClientUrl(resolveBaseUrl(clientOptions), buildSyncStreamPath(lastSeq)), {
508
- headers: Object.fromEntries(createRequestHeaders(clientOptions).entries()),
509
- signal: abortController.signal,
510
- credentials: "same-origin"
511
- });
512
- if (!response.ok || !response.body)
513
- throw new Error("SSE connection failed");
514
- await readSseStream(response.body, ({ event, data }) => handleEvent(event, data), {
515
- signal: abortController.signal
516
- });
521
+ await readConnection(abortController.signal);
517
522
  } catch (err) {
518
523
  if (closed || err.name === "AbortError")
519
524
  return;
package/dist/client.d.ts CHANGED
@@ -1432,6 +1432,7 @@ export declare type SseEvent = {
1432
1432
  };
1433
1433
 
1434
1434
  export declare type StartSyncInput = SyncWriterProvider & {
1435
+ /** Called after the initial snapshot, or when a cursor-based connection resumes. */
1435
1436
  onConnected?: () => void;
1436
1437
  onDisconnected?: () => void;
1437
1438
  onConnectionLost?: () => void;
@@ -215,7 +215,7 @@ var WEBVIEW_HOST_CAPABILITIES = [
215
215
  ...ALWAYS_AVAILABLE_WEBVIEW_CAPABILITIES
216
216
  ];
217
217
  // package.json
218
- var version = "0.22.1";
218
+ var version = "0.23.0";
219
219
 
220
220
  // src/version.ts
221
221
  var SDK_VERSION = version;
@@ -345,6 +345,180 @@ var defineExtensionView = (definition) => ({
345
345
  return typeof cleanup === "function" ? cleanup : () => {};
346
346
  }
347
347
  });
348
+ // src/extensions/event-reference.ts
349
+ var resolveEventReferenceId = (ref, ownerExtensionId) => {
350
+ if (typeof ref === "string")
351
+ return ref;
352
+ const extensionId = ref.extensionId ?? ownerExtensionId;
353
+ if (!extensionId || extensionId === "pstdio")
354
+ return ref.id;
355
+ const lifecycle = /^(command\.(?:requested|started|completed|rejected|failed):)(.+)$/.exec(ref.id);
356
+ if (lifecycle)
357
+ return `${lifecycle[1]}${extensionId}.command.${lifecycle[2]}`;
358
+ return `${extensionId}.event.${ref.id}`;
359
+ };
360
+ // src/extensions/page-resource-codec.ts
361
+ var fromUri = (uri) => {
362
+ try {
363
+ const parsed = new URL(uri);
364
+ if (parsed.protocol !== "pstdio:" || parsed.hostname !== "extension-resource")
365
+ return;
366
+ const [type, id, ...rest] = parsed.pathname.slice(1).split("/");
367
+ if (!type || !id || rest.length > 0)
368
+ return;
369
+ const extensionId = parsed.searchParams.get("extensionId");
370
+ const projectId = parsed.searchParams.get("projectId");
371
+ return {
372
+ type: decodeURIComponent(type),
373
+ id: decodeURIComponent(id),
374
+ ...extensionId ? { extensionId } : {},
375
+ ...projectId ? { projectId } : {}
376
+ };
377
+ } catch {
378
+ return;
379
+ }
380
+ };
381
+ var defaultPageResourceCodec = {
382
+ normalize: (resource) => ({ ...resource }),
383
+ toUri: (resource) => {
384
+ const uri = `pstdio://extension-resource/${encodeURIComponent(resource.type)}/${encodeURIComponent(resource.id)}`;
385
+ const query = new URLSearchParams;
386
+ if (resource.extensionId)
387
+ query.set("extensionId", resource.extensionId);
388
+ if (resource.projectId)
389
+ query.set("projectId", resource.projectId);
390
+ return query.size ? `${uri}?${query}` : uri;
391
+ },
392
+ fromUri
393
+ };
394
+ // src/extensions/page-url.ts
395
+ var hostExtensionId = "pstdio";
396
+ var pageRefKey = (ref) => `${ref.extensionId ?? ""}:page:${ref.id}`;
397
+ var pageForRef = (pages, ref) => pages.find((page) => pageRefKey(page.ref) === pageRefKey(ref));
398
+ var encodePath = (path) => path.split("/").filter(Boolean).map((segment) => encodeURIComponent(segment)).join("/");
399
+ var routePath = (projectId, page) => {
400
+ const project = `/projects/${encodeURIComponent(projectId)}`;
401
+ const path = encodePath(page.path);
402
+ if (page.ref.extensionId === hostExtensionId)
403
+ return path ? `${project}/${path}` : project;
404
+ if (!page.ref.extensionId)
405
+ throw new Error(`Page "${page.id}" has no extension id`);
406
+ return `${project}/extensions/${encodeURIComponent(page.ref.extensionId)}/${path}`;
407
+ };
408
+ var normalizedSection = (value) => {
409
+ if (!value || typeof value !== "object" || !Array.isArray(value.anchors))
410
+ return;
411
+ const anchors = value.anchors;
412
+ if (anchors.some((anchor) => !anchor || typeof anchor !== "object" || typeof anchor.id !== "string" || typeof anchor.heading !== "string" || anchor.occurrence !== undefined && (!Number.isInteger(anchor.occurrence) || Number(anchor.occurrence) < 0))) {
413
+ return;
414
+ }
415
+ return {
416
+ anchors: anchors.map((anchor) => {
417
+ const value2 = anchor;
418
+ return {
419
+ id: value2.id,
420
+ heading: value2.heading,
421
+ ...value2.occurrence !== undefined ? { occurrence: value2.occurrence } : {}
422
+ };
423
+ })
424
+ };
425
+ };
426
+ var serializeSection = (section) => {
427
+ const normalized = normalizedSection(section);
428
+ if (!normalized)
429
+ throw new Error("Page location has an invalid section");
430
+ return JSON.stringify(normalized);
431
+ };
432
+ var parseSection = (value) => {
433
+ try {
434
+ return normalizedSection(JSON.parse(value));
435
+ } catch {
436
+ return;
437
+ }
438
+ };
439
+ var serializeWorkbenchPageUrl = (input) => {
440
+ const page = pageForRef(input.pages, input.location.page);
441
+ if (!page)
442
+ throw new Error(`Unknown page ref: ${pageRefKey(input.location.page)}`);
443
+ const query = new URLSearchParams;
444
+ if (input.location.resource) {
445
+ query.set("resource", input.resources.toUri(input.resources.normalize(input.location.resource)));
446
+ }
447
+ if (input.location.section)
448
+ query.set("section", serializeSection(input.location.section));
449
+ const encoded = query.toString();
450
+ const path = routePath(input.projectId, page);
451
+ return encoded ? `${path}?${encoded}` : path;
452
+ };
453
+ var decodedSegments = (pathname) => {
454
+ try {
455
+ return pathname.split("/").filter(Boolean).map((segment) => decodeURIComponent(segment));
456
+ } catch {
457
+ return;
458
+ }
459
+ };
460
+ var isWorkbenchProjectUrl = (urlValue, projectId) => {
461
+ try {
462
+ const url = new URL(urlValue, "http://workbench.local");
463
+ const segments = decodedSegments(url.pathname);
464
+ return Boolean(segments && segments[0] === "projects" && segments[1] === projectId);
465
+ } catch {
466
+ return false;
467
+ }
468
+ };
469
+ var pageForRoute = (pages, extensionId, path) => pages.find((page) => page.ref.extensionId === extensionId && page.path === path);
470
+ var parseResource = (uri, resources) => {
471
+ try {
472
+ const resource = resources.fromUri(uri);
473
+ return resource ? resources.normalize(resource) : undefined;
474
+ } catch {
475
+ return;
476
+ }
477
+ };
478
+ var parseWorkbenchPageUrl = (input) => {
479
+ let url;
480
+ try {
481
+ url = new URL(input.url, "http://workbench.local");
482
+ } catch {
483
+ return;
484
+ }
485
+ const segments = decodedSegments(url.pathname);
486
+ if (!segments || segments[0] !== "projects" || segments[1] !== input.projectId)
487
+ return;
488
+ const route = segments.slice(2);
489
+ const extensionRoute = route[0] === "extensions";
490
+ const extensionId = extensionRoute ? route[1] : hostExtensionId;
491
+ const path = (extensionRoute ? route.slice(2) : route).join("/");
492
+ if (!extensionId || extensionRoute && !path)
493
+ return;
494
+ const page = pageForRoute(input.pages, extensionId, path);
495
+ if (!page)
496
+ return;
497
+ const resourceValue = url.searchParams.get("resource");
498
+ const resource = resourceValue ? parseResource(resourceValue, input.resources) : undefined;
499
+ if (resourceValue && !resource)
500
+ return;
501
+ const sectionValue = url.searchParams.get("section");
502
+ const section = sectionValue ? parseSection(sectionValue) : undefined;
503
+ if (sectionValue && !section)
504
+ return;
505
+ return {
506
+ pageId: page.id,
507
+ ...resource ? { resource } : {},
508
+ ...section ? { section } : {}
509
+ };
510
+ };
511
+ var serializePageUrl = (input) => serializeWorkbenchPageUrl({
512
+ projectId: input.projectId,
513
+ location: { page: input.page.ref, resource: input.resource },
514
+ pages: [input.page],
515
+ resources: defaultPageResourceCodec
516
+ });
517
+ var parsePageUrl = (input) => {
518
+ if (!input.url.startsWith("/") || input.url.startsWith("//"))
519
+ return;
520
+ return parseWorkbenchPageUrl({ ...input, resources: defaultPageResourceCodec });
521
+ };
348
522
  // src/extensions/params.ts
349
523
  var params = {
350
524
  text: (options) => ({ type: "text", ...options }),
@@ -459,6 +633,19 @@ var createTerminalSessionBridge = (host) => ({
459
633
  // src/extensions/webview-capabilities.ts
460
634
  var artifactMountId = (mount) => typeof mount === "string" ? mount : mount.id;
461
635
  var artifactsRead = (mount) => `artifacts.read:${artifactMountId(mount)}`;
636
+ // src/extensions/webview-events.ts
637
+ var EXTENSION_EVENTS_SCOPE = "extension.events";
638
+ var createWebviewEventsClient = (host, extensionId) => ({
639
+ subscribe(event, listener) {
640
+ const id = resolveEventReferenceId(event, extensionId);
641
+ return host.onEvent(EXTENSION_EVENTS_SCOPE, (payload) => {
642
+ const notification = payload;
643
+ if (notification.type === "reset" || notification.type === "changed" && notification.id === id)
644
+ listener();
645
+ });
646
+ }
647
+ });
648
+
462
649
  // src/extensions/webview-client.ts
463
650
  var createWebviewClient = (host, options) => {
464
651
  const extensionId = options?.extensionId ?? host.extensionId;
@@ -495,7 +682,8 @@ var createWebviewClient = (host, options) => {
495
682
  readText: (mount, path) => host.call("artifacts.read", { op: "readText", mount: artifactMountId(mount), path }),
496
683
  imageUrl: (mount, path) => host.call("artifacts.read", { op: "imageUrl", mount: artifactMountId(mount), path })
497
684
  };
498
- return { artifacts, commands, settings };
685
+ const events = createWebviewEventsClient(host, extensionId);
686
+ return { artifacts, commands, events, settings };
499
687
  };
500
688
  // src/extensions/when.ts
501
689
  var matchesResourceWhen = (when, resourceType) => {
@@ -520,17 +708,23 @@ export {
520
708
  unwrapCommandOutcome,
521
709
  sessionSlots,
522
710
  sessionEvents,
711
+ serializeWorkbenchPageUrl,
712
+ serializePageUrl,
523
713
  resourceMenuSlotRef2 as resourceMenuSlotRef,
524
714
  resourceKey,
715
+ resolveEventReferenceId,
525
716
  qualifyRef,
526
717
  projectSlots,
527
718
  projectEvents,
719
+ parseWorkbenchPageUrl,
720
+ parsePageUrl,
528
721
  params,
529
722
  packageAsset,
530
723
  matchesResourceWhen,
531
724
  localContributionIdPattern,
532
725
  localContributionIdGrammar,
533
726
  l10n,
727
+ isWorkbenchProjectUrl,
534
728
  isValidLocalContributionId,
535
729
  isLocalizedString,
536
730
  gitEvents,
@@ -569,6 +763,7 @@ export {
569
763
  defineCommand,
570
764
  defineArtifactMount,
571
765
  defineActivityItem,
766
+ defaultPageResourceCodec,
572
767
  createWebviewClient,
573
768
  createTerminalSessionBridge,
574
769
  commandRef,
@@ -580,6 +775,7 @@ export {
580
775
  WEBVIEW_HOST_CAPABILITIES,
581
776
  WEBVIEW_DECLARABLE_CAPABILITIES,
582
777
  SDK_VERSION,
778
+ EXTENSION_EVENTS_SCOPE,
583
779
  EXTENSION_API_VERSION,
584
780
  ALWAYS_AVAILABLE_WEBVIEW_CAPABILITIES
585
781
  };
@@ -680,6 +680,9 @@ export declare interface DateControl extends BaseControl {
680
680
  max?: string;
681
681
  }
682
682
 
683
+ /** Resource URI conversion belongs to route and persistence adapters. */
684
+ export declare const defaultPageResourceCodec: PageResourceCodec;
685
+
683
686
  export declare const defineActivityItem: <Definition extends Omit<ActivityItemContribution, "ref">>(definition: Definition) => Definition & ContributionDefinition<"activity-item">;
684
687
 
685
688
  export declare const defineArtifactMount: <Definition extends Omit<ArtifactMountContribution, "ref">>(definition: Definition) => Definition & ContributionDefinition<"artifact-mount">;
@@ -815,7 +818,7 @@ export declare interface EventRef<TPayload extends Struct = Struct> {
815
818
  /** Build a typed event reference from separate ownership and local identity. */
816
819
  export declare const eventRef: <TPayload extends Struct = Struct>(input: ExternalRefInput) => EventRef<TPayload>;
817
820
 
818
- declare type ExactOptions<Definition, Contract> = unknown extends Contract ? Definition : [Contract] extends [Definition] ? Definition : Contract extends unknown ? Definition extends Contract ? Contract extends EventRef ? Definition : Definition extends (...args: never[]) => unknown ? Definition : Definition extends readonly unknown[] ? Contract extends readonly (infer Item)[] ? {
821
+ declare type ExactOptions<Definition, Contract> = unknown extends Contract ? Definition : [Contract] extends [Definition] ? Definition : Contract extends unknown ? Definition extends Contract ? Contract extends EventRef | CommandRef ? Definition : Definition extends (...args: never[]) => unknown ? Definition : Definition extends readonly unknown[] ? Contract extends readonly (infer Item)[] ? {
819
822
  [Index in keyof Definition]: ExactOptions<Definition[Index], Item>;
820
823
  } : never : Definition extends object ? {
821
824
  [Key in keyof Definition]: Key extends keyof Contract ? ExactOptions<Definition[Key], Contract[Key]> : never;
@@ -824,6 +827,8 @@ declare type ExactOptions<Definition, Contract> = unknown extends Contract ? Def
824
827
  /** Current host extension API version. `engines.pstdio` in package.json is a semver range checked against this. */
825
828
  export declare const EXTENSION_API_VERSION = "1.0.0-alpha.10";
826
829
 
830
+ export declare const EXTENSION_EVENTS_SCOPE = "extension.events";
831
+
827
832
  export declare interface ExtensionActivityApi {
828
833
  record(input: {
829
834
  message: string;
@@ -1475,6 +1480,8 @@ export declare const isLocalizedString: (value: unknown) => value is LocalizedSt
1475
1480
 
1476
1481
  export declare const isValidLocalContributionId: (id: string) => boolean;
1477
1482
 
1483
+ export declare const isWorkbenchProjectUrl: (urlValue: string, projectId: string) => boolean;
1484
+
1478
1485
  export declare type JsonObject = {
1479
1486
  [key: string]: JsonValue;
1480
1487
  };
@@ -2033,6 +2040,12 @@ declare type PagePanelRefs<Slots extends readonly PageSlot[]> = {
2033
2040
 
2034
2041
  export declare type PageRef = ContributionRef<"page">;
2035
2042
 
2043
+ declare interface PageResourceCodec {
2044
+ normalize(resource: ResourceRef): ResourceRef;
2045
+ toUri(resource: ResourceRef): string;
2046
+ fromUri(uri: string): ResourceRef | undefined;
2047
+ }
2048
+
2036
2049
  /** A page-owned panel. Main presentation and routed context belong to the page. */
2037
2050
  export declare interface PageSlot extends PlacementPresentation {
2038
2051
  readonly id: string;
@@ -2054,6 +2067,12 @@ export declare type PageSlotRegion = ExtensionPanelRegion;
2054
2067
 
2055
2068
  export declare type PageSlotRole = "primary" | "auxiliary";
2056
2069
 
2070
+ export declare interface PageUrlDefinition {
2071
+ id: string;
2072
+ ref: PageRef;
2073
+ path: string;
2074
+ }
2075
+
2057
2076
  export declare type PanelRef = PlacementRef | PageSlotRef;
2058
2077
 
2059
2078
  declare type ParamBase<TValue, TRequired extends boolean | undefined = boolean | undefined> = {
@@ -2139,6 +2158,26 @@ export declare type ParamType = "text" | "longtext" | "markdown" | "number" | "b
2139
2158
 
2140
2159
  export declare type ParamValue<TDescriptor extends ParamDescriptor> = TDescriptor extends ParamDescriptor<infer V> ? V : never;
2141
2160
 
2161
+ export declare interface ParsedWorkbenchPageUrl {
2162
+ pageId: string;
2163
+ resource?: ResourceRef;
2164
+ section?: FileRendererSectionTarget;
2165
+ }
2166
+
2167
+ /** Resolve a dashboard URL against the caller's declared pages and project. */
2168
+ export declare const parsePageUrl: (input: {
2169
+ url: string;
2170
+ projectId: string;
2171
+ pages: readonly PageUrlDefinition[];
2172
+ }) => ParsedWorkbenchPageUrl | undefined;
2173
+
2174
+ export declare const parseWorkbenchPageUrl: (input: {
2175
+ url: string;
2176
+ projectId: string;
2177
+ pages: readonly PageUrlDefinition[];
2178
+ resources: PageResourceCodec;
2179
+ }) => ParsedWorkbenchPageUrl | undefined;
2180
+
2142
2181
  export declare type PatchPart = {
2143
2182
  type: "patch";
2144
2183
  hash?: string;
@@ -2400,6 +2439,9 @@ declare type RequiredParamKeys<TSchema extends ParamObjectSchema> = {
2400
2439
  } ? K : never;
2401
2440
  }[keyof TSchema];
2402
2441
 
2442
+ /** Resolve an event ref using the same ownership rules as commands and hooks. */
2443
+ export declare const resolveEventReferenceId: (ref: RendererEventReference, ownerExtensionId?: string) => string;
2444
+
2403
2445
  export declare interface ResourceAnchor extends ResourceRef {
2404
2446
  role?: ResourceRole;
2405
2447
  }
@@ -2583,6 +2625,20 @@ export declare interface SerializedError {
2583
2625
  cause?: JsonValue;
2584
2626
  }
2585
2627
 
2628
+ /** Serialize a project page using the same resource encoding as the dashboard. */
2629
+ export declare const serializePageUrl: (input: {
2630
+ projectId: string;
2631
+ page: PageUrlDefinition;
2632
+ resource?: ResourceRef;
2633
+ }) => string;
2634
+
2635
+ export declare const serializeWorkbenchPageUrl: (input: {
2636
+ projectId: string;
2637
+ location: PageLocation;
2638
+ pages: readonly PageUrlDefinition[];
2639
+ resources: PageResourceCodec;
2640
+ }) => string;
2641
+
2586
2642
  declare type SessionAttachmentRef = z.infer<typeof sessionAttachmentRefSchema>;
2587
2643
 
2588
2644
  declare const sessionAttachmentRefSchema: z.ZodObject<{
@@ -3221,6 +3277,7 @@ export declare type WebviewCapabilityDeclaration = WebviewDeclarableCapability |
3221
3277
  export declare type WebviewClient<TCommands, TSettings = undefined> = {
3222
3278
  artifacts: WebviewArtifactsClient;
3223
3279
  commands: WebviewCommandsClient<TCommands>;
3280
+ events: WebviewEventsClient;
3224
3281
  settings: WebviewSettingsClient<ClientSettingsMap<TSettings>>;
3225
3282
  };
3226
3283
 
@@ -3249,6 +3306,18 @@ export declare interface WebviewContribution {
3249
3306
 
3250
3307
  export declare type WebviewDeclarableCapability = (typeof WEBVIEW_DECLARABLE_CAPABILITIES)[number];
3251
3308
 
3309
+ export declare interface WebviewEventsClient {
3310
+ /** Refetch on a matching event or host sync reconnect. Returns the unsubscribe function. */
3311
+ subscribe(event: RendererEventReference, listener: () => void): () => void;
3312
+ }
3313
+
3314
+ export declare type WebviewExtensionEvent = {
3315
+ type: "changed";
3316
+ id: string;
3317
+ } | {
3318
+ type: "reset";
3319
+ };
3320
+
3252
3321
  export declare interface WebviewExtensionSettingKeyParams {
3253
3322
  key: string;
3254
3323
  }
package/dist/hooks.d.ts CHANGED
@@ -1465,6 +1465,7 @@ declare type SseEvent = {
1465
1465
  };
1466
1466
 
1467
1467
  declare type StartSyncInput = SyncWriterProvider & {
1468
+ /** Called after the initial snapshot, or when a cursor-based connection resumes. */
1468
1469
  onConnected?: () => void;
1469
1470
  onDisconnected?: () => void;
1470
1471
  onConnectionLost?: () => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pstdio/sdk",
3
- "version": "0.22.1",
3
+ "version": "0.23.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/pufflyai/prompt-studio"