@hasna/skills 0.5.0 → 0.5.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.
package/dist/index.js CHANGED
@@ -10254,12 +10254,106 @@ function primitiveHaystack(primitive) {
10254
10254
  function clone(value) {
10255
10255
  return value === undefined ? undefined : JSON.parse(JSON.stringify(value));
10256
10256
  }
10257
+ // src/lib/remote-workspace-selection.ts
10258
+ var record = (v) => !!v && typeof v === "object" && !Array.isArray(v);
10259
+ var uuid = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v);
10260
+ var text = (v, max = 1024) => typeof v === "string" && !!v.trim() && v.length <= max && !/[\p{Cc}\p{Cs}\u2028\u2029]/u.test(v);
10261
+ var role = (v) => typeof v === "string" && ["owner", "admin", "member", "viewer"].includes(v);
10262
+ var invalidWorkspaceResult = "The server returned an invalid workspace selection result.";
10263
+
10264
+ class WorkspaceContextInputError extends Error {
10265
+ constructor() {
10266
+ super("Provide the observed user ID and exact lowercase membership ID.");
10267
+ this.name = "WorkspaceContextInputError";
10268
+ }
10269
+ }
10270
+
10271
+ class WorkspaceIdentityMismatchError extends Error {
10272
+ constructor() {
10273
+ super("The verified account does not match the requested workspace context.");
10274
+ this.name = "WorkspaceIdentityMismatchError";
10275
+ }
10276
+ }
10277
+ function workspaceExpectedUserId(value) {
10278
+ if (!uuid(value))
10279
+ throw new WorkspaceContextInputError;
10280
+ return value;
10281
+ }
10282
+ function workspaceContext(value) {
10283
+ if (!record(value) || Object.keys(value).sort().join(",") !== "membershipId,userId" || !uuid(value.userId) || !uuid(value.membershipId))
10284
+ throw new WorkspaceContextInputError;
10285
+ return { userId: value.userId, membershipId: value.membershipId };
10286
+ }
10287
+ function invalid() {
10288
+ throw new Error(invalidWorkspaceResult);
10289
+ }
10290
+ function organization(v) {
10291
+ if (!record(v) || !uuid(v.id) || !text(v.slug) || !text(v.name))
10292
+ return invalid();
10293
+ return { id: v.id, slug: v.slug, name: v.name };
10294
+ }
10295
+ function parseAccountWorkspaces(value) {
10296
+ if (!record(value) || !Array.isArray(value.workspaces) || !value.workspaces.length || value.workspaces.length > 1000)
10297
+ return invalid();
10298
+ const workspaces = value.workspaces.map((v) => {
10299
+ if (!record(v) || !uuid(v.membershipId) || !role(v.role) || typeof v.current !== "boolean")
10300
+ return invalid();
10301
+ return { membershipId: v.membershipId, organization: organization(v.organization), role: v.role, current: v.current };
10302
+ });
10303
+ if (workspaces.filter((w) => w.current).length !== 1 || new Set(workspaces.map((w) => w.membershipId)).size !== workspaces.length || new Set(workspaces.map((w) => w.organization.id)).size !== workspaces.length)
10304
+ return invalid();
10305
+ return { workspaces };
10306
+ }
10307
+ function parseWorkspaceIdentity(value, expectedUserId) {
10308
+ if (!record(value))
10309
+ return invalid();
10310
+ const user = value.user;
10311
+ if (!record(user) || !uuid(user.id) || !uuid(user.membershipId) || !text(user.email, 320) || !(user.displayName === null || text(user.displayName)) || !role(user.role))
10312
+ return invalid();
10313
+ if (user.id !== expectedUserId)
10314
+ throw new WorkspaceIdentityMismatchError;
10315
+ return { user: { id: user.id, membershipId: user.membershipId, email: user.email, displayName: user.displayName, role: user.role }, organization: organization(value.organization) };
10316
+ }
10317
+ function sessionToken(value) {
10318
+ if (typeof value !== "string" || !value || value.length > 8192 || /[^\x21-\x7e]/.test(value) || value.startsWith("sk_"))
10319
+ return invalid();
10320
+ return value;
10321
+ }
10322
+ function parseWorkspaceSession(value, expected) {
10323
+ const identity = parseWorkspaceIdentity(value, expected.userId);
10324
+ if (identity.user.membershipId !== expected.membershipId)
10325
+ throw new WorkspaceIdentityMismatchError;
10326
+ return { token: sessionToken(value.token), ...identity };
10327
+ }
10328
+ function parseWorkspaceLogin(value, expectedUserId) {
10329
+ const user = record(value) && value.user;
10330
+ if (!record(value) || !record(user) || !uuid(user.id))
10331
+ return invalid();
10332
+ if (expectedUserId !== undefined && user.id !== expectedUserId)
10333
+ throw new WorkspaceIdentityMismatchError;
10334
+ return { token: sessionToken(value.token), userId: user.id };
10335
+ }
10336
+ var workspaceSelectionFailures = {
10337
+ INVALID_WORKSPACE_SELECTION: [400, "Provide only the exact membership ID from your workspace list."],
10338
+ SESSION_EXPIRED: [401, "Sign in again before selecting a workspace."],
10339
+ ACCOUNT_UNAVAILABLE: [403, "Account is unavailable."],
10340
+ INTERACTIVE_SESSION_REQUIRED: [403, "Interactive sign-in is required to select a workspace."],
10341
+ WORKSPACE_UNAVAILABLE: [404, "Workspace is unavailable. Refresh your workspace list."],
10342
+ WORKSPACE_BUSY: [503, "Workspace is busy. Refresh before retrying."]
10343
+ };
10344
+ function workspaceSelectionFailure(value, status) {
10345
+ if (!record(value) || typeof value.code !== "string" || !Object.hasOwn(workspaceSelectionFailures, value.code))
10346
+ return null;
10347
+ const code = value.code;
10348
+ return workspaceSelectionFailures[code][0] === status ? code : null;
10349
+ }
10350
+
10257
10351
  // src/lib/remote-workspace.ts
10258
- var record = (value) => !!value && typeof value === "object" && !Array.isArray(value);
10352
+ var record2 = (value) => !!value && typeof value === "object" && !Array.isArray(value);
10259
10353
  var cursor = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,512}$/.test(value);
