@pstdio/sdk 0.25.0 → 0.36.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.
@@ -3,10 +3,10 @@ var assertSafePathSegment = (value) => {
3
3
  if (!value || value === "." || value === ".." || /[/\\\0]/.test(value))
4
4
  throw new Error(`Unsafe path segment: ${value}`);
5
5
  };
6
- var requireRepoFiles = (repoFiles) => {
7
- if (!repoFiles)
8
- throw new Error("This command must be run inside a project repository.");
9
- return repoFiles;
6
+ var requireRepoFiles = (projectFiles) => {
7
+ if (!projectFiles)
8
+ throw new Error("This command must be run inside a project folder.");
9
+ return projectFiles;
10
10
  };
11
11
  var createDraftLayout = (root, document) => {
12
12
  const directory = (name) => {
package/dist/data.d.ts CHANGED
@@ -1,49 +1,27 @@
1
- export declare const applyFrontmatter: (frontmatter: string, content: string) => string;
2
-
3
- declare interface ArtifactFile {
4
- path: string;
5
- size?: number;
6
- updatedAt?: string;
7
- }
8
-
9
- declare interface ArtifactMount {
10
- exists(path: string): Promise<boolean>;
11
- readText(path: string): Promise<string>;
12
- writeText(path: string, value: string): Promise<void>;
13
- /** Replace existing text. Fails if missing and never recreates a concurrently deleted file. */
14
- updateText(path: string, value: string): Promise<void>;
15
- readBytes(path: string): Promise<Uint8Array>;
16
- writeBytes(path: string, value: Uint8Array): Promise<void>;
17
- list(pattern?: string): Promise<ArtifactFile[]>;
18
- listDirs(path?: string): Promise<string[]>;
19
- delete(path: string): Promise<void>;
20
- }
21
-
22
- export declare const assertSafePathSegment: (value: string) => void;
23
-
24
- export declare const createDraftLayout: (root: string, document: string) => {
25
- directory: (name: string) => string;
26
- markdown: (name: string, suffix?: string) => string;
27
- files: (name: string, suffix?: string) => string;
28
- };
29
-
30
- export declare const findClosingFrontmatterDelimiter: (content: string) => {
31
- end: number;
32
- start: number;
33
- } | null;
34
-
35
- export declare const quoteYamlScalar: (value: string) => string;
36
-
37
- export declare const requireRepoFiles: (repoFiles: ArtifactMount | undefined) => ArtifactMount;
38
-
39
- export declare const resolveByIdOrName: <TItem extends {
40
- id: string;
41
- }>(items: TItem[], value: string, nameOf: (item: TItem) => string, label: string) => string;
42
-
43
- export declare const sameName: (a: string, b: string) => boolean;
44
-
45
- export declare const stripFrontmatter: (content: string) => string;
46
-
47
- export declare const unquoteYamlScalar: (value: string) => string;
48
-
49
- export { }
1
+ import { Ir as ArtifactMount } from "./index-CR17_9lz.js";
2
+ //#region src/data/draft-layout.d.ts
3
+ export declare const assertSafePathSegment: (value: string) => void;
4
+ export declare const requireRepoFiles: (projectFiles: ArtifactMount | undefined) => ArtifactMount;
5
+ export declare const createDraftLayout: (root: string, document: string) => {
6
+ directory: (name: string) => string;
7
+ markdown: (name: string, suffix?: string) => string;
8
+ files: (name: string, suffix?: string) => string;
9
+ };
10
+ //#endregion
11
+ //#region src/data/frontmatter.d.ts
12
+ export declare const quoteYamlScalar: (value: string) => string;
13
+ export declare const findClosingFrontmatterDelimiter: (content: string) => {
14
+ end: number;
15
+ start: number;
16
+ } | null;
17
+ export declare const stripFrontmatter: (content: string) => string;
18
+ export declare const applyFrontmatter: (frontmatter: string, content: string) => string;
19
+ export declare const unquoteYamlScalar: (value: string) => string;
20
+ //#endregion
21
+ //#region src/data/resolve.d.ts
22
+ export declare const sameName: (a: string, b: string) => boolean;
23
+ export declare const resolveByIdOrName: <TItem extends {
24
+ id: string;
25
+ }>(items: TItem[], value: string, nameOf: (item: TItem) => string, label: string) => string;
26
+ //#endregion
27
+ export {};
@@ -1,3 +1,7 @@
1
+ // ../pstdio-api-contracts/src/extension-kernel/api-versions.ts
2
+ var numericIdentifier = "(?:0|[1-9]\\d*)";
3
+ var prereleaseIdentifier = `(?:${numericIdentifier}|\\d*[A-Za-z-][0-9A-Za-z-]*)`;
4
+ var exactVersion = new RegExp(`^${numericIdentifier}\\.${numericIdentifier}\\.${numericIdentifier}(?:-${prereleaseIdentifier}(?:\\.${prereleaseIdentifier})*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$`);
1
5
  // ../pstdio-api-contracts/src/extension-kernel/types/composition.ts
2
6
  var dockedWorkbenchRegions = ["sidenav", "main", "secondary", "side"];
3
7
  var extensionPanelRegions = ["main", "secondary", "side"];
@@ -133,6 +137,11 @@ var workspaceSlots = {
133
137
  var projectEvents = {
134
138
  opened: hostEventRef("project.opened")
135
139
  };
140
+ var viewDataEvents = {
141
+ sessionsChanged: hostEventRef("view.sessions.changed"),
142
+ workspacesChanged: hostEventRef("view.workspaces.changed"),
143
+ repositoriesChanged: hostEventRef("view.repositories.changed")
144
+ };
136
145
  var sessionEvents = {
137
146
  started: hostEventRef("session.started"),
138
147
  resumed: hostEventRef("session.resumed"),
@@ -262,7 +271,7 @@ var packageAsset = (path, baseUrl) => ({
262
271
  baseUrl
263
272
  });
264
273
  // ../pstdio-api-contracts/src/extension-kernel/types/extension.ts
265
- var EXTENSION_API_VERSION = "1.0.0-alpha.10";
274
+ var EXTENSION_API_VERSION = "1.0.0-alpha.13";
266
275
  // ../pstdio-api-contracts/src/extension-kernel/types/webview-capabilities.ts
267
276
  var WEBVIEW_HOST_CAPABILITY_VERSION = 1;
268
277
  var WEBVIEW_DECLARABLE_CAPABILITIES = [
@@ -291,8 +300,186 @@ var WEBVIEW_HOST_CAPABILITIES = [
291
300
  ...WEBVIEW_SCOPED_DECLARABLE_CAPABILITIES,
292
301
  ...ALWAYS_AVAILABLE_WEBVIEW_CAPABILITIES
293
302
  ];
303
+ // ../pstdio-api-contracts/src/history-turn-evidence.ts
304
+ var historyTurnEvidence = (known, native, prompt, body) => {
305
+ const signatures = (turn) => JSON.stringify([prompt(turn), body(turn)]);
306
+ if (known.length === native.length && known.every((turn, index) => signatures(turn) === signatures(native[index]))) {
307
+ return signatures;
308
+ }
309
+ const tokens = (turns) => {
310
+ const positions = new Map;
311
+ turns.forEach((turn, index) => {
312
+ for (const value of new Set(body(turn))) {
313
+ const token = JSON.stringify([prompt(turn), value]);
314
+ positions.set(token, positions.has(token) ? -1 : index);
315
+ }
316
+ });
317
+ return positions;
318
+ };
319
+ const left = tokens(known);
320
+ const right = tokens(native);
321
+ const matches = new Map;
322
+ const reverse = new Map;
323
+ for (const [token, index] of left) {
324
+ const other = right.get(token);
325
+ if (index < 0 || other === undefined || other < 0)
326
+ continue;
327
+ const targets = matches.get(index) ?? new Set;
328
+ targets.add(other);
329
+ matches.set(index, targets);
330
+ const sources = reverse.get(other) ?? new Set;
331
+ sources.add(index);
332
+ reverse.set(other, sources);
333
+ }
334
+ const keys = new Map;
335
+ known.forEach((turn, index) => {
336
+ keys.set(turn, `known:${index}`);
337
+ });
338
+ native.forEach((turn, index) => {
339
+ keys.set(turn, `native:${index}`);
340
+ });
341
+ for (const [index, targets] of matches) {
342
+ if (targets.size !== 1)
343
+ continue;
344
+ const other = [...targets][0];
345
+ if (reverse.get(other)?.size !== 1)
346
+ continue;
347
+ const key = `pair:${index}:${other}`;
348
+ keys.set(known[index], key);
349
+ keys.set(native[other], key);
350
+ }
351
+ return (turn) => keys.get(turn);
352
+ };
353
+
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]);
365
+ var positions = (items, key) => {
366
+ const result = new Map;
367
+ items.forEach((item, index) => {
368
+ const value = key(item);
369
+ const indices = result.get(value) ?? [];
370
+ indices.push(index);
371
+ result.set(value, indices);
372
+ });
373
+ return result;
374
+ };
375
+ var mergeOrderedHistory = (known, native, key, merge, refineKey) => {
376
+ if (!known.length)
377
+ return native;
378
+ if (!native.length)
379
+ return known;
380
+ const knownPositions = positions(known, key);
381
+ const nativePositions = positions(native, key);
382
+ const anchors = [];
383
+ for (const [value, indices] of knownPositions) {
384
+ const other = nativePositions.get(value);
385
+ if (indices.length === 1 && other?.length === 1)
386
+ anchors.push([indices[0], other[0]]);
387
+ }
388
+ if (!anchors.length) {
389
+ if (refineKey) {
390
+ const refined = mergeOrderedHistory(known, native, refineKey(known, native), merge);
391
+ return refined;
392
+ }
393
+ const paired = Math.min(known.length, native.length);
394
+ if (known.slice(0, paired).every((item, index) => key(item) === key(native[index]))) {
395
+ return [
396
+ ...known.slice(0, paired).map((item, index) => merge(item, native[index])),
397
+ ...known.slice(paired),
398
+ ...native.slice(paired)
399
+ ];
400
+ }
401
+ throw new HistoryConflict("ambiguous_interval");
402
+ }
403
+ let left = 0;
404
+ let right = 0;
405
+ const result = [];
406
+ 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));
410
+ result.push(merge(known[a], native[b]));
411
+ left = a + 1;
412
+ right = b + 1;
413
+ }
414
+ result.push(...mergeOrderedHistory(known.slice(left), native.slice(right), key, merge, refineKey));
415
+ return result;
416
+ };
417
+ var splitHistoryTurns = (messages) => {
418
+ const turns = [];
419
+ for (const message of messages) {
420
+ if (message.role === "user" || !turns.length)
421
+ turns.push([]);
422
+ turns[turns.length - 1].push(message);
423
+ }
424
+ return turns;
425
+ };
426
+ var mergeHistoryMetadata = (known, native) => {
427
+ const files = native.parts.filter((part) => part.type === "file");
428
+ const fileKeys = new Set(files.map((part) => part.fileId ?? part.url));
429
+ const missing = known.parts.filter((part) => part.type === "file" && !fileKeys.has(part.fileId ?? part.url));
430
+ const parts = native.role === "user" ? [...known.parts.filter((part) => part.type === "text"), ...native.parts.filter((part) => part.type !== "text")] : native.parts;
431
+ return { ...known, ...native, parts: [...parts, ...missing] };
432
+ };
433
+ var isUsage = (message) => message.role === "system" && message.parts.length > 0 && message.parts.every((part) => part.type === "token_usage");
434
+ var combineTextRuns = (messages) => {
435
+ const runs = [];
436
+ for (const message of messages) {
437
+ const previous = runs.at(-1);
438
+ const part = message.parts[0];
439
+ const previousPart = previous?.parts[0];
440
+ if (previous && message.role === previous.role && message.parts.length === 1 && previous.parts.length === 1 && (part.type === "text" || part.type === "reasoning") && previousPart?.type === part.type) {
441
+ runs[runs.length - 1] = { ...previous, parts: [{ ...part, text: previousPart.text + part.text }] };
442
+ } else
443
+ runs.push(message);
444
+ }
445
+ return runs;
446
+ };
447
+ var reconcileMessageHistory = (input, projection = {}) => {
448
+ const key = projection.key ?? historyMessageKey;
449
+ const merge = projection.merge ?? mergeHistoryMetadata;
450
+ const generated = projection.isGenerated ?? isUsage;
451
+ const mergeTurn = (known, native) => {
452
+ const startsWithUser = known[0]?.role === "user" && native[0]?.role === "user";
453
+ const body = (turn) => combineTextRuns(turn.slice(startsWithUser ? 1 : 0).filter((message) => !generated(message)));
454
+ const messages = mergeOrderedHistory(body(known), body(native), key, merge);
455
+ const metadata = [...native.filter(generated)];
456
+ const counts = new Map;
457
+ metadata.forEach((message) => {
458
+ counts.set(historyMessageKey(message), (counts.get(historyMessageKey(message)) ?? 0) + 1);
459
+ });
460
+ for (const message of known.filter(generated)) {
461
+ const value = historyMessageKey(message);
462
+ const remaining = counts.get(value) ?? 0;
463
+ if (remaining)
464
+ counts.set(value, remaining - 1);
465
+ else
466
+ metadata.push(message);
467
+ }
468
+ return [...startsWithUser ? [mergeHistoryMetadata(known[0], native[0])] : [], ...messages, ...metadata];
469
+ };
470
+ try {
471
+ 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)));
473
+ const messages = turns.flat().map((message, index) => message.index === undefined ? message : { ...message, index });
474
+ return { kind: "recovered", messages };
475
+ } catch (error) {
476
+ if (error instanceof HistoryConflict)
477
+ return { kind: "conflict", category: error.message };
478
+ throw error;
479
+ }
480
+ };
294
481
  // package.json
