@pstdio/sdk 0.3.0 → 0.4.2

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,22 @@
1
+ import type { JsonObject, Struct } from "./json";
2
+ export type UiSlotKind = "menu" | "navigation" | "view" | "settings" | "renderer";
3
+ export interface SlotOptions<TKind extends UiSlotKind = UiSlotKind> {
4
+ kind: TKind;
5
+ label?: string;
6
+ description?: string;
7
+ metadata?: JsonObject;
8
+ }
9
+ export interface SlotRef<TContext extends Struct = Struct, TKind extends UiSlotKind = UiSlotKind> {
10
+ id: string;
11
+ kind: TKind;
12
+ label?: string;
13
+ description?: string;
14
+ metadata?: JsonObject;
15
+ /** Phantom field used to constrain compatible contributions; never populated at runtime. */
16
+ context?: TContext;
17
+ }
18
+ export interface SlotInvocationContext<TContext extends Struct = Struct> {
19
+ id: string;
20
+ kind: UiSlotKind;
21
+ context: TContext;
22
+ }
@@ -178,14 +178,30 @@ var removeAllWorktreesForTicket = async (ctx, input) => {
178
178
  return removed;
179
179
  };
180
180
  // src/plugins/helpers/run-command.ts
181
+ import { accessSync, constants } from "node:fs";
182
+ import { delimiter, join } from "node:path";
183
+ var resolveCommandPath = (command, env) => {
184
+ if (command.includes("/") || command.includes("\\"))
185
+ return command;
186
+ for (const dir of env.PATH?.split(delimiter) ?? []) {
187
+ const candidate = join(dir || ".", command);
188
+ try {
189
+ accessSync(candidate, constants.X_OK);
190
+ return candidate;
191
+ } catch {}
192
+ }
193
+ return command;
194
+ };
181
195
  var runCommand = async (cwd, command, options = {}) => {
182
196
  const [cmd, ...args] = command;
183
197
  const stdio = options.quiet ? "ignore" : "pipe";
198
+ const env = { ...process.env, ...options.env };
199
+ const resolvedCmd = resolveCommandPath(cmd, env);
184
200
  let proc;
185
201
  try {
186
- proc = Bun.spawn([cmd, ...args], {
202
+ proc = Bun.spawn([resolvedCmd, ...args], {
187
203
  cwd,
188
- env: options.env ?? { ...process.env },
204
+ env,
189
205
  stdin: "ignore",
190
206
  stdout: stdio,
191
207
  stderr: stdio
@@ -204,14 +220,14 @@ var runCommand = async (cwd, command, options = {}) => {
204
220
  };
205
221
  // src/plugins/helpers/save-ticket.ts
206
222
  import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
207
- import { basename, isAbsolute, join, relative, resolve } from "node:path";
208
- var TICKETS_DIR = join(".pstdio", "tickets");
223
+ import { basename, isAbsolute, join as join2, relative, resolve } from "node:path";
224
+ var TICKETS_DIR = join2(".pstdio", "tickets");
209
225
  var TICKET_FILES_DIR = "files";
210
226
  var TICKET_ARTIFACTS_DIR = "artifacts";
211
227
  var MAX_DISPLAY_TITLE_LENGTH = 50;
212
228
  var ACTIONABLE_FRONTMATTER_KEYS = ["blocked_reason", "parent_id", "status"];
213
229
  var resolveTicketDir = (rootPath, shorthand) => {
214
- const exactDir = join(rootPath, TICKETS_DIR, shorthand);
230
+ const exactDir = join2(rootPath, TICKETS_DIR, shorthand);
215
231
  if (!existsSync(exactDir))
216
232
  return null;
217
233
  if (!statSync(exactDir).isDirectory()) {
@@ -223,20 +239,20 @@ var readTicketFile = (rootPath, shorthand) => {
223
239
  const dir = resolveTicketDir(rootPath, shorthand);
224
240
  if (!dir)
225
241
  return null;
226
- const filePath = join(dir, "ticket.md");
242
+ const filePath = join2(dir, "ticket.md");
227
243
  if (!existsSync(filePath))
228
244
  return null;
229
245
  return readFileSync(filePath, "utf8");
230
246
  };
231
247
  var writeTicketFile = (rootPath, shorthand, content) => {
232
- const dir = resolveTicketDir(rootPath, shorthand) ?? join(rootPath, TICKETS_DIR, shorthand);
248
+ const dir = resolveTicketDir(rootPath, shorthand) ?? join2(rootPath, TICKETS_DIR, shorthand);
233
249
  mkdirSync(dir, { recursive: true });
234
- writeFileSync(join(dir, "ticket.md"), content);
250
+ writeFileSync(join2(dir, "ticket.md"), content);
235
251
  };
236
252
  var walkFiles = (baseDir, currentDir, files) => {
237
253
  const entries = readdirSync(currentDir, { withFileTypes: true });
238
254
  for (const entry of entries) {
239
- const fullPath = join(currentDir, entry.name);
255
+ const fullPath = join2(currentDir, entry.name);
240
256
  if (entry.isDirectory()) {
241
257
  walkFiles(baseDir, fullPath, files);
242
258
  continue;
@@ -250,7 +266,7 @@ var listDirFiles = (rootPath, shorthand, subDir) => {
250
266
  const dir = resolveTicketDir(rootPath, shorthand);
251
267
  if (!dir)
252
268
  return [];
253
- const baseDir = join(dir, subDir);
269
+ const baseDir = join2(dir, subDir);
254
270
  if (!existsSync(baseDir))
255
271
  return [];
256
272
  const files = [];
@@ -262,7 +278,7 @@ var readSafe = (rootPath, shorthand, subDir, requestedPath) => {
262
278
  const ticketDir = resolveTicketDir(rootPath, shorthand);
263
279
  if (!ticketDir)
264
280
  throw new Error(`Ticket directory not found: ${shorthand}`);
265
- const baseDir = join(ticketDir, subDir);
281
+ const baseDir = join2(ticketDir, subDir);
266
282
  const target = resolve(baseDir, requestedPath);
267
283
  const rel = relative(baseDir, target);
268
284
  if (isAbsolute(rel) || rel.startsWith("..")) {
@@ -475,8 +491,8 @@ var setWorkspaceAttemptStatus = async (ctx, input) => {
475
491
  };
476
492
  // src/plugins/helpers/ticket-pull.ts
477
493
  import { existsSync as existsSync2, mkdirSync as mkdirSync2, statSync as statSync2, writeFileSync as writeFileSync2 } from "node:fs";
478
- import { dirname, isAbsolute as isAbsolute2, join as join2, relative as relative2, resolve as resolve2 } from "node:path";
479
- var TICKETS_DIR2 = join2(".pstdio", "tickets");
494
+ import { dirname, isAbsolute as isAbsolute2, join as join3, relative as relative2, resolve as resolve2 } from "node:path";
495
+ var TICKETS_DIR2 = join3(".pstdio", "tickets");
480
496
  var TICKET_FILES_DIR2 = "files";
481
497
  var escapeYamlScalar = (value) => value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n");
482
498
  var buildTicketFrontmatter = (fields) => {
@@ -522,7 +538,7 @@ ${body}`;
522
538
  };
523
539
  var toRelativeFilePath = (baseDir, absolutePath) => relative2(baseDir, absolutePath).split("\\").join("/");
524
540
  var resolveTicketDir2 = (rootPath, shorthand) => {
525
- const exactDir = join2(rootPath, TICKETS_DIR2, shorthand);
541
+ const exactDir = join3(rootPath, TICKETS_DIR2, shorthand);
526
542
  if (!existsSync2(exactDir))
527
543
  return null;
528
544
  if (!statSync2(exactDir).isDirectory()) {
@@ -532,8 +548,8 @@ var resolveTicketDir2 = (rootPath, shorthand) => {
532
548
  };
533
549
  var writeTicketFile2 = (rootPath, shorthand, content, overwrite = true) => {
534
550
  const existingDir = resolveTicketDir2(rootPath, shorthand);
535
- const dir = existingDir ?? join2(rootPath, TICKETS_DIR2, shorthand);
536
- const filePath = join2(dir, "ticket.md");
551
+ const dir = existingDir ?? join3(rootPath, TICKETS_DIR2, shorthand);
552
+ const filePath = join3(dir, "ticket.md");
537
553
  if (!overwrite && existsSync2(filePath)) {
538
554
  throw new Error(`Local file already exists: ${toRelativeFilePath(rootPath, filePath)}. Use force to overwrite.`);
539
555
  }
@@ -545,7 +561,7 @@ var resolveTicketAttachmentPath = (rootPath, shorthand, fileName) => {
545
561
  const ticketDir = resolveTicketDir2(rootPath, shorthand);
546
562
  if (!ticketDir)
547
563
  throw new Error(`Ticket directory not found for ${shorthand}`);
548
- const filesDir = join2(ticketDir, TICKET_FILES_DIR2);
564
+ const filesDir = join3(ticketDir, TICKET_FILES_DIR2);
549
565
  const targetPath = resolve2(filesDir, fileName);
550
566
  const rel = relative2(filesDir, targetPath);
551
567
  if (isAbsolute2(rel) || rel.startsWith("..")) {
@@ -678,20 +694,20 @@ var updateTicketWhenAllAttemptsMatch = async (ctx, input) => {
678
694
  };
679
695
  // src/plugins/helpers/worktree-bootstrap.ts
680
696
  import { cpSync, existsSync as existsSync3, mkdirSync as mkdirSync3 } from "node:fs";
681
- import { join as join3 } from "node:path";
697
+ import { join as join4 } from "node:path";
682
698
  var AGENT_DIRS = [".claude", ".opencode", ".agents"];
683
699
  var bootstrapWorktree = async (ctx, input) => {
684
700
  const { repoPath, worktreePath, ticketId } = input;
685
- const repoConfig = join3(repoPath, ".pstdio", "config.json");
686
- const worktreeConfigDir = join3(worktreePath, ".pstdio");
687
- const worktreeConfig = join3(worktreeConfigDir, "config.json");
701
+ const repoConfig = join4(repoPath, ".pstdio", "config.json");
702
+ const worktreeConfigDir = join4(worktreePath, ".pstdio");
703
+ const worktreeConfig = join4(worktreeConfigDir, "config.json");
688
704
  if (existsSync3(repoConfig)) {
689
705
  mkdirSync3(worktreeConfigDir, { recursive: true });
690
706
  cpSync(repoConfig, worktreeConfig);
691
707
  }
692
708
  for (const agentDir of AGENT_DIRS) {
693
- const fromDir = join3(repoPath, agentDir);
694
- const toDir = join3(worktreePath, agentDir);
709
+ const fromDir = join4(repoPath, agentDir);
710
+ const toDir = join4(worktreePath, agentDir);
695
711
  if (!existsSync3(fromDir))
696
712
  continue;
697
713
  mkdirSync3(toDir, { recursive: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pstdio/sdk",
3
- "version": "0.3.0",
3
+ "version": "0.4.2",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/pufflyai/prompt-studio"
@@ -25,6 +25,10 @@
25
25
  "import": "./dist/client/index.js",
26
26
  "types": "./dist/client/index.d.ts"
27
27
  },
28
+ "./extensions": {
29
+ "import": "./dist/extensions/index.js",
30
+ "types": "./dist/extensions/index.d.ts"
31
+ },
28
32
  "./plugins": {
29
33
  "import": "./dist/plugins/index.js",
30
34
  "types": "./dist/plugins/index.d.ts"
@@ -40,7 +44,7 @@
40
44
  },
41
45
  "scripts": {
42
46
  "build": "rm -rf ./dist && bun run build:js && bun run build:types",
43
- "build:js": "bun build ./src/api/index.ts ./src/client/index.ts ./src/plugins/index.ts ./src/prompts/index.ts ./src/hooks/index.ts ./src/resources/index.ts --outdir ./dist --root ./src --target node --format esm --packages external",
47
+ "build:js": "bun build ./src/api/index.ts ./src/client/index.ts ./src/extensions/index.ts ./src/plugins/index.ts ./src/prompts/index.ts ./src/hooks/index.ts ./src/resources/index.ts --outdir ./dist --root ./src --target node --format esm --packages external",
44
48
  "build:types": "tsc --project ./tsconfig.build.json",
45
49
  "prepack": "bun run build",
46
50
  "typecheck": "tsc --noEmit",