@pstdio/sdk 0.10.0 → 0.11.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.
Files changed (43) hide show
  1. package/README.md +1 -4
  2. package/dist/api/extensions.d.ts +1 -1
  3. package/dist/api/index.d.ts +2 -5
  4. package/dist/api/workspaces.d.ts +2 -6
  5. package/dist/client/client.d.ts +0 -9
  6. package/dist/client/index.d.ts +0 -3
  7. package/dist/client/index.js +16 -110
  8. package/dist/client/projects.d.ts +2 -2
  9. package/dist/client/workspaces.d.ts +2 -4
  10. package/dist/extensions/command-outcome.d.ts +5 -0
  11. package/dist/extensions/define-extension-view.d.ts +25 -0
  12. package/dist/extensions/index.d.ts +6 -3
  13. package/dist/extensions/index.js +90 -35
  14. package/dist/extensions/kernel-slots.d.ts +7 -63
  15. package/dist/extensions/l10n.d.ts +10 -0
  16. package/dist/extensions/params.d.ts +2 -1
  17. package/dist/extensions/types/context.d.ts +51 -189
  18. package/dist/extensions/types/contributions.d.ts +133 -34
  19. package/dist/extensions/types/extension.d.ts +15 -6
  20. package/dist/extensions/types/index.d.ts +1 -0
  21. package/dist/extensions/types/params.d.ts +5 -2
  22. package/dist/extensions/types/tree-renderer.d.ts +89 -0
  23. package/dist/extensions/types/webview-capabilities.d.ts +30 -2
  24. package/dist/extensions/when.d.ts +9 -0
  25. package/dist/extensions/workbench-targets.d.ts +1 -11
  26. package/dist/hooks/entities.d.ts +7 -9
  27. package/dist/hooks/index.d.ts +0 -2
  28. package/dist/hooks/session.d.ts +2 -3
  29. package/dist/hooks/worktree.d.ts +4 -3
  30. package/dist/resources/index.d.ts +0 -3
  31. package/dist/resources/workspace.d.ts +0 -1
  32. package/package.json +1 -1
  33. package/dist/api/statuses.d.ts +0 -2
  34. package/dist/api/tags.d.ts +0 -2
  35. package/dist/api/tickets.d.ts +0 -26
  36. package/dist/client/statuses.d.ts +0 -24
  37. package/dist/client/tags.d.ts +0 -15
  38. package/dist/client/tickets.d.ts +0 -24
  39. package/dist/hooks/attempt.d.ts +0 -16
  40. package/dist/hooks/ticket.d.ts +0 -26
  41. package/dist/resources/status.d.ts +0 -2
  42. package/dist/resources/tag.d.ts +0 -2
  43. package/dist/resources/ticket.d.ts +0 -2
package/README.md CHANGED
@@ -51,10 +51,7 @@ const client = createClient({
51
51
  token: process.env.PSTDIO_API_TOKEN,
52
52
  });
53
53
 
