@keystrokehq/cli 0.0.127 → 0.0.129

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/dist/index.mjs CHANGED
@@ -2103,6 +2103,10 @@ const CreateProjectRequestSchema = object({
2103
2103
  name: string().trim().min(1),
2104
2104
  description: string().trim().min(1).optional()
2105
2105
  });
2106
+ const UpdateProjectRequestSchema = object({
2107
+ name: string().trim().min(1).optional(),
2108
+ description: string().trim().optional()
2109
+ }).refine((data) => data.name !== void 0 || data.description !== void 0, { message: "At least one field is required" });
2106
2110
  const CreateProjectResponseSchema = object({ project: ProjectSchema });
2107
2111
  const ProjectResponseSchema = object({ project: ProjectSchema });
2108
2112
  const ProjectReachabilityResponseSchema = object({ reachable: boolean() });
@@ -2670,6 +2674,25 @@ const WorkflowSummaryListResponseSchema = array(WorkflowSummarySchema);
2670
2674
  const WorkflowSummaryDetailResponseSchema = WorkflowSummarySchema.nullable();
2671
2675
  const SkillSummaryListResponseSchema = array(SkillSummarySchema);
2672
2676
  const SkillSummaryDetailResponseSchema = SkillSummarySchema.nullable();
2677
+ const RecentResourceKindSchema = _enum([
2678
+ "agent",
2679
+ "workflow",
2680
+ "skill"
2681
+ ]);
2682
+ const RecentResourceSourceSchema = _enum(["owned", "shared"]);
2683
+ const RecentResourceListResponseSchema = array(object({
2684
+ id: string().min(1),
2685
+ resourceKind: RecentResourceKindSchema,
2686
+ resourceId: string().min(1),
2687
+ name: string().min(1),
2688
+ description: string().optional(),
2689
+ projectId: string().min(1),
2690
+ projectName: string().min(1),
2691
+ sourcePath: string().min(1).optional(),
2692
+ source: RecentResourceSourceSchema,
2693
+ lastOpenedAt: string().min(1),
2694
+ lastModifiedAt: string().min(1)
2695
+ }));
2673
2696
  const isoDateTime = string().datetime();
2674
2697
  const sha256Hex = string().regex(/^[a-f0-9]{64}$/, "Expected a lowercase hex sha256 digest");