295
- var version = "0.25.0";
482
+ var version = "0.36.0";
296
483
 
297
484
  // src/version.ts
298
485
  var SDK_VERSION = version;
@@ -609,7 +796,6 @@ var params = {
609
796
  type: "multi-select",
610
797
  ...options
611
798
  }),
612
- repo: (options) => ({ type: "repo", ...options }),
613
799
  harness: (options) => ({ type: "harness", ...options }),
614
800
  template: (options) => {
615
801
  const { type: templateType, ...rest } = options;
@@ -732,7 +918,8 @@ var createWebviewClient = (host, options) => {
732
918
  const runCommand = async (commandKey, params) => {
733
919
  const response = await host.call("commands.execute", {
734
920
  commandId: `${extensionId}.command.${commandKey}`,
735
- params
921
+ params,
922
+ ...options?.workspaceId ? { workspaceId: options.workspaceId } : {}
736
923
  });
737
924
  return unwrapCommandOutcome(response);
738
925
  };
@@ -776,6 +963,7 @@ export {
776
963
  ALWAYS_AVAILABLE_WEBVIEW_CAPABILITIES,
777
964
  EXTENSION_API_VERSION,
778
965
  EXTENSION_EVENTS_SCOPE,
966
+ HistoryConflict,
779
967
  SDK_VERSION,
780
968
  WEBVIEW_DECLARABLE_CAPABILITIES,
781
969
  WEBVIEW_HOST_CAPABILITIES,
@@ -824,6 +1012,8 @@ export {
824
1012
  eventRef,
825
1013
  extensionPanelRegions,
826
1014
  gitEvents,
1015
+ historyMessageKey,
1016
+ historyValueKey,
827
1017
  isLocalizedString,
828
1018
  isNavigationTarget,
829
1019
  isValidLocalContributionId,
@@ -832,6 +1022,8 @@ export {
832
1022
  localContributionIdGrammar,
833
1023
  localContributionIdPattern,
834
1024
  matchesResourceWhen,
1025
+ mergeHistoryMetadata,
1026
+ mergeOrderedHistory,
835
1027
  packageAsset,
836
1028
  params,
837
1029
  parsePageUrl,
@@ -841,6 +1033,7 @@ export {
841
1033
  projectSlots,
842
1034
  qualifyNavigationTarget,
843
1035
  qualifyRef,
1036
+ reconcileMessageHistory,
844
1037
  resolveEventReferenceId,
845
1038
  resourceKey,
846
1039
  resourceMenuSlotRef2 as resourceMenuSlotRef,
@@ -848,7 +1041,10 @@ export {
848
1041
  serializeWorkbenchPageUrl,
849
1042
  sessionEvents,
850
1043
  sessionSlots,
1044
+ splitHistoryTurns,
1045
+ submittedPrompt,
851
1046
  unwrapCommandOutcome,
1047
+ viewDataEvents,
852
1048
  workbenchModeDefinitions,
853
1049
  workbenchModes,
854
1050
  workbenchPageDefinitions,
@@ -1,23 +1,18 @@
1
- import { QueryKey } from '@tanstack/react-query';
2
- import { UseMutationResult } from '@tanstack/react-query';
3
- import { UseQueryResult } from '@tanstack/react-query';
4
-
5
- declare interface CommandMutationInput<TParams, TResult> {
6
- command: (params: TParams) => Promise<TResult>;
7
- invalidate?: QueryKey[];
8
- }
9
-
10
- declare interface CommandQueryInput<TResult> {
11
- queryKey: QueryKey;
12
- command: () => Promise<TResult>;
13
- enabled?: boolean;
14
- staleTime?: number;
15
- }
16
-
17
- /** Writes server state via a typed client command and refreshes affected queries on success. */
18
- export declare const useCommandMutation: <TParams, TResult>(input: CommandMutationInput<TParams, TResult>) => UseMutationResult<TResult, Error, TParams, unknown>;
19
-
20
- /** Reads server state via a typed client command, cached and deduped by react-query. */
21
- export declare const useCommandQuery: <TResult>(input: CommandQueryInput<TResult>) => UseQueryResult<TResult>;
22
-
23
- export { }
1
+ import { QueryKey, UseQueryResult } from "@tanstack/react-query";
2
+ //#region src/extensions/react/index.d.ts
3
+ interface CommandQueryInput<TResult> {
4
+ queryKey: QueryKey;
5
+ command: () => Promise<TResult>;
6
+ enabled?: boolean;
7
+ staleTime?: number;
8
+ }
9
+ /** Reads server state via a typed client command, cached and deduped by react-query. */
10
+ export declare const useCommandQuery: <TResult>(input: CommandQueryInput<TResult>) => UseQueryResult<TResult>;
11
+ interface CommandMutationInput<TParams, TResult> {
12
+ command: (params: TParams) => Promise<TResult>;
13
+ invalidate?: QueryKey[];
14
+ }
15
+ /** Writes server state via a typed client command and refreshes affected queries on success. */
16
+ export declare const useCommandMutation: <TParams, TResult>(input: CommandMutationInput<TParams, TResult>) => import("@tanstack/react-query").UseMutationResult<TResult, Error, TParams, unknown>;
17
+ //#endregion
18
+ export {};