10260
- var uuid = (value) => typeof value === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(value);
10354
+ var uuid2 = (value) => typeof value === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(value);
10261
10355
  function workspaceMembersQuery(options = {}) {
10262
- if (!record(options) || Object.keys(options).some((key) => key !== "limit" && key !== "cursor") || options.limit !== undefined && (!Number.isInteger(options.limit) || options.limit < 1 || options.limit > 100) || options.cursor !== undefined && !cursor(options.cursor))
10356
+ if (!record2(options) || Object.keys(options).some((key) => key !== "limit" && key !== "cursor") || options.limit !== undefined && (!Number.isInteger(options.limit) || options.limit < 1 || options.limit > 100) || options.cursor !== undefined && !cursor(options.cursor))
10263
10357
  throw new Error("Use a roster limit from 1 to 100 and an unchanged continuation cursor.");
10264
10358
  const query = new URLSearchParams;
10265
10359
  if (options.limit !== undefined)
@@ -10275,7 +10369,7 @@ function timestamp(value) {
10275
10369
  return Number.isFinite(time) && new Date(time).toISOString().slice(0, 23) === value.slice(0, 23);
10276
10370
  }
10277
10371
  function parseMember(row, fail) {
10278
- if (!record(row) || !uuid(row.membershipId) || !uuid(row.userId) || typeof row.email !== "string" || !row.email || !(row.displayName === null || typeof row.displayName === "string") || !isRole(row.role) || !timestamp(row.createdAt))
10372
+ if (!record2(row) || !uuid2(row.membershipId) || !uuid2(row.userId) || typeof row.email !== "string" || !row.email || !(row.displayName === null || typeof row.displayName === "string") || !isRole(row.role) || !timestamp(row.createdAt))
10279
10373
  return fail();
10280
10374
  return {
10281
10375
  membershipId: row.membershipId,
@@ -10295,12 +10389,12 @@ class WorkspaceMemberInputError extends Error {
10295
10389
  }
10296
10390
  }
10297
10391
  function mutationInput(membershipId, input, roleChange) {
10298
- if (typeof membershipId !== "string" || !uuid(membershipId) || membershipId !== membershipId.toLowerCase() || !record(input) || Object.keys(input).sort().join(",") !== (roleChange ? "expectedRole,role" : "expectedRole"))
10392
+ if (typeof membershipId !== "string" || !uuid2(membershipId) || membershipId !== membershipId.toLowerCase() || !record2(input) || Object.keys(input).sort().join(",") !== (roleChange ? "expectedRole,role" : "expectedRole"))
10299
10393
  throw new WorkspaceMemberInputError;
10300
- const expectedRole = input.expectedRole, role = roleChange ? input.role : undefined;
10301
- if (!isRole(expectedRole) || roleChange && !isRole(role))
10394
+ const expectedRole = input.expectedRole, role2 = roleChange ? input.role : undefined;
10395
+ if (!isRole(expectedRole) || roleChange && !isRole(role2))
10302
10396
  throw new WorkspaceMemberInputError;
10303
- return { membershipId, role, expectedRole };
10397
+ return { membershipId, role: role2, expectedRole };
10304
10398
  }
10305
10399
  function workspaceMemberRoleInput(membershipId, input) {
10306
10400
  const value = mutationInput(membershipId, input, true);
@@ -10311,19 +10405,19 @@ function workspaceMemberRemovalInput(membershipId, input) {
10311
10405
  return { membershipId: value.membershipId, body: { expectedRole: value.expectedRole } };
10312
10406
  }
10313
10407
  var invalidMemberResult = "The server returned an invalid workspace member result. Refresh the roster before another action.";
10314
- function parseWorkspaceMemberRoleResult(value, membershipId, role) {
10408
+ function parseWorkspaceMemberRoleResult(value, membershipId, role2) {
10315
10409
  const fail = () => {
10316
10410
  throw new Error(invalidMemberResult);
10317
10411
  };
10318
- if (!record(value) || !uuid(value.organizationId) || typeof value.changed !== "boolean")
10412
+ if (!record2(value) || !uuid2(value.organizationId) || typeof value.changed !== "boolean")
10319
10413
  return fail();
10320
10414
  const member = parseMember(value.member, fail);
10321
- if (member.membershipId !== membershipId || member.role !== role)
10415
+ if (member.membershipId !== membershipId || member.role !== role2)
10322
10416
  return fail();
10323
10417
  return { organizationId: value.organizationId, member, changed: value.changed };
10324
10418
  }
10325
10419
  function parseWorkspaceMemberRemovalResult(value, membershipId) {
10326
- if (!record(value) || !uuid(value.organizationId) || value.membershipId !== membershipId || value.removed !== true || typeof value.alreadyRemoved !== "boolean")
10420
+ if (!record2(value) || !uuid2(value.organizationId) || value.membershipId !== membershipId || value.removed !== true || typeof value.alreadyRemoved !== "boolean")
10327
10421
  throw new Error(invalidMemberResult);
10328
10422
  return { organizationId: value.organizationId, membershipId, removed: true, alreadyRemoved: value.alreadyRemoved };
10329
10423
  }
@@ -10340,7 +10434,7 @@ var workspaceMemberFailures = {
10340
10434
  MEMBERSHIP_BUSY: [503, "Membership is busy. Refresh the roster before another action."]
10341
10435
  };
10342
10436
  function workspaceMemberFailure(value, status) {
10343
- if (!record(value) || typeof value.code !== "string" || !Object.hasOwn(workspaceMemberFailures, value.code))
10437
+ if (!record2(value) || typeof value.code !== "string" || !Object.hasOwn(workspaceMemberFailures, value.code))
10344
10438
  return null;
10345
10439
  const code = value.code;
10346
10440
  return workspaceMemberFailures[code][0] === status ? code : null;
@@ -10349,13 +10443,72 @@ function parseWorkspaceMembersPage(value) {
10349
10443
  const fail = () => {
10350
10444
  throw new Error("The server returned an invalid workspace roster.");
10351
10445
  };
10352
- if (!record(value) || !uuid(value.organizationId) || !Array.isArray(value.members) || value.members.length > 100 || !(value.nextCursor === null || cursor(value.nextCursor)) || !value.members.length && value.nextCursor !== null)
10446
+ if (!record2(value) || !uuid2(value.organizationId) || !Array.isArray(value.members) || value.members.length > 100 || !(value.nextCursor === null || cursor(value.nextCursor)) || !value.members.length && value.nextCursor !== null)
10353
10447
  return fail();
10354
10448
  const members = value.members.map((row) => parseMember(row, fail));
10355
10449
  if (new Set(members.map((row) => row.membershipId)).size !== members.length)
10356
10450
  return fail();
10357
10451
  return { organizationId: value.organizationId, members, nextCursor: value.nextCursor };
10358
10452
  }
10453
+
10454
+ // src/lib/remote-workspace-leave.ts
10455
+ class WorkspaceLeaveInputError extends Error {
10456
+ constructor() {
10457
+ super("Confirm leaving the exact observed user and membership with its expected role.");
10458
+ this.name = "WorkspaceLeaveInputError";
10459
+ }
10460
+ }
10461
+ function workspaceLeaveInput(context, input) {
10462
+ const target = workspaceContext(context);
10463
+ if (!input || typeof input !== "object" || Array.isArray(input) || Object.keys(input).sort().join(",") !== "confirm,expectedRole" || input.confirm !== true)
10464
+ throw new WorkspaceLeaveInputError;
10465
+ const captured = workspaceMemberRemovalInput(target.membershipId, { expectedRole: input.expectedRole });
10466
+ return {
10467
+ context: target,
10468
+ input: { expectedRole: captured.body.expectedRole, confirm: true },
10469
+ body: { membershipId: target.membershipId, expectedRole: captured.body.expectedRole }
10470
+ };
10471
+ }
10472
+ var workspaceLeaveFailures = {
10473
+ INVALID_REQUEST: [400, "Provide the exact current membership and expected role."],
10474
+ ACCOUNT_UNAVAILABLE: [403, "Account is unavailable."],
10475
+ INTERACTIVE_SESSION_REQUIRED: [403, "Fresh interactive sign-in is required to leave a workspace."],
10476
+ MEMBERSHIP_ROLE_CHANGED: [409, "Your role changed. Sign in and inspect the workspace before leaving."],
10477
+ LAST_OWNER_REQUIRED: [409, "The workspace must retain another active owner."],
10478
+ LAST_WORKSPACE_REQUIRED: [409, "Another available workspace is required before leaving."],
10479
+ MEMBERSHIP_BUSY: [503, "Membership is busy. Inspect the workspace before another leave action."]
10480
+ };
10481
+
10482
+ class RemoteWorkspaceLeaveError extends Error {
10483
+ code;
10484
+ status;
10485
+ constructor(code) {
10486
+ super(workspaceLeaveFailures[code][1]);
10487
+ this.code = code;
10488
+ this.name = "RemoteWorkspaceLeaveError";
10489
+ this.status = workspaceLeaveFailures[code][0];
10490
+ }
10491
+ }
10492
+
10493
+ class RemoteWorkspaceLeaveUnconfirmedError extends Error {
10494
+ code = "WORKSPACE_LEAVE_UNCONFIRMED";
10495
+ constructor() {
10496
+ super("The leave outcome is unconfirmed. Sign in again and inspect available memberships before another action. Do not retry automatically; saved credentials are unchanged.");
10497
+ this.name = "RemoteWorkspaceLeaveUnconfirmedError";
10498
+ }
10499
+ }
10500
+ function workspaceLeaveFailure(value, status) {
10501
+ if (!value || typeof value !== "object" || Array.isArray(value))
10502
+ return null;
10503
+ const code = value.code;
10504
+ return typeof code === "string" && Object.hasOwn(workspaceLeaveFailures, code) && workspaceLeaveFailures[code][0] === status ? code : null;
10505
+ }
10506
+ function parseWorkspaceLeaveResult(value, membershipId, organizationId) {
10507
+ const row = value;
10508
+ if (!row || typeof row !== "object" || Array.isArray(row) || row.membershipId !== membershipId || row.organizationId !== organizationId || row.removed !== true || row.signInRequired !== true)
10509
+ throw new RemoteWorkspaceLeaveUnconfirmedError;
10510
+ return { membershipId, organizationId, removed: true, signInRequired: true };
10511
+ }
10359
10512
  // src/lib/auth-store.ts
10360
10513
  function getApiUrl(action, env = process.env, options = {}) {
10361
10514
  return requireSkillsApiOrigin(action, env, options);
@@ -10364,44 +10517,44 @@ function getApiUrl(action, env = process.env, options = {}) {
10364
10517
  // src/lib/remote-run-contract.ts
10365
10518
  var REMOTE_SKILL_RUN_CONTRACT_VERSION = 1;
10366
10519
  function normalizeRemoteSkillRunContract(payload, fallbackSkill) {
10367
- const record2 = isRecord3(payload) ? payload : {};
10520
+ const record3 = isRecord3(payload) ? payload : {};
10368
10521
  return {
10369
10522
  contractVersion: REMOTE_SKILL_RUN_CONTRACT_VERSION,
10370
- ...pickString(record2, "id"),
10371
- skill: pickStringValue(record2, "skill") ?? fallbackSkill,
10372
- ...pickString(record2, "requestedSlug"),
10373
- ...pickString(record2, "status"),
10374
- ...pickNumber(record2, "exitCode"),
10375
- ...pickString(record2, "correlationId"),
10376
- ...pickString(record2, "createdAt"),
10377
- ...pickString(record2, "startedAt"),
10378
- ...pickString(record2, "completedAt"),
10379
- ...pickNumber(record2, "durationMs"),
10380
- ...pickString(record2, "outputType"),
10381
- ...hasOwn(record2, "outputPreview") ? { outputPreview: record2.outputPreview } : {},
10382
- ...pickString(record2, "errorCode"),
10383
- ...pickString(record2, "errorMessage"),
10384
- ...pickString(record2, "error"),
10385
- ...pickString(record2, "code"),
10386
- ...hasOwn(record2, "details") ? { details: record2.details } : {}
10523
+ ...pickString(record3, "id"),
10524
+ skill: pickStringValue(record3, "skill") ?? fallbackSkill,
10525
+ ...pickString(record3, "requestedSlug"),
10526
+ ...pickString(record3, "status"),
10527
+ ...pickNumber(record3, "exitCode"),
10528
+ ...pickString(record3, "correlationId"),
10529
+ ...pickString(record3, "createdAt"),
10530
+ ...pickString(record3, "startedAt"),
10531
+ ...pickString(record3, "completedAt"),
10532
+ ...pickNumber(record3, "durationMs"),
10533
+ ...pickString(record3, "outputType"),
10534
+ ...hasOwn(record3, "outputPreview") ? { outputPreview: record3.outputPreview } : {},
10535
+ ...pickString(record3, "errorCode"),
10536
+ ...pickString(record3, "errorMessage"),
10537
+ ...pickString(record3, "error"),
10538
+ ...pickString(record3, "code"),
10539
+ ...hasOwn(record3, "details") ? { details: record3.details } : {}
10387
10540
  };
10388
10541
  }
10389
10542
  function isRecord3(value) {
10390
10543
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
10391
10544
  }
10392
- function hasOwn(record2, key) {
10393
- return Object.prototype.hasOwnProperty.call(record2, key);
10545
+ function hasOwn(record3, key) {
10546
+ return Object.prototype.hasOwnProperty.call(record3, key);
10394
10547
  }
10395
- function pickString(record2, key) {
10396
- const value = pickStringValue(record2, key);
10548
+ function pickString(record3, key) {
10549
+ const value = pickStringValue(record3, key);
10397
10550
  return value === undefined ? {} : { [key]: value };
10398
10551
  }
10399
- function pickStringValue(record2, key) {
10400
- const value = record2[key];
10552
+ function pickStringValue(record3, key) {
10553
+ const value = record3[key];
10401
10554
  return typeof value === "string" ? value : undefined;
10402
10555
  }
10403
- function pickNumber(record2, key) {
10404
- const value = record2[key];
10556
+ function pickNumber(record3, key) {
10557
+ const value = record3[key];
10405
10558
  return typeof value === "number" && Number.isFinite(value) ? { [key]: value } : {};
10406
10559
  }
10407
10560
 
@@ -10564,11 +10717,11 @@ function parseUpdatedProfile(value) {
10564
10717
  return { user: { id: user.id, email: user.email, displayName: user.displayName, role: user.role } };
10565
10718
  }
10566
10719
  function parseUpdatedWorkspace(value) {
10567
- const organization = isRecord4(value) && value.organization;
10568
- if (!isRecord4(organization) || !string(organization.id) || !string(organization.slug) || !string(organization.name)) {
10720
+ const organization2 = isRecord4(value) && value.organization;
10721
+ if (!isRecord4(organization2) || !string(organization2.id) || !string(organization2.slug) || !string(organization2.name)) {
10569
10722
  throw new Error("The server returned an invalid workspace.");
10570
10723
  }
10571
- return { organization: { id: organization.id, slug: organization.slug, name: organization.name } };
10724
+ return { organization: { id: organization2.id, slug: organization2.slug, name: organization2.name } };
10572
10725
  }
10573
10726
 
10574
10727
  // src/lib/remote-client.ts
@@ -10606,6 +10759,16 @@ class RemoteWorkspaceMemberError extends RemoteRequestError {
10606
10759
  }
10607
10760
  }
10608
10761
 
10762
+ class RemoteWorkspaceSelectionError extends RemoteRequestError {
10763
+ code;
10764
+ constructor(path, code) {
10765
+ super(path, workspaceSelectionFailures[code][0]);
10766
+ this.code = code;
10767
+ this.name = "RemoteWorkspaceSelectionError";
10768
+ this.message = workspaceSelectionFailures[code][1];
10769
+ }
10770
+ }
10771
+
10609
10772
  class RemoteCapabilityUnavailableError extends RemoteRequestError {
10610
10773
  code = "SUBSCRIPTION_CHECKOUT_UNAVAILABLE";
10611
10774
  constructor() {
@@ -10627,6 +10790,7 @@ class RemoteSkillsClient {
10627
10790
  return fetch(`${this.apiUrl}${path}`, {
10628
10791
  ...options,
10629
10792
  redirect: "error",
10793
+ credentials: "omit",
10630
10794
  signal: options?.signal ?? AbortSignal.timeout(15000),
10631
10795
  headers: {
10632
10796
  Authorization: `Bearer ${this.apiKey}`,
@@ -10733,6 +10897,65 @@ class RemoteSkillsClient {
10733
10897
  async getIdentity() {
10734
10898
  return (await this.requestNewRoute("/api/auth/whoami")).json();
10735
10899
  }
10900
+ async listAccountWorkspaces(expectedUserId) {
10901
+ const expected = expectedUserId === undefined ? undefined : workspaceExpectedUserId(expectedUserId);
10902
+ const connection = new RemoteSkillsClient(this.apiKey, this.apiUrl);
10903
+ let identity;
10904
+ if (expected !== undefined) {
10905
+ const value = await connection.requestWorkspaceSelection("/api/auth/whoami");
10906
+ if (!value || typeof value !== "object" || value.authMethod !== "jwt")
10907
+ throw new RemoteWorkspaceSelectionError("/api/v1/account/workspaces", "INTERACTIVE_SESSION_REQUIRED");
10908
+ identity = parseWorkspaceIdentity(value, expected);
10909
+ }
10910
+ const result = parseAccountWorkspaces(await connection.requestWorkspaceSelection("/api/v1/account/workspaces"));
10911
+ const current = result.workspaces.find((workspace) => workspace.current);
10912
+ if (identity && (current.membershipId !== identity.user.membershipId || current.organization.id !== identity.organization.id))
10913
+ throw new WorkspaceIdentityMismatchError;
10914
+ return result;
10915
+ }
10916
+ async switchWorkspace(context) {
10917
+ const target = workspaceContext(context);
10918
+ const connection = new RemoteSkillsClient(this.apiKey, this.apiUrl);
10919
+ const value = await connection.requestWorkspaceSelection("/api/auth/whoami");
10920
+ if (!value || typeof value !== "object" || value.authMethod !== "jwt")
10921
+ throw new RemoteWorkspaceSelectionError("/api/v1/account/workspaces/switch", "INTERACTIVE_SESSION_REQUIRED");
10922
+ parseWorkspaceIdentity(value, target.userId);
10923
+ const selected = parseWorkspaceSession(await connection.requestWorkspaceSelection("/api/v1/account/workspaces/switch", {
10924
+ method: "POST",
10925
+ body: JSON.stringify({ membershipId: target.membershipId })
10926
+ }), target);
10927
+ const verified = await new RemoteSkillsClient(selected.token, connection.apiUrl).requestWorkspaceSelection("/api/auth/whoami");
10928
+ if (!verified || typeof verified !== "object" || verified.authMethod !== "jwt")
10929
+ throw new RemoteWorkspaceSelectionError("/api/v1/account/workspaces/switch", "INTERACTIVE_SESSION_REQUIRED");
10930
+ const identity = parseWorkspaceIdentity(verified, target.userId);
10931
+ if (identity.user.membershipId !== target.membershipId || identity.organization.id !== selected.organization.id)
10932
+ throw new WorkspaceIdentityMismatchError;
10933
+ return { token: selected.token, ...identity };
10934
+ }
10935
+ async requestWorkspaceSelection(path, options) {
10936
+ let response;
10937
+ try {
10938
+ response = await this.request(path, { ...options, credentials: "omit" });
10939
+ } catch {
10940
+ throw new Error("Unable to reach the Skills workspace API.");
10941
+ }
10942
+ let value;
10943
+ try {
10944
+ value = JSON.parse(new TextDecoder().decode(await readBoundedResponse(response, response.ok ? 1024 * 1024 : 4096)));
10945
+ } catch {
10946
+ if (response.ok)
10947
+ throw new Error(invalidWorkspaceResult);
10948
+ }
10949
+ if (!response.ok) {
10950
+ const code = workspaceSelectionFailure(value, response.status);
10951
+ if (code)
10952
+ throw new RemoteWorkspaceSelectionError(path, code);
10953
+ if (response.status === 404 || response.status === 405)
10954
+ throw new RemoteRouteUnsupportedError(path, response.status, this.apiUrl);
10955
+ throw new RemoteRequestError(path, response.status);
10956
+ }
10957
+ return value;
10958
+ }
10736
10959
  async updateProfile(input) {
10737
10960
  const body = customerNamePatch(input, "displayName");
10738
10961
  return parseUpdatedProfile(await (await this.requestNewRoute("/api/v1/account/profile", { method: "PATCH", body: JSON.stringify(body) })).json());
@@ -10785,6 +11008,30 @@ class RemoteSkillsClient {
10785
11008
  }
10786
11009
  return value;
10787
11010
  }
11011
+ async leaveWorkspace(context, input) {
11012
+ const captured = workspaceLeaveInput(context, input);
11013
+ const connection = new RemoteSkillsClient(this.apiKey, this.apiUrl);
11014
+ const value = await connection.requestWorkspaceSelection("/api/auth/whoami");
11015
+ if (!value || typeof value !== "object" || value.authMethod !== "jwt")
11016
+ throw new RemoteWorkspaceLeaveError("INTERACTIVE_SESSION_REQUIRED");
11017
+ const identity = parseWorkspaceIdentity(value, captured.context.userId);
11018
+ if (identity.user.membershipId !== captured.context.membershipId)
11019
+ throw new WorkspaceIdentityMismatchError;
11020
+ let response, body;
11021
+ try {
11022
+ response = await connection.request("/api/v1/account/workspaces/leave", { method: "POST", body: JSON.stringify(captured.body) });
11023
+ body = JSON.parse(new TextDecoder().decode(await readBoundedResponse(response, 4096)));
11024
+ } catch {
11025
+ throw new RemoteWorkspaceLeaveUnconfirmedError;
11026
+ }
11027
+ if (!response.ok) {
11028
+ const code = workspaceLeaveFailure(body, response.status);
11029
+ if (code)
11030
+ throw new RemoteWorkspaceLeaveError(code);
11031
+ throw new RemoteWorkspaceLeaveUnconfirmedError;
11032
+ }
11033
+ return parseWorkspaceLeaveResult(body, captured.context.membershipId, identity.organization.id);
11034
+ }
10788
11035
  async listApiKeys() {
10789
11036
  return this.arrayResponse("/api/auth/keys");
10790
11037
  }
@@ -11035,13 +11282,13 @@ class RemoteSkillsClient {
11035
11282
  return normalizeUpdatedSincePage(await response.json());
11036
11283
  }
11037
11284
  }
11038
- function requireOptionalString(record2, field) {
11039
- if (record2[field] === undefined)
11285
+ function requireOptionalString(record3, field) {
11286
+ if (record3[field] === undefined)
11040
11287
  return;
11041
- if (typeof record2[field] !== "string") {
11288
+ if (typeof record3[field] !== "string") {
11042
11289
  throw new Error(`Remote payload did not match the expected contract (${field} must be a string when present)`);
11043
11290
  }
11044
- return record2[field];
11291
+ return record3[field];
11045
11292
  }
11046
11293
  var INVALID_SKILL_VERSION_RESPONSE = "Remote skill version payload did not match the expected contract.";
11047
11294
  function isVersionRecord(value) {
@@ -11064,19 +11311,19 @@ function normalizePin(entry) {
11064
11311
  if (!entry || typeof entry !== "object") {
11065
11312
  throw new Error("Remote pin payload did not match the expected contract (expected an object)");
11066
11313
  }
11067
- const record2 = entry;
11068
- const slug = typeof record2.slug === "string" && record2.slug.trim() ? record2.slug.trim() : undefined;
11314
+ const record3 = entry;
11315
+ const slug = typeof record3.slug === "string" && record3.slug.trim() ? record3.slug.trim() : undefined;
11069
11316
  if (!slug) {
11070
11317
  throw new Error("Remote pin payload did not match the expected contract (missing slug)");
11071
11318
  }
11072
11319
  let metadata;
11073
- if (record2.metadata !== undefined) {
11074
- if (!record2.metadata || typeof record2.metadata !== "object" || Array.isArray(record2.metadata)) {
11320
+ if (record3.metadata !== undefined) {
11321
+ if (!record3.metadata || typeof record3.metadata !== "object" || Array.isArray(record3.metadata)) {
11075
11322
  throw new Error("Remote pin payload did not match the expected contract (metadata must be a JSON object when present)");
11076
11323
  }
11077
- metadata = record2.metadata;
11324
+ metadata = record3.metadata;
11078
11325
  }
11079
- const pinnedAt = requireOptionalString(record2, "pinnedAt");
11326
+ const pinnedAt = requireOptionalString(record3, "pinnedAt");
11080
11327
  return {
11081
11328
  slug,
11082
11329
  ...pinnedAt !== undefined ? { pinnedAt } : {},
@@ -11093,16 +11340,16 @@ function normalizeSkillSummary(entry) {
11093
11340
  if (!entry || typeof entry !== "object") {
11094
11341
  throw new Error("Remote skill payload did not match the expected contract (expected an object)");
11095
11342
  }
11096
- const record2 = entry;
11097
- const slug = typeof record2.slug === "string" && record2.slug.trim() ? record2.slug.trim() : undefined;
11343
+ const record3 = entry;
11344
+ const slug = typeof record3.slug === "string" && record3.slug.trim() ? record3.slug.trim() : undefined;
11098
11345
  if (!slug) {
11099
11346
  throw new Error("Remote skill payload did not match the expected contract (missing slug)");
11100
11347
  }
11101
11348
  return {
11102
11349
  slug,
11103
- ...requireOptionalString(record2, "name") !== undefined ? { name: requireOptionalString(record2, "name") } : {},
11104
- ...requireOptionalString(record2, "version") !== undefined ? { version: requireOptionalString(record2, "version") } : {},
11105
- ...requireOptionalString(record2, "updatedAt") !== undefined ? { updatedAt: requireOptionalString(record2, "updatedAt") } : {}
11350
+ ...requireOptionalString(record3, "name") !== undefined ? { name: requireOptionalString(record3, "name") } : {},
11351
+ ...requireOptionalString(record3, "version") !== undefined ? { version: requireOptionalString(record3, "version") } : {},
11352
+ ...requireOptionalString(record3, "updatedAt") !== undefined ? { updatedAt: requireOptionalString(record3, "updatedAt") } : {}
11106
11353
  };
11107
11354
  }
11108
11355
  function normalizeSkillSummaryList(payload) {
@@ -11155,12 +11402,12 @@ function normalizeUpdatedSincePage(payload) {
11155
11402
  if (!payload || typeof payload !== "object") {
11156
11403
  throw new Error("Updated-since payload did not match the expected contract (expected an object)");
11157
11404
  }
11158
- const record2 = payload;
11159
- if (!Array.isArray(record2.skills)) {
11405
+ const record3 = payload;
11406
+ if (!Array.isArray(record3.skills)) {
11160
11407
  throw new Error("Updated-since payload did not match the expected contract (missing skills array)");
11161
11408
  }
11162
- const skills = record2.skills.map(normalizeSkillSummary);
11163
- const nextCursor = record2.nextCursor === undefined || record2.nextCursor === null ? null : record2.nextCursor;
11409
+ const skills = record3.skills.map(normalizeSkillSummary);
11410
+ const nextCursor = record3.nextCursor === undefined || record3.nextCursor === null ? null : record3.nextCursor;
11164
11411
  if (nextCursor !== null && typeof nextCursor !== "string") {
11165
11412
  throw new Error("Updated-since payload did not match the expected contract (nextCursor must be a string or absent)");
11166
11413
  }
@@ -11397,8 +11644,8 @@ function revisionIdOf(content) {
11397
11644
  });
11398
11645
  return createHash4("sha256").update(canonical).digest("hex");
11399
11646
  }
11400
- function revisionIdOfRecord(record2) {
11401
- return revisionIdOf(record2);
11647
+ function revisionIdOfRecord(record3) {
11648
+ return revisionIdOf(record3);
11402
11649
  }
11403
11650
 
11404
11651
  // src/lib/skill-bundle.ts
@@ -12105,16 +12352,16 @@ function installBundleAtomically(name, entries, options = {}, marker = {}) {
12105
12352
  }
12106
12353
  return { path: target, created };
12107
12354
  }
12108
- function writePullMarker(dir, record2) {
12355
+ function writePullMarker(dir, record3) {
12109
12356
  const marker = {
12110
12357
  managedBy: "@hasna/skills",
12111
- skill: record2.skill,
12112
- source: record2.source ?? "pull",
12113
- ...record2.version ? { version: record2.version } : {},
12114
- ...record2.contentHash ? { contentHash: record2.contentHash } : {},
12115
- ...record2.sourceCommit ? { sourceCommit: record2.sourceCommit } : {},
12116
- ...record2.signature ? { signature: record2.signature } : {},
12117
- ...record2.revisionId ? { revisionId: record2.revisionId } : {},
12358
+ skill: record3.skill,
12359
+ source: record3.source ?? "pull",
12360
+ ...record3.version ? { version: record3.version } : {},
12361
+ ...record3.contentHash ? { contentHash: record3.contentHash } : {},
12362
+ ...record3.sourceCommit ? { sourceCommit: record3.sourceCommit } : {},
12363
+ ...record3.signature ? { signature: record3.signature } : {},
12364
+ ...record3.revisionId ? { revisionId: record3.revisionId } : {},
12118
12365
  syncedAt: new Date().toISOString()
12119
12366
  };
12120
12367
  writeFileSync8(join17(dir, PULL_MARKER_FILE), `${JSON.stringify(marker, null, 2)}
@@ -12129,19 +12376,19 @@ async function safeMeta(client, slug) {
12129
12376
  }
12130
12377
  if (!raw || typeof raw !== "object")
12131
12378
  return null;
12132
- const record2 = raw;
12133
- const kind = record2.kind === "instruction" || record2.kind === "executable" ? record2.kind : undefined;
12134
- const tags = Array.isArray(record2.tags) ? record2.tags.filter((tag) => typeof tag === "string" && tag.trim().length > 0) : undefined;
12379
+ const record3 = raw;
12380
+ const kind = record3.kind === "instruction" || record3.kind === "executable" ? record3.kind : undefined;
12381
+ const tags = Array.isArray(record3.tags) ? record3.tags.filter((tag) => typeof tag === "string" && tag.trim().length > 0) : undefined;
12135
12382
  return {
12136
- ...str(record2.displayName) ? { displayName: str(record2.displayName) } : {},
12137
- ...str(record2.description) ? { description: str(record2.description) } : {},
12138
- ...str(record2.category) ? { category: str(record2.category) } : {},
12383
+ ...str(record3.displayName) ? { displayName: str(record3.displayName) } : {},
12384
+ ...str(record3.description) ? { description: str(record3.description) } : {},
12385
+ ...str(record3.category) ? { category: str(record3.category) } : {},
12139
12386
  ...tags && tags.length ? { tags } : {},
12140
- ...str(record2.version) ? { version: str(record2.version) } : {},
12387
+ ...str(record3.version) ? { version: str(record3.version) } : {},
12141
12388
  ...kind ? { kind } : {},
12142
- ...REVISION_ID_PATTERN.test(str(record2.revisionId) ?? "") ? { revisionId: str(record2.revisionId) } : {},
12143
- ...typeof record2.skillMd === "string" && record2.skillMd.length > 0 ? { skillMd: record2.skillMd } : {},
12144
- ...str(record2.publishedSource) ? { publishedSource: str(record2.publishedSource) } : {}
12389
+ ...REVISION_ID_PATTERN.test(str(record3.revisionId) ?? "") ? { revisionId: str(record3.revisionId) } : {},
12390
+ ...typeof record3.skillMd === "string" && record3.skillMd.length > 0 ? { skillMd: record3.skillMd } : {},
12391
+ ...str(record3.publishedSource) ? { publishedSource: str(record3.publishedSource) } : {}
12145
12392
  };
12146
12393
  }
12147
12394
  function pickCorpusOptions(options) {
@@ -12150,8 +12397,8 @@ function pickCorpusOptions(options) {
12150
12397
  function extractSlug(entry) {
12151
12398
  if (!entry || typeof entry !== "object")
12152
12399
  return;
12153
- const record2 = entry;
12154
- return str(record2.slug) ?? str(record2.name);
12400
+ const record3 = entry;
12401
+ return str(record3.slug) ?? str(record3.name);
12155
12402
  }
12156
12403
  function dedupe(values) {
12157
12404
  return [...new Set(values)];
@@ -12277,7 +12524,7 @@ import { dirname as dirname7, relative as relative4 } from "path";
12277
12524
  // package.json
12278
12525
  var package_default = {
12279
12526
  name: "@hasna/skills",
12280
- version: "0.5.0",
12527
+ version: "0.5.2",
12281
12528
  description: "Skills library for AI coding agents",
12282
12529
  type: "module",
12283
12530
  bin: {
@@ -13788,7 +14035,7 @@ class SkillsPostgresSyncStore {
13788
14035
  }
13789
14036
  async upsertRecords(records) {
13790
14037
  let count = 0;
13791
- for (const record2 of records) {
14038
+ for (const record3 of records) {
13792
14039
  await this.client.query([
13793
14040
  "INSERT INTO skills_sync_records",
13794
14041
  "(scope, kind, id, updated_at, deleted_at, source, payload)",
@@ -13799,13 +14046,13 @@ class SkillsPostgresSyncStore {
13799
14046
  "source = EXCLUDED.source,",
13800
14047
  "payload = EXCLUDED.payload"
13801
14048
  ].join(" "), [
13802
- record2.scope,
13803
- record2.kind,
13804
- record2.id,
13805
- record2.updatedAt,
13806
- record2.deletedAt ?? null,
13807
- record2.source ?? null,
13808
- JSON.stringify(record2.payload)
14049
+ record3.scope,
14050
+ record3.kind,
14051
+ record3.id,
14052
+ record3.updatedAt,
14053
+ record3.deletedAt ?? null,
14054
+ record3.source ?? null,
14055
+ JSON.stringify(record3.payload)
13809
14056
  ]);
13810
14057
  count += 1;
13811
14058
  }
@@ -14784,13 +15031,13 @@ async function requestAuthApi(instance, path, options) {
14784
15031
  apiUrl: safeUrl
14785
15032
  });
14786
15033
  }
14787
- const text = await res.text();
14788
- const body = text ? parseJsonBody(text) : {};
15034
+ const text2 = await res.text();
15035
+ const body = text2 ? parseJsonBody(text2) : {};
14789
15036
  if (!res.ok) {
14790
- const record2 = isRecord5(body) ? body : {};
14791
- const detail = typeof record2.detail === "string" ? record2.detail : undefined;
14792
- const error = typeof record2.error === "string" ? record2.error : undefined;
14793
- const code = typeof record2.code === "string" ? record2.code : undefined;
15037
+ const record3 = isRecord5(body) ? body : {};
15038
+ const detail = typeof record3.detail === "string" ? record3.detail : undefined;
15039
+ const error = typeof record3.error === "string" ? record3.error : undefined;
15040
+ const code = typeof record3.code === "string" ? record3.code : undefined;
14794
15041
  throw new HostedApiError(detail || error || `${res.status} ${res.statusText}`, {
14795
15042
  status: res.status,
14796
15043
  code,
@@ -14801,15 +15048,15 @@ async function requestAuthApi(instance, path, options) {
14801
15048
  }
14802
15049
  return body;
14803
15050
  }
14804
- function parseJsonBody(text) {
15051
+ function parseJsonBody(text2) {
14805
15052
  try {
14806
- return JSON.parse(text);
15053
+ return JSON.parse(text2);
14807
15054
  } catch {
14808
- return { detail: condenseErrorBody(text) };
15055
+ return { detail: condenseErrorBody(text2) };
14809
15056
  }
14810
15057
  }
14811
- function condenseErrorBody(text) {
14812
- const stripped = /<[a-z!/]/i.test(text) ? text.replace(/<(script|style)[\s\S]*?<\/\1>/gi, " ").replace(/<[^>]*>/g, " ") : text;
15058
+ function condenseErrorBody(text2) {
15059
+ const stripped = /<[a-z!/]/i.test(text2) ? text2.replace(/<(script|style)[\s\S]*?<\/\1>/gi, " ").replace(/<[^>]*>/g, " ") : text2;
14813
15060
  const collapsed = stripped.replace(/\s+/g, " ").trim();
14814
15061
  if (collapsed.length <= MAX_ERROR_DETAIL_LENGTH)
14815
15062
  return collapsed;
@@ -14836,7 +15083,12 @@ class RemoteSkillsAuthClient {
14836
15083
  pollDevice(deviceCode) {
14837
15084
  return this.request("/api/auth/device/token", { method: "POST", body: JSON.stringify({ deviceCode }) });
14838
15085
  }
14839
- async sessionClient(email, code) {
15086
+ async sessionClient(email, code, context) {
15087
+ if (context !== undefined) {
15088
+ const target = workspaceContext(context), apiOrigin2 = this.apiOrigin;
15089
+ const session = await this.switchWorkspace(email, code, target);
15090
+ return new RemoteSkillsClient(session.token, apiOrigin2);
15091
+ }
14840
15092
  const apiOrigin = this.apiOrigin;
14841
15093
  if (!email.includes("@") || !/^\d{6}$/.test(code))
14842
15094
  throw new Error("Fresh email and six-digit verification code are required to manage this account");
@@ -14845,34 +15097,80 @@ class RemoteSkillsAuthClient {
14845
15097
  throw new Error("The server did not return an authorized account session");
14846
15098
  return new RemoteSkillsClient(login.token, apiOrigin);
14847
15099
  }
14848
- async createApiKey(email, code, name, scopes) {
14849
- return (await this.sessionClient(email, code)).createApiKey(name, scopes);
15100
+ async listAccountWorkspaces(email, code, expectedUserId) {
15101
+ const login = await this.workspaceLogin(email, code, expectedUserId);
15102
+ const result = await new RemoteSkillsClient(login.token, login.apiOrigin).listAccountWorkspaces(login.userId);
15103
+ return { userId: login.userId, ...result };
14850
15104
  }
14851
- async listApiKeys(email, code) {
14852
- return (await this.sessionClient(email, code)).listApiKeys();
15105
+ async switchWorkspace(email, code, context) {
15106
+ const target = workspaceContext(context);
15107
+ const login = await this.workspaceLogin(email, code, target.userId);
15108
+ return new RemoteSkillsClient(login.token, login.apiOrigin).switchWorkspace(target);
14853
15109
  }
14854
- async revokeApiKey(email, code, keyId) {
14855
- return (await this.sessionClient(email, code)).revokeApiKey(keyId);
15110
+ async workspaceLogin(email, code, expectedUserId) {
15111
+ const expected = expectedUserId === undefined ? undefined : workspaceExpectedUserId(expectedUserId);
15112
+ const apiOrigin = this.apiOrigin;
15113
+ if (typeof email !== "string" || !email.includes("@") || typeof code !== "string" || !/^\d{6}$/.test(code))
15114
+ throw new Error("Fresh email and six-digit verification code are required to manage this account");
15115
+ let response;
15116
+ try {
15117
+ response = await fetch(`${apiOrigin}/api/auth/verify`, {
15118
+ method: "POST",
15119
+ redirect: "error",
15120
+ credentials: "omit",
15121
+ signal: AbortSignal.timeout(15000),
15122
+ headers: { "Content-Type": "application/json" },
15123
+ body: JSON.stringify({ email, code })
15124
+ });
15125
+ } catch {
15126
+ throw new HostedApiError("Unable to verify the Skills account.");
15127
+ }
15128
+ if (!response.ok) {
15129
+ response.body?.cancel().catch(() => {});
15130
+ throw new HostedApiError("Unable to verify the Skills account.", { status: response.status });
15131
+ }
15132
+ let value;
15133
+ try {
15134
+ value = JSON.parse(new TextDecoder().decode(await readBoundedResponse(response, 64 * 1024)));
15135
+ } catch {
15136
+ throw new HostedApiError("The server returned an invalid account verification result.");
15137
+ }
15138
+ return { ...parseWorkspaceLogin(value, expected), apiOrigin };
15139
+ }
15140
+ async createApiKey(email, code, name, scopes, context) {
15141
+ const capturedScopes = scopes === undefined ? undefined : [...scopes];
15142
+ return (await this.sessionClient(email, code, context)).createApiKey(name, capturedScopes);
14856
15143
  }
14857
- async updateProfile(email, code, input) {
14858
- customerNamePatch(input, "displayName");
14859
- return (await this.sessionClient(email, code)).updateProfile(input);
15144
+ async listApiKeys(email, code, context) {
15145
+ return (await this.sessionClient(email, code, context)).listApiKeys();
14860
15146
  }
14861
- async updateCurrentWorkspace(email, code, input) {
14862
- customerNamePatch(input, "name");
14863
- return (await this.sessionClient(email, code)).updateCurrentWorkspace(input);
15147
+ async revokeApiKey(email, code, keyId, context) {
15148
+ return (await this.sessionClient(email, code, context)).revokeApiKey(keyId);
14864
15149
  }
14865
- async listWorkspaceMembers(email, code, options = {}) {
15150
+ async updateProfile(email, code, input, context) {
15151
+ const body = customerNamePatch(input, "displayName");
15152
+ return (await this.sessionClient(email, code, context)).updateProfile({ displayName: body.displayName });
15153
+ }
15154
+ async updateCurrentWorkspace(email, code, input, context) {
15155
+ const body = customerNamePatch(input, "name");
15156
+ return (await this.sessionClient(email, code, context)).updateCurrentWorkspace({ name: body.name });
15157
+ }
15158
+ async listWorkspaceMembers(email, code, options = {}, context) {
14866
15159
  workspaceMembersQuery(options);
14867
- return (await this.sessionClient(email, code)).listWorkspaceMembers(options);
15160
+ const captured = { ...options };
15161
+ return (await this.sessionClient(email, code, context)).listWorkspaceMembers(captured);
14868
15162
  }
14869
- async setWorkspaceMemberRole(email, code, membershipId, input) {
15163
+ async setWorkspaceMemberRole(email, code, membershipId, input, context) {
14870
15164
  const captured = workspaceMemberRoleInput(membershipId, input);
14871
- return (await this.sessionClient(email, code)).setWorkspaceMemberRole(captured.membershipId, captured.body);
15165
+ return (await this.sessionClient(email, code, context)).setWorkspaceMemberRole(captured.membershipId, captured.body);
15166
+ }
15167
+ async leaveWorkspace(email, code, context, input) {
15168
+ const captured = workspaceLeaveInput(context, input);
15169
+ return (await this.sessionClient(email, code, captured.context)).leaveWorkspace(captured.context, captured.input);
14872
15170
  }
14873
- async removeWorkspaceMember(email, code, membershipId, input) {
15171
+ async removeWorkspaceMember(email, code, membershipId, input, context) {
14874
15172
  const captured = workspaceMemberRemovalInput(membershipId, input);
14875
- return (await this.sessionClient(email, code)).removeWorkspaceMember(captured.membershipId, captured.body);
15173
+ return (await this.sessionClient(email, code, context)).removeWorkspaceMember(captured.membershipId, captured.body);
14876
15174
  }
14877
15175
  request(path, options) {
14878
15176
  if (!["/api/auth/login", "/api/auth/verify", "/api/auth/device/start", "/api/auth/device/token", "/api/auth/keys", "/api/auth/whoami"].includes(path))
@@ -15062,6 +15360,9 @@ export {
15062
15360
  agentGlobalSkillsDir,
15063
15361
  addSchedule,
15064
15362
  adaptSkillMdForAgent,
15363
+ WorkspaceLeaveInputError,
15364
+ WorkspaceIdentityMismatchError,
15365
+ WorkspaceContextInputError,
15065
15366
  TOOL_PRIMITIVE_SCHEMA_VERSION,
15066
15367
  TOOL_PRIMITIVES,
15067
15368
  StationSnapshotError,
@@ -15093,7 +15394,10 @@ export {
15093
15394
  SKILLS_API_KEY_ENV_KEYS,
15094
15395
  SKILLS_API_KEY_ENV,
15095
15396
  SKILLS,
15397
+ RemoteWorkspaceSelectionError,
15096
15398
  RemoteWorkspaceMemberError,
15399
+ RemoteWorkspaceLeaveUnconfirmedError,
15400
+ RemoteWorkspaceLeaveError,
15097
15401
  RemoteSkillsClient,
15098
15402
  RemoteSkillsAuthClient,
15099
15403
  RemoteRouteUnsupportedError,