@pstdio/sdk 0.36.1 → 0.37.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
@@ -15,12 +15,14 @@ bun add @pstdio/sdk
15
15
  | `@pstdio/sdk/resources` | Product resource types |
16
16
  | `@pstdio/sdk/prompts` | Prompt rendering |
17
17
  | `@pstdio/sdk/hooks` | Hook API contracts |
18
+ | `@pstdio/sdk/data` | Draft layout, frontmatter, and ID/name resolution helpers |
19
+ | `@pstdio/sdk/testing` | Command contexts and in-memory adapters for extension tests |
18
20
 
19
21
  Native extension entries work without React. The React entry requires its declared React and TanStack Query peers. Public declarations include their private contract dependencies and support `skipLibCheck: false` outside the repository.
20
22
 
21
23
  ## Build an extension
22
24
 
23
- Start with the [workbench cookbook](https://github.com/pufflyai/prompt-studio/blob/main/.pstdio/docs/extensions/cookbook.md) and [Extension Lab](https://github.com/pufflyai/prompt-studio/blob/main/extensions/extension-lab/README.md). Existing examples cover saved edits, inspectors, shared panels, custom modes, provider refs, and webview cleanup.
25
+ Start with the [workbench cookbook](https://github.com/pufflyai/prompt-studio/blob/main/documentation/guides/extensions/0002-workbench-cookbook.md) and [Extension Lab](https://github.com/pufflyai/prompt-studio/blob/main/extensions/extension-lab/README.md). Existing examples cover saved edits, inspectors, shared panels, custom modes, provider refs, and webview cleanup.
24
26
 
25
27
  Keep package identity in `package.json`. Export `defineExtension(...)` from the manifest's `main`. Install through `pst extensions dev <path>` from a linked project. The same workflow watches native TypeScript, contribution declarations, and webview assets.
26
28
 
@@ -94,7 +96,7 @@ Host authors should use the [workbench guide](https://github.com/pufflyai/prompt
94
96
 
95
97
  ## Workspace contracts
96
98
 
97
- The alpha.13 host opens one folder per project and uses workspace APIs for execution and files.
99
+ The host opens one folder per project and uses workspace APIs for execution and files.
98
100
  Use `ctx.projectFiles` for the project's default workspace and `ctx.workspaceFiles`
99
101
  for the invocation's working files. Project file operations check the current workspace
100
102
  readiness and file capabilities. Remote workspaces never fall back to local files.
@@ -114,8 +116,8 @@ Directory creation accepts one child name under an existing parent.
114
116
  Webviews can set `workspaceId` in `createWebviewClient(host, { workspaceId })`
115
117
  to run commands in that workspace. The host validates project ownership.
116
118
 
117
- Extensions that work with both host contracts can declare the exact versions
118
- `1.0.0-alpha.12 || 1.0.0-alpha.13` in `engines.pstdio`.
119
+ The current host API version is `1.0.0-alpha.14`. Extensions that also work with the
120
+ previous contract can declare `1.0.0-alpha.13 || 1.0.0-alpha.14` in `engines.pstdio`.
119
121
  General version ranges and wildcards remain unsupported.
120
122
  The compatible extension release must precede the host cutover.
121
- See [the staged release ADR](../../.pstdio/docs/adrs/0030-temporary-workspace-contract-release-bridge.md).
123
+ See [the staged release ADR](../../documentation/adrs/0030-temporary-workspace-contract-release-bridge.md).
package/dist/api/index.js CHANGED
@@ -3087,6 +3087,9 @@ function handlePipeResult(left, next, ctx) {
3087
3087
  }
3088
3088
  return next._zod.run({ value: left.value, issues: left.issues }, ctx);
3089
3089
  }
3090
+ var $ZodPreprocess = /* @__PURE__ */ $constructor("$ZodPreprocess", (inst, def) => {
3091
+ $ZodPipe.init(inst, def);
3092
+ });
3090
3093
  var $ZodReadonly = /* @__PURE__ */ $constructor("$ZodReadonly", (inst, def) => {
3091
3094
  $ZodType.init(inst, def);
3092
3095
  defineLazyInternal(inst, "propValues", (zod) => zod.def.innerType._zod.propValues);
@@ -6122,6 +6125,10 @@ function pipe(in_, out) {
6122
6125
  out
6123
6126
  });
6124
6127
  }
6128
+ var ZodPreprocess = /* @__PURE__ */ $constructor("ZodPreprocess", (inst, def) => {
6129
+ ZodPipe.init(inst, def);
6130
+ $ZodPreprocess.init(inst, def);
6131
+ });
6125
6132
  var ZodReadonly = /* @__PURE__ */ $constructor("ZodReadonly", (inst, def) => {
6126
6133
  $ZodReadonly.init(inst, def);
6127
6134
  ZodType.init(inst, def);
@@ -6157,12 +6164,41 @@ function refine(fn, _params = {}) {
6157
6164
  function superRefine(fn, params) {
6158
6165
  return _superRefine(fn, params);
6159
6166
  }
6167
+ function _instanceof(cls, params = {}) {
6168
+ const inst = new ZodCustom({
6169
+ type: "custom",
6170
+ check: "custom",
6171
+ fn: (data) => data instanceof cls,
6172
+ abort: true,
6173
+ ...normalizeParams(params)
6174
+ });
6175
+ inst._zod.bag.Class = cls;
6176
+ inst._zod.check = (payload) => {
6177
+ if (!(payload.value instanceof cls)) {
6178
+ payload.issues.push({
6179
+ code: "invalid_type",
6180
+ expected: cls.name,
6181
+ input: payload.value,
6182
+ inst,
6183
+ path: [...inst._zod.def.path ?? []]
6184
+ });
6185
+ }
6186
+ };
6187
+ return inst;
6188
+ }
6160
6189
  function json(params) {
6161
6190
  const jsonSchema = lazy(() => {
6162
6191
  return union([string2(params), number2(), boolean2(), _null3(), array(jsonSchema), record(string2(), jsonSchema)]);
6163
6192
  });
6164
6193
  return jsonSchema;
6165
6194
  }
6195
+ function preprocess(fn, schema) {
6196
+ return new ZodPreprocess({
6197
+ type: "pipe",
6198
+ in: transform(fn),
6199
+ out: schema
6200
+ });
6201
+ }
6166
6202
  // ../../node_modules/.bun/zod@4.5.4/node_modules/zod/v4/classic/coerce.js
6167
6203
  var exports_coerce = {};
6168
6204
  __export(exports_coerce, {
@@ -7314,7 +7350,8 @@ var workbenchExtensionNavigationTreeRecordSchema = object({
7314
7350
  extensionId: string2(),
7315
7351
  owner: union([modeRefSchema2, pageRefSchema2]),
7316
7352
  slot: _enum(["header", "content", "footer"]),
7317
- view: viewRefSchema2
7353
+ view: viewRefSchema2,
7354
+ resourceScope: _enum(["project", "selection"]).optional()
7318
7355
  });
7319
7356
  var workbenchExtensionResourceKindRecordSchema = object({
7320
7357
  id: string2(),
@@ -7541,10 +7578,6 @@ var setProjectExtensionEnabledRequestSchema = object({
7541
7578
  var setExtensionAutomationEnabledRequestSchema = object({
7542
7579
  enabled: boolean2()
7543
7580
  });
7544
- var attemptExtensionFixResponseSchema = object({
7545
- sessionId: string2(),
7546
- title: string2()
7547
- });
7548
7581
  var upgradeProjectExtensionResponseSchema = object({
7549
7582
  changed: boolean2(),
7550
7583
  extension: projectExtensionInstanceSchema
@@ -7552,6 +7585,13 @@ var upgradeProjectExtensionResponseSchema = object({
7552
7585
  var installMarketplaceExtensionResponseSchema = object({
7553
7586
  extension: projectExtensionInstanceSchema
7554
7587
  });
7588
+ var addLocalExtensionFolderRequestSchema = object({
7589
+ name: string2().min(1),
7590
+ files: preprocess((value) => Array.isArray(value) ? value : [value], array(_instanceof(File).meta({ type: "string", format: "binary" })).min(1))
7591
+ });
7592
+ var addLocalExtensionFolderResponseSchema = object({
7593
+ extension: projectExtensionInstanceSchema
7594
+ });
7555
7595
  var setupProjectExtensionResponseSchema = object({
7556
7596
  extensionId: string2(),
7557
7597
  name: string2(),
@@ -7876,10 +7916,11 @@ var packageAsset = (path, baseUrl) => ({
7876
7916
  baseUrl
7877
7917
  });
7878
7918
  // ../pstdio-api-contracts/src/extension-kernel/types/extension.ts
7879
- var EXTENSION_API_VERSION = "1.0.0-alpha.13";
7919
+ var EXTENSION_API_VERSION = "1.0.0-alpha.14";
7880
7920
  // ../pstdio-api-contracts/src/extension-kernel/types/webview-capabilities.ts
7881
7921
  var WEBVIEW_HOST_CAPABILITY_VERSION = 1;
7882
7922
  var WEBVIEW_DECLARABLE_CAPABILITIES = [
7923
+ "clipboard.write",
7883
7924
  "commands.execute",
7884
7925
  "navigation.open",
7885
7926
  "placement.close",
@@ -7901,7 +7942,7 @@ var WEBVIEW_DECLARABLE_CAPABILITIES = [
7901
7942
  var WEBVIEW_SCOPED_DECLARABLE_CAPABILITIES = ["artifacts.read"];
7902
7943
  var ALWAYS_AVAILABLE_WEBVIEW_CAPABILITIES = ["host.dispatchKeyboardEvent"];
7903
7944
  var WEBVIEW_HOST_CAPABILITIES = [
7904
- ...WEBVIEW_DECLARABLE_CAPABILITIES,
7945
+ ...WEBVIEW_DECLARABLE_CAPABILITIES.filter((capability) => capability !== "clipboard.write"),
7905
7946
  ...WEBVIEW_SCOPED_DECLARABLE_CAPABILITIES,
7906
7947
  ...ALWAYS_AVAILABLE_WEBVIEW_CAPABILITIES
7907
7948
  ];
@@ -7969,17 +8010,7 @@ var historyTurnEvidence = (known, native, prompt, body) => {
7969
8010
  return (turn) => keys.get(turn);
7970
8011
  };
7971
8012
 
7972
- // ../pstdio-api-contracts/src/history-reconciliation.ts
7973
- class HistoryConflict extends Error {
7974
- }
7975
- var submittedPrompt = (message) => message.parts.filter((part) => part.type === "text").map((part) => part.text).join(`
7976
- `).replace(/\n\n<session-attachments>[\s\S]*<\/session-attachments>\s*$/, "").trim();
7977
- var historyValueKey = (value) => JSON.stringify(value, (_key, item) => {
7978
- if (!item || typeof item !== "object" || Array.isArray(item))
7979
- return item;
7980
- return Object.fromEntries(Object.entries(item).sort(([a], [b]) => a.localeCompare(b)));
7981
- });
7982
- var historyMessageKey = (message) => historyValueKey([message.role, message.parts]);
8013
+ // ../pstdio-api-contracts/src/ordered-history-merge.ts
7983
8014
  var positions = (items, key) => {
7984
8015
  const result = new Map;
7985
8016
  items.forEach((item, index) => {
@@ -7990,24 +8021,53 @@ var positions = (items, key) => {
7990
8021
  });
7991
8022
  return result;
7992
8023
  };
7993
- var mergeOrderedHistory = (known, native, key, merge, refineKey) => {
8024
+ var orderedAnchors = (anchors) => {
8025
+ const tails = [];
8026
+ const previous = [];
8027
+ anchors.forEach(([, native], index) => {
8028
+ let low = 0;
8029
+ let high = tails.length;
8030
+ while (low < high) {
8031
+ const middle = low + high >> 1;
8032
+ if (anchors[tails[middle]][1] < native)
8033
+ low = middle + 1;
8034
+ else
8035
+ high = middle;
8036
+ }
8037
+ previous[index] = low > 0 ? tails[low - 1] : -1;
8038
+ tails[low] = index;
8039
+ });
8040
+ const kept = [];
8041
+ for (let index = tails.at(-1) ?? -1;index >= 0; index = previous[index])
8042
+ kept.unshift(anchors[index]);
8043
+ return kept;
8044
+ };
8045
+ var newerThanSaved = (known, native, options) => {
8046
+ const times = options.time ? known.map(options.time).filter((value) => value !== undefined) : [];
8047
+ if (!times.length)
8048
+ return [];
8049
+ const savedUntil = Math.max(...times);
8050
+ return native.filter((item) => (options.time?.(item) ?? savedUntil) > savedUntil);
8051
+ };
8052
+ var mergeOrderedHistory = (known, native, options, trailing = true) => {
8053
+ const { key, merge, refineKey, covered } = options;
8054
+ const missing = native.filter((item) => !covered?.(item));
7994
8055
  if (!known.length)
7995
- return native;
8056
+ return missing;
7996
8057
  if (!native.length)
7997
8058
  return known;
7998
8059
  const knownPositions = positions(known, key);
7999
8060
  const nativePositions = positions(native, key);
8000
- const anchors = [];
8061
+ const found = [];
8001
8062
  for (const [value, indices] of knownPositions) {
8002
8063
  const other = nativePositions.get(value);
8003
8064
  if (indices.length === 1 && other?.length === 1)
8004
- anchors.push([indices[0], other[0]]);
8065
+ found.push([indices[0], other[0]]);
8005
8066
  }
8067
+ const anchors = orderedAnchors(found.sort((a, b) => a[0] - b[0]));
8006
8068
  if (!anchors.length) {
8007
- if (refineKey) {
8008
- const refined = mergeOrderedHistory(known, native, refineKey(known, native), merge);
8009
- return refined;
8010
- }
8069
+ if (refineKey)
8070
+ return mergeOrderedHistory(known, native, { ...options, key: refineKey(known, native), refineKey: undefined }, trailing);
8011
8071
  const paired = Math.min(known.length, native.length);
8012
8072
  if (known.slice(0, paired).every((item, index) => key(item) === key(native[index]))) {
8013
8073
  return [
@@ -8016,22 +8076,35 @@ var mergeOrderedHistory = (known, native, key, merge, refineKey) => {
8016
8076
  ...native.slice(paired)
8017
8077
  ];
8018
8078
  }
8019
- throw new HistoryConflict("ambiguous_interval");
8079
+ return trailing ? [...known, ...newerThanSaved(known, missing, options)] : known;
8020
8080
  }
8081
+ const kept = new Set(anchors.map(([, index]) => index));
8082
+ const reordered = new Set(found.filter(([, index]) => !kept.has(index)).map(([, index]) => native[index]));
8083
+ const nativeSpan = (start, end) => native.slice(start, end).filter((item) => !reordered.has(item));
8021
8084
  let left = 0;
8022
8085
  let right = 0;
8023
8086
  const result = [];
8024
8087
  for (const [a, b] of anchors) {
8025
- if (b < right)
8026
- throw new HistoryConflict("conflicting_order");
8027
- result.push(...mergeOrderedHistory(known.slice(left, a), native.slice(right, b), key, merge, refineKey));
8088
+ result.push(...mergeOrderedHistory(known.slice(left, a), nativeSpan(right, b), options, false));
8028
8089
  result.push(merge(known[a], native[b]));
8029
8090
  left = a + 1;
8030
8091
  right = b + 1;
8031
8092
  }
8032
- result.push(...mergeOrderedHistory(known.slice(left), native.slice(right), key, merge, refineKey));
8093
+ result.push(...mergeOrderedHistory(known.slice(left), nativeSpan(right), options, trailing));
8033
8094
  return result;
8034
8095
  };
8096
+
8097
+ // ../pstdio-api-contracts/src/history-reconciliation.ts
8098
+ class HistoryConflict extends Error {
8099
+ }
8100
+ var submittedPrompt = (message) => message.parts.filter((part) => part.type === "text").map((part) => part.text).join(`
8101
+ `).replace(/\n\n<session-attachments>[\s\S]*<\/session-attachments>\s*$/, "").trim();
8102
+ var historyValueKey = (value) => JSON.stringify(value, (_key, item) => {
8103
+ if (!item || typeof item !== "object" || Array.isArray(item))
8104
+ return item;
8105
+ return Object.fromEntries(Object.entries(item).sort(([a], [b]) => a.localeCompare(b)));
8106
+ });
8107
+ var historyMessageKey = (message) => historyValueKey([message.role, message.parts]);
8035
8108
  var splitHistoryTurns = (messages) => {
8036
8109
  const turns = [];
8037
8110
  for (const message of messages) {
@@ -8069,7 +8142,14 @@ var reconcileMessageHistory = (input, projection = {}) => {
8069
8142
  const mergeTurn = (known, native) => {
8070
8143
  const startsWithUser = known[0]?.role === "user" && native[0]?.role === "user";
8071
8144
  const body = (turn) => combineTextRuns(turn.slice(startsWithUser ? 1 : 0).filter((message) => !generated(message)));
8072
- const messages = mergeOrderedHistory(body(known), body(native), key, merge);
8145
+ const shown = known.flatMap((message) => message.parts.flatMap((part) => part.type === "text" ? [part.text] : []));
8146
+ const saved = shown.join("");
8147
+ const messages = mergeOrderedHistory(body(known), body(native), {
8148
+ key,
8149
+ merge,
8150
+ time: (message) => message.createdAt,
8151
+ covered: (message) => message.parts.length > 0 && message.parts.every((part) => part.type === "text" && saved.includes(part.text))
8152
+ });
8073
8153
  const metadata = [...native.filter(generated)];
8074
8154
  const counts = new Map;
8075
8155
  metadata.forEach((message) => {
@@ -8087,7 +8167,12 @@ var reconcileMessageHistory = (input, projection = {}) => {
8087
8167
  };
8088
8168
  try {
8089
8169
  const prompt = (turn) => turn[0]?.role === "user" ? `user:${submittedPrompt(turn[0])}` : "prefix";
8090
- const turns = mergeOrderedHistory(splitHistoryTurns(input.knownMessages), splitHistoryTurns(input.nativeMessages), prompt, mergeTurn, (known, native) => historyTurnEvidence(known, native, prompt, (turn) => combineTextRuns(turn.slice(1).filter((message) => !generated(message))).map(key)));
8170
+ const turns = mergeOrderedHistory(splitHistoryTurns(input.knownMessages), splitHistoryTurns(input.nativeMessages), {
8171
+ key: prompt,
8172
+ merge: mergeTurn,
8173
+ refineKey: (known, native) => historyTurnEvidence(known, native, prompt, (turn) => combineTextRuns(turn.slice(1).filter((message) => !generated(message))).map(key)),
8174
+ time: (turn) => turn[0]?.createdAt
8175
+ });
8091
8176
  const messages = turns.flat().map((message, index) => message.index === undefined ? message : { ...message, index });
8092
8177
  return { kind: "recovered", messages };
8093
8178
  } catch (error) {
@@ -8352,10 +8437,6 @@ var followUpDecisionSchema = union([
8352
8437
  var followUpResponseSchema = sessionSchema.extend({
8353
8438
  follow_up: followUpDecisionSchema
8354
8439
  });
8355
- var sessionHistoryIssueSchema = object({
8356
- code: _enum(["reconciliation_conflict", "checkpoint_unreadable", "native_unavailable"]),
8357
- category: string2()
8358
- });
8359
8440
  var sessionQueuedMessagesResponseSchema = object({ messages: array(sessionMessageSchema) });
8360
8441
  var sessionConversationSourcesSchema = object({
8361
8442
  checkpoint: array(sessionMessageSchema).nullable(),
@@ -8364,7 +8445,6 @@ var sessionConversationSourcesSchema = object({
8364
8445
  nativeError: string2().nullable()
8365
8446
  });
8366
8447
  var sessionConversationResponseSchema = object({
8367
- historyIssue: sessionHistoryIssueSchema.optional(),
8368
8448
  session: sessionSchema,
8369
8449
  messages: array(sessionMessageSchema)
8370
8450
  });
package/dist/api.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { $ as WorkbenchExtensionMetadata, $a as FollowUpInput, At as TerminalHostEvent, B as ConfigureExtensionConnectionInput, C as ExtensionSettingsPanelRecord, Co as UpdateNotificationInput, D as ExtensionCommandPaletteResourceRecord, E as ExtensionKeybindingRecord, F as ProjectExtensionInstance, G as LocalizableString, H as ListExtensionConnectionsResponse, I as UpgradeProjectExtensionResponse, J as ExtensionMenuContribution, K as ExtensionCommandPaletteContribution, L as CommandExecuteRequest, M as InstallMarketplaceExtensionResponse, Mt as TerminalSessionRequest, N as ListProjectExtensionsResponse, Nt as TerminalSessionResult, O as WorkbenchExtensionCommandPaletteResourceRecord, P as MarketplaceExtension, Q as WorkbenchExtensionHarnessRecord, Qa as CreateSessionInput, R as CommandExecuteResponse, S as ExtensionSettingValueRecord, So as NotificationStatus, T as UpdateExtensionSettingRequest, U as ExtensionDiagnostic, V as ExtensionConnectionRecord, W as ExtensionRecord, X as ListExtensionAppearanceResponse, Xa as UpdateSkillInput, Xu as ResourceRef, Y as WorkbenchExtensionAutomationRecord, Z as ListExtensionCommandsResponse, Za as ApprovalInput, _ as CreateProjectInput, _o as NotificationAction, a as RemoveWorktreeResponse$1, at as AutomationRunStatus, bo as NotificationOrigin, c as WorkspaceFileContent$1, co as SessionConversationResponse, ct as IssueAutomationTokenInput, do as SessionQueuedMessagesResponse, dt as ListAutomationTokensResponse, et as WorkbenchExtensionViewBody, f as WorkspaceProviderDescriptor, g as sessionAttachmentMimeTypesByExtension, go as Notification, h as UpdateSettingsInput, ho as ListNotificationsResponse, i as ListWorkspaceFilesInput$1, io as ResolveSessionIdResponse, it as AutomationRunEvent, jt as TerminalSessionOperation, k as AttemptExtensionFixResponse, l as WorkspaceFileEntry$1, lo as SessionConversationSources, lt as IssueAutomationTokenResponse, m as Settings, mo as ListNotificationsQuery, nt as AutomationRun, o as RenameWorkspaceInput$1, oo as SessionAttachment, ot as AutomationTokenRecord, p as WriteWorkspaceFileInput$1, po as CreateNotificationInput, q as ExtensionCommandRecord, ro as ResolveSessionIdInput, rt as AutomationRunError, so as SessionAttachmentRef, st as CreateAutomationRunInput, t as CreateWorkspaceInput$1, tt as WorkbenchExtensionViewRecord, u as WorkspaceFilesResponse$1, uo as SessionHistoryIssue, ut as ListAutomationRunEventsResponse, vo as NotificationActorType, w as ListExtensionSettingsResponse, x as ExtensionSettingDefinitionRecord, xo as NotificationPriority, y as UpdateProjectInput, yo as NotificationKind } from "./index-CJUDgZmO.js";
2
- import "./sessions-CPa_dPkI.js";
3
- import "./skills-CPa_dPkI.js";
1
+ import { $ as WorkbenchExtensionMetadata, $a as FollowUpInput, At as TerminalHostEvent, B as ConfigureExtensionConnectionInput, C as ExtensionSettingsPanelRecord, D as ExtensionCommandPaletteResourceRecord, E as ExtensionKeybindingRecord, F as ProjectExtensionInstance, G as LocalizableString, H as ListExtensionConnectionsResponse, I as UpgradeProjectExtensionResponse, J as ExtensionMenuContribution, K as ExtensionCommandPaletteContribution, L as CommandExecuteRequest, M as InstallMarketplaceExtensionResponse, Mt as TerminalSessionRequest, N as ListProjectExtensionsResponse, Nt as TerminalSessionResult, O as WorkbenchExtensionCommandPaletteResourceRecord, P as MarketplaceExtension, Q as WorkbenchExtensionHarnessRecord, Qa as CreateSessionInput, R as CommandExecuteResponse, S as ExtensionSettingValueRecord, So as UpdateNotificationInput, T as UpdateExtensionSettingRequest, U as ExtensionDiagnostic, V as ExtensionConnectionRecord, W as ExtensionRecord, X as ListExtensionAppearanceResponse, Xa as UpdateSkillInput, Y as WorkbenchExtensionAutomationRecord, Yu as ResourceRef, Z as ListExtensionCommandsResponse, Za as ApprovalInput, _ as CreateProjectInput, _o as NotificationActorType, a as RemoveWorktreeResponse$1, at as AutomationRunStatus, bo as NotificationPriority, c as WorkspaceFileContent$1, co as SessionConversationResponse, ct as IssueAutomationTokenInput, dt as ListAutomationTokensResponse, et as WorkbenchExtensionViewBody, f as WorkspaceProviderDescriptor, fo as CreateNotificationInput, g as sessionAttachmentMimeTypesByExtension, go as NotificationAction, h as UpdateSettingsInput, ho as Notification, i as ListWorkspaceFilesInput$1, io as ResolveSessionIdResponse, it as AutomationRunEvent, jt as TerminalSessionOperation, k as AddLocalExtensionFolderResponse, l as WorkspaceFileEntry$1, lo as SessionConversationSources, lt as IssueAutomationTokenResponse, m as Settings, mo as ListNotificationsResponse, nt as AutomationRun, o as RenameWorkspaceInput$1, oo as SessionAttachment, ot as AutomationTokenRecord, p as WriteWorkspaceFileInput$1, po as ListNotificationsQuery, q as ExtensionCommandRecord, ro as ResolveSessionIdInput, rt as AutomationRunError, so as SessionAttachmentRef, st as CreateAutomationRunInput, t as CreateWorkspaceInput$1, tt as WorkbenchExtensionViewRecord, u as WorkspaceFilesResponse$1, uo as SessionQueuedMessagesResponse, ut as ListAutomationRunEventsResponse, vo as NotificationKind, w as ListExtensionSettingsResponse, x as ExtensionSettingDefinitionRecord, xo as NotificationStatus, y as UpdateProjectInput, yo as NotificationOrigin } from "./index-CnOTGr_I.js";
2
+ import "./sessions-CkEvTavd.js";
3
+ import "./skills-CkEvTavd.js";
4
4
  //#region src/api/workspaces.d.ts
5
5
  type CreateWorkspaceInput = CreateWorkspaceInput$1;
6
6
  type RemoveWorktreeResponse = RemoveWorktreeResponse$1;
@@ -11,5 +11,5 @@ type WorkspaceFileEntry = WorkspaceFileEntry$1;
11
11
  type WorkspaceFilesResponse = WorkspaceFilesResponse$1;
12
12
  type WriteWorkspaceFileInput = WriteWorkspaceFileInput$1;
13
13
  //#endregion
14
- export { type ApprovalInput, type AttemptExtensionFixResponse, type AutomationRun, type AutomationRunError, type AutomationRunEvent, type AutomationRunStatus, type AutomationTokenRecord, type CommandExecuteRequest, type CommandExecuteResponse, type ConfigureExtensionConnectionInput, type CreateAutomationRunInput, type CreateNotificationInput, type CreateProjectInput, type CreateSessionInput, type CreateWorkspaceInput, type ExtensionCommandPaletteContribution, type ExtensionCommandPaletteResourceRecord, type ExtensionCommandRecord, type ExtensionConnectionRecord, type ExtensionDiagnostic, type ExtensionKeybindingRecord, type ExtensionMenuContribution, type ExtensionRecord, type ExtensionSettingDefinitionRecord, type ExtensionSettingValueRecord, type ExtensionSettingsPanelRecord, type FollowUpInput, type InstallMarketplaceExtensionResponse, type IssueAutomationTokenInput, type IssueAutomationTokenResponse, type ListAutomationRunEventsResponse, type ListAutomationTokensResponse, type ListExtensionAppearanceResponse, type ListExtensionCommandsResponse, type ListExtensionConnectionsResponse, type ListExtensionSettingsResponse, type ListNotificationsQuery, type ListNotificationsResponse, type ListProjectExtensionsResponse, type ListWorkspaceFilesInput, type LocalizableString, type MarketplaceExtension, type Notification, type NotificationAction, type NotificationActorType, type NotificationKind, type NotificationOrigin, type NotificationPriority, type NotificationStatus, type ProjectExtensionInstance, type RemoveWorktreeResponse, type RenameWorkspaceInput, type ResolveSessionIdInput, type ResolveSessionIdResponse, type ResourceRef, type SessionAttachment, type SessionAttachmentRef, type SessionConversationResponse, type SessionConversationSources, type SessionHistoryIssue, type SessionQueuedMessagesResponse, type Settings, type TerminalHostEvent, type TerminalSessionOperation, type TerminalSessionRequest, type TerminalSessionResult, type UpdateExtensionSettingRequest, type UpdateNotificationInput, type UpdateProjectInput, type UpdateSettingsInput, type UpdateSkillInput, type UpgradeProjectExtensionResponse, type WorkbenchExtensionAutomationRecord, type WorkbenchExtensionCommandPaletteResourceRecord, type WorkbenchExtensionHarnessRecord, type WorkbenchExtensionMetadata, type WorkbenchExtensionViewBody, type WorkbenchExtensionViewRecord, type WorkspaceFileContent, type WorkspaceFileEntry, type WorkspaceFilesResponse, type WorkspaceProviderDescriptor, type WriteWorkspaceFileInput, sessionAttachmentMimeTypesByExtension };
14
+ export { type AddLocalExtensionFolderResponse, type ApprovalInput, type AutomationRun, type AutomationRunError, type AutomationRunEvent, type AutomationRunStatus, type AutomationTokenRecord, type CommandExecuteRequest, type CommandExecuteResponse, type ConfigureExtensionConnectionInput, type CreateAutomationRunInput, type CreateNotificationInput, type CreateProjectInput, type CreateSessionInput, type CreateWorkspaceInput, type ExtensionCommandPaletteContribution, type ExtensionCommandPaletteResourceRecord, type ExtensionCommandRecord, type ExtensionConnectionRecord, type ExtensionDiagnostic, type ExtensionKeybindingRecord, type ExtensionMenuContribution, type ExtensionRecord, type ExtensionSettingDefinitionRecord, type ExtensionSettingValueRecord, type ExtensionSettingsPanelRecord, type FollowUpInput, type InstallMarketplaceExtensionResponse, type IssueAutomationTokenInput, type IssueAutomationTokenResponse, type ListAutomationRunEventsResponse, type ListAutomationTokensResponse, type ListExtensionAppearanceResponse, type ListExtensionCommandsResponse, type ListExtensionConnectionsResponse, type ListExtensionSettingsResponse, type ListNotificationsQuery, type ListNotificationsResponse, type ListProjectExtensionsResponse, type ListWorkspaceFilesInput, type LocalizableString, type MarketplaceExtension, type Notification, type NotificationAction, type NotificationActorType, type NotificationKind, type NotificationOrigin, type NotificationPriority, type NotificationStatus, type ProjectExtensionInstance, type RemoveWorktreeResponse, type RenameWorkspaceInput, type ResolveSessionIdInput, type ResolveSessionIdResponse, type ResourceRef, type SessionAttachment, type SessionAttachmentRef, type SessionConversationResponse, type SessionConversationSources, type SessionQueuedMessagesResponse, type Settings, type TerminalHostEvent, type TerminalSessionOperation, type TerminalSessionRequest, type TerminalSessionResult, type UpdateExtensionSettingRequest, type UpdateNotificationInput, type UpdateProjectInput, type UpdateSettingsInput, type UpdateSkillInput, type UpgradeProjectExtensionResponse, type WorkbenchExtensionAutomationRecord, type WorkbenchExtensionCommandPaletteResourceRecord, type WorkbenchExtensionHarnessRecord, type WorkbenchExtensionMetadata, type WorkbenchExtensionViewBody, type WorkbenchExtensionViewRecord, type WorkspaceFileContent, type WorkspaceFileEntry, type WorkspaceFilesResponse, type WorkspaceProviderDescriptor, type WriteWorkspaceFileInput, sessionAttachmentMimeTypesByExtension };
15
15
  export {};
@@ -181,9 +181,9 @@ var createRequestHeaders = (options, reqOpts = {}) => {
181
181
  headers.set("authorization", `Bearer ${token}`);
182
182
  return headers;
183
183
  };
184
- var isBinaryBody = (body) => body instanceof ArrayBuffer || ArrayBuffer.isView(body);
184
+ var isRawBody = (body) => body instanceof ArrayBuffer || ArrayBuffer.isView(body) || body instanceof FormData;
185
185
  var serializeRequestBody = (body) => {
186
- if (body instanceof ArrayBuffer)
186
+ if (body instanceof ArrayBuffer || body instanceof FormData)
187
187
  return body;
188
188
  if (ArrayBuffer.isView(body)) {
189
189
  if (body.buffer instanceof ArrayBuffer)
@@ -201,7 +201,7 @@ var createRequest = (options) => {
201
201
  const url = resolveClientUrl(baseUrl, path);
202
202
  const headers = createRequestHeaders(options, {
203
203
  headers: reqOpts.headers,
204
- hasJsonBody: reqOpts.body !== undefined && !isBinaryBody(reqOpts.body)
204
+ hasJsonBody: reqOpts.body !== undefined && !isRawBody(reqOpts.body)
205
205
  });
206
206
  if (!isSameOriginTarget(baseUrl, path, url))
207
207
  headers.delete("authorization");
@@ -325,10 +325,6 @@ var dispatchSessionStreamEvent = (event, handlers) => {
325
325
  handlers.onApprovalRequest?.(parseEventData(event.data));
326
326
  return;
327
327
  }
328
- if (event.event === "history_issue") {
329
- handlers.onHistoryIssue?.(parseEventData(event.data));
330
- return;
331
- }
332
328
  if (event.event === "queued_messages") {
333
329
  handlers.onQueuedMessages?.(parseEventData(event.data));
334
330
  return;
package/dist/client.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { A as RequestFn, C as DirectoryEntry, D as AgentClient, E as AutomationClient, M as createRequest, O as ClientOptions, S as NotificationsClient, T as ExtensionClient, _ as SessionStreamHandlers, a as SyncClient, b as createRuntimeClient, c as SyncWriter, d as parseSyncDeleteEvent, f as SkillClient, g as SessionStreamConnection, h as SessionClient, i as StartSyncInput, j as RequestOptions, k as PstdioApiError, l as SyncWriterProvider, m as ListSessionsInput, n as createClient, o as SyncConnection, p as SettingsClient, r as WorkspaceClient, s as SyncRow, t as PstdioClient, u as applySyncEvent, v as SseEvent, w as FilesystemClient, x as ProjectClient, y as RuntimeClient } from "./index-KZC6jRip.js";
1
+ import { A as RequestFn, C as DirectoryEntry, D as AgentClient, E as AutomationClient, M as createRequest, O as ClientOptions, S as NotificationsClient, T as ExtensionClient, _ as SessionStreamHandlers, a as SyncClient, b as createRuntimeClient, c as SyncWriter, d as parseSyncDeleteEvent, f as SkillClient, g as SessionStreamConnection, h as SessionClient, i as StartSyncInput, j as RequestOptions, k as PstdioApiError, l as SyncWriterProvider, m as ListSessionsInput, n as createClient, o as SyncConnection, p as SettingsClient, r as WorkspaceClient, s as SyncRow, t as PstdioClient, u as applySyncEvent, v as SseEvent, w as FilesystemClient, x as ProjectClient, y as RuntimeClient } from "./index-DZSUI5-9.js";
2
2
  export { type AgentClient, type AutomationClient, type ClientOptions, type DirectoryEntry, type ExtensionClient, type FilesystemClient, type ListSessionsInput, type NotificationsClient, type ProjectClient, PstdioApiError, type PstdioClient, type RequestFn, type RequestOptions, type RuntimeClient, type SessionClient, type SessionStreamConnection, type SessionStreamHandlers, type SettingsClient, type SkillClient, type SseEvent, type StartSyncInput, type SyncClient, type SyncConnection, type SyncRow, type SyncWriter, type SyncWriterProvider, type WorkspaceClient, applySyncEvent, createClient, createRequest, createRuntimeClient, parseSyncDeleteEvent };
3
3
  export {};
package/dist/data.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Ir as ArtifactMount } from "./index-CJUDgZmO.js";
1
+ import { Ir as ArtifactMount } from "./index-CnOTGr_I.js";
2
2
  //#region src/data/draft-layout.d.ts
3
3
  export declare const assertSafePathSegment: (value: string) => void;
4
4
  export declare const requireRepoFiles: (projectFiles: ArtifactMount | undefined) => ArtifactMount;
@@ -271,10 +271,11 @@ var packageAsset = (path, baseUrl) => ({
271
271
  baseUrl
272
272
  });
273
273
  // ../pstdio-api-contracts/src/extension-kernel/types/extension.ts
274
- var EXTENSION_API_VERSION = "1.0.0-alpha.13";
274
+ var EXTENSION_API_VERSION = "1.0.0-alpha.14";
275
275
  // ../pstdio-api-contracts/src/extension-kernel/types/webview-capabilities.ts
276
276
  var WEBVIEW_HOST_CAPABILITY_VERSION = 1;
277
277
  var WEBVIEW_DECLARABLE_CAPABILITIES = [
278
+ "clipboard.write",
278
279
  "commands.execute",
279
280
  "navigation.open",
280
281
  "placement.close",
@@ -296,7 +297,7 @@ var WEBVIEW_DECLARABLE_CAPABILITIES = [
296
297
  var WEBVIEW_SCOPED_DECLARABLE_CAPABILITIES = ["artifacts.read"];
297
298
  var ALWAYS_AVAILABLE_WEBVIEW_CAPABILITIES = ["host.dispatchKeyboardEvent"];
298
299
  var WEBVIEW_HOST_CAPABILITIES = [
299
- ...WEBVIEW_DECLARABLE_CAPABILITIES,
300
+ ...WEBVIEW_DECLARABLE_CAPABILITIES.filter((capability) => capability !== "clipboard.write"),
300
301
  ...WEBVIEW_SCOPED_DECLARABLE_CAPABILITIES,
301
302
  ...ALWAYS_AVAILABLE_WEBVIEW_CAPABILITIES
302
303
  ];
@@ -351,17 +352,7 @@ var historyTurnEvidence = (known, native, prompt, body) => {
351
352
  return (turn) => keys.get(turn);
352
353
  };
353
354
 
354
- // ../pstdio-api-contracts/src/history-reconciliation.ts
355
- class HistoryConflict extends Error {
356
- }
357
- var submittedPrompt = (message) => message.parts.filter((part) => part.type === "text").map((part) => part.text).join(`
358
- `).replace(/\n\n<session-attachments>[\s\S]*<\/session-attachments>\s*$/, "").trim();
359
- var historyValueKey = (value) => JSON.stringify(value, (_key, item) => {
360
- if (!item || typeof item !== "object" || Array.isArray(item))
361
- return item;
362
- return Object.fromEntries(Object.entries(item).sort(([a], [b]) => a.localeCompare(b)));
363
- });
364
- var historyMessageKey = (message) => historyValueKey([message.role, message.parts]);
355
+ // ../pstdio-api-contracts/src/ordered-history-merge.ts
365
356
  var positions = (items, key) => {
366
357
  const result = new Map;
367
358
  items.forEach((item, index) => {
@@ -372,24 +363,53 @@ var positions = (items, key) => {
372
363
  });
373
364
  return result;
374
365
  };
375
- var mergeOrderedHistory = (known, native, key, merge, refineKey) => {
366
+ var orderedAnchors = (anchors) => {
367
+ const tails = [];
368
+ const previous = [];
369
+ anchors.forEach(([, native], index) => {
370
+ let low = 0;
371
+ let high = tails.length;
372
+ while (low < high) {
373
+ const middle = low + high >> 1;
374
+ if (anchors[tails[middle]][1] < native)
375
+ low = middle + 1;
376
+ else
377
+ high = middle;
378
+ }
379
+ previous[index] = low > 0 ? tails[low - 1] : -1;
380
+ tails[low] = index;
381
+ });
382
+ const kept = [];
383
+ for (let index = tails.at(-1) ?? -1;index >= 0; index = previous[index])
384
+ kept.unshift(anchors[index]);
385
+ return kept;
386
+ };
387
+ var newerThanSaved = (known, native, options) => {
388
+ const times = options.time ? known.map(options.time).filter((value) => value !== undefined) : [];
389
+ if (!times.length)
390
+ return [];
391
+ const savedUntil = Math.max(...times);
392
+ return native.filter((item) => (options.time?.(item) ?? savedUntil) > savedUntil);
393
+ };
394
+ var mergeOrderedHistory = (known, native, options, trailing = true) => {
395
+ const { key, merge, refineKey, covered } = options;
396
+ const missing = native.filter((item) => !covered?.(item));
376
397
  if (!known.length)
377
- return native;
398
+ return missing;
378
399
  if (!native.length)
379
400
  return known;
380
401
  const knownPositions = positions(known, key);
381
402
  const nativePositions = positions(native, key);
382
- const anchors = [];
403
+ const found = [];
383
404
  for (const [value, indices] of knownPositions) {
384
405
  const other = nativePositions.get(value);
385
406
  if (indices.length === 1 && other?.length === 1)
386
- anchors.push([indices[0], other[0]]);
407
+ found.push([indices[0], other[0]]);
387
408
  }
409
+ const anchors = orderedAnchors(found.sort((a, b) => a[0] - b[0]));
388
410
  if (!anchors.length) {
389
- if (refineKey) {
390
- const refined = mergeOrderedHistory(known, native, refineKey(known, native), merge);
391
- return refined;
392
- }
411
+ if (refineKey)
412
+ return mergeOrderedHistory(known, native, { ...options, key: refineKey(known, native), refineKey: undefined }, trailing);
393
413
  const paired = Math.min(known.length, native.length);
394
414
  if (known.slice(0, paired).every((item, index) => key(item) === key(native[index]))) {
395
415
  return [
@@ -398,22 +418,35 @@ var mergeOrderedHistory = (known, native, key, merge, refineKey) => {
398
418
  ...native.slice(paired)
399
419
  ];
400
420
  }
401
- throw new HistoryConflict("ambiguous_interval");
421
+ return trailing ? [...known, ...newerThanSaved(known, missing, options)] : known;
402
422
  }
423
+ const kept = new Set(anchors.map(([, index]) => index));
424
+ const reordered = new Set(found.filter(([, index]) => !kept.has(index)).map(([, index]) => native[index]));
425
+ const nativeSpan = (start, end) => native.slice(start, end).filter((item) => !reordered.has(item));
403
426
  let left = 0;
404
427
  let right = 0;
405
428
  const result = [];
406
429
  for (const [a, b] of anchors) {
407
- if (b < right)
408
- throw new HistoryConflict("conflicting_order");
409
- result.push(...mergeOrderedHistory(known.slice(left, a), native.slice(right, b), key, merge, refineKey));
430
+ result.push(...mergeOrderedHistory(known.slice(left, a), nativeSpan(right, b), options, false));
410
431
  result.push(merge(known[a], native[b]));
411
432
  left = a + 1;
412
433
  right = b + 1;
413
434
  }
414
- result.push(...mergeOrderedHistory(known.slice(left), native.slice(right), key, merge, refineKey));
435
+ result.push(...mergeOrderedHistory(known.slice(left), nativeSpan(right), options, trailing));
415
436
  return result;
416
437
  };
438
+
439
+ // ../pstdio-api-contracts/src/history-reconciliation.ts
440
+ class HistoryConflict extends Error {
441
+ }
442
+ var submittedPrompt = (message) => message.parts.filter((part) => part.type === "text").map((part) => part.text).join(`
443
+ `).replace(/\n\n<session-attachments>[\s\S]*<\/session-attachments>\s*$/, "").trim();
444
+ var historyValueKey = (value) => JSON.stringify(value, (_key, item) => {
445
+ if (!item || typeof item !== "object" || Array.isArray(item))
446
+ return item;
447
+ return Object.fromEntries(Object.entries(item).sort(([a], [b]) => a.localeCompare(b)));
448
+ });
449
+ var historyMessageKey = (message) => historyValueKey([message.role, message.parts]);
417
450
  var splitHistoryTurns = (messages) => {
418
451
  const turns = [];
419
452
  for (const message of messages) {
@@ -451,7 +484,14 @@ var reconcileMessageHistory = (input, projection = {}) => {
451
484
  const mergeTurn = (known, native) => {
452
485
  const startsWithUser = known[0]?.role === "user" && native[0]?.role === "user";
453
486
  const body = (turn) => combineTextRuns(turn.slice(startsWithUser ? 1 : 0).filter((message) => !generated(message)));
454
- const messages = mergeOrderedHistory(body(known), body(native), key, merge);
487
+ const shown = known.flatMap((message) => message.parts.flatMap((part) => part.type === "text" ? [part.text] : []));
488
+ const saved = shown.join("");
489
+ const messages = mergeOrderedHistory(body(known), body(native), {
490
+ key,
491
+ merge,
492
+ time: (message) => message.createdAt,
493
+ covered: (message) => message.parts.length > 0 && message.parts.every((part) => part.type === "text" && saved.includes(part.text))
494
+ });
455
495
  const metadata = [...native.filter(generated)];
456
496
  const counts = new Map;
457
497
  metadata.forEach((message) => {
@@ -469,7 +509,12 @@ var reconcileMessageHistory = (input, projection = {}) => {
469
509
  };
470
510
  try {
471
511
  const prompt = (turn) => turn[0]?.role === "user" ? `user:${submittedPrompt(turn[0])}` : "prefix";
472
- const turns = mergeOrderedHistory(splitHistoryTurns(input.knownMessages), splitHistoryTurns(input.nativeMessages), prompt, mergeTurn, (known, native) => historyTurnEvidence(known, native, prompt, (turn) => combineTextRuns(turn.slice(1).filter((message) => !generated(message))).map(key)));
512
+ const turns = mergeOrderedHistory(splitHistoryTurns(input.knownMessages), splitHistoryTurns(input.nativeMessages), {
513
+ key: prompt,
514
+ merge: mergeTurn,
515
+ refineKey: (known, native) => historyTurnEvidence(known, native, prompt, (turn) => combineTextRuns(turn.slice(1).filter((message) => !generated(message))).map(key)),
516
+ time: (turn) => turn[0]?.createdAt
517
+ });
473
518
  const messages = turns.flat().map((message, index) => message.index === undefined ? message : { ...message, index });
474
519
  return { kind: "recovered", messages };
475
520
  } catch (error) {
@@ -479,7 +524,7 @@ var reconcileMessageHistory = (input, projection = {}) => {
479
524
  }
480
525
  };
481
526
  // package.json
482
- var version = "0.36.1";
527
+ var version = "0.37.0";
483
528
 
484
529
  // src/version.ts
485
530
  var SDK_VERSION = version;