2675
2698
  /**
@@ -5096,16 +5119,22 @@ function createProjectsResource(http) {
5096
5119
  throw await toPlatformError(error);
5097
5120
  }
5098
5121
  },
5099
- update: mock({
5100
- domain: "projects",
5101
- method: "update",
5102
- plannedEndpoint: "PATCH /api/projects/:id"
5103
- }, async (projectId, patch) => {
5104
- return {
5105
- id: projectId,
5106
- ...patch
5107
- };
5108
- }),
5122
+ async update(projectId, patch) {
5123
+ const body = UpdateProjectRequestSchema.parse(patch);
5124
+ try {
5125
+ const data = await http.patch(`/api/projects/${encodeURIComponent(projectId)}`, { json: body }).json();
5126
+ return ProjectResponseSchema.parse(data).project;
5127
+ } catch (error) {
5128
+ throw await toPlatformError(error);
5129
+ }
5130
+ },
5131
+ async delete(projectId) {
5132
+ try {
5133
+ await http.delete(`/api/projects/${encodeURIComponent(projectId)}`);
5134
+ } catch (error) {
5135
+ throw await toPlatformError(error);
5136
+ }
5137
+ },
5109
5138
  async checkReachability(projectId) {
5110
5139
  try {
5111
5140
  const data = await http.get(`/api/projects/${encodeURIComponent(projectId)}/reachability`, { timeout: PROJECT_REACHABILITY_REQUEST_TIMEOUT_MS }).json();
@@ -5176,6 +5205,16 @@ function createSkillsResource(http) {
5176
5205
  }
5177
5206
  };
5178
5207
  }
5208
+ function createRecentsResource(http) {
5209
+ return { async list() {
5210
+ try {
5211
+ const data = await http.get("/api/recents").json();
5212
+ return RecentResourceListResponseSchema.parse(data);
5213
+ } catch (error) {
5214
+ throw await toPlatformError(error);
5215
+ }
5216
+ } };
5217
+ }
5179
5218
  const DEFAULT_PROJECT_SETTINGS = {
5180
5219
  description: "",
5181
5220
  defaultRole: "editor",
@@ -6704,21 +6743,6 @@ const workflowSeed = [{
6704
6743
  stepCount: 4,
6705
6744
  lastRunAt: "2026-05-31T16:40:00Z"
6706
6745
  }];
6707
- const skillSeed = [{
6708
- id: "skill-attio-sync",
6709
- name: "Attio Sync",
6710
- projectId: "project_personal_repo",
6711
- updatedAt: "2026-06-01T18:05:00Z",
6712
- description: "Enrich company and contact records from Attio.",
6713
- sourcePath: ".agents/skills/attio-sync/SKILL.md"
6714
- }, {
6715
- id: "skill-doc-coauthor",
6716
- name: "Doc Co-author",
6717
- projectId: "project_personal_repo",
6718
- updatedAt: "2026-05-30T10:24:00Z",
6719
- description: "Collaborative writing, editing, and version tracking for docs.",
6720
- sourcePath: ".agents/skills/doc-coauthor/SKILL.md"
6721
- }];
6722
6746
  const deploymentSeed = [{
6723
6747
  id: "deployment-v002",
6724
6748
  projectId: "project_personal_repo",
@@ -6814,75 +6838,6 @@ const apiKeySeed = [
6814
6838
  }
6815
6839
  ];
6816
6840
  let credentialRecords = [...credentialSeed];
6817
- const recentProjectNameById = { project_personal_repo: "Blake's Project" };
6818
- function laterIso(a, b) {
6819
- return new Date(a).getTime() >= new Date(b).getTime() ? a : b;
6820
- }
6821
- function hoursBefore(iso, hours) {
6822
- return (/* @__PURE__ */ new Date(new Date(iso).getTime() - hours * 36e5)).toISOString();
6823
- }
6824
- function buildRecentResourceSeed() {
6825
- const agentRecents = agentSeed.map((agent, index) => {
6826
- const lastModifiedAt = agent.updatedAt;
6827
- const lastOpenedAt = hoursBefore(lastModifiedAt, index * 5 + 2);
6828
- return {
6829
- id: `recent-agent-${agent.id}`,
6830
- resourceKind: "agent",
6831
- resourceId: agent.id,
6832
- name: agent.name,
6833
- description: agent.description,
6834
- projectId: agent.projectId,
6835
- projectName: recentProjectNameById[agent.projectId] ?? agent.projectId,
6836
- sourcePath: agent.sourcePath,
6837
- source: "owned",
6838
- lastOpenedAt,
6839
- lastModifiedAt
6840
- };
6841
- });
6842
- const workflowRecents = workflowSeed.map((workflow, index) => {
6843
- const lastModifiedAt = workflow.updatedAt;
6844
- const lastOpenedAt = hoursBefore(lastModifiedAt, index * 4 + 6);
6845
- return {
6846
- id: `recent-workflow-${workflow.id}`,
6847
- resourceKind: "workflow",
6848
- resourceId: workflow.id,
6849
- name: workflow.name,
6850
- description: workflow.description,
6851
- projectId: workflow.projectId,
6852
- projectName: recentProjectNameById[workflow.projectId] ?? workflow.projectId,
6853
- sourcePath: workflow.sourcePath,
6854
- source: "owned",
6855
- lastOpenedAt,
6856
- lastModifiedAt
6857
- };
6858
- });
6859
- const skillRecents = skillSeed.map((skill, index) => {
6860
- const lastModifiedAt = skill.updatedAt;
6861
- const lastOpenedAt = hoursBefore(lastModifiedAt, index * 3 + 1);
6862
- return {
6863
- id: `recent-skill-${skill.id}`,
6864
- resourceKind: "skill",
6865
- resourceId: skill.id,
6866
- name: skill.name,
6867
- description: skill.description,
6868
- projectId: skill.projectId,
6869
- projectName: recentProjectNameById[skill.projectId] ?? skill.projectId,
6870
- sourcePath: skill.sourcePath,
6871
- source: "owned",
6872
- lastOpenedAt,
6873
- lastModifiedAt
6874
- };
6875
- });
6876
- return [
6877
- ...agentRecents,
6878
- ...workflowRecents,
6879
- ...skillRecents
6880
- ].sort((left, right) => {
6881
- const leftAt = laterIso(left.lastOpenedAt, left.lastModifiedAt);
6882
- const rightAt = laterIso(right.lastOpenedAt, right.lastModifiedAt);
6883
- return new Date(rightAt).getTime() - new Date(leftAt).getTime();
6884
- });
6885
- }
6886
6841
  function createMockApiKeySecret() {
6887
6842
  const secret = `sk_${`${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`}`;
6888
6843
  return {
@@ -7106,13 +7061,6 @@ function createApiKeysResource() {
7106
7061
  })
7107
7062
  };
7108
7063
  }
7109
- function createRecentsResource() {
7110
- return { list: mock({
7111
- domain: "recents",
7112
- method: "list",
7113
- plannedEndpoint: "GET /api/recents"
7114
- }, async () => buildRecentResourceSeed()) };
7115
- }
7116
7064
  const historyProjectNameById = { project_personal_repo: "Blake's Project" };