54
- const tickets = await client.tickets.list("proj_123", {
55
- status: "wip",
56
- tag: ["backend", "bug"],
57
- });
54
+ const projects = await client.projects.list();
58
55
  ```
59
56
 
60
57
  ### Client options
@@ -1 +1 @@
1
- export type { CommandExecuteRequest, CommandExecuteResponse, ExtensionCommandRecord, ExtensionDataRendererRecord, ExtensionDiagnostic, ExtensionMenuContribution, ExtensionModeRecord, ExtensionNavigationRecord, ExtensionRecord, ExtensionRouteRecord, ExtensionSettingDefinitionRecord, ExtensionSettingsPanelRecord, ExtensionSettingValueRecord, ExtensionTreeItemContribution, ExtensionViewRecord, ListExtensionAppearanceResponse, ListExtensionCommandsResponse, ListExtensionSettingsResponse, ListProjectExtensionsResponse, ModeLayoutContributionRecord, ProjectExtensionInstance, UpdateExtensionSettingRequest, UpdateInstalledExtensionTemplateInput, UpdateInstalledExtensionTemplateResponse, WorkbenchExtensionDataRendererRecord, WorkbenchExtensionMetadata, } from "pstdio-api-contracts";
1
+ export type { CommandExecuteRequest, CommandExecuteResponse, ExtensionCommandPaletteContribution, ExtensionCommandPaletteResourceRecord, ExtensionCommandRecord, ExtensionDataRendererRecord, ExtensionDiagnostic, ExtensionKeybindingRecord, ExtensionMenuContribution, ExtensionModeRecord, ExtensionNavigationRecord, ExtensionRecord, ExtensionRouteRecord, ExtensionSettingDefinitionRecord, ExtensionSettingsPanelRecord, ExtensionSettingValueRecord, ExtensionTreeItemContribution, ExtensionTreeRendererRecord, ExtensionViewRecord, ListExtensionAppearanceResponse, ListExtensionCommandsResponse, ListExtensionSettingsResponse, ListProjectExtensionsResponse, LocalizableString, ModeLayoutContributionRecord, ProjectExtensionInstance, UpdateExtensionSettingRequest, UpdateInstalledExtensionTemplateInput, UpdateInstalledExtensionTemplateResponse, WorkbenchExtensionCommandPaletteResourceRecord, WorkbenchExtensionDataRendererRecord, WorkbenchExtensionMetadata, WorkbenchExtensionTreeRendererRecord, } from "pstdio-api-contracts";
@@ -1,11 +1,8 @@
1
1
  export type { SetupAgentInput, SetupAvailableAgentsInput, UpdateAgentInput } from "./agents";
2
- export type { CommandExecuteRequest, CommandExecuteResponse, ExtensionCommandRecord, ExtensionDataRendererRecord, ExtensionDiagnostic, ExtensionMenuContribution, ExtensionModeRecord, ExtensionNavigationRecord, ExtensionRecord, ExtensionRouteRecord, ExtensionSettingDefinitionRecord, ExtensionSettingsPanelRecord, ExtensionSettingValueRecord, ExtensionTreeItemContribution, ExtensionViewRecord, ListExtensionAppearanceResponse, ListExtensionCommandsResponse, ListExtensionSettingsResponse, ListProjectExtensionsResponse, ProjectExtensionInstance, UpdateExtensionSettingRequest, UpdateInstalledExtensionTemplateInput, UpdateInstalledExtensionTemplateResponse, WorkbenchExtensionDataRendererRecord, WorkbenchExtensionMetadata, } from "./extensions";
2
+ export type { CommandExecuteRequest, CommandExecuteResponse, ExtensionCommandPaletteContribution, ExtensionCommandPaletteResourceRecord, ExtensionCommandRecord, ExtensionDataRendererRecord, ExtensionDiagnostic, ExtensionKeybindingRecord, ExtensionMenuContribution, ExtensionModeRecord, ExtensionNavigationRecord, ExtensionRecord, ExtensionRouteRecord, ExtensionSettingDefinitionRecord, ExtensionSettingsPanelRecord, ExtensionSettingValueRecord, ExtensionTreeItemContribution, ExtensionTreeRendererRecord, ExtensionViewRecord, ListExtensionAppearanceResponse, ListExtensionCommandsResponse, ListExtensionSettingsResponse, ListProjectExtensionsResponse, LocalizableString, ProjectExtensionInstance, UpdateExtensionSettingRequest, UpdateInstalledExtensionTemplateInput, UpdateInstalledExtensionTemplateResponse, WorkbenchExtensionCommandPaletteResourceRecord, WorkbenchExtensionDataRendererRecord, WorkbenchExtensionMetadata, WorkbenchExtensionTreeRendererRecord, } from "./extensions";
3
3
  export type { CreateProjectInput, RegisterRepoInput } from "./projects";
4
4
  export type { ApprovalInput, CreateSessionInput, FollowUpInput, ResolveSessionIdInput, ResolveSessionIdResponse, SessionConversationResponse, } from "./sessions";
5
5
  export type { Settings, UpdateSettingsInput } from "./settings";
6
6
  export type { UpdateSkillInput } from "./skills";
7
- export type { CreateAttemptStatusInput, CreateStatusInput } from "./statuses";
8
- export type { CreateTagInput, CreateTagOptionInput, UpdateTagInput, UpdateTagOptionInput } from "./tags";
9
7
  export type { CreateTemplateInput, UpdateTemplateInput } from "./templates";
10
- export type { CreateTicketAttemptInput, CreateTicketInput, ListTicketsInput, TicketAttemptMode, TicketAttemptResponse, UpdateTicketInput, UpdateWhenAttemptStatusInput, UpdateWhenAttemptStatusResponse, UploadTicketFileInput, } from "./tickets";
11
- export type { CreateWorkspaceInput, RemoveWorktreeResponse, UpdateAttemptStatusInput, UpdateAttemptStatusResponse, } from "./workspaces";
8
+ export type { CreateWorkspaceInput, RemoveWorktreeResponse, RenameWorkspaceInput } from "./workspaces";
@@ -1,10 +1,6 @@
1
- import type { CreateWorkspaceInput as ContractCreateWorkspaceInput, ListWorkspaceActivityInput as ContractListWorkspaceActivityInput, ListWorkspaceActivityResponse as ContractListWorkspaceActivityResponse, RemoveWorktreeResponse as ContractRemoveWorktreeResponse, UpdateAttemptStatusInput as ContractUpdateAttemptStatusInput, UpdateAttemptStatusResponse as ContractUpdateAttemptStatusResponse } from "pstdio-api-contracts";
2
- /** @deprecated Requires legacy ticket-workspace linkage. Ticket ownership is moving to the pstdio tickets extension. */
1
+ import type { CreateWorkspaceInput as ContractCreateWorkspaceInput, ListWorkspaceActivityInput as ContractListWorkspaceActivityInput, ListWorkspaceActivityResponse as ContractListWorkspaceActivityResponse, RemoveWorktreeResponse as ContractRemoveWorktreeResponse, RenameWorkspaceInput as ContractRenameWorkspaceInput } from "pstdio-api-contracts";
3
2
  export type CreateWorkspaceInput = ContractCreateWorkspaceInput;
4
3
  export type ListWorkspaceActivityInput = ContractListWorkspaceActivityInput;
5
4
  export type ListWorkspaceActivityResponse = ContractListWorkspaceActivityResponse;
6
5
  export type RemoveWorktreeResponse = ContractRemoveWorktreeResponse;
7
- /** @deprecated Legacy ticket attempt status mutation. Workspace status automation is extension-owned. */
8
- export type UpdateAttemptStatusInput = ContractUpdateAttemptStatusInput;
9
- /** @deprecated Legacy ticket attempt status mutation. Workspace status automation is extension-owned. */
10
- export type UpdateAttemptStatusResponse = ContractUpdateAttemptStatusResponse;
6
+ export type RenameWorkspaceInput = ContractRenameWorkspaceInput;
@@ -5,22 +5,13 @@ import type { ClientOptions } from "./request";
5
5
  import { type SessionClient } from "./sessions";
6
6
  import { type SettingsClient } from "./settings";
7
7
  import { type SkillClient } from "./skills";
8
- import { type StatusClient } from "./statuses";
9
8
  import { type SyncClient } from "./sync";
10
- import { type TagClient } from "./tags";
11
9
  import { type TemplateClient } from "./templates";
12
- import { type TicketClient } from "./tickets";
13
10
  import { type WorkspaceClient } from "./workspaces";
14
11
  export type PstdioClient = {
15
12
  projects: ProjectClient;
16
- /** @deprecated Legacy core ticket client. Ticket data is owned by the pstdio tickets extension. */
17
- tickets: TicketClient;
18
13
  workspaces: WorkspaceClient;
19
14
  sessions: SessionClient;
20
- /** @deprecated Legacy core ticket status client. Ticket statuses are owned by the pstdio tickets extension. */
21
- statuses: StatusClient;
22
- /** @deprecated Legacy core ticket tag client. Ticket tags are owned by the pstdio tickets extension. */
23
- tags: TagClient;
24
15
  templates: TemplateClient;
25
16
  skills: SkillClient;
26
17
  agents: AgentClient;
@@ -7,9 +7,6 @@ export type { ListSessionsInput, SessionClient, SessionStreamConnection, Session
7
7
  export type { SettingsClient } from "./settings";
8
8
  export type { SkillClient } from "./skills";
9
9
  export type { SseEvent } from "./sse";
10
- export type { StatusClient } from "./statuses";
11
10
  export { applySyncEvent, parseSyncDeleteEvent, type StartSyncInput, type SyncClient, type SyncConnection, type SyncRow, type SyncWriter, type SyncWriterProvider, } from "./sync";
12
- export type { TagClient } from "./tags";
13
11
  export type { TemplateClient } from "./templates";
14
- export type { TicketClient } from "./tickets";
15
12
  export type { WorkspaceClient } from "./workspaces";
@@ -107,19 +107,32 @@ var createRequestHeaders = (options, reqOpts = {}) => {
107
107
  headers.set("authorization", `Bearer ${options.token}`);
108
108
  return headers;
109
109
  };
110
+ var isBinaryBody = (body) => body instanceof ArrayBuffer || ArrayBuffer.isView(body);
111
+ var serializeRequestBody = (body) => {
112
+ if (body instanceof ArrayBuffer)
113
+ return body;
114
+ if (ArrayBuffer.isView(body)) {
115
+ if (body.buffer instanceof ArrayBuffer)
116
+ return body;
117
+ const copy = new Uint8Array(body.byteLength);
118
+ copy.set(new Uint8Array(body.buffer, body.byteOffset, body.byteLength));
119
+ return copy;
120
+ }
121
+ return JSON.stringify(body);
122
+ };
110
123
  var createRequest = (options) => {
111
124
  const baseUrl = resolveBaseUrl(options);
112
125
  const fetchFn = resolveFetch(options);
113
126
  return async (path, reqOpts = {}) => {
114
127
  const headers = createRequestHeaders(options, {
115
128
  headers: reqOpts.headers,
116
- hasJsonBody: reqOpts.body !== undefined
129
+ hasJsonBody: reqOpts.body !== undefined && !isBinaryBody(reqOpts.body)
117
130
  });
118
131
  const url = resolveClientUrl(baseUrl, path);
119
132
  const response = await fetchFn(url, {
120
133
  method: reqOpts.method ?? "GET",
121
134
  headers: Object.fromEntries(headers.entries()),
122
- body: reqOpts.body !== undefined ? JSON.stringify(reqOpts.body) : undefined,
135
+ body: reqOpts.body !== undefined ? serializeRequestBody(reqOpts.body) : undefined,
123
136
  signal: reqOpts.signal,
124
137
  cache: reqOpts.cache
125
138
  });
@@ -288,19 +301,6 @@ var createSkillClient = (request) => ({
288
301
  updatePreferences: (projectId, skillName, input) => request(`/v1/projects/${projectId}/skills/${skillName}`, { method: "PUT", body: input })
289
302
  });
290
303
 
291
- // src/client/statuses.ts
292
- var createStatusClient = (request) => ({
293
- list: (projectId) => request(`/v1/projects/${projectId}/statuses`),
294
- create: (projectId, input) => request(`/v1/projects/${projectId}/statuses`, { method: "POST", body: input }),
295
- update: (projectId, statusId, input) => request(`/v1/projects/${projectId}/statuses/${statusId}`, { method: "PATCH", body: input }),
296
- setDefault: (projectId, statusId) => request(`/v1/projects/${projectId}/statuses/${statusId}/set-default`, { method: "PATCH" }),
297
- delete: (projectId, statusId) => request(`/v1/projects/${projectId}/statuses/${statusId}`, { method: "DELETE" }),
298
- listAttemptStatuses: (projectId) => request(`/v1/projects/${projectId}/attempt-statuses`),
299
- createAttemptStatus: (projectId, input) => request(`/v1/projects/${projectId}/attempt-statuses`, { method: "POST", body: input }),
300
- updateAttemptStatus: (projectId, statusId, input) => request(`/v1/projects/${projectId}/attempt-statuses/${statusId}`, { method: "PATCH", body: input }),
301
- deleteAttemptStatus: (projectId, statusId) => request(`/v1/projects/${projectId}/attempt-statuses/${statusId}`, { method: "DELETE" })
302
- });
303
-
304
304
  // src/client/sync.ts
305
305
  var DEFAULT_HEARTBEAT_INTERVAL_MS = 1e4;
306
306
  var DEFAULT_HEARTBEAT_THRESHOLD = 3;
@@ -432,17 +432,6 @@ var createSyncClient = (clientOptions) => ({
432
432
  }
433
433
  });
434
434
 
435
- // src/client/tags.ts
436
- var createTagClient = (request) => ({
437
- list: (projectId) => request(`/v1/projects/${projectId}/ticket-tags`),
438
- create: (projectId, input) => request(`/v1/projects/${projectId}/ticket-tags`, { method: "POST", body: input }),
439
- update: (projectId, tagId, input) => request(`/v1/projects/${projectId}/ticket-tags/${tagId}`, { method: "PATCH", body: input }),
440
- delete: (projectId, tagId) => request(`/v1/projects/${projectId}/ticket-tags/${tagId}`, { method: "DELETE" }),
441
- createOption: (projectId, tagId, input) => request(`/v1/projects/${projectId}/ticket-tags/${tagId}/options`, { method: "POST", body: input }),
442
- updateOption: (projectId, tagId, optionId, input) => request(`/v1/projects/${projectId}/ticket-tags/${tagId}/options/${optionId}`, { method: "PATCH", body: input }),
443
- deleteOption: (projectId, tagId, optionId) => request(`/v1/projects/${projectId}/ticket-tags/${tagId}/options/${optionId}`, { method: "DELETE" })
444
- });
445
-
446
435
  // src/client/templates.ts
447
436
  var createTemplateClient = (request) => ({
448
437
  list: (projectId) => request(`/v1/projects/${projectId}/templates`),
@@ -452,86 +441,6 @@ var createTemplateClient = (request) => ({
452
441
  delete: (projectId, templateId) => request(`/v1/projects/${projectId}/templates/${templateId}`, { method: "DELETE" })
453
442
  });
454
443
 
455
- // src/client/tickets.ts
456
- var resolveBaseUrl2 = (options) => options.baseUrl ?? (typeof process !== "undefined" ? process.env.PSTDIO_API_URL : undefined) ?? "http://localhost:19840";
457
- var readErrorMessage2 = async (response) => {
458
- const errorBody = await response.json().catch(() => null);
459
- if (errorBody && typeof errorBody === "object" && errorBody !== null && "error" in errorBody) {
460
- return String(errorBody.error);
461
- }
462
- return `Request failed: ${response.status}`;
463
- };
464
- var buildTicketsQuery = (projectId, input = {}) => {
465
- const params = new URLSearchParams({ project_id: projectId });
466
- if (input.status)
467
- params.append("status", input.status);
468
- if (Array.isArray(input.tag)) {
469
- for (const tag of input.tag)
470
- params.append("tag", tag);
471
- } else if (input.tag) {
472
- params.append("tag", input.tag);
473
- }
474
- if (input.archived !== undefined)
475
- params.append("archived", String(input.archived));
476
- if (input.draft !== undefined)
477
- params.append("draft", String(input.draft));
478
- if (input.parent_id)
479
- params.append("parent_id", input.parent_id);
480
- if (input.shorthand)
481
- params.append("shorthand", input.shorthand);
482
- if (input.search)
483
- params.append("search", input.search);
484
- return params.toString();
485
- };
486
- var buildActivityQuery = (input = {}) => {
487
- const params = new URLSearchParams;
488
- if (input.resource_type)
489
- params.append("resource_type", input.resource_type);
490
- if (input.event_type)
491
- params.append("event_type", input.event_type);
492
- if (input.from)
493
- params.append("from", input.from);
494
- if (input.to)
495
- params.append("to", input.to);
496
- if (input.cursor)
497
- params.append("cursor", input.cursor);
498
- if (input.limit !== undefined)
499
- params.append("limit", String(input.limit));
500
- return params.toString();
501
- };
502
- var createTicketClient = (request, options = {}) => ({
503
- list: (projectId, input) => request(`/v1/tickets?${buildTicketsQuery(projectId, input)}`),
504
- get: (ticketId) => request(`/v1/tickets/${ticketId}`),
505
- create: (input) => request("/v1/tickets", { method: "POST", body: input }),
506
- update: (ticketId, input) => request(`/v1/tickets/${ticketId}`, { method: "PATCH", body: input }),
507
- delete: (ticketId) => request(`/v1/tickets/${ticketId}`, { method: "DELETE" }),
508
- createAttempt: (ticketId, input) => request(`/v1/tickets/${ticketId}/attempts`, { method: "POST", body: input }),
509
- listActivity: (ticketId, input) => {
510
- const query = buildActivityQuery(input);
511
- return request(`/v1/tickets/${ticketId}/activity${query ? `?${query}` : ""}`);
512
- },
513
- listProjectActivity: (projectId, input) => {
514
- const query = buildActivityQuery(input);
515
- return request(`/v1/projects/${projectId}/activity${query ? `?${query}` : ""}`);
516
- },
517
- updateWhenAttemptStatus: (ticketId, input) => request(`/v1/tickets/${ticketId}/update-when-attempt-status`, { method: "POST", body: input }),
518
- listFiles: (ticketId) => request(`/v1/tickets/${ticketId}/files`),
519
- getFileContent: async (ticketId, fileId, requestOptions = {}) => {
520
- const baseUrl = resolveBaseUrl2(options);
521
- const fetchFn = options.fetch ?? globalThis.fetch;
522
- const headers = {};
523
- if (options.token)
524
- headers.authorization = `Bearer ${options.token}`;
525
- const response = await fetchFn(`${baseUrl}/v1/tickets/${encodeURIComponent(ticketId)}/files/${encodeURIComponent(fileId)}/content`, { cache: requestOptions.cache, headers, signal: requestOptions.signal });
526
- if (!response.ok) {
527
- throw new PstdioApiError(await readErrorMessage2(response), response.status);
528
- }
529
- return new Uint8Array(await response.arrayBuffer());
530
- },
531
- uploadFile: (ticketId, input) => request(`/v1/tickets/${ticketId}/files`, { method: "POST", body: input }),
532
- deleteFile: (ticketId, fileId) => request(`/v1/tickets/${ticketId}/files/${fileId}`, { method: "DELETE" })
533
- });
534
-
535
444
  // src/client/workspaces.ts
536
445
  var createWorkspaceClient = (request) => ({
537
446
  listActivity: (workspaceId, input = {}) => {
@@ -552,7 +461,7 @@ var createWorkspaceClient = (request) => ({
552
461
  list: (projectId) => request(`/v1/workspaces?project_id=${projectId}`),
553
462
  getByShorthand: (projectId, shorthand) => request(`/v1/workspaces/by-shorthand?project_id=${encodeURIComponent(projectId)}&shorthand=${encodeURIComponent(shorthand)}`),
554
463
  create: (input) => request("/v1/workspaces", { method: "POST", body: input }),
555
- updateAttemptStatus: (workspaceId, input) => request(`/v1/workspaces/${workspaceId}/attempt-status`, { method: "PATCH", body: input }),
464
+ rename: (workspaceId, input) => request(`/v1/workspaces/${workspaceId}`, { method: "PATCH", body: input }),
556
465
  removeWorktree: (workspaceId) => request(`/v1/workspaces/${workspaceId}/remove-worktree`, { method: "POST" }),
557
466
  delete: (workspaceId) => request(`/v1/workspaces/${workspaceId}`, { method: "DELETE" })
558
467
  });
@@ -562,11 +471,8 @@ var createClient = (options = {}) => {
562
471
  const request = createRequest(options);
563
472
  return {
564
473
  projects: createProjectClient(request),
565
- tickets: createTicketClient(request, options),
566
474
  workspaces: createWorkspaceClient(request),
567
475
  sessions: createSessionClient(request, options),
568
- statuses: createStatusClient(request),
569
- tags: createTagClient(request),
570
476
  templates: createTemplateClient(request),
571
477
  skills: createSkillClient(request),
572
478
  agents: createAgentClient(request),
@@ -1,4 +1,4 @@
1
- import type { CreateProjectInput, ListProjectActivityForTicketsInput, ListTicketActivityResponse, RegisterRepoInput, Repo } from "pstdio-api-contracts";
1
+ import type { CreateProjectInput, ListActivityResponse, ListProjectActivityInput, RegisterRepoInput, Repo } from "pstdio-api-contracts";
2
2
  import type { Project } from "../resources";
3
3
  import type { RequestFn } from "./request";
4
4
  export type ProjectClient = {
@@ -6,7 +6,7 @@ export type ProjectClient = {
6
6
  get(projectId: string): Promise<Project>;
7
7
  create(input: CreateProjectInput): Promise<Project>;
8
8
  delete(projectId: string): Promise<void>;
9
- listActivity(projectId: string, input?: ListProjectActivityForTicketsInput): Promise<ListTicketActivityResponse>;
9
+ listActivity(projectId: string, input?: ListProjectActivityInput): Promise<ListActivityResponse>;
10
10
  listRepos(projectId: string): Promise<Repo[]>;
11
11
  registerRepo(projectId: string, input: RegisterRepoInput): Promise<Repo>;
12
12
  removeRepo(projectId: string, repoId: string): Promise<void>;
@@ -1,13 +1,11 @@
1
- import type { CreateWorkspaceInput, ListWorkspaceActivityInput, ListWorkspaceActivityResponse, RemoveWorktreeResponse, UpdateAttemptStatusInput, UpdateAttemptStatusResponse } from "pstdio-api-contracts";
1
+ import type { CreateWorkspaceInput, ListWorkspaceActivityInput, ListWorkspaceActivityResponse, RemoveWorktreeResponse, RenameWorkspaceInput } from "pstdio-api-contracts";
2
2
  import type { Workspace, WorkspaceListItem } from "../resources";
3
3
  import type { RequestFn } from "./request";
4
4
  export type WorkspaceClient = {
5
5
  list(projectId: string): Promise<WorkspaceListItem[]>;
6
6
  getByShorthand(projectId: string, shorthand: string): Promise<Workspace>;
7
- /** @deprecated Requires legacy ticket-workspace linkage. Ticket ownership is moving to the pstdio tickets extension. */
8
7
  create(input: CreateWorkspaceInput): Promise<Workspace>;
9
- /** @deprecated Legacy ticket attempt status mutation. Workspace status automation is extension-owned. */
10
- updateAttemptStatus(workspaceId: string, input: UpdateAttemptStatusInput): Promise<UpdateAttemptStatusResponse>;
8
+ rename(workspaceId: string, input: RenameWorkspaceInput): Promise<Workspace>;
11
9
  listActivity(workspaceId: string, input?: ListWorkspaceActivityInput): Promise<ListWorkspaceActivityResponse>;
12
10
  removeWorktree(workspaceId: string): Promise<RemoveWorktreeResponse>;
13
11
  delete(workspaceId: string): Promise<void>;
@@ -0,0 +1,5 @@
1
+ import type { CommandOutcome } from "./types";
2
+ export type CommandResponse<TResult = unknown> = {
3
+ outcome: CommandOutcome<TResult>;
4
+ };
5
+ export declare const unwrapCommandOutcome: <TResult>(response: CommandResponse<TResult>, fallbackReason?: string) => TResult;
@@ -15,10 +15,35 @@ export type PropsStore<TProps = unknown> = {
15
15
  get: () => TProps;
16
16
  subscribe: (listener: (props: TProps) => void) => () => void;
17
17
  };
18
+ export interface WebviewFilesClient {
19
+ pick(opts?: {
20
+ accept?: string;
21
+ multiple?: boolean;
22
+ }): Promise<File[]>;
23
+ upload(input: {
24
+ name: string;
25
+ data: Uint8Array | ArrayBuffer;
26
+ mimeType?: string;
27
+ scope?: {
28
+ type: string;
29
+ id?: string;
30
+ };
31
+ }): Promise<import("./types/webview-capabilities").ExtensionBlobRef>;
32
+ list(input?: {
33
+ scope?: {
34
+ type: string;
35
+ id?: string;
36
+ };
37
+ }): Promise<import("./types/webview-capabilities").ExtensionBlobRef[]>;
38
+ delete(id: string): Promise<void>;
39
+ }
18
40
  export type ExtensionViewRenderContext<TProps = unknown> = {
19
41
  mount: HTMLElement;
20
42
  host: GuestHost;
43
+ files: WebviewFilesClient;
21
44
  propsStore: PropsStore<TProps>;
45
+ locale: string;
46
+ t: (key: string, defaultValue?: string, args?: Record<string, unknown>) => string;
22
47
  };
23
48
  export type ExtensionViewRender<TProps = unknown> = (context: ExtensionViewRenderContext<TProps>) => void | (() => void) | Promise<void | (() => void)>;
24
49
  export type ExtensionViewModule<TProps = unknown> = {
@@ -1,12 +1,15 @@
1
+ export { type CommandResponse, unwrapCommandOutcome } from "./command-outcome";
1
2
  export { defineCommand, defineHook, defineMiddleware } from "./define-command";
2
3
  export { defineExtension } from "./define-extension";
3
- export { defineExtensionView, type ExtensionViewModule, type ExtensionViewRender, type ExtensionViewRenderContext, type GuestHost, type PropsStore, } from "./define-extension-view";
4
- export type { AttemptStatusChangePayload, CommitPayload, ConflictPayload, MergePayload, RebasePayload, SessionLifecyclePayload, TicketArchivedEventPayload, TicketLifecyclePayload, TicketStatusChangePayload, WorktreeCreatedEventPayload, WorktreeRemovedPayload, } from "./kernel-slots";
5
- export { attemptStatusEvents, gitEvents, projectEvents, projectSlots, sessionEvents, sessionSlots, ticketEvents, ticketSlots, workspaceCommands, workspaceEvents, workspaceSlots, worktreeEvents, } from "./kernel-slots";
4
+ export { defineExtensionView, type ExtensionViewModule, type ExtensionViewRender, type ExtensionViewRenderContext, type GuestHost, type PropsStore, type WebviewFilesClient, } from "./define-extension-view";
5
+ export type { CommitPayload, ConflictPayload, MergePayload, RebasePayload, SessionLifecyclePayload, WorktreeCreatedEventPayload, WorktreeRemovedPayload, } from "./kernel-slots";
6
+ export { gitEvents, projectEvents, projectSlots, sessionEvents, sessionSlots, workspaceEvents, workspaceSlots, worktreeEvents, } from "./kernel-slots";
7
+ export { isLocalizedString, type Localizable, type LocalizedString, l10n } from "./l10n";
6
8
  export { packageAsset } from "./package-asset";
7
9
  export { params } from "./params";
8
10
  export { commandEvent, commandRef, commandsOf, eventRef } from "./refs";
9
11
  export type * from "./types";
10
12
  export { EXTENSION_API_VERSION } from "./types/extension";
11
13
  export { ALWAYS_AVAILABLE_WEBVIEW_CAPABILITIES, WEBVIEW_DECLARABLE_CAPABILITIES, WEBVIEW_HOST_CAPABILITIES, WEBVIEW_HOST_CAPABILITY_VERSION, } from "./types/webview-capabilities";
14
+ export { matchesResourceWhen } from "./when";
12
15
  export { getWorkbenchTargetDefinition, type WorkbenchAttachmentTarget, type WorkbenchContributionKind, type WorkbenchLayoutTarget, type WorkbenchMenuTarget, type WorkbenchModeLayoutTarget, type WorkbenchSettingsScope, type WorkbenchSettingsTarget, type WorkbenchTargetDefinition, type WorkbenchTargetGranularity, type WorkbenchTreeTarget, type WorkbenchViewTarget, workbenchMenuTargets, workbenchModeLayoutTargets, workbenchSettingsScopes, workbenchSettingsTargets, workbenchTargets, workbenchTreeTargets, workbenchViewTargets, } from "./workbench-targets";
@@ -1,3 +1,11 @@
1
+ // src/extensions/command-outcome.ts
2
+ var unwrapCommandOutcome = (response, fallbackReason = "Command failed.") => {
3
+ const { outcome } = response;
4
+ if (outcome.status !== "success") {
5
+ throw new Error(outcome.reason || fallbackReason);
6
+ }
7
+ return outcome.value;
8
+ };
1
9
  // src/extensions/define-command.ts
2
10
  var defineCommand = (definition) => definition;
3
11
  var defineMiddleware = (definition) => definition;
@@ -5,9 +13,66 @@ var defineHook = (definition) => definition;
5
13
  // src/extensions/define-extension.ts
6
14
  var defineExtension = (extension) => extension;
7
15
  // src/extensions/define-extension-view.ts
16
+ var pickFiles = (opts = {}) => new Promise((resolve, reject) => {
17
+ const input = document.createElement("input");
18
+ input.type = "file";
19
+ input.accept = opts.accept ?? "";
20
+ input.multiple = opts.multiple ?? false;
21
+ input.style.display = "none";
22
+ input.addEventListener("change", () => {
23
+ const files = input.files ? Array.from(input.files) : [];
24
+ input.remove();
25
+ resolve(files);
26
+ });
27
+ input.addEventListener("cancel", () => {
28
+ input.remove();
29
+ resolve([]);
30
+ });
31
+ input.addEventListener("error", () => {
32
+ input.remove();
33
+ reject(new Error("Could not pick files."));
34
+ });
35
+ document.body.appendChild(input);
36
+ input.click();
37
+ });
38
+ var createFilesClient = (host) => ({
39
+ pick: pickFiles,
40
+ upload: (input) => host.call("files.upload", input),
41
+ list: async (input) => {
42
+ const response = await host.call("files.list", input ?? {});
43
+ return response.files ?? [];
44
+ },
45
+ delete: (id) => host.call("files.delete", { id })
46
+ });
47
+ var readTranslationProps = (props) => {
48
+ const translations = typeof props === "object" && props !== null && "translations" in props ? props.translations : undefined;
49
+ if (typeof translations !== "object" || translations === null)
50
+ return null;
51
+ return translations;
52
+ };
53
+ var interpolate = (value, args) => Object.entries(args ?? {}).reduce((next, [key, replacement]) => next.replaceAll(`{{${key}}}`, String(replacement)), value);
54
+ var createTranslationApi = (propsStore) => {
55
+ const locale = () => readTranslationProps(propsStore.get())?.locale ?? "en";
56
+ const t = (key, defaultValue, args) => {
57
+ const translations = readTranslationProps(propsStore.get());
58
+ const value = translations?.bundle?.[key] ?? translations?.defaultBundle?.[key] ?? defaultValue ?? key;
59
+ return interpolate(value, args);
60
+ };
61
+ return { locale, t };
62
+ };
8
63
  var defineExtensionView = (definition) => ({
9
64
  mount: async (mount, host, propsStore) => {
10
- const cleanup = await definition.render({ mount, host, propsStore });
65
+ const translations = createTranslationApi(propsStore);
66
+ const cleanup = await definition.render({
67
+ mount,
68
+ host,
69
+ files: createFilesClient(host),
70
+ propsStore,
71
+ get locale() {
72
+ return translations.locale();
73
+ },
74
+ t: translations.t
75
+ });
11
76
  return typeof cleanup === "function" ? cleanup : () => {};
12
77
  }
13
78
  });
@@ -40,7 +105,6 @@ var projectSlots = {
40
105
  sidebar: defineSlot("project.sidebar", { kind: "view" }),
41
106
  headerPrimary: defineSlot("project.headerPrimary", { kind: "menu" }),
42
107
  headerOverflow: defineSlot("project.headerOverflow", { kind: "menu" }),
43
- commandPanel: defineSlot("project.commandPanel", { kind: "menu" }),
44
108
  settingsPanels: defineSlot("project.settingsPanels", { kind: "settings" })
45
109
  };
46
110
  var sessionSlots = {
@@ -48,10 +112,6 @@ var sessionSlots = {
48
112
  headerOverflow: defineSlot("session.headerOverflow", { kind: "menu" }),
49
113
  transcriptActions: defineSlot("session.transcriptActions", { kind: "menu" })
50
114
  };
51
- var ticketSlots = {
52
- headerPrimary: defineSlot("ticket.headerPrimary", { kind: "menu" }),
53
- headerOverflow: defineSlot("ticket.headerOverflow", { kind: "menu" })
54
- };
55
115
  var workspaceSlots = {
56
116
  headerPrimary: defineSlot("workspace.headerPrimary", { kind: "menu" }),
57
117
  headerOverflow: defineSlot("workspace.headerOverflow", { kind: "menu" }),
@@ -68,12 +128,6 @@ var sessionEvents = {
68
128
  failed: eventRef("session.failed"),
69
129
  completed: eventRef("session.completed")
70
130
  };
71
- var ticketEvents = {
72
- created: eventRef("ticket.created"),
73
- statusChanged: eventRef("ticket.statusChanged"),
74
- archived: eventRef("ticket.archived"),
75
- deleted: eventRef("ticket.deleted")
76
- };
77
131
  var workspaceEvents = {
78
132
  created: eventRef("workspace.created"),
79
133
  archived: eventRef("workspace.archived"),
@@ -89,12 +143,12 @@ var gitEvents = {
89
143
  merged: eventRef("git.merged"),
90
144
  conflicted: eventRef("git.conflicted")
91
145
  };
92
- var attemptStatusEvents = {
93
- changed: eventRef("attemptStatus.changed")
94
- };
95
- var workspaceCommands = {
96
- setAttemptStatus: commandRef("kernel.workspace.setAttemptStatus")
97
- };
146
+ // src/extensions/l10n.ts
147
+ var l10n = (key, defaultValue) => ({
148
+ $l10n: key,
149
+ ...defaultValue === undefined ? {} : { default: defaultValue }
150
+ });
151
+ var isLocalizedString = (value) => typeof value === "object" && value !== null && ("$l10n" in value) && typeof value.$l10n === "string";
98
152
  // src/extensions/package-asset.ts
99
153
  var packageAsset = (path, baseUrl) => ({
100
154
  kind: "package-asset",
@@ -124,7 +178,8 @@ var params = {
124
178
  templateType: options.type
125
179
  }),
126
180
  resource: (options) => ({ type: "resource", ...options }),
127
- json: (options) => ({ type: "json", ...options })
181
+ json: (options) => ({ type: "json", ...options }),
182
+ list: (options) => ({ type: "list", ...options })
128
183
  };
129
184
  // src/extensions/types/extension.ts
130
185
  var EXTENSION_API_VERSION = "1.0.0";
@@ -139,19 +194,25 @@ var WEBVIEW_DECLARABLE_CAPABILITIES = [
139
194
  "extension.settings.all",
140
195
  "extension.settings.get",
141
196
  "extension.settings.set",
142
- "extension.settings.delete"
197
+ "extension.settings.delete",
198
+ "files.upload",
199
+ "files.list",
200
+ "files.delete"
143
201
  ];
144
202
  var ALWAYS_AVAILABLE_WEBVIEW_CAPABILITIES = ["host.dispatchKeyboardEvent"];
145
203
  var WEBVIEW_HOST_CAPABILITIES = [
146
204
  ...WEBVIEW_DECLARABLE_CAPABILITIES,
147
205
  ...ALWAYS_AVAILABLE_WEBVIEW_CAPABILITIES
148
206
  ];
207
+ // src/extensions/when.ts
208
+ var matchesResourceWhen = (when, resourceType) => {
209
+ const resourceTypes = when?.resourceType;
210
+ if (!resourceTypes?.length)
211
+ return true;
212
+ return resourceType ? resourceTypes.includes(resourceType) : false;
213
+ };
149
214
  // src/extensions/workbench-targets.ts
150
- var workbenchMenuTargets = [
151
- "workbench.nav.actions",
152
- "workbench.nav.overflow",
153
- "workbench.commandPalette"
154
- ];
215
+ var workbenchMenuTargets = ["workbench.nav.actions", "workbench.nav.overflow"];
155
216
  var workbenchTreeTargets = [
156
217
  "workbench.left.tree",
157
218
  "workbench.main.left.tree",
@@ -185,12 +246,6 @@ var workbenchTargets = [
185
246
  granularity: "surface",
186
247
  rationale: "Secondary command surface in the host-owned nav (top) workbench chrome."
187
248
  },
188
- {
189
- id: "workbench.commandPalette",
190
- allowedKinds: ["menu"],
191
- granularity: "surface",
192
- rationale: "Global command discovery surface owned by the workbench."
193
- },
194
249
  {
195
250
  id: "workbench.left.tree",
196
251
  allowedKinds: ["treeItem"],
@@ -245,7 +300,6 @@ export {
245
300
  worktreeEvents,
246
301
  workspaceSlots,
247
302
  workspaceEvents,
248
- workspaceCommands,
249
303
  workbenchViewTargets,
250
304
  workbenchTreeTargets,
251
305
  workbenchTargets,
@@ -253,14 +307,16 @@ export {
253
307
  workbenchSettingsScopes,
254
308
  workbenchModeLayoutTargets,
255
309
  workbenchMenuTargets,
256
- ticketSlots,
257
- ticketEvents,
310
+ unwrapCommandOutcome,
258
311
  sessionSlots,
259
312
  sessionEvents,
260
313
  projectSlots,
261
314
  projectEvents,
262
315
  params,
263
316
  packageAsset,
317
+ matchesResourceWhen,
318
+ l10n,
319
+ isLocalizedString,
264
320
  gitEvents,
265
321
  getWorkbenchTargetDefinition,
266
322
  eventRef,
@@ -272,7 +328,6 @@ export {
272
328
  commandsOf,
273
329
  commandRef,
274
330
  commandEvent,
275
- attemptStatusEvents,
276
331
  WEBVIEW_HOST_CAPABILITY_VERSION,
277
332
  WEBVIEW_HOST_CAPABILITIES,
278
333
  WEBVIEW_DECLARABLE_CAPABILITIES,