7117
7065
  const MOCK_ACTOR = {
7118
7066
  userId: "user_blake",
@@ -8633,7 +8581,7 @@ function createPlatformClient(options) {
8633
8581
  members: createMembersResource(http),
8634
8582
  invitations: createInvitationsResource(http),
8635
8583
  apiKeys: createApiKeysResource(),
8636
- recents: createRecentsResource(),
8584
+ recents: createRecentsResource(http),
8637
8585
  userPreferences: createUserPreferencesResource({ getCurrentUserId: options.getCurrentUserId }),
8638
8586
  userAvatar: createUserAvatarResource(http),
8639
8587
  organizationSidebarBranding: createOrganizationSidebarBrandingResource({ getActiveOrganizationId: () => activeOrganizationId }),
@@ -8833,6 +8781,9 @@ function setCliTargetOptions(options) {
8833
8781
  function getCliTargetOptions() {
8834
8782
  return targetOptions;
8835
8783
  }
8784
+ function resolveActiveProjectId(config) {
8785
+ return getCliTargetOptions().projectId ?? config.get("activeProjectId");
8786
+ }
8836
8787
  //#endregion
8837
8788
  //#region src/errors/example-input.ts
8838
8789
  function exampleValueFromValidationMessage(message) {
@@ -9632,8 +9583,7 @@ async function runDeploy(options) {
9632
9583
  function registerDeployCommand(program) {
9633
9584
  program.command("deploy").description("Build, upload, and deploy the project to the platform").option("--dir <path>", "Project directory", process.cwd()).option("--skip-build", "Upload the existing dist/ without rebuilding").action(async (options) => {
9634
9585
  try {
9635
- const config = createCliConfig();
9636
- const projectId = getCliTargetOptions().projectId ?? config.get("activeProjectId");
9586
+ const projectId = resolveActiveProjectId(createCliConfig());
9637
9587
  if (!projectId) throw new Error("Usage: keystroke deploy --project <id>");
9638
9588
  await runDeploy({
9639
9589
  dir: options.dir,
@@ -10216,10 +10166,23 @@ async function runProjectCreate(config, input) {
10216
10166
  writeInactiveDeployHints([project]);
10217
10167
  });
10218
10168
  }
10169
+ async function runProjectUpdate(config, input) {
10170
+ await withActivePlatformClient(config, async (platform) => {
10171
+ const { projectId, ...patch } = input;
10172
+ const project = await platform.projects.update(projectId, patch);
10173
+ process.stdout.write(`${JSON.stringify({ project }, null, 2)}\n`);
10174
+ });
10175
+ }
10176
+ async function runProjectDelete(config, projectId) {
10177
+ await withActivePlatformClient(config, async (platform) => {
10178
+ await platform.projects.delete(projectId);
10179
+ process.stdout.write(`${JSON.stringify({ deleted: projectId }, null, 2)}\n`);
10180
+ });
10181
+ }
10219
10182
  //#endregion
10220
10183
  //#region src/commands/project/index.ts
10221
10184
  function registerProjectCommand(program) {
10222
- const project = program.command("project").description("List and create platform projects");
10185
+ const project = program.command("project").description("List, create, update, and delete platform projects");
10223
10186
  project.command("list").description("List projects in the active organization").action(async () => {
10224
10187
  const config = createCliConfig();
10225
10188
  try {
@@ -10247,6 +10210,40 @@ function registerProjectCommand(program) {
10247
10210
  process.exitCode = 1;
10248
10211
  }
10249
10212
  });
10213
+ project.command("update").description("Update a platform project's name and/or description").option("--name <name>", "Project name").option("--description <description>", "Project description").action(async (options) => {
10214
+ const config = createCliConfig();
10215
+ try {
10216
+ const projectId = resolveActiveProjectId(config);
10217
+ if (!projectId) throw new Error("Usage: keystroke --project <id> project update --name <name>");
10218
+ if (!options.name && options.description === void 0) throw new Error("At least one of --name or --description is required");
10219
+ await runProjectUpdate(config, {
10220
+ projectId,
10221
+ ...options.name ? { name: options.name } : {},
10222
+ ...options.description !== void 0 ? { description: options.description } : {}
10223
+ });
10224
+ } catch (error) {
10225
+ process.stderr.write(`${formatCliError(error, "Update project failed", {
10226
+ serverUrl: getPlatformUrl(config),
10227
+ webUrl: getWebUrl(config)
10228
+ })}\n`);
10229
+ process.exitCode = 1;
10230
+ }
10231
+ });
10232
+ project.command("delete").description("Delete a platform project").option("-y, --yes", "Skip confirmation prompt").action(async (options) => {
10233
+ const config = createCliConfig();
10234
+ try {
10235
+ const projectId = resolveActiveProjectId(config);
10236
+ if (!projectId) throw new Error("Usage: keystroke --project <id> project delete");
10237
+ if (!options.yes) throw new Error("Pass --yes to confirm project deletion");
10238
+ await runProjectDelete(config, projectId);
10239
+ } catch (error) {
10240
+ process.stderr.write(`${formatCliError(error, "Delete project failed", {
10241
+ serverUrl: getPlatformUrl(config),
10242
+ webUrl: getWebUrl(config)
10243
+ })}\n`);
10244
+ process.exitCode = 1;
10245
+ }
10246
+ });
10250
10247
  }
10251
10248
  //#endregion
10252
10249
  //#region src/commands/start.ts