@hasna/skills 0.5.0 → 0.5.1

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/bin/index.js CHANGED
@@ -36860,7 +36860,7 @@ var package_default;
36860
36860
  var init_package = __esm(() => {
36861
36861
  package_default = {
36862
36862
  name: "@hasna/skills",
36863
- version: "0.5.0",
36863
+ version: "0.5.1",
36864
36864
  description: "Skills library for AI coding agents",
36865
36865
  type: "module",
36866
36866
  bin: {
@@ -49045,9 +49045,99 @@ var init_read_access = __esm(() => {
49045
49045
  init_remote_registry();
49046
49046
  });
49047
49047
 
49048
+ // src/lib/remote-workspace-selection.ts
49049
+ function workspaceExpectedUserId(value) {
49050
+ if (!uuid(value))
49051
+ throw new WorkspaceContextInputError;
49052
+ return value;
49053
+ }
49054
+ function workspaceContext(value) {
49055
+ if (!record(value) || Object.keys(value).sort().join(",") !== "membershipId,userId" || !uuid(value.userId) || !uuid(value.membershipId))
49056
+ throw new WorkspaceContextInputError;
49057
+ return { userId: value.userId, membershipId: value.membershipId };
49058
+ }
49059
+ function invalid() {
49060
+ throw new Error(invalidWorkspaceResult);
49061
+ }
49062
+ function organization(v) {
49063
+ if (!record(v) || !uuid(v.id) || !text(v.slug) || !text(v.name))
49064
+ return invalid();
49065
+ return { id: v.id, slug: v.slug, name: v.name };
49066
+ }
49067
+ function parseAccountWorkspaces(value) {
49068
+ if (!record(value) || !Array.isArray(value.workspaces) || !value.workspaces.length || value.workspaces.length > 1000)
49069
+ return invalid();
49070
+ const workspaces = value.workspaces.map((v) => {
49071
+ if (!record(v) || !uuid(v.membershipId) || !role(v.role) || typeof v.current !== "boolean")
49072
+ return invalid();
49073
+ return { membershipId: v.membershipId, organization: organization(v.organization), role: v.role, current: v.current };
49074
+ });
49075
+ 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)
49076
+ return invalid();
49077
+ return { workspaces };
49078
+ }
49079
+ function parseWorkspaceIdentity(value, expectedUserId) {
49080
+ if (!record(value))
49081
+ return invalid();
49082
+ const user = value.user;
49083
+ if (!record(user) || !uuid(user.id) || !uuid(user.membershipId) || !text(user.email, 320) || !(user.displayName === null || text(user.displayName)) || !role(user.role))
49084
+ return invalid();
49085
+ if (user.id !== expectedUserId)
49086
+ throw new WorkspaceIdentityMismatchError;
49087
+ return { user: { id: user.id, membershipId: user.membershipId, email: user.email, displayName: user.displayName, role: user.role }, organization: organization(value.organization) };
49088
+ }
49089
+ function sessionToken(value) {
49090
+ if (typeof value !== "string" || !value || value.length > 8192 || /[^\x21-\x7e]/.test(value) || value.startsWith("sk_"))
49091
+ return invalid();
49092
+ return value;
49093
+ }
49094
+ function parseWorkspaceSession(value, expected) {
49095
+ const identity2 = parseWorkspaceIdentity(value, expected.userId);
49096
+ if (identity2.user.membershipId !== expected.membershipId)
49097
+ throw new WorkspaceIdentityMismatchError;
49098
+ return { token: sessionToken(value.token), ...identity2 };
49099
+ }
49100
+ function parseWorkspaceLogin(value, expectedUserId) {
49101
+ const user = record(value) && value.user;
49102
+ if (!record(value) || !record(user) || !uuid(user.id))
49103
+ return invalid();
49104
+ if (expectedUserId !== undefined && user.id !== expectedUserId)
49105
+ throw new WorkspaceIdentityMismatchError;
49106
+ return { token: sessionToken(value.token), userId: user.id };
49107
+ }
49108
+ function workspaceSelectionFailure(value, status) {
49109
+ if (!record(value) || typeof value.code !== "string" || !Object.hasOwn(workspaceSelectionFailures, value.code))
49110
+ return null;
49111
+ const code = value.code;
49112
+ return workspaceSelectionFailures[code][0] === status ? code : null;
49113
+ }
49114
+ var record = (v) => !!v && typeof v === "object" && !Array.isArray(v), 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), text = (v, max2 = 1024) => typeof v === "string" && !!v.trim() && v.length <= max2 && !/[\p{Cc}\p{Cs}\u2028\u2029]/u.test(v), role = (v) => typeof v === "string" && ["owner", "admin", "member", "viewer"].includes(v), invalidWorkspaceResult = "The server returned an invalid workspace selection result.", WorkspaceContextInputError, WorkspaceIdentityMismatchError, workspaceSelectionFailures;
49115
+ var init_remote_workspace_selection = __esm(() => {
49116
+ WorkspaceContextInputError = class WorkspaceContextInputError extends Error {
49117
+ constructor() {
49118
+ super("Provide the observed user ID and exact lowercase membership ID.");
49119
+ this.name = "WorkspaceContextInputError";
49120
+ }
49121
+ };
49122
+ WorkspaceIdentityMismatchError = class WorkspaceIdentityMismatchError extends Error {
49123
+ constructor() {
49124
+ super("The verified account does not match the requested workspace context.");
49125
+ this.name = "WorkspaceIdentityMismatchError";
49126
+ }
49127
+ };
49128
+ workspaceSelectionFailures = {
49129
+ INVALID_WORKSPACE_SELECTION: [400, "Provide only the exact membership ID from your workspace list."],
49130
+ SESSION_EXPIRED: [401, "Sign in again before selecting a workspace."],
49131
+ ACCOUNT_UNAVAILABLE: [403, "Account is unavailable."],
49132
+ INTERACTIVE_SESSION_REQUIRED: [403, "Interactive sign-in is required to select a workspace."],
49133
+ WORKSPACE_UNAVAILABLE: [404, "Workspace is unavailable. Refresh your workspace list."],
49134
+ WORKSPACE_BUSY: [503, "Workspace is busy. Refresh before retrying."]
49135
+ };
49136
+ });
49137
+
49048
49138
  // src/lib/remote-workspace.ts
49049
49139
  function workspaceMembersQuery(options = {}) {
49050
- 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))
49140
+ 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))
49051
49141
  throw new Error("Use a roster limit from 1 to 100 and an unchanged continuation cursor.");
49052
49142
  const query = new URLSearchParams;
49053
49143
  if (options.limit !== undefined)
@@ -49063,7 +49153,7 @@ function timestamp(value) {
49063
49153
  return Number.isFinite(time) && new Date(time).toISOString().slice(0, 23) === value.slice(0, 23);
49064
49154
  }
49065
49155
  function parseMember(row, fail2) {
49066
- 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))
49156
+ 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))
49067
49157
  return fail2();
49068
49158
  return {
49069
49159
  membershipId: row.membershipId,
@@ -49075,12 +49165,12 @@ function parseMember(row, fail2) {
49075
49165
  };
49076
49166
  }
49077
49167
  function mutationInput(membershipId, input, roleChange) {
49078
- if (typeof membershipId !== "string" || !uuid(membershipId) || membershipId !== membershipId.toLowerCase() || !record(input) || Object.keys(input).sort().join(",") !== (roleChange ? "expectedRole,role" : "expectedRole"))
49168
+ if (typeof membershipId !== "string" || !uuid2(membershipId) || membershipId !== membershipId.toLowerCase() || !record2(input) || Object.keys(input).sort().join(",") !== (roleChange ? "expectedRole,role" : "expectedRole"))
49079
49169
  throw new WorkspaceMemberInputError;
49080
- const expectedRole = input.expectedRole, role = roleChange ? input.role : undefined;
49081
- if (!isRole(expectedRole) || roleChange && !isRole(role))
49170
+ const expectedRole = input.expectedRole, role2 = roleChange ? input.role : undefined;
49171
+ if (!isRole(expectedRole) || roleChange && !isRole(role2))
49082
49172
  throw new WorkspaceMemberInputError;
49083
- return { membershipId, role, expectedRole };
49173
+ return { membershipId, role: role2, expectedRole };
49084
49174
  }
49085
49175
  function workspaceMemberRoleInput(membershipId, input) {
49086
49176
  const value = mutationInput(membershipId, input, true);
@@ -49090,24 +49180,24 @@ function workspaceMemberRemovalInput(membershipId, input) {
49090
49180
  const value = mutationInput(membershipId, input, false);
49091
49181
  return { membershipId: value.membershipId, body: { expectedRole: value.expectedRole } };
49092
49182
  }
49093
- function parseWorkspaceMemberRoleResult(value, membershipId, role) {
49183
+ function parseWorkspaceMemberRoleResult(value, membershipId, role2) {
49094
49184
  const fail2 = () => {
49095
49185
  throw new Error(invalidMemberResult);
49096
49186
  };
49097
- if (!record(value) || !uuid(value.organizationId) || typeof value.changed !== "boolean")
49187
+ if (!record2(value) || !uuid2(value.organizationId) || typeof value.changed !== "boolean")
49098
49188
  return fail2();
49099
49189
  const member = parseMember(value.member, fail2);
49100
- if (member.membershipId !== membershipId || member.role !== role)
49190
+ if (member.membershipId !== membershipId || member.role !== role2)
49101
49191
  return fail2();
49102
49192
  return { organizationId: value.organizationId, member, changed: value.changed };
49103
49193
  }
49104
49194
  function parseWorkspaceMemberRemovalResult(value, membershipId) {
49105
- if (!record(value) || !uuid(value.organizationId) || value.membershipId !== membershipId || value.removed !== true || typeof value.alreadyRemoved !== "boolean")
49195
+ if (!record2(value) || !uuid2(value.organizationId) || value.membershipId !== membershipId || value.removed !== true || typeof value.alreadyRemoved !== "boolean")
49106
49196
  throw new Error(invalidMemberResult);
49107
49197
  return { organizationId: value.organizationId, membershipId, removed: true, alreadyRemoved: value.alreadyRemoved };
49108
49198
  }
49109
49199
  function workspaceMemberFailure(value, status) {
49110
- if (!record(value) || typeof value.code !== "string" || !Object.hasOwn(workspaceMemberFailures, value.code))
49200
+ if (!record2(value) || typeof value.code !== "string" || !Object.hasOwn(workspaceMemberFailures, value.code))
49111
49201
  return null;
49112
49202
  const code = value.code;
49113
49203
  return workspaceMemberFailures[code][0] === status ? code : null;
@@ -49116,14 +49206,14 @@ function parseWorkspaceMembersPage(value) {
49116
49206
  const fail2 = () => {
49117
49207
  throw new Error("The server returned an invalid workspace roster.");
49118
49208
  };
49119
- 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)
49209
+ 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)
49120
49210
  return fail2();
49121
49211
  const members = value.members.map((row) => parseMember(row, fail2));
49122
49212
  if (new Set(members.map((row) => row.membershipId)).size !== members.length)
49123
49213
  return fail2();
49124
49214
  return { organizationId: value.organizationId, members, nextCursor: value.nextCursor };
49125
49215
  }
49126
- var record = (value) => !!value && typeof value === "object" && !Array.isArray(value), cursor = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,512}$/.test(value), 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), isRole = (value) => typeof value === "string" && ["owner", "admin", "member", "viewer"].includes(value), WorkspaceMemberInputError, invalidMemberResult = "The server returned an invalid workspace member result. Refresh the roster before another action.", workspaceMemberFailures;
49216
+ var record2 = (value) => !!value && typeof value === "object" && !Array.isArray(value), cursor = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,512}$/.test(value), 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), isRole = (value) => typeof value === "string" && ["owner", "admin", "member", "viewer"].includes(value), WorkspaceMemberInputError, invalidMemberResult = "The server returned an invalid workspace member result. Refresh the roster before another action.", workspaceMemberFailures;
49127
49217
  var init_remote_workspace = __esm(() => {
49128
49218
  WorkspaceMemberInputError = class WorkspaceMemberInputError extends Error {
49129
49219
  constructor() {
@@ -49163,14 +49253,14 @@ function readIdentity(env3 = process.env) {
49163
49253
  const parsed = JSON.parse(readFileSync12(getIdentityFilePath(env3), "utf-8"));
49164
49254
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
49165
49255
  return {};
49166
- const record2 = parsed;
49256
+ const record3 = parsed;
49167
49257
  const selected = resolveSkillsApiOrigin(env3)?.origin;
49168
- const bound = typeof record2.apiUrl === "string" ? record2.apiUrl : readCredentialValue(SKILLS_BOUND_API_URL, env3) ?? readStoredApiUrl(env3) ?? defaultFleetGatewayBaseUrl("skills");
49258
+ const bound = typeof record3.apiUrl === "string" ? record3.apiUrl : readCredentialValue(SKILLS_BOUND_API_URL, env3) ?? readStoredApiUrl(env3) ?? defaultFleetGatewayBaseUrl("skills");
49169
49259
  if (selected && normalizeSkillsApiOrigin(bound) !== selected)
49170
49260
  return {};
49171
49261
  const identity2 = {};
49172
49262
  for (const field of ["email", "orgId", "orgSlug", "userId"]) {
49173
- const value = record2[field];
49263
+ const value = record3[field];
49174
49264
  if (typeof value === "string" && value.length > 0)
49175
49265
  identity2[field] = value;
49176
49266
  }
@@ -49319,44 +49409,44 @@ var init_auth_store = __esm(() => {
49319
49409
 
49320
49410
  // src/lib/remote-run-contract.ts
49321
49411
  function normalizeRemoteSkillRunContract(payload, fallbackSkill) {
49322
- const record2 = isRecord3(payload) ? payload : {};
49412
+ const record3 = isRecord3(payload) ? payload : {};
49323
49413
  return {
49324
49414
  contractVersion: REMOTE_SKILL_RUN_CONTRACT_VERSION,
49325
- ...pickString(record2, "id"),
49326
- skill: pickStringValue(record2, "skill") ?? fallbackSkill,
49327
- ...pickString(record2, "requestedSlug"),
49328
- ...pickString(record2, "status"),
49329
- ...pickNumber(record2, "exitCode"),
49330
- ...pickString(record2, "correlationId"),
49331
- ...pickString(record2, "createdAt"),
49332
- ...pickString(record2, "startedAt"),
49333
- ...pickString(record2, "completedAt"),
49334
- ...pickNumber(record2, "durationMs"),
49335
- ...pickString(record2, "outputType"),
49336
- ...hasOwn(record2, "outputPreview") ? { outputPreview: record2.outputPreview } : {},
49337
- ...pickString(record2, "errorCode"),
49338
- ...pickString(record2, "errorMessage"),
49339
- ...pickString(record2, "error"),
49340
- ...pickString(record2, "code"),
49341
- ...hasOwn(record2, "details") ? { details: record2.details } : {}
49415
+ ...pickString(record3, "id"),
49416
+ skill: pickStringValue(record3, "skill") ?? fallbackSkill,
49417
+ ...pickString(record3, "requestedSlug"),
49418
+ ...pickString(record3, "status"),
49419
+ ...pickNumber(record3, "exitCode"),
49420
+ ...pickString(record3, "correlationId"),
49421
+ ...pickString(record3, "createdAt"),
49422
+ ...pickString(record3, "startedAt"),
49423
+ ...pickString(record3, "completedAt"),
49424
+ ...pickNumber(record3, "durationMs"),
49425
+ ...pickString(record3, "outputType"),
49426
+ ...hasOwn(record3, "outputPreview") ? { outputPreview: record3.outputPreview } : {},
49427
+ ...pickString(record3, "errorCode"),
49428
+ ...pickString(record3, "errorMessage"),
49429
+ ...pickString(record3, "error"),
49430
+ ...pickString(record3, "code"),
49431
+ ...hasOwn(record3, "details") ? { details: record3.details } : {}
49342
49432
  };
49343
49433
  }
49344
49434
  function isRecord3(value) {
49345
49435
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
49346
49436
  }
49347
- function hasOwn(record2, key) {
49348
- return Object.prototype.hasOwnProperty.call(record2, key);
49437
+ function hasOwn(record3, key) {
49438
+ return Object.prototype.hasOwnProperty.call(record3, key);
49349
49439
  }
49350
- function pickString(record2, key) {
49351
- const value = pickStringValue(record2, key);
49440
+ function pickString(record3, key) {
49441
+ const value = pickStringValue(record3, key);
49352
49442
  return value === undefined ? {} : { [key]: value };
49353
49443
  }
49354
- function pickStringValue(record2, key) {
49355
- const value = record2[key];
49444
+ function pickStringValue(record3, key) {
49445
+ const value = record3[key];
49356
49446
  return typeof value === "string" ? value : undefined;
49357
49447
  }
49358
- function pickNumber(record2, key) {
49359
- const value = record2[key];
49448
+ function pickNumber(record3, key) {
49449
+ const value = record3[key];
49360
49450
  return typeof value === "number" && Number.isFinite(value) ? { [key]: value } : {};
49361
49451
  }
49362
49452
  var REMOTE_SKILL_RUN_CONTRACT_VERSION = 1;
@@ -49548,11 +49638,11 @@ function parseUpdatedProfile(value) {
49548
49638
  return { user: { id: user.id, email: user.email, displayName: user.displayName, role: user.role } };
49549
49639
  }
49550
49640
  function parseUpdatedWorkspace(value) {
49551
- const organization = isRecord4(value) && value.organization;
49552
- if (!isRecord4(organization) || !string(organization.id) || !string(organization.slug) || !string(organization.name)) {
49641
+ const organization2 = isRecord4(value) && value.organization;
49642
+ if (!isRecord4(organization2) || !string(organization2.id) || !string(organization2.slug) || !string(organization2.name)) {
49553
49643
  throw new Error("The server returned an invalid workspace.");
49554
49644
  }
49555
- return { organization: { id: organization.id, slug: organization.slug, name: organization.name } };
49645
+ return { organization: { id: organization2.id, slug: organization2.slug, name: organization2.name } };
49556
49646
  }
49557
49647
 
49558
49648
  // src/lib/remote-client.ts
@@ -49560,6 +49650,7 @@ var exports_remote_client = {};
49560
49650
  __export(exports_remote_client, {
49561
49651
  createRemoteSkillsClientReadOnly: () => createRemoteSkillsClientReadOnly,
49562
49652
  createRemoteSkillsClient: () => createRemoteSkillsClient,
49653
+ RemoteWorkspaceSelectionError: () => RemoteWorkspaceSelectionError,
49563
49654
  RemoteWorkspaceMemberError: () => RemoteWorkspaceMemberError,
49564
49655
  RemoteSkillsClient: () => RemoteSkillsClient,
49565
49656
  RemoteRouteUnsupportedError: () => RemoteRouteUnsupportedError,
@@ -49579,6 +49670,7 @@ class RemoteSkillsClient {
49579
49670
  return fetch(`${this.apiUrl}${path}`, {
49580
49671
  ...options,
49581
49672
  redirect: "error",
49673
+ credentials: "omit",
49582
49674
  signal: options?.signal ?? AbortSignal.timeout(15000),
49583
49675
  headers: {
49584
49676
  Authorization: `Bearer ${this.apiKey}`,
@@ -49685,6 +49777,65 @@ class RemoteSkillsClient {
49685
49777
  async getIdentity() {
49686
49778
  return (await this.requestNewRoute("/api/auth/whoami")).json();
49687
49779
  }
49780
+ async listAccountWorkspaces(expectedUserId) {
49781
+ const expected = expectedUserId === undefined ? undefined : workspaceExpectedUserId(expectedUserId);
49782
+ const connection = new RemoteSkillsClient(this.apiKey, this.apiUrl);
49783
+ let identity2;
49784
+ if (expected !== undefined) {
49785
+ const value = await connection.requestWorkspaceSelection("/api/auth/whoami");
49786
+ if (!value || typeof value !== "object" || value.authMethod !== "jwt")
49787
+ throw new RemoteWorkspaceSelectionError("/api/v1/account/workspaces", "INTERACTIVE_SESSION_REQUIRED");
49788
+ identity2 = parseWorkspaceIdentity(value, expected);
49789
+ }
49790
+ const result2 = parseAccountWorkspaces(await connection.requestWorkspaceSelection("/api/v1/account/workspaces"));
49791
+ const current = result2.workspaces.find((workspace) => workspace.current);
49792
+ if (identity2 && (current.membershipId !== identity2.user.membershipId || current.organization.id !== identity2.organization.id))
49793
+ throw new WorkspaceIdentityMismatchError;
49794
+ return result2;
49795
+ }
49796
+ async switchWorkspace(context) {
49797
+ const target = workspaceContext(context);
49798
+ const connection = new RemoteSkillsClient(this.apiKey, this.apiUrl);
49799
+ const value = await connection.requestWorkspaceSelection("/api/auth/whoami");
49800
+ if (!value || typeof value !== "object" || value.authMethod !== "jwt")
49801
+ throw new RemoteWorkspaceSelectionError("/api/v1/account/workspaces/switch", "INTERACTIVE_SESSION_REQUIRED");
49802
+ parseWorkspaceIdentity(value, target.userId);
49803
+ const selected = parseWorkspaceSession(await connection.requestWorkspaceSelection("/api/v1/account/workspaces/switch", {
49804
+ method: "POST",
49805
+ body: JSON.stringify({ membershipId: target.membershipId })
49806
+ }), target);
49807
+ const verified = await new RemoteSkillsClient(selected.token, connection.apiUrl).requestWorkspaceSelection("/api/auth/whoami");
49808
+ if (!verified || typeof verified !== "object" || verified.authMethod !== "jwt")
49809
+ throw new RemoteWorkspaceSelectionError("/api/v1/account/workspaces/switch", "INTERACTIVE_SESSION_REQUIRED");
49810
+ const identity2 = parseWorkspaceIdentity(verified, target.userId);
49811
+ if (identity2.user.membershipId !== target.membershipId || identity2.organization.id !== selected.organization.id)
49812
+ throw new WorkspaceIdentityMismatchError;
49813
+ return { token: selected.token, ...identity2 };
49814
+ }
49815
+ async requestWorkspaceSelection(path, options) {
49816
+ let response;
49817
+ try {
49818
+ response = await this.request(path, { ...options, credentials: "omit" });
49819
+ } catch {
49820
+ throw new Error("Unable to reach the Skills workspace API.");
49821
+ }
49822
+ let value;
49823
+ try {
49824
+ value = JSON.parse(new TextDecoder().decode(await readBoundedResponse(response, response.ok ? 1024 * 1024 : 4096)));
49825
+ } catch {
49826
+ if (response.ok)
49827
+ throw new Error(invalidWorkspaceResult);
49828
+ }
49829
+ if (!response.ok) {
49830
+ const code = workspaceSelectionFailure(value, response.status);
49831
+ if (code)
49832
+ throw new RemoteWorkspaceSelectionError(path, code);
49833
+ if (response.status === 404 || response.status === 405)
49834
+ throw new RemoteRouteUnsupportedError(path, response.status, this.apiUrl);
49835
+ throw new RemoteRequestError(path, response.status);
49836
+ }
49837
+ return value;
49838
+ }
49688
49839
  async updateProfile(input) {
49689
49840
  const body = customerNamePatch(input, "displayName");
49690
49841
  return parseUpdatedProfile(await (await this.requestNewRoute("/api/v1/account/profile", { method: "PATCH", body: JSON.stringify(body) })).json());
@@ -49987,13 +50138,13 @@ class RemoteSkillsClient {
49987
50138
  return normalizeUpdatedSincePage(await response.json());
49988
50139
  }
49989
50140
  }
49990
- function requireOptionalString(record2, field) {
49991
- if (record2[field] === undefined)
50141
+ function requireOptionalString(record3, field) {
50142
+ if (record3[field] === undefined)
49992
50143
  return;
49993
- if (typeof record2[field] !== "string") {
50144
+ if (typeof record3[field] !== "string") {
49994
50145
  throw new Error(`Remote payload did not match the expected contract (${field} must be a string when present)`);
49995
50146
  }
49996
- return record2[field];
50147
+ return record3[field];
49997
50148
  }
49998
50149
  function isVersionRecord(value) {
49999
50150
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -50015,19 +50166,19 @@ function normalizePin(entry) {
50015
50166
  if (!entry || typeof entry !== "object") {
50016
50167
  throw new Error("Remote pin payload did not match the expected contract (expected an object)");
50017
50168
  }
50018
- const record2 = entry;
50019
- const slug = typeof record2.slug === "string" && record2.slug.trim() ? record2.slug.trim() : undefined;
50169
+ const record3 = entry;
50170
+ const slug = typeof record3.slug === "string" && record3.slug.trim() ? record3.slug.trim() : undefined;
50020
50171
  if (!slug) {
50021
50172
  throw new Error("Remote pin payload did not match the expected contract (missing slug)");
50022
50173
  }
50023
50174
  let metadata;
50024
- if (record2.metadata !== undefined) {
50025
- if (!record2.metadata || typeof record2.metadata !== "object" || Array.isArray(record2.metadata)) {
50175
+ if (record3.metadata !== undefined) {
50176
+ if (!record3.metadata || typeof record3.metadata !== "object" || Array.isArray(record3.metadata)) {
50026
50177
  throw new Error("Remote pin payload did not match the expected contract (metadata must be a JSON object when present)");
50027
50178
  }
50028
- metadata = record2.metadata;
50179
+ metadata = record3.metadata;
50029
50180
  }
50030
- const pinnedAt = requireOptionalString(record2, "pinnedAt");
50181
+ const pinnedAt = requireOptionalString(record3, "pinnedAt");
50031
50182
  return {
50032
50183
  slug,
50033
50184
  ...pinnedAt !== undefined ? { pinnedAt } : {},
@@ -50044,16 +50195,16 @@ function normalizeSkillSummary(entry) {
50044
50195
  if (!entry || typeof entry !== "object") {
50045
50196
  throw new Error("Remote skill payload did not match the expected contract (expected an object)");
50046
50197
  }
50047
- const record2 = entry;
50048
- const slug = typeof record2.slug === "string" && record2.slug.trim() ? record2.slug.trim() : undefined;
50198
+ const record3 = entry;
50199
+ const slug = typeof record3.slug === "string" && record3.slug.trim() ? record3.slug.trim() : undefined;
50049
50200
  if (!slug) {
50050
50201
  throw new Error("Remote skill payload did not match the expected contract (missing slug)");
50051
50202
  }
50052
50203
  return {
50053
50204
  slug,
50054
- ...requireOptionalString(record2, "name") !== undefined ? { name: requireOptionalString(record2, "name") } : {},
50055
- ...requireOptionalString(record2, "version") !== undefined ? { version: requireOptionalString(record2, "version") } : {},
50056
- ...requireOptionalString(record2, "updatedAt") !== undefined ? { updatedAt: requireOptionalString(record2, "updatedAt") } : {}
50205
+ ...requireOptionalString(record3, "name") !== undefined ? { name: requireOptionalString(record3, "name") } : {},
50206
+ ...requireOptionalString(record3, "version") !== undefined ? { version: requireOptionalString(record3, "version") } : {},
50207
+ ...requireOptionalString(record3, "updatedAt") !== undefined ? { updatedAt: requireOptionalString(record3, "updatedAt") } : {}
50057
50208
  };
50058
50209
  }
50059
50210
  function normalizeSkillSummaryList(payload) {
@@ -50106,12 +50257,12 @@ function normalizeUpdatedSincePage(payload) {
50106
50257
  if (!payload || typeof payload !== "object") {
50107
50258
  throw new Error("Updated-since payload did not match the expected contract (expected an object)");
50108
50259
  }
50109
- const record2 = payload;
50110
- if (!Array.isArray(record2.skills)) {
50260
+ const record3 = payload;
50261
+ if (!Array.isArray(record3.skills)) {
50111
50262
  throw new Error("Updated-since payload did not match the expected contract (missing skills array)");
50112
50263
  }
50113
- const skills = record2.skills.map(normalizeSkillSummary);
50114
- const nextCursor = record2.nextCursor === undefined || record2.nextCursor === null ? null : record2.nextCursor;
50264
+ const skills = record3.skills.map(normalizeSkillSummary);
50265
+ const nextCursor = record3.nextCursor === undefined || record3.nextCursor === null ? null : record3.nextCursor;
50115
50266
  if (nextCursor !== null && typeof nextCursor !== "string") {
50116
50267
  throw new Error("Updated-since payload did not match the expected contract (nextCursor must be a string or absent)");
50117
50268
  }
@@ -50124,8 +50275,9 @@ async function createRemoteSkillsClient(env3 = process.env) {
50124
50275
  function createRemoteSkillsClientReadOnly(env3 = process.env) {
50125
50276
  return createRemoteSkillsClient(env3);
50126
50277
  }
50127
- var RemoteRouteUnsupportedError, RemoteRequestError, RemoteWorkspaceMemberError, RemoteCapabilityUnavailableError, INVALID_SKILL_VERSION_RESPONSE = "Remote skill version payload did not match the expected contract.";
50278
+ var RemoteRouteUnsupportedError, RemoteRequestError, RemoteWorkspaceMemberError, RemoteWorkspaceSelectionError, RemoteCapabilityUnavailableError, INVALID_SKILL_VERSION_RESPONSE = "Remote skill version payload did not match the expected contract.";
50128
50279
  var init_remote_client = __esm(() => {
50280
+ init_remote_workspace_selection();
50129
50281
  init_remote_workspace();
50130
50282
  init_remote_workspace();
50131
50283
  init_auth_store();
@@ -50163,6 +50315,15 @@ var init_remote_client = __esm(() => {
50163
50315
  this.message = workspaceMemberFailures[code][1];
50164
50316
  }
50165
50317
  };
50318
+ RemoteWorkspaceSelectionError = class RemoteWorkspaceSelectionError extends RemoteRequestError {
50319
+ code;
50320
+ constructor(path, code) {
50321
+ super(path, workspaceSelectionFailures[code][0]);
50322
+ this.code = code;
50323
+ this.name = "RemoteWorkspaceSelectionError";
50324
+ this.message = workspaceSelectionFailures[code][1];
50325
+ }
50326
+ };
50166
50327
  RemoteCapabilityUnavailableError = class RemoteCapabilityUnavailableError extends RemoteRequestError {
50167
50328
  code = "SUBSCRIPTION_CHECKOUT_UNAVAILABLE";
50168
50329
  constructor() {
@@ -50891,16 +51052,16 @@ function installBundleAtomically(name, entries, options = {}, marker = {}) {
50891
51052
  }
50892
51053
  return { path: target, created };
50893
51054
  }
50894
- function writePullMarker(dir, record2) {
51055
+ function writePullMarker(dir, record3) {
50895
51056
  const marker = {
50896
51057
  managedBy: "@hasna/skills",
50897
- skill: record2.skill,
50898
- source: record2.source ?? "pull",
50899
- ...record2.version ? { version: record2.version } : {},
50900
- ...record2.contentHash ? { contentHash: record2.contentHash } : {},
50901
- ...record2.sourceCommit ? { sourceCommit: record2.sourceCommit } : {},
50902
- ...record2.signature ? { signature: record2.signature } : {},
50903
- ...record2.revisionId ? { revisionId: record2.revisionId } : {},
51058
+ skill: record3.skill,
51059
+ source: record3.source ?? "pull",
51060
+ ...record3.version ? { version: record3.version } : {},
51061
+ ...record3.contentHash ? { contentHash: record3.contentHash } : {},
51062
+ ...record3.sourceCommit ? { sourceCommit: record3.sourceCommit } : {},
51063
+ ...record3.signature ? { signature: record3.signature } : {},
51064
+ ...record3.revisionId ? { revisionId: record3.revisionId } : {},
50904
51065
  syncedAt: new Date().toISOString()
50905
51066
  };
50906
51067
  writeFileSync8(join20(dir, PULL_MARKER_FILE), `${JSON.stringify(marker, null, 2)}
@@ -50915,19 +51076,19 @@ async function safeMeta(client, slug) {
50915
51076
  }
50916
51077
  if (!raw || typeof raw !== "object")
50917
51078
  return null;
50918
- const record2 = raw;
50919
- const kind = record2.kind === "instruction" || record2.kind === "executable" ? record2.kind : undefined;
50920
- const tags = Array.isArray(record2.tags) ? record2.tags.filter((tag) => typeof tag === "string" && tag.trim().length > 0) : undefined;
51079
+ const record3 = raw;
51080
+ const kind = record3.kind === "instruction" || record3.kind === "executable" ? record3.kind : undefined;
51081
+ const tags = Array.isArray(record3.tags) ? record3.tags.filter((tag) => typeof tag === "string" && tag.trim().length > 0) : undefined;
50921
51082
  return {
50922
- ...str(record2.displayName) ? { displayName: str(record2.displayName) } : {},
50923
- ...str(record2.description) ? { description: str(record2.description) } : {},
50924
- ...str(record2.category) ? { category: str(record2.category) } : {},
51083
+ ...str(record3.displayName) ? { displayName: str(record3.displayName) } : {},
51084
+ ...str(record3.description) ? { description: str(record3.description) } : {},
51085
+ ...str(record3.category) ? { category: str(record3.category) } : {},
50925
51086
  ...tags && tags.length ? { tags } : {},
50926
- ...str(record2.version) ? { version: str(record2.version) } : {},
51087
+ ...str(record3.version) ? { version: str(record3.version) } : {},
50927
51088
  ...kind ? { kind } : {},
50928
- ...REVISION_ID_PATTERN.test(str(record2.revisionId) ?? "") ? { revisionId: str(record2.revisionId) } : {},
50929
- ...typeof record2.skillMd === "string" && record2.skillMd.length > 0 ? { skillMd: record2.skillMd } : {},
50930
- ...str(record2.publishedSource) ? { publishedSource: str(record2.publishedSource) } : {}
51089
+ ...REVISION_ID_PATTERN.test(str(record3.revisionId) ?? "") ? { revisionId: str(record3.revisionId) } : {},
51090
+ ...typeof record3.skillMd === "string" && record3.skillMd.length > 0 ? { skillMd: record3.skillMd } : {},
51091
+ ...str(record3.publishedSource) ? { publishedSource: str(record3.publishedSource) } : {}
50931
51092
  };
50932
51093
  }
50933
51094
  function pickCorpusOptions(options) {
@@ -50936,8 +51097,8 @@ function pickCorpusOptions(options) {
50936
51097
  function extractSlug(entry) {
50937
51098
  if (!entry || typeof entry !== "object")
50938
51099
  return;
50939
- const record2 = entry;
50940
- return str(record2.slug) ?? str(record2.name);
51100
+ const record3 = entry;
51101
+ return str(record3.slug) ?? str(record3.name);
50941
51102
  }
50942
51103
  function dedupe(values2) {
50943
51104
  return [...new Set(values2)];
@@ -51210,17 +51371,17 @@ var init_install = __esm(() => {
51210
51371
 
51211
51372
  // src/lib/compact-output.ts
51212
51373
  function truncateText(value, maxChars = 96) {
51213
- const text = String(value ?? "").replace(/\s+/g, " ").trim();
51214
- if (text.length <= maxChars)
51215
- return text;
51216
- return `${text.slice(0, Math.max(0, maxChars - 3)).trimEnd()}...`;
51374
+ const text2 = String(value ?? "").replace(/\s+/g, " ").trim();
51375
+ if (text2.length <= maxChars)
51376
+ return text2;
51377
+ return `${text2.slice(0, Math.max(0, maxChars - 3)).trimEnd()}...`;
51217
51378
  }
51218
51379
  function previewText(value, maxChars = DEFAULT_PREVIEW_CHARS) {
51219
- const text = String(value ?? "");
51380
+ const text2 = String(value ?? "");
51220
51381
  return {
51221
- text: text.length > maxChars ? `${text.slice(0, Math.max(0, maxChars - 3))}...` : text,
51222
- length: text.length,
51223
- truncated: text.length > maxChars
51382
+ text: text2.length > maxChars ? `${text2.slice(0, Math.max(0, maxChars - 3))}...` : text2,
51383
+ length: text2.length,
51384
+ truncated: text2.length > maxChars
51224
51385
  };
51225
51386
  }
51226
51387
  function parsePageLimit(value, fallback, options = {}) {
@@ -51339,10 +51500,10 @@ function handleBrowseError(error) {
51339
51500
  process.exitCode = 1;
51340
51501
  }
51341
51502
  async function writeJson(value, space) {
51342
- const text = `${JSON.stringify(value, null, space)}
51503
+ const text2 = `${JSON.stringify(value, null, space)}
51343
51504
  `;
51344
51505
  await new Promise((resolve3, reject2) => {
51345
- process.stdout.write(text, (error) => {
51506
+ process.stdout.write(text2, (error) => {
51346
51507
  if (error)
51347
51508
  reject2(error);
51348
51509
  else
@@ -52049,12 +52210,12 @@ function generateSkillMd(name) {
52049
52210
  `) + `
52050
52211
  `;
52051
52212
  }
52052
- function extractEnvVars(text) {
52213
+ function extractEnvVars(text2) {
52053
52214
  const envVars = new Set;
52054
52215
  for (const pattern of [ENV_VAR_PATTERN, GENERIC_ENV_PATTERN]) {
52055
52216
  pattern.lastIndex = 0;
52056
52217
  let match;
52057
- while ((match = pattern.exec(text)) !== null) {
52218
+ while ((match = pattern.exec(text2)) !== null) {
52058
52219
  envVars.add(match[1]);
52059
52220
  }
52060
52221
  }
@@ -53260,8 +53421,8 @@ function writeRollbackRecord(mode, entries, appDir = getDataDir()) {
53260
53421
  const dir = join24(appDir, ROLLBACK_DIRNAME);
53261
53422
  mkdirSync9(dir, { recursive: true });
53262
53423
  const file = join24(dir, `${mode}-${Date.now()}.json`);
53263
- const record2 = { version: 1, mode, timestamp: new Date().toISOString(), entries };
53264
- writeFileSync10(file, `${JSON.stringify(record2, null, 2)}
53424
+ const record3 = { version: 1, mode, timestamp: new Date().toISOString(), entries };
53425
+ writeFileSync10(file, `${JSON.stringify(record3, null, 2)}
53265
53426
  `);
53266
53427
  return file;
53267
53428
  }
@@ -53568,10 +53729,10 @@ function setEnvAssignment(path, assignment) {
53568
53729
  }
53569
53730
  let prepared = initial2;
53570
53731
  if (previous) {
53571
- const original = readFileSync20(descriptor), text = original.toString("utf8");
53572
- if (!Buffer.from(text, "utf8").equals(original))
53732
+ const original = readFileSync20(descriptor), text2 = original.toString("utf8");
53733
+ if (!Buffer.from(text2, "utf8").equals(original))
53573
53734
  throw new EnvAssignmentError(INVALID_LAYOUT);
53574
- prepared = prepareEnvAssignment(assignment, text);
53735
+ prepared = prepareEnvAssignment(assignment, text2);
53575
53736
  }
53576
53737
  const bytes = Buffer.from(prepared.content, "utf8");
53577
53738
  let written = 0;
@@ -54139,7 +54300,7 @@ function createSkillRun(params, targetDir = process.cwd()) {
54139
54300
  mkdirSync10(logsDir, { recursive: true });
54140
54301
  mkdirSync10(exportDir, { recursive: true });
54141
54302
  mkdirSync10(join27(root, "tmp"), { recursive: true });
54142
- const record2 = {
54303
+ const record3 = {
54143
54304
  id,
54144
54305
  skill: skillName,
54145
54306
  status: params.status ?? "running",
@@ -54157,10 +54318,10 @@ function createSkillRun(params, targetDir = process.cwd()) {
54157
54318
  logsDir: toProjectRelative(targetDir, logsDir)
54158
54319
  }
54159
54320
  };
54160
- const context = { targetDir, runDir, exportDir, logsDir, record: record2 };
54321
+ const context = { targetDir, runDir, exportDir, logsDir, record: record3 };
54161
54322
  writeRunRecord(context);
54162
54323
  writeArtifactsManifest(context, []);
54163
- appendRunEvent(context, "created", { status: record2.status });
54324
+ appendRunEvent(context, "created", { status: record3.status });
54164
54325
  return context;
54165
54326
  }
54166
54327
  function completeSkillRun(context, patch) {
@@ -54210,9 +54371,9 @@ function listSkillRuns(targetDir = process.cwd(), limit = 50) {
54210
54371
  if (!statSync14(dayDir).isDirectory())
54211
54372
  continue;
54212
54373
  for (const runId of readdirSync13(dayDir).sort().reverse()) {
54213
- const record2 = readRunRecord(join27(dayDir, runId));
54214
- if (record2)
54215
- records.push(record2);
54374
+ const record3 = readRunRecord(join27(dayDir, runId));
54375
+ if (record3)
54376
+ records.push(record3);
54216
54377
  if (records.length >= limit)
54217
54378
  return records;
54218
54379
  }
@@ -54224,9 +54385,9 @@ function findSkillRun(runId, targetDir = process.cwd()) {
54224
54385
  if (!existsSync25(runsRoot))
54225
54386
  return null;
54226
54387
  for (const day of readdirSync13(runsRoot)) {
54227
- const record2 = readRunRecord(join27(runsRoot, day, runId));
54228
- if (record2)
54229
- return record2;
54388
+ const record3 = readRunRecord(join27(runsRoot, day, runId));
54389
+ if (record3)
54390
+ return record3;
54230
54391
  }
54231
54392
  return null;
54232
54393
  }
@@ -55062,7 +55223,7 @@ function datetime(args) {
55062
55223
  const timeRegex2 = `${time2}(?:${opts.join("|")})`;
55063
55224
  return new RegExp(`^${dateSource}T(?:${timeRegex2})$`);
55064
55225
  }
55065
- var cuid, cuid2, ulid, xid, ksuid, nanoid, duration, guid, uuid2 = (version) => {
55226
+ var cuid, cuid2, ulid, xid, ksuid, nanoid, duration, guid, uuid3 = (version) => {
55066
55227
  if (!version)
55067
55228
  return /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000)$/;
55068
55229
  return new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${version}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`);
@@ -55856,9 +56017,9 @@ var init_schemas = __esm(() => {
55856
56017
  const v = versionMap[def.version];
55857
56018
  if (v === undefined)
55858
56019
  throw new Error(`Invalid UUID version: "${def.version}"`);
55859
- def.pattern ?? (def.pattern = uuid2(v));
56020
+ def.pattern ?? (def.pattern = uuid3(v));
55860
56021
  } else
55861
- def.pattern ?? (def.pattern = uuid2());
56022
+ def.pattern ?? (def.pattern = uuid3());
55862
56023
  $ZodStringFormat.init(inst, def);
55863
56024
  });
55864
56025
  $ZodEmail = /* @__PURE__ */ $constructor("$ZodEmail", (inst, def) => {
@@ -58338,7 +58499,7 @@ function intersection2(left, right) {
58338
58499
  right
58339
58500
  });
58340
58501
  }
58341
- function record2(keyType, valueType, params) {
58502
+ function record3(keyType, valueType, params) {
58342
58503
  return new ZodRecord2({
58343
58504
  type: "record",
58344
58505
  keyType,
@@ -59039,7 +59200,7 @@ var init_types2 = __esm(() => {
59039
59200
  });
59040
59201
  FormElicitationCapabilitySchema = intersection2(object2({
59041
59202
  applyDefaults: boolean2().optional()
59042
- }), record2(string3(), unknown()));
59203
+ }), record3(string3(), unknown()));
59043
59204
  ElicitationCapabilitySchema = preprocess((value) => {
59044
59205
  if (value && typeof value === "object" && !Array.isArray(value)) {
59045
59206
  if (Object.keys(value).length === 0) {
@@ -59050,7 +59211,7 @@ var init_types2 = __esm(() => {
59050
59211
  }, intersection2(object2({
59051
59212
  form: FormElicitationCapabilitySchema.optional(),
59052
59213
  url: AssertObjectSchema.optional()
59053
- }), record2(string3(), unknown()).optional()));
59214
+ }), record3(string3(), unknown()).optional()));
59054
59215
  ClientTasksCapabilitySchema = looseObject({
59055
59216
  list: AssertObjectSchema.optional(),
59056
59217
  cancel: AssertObjectSchema.optional(),
@@ -59073,7 +59234,7 @@ var init_types2 = __esm(() => {
59073
59234
  }).optional()
59074
59235
  });
59075
59236
  ClientCapabilitiesSchema = object2({
59076
- experimental: record2(string3(), AssertObjectSchema).optional(),
59237
+ experimental: record3(string3(), AssertObjectSchema).optional(),
59077
59238
  sampling: object2({
59078
59239
  context: AssertObjectSchema.optional(),
59079
59240
  tools: AssertObjectSchema.optional()
@@ -59083,7 +59244,7 @@ var init_types2 = __esm(() => {
59083
59244
  listChanged: boolean2().optional()
59084
59245
  }).optional(),
59085
59246
  tasks: ClientTasksCapabilitySchema.optional(),
59086
- extensions: record2(string3(), AssertObjectSchema).optional()
59247
+ extensions: record3(string3(), AssertObjectSchema).optional()
59087
59248
  });
59088
59249
  InitializeRequestParamsSchema = BaseRequestParamsSchema.extend({
59089
59250
  protocolVersion: string3(),
@@ -59095,7 +59256,7 @@ var init_types2 = __esm(() => {
59095
59256
  params: InitializeRequestParamsSchema
59096
59257
  });
59097
59258
  ServerCapabilitiesSchema = object2({
59098
- experimental: record2(string3(), AssertObjectSchema).optional(),
59259
+ experimental: record3(string3(), AssertObjectSchema).optional(),
59099
59260
  logging: AssertObjectSchema.optional(),
59100
59261
  completions: AssertObjectSchema.optional(),
59101
59262
  prompts: object2({
@@ -59109,7 +59270,7 @@ var init_types2 = __esm(() => {
59109
59270
  listChanged: boolean2().optional()
59110
59271
  }).optional(),
59111
59272
  tasks: ServerTasksCapabilitySchema.optional(),
59112
- extensions: record2(string3(), AssertObjectSchema).optional()
59273
+ extensions: record3(string3(), AssertObjectSchema).optional()
59113
59274
  });
59114
59275
  InitializeResultSchema = ResultSchema.extend({
59115
59276
  protocolVersion: string3(),
@@ -59196,7 +59357,7 @@ var init_types2 = __esm(() => {
59196
59357
  ResourceContentsSchema = object2({
59197
59358
  uri: string3(),
59198
59359
  mimeType: optional(string3()),
59199
- _meta: record2(string3(), unknown()).optional()
59360
+ _meta: record3(string3(), unknown()).optional()
59200
59361
  });
59201
59362
  TextResourceContentsSchema = ResourceContentsSchema.extend({
59202
59363
  text: string3()
@@ -59301,7 +59462,7 @@ var init_types2 = __esm(() => {
59301
59462
  });
59302
59463
  GetPromptRequestParamsSchema = BaseRequestParamsSchema.extend({
59303
59464
  name: string3(),
59304
- arguments: record2(string3(), string3()).optional()
59465
+ arguments: record3(string3(), string3()).optional()
59305
59466
  });
59306
59467
  GetPromptRequestSchema = RequestSchema.extend({
59307
59468
  method: literal("prompts/get"),
@@ -59311,34 +59472,34 @@ var init_types2 = __esm(() => {
59311
59472
  type: literal("text"),
59312
59473
  text: string3(),
59313
59474
  annotations: AnnotationsSchema.optional(),
59314
- _meta: record2(string3(), unknown()).optional()
59475
+ _meta: record3(string3(), unknown()).optional()
59315
59476
  });
59316
59477
  ImageContentSchema = object2({
59317
59478
  type: literal("image"),
59318
59479
  data: Base64Schema,
59319
59480
  mimeType: string3(),
59320
59481
  annotations: AnnotationsSchema.optional(),
59321
- _meta: record2(string3(), unknown()).optional()
59482
+ _meta: record3(string3(), unknown()).optional()
59322
59483
  });
59323
59484
  AudioContentSchema = object2({
59324
59485
  type: literal("audio"),
59325
59486
  data: Base64Schema,
59326
59487
  mimeType: string3(),
59327
59488
  annotations: AnnotationsSchema.optional(),
59328
- _meta: record2(string3(), unknown()).optional()
59489
+ _meta: record3(string3(), unknown()).optional()
59329
59490
  });
59330
59491
  ToolUseContentSchema = object2({
59331
59492
  type: literal("tool_use"),
59332
59493
  name: string3(),
59333
59494
  id: string3(),
59334
- input: record2(string3(), unknown()),
59335
- _meta: record2(string3(), unknown()).optional()
59495
+ input: record3(string3(), unknown()),
59496
+ _meta: record3(string3(), unknown()).optional()
59336
59497
  });
59337
59498
  EmbeddedResourceSchema = object2({
59338
59499
  type: literal("resource"),
59339
59500
  resource: union2([TextResourceContentsSchema, BlobResourceContentsSchema]),
59340
59501
  annotations: AnnotationsSchema.optional(),
59341
- _meta: record2(string3(), unknown()).optional()
59502
+ _meta: record3(string3(), unknown()).optional()
59342
59503
  });
59343
59504
  ResourceLinkSchema = ResourceSchema.extend({
59344
59505
  type: literal("resource_link")
@@ -59378,17 +59539,17 @@ var init_types2 = __esm(() => {
59378
59539
  description: string3().optional(),
59379
59540
  inputSchema: object2({
59380
59541
  type: literal("object"),
59381
- properties: record2(string3(), AssertObjectSchema).optional(),
59542
+ properties: record3(string3(), AssertObjectSchema).optional(),
59382
59543
  required: array(string3()).optional()
59383
59544
  }).catchall(unknown()),
59384
59545
  outputSchema: object2({
59385
59546
  type: literal("object"),
59386
- properties: record2(string3(), AssertObjectSchema).optional(),
59547
+ properties: record3(string3(), AssertObjectSchema).optional(),
59387
59548
  required: array(string3()).optional()
59388
59549
  }).catchall(unknown()).optional(),
59389
59550
  annotations: ToolAnnotationsSchema.optional(),
59390
59551
  execution: ToolExecutionSchema.optional(),
59391
- _meta: record2(string3(), unknown()).optional()
59552
+ _meta: record3(string3(), unknown()).optional()
59392
59553
  });
59393
59554
  ListToolsRequestSchema = PaginatedRequestSchema.extend({
59394
59555
  method: literal("tools/list")
@@ -59398,7 +59559,7 @@ var init_types2 = __esm(() => {
59398
59559
  });
59399
59560
  CallToolResultSchema = ResultSchema.extend({
59400
59561
  content: array(ContentBlockSchema).default([]),
59401
- structuredContent: record2(string3(), unknown()).optional(),
59562
+ structuredContent: record3(string3(), unknown()).optional(),
59402
59563
  isError: boolean2().optional()
59403
59564
  });
59404
59565
  CompatibilityCallToolResultSchema = CallToolResultSchema.or(ResultSchema.extend({
@@ -59406,7 +59567,7 @@ var init_types2 = __esm(() => {
59406
59567
  }));
59407
59568
  CallToolRequestParamsSchema = TaskAugmentedRequestParamsSchema.extend({
59408
59569
  name: string3(),
59409
- arguments: record2(string3(), unknown()).optional()
59570
+ arguments: record3(string3(), unknown()).optional()
59410
59571
  });
59411
59572
  CallToolRequestSchema = RequestSchema.extend({
59412
59573
  method: literal("tools/call"),
@@ -59455,7 +59616,7 @@ var init_types2 = __esm(() => {
59455
59616
  content: array(ContentBlockSchema).default([]),
59456
59617
  structuredContent: object2({}).loose().optional(),
59457
59618
  isError: boolean2().optional(),
59458
- _meta: record2(string3(), unknown()).optional()
59619
+ _meta: record3(string3(), unknown()).optional()
59459
59620
  });
59460
59621
  SamplingContentSchema = discriminatedUnion("type", [TextContentSchema, ImageContentSchema, AudioContentSchema]);
59461
59622
  SamplingMessageContentBlockSchema = discriminatedUnion("type", [
@@ -59468,7 +59629,7 @@ var init_types2 = __esm(() => {
59468
59629
  SamplingMessageSchema = object2({
59469
59630
  role: RoleSchema,
59470
59631
  content: union2([SamplingMessageContentBlockSchema, array(SamplingMessageContentBlockSchema)]),
59471
- _meta: record2(string3(), unknown()).optional()
59632
+ _meta: record3(string3(), unknown()).optional()
59472
59633
  });
59473
59634
  CreateMessageRequestParamsSchema = TaskAugmentedRequestParamsSchema.extend({
59474
59635
  messages: array(SamplingMessageSchema),
@@ -59581,7 +59742,7 @@ var init_types2 = __esm(() => {
59581
59742
  message: string3(),
59582
59743
  requestedSchema: object2({
59583
59744
  type: literal("object"),
59584
- properties: record2(string3(), PrimitiveSchemaDefinitionSchema),
59745
+ properties: record3(string3(), PrimitiveSchemaDefinitionSchema),
59585
59746
  required: array(string3()).optional()
59586
59747
  })
59587
59748
  });
@@ -59605,7 +59766,7 @@ var init_types2 = __esm(() => {
59605
59766
  });
59606
59767
  ElicitResultSchema = ResultSchema.extend({
59607
59768
  action: _enum(["accept", "decline", "cancel"]),
59608
- content: preprocess((val) => val === null ? undefined : val, record2(string3(), union2([string3(), number2(), boolean2(), array(string3())])).optional())
59769
+ content: preprocess((val) => val === null ? undefined : val, record3(string3(), union2([string3(), number2(), boolean2(), array(string3())])).optional())
59609
59770
  });
59610
59771
  ResourceTemplateReferenceSchema = object2({
59611
59772
  type: literal("ref/resource"),
@@ -59622,7 +59783,7 @@ var init_types2 = __esm(() => {
59622
59783
  value: string3()
59623
59784
  }),
59624
59785
  context: object2({
59625
- arguments: record2(string3(), string3()).optional()
59786
+ arguments: record3(string3(), string3()).optional()
59626
59787
  }).optional()
59627
59788
  });
59628
59789
  CompleteRequestSchema = RequestSchema.extend({
@@ -59639,7 +59800,7 @@ var init_types2 = __esm(() => {
59639
59800
  RootSchema = object2({
59640
59801
  uri: string3().startsWith("file://"),
59641
59802
  name: string3().optional(),
59642
- _meta: record2(string3(), unknown()).optional()
59803
+ _meta: record3(string3(), unknown()).optional()
59643
59804
  });
59644
59805
  ListRootsRequestSchema = RequestSchema.extend({
59645
59806
  method: literal("roots/list"),
@@ -66892,7 +67053,7 @@ var require_core = __commonJS((exports) => {
66892
67053
  errorsText(errors4 = this.errors, { separator = ", ", dataVar = "data" } = {}) {
66893
67054
  if (!errors4 || errors4.length === 0)
66894
67055
  return "No errors";
66895
- return errors4.map((e) => `${dataVar}${e.instancePath} ${e.message}`).reduce((text, msg) => text + separator + msg);
67056
+ return errors4.map((e) => `${dataVar}${e.instancePath} ${e.message}`).reduce((text2, msg) => text2 + separator + msg);
66896
67057
  }
66897
67058
  $dataMetaSchema(metaSchema, keywordsJsonPointers) {
66898
67059
  const rules = this.RULES.all;
@@ -67303,8 +67464,8 @@ var require_multipleOf = __commonJS((exports) => {
67303
67464
  const { gen, data, schemaCode, it } = cxt;
67304
67465
  const prec = it.opts.multipleOfPrecision;
67305
67466
  const res = gen.let("res");
67306
- const invalid = prec ? (0, codegen_1._)`Math.abs(Math.round(${res}) - ${res}) > 1e-${prec}` : (0, codegen_1._)`${res} !== parseInt(${res})`;
67307
- cxt.fail$data((0, codegen_1._)`(${schemaCode} === 0 || (${res} = ${data}/${schemaCode}, ${invalid}))`);
67467
+ const invalid2 = prec ? (0, codegen_1._)`Math.abs(Math.round(${res}) - ${res}) > 1e-${prec}` : (0, codegen_1._)`${res} !== parseInt(${res})`;
67468
+ cxt.fail$data((0, codegen_1._)`(${schemaCode} === 0 || (${res} = ${data}/${schemaCode}, ${invalid2}))`);
67308
67469
  }
67309
67470
  };
67310
67471
  exports.default = def;
@@ -73400,13 +73561,13 @@ async function requestAuthApi(instance, path, options) {
73400
73561
  apiUrl: safeUrl
73401
73562
  });
73402
73563
  }
73403
- const text = await res.text();
73404
- const body = text ? parseJsonBody(text) : {};
73564
+ const text2 = await res.text();
73565
+ const body = text2 ? parseJsonBody(text2) : {};
73405
73566
  if (!res.ok) {
73406
- const record4 = isRecord5(body) ? body : {};
73407
- const detail = typeof record4.detail === "string" ? record4.detail : undefined;
73408
- const error2 = typeof record4.error === "string" ? record4.error : undefined;
73409
- const code = typeof record4.code === "string" ? record4.code : undefined;
73567
+ const record5 = isRecord5(body) ? body : {};
73568
+ const detail = typeof record5.detail === "string" ? record5.detail : undefined;
73569
+ const error2 = typeof record5.error === "string" ? record5.error : undefined;
73570
+ const code = typeof record5.code === "string" ? record5.code : undefined;
73410
73571
  throw new HostedApiError(detail || error2 || `${res.status} ${res.statusText}`, {
73411
73572
  status: res.status,
73412
73573
  code,
@@ -73417,15 +73578,15 @@ async function requestAuthApi(instance, path, options) {
73417
73578
  }
73418
73579
  return body;
73419
73580
  }
73420
- function parseJsonBody(text) {
73581
+ function parseJsonBody(text2) {
73421
73582
  try {
73422
- return JSON.parse(text);
73583
+ return JSON.parse(text2);
73423
73584
  } catch {
73424
- return { detail: condenseErrorBody(text) };
73585
+ return { detail: condenseErrorBody(text2) };
73425
73586
  }
73426
73587
  }
73427
- function condenseErrorBody(text) {
73428
- const stripped = /<[a-z!/]/i.test(text) ? text.replace(/<(script|style)[\s\S]*?<\/\1>/gi, " ").replace(/<[^>]*>/g, " ") : text;
73588
+ function condenseErrorBody(text2) {
73589
+ const stripped = /<[a-z!/]/i.test(text2) ? text2.replace(/<(script|style)[\s\S]*?<\/\1>/gi, " ").replace(/<[^>]*>/g, " ") : text2;
73429
73590
  const collapsed = stripped.replace(/\s+/g, " ").trim();
73430
73591
  if (collapsed.length <= MAX_ERROR_DETAIL_LENGTH)
73431
73592
  return collapsed;
@@ -73452,7 +73613,12 @@ class RemoteSkillsAuthClient {
73452
73613
  pollDevice(deviceCode) {
73453
73614
  return this.request("/api/auth/device/token", { method: "POST", body: JSON.stringify({ deviceCode }) });
73454
73615
  }
73455
- async sessionClient(email2, code) {
73616
+ async sessionClient(email2, code, context) {
73617
+ if (context !== undefined) {
73618
+ const target = workspaceContext(context), apiOrigin2 = this.apiOrigin;
73619
+ const session = await this.switchWorkspace(email2, code, target);
73620
+ return new RemoteSkillsClient(session.token, apiOrigin2);
73621
+ }
73456
73622
  const apiOrigin = this.apiOrigin;
73457
73623
  if (!email2.includes("@") || !/^\d{6}$/.test(code))
73458
73624
  throw new Error("Fresh email and six-digit verification code are required to manage this account");
@@ -73461,34 +73627,76 @@ class RemoteSkillsAuthClient {
73461
73627
  throw new Error("The server did not return an authorized account session");
73462
73628
  return new RemoteSkillsClient(login.token, apiOrigin);
73463
73629
  }
73464
- async createApiKey(email2, code, name, scopes) {
73465
- return (await this.sessionClient(email2, code)).createApiKey(name, scopes);
73630
+ async listAccountWorkspaces(email2, code, expectedUserId) {
73631
+ const login = await this.workspaceLogin(email2, code, expectedUserId);
73632
+ const result2 = await new RemoteSkillsClient(login.token, login.apiOrigin).listAccountWorkspaces(login.userId);
73633
+ return { userId: login.userId, ...result2 };
73466
73634
  }
73467
- async listApiKeys(email2, code) {
73468
- return (await this.sessionClient(email2, code)).listApiKeys();
73635
+ async switchWorkspace(email2, code, context) {
73636
+ const target = workspaceContext(context);
73637
+ const login = await this.workspaceLogin(email2, code, target.userId);
73638
+ return new RemoteSkillsClient(login.token, login.apiOrigin).switchWorkspace(target);
73639
+ }
73640
+ async workspaceLogin(email2, code, expectedUserId) {
73641
+ const expected = expectedUserId === undefined ? undefined : workspaceExpectedUserId(expectedUserId);
73642
+ const apiOrigin = this.apiOrigin;
73643
+ if (typeof email2 !== "string" || !email2.includes("@") || typeof code !== "string" || !/^\d{6}$/.test(code))
73644
+ throw new Error("Fresh email and six-digit verification code are required to manage this account");
73645
+ let response;
73646
+ try {
73647
+ response = await fetch(`${apiOrigin}/api/auth/verify`, {
73648
+ method: "POST",
73649
+ redirect: "error",
73650
+ credentials: "omit",
73651
+ signal: AbortSignal.timeout(15000),
73652
+ headers: { "Content-Type": "application/json" },
73653
+ body: JSON.stringify({ email: email2, code })
73654
+ });
73655
+ } catch {
73656
+ throw new HostedApiError("Unable to verify the Skills account.");
73657
+ }
73658
+ if (!response.ok) {
73659
+ response.body?.cancel().catch(() => {});
73660
+ throw new HostedApiError("Unable to verify the Skills account.", { status: response.status });
73661
+ }
73662
+ let value;
73663
+ try {
73664
+ value = JSON.parse(new TextDecoder().decode(await readBoundedResponse(response, 64 * 1024)));
73665
+ } catch {
73666
+ throw new HostedApiError("The server returned an invalid account verification result.");
73667
+ }
73668
+ return { ...parseWorkspaceLogin(value, expected), apiOrigin };
73469
73669
  }
73470
- async revokeApiKey(email2, code, keyId) {
73471
- return (await this.sessionClient(email2, code)).revokeApiKey(keyId);
73670
+ async createApiKey(email2, code, name, scopes, context) {
73671
+ const capturedScopes = scopes === undefined ? undefined : [...scopes];
73672
+ return (await this.sessionClient(email2, code, context)).createApiKey(name, capturedScopes);
73472
73673
  }
73473
- async updateProfile(email2, code, input) {
73474
- customerNamePatch(input, "displayName");
73475
- return (await this.sessionClient(email2, code)).updateProfile(input);
73674
+ async listApiKeys(email2, code, context) {
73675
+ return (await this.sessionClient(email2, code, context)).listApiKeys();
73476
73676
  }
73477
- async updateCurrentWorkspace(email2, code, input) {
73478
- customerNamePatch(input, "name");
73479
- return (await this.sessionClient(email2, code)).updateCurrentWorkspace(input);
73677
+ async revokeApiKey(email2, code, keyId, context) {
73678
+ return (await this.sessionClient(email2, code, context)).revokeApiKey(keyId);
73480
73679
  }
73481
- async listWorkspaceMembers(email2, code, options = {}) {
73680
+ async updateProfile(email2, code, input, context) {
73681
+ const body = customerNamePatch(input, "displayName");
73682
+ return (await this.sessionClient(email2, code, context)).updateProfile({ displayName: body.displayName });
73683
+ }
73684
+ async updateCurrentWorkspace(email2, code, input, context) {
73685
+ const body = customerNamePatch(input, "name");
73686
+ return (await this.sessionClient(email2, code, context)).updateCurrentWorkspace({ name: body.name });
73687
+ }
73688
+ async listWorkspaceMembers(email2, code, options = {}, context) {
73482
73689
  workspaceMembersQuery(options);
73483
- return (await this.sessionClient(email2, code)).listWorkspaceMembers(options);
73690
+ const captured = { ...options };
73691
+ return (await this.sessionClient(email2, code, context)).listWorkspaceMembers(captured);
73484
73692
  }
73485
- async setWorkspaceMemberRole(email2, code, membershipId, input) {
73693
+ async setWorkspaceMemberRole(email2, code, membershipId, input, context) {
73486
73694
  const captured = workspaceMemberRoleInput(membershipId, input);
73487
- return (await this.sessionClient(email2, code)).setWorkspaceMemberRole(captured.membershipId, captured.body);
73695
+ return (await this.sessionClient(email2, code, context)).setWorkspaceMemberRole(captured.membershipId, captured.body);
73488
73696
  }
73489
- async removeWorkspaceMember(email2, code, membershipId, input) {
73697
+ async removeWorkspaceMember(email2, code, membershipId, input, context) {
73490
73698
  const captured = workspaceMemberRemovalInput(membershipId, input);
73491
- return (await this.sessionClient(email2, code)).removeWorkspaceMember(captured.membershipId, captured.body);
73699
+ return (await this.sessionClient(email2, code, context)).removeWorkspaceMember(captured.membershipId, captured.body);
73492
73700
  }
73493
73701
  request(path, options) {
73494
73702
  if (!["/api/auth/login", "/api/auth/verify", "/api/auth/device/start", "/api/auth/device/token", "/api/auth/keys", "/api/auth/whoami"].includes(path))
@@ -73498,6 +73706,8 @@ class RemoteSkillsAuthClient {
73498
73706
  }
73499
73707
  var MAX_ERROR_DETAIL_LENGTH = 200, HostedApiError;
73500
73708
  var init_remote_auth = __esm(() => {
73709
+ init_remote_workspace_selection();
73710
+ init_remote_files();
73501
73711
  init_remote_workspace();
73502
73712
  init_remote_workspace();
73503
73713
  init_remote_client();
@@ -73520,6 +73730,224 @@ var init_remote_auth = __esm(() => {
73520
73730
  };
73521
73731
  });
73522
73732
 
73733
+ // src/lib/workspace-profile.ts
73734
+ import { constants as constants4, closeSync as closeSync4, fstatSync as fstatSync4, lstatSync as lstatSync6, mkdirSync as mkdirSync14, mkdtempSync as mkdtempSync4, openSync as openSync4, readFileSync as readFileSync25, renameSync as renameSync6, rmSync as rmSync7, writeFileSync as writeFileSync14 } from "fs";
73735
+ import { dirname as dirname10, join as join32 } from "path";
73736
+ function stat(path) {
73737
+ try {
73738
+ return lstatSync6(path);
73739
+ } catch (error2) {
73740
+ if (error2.code === "ENOENT")
73741
+ return null;
73742
+ throw error2;
73743
+ }
73744
+ }
73745
+ function safeText(file) {
73746
+ if (stat(file) === null)
73747
+ return null;
73748
+ const fd = openSync4(file, constants4.O_RDONLY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK);
73749
+ try {
73750
+ const s = fstatSync4(fd);
73751
+ if (!s.isFile() || s.size > 65536 || ![256, 384].includes(s.mode & 4095) || process.getuid && s.uid !== process.getuid())
73752
+ return fail2("The selected profile must use bounded owner-only regular files.");
73753
+ return readFileSync25(fd, "utf8");
73754
+ } finally {
73755
+ closeSync4(fd);
73756
+ }
73757
+ }
73758
+ function checkIdentityMetadata(file, identity2) {
73759
+ const text2 = safeText(file);
73760
+ if (text2 === null)
73761
+ return;
73762
+ let value;
73763
+ try {
73764
+ value = JSON.parse(text2);
73765
+ } catch {
73766
+ return fail2("The profile identity metadata is invalid. Sign in again before managing this workspace.");
73767
+ }
73768
+ if (!value || typeof value !== "object" || Array.isArray(value))
73769
+ return fail2("The profile identity metadata is invalid.");
73770
+ for (const [key, expected] of Object.entries({ userId: identity2.user.id, orgId: identity2.organization.id })) {
73771
+ if (value[key] !== undefined && value[key] !== expected)
73772
+ return fail2("The profile identity metadata does not match its authenticated key. Sign in again before managing this workspace.");
73773
+ }
73774
+ }
73775
+ async function keyIdentity(key, origin) {
73776
+ const value = await new RemoteSkillsClient(key, origin).getIdentity();
73777
+ if (value.authMethod !== "api_key")
73778
+ return fail2("The selected credential is not a workspace API key.");
73779
+ const user = value.user;
73780
+ return parseWorkspaceIdentity(value, workspaceExpectedUserId(user?.id));
73781
+ }
73782
+ function prepareProfileWorkspace(action, source = process.env) {
73783
+ const env3 = { ...source }, origin = getApiUrl(action, env3), profile = selectedSkillsProfile(env3);
73784
+ const unchanged2 = captureSkillsCredentialFiles(skillsProfileCredentialFiles(env3));
73785
+ return { origin, async resolve() {
73786
+ unchanged2();
73787
+ if (!profile)
73788
+ return { origin, context: undefined, unchanged: unchanged2 };
73789
+ const connection = await resolveSkillsConnection(env3);
73790
+ if (!connection || connection.apiOrigin !== origin)
73791
+ return fail2("The selected profile has no usable credential for this server.");
73792
+ const identity2 = await keyIdentity(connection.apiKey, origin);
73793
+ checkIdentityMetadata(getIdentityFilePath(env3), identity2);
73794
+ unchanged2();
73795
+ const context = { userId: identity2.user.id, membershipId: identity2.user.membershipId };
73796
+ return { origin, context, unchanged: unchanged2 };
73797
+ } };
73798
+ }
73799
+ async function captureProfileWorkspace(action, source = process.env) {
73800
+ return prepareProfileWorkspace(action, source).resolve();
73801
+ }
73802
+ async function prepareWorkspaceEnrollment(membershipId, source = process.env) {
73803
+ workspaceExpectedUserId(membershipId);
73804
+ const env3 = { ...source }, profile = selectedSkillsProfile(env3);
73805
+ if (!profile)
73806
+ return fail2("Workspace login requires an explicit HASNA_PROFILE name.");
73807
+ if (["HASNA_SKILLS_API_KEY_OVERRIDE", "HASNA_SKILLS_API_KEY_REF", "HASNA_SKILLS_API_KEY", "SKILLS_API_KEY"].some((name) => env3[name]?.trim()))
73808
+ return fail2("Clear injected API keys before enrolling a named workspace profile.");
73809
+ const origin = getApiUrl("Sign in to a workspace", env3);
73810
+ const file = getAuthFilePath(env3), identityFile = getIdentityFilePath(env3);
73811
+ const paths = [...new Set([...skillsProfileCredentialFiles(env3), file, identityFile])];
73812
+ const unchangedFiles = captureSkillsCredentialFiles(paths);
73813
+ const old = safeText(file), oldIdentity = safeText(identityFile);
73814
+ const managed = new Set(["HASNA_SKILLS_API_KEY", "SKILLS_API_KEY", "HASNA_SKILLS_API_URL", "SKILLS_API_URL", "HASNA_SKILLS_BOUND_API_URL"]);
73815
+ const lines = (old ?? "").split(/\r?\n/).filter((line) => !managed.has(/^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/.exec(line)?.[1] ?? ""));
73816
+ const credentialBody = (key) => [...lines.filter(Boolean), `HASNA_SKILLS_API_KEY=${key}`, `HASNA_SKILLS_API_URL=${origin}`, `HASNA_SKILLS_BOUND_API_URL=${origin}`, ""].join(`
73817
+ `);
73818
+ if (Buffer.byteLength(credentialBody("x".repeat(8192)), "utf8") > 65536)
73819
+ return fail2("The selected profile has insufficient space for a bounded credential. Reduce its unrelated configuration before signing in.");
73820
+ const parents = [];
73821
+ for (let path = dirname10(file);; path = dirname10(path)) {
73822
+ const before2 = stat(path);
73823
+ if (before2 && (!before2.isDirectory() || before2.isSymbolicLink()))
73824
+ return fail2("The profile directory must not be a symbolic link.");
73825
+ parents.push([path, before2]);
73826
+ if (path === dirname10(path))
73827
+ break;
73828
+ }
73829
+ const unchanged2 = () => {
73830
+ unchangedFiles();
73831
+ for (const [path, before2] of parents) {
73832
+ const now3 = stat(path);
73833
+ if (!before2 ? now3 !== null : !now3 || !now3.isDirectory() || before2.dev !== now3.dev || before2.ino !== now3.ino)
73834
+ changed();
73835
+ }
73836
+ };
73837
+ let expected;
73838
+ try {
73839
+ const connection = await resolveSkillsConnection(env3);
73840
+ if (connection) {
73841
+ if (connection.apiKeyTier !== "profile" || connection.apiOrigin !== origin)
73842
+ return fail2("Workspace login must resolve only the explicitly named profile.");
73843
+ expected = await keyIdentity(connection.apiKey, origin);
73844
+ checkIdentityMetadata(identityFile, expected);
73845
+ }
73846
+ } catch (error2) {
73847
+ if (!(error2 instanceof SkillsFleetCredentialError && error2.code === "MISSING_API_CREDENTIAL" && (old === null || !/^\s*(?:export\s+)?(?:HASNA_SKILLS_API_KEY|SKILLS_API_KEY)\s*=/m.test(old))))
73848
+ throw error2;
73849
+ }
73850
+ unchanged2();
73851
+ return {
73852
+ profile,
73853
+ origin,
73854
+ async complete(email2, code) {
73855
+ unchanged2();
73856
+ if (!email2.includes("@") || !/^\d{6}$/.test(code))
73857
+ return fail2("A fresh email and six-digit verification code are required.");
73858
+ if (expected && expected.user.email.toLowerCase() !== email2.toLowerCase())
73859
+ return fail2("This profile belongs to another account. Use a different profile or ordinary replacement login.");
73860
+ let issued = false;
73861
+ try {
73862
+ const result2 = await new RemoteSkillsAuthClient(origin).verifyCode(email2, code);
73863
+ const login = parseWorkspaceLogin(result2, expected?.user.id);
73864
+ if (result2.firstLogin === true)
73865
+ return fail2("This sign-in created a new account using the server signup policy. Finish ordinary account login before enrolling a workspace profile.");
73866
+ const session = await new RemoteSkillsClient(login.token, origin).switchWorkspace({ userId: login.userId, membershipId });
73867
+ if (session.user.email.toLowerCase() !== email2.toLowerCase())
73868
+ return fail2("The verified account does not match the requested email.");
73869
+ if (session.user.role === "viewer")
73870
+ return fail2("Viewer memberships cannot enroll API keys.");
73871
+ unchanged2();
73872
+ issued = true;
73873
+ const created = await new RemoteSkillsClient(session.token, origin).createApiKey("cli");
73874
+ const verified = await keyIdentity(created.key, origin);
73875
+ if (verified.user.id !== session.user.id || verified.user.membershipId !== membershipId || verified.organization.id !== session.organization.id)
73876
+ return fail2("The issued key does not match the selected workspace.");
73877
+ unchanged2();
73878
+ if (!created.key.trim() || /[^\x21-\x7e]/.test(created.key) || created.key.length > 8192)
73879
+ return fail2("The server returned an invalid API key.");
73880
+ const body = credentialBody(created.key);
73881
+ if (Buffer.byteLength(body, "utf8") > 65536)
73882
+ return fail2("The new profile exceeds the credential reader size limit.");
73883
+ const identity2 = JSON.stringify({ email: verified.user.email, userId: verified.user.id, orgId: verified.organization.id, orgSlug: verified.organization.slug, apiUrl: origin }, null, 2) + `
73884
+ `;
73885
+ mkdirSync14(dirname10(file), { recursive: true, mode: 448 });
73886
+ const temp = mkdtempSync4(join32(dirname10(file), ".workspace-login-"));
73887
+ let identityInstalled = false;
73888
+ try {
73889
+ writeFileSync14(join32(temp, "credentials"), body, { mode: 384, flag: "wx" });
73890
+ writeFileSync14(join32(temp, "identity"), identity2, { mode: 384, flag: "wx" });
73891
+ unchangedFiles();
73892
+ for (const [path, before2] of parents) {
73893
+ const now3 = stat(path);
73894
+ if (!now3 || !now3.isDirectory() || now3.isSymbolicLink() || before2 && (before2.dev !== now3.dev || before2.ino !== now3.ino))
73895
+ changed();
73896
+ if (!before2 && now3 && ((now3.mode & 63) !== 0 || process.getuid && now3.uid !== process.getuid()))
73897
+ changed();
73898
+ }
73899
+ renameSync6(join32(temp, "identity"), identityFile);
73900
+ identityInstalled = true;
73901
+ renameSync6(join32(temp, "credentials"), file);
73902
+ } catch (error2) {
73903
+ if (identityInstalled) {
73904
+ if (oldIdentity === null)
73905
+ rmSync7(identityFile, { force: true });
73906
+ else {
73907
+ writeFileSync14(join32(temp, "restore"), oldIdentity, { mode: 384, flag: "wx" });
73908
+ renameSync6(join32(temp, "restore"), identityFile);
73909
+ }
73910
+ }
73911
+ throw error2;
73912
+ } finally {
73913
+ rmSync7(temp, { recursive: true, force: true });
73914
+ }
73915
+ return {
73916
+ status: "authenticated",
73917
+ profile,
73918
+ apiUrl: origin,
73919
+ userId: verified.user.id,
73920
+ email: verified.user.email,
73921
+ membershipId,
73922
+ organization: verified.organization.slug,
73923
+ organizationId: verified.organization.id,
73924
+ role: verified.user.role,
73925
+ keyCreated: true
73926
+ };
73927
+ } catch (error2) {
73928
+ if (issued)
73929
+ return fail2("Workspace key issuance was attempted, but enrollment could not be confirmed. Inspect the selected profile and workspace keys before retrying; do not retry automatically.");
73930
+ if (error2 instanceof WorkspaceProfileError)
73931
+ throw error2;
73932
+ return fail2("Unable to verify and select the workspace. Check the account, membership, selected server and fresh code. No enrollment key was requested.");
73933
+ }
73934
+ }
73935
+ };
73936
+ }
73937
+ var WorkspaceProfileError, fail2 = (message) => {
73938
+ throw new WorkspaceProfileError(message);
73939
+ }, changed = () => fail2("The selected profile changed during sign-in. No credential was saved; retry with a stable profile.");
73940
+ var init_workspace_profile = __esm(() => {
73941
+ init_auth_store();
73942
+ init_fleet_credentials();
73943
+ init_instance_credentials();
73944
+ init_remote_client();
73945
+ init_remote_auth();
73946
+ init_remote_workspace_selection();
73947
+ WorkspaceProfileError = class WorkspaceProfileError extends Error {
73948
+ };
73949
+ });
73950
+
73523
73951
  // src/mcp/remote-customer-tools.ts
73524
73952
  function registerRemoteCustomerTools(server) {
73525
73953
  const memberRole = exports_external.enum(["owner", "admin", "member", "viewer"]);
@@ -73533,9 +73961,9 @@ function registerRemoteCustomerTools(server) {
73533
73961
  title: "Set Current Workspace Member Role",
73534
73962
  description: "Change exactly this membership incarnation with its observed expectedRole and fresh verification. The server enforces owner/admin policy. No automatic refresh or retry; saved credentials stay unchanged.",
73535
73963
  inputSchema: exports_external.object({ ...memberInput, role: memberRole }).strict()
73536
- }, async ({ membershipId, role, expectedRole, email: email2, code }) => {
73964
+ }, async ({ membershipId, role: role2, expectedRole, email: email2, code }) => {
73537
73965
  try {
73538
- return mcpJson(await new RemoteSkillsAuthClient(getApiUrl("Set workspace member role")).setWorkspaceMemberRole(email2, code, membershipId, { role, expectedRole }));
73966
+ return mcpJson(await freshAccount("Set workspace member role", (client, context) => client.setWorkspaceMemberRole(email2, code, membershipId, { role: role2, expectedRole }, context)));
73539
73967
  } catch (error2) {
73540
73968
  return memberError(error2);
73541
73969
  }
@@ -73546,7 +73974,7 @@ function registerRemoteCustomerTools(server) {
73546
73974
  inputSchema: exports_external.object(memberInput).strict()
73547
73975
  }, async ({ membershipId, expectedRole, email: email2, code }) => {
73548
73976
  try {
73549
- return mcpJson(await new RemoteSkillsAuthClient(getApiUrl("Remove workspace member")).removeWorkspaceMember(email2, code, membershipId, { expectedRole }));
73977
+ return mcpJson(await freshAccount("Remove workspace member", (client, context) => client.removeWorkspaceMember(email2, code, membershipId, { expectedRole }, context)));
73550
73978
  } catch (error2) {
73551
73979
  return memberError(error2);
73552
73980
  }
@@ -73562,7 +73990,7 @@ function registerRemoteCustomerTools(server) {
73562
73990
  }).strict()
73563
73991
  }, async ({ email: email2, code, limit, cursor: cursor2 }) => {
73564
73992
  try {
73565
- return mcpJson(await new RemoteSkillsAuthClient(getApiUrl("List workspace members")).listWorkspaceMembers(email2, code, { limit, cursor: cursor2 }));
73993
+ return mcpJson(await freshAccount("List workspace members", (client, context) => client.listWorkspaceMembers(email2, code, { limit, cursor: cursor2 }, context)));
73566
73994
  } catch {
73567
73995
  return mcpError("WORKSPACE_MEMBERS_FAILED", "Unable to list workspace members. Check the selected server, owner/admin permissions, pagination and fresh verification code.");
73568
73996
  }
@@ -73574,8 +74002,7 @@ function registerRemoteCustomerTools(server) {
73574
74002
  inputSchema: exports_external.object({ name: exports_external.string().min(1), email: exports_external.string().email(), code: exports_external.string().regex(/^\d{6}$/) }).strict()
73575
74003
  }, async ({ name, email: email2, code }) => {
73576
74004
  try {
73577
- const client = new RemoteSkillsAuthClient(getApiUrl("Update customer name"));
73578
- return mcpJson(kind === "profile" ? await client.updateProfile(email2, code, { displayName: name }) : await client.updateCurrentWorkspace(email2, code, { name }));
74005
+ return mcpJson(await freshAccount("Update customer name", async (client, context) => kind === "profile" ? client.updateProfile(email2, code, { displayName: name }, context) : client.updateCurrentWorkspace(email2, code, { name }, context)));
73579
74006
  } catch {
73580
74007
  return mcpError("NAME_UPDATE_FAILED", "Unable to update the name. Check the selected server, name, permissions and fresh verification code.");
73581
74008
  }
@@ -73597,9 +74024,9 @@ function registerRemoteCustomerTools(server) {
73597
74024
  inputSchema: { email: exports_external.string().email(), code: exports_external.string().regex(/^\d{6}$/) }
73598
74025
  }, async ({ email: email2, code }) => {
73599
74026
  try {
73600
- return mcpJson(await new RemoteSkillsAuthClient(getApiUrl("List API keys")).listApiKeys(email2, code));
73601
- } catch (error2) {
73602
- return mcpError("KEY_LIST_FAILED", error2.message);
74027
+ return mcpJson(await freshAccount("List API keys", (client, context) => client.listApiKeys(email2, code, context)));
74028
+ } catch {
74029
+ return mcpError("KEY_LIST_FAILED", "Unable to list API keys. Check the selected profile, server, account and fresh verification code.");
73603
74030
  }
73604
74031
  });
73605
74032
  server.registerTool("revoke_api_key", {
@@ -73608,9 +74035,9 @@ function registerRemoteCustomerTools(server) {
73608
74035
  inputSchema: { key_id: exports_external.string().min(1), email: exports_external.string().email(), code: exports_external.string().regex(/^\d{6}$/) }
73609
74036
  }, async ({ key_id, email: email2, code }) => {
73610
74037
  try {
73611
- return mcpJson(await new RemoteSkillsAuthClient(getApiUrl("Revoke API key")).revokeApiKey(email2, code, key_id));
73612
- } catch (error2) {
73613
- return mcpError("KEY_REVOKE_FAILED", error2.message);
74038
+ return mcpJson(await freshAccount("Revoke API key", (client, context) => client.revokeApiKey(email2, code, key_id, context)));
74039
+ } catch {
74040
+ return mcpError("KEY_REVOKE_FAILED", "Unable to revoke this API key. Check the selected profile, key, account and fresh verification code.");
73614
74041
  }
73615
74042
  });
73616
74043
  server.registerTool("create_api_key", {
@@ -73618,10 +74045,11 @@ function registerRemoteCustomerTools(server) {
73618
74045
  description: "Create an API key using fresh email OTP reauthentication; returns its secret once. A stored API key cannot grant this authority.",
73619
74046
  inputSchema: { name: exports_external.string().min(1), email: exports_external.string().email(), code: exports_external.string().regex(/^\d{6}$/), scopes: exports_external.array(exports_external.string()).optional() }
73620
74047
  }, async ({ name, email: email2, code, scopes }) => {
74048
+ const capturedScopes = scopes === undefined ? undefined : [...scopes];
73621
74049
  try {
73622
- return mcpJson(await new RemoteSkillsAuthClient(getApiUrl("Create API key")).createApiKey(email2, code, name, scopes));
73623
- } catch (error2) {
73624
- return mcpError("KEY_CREATION_FAILED", error2.message);
74050
+ return mcpJson(await freshAccount("Create API key", (client, context) => client.createApiKey(email2, code, name, capturedScopes, context)));
74051
+ } catch {
74052
+ return mcpError("KEY_CREATION_FAILED", "API key creation could not be confirmed. Check the selected profile and workspace keys before retrying; a lost response may still have created a key.");
73625
74053
  }
73626
74054
  });
73627
74055
  server.registerTool("quote_skill", {
@@ -73655,10 +74083,15 @@ async function callRemote(action) {
73655
74083
  return mcpError("REMOTE_REQUEST_FAILED", error2 instanceof Error ? error2.message : "Skills server request failed");
73656
74084
  }
73657
74085
  }
74086
+ async function freshAccount(action, operation) {
74087
+ const target = await captureProfileWorkspace(action);
74088
+ target.unchanged();
74089
+ return operation(new RemoteSkillsAuthClient(target.origin), target.context);
74090
+ }
73658
74091
  var init_remote_customer_tools = __esm(() => {
73659
74092
  init_zod();
73660
74093
  init_remote_auth();
73661
- init_auth_store();
74094
+ init_workspace_profile();
73662
74095
  init_remote_customer_operations();
73663
74096
  init_remote_client();
73664
74097
  init_helpers();
@@ -74106,9 +74539,9 @@ var init_mcp2 = __esm(() => {
74106
74539
  });
74107
74540
 
74108
74541
  // src/cli/commands/runtime-mcp.ts
74109
- import { existsSync as existsSync30, mkdirSync as mkdirSync14, readFileSync as readFileSync25, writeFileSync as writeFileSync14 } from "fs";
74542
+ import { existsSync as existsSync30, mkdirSync as mkdirSync15, readFileSync as readFileSync26, writeFileSync as writeFileSync15 } from "fs";
74110
74543
  import { homedir as homedir7 } from "os";
74111
- import { dirname as dirname10, join as join32 } from "path";
74544
+ import { dirname as dirname11, join as join33 } from "path";
74112
74545
  async function handleMcp(options) {
74113
74546
  if (options.register) {
74114
74547
  let agents;
@@ -74151,24 +74584,24 @@ async function registerMcpForAgent(agent, command) {
74151
74584
  case "codex":
74152
74585
  return registerCodexMcp(command);
74153
74586
  case "gemini":
74154
- return registerJsonMcpServer(agent, join32(homedir7(), ".gemini", "settings.json"), "mcpServers", {
74587
+ return registerJsonMcpServer(agent, join33(homedir7(), ".gemini", "settings.json"), "mcpServers", {
74155
74588
  command,
74156
74589
  args: []
74157
74590
  });
74158
74591
  case "pi":
74159
- return registerJsonMcpServer(agent, join32(homedir7(), ".pi", "agent", "mcp.json"), "mcpServers", {
74592
+ return registerJsonMcpServer(agent, join33(homedir7(), ".pi", "agent", "mcp.json"), "mcpServers", {
74160
74593
  command,
74161
74594
  args: []
74162
74595
  });
74163
74596
  case "opencode":
74164
74597
  return registerOpenCodeMcp(command);
74165
74598
  case "cursor":
74166
- return registerJsonMcpServer(agent, join32(homedir7(), ".cursor", "mcp.json"), "mcpServers", {
74599
+ return registerJsonMcpServer(agent, join33(homedir7(), ".cursor", "mcp.json"), "mcpServers", {
74167
74600
  command,
74168
74601
  args: []
74169
74602
  });
74170
74603
  case "windsurf":
74171
- return registerJsonMcpServer(agent, join32(homedir7(), ".windsurf", "mcp.json"), "mcpServers", {
74604
+ return registerJsonMcpServer(agent, join33(homedir7(), ".windsurf", "mcp.json"), "mcpServers", {
74172
74605
  command,
74173
74606
  args: []
74174
74607
  });
@@ -74191,7 +74624,7 @@ async function registerClaudeMcp(command) {
74191
74624
  if (exitCode === 0) {
74192
74625
  return { agent: "claude", success: true, command: cliCommand };
74193
74626
  }
74194
- const fallback = registerJsonMcpServer("claude", join32(homedir7(), ".claude", ".mcp.json"), "mcpServers", {
74627
+ const fallback = registerJsonMcpServer("claude", join33(homedir7(), ".claude", ".mcp.json"), "mcpServers", {
74195
74628
  command,
74196
74629
  args: []
74197
74630
  });
@@ -74201,7 +74634,7 @@ async function registerClaudeMcp(command) {
74201
74634
  error: fallback.success ? undefined : `claude exited with ${exitCode}: ${(stderr || stdout).trim()}`
74202
74635
  };
74203
74636
  } catch (err) {
74204
- const fallback = registerJsonMcpServer("claude", join32(homedir7(), ".claude", ".mcp.json"), "mcpServers", {
74637
+ const fallback = registerJsonMcpServer("claude", join33(homedir7(), ".claude", ".mcp.json"), "mcpServers", {
74205
74638
  command,
74206
74639
  args: []
74207
74640
  });
@@ -74213,11 +74646,11 @@ async function registerClaudeMcp(command) {
74213
74646
  }
74214
74647
  }
74215
74648
  function registerCodexMcp(command) {
74216
- const path = join32(homedir7(), ".codex", "config.toml");
74649
+ const path = join33(homedir7(), ".codex", "config.toml");
74217
74650
  const config2 = `[mcp_servers.${MCP_SERVER_NAME}]
74218
74651
  command = ${JSON.stringify(command)}`;
74219
74652
  try {
74220
- const current = existsSync30(path) ? readFileSync25(path, "utf-8") : "";
74653
+ const current = existsSync30(path) ? readFileSync26(path, "utf-8") : "";
74221
74654
  writeTextFile(path, upsertTomlSection(current, `[mcp_servers.${MCP_SERVER_NAME}]`, `command = ${JSON.stringify(command)}`));
74222
74655
  return { agent: "codex", success: true, path, config: config2 };
74223
74656
  } catch (err) {
@@ -74225,7 +74658,7 @@ command = ${JSON.stringify(command)}`;
74225
74658
  }
74226
74659
  }
74227
74660
  function registerOpenCodeMcp(command) {
74228
- const path = join32(homedir7(), ".config", "opencode", "opencode.json");
74661
+ const path = join33(homedir7(), ".config", "opencode", "opencode.json");
74229
74662
  const config2 = JSON.stringify({
74230
74663
  $schema: "https://opencode.ai/config.json",
74231
74664
  mcp: {
@@ -74269,7 +74702,7 @@ function registerJsonMcpServer(agent, path, containerKey, server2) {
74269
74702
  function readJsonObject2(path) {
74270
74703
  if (!existsSync30(path))
74271
74704
  return {};
74272
- const raw = readFileSync25(path, "utf-8").trim();
74705
+ const raw = readFileSync26(path, "utf-8").trim();
74273
74706
  if (!raw)
74274
74707
  return {};
74275
74708
  const parsed = JSON.parse(raw);
@@ -74282,8 +74715,8 @@ function writeJsonObject(path, data) {
74282
74715
  `);
74283
74716
  }
74284
74717
  function writeTextFile(path, content) {
74285
- mkdirSync14(dirname10(path), { recursive: true });
74286
- writeFileSync14(path, content.endsWith(`
74718
+ mkdirSync15(dirname11(path), { recursive: true });
74719
+ writeFileSync15(path, content.endsWith(`
74287
74720
  `) ? content : `${content}
74288
74721
  `);
74289
74722
  }
@@ -74313,7 +74746,7 @@ function findCommandOnPath(command) {
74313
74746
  for (const dir of pathValue.split(":")) {
74314
74747
  if (!dir)
74315
74748
  continue;
74316
- const candidate = join32(dir, command);
74749
+ const candidate = join33(dir, command);
74317
74750
  if (existsSync30(candidate))
74318
74751
  return candidate;
74319
74752
  }
@@ -74375,8 +74808,8 @@ var exports_runtime = {};
74375
74808
  __export(exports_runtime, {
74376
74809
  registerRuntime: () => registerRuntime
74377
74810
  });
74378
- import { lstatSync as lstatSync6, mkdirSync as mkdirSync15, readFileSync as readFileSync26, realpathSync as realpathSync2, writeFileSync as writeFileSync15 } from "fs";
74379
- import { basename as basename5, isAbsolute as isAbsolute4, join as join33 } from "path";
74811
+ import { lstatSync as lstatSync7, mkdirSync as mkdirSync16, readFileSync as readFileSync27, realpathSync as realpathSync2, writeFileSync as writeFileSync16 } from "fs";
74812
+ import { basename as basename5, isAbsolute as isAbsolute4, join as join34 } from "path";
74380
74813
  import { createInterface } from "readline";
74381
74814
  function registerRuntime(parent) {
74382
74815
  parent.command("run").argument("<skill>", "Skill name").argument("[args...]", "Arguments to pass to the skill").allowUnknownOption(true).passThroughOptions(true).option("--json", "Output result as JSON", false).option("--remote", "Run on the configured server, using its catalog and quote", false).option("--yes", "Approve the server's quoted credit cost for this run", false).option("--idempotency-key <key>", "Reuse this key when retrying the same remote submission").option("--file <path>", "Attach a local input file to a remote run (repeatable)", (value, prior) => [...prior, value], []).option("--wait", "Poll remote runs until a terminal status", false).option("--poll-interval-ms <ms>", "Remote polling interval in milliseconds", "1000").option("--poll-timeout-ms <ms>", "Maximum time to wait for a remote run", "300000").description("Run a skill directly").action(async (name, args2, options) => handleRun(name, args2, options));
@@ -74650,10 +75083,10 @@ async function handleRun(name, args2, options) {
74650
75083
  try {
74651
75084
  parsePollingOptions(options);
74652
75085
  inputFiles = (options.file ?? []).map((path) => {
74653
- const info = lstatSync6(path);
75086
+ const info = lstatSync7(path);
74654
75087
  if (!info.isFile() || info.size > 20 * 1024 * 1024)
74655
75088
  throw new Error("Input must be a regular file no larger than 20 MiB");
74656
- return { name: basename5(path), bytes: new Uint8Array(readFileSync26(path)) };
75089
+ return { name: basename5(path), bytes: new Uint8Array(readFileSync27(path)) };
74657
75090
  });
74658
75091
  describeRemoteFiles(inputFiles);
74659
75092
  client = new RemoteSkillsClient(routing.apiKey, routing.apiOrigin);
@@ -75024,7 +75457,7 @@ async function handleExportsDownload(runId, options) {
75024
75457
  const canonicalSkill = typeof remoteRun.skill === "string" ? remoteRun.skill : "remote";
75025
75458
  const requestedSkill = typeof remoteRun.requestedSlug === "string" && remoteRun.requestedSlug.trim() ? remoteRun.requestedSlug : canonicalSkill;
75026
75459
  const exportDir = getRunExportDir(runId, requestedSkill);
75027
- mkdirSync15(exportDir, { recursive: true });
75460
+ mkdirSync16(exportDir, { recursive: true });
75028
75461
  const downloaded = [];
75029
75462
  for (const artifact of artifacts) {
75030
75463
  const artifactId = String(artifact.id || "");
@@ -75032,9 +75465,9 @@ async function handleExportsDownload(runId, options) {
75032
75465
  continue;
75033
75466
  const verified = await client.getVerifiedRunArtifact(runId, artifactId);
75034
75467
  const relativePath = safeArtifactRelativePath(typeof artifact.relativePath === "string" ? artifact.relativePath : artifact.fileName, String(artifact.fileName || artifactId));
75035
- const outputPath = join33(exportDir, relativePath);
75468
+ const outputPath = join34(exportDir, relativePath);
75036
75469
  ensureSafeExportParent(exportDir, relativePath);
75037
- writeFileSync15(outputPath, verified.bytes, { flag: "wx", mode: 384 });
75470
+ writeFileSync16(outputPath, verified.bytes, { flag: "wx", mode: 384 });
75038
75471
  downloaded.push({ id: artifactId, path: outputPath, byteSize: verified.byteSize });
75039
75472
  }
75040
75473
  const payload = {
@@ -75071,14 +75504,14 @@ function ensureSafeExportParent(root, relativePath) {
75071
75504
  let parent = root;
75072
75505
  for (const part of ["", ...parts]) {
75073
75506
  if (part)
75074
- parent = join33(parent, part);
75507
+ parent = join34(parent, part);
75075
75508
  try {
75076
- if (!lstatSync6(parent).isDirectory() || lstatSync6(parent).isSymbolicLink())
75509
+ if (!lstatSync7(parent).isDirectory() || lstatSync7(parent).isSymbolicLink())
75077
75510
  throw new Error("Unsafe artifact directory");
75078
75511
  } catch (error2) {
75079
75512
  if (error2.code !== "ENOENT")
75080
75513
  throw error2;
75081
- mkdirSync15(parent, { mode: 448 });
75514
+ mkdirSync16(parent, { mode: 448 });
75082
75515
  }
75083
75516
  }
75084
75517
  }
@@ -75416,7 +75849,7 @@ var init_completion = __esm(() => {
75416
75849
  // src/lib/portable-snapshot-filter.ts
75417
75850
  import { readdirSync as readdirSync16, statSync as statSync17 } from "fs";
75418
75851
  import { homedir as homedir8 } from "os";
75419
- import { join as join34, sep as sep3 } from "path";
75852
+ import { join as join35, sep as sep3 } from "path";
75420
75853
  function isExcludedSkillFileName(fileName) {
75421
75854
  if (EXCLUDE_FILE_NAMES.has(fileName)) {
75422
75855
  return true;
@@ -75439,16 +75872,16 @@ function isPortableWithinSkill(relativeParts) {
75439
75872
  function homePathFor(definition, homesRoot) {
75440
75873
  const home = homesRoot ?? homedir8();
75441
75874
  if (definition.subClass === "skills" || definition.subClass === "custom") {
75442
- return join34(skillsDataRootForHome(home), definition.name);
75875
+ return join35(skillsDataRootForHome(home), definition.name);
75443
75876
  }
75444
75877
  if (definition.agent === "opencode") {
75445
- return join34(home, ".config", "opencode", "skills");
75878
+ return join35(home, ".config", "opencode", "skills");
75446
75879
  }
75447
- return join34(home, `.${definition.agent}`, "skills");
75880
+ return join35(home, `.${definition.agent}`, "skills");
75448
75881
  }
75449
75882
  function destinationFor(definition, stationId, relativePath) {
75450
- const category = definition.subClass === "agent-homes" ? join34("agent-homes", definition.agent ?? "") : definition.name;
75451
- return join34("resources", stationId, "skills", category, ...relativePath.split(sep3));
75883
+ const category = definition.subClass === "agent-homes" ? join35("agent-homes", definition.agent ?? "") : definition.name;
75884
+ return join35("resources", stationId, "skills", category, ...relativePath.split(sep3));
75452
75885
  }
75453
75886
  function walkEntries(absoluteRoot) {
75454
75887
  let entries;
@@ -75459,7 +75892,7 @@ function walkEntries(absoluteRoot) {
75459
75892
  }
75460
75893
  const output = [];
75461
75894
  for (const entry of entries) {
75462
- const childFull = join34(absoluteRoot, entry.name);
75895
+ const childFull = join35(absoluteRoot, entry.name);
75463
75896
  if (entry.isSymbolicLink()) {
75464
75897
  output.push({ kind: "symlink", relativePath: entry.name, fullPath: childFull });
75465
75898
  continue;
@@ -75470,7 +75903,7 @@ function walkEntries(absoluteRoot) {
75470
75903
  }
75471
75904
  const nested = walkEntries(childFull);
75472
75905
  for (const item of nested) {
75473
- output.push({ ...item, relativePath: join34(entry.name, item.relativePath) });
75906
+ output.push({ ...item, relativePath: join35(entry.name, item.relativePath) });
75474
75907
  }
75475
75908
  continue;
75476
75909
  }
@@ -75566,19 +75999,19 @@ var init_portable_snapshot_filter = __esm(() => {
75566
75999
  import { createHash as createHash7 } from "crypto";
75567
76000
  import {
75568
76001
  copyFileSync as copyFileSync2,
75569
- mkdirSync as mkdirSync16,
75570
- readFileSync as readFileSync27,
76002
+ mkdirSync as mkdirSync17,
76003
+ readFileSync as readFileSync28,
75571
76004
  statSync as statSync18,
75572
- writeFileSync as writeFileSync16
76005
+ writeFileSync as writeFileSync17
75573
76006
  } from "fs";
75574
- import { dirname as dirname12, isAbsolute as isAbsolute5, relative as relative5, resolve as resolve3, sep as sep4 } from "path";
76007
+ import { dirname as dirname13, isAbsolute as isAbsolute5, relative as relative5, resolve as resolve3, sep as sep4 } from "path";
75575
76008
  function validateStationId(stationId) {
75576
76009
  if (!/^[a-z0-9-]+$/.test(stationId)) {
75577
76010
  throw new StationSnapshotError("INVALID_STATION", `station id must be a slug, got: ${stationId}`);
75578
76011
  }
75579
76012
  }
75580
76013
  function sha256File(filePath) {
75581
- return createHash7("sha256").update(readFileSync27(filePath)).digest("hex");
76014
+ return createHash7("sha256").update(readFileSync28(filePath)).digest("hex");
75582
76015
  }
75583
76016
  function scanHome(definition, homesRoot) {
75584
76017
  const homePath = homePathFor(definition, homesRoot);
@@ -75699,7 +76132,7 @@ function writeStationSnapshot(options) {
75699
76132
  let written = 0;
75700
76133
  for (const plan of untouched) {
75701
76134
  const destination = resolve3(repoRoot, plan.destination);
75702
- mkdirSync16(dirname12(destination), { recursive: true });
76135
+ mkdirSync17(dirname13(destination), { recursive: true });
75703
76136
  copyFileSync2(plan.source.fullPath, destination);
75704
76137
  written += 1;
75705
76138
  }
@@ -75718,8 +76151,8 @@ function writeStationSnapshot(options) {
75718
76151
  files: manifestFiles
75719
76152
  };
75720
76153
  const manifestPath = resolve3(repoRoot, "resources", options.stationId, "skills", "sync-manifest.json");
75721
- mkdirSync16(dirname12(manifestPath), { recursive: true });
75722
- writeFileSync16(manifestPath, `${JSON.stringify(manifest, null, 2)}
76154
+ mkdirSync17(dirname13(manifestPath), { recursive: true });
76155
+ writeFileSync17(manifestPath, `${JSON.stringify(manifest, null, 2)}
75723
76156
  `);
75724
76157
  return {
75725
76158
  ...base2,
@@ -75751,7 +76184,7 @@ __export(exports_create_sync_config, {
75751
76184
  registerCreateSync: () => registerCreateSync
75752
76185
  });
75753
76186
  import { existsSync as existsSync31 } from "fs";
75754
- import { join as join35 } from "path";
76187
+ import { join as join36 } from "path";
75755
76188
  function registerCreateSync(parent) {
75756
76189
  const configCmd = parent.command("config").description("Manage skills configuration");
75757
76190
  configCmd.command("show", { isDefault: true }).option("--json", "Output as JSON", false).description("Show current merged configuration").action((options) => {
@@ -75857,7 +76290,7 @@ function handleCreate(name, options) {
75857
76290
  console.log(source_default.green(`\u2713 Created custom skill '${result2.name}' at ${result2.path}`));
75858
76291
  console.log(source_default.dim(` Category: ${result2.manifest.category}`));
75859
76292
  console.log(source_default.dim(` Tags: ${result2.manifest.tags?.join(", ")}`));
75860
- console.log(` ${source_default.cyan("Edit:")} ${join35(result2.path, "src", "index.ts")}`);
76293
+ console.log(` ${source_default.cyan("Edit:")} ${join36(result2.path, "src", "index.ts")}`);
75861
76294
  console.log(` ${source_default.cyan("Run:")} skills run ${result2.name} --help`);
75862
76295
  }
75863
76296
  } catch (error2) {
@@ -76136,27 +76569,27 @@ var init_create_sync_config = __esm(() => {
76136
76569
  import { createHash as createHash8 } from "crypto";
76137
76570
  import {
76138
76571
  copyFileSync as copyFileSync3,
76139
- mkdirSync as mkdirSync17,
76572
+ mkdirSync as mkdirSync18,
76140
76573
  readdirSync as readdirSync17,
76141
- readFileSync as readFileSync28,
76574
+ readFileSync as readFileSync29,
76142
76575
  statSync as statSync19,
76143
- writeFileSync as writeFileSync17
76576
+ writeFileSync as writeFileSync18
76144
76577
  } from "fs";
76145
- import { dirname as dirname13, join as join36, resolve as resolve4, sep as sep5 } from "path";
76146
- function fail2(code, message, detail = []) {
76578
+ import { dirname as dirname14, join as join37, resolve as resolve4, sep as sep5 } from "path";
76579
+ function fail3(code, message, detail = []) {
76147
76580
  throw new StationSnapshotError(code, message, detail);
76148
76581
  }
76149
76582
  function snapshotRootFor(repoRoot, stationId) {
76150
- return join36(repoRoot, "resources", stationId, "skills");
76583
+ return join37(repoRoot, "resources", stationId, "skills");
76151
76584
  }
76152
76585
  function readSnapshotManifest(repoRoot, stationId) {
76153
76586
  const snapshotRoot = snapshotRootFor(repoRoot, stationId);
76154
- const manifestPath = join36(snapshotRoot, "sync-manifest.json");
76587
+ const manifestPath = join37(snapshotRoot, "sync-manifest.json");
76155
76588
  let manifest;
76156
76589
  try {
76157
- manifest = JSON.parse(readFileSync28(manifestPath, "utf8"));
76590
+ manifest = JSON.parse(readFileSync29(manifestPath, "utf8"));
76158
76591
  } catch (error2) {
76159
- fail2("MANIFEST_UNREADABLE", `cannot read snapshot manifest: ${manifestPath}: ${error2.message}`);
76592
+ fail3("MANIFEST_UNREADABLE", `cannot read snapshot manifest: ${manifestPath}: ${error2.message}`);
76160
76593
  }
76161
76594
  const sourceSnapshotSha = sha256File(manifestPath);
76162
76595
  return { manifest, manifestPath, sourceSnapshotSha };
@@ -76178,7 +76611,7 @@ function planStationHydration(stationId, repoRoot) {
76178
76611
  const hashMismatches = [];
76179
76612
  const skippedByRule = [];
76180
76613
  for (const agent of SYNC_AGENTS) {
76181
- const agentRoot = join36(snapshotRoot, "agent-homes", agent);
76614
+ const agentRoot = join37(snapshotRoot, "agent-homes", agent);
76182
76615
  let identEntries;
76183
76616
  try {
76184
76617
  identEntries = readdirSync17(agentRoot, { withFileTypes: true });
@@ -76189,7 +76622,7 @@ function planStationHydration(stationId, repoRoot) {
76189
76622
  if (!identEntry.isDirectory() || identEntry.name.startsWith(".")) {
76190
76623
  continue;
76191
76624
  }
76192
- const identRoot = join36(agentRoot, identEntry.name);
76625
+ const identRoot = join37(agentRoot, identEntry.name);
76193
76626
  const entries = walkEntries(identRoot);
76194
76627
  for (const entry of entries) {
76195
76628
  const relativeParts = [identEntry.name, ...entry.relativePath.split(sep5)];
@@ -76263,10 +76696,10 @@ function planStationHydration(stationId, repoRoot) {
76263
76696
  }
76264
76697
  }
76265
76698
  if (symlinks.length > 0) {
76266
- fail2("SYMLINKS_REFUSED", `${symlinks.length} symlink(s) inside the snapshot; symlinks are refused (fail closed)`);
76699
+ fail3("SYMLINKS_REFUSED", `${symlinks.length} symlink(s) inside the snapshot; symlinks are refused (fail closed)`);
76267
76700
  }
76268
76701
  if (hashMismatches.length > 0) {
76269
- fail2("MANIFEST_HASH_MISMATCH", `${hashMismatches.length} snapshot file(s) no longer match their sync-manifest sha256; ` + "stale or tampered content is refused (fail closed), nothing written \u2014 re-run sync to refresh the manifest", hashMismatches.map((mismatch) => `agent-homes/${mismatch.agent}/${mismatch.ident}/${mismatch.relativePath}`));
76702
+ fail3("MANIFEST_HASH_MISMATCH", `${hashMismatches.length} snapshot file(s) no longer match their sync-manifest sha256; ` + "stale or tampered content is refused (fail closed), nothing written \u2014 re-run sync to refresh the manifest", hashMismatches.map((mismatch) => `agent-homes/${mismatch.agent}/${mismatch.ident}/${mismatch.relativePath}`));
76270
76703
  }
76271
76704
  const byIdent = new Map;
76272
76705
  for (const candidate of candidates) {
@@ -76290,7 +76723,7 @@ function planStationHydration(stationId, repoRoot) {
76290
76723
  for (const copy of copies) {
76291
76724
  let isStub = false;
76292
76725
  try {
76293
- isStub = isPointerSkillMd(readFileSync28(copy.fullPath, "utf8"));
76726
+ isStub = isPointerSkillMd(readFileSync29(copy.fullPath, "utf8"));
76294
76727
  } catch {
76295
76728
  isStub = false;
76296
76729
  }
@@ -76374,7 +76807,7 @@ function writeStationHydration(options) {
76374
76807
  const toWrite = [];
76375
76808
  for (const skill of plan.winners) {
76376
76809
  for (const file of skill.files) {
76377
- const destination = join36(cacheRoot, skill.ident, file.withinIdent);
76810
+ const destination = join37(cacheRoot, skill.ident, file.withinIdent);
76378
76811
  const digest = sha256File(file.winner.fullPath);
76379
76812
  let existingDigest = null;
76380
76813
  try {
@@ -76391,11 +76824,11 @@ function writeStationHydration(options) {
76391
76824
  }
76392
76825
  }
76393
76826
  if (conflicts.length > 0) {
76394
- fail2("CONFLICT", `${conflicts.length} conflict(s); terminal non-acceptance, nothing written`, conflicts);
76827
+ fail3("CONFLICT", `${conflicts.length} conflict(s); terminal non-acceptance, nothing written`, conflicts);
76395
76828
  }
76396
76829
  let written = 0;
76397
76830
  for (const entry of toWrite) {
76398
- mkdirSync17(dirname13(entry.destination), { recursive: true });
76831
+ mkdirSync18(dirname14(entry.destination), { recursive: true });
76399
76832
  copyFileSync3(entry.fullPath, entry.destination);
76400
76833
  written += 1;
76401
76834
  }
@@ -76416,9 +76849,9 @@ function writeStationHydration(options) {
76416
76849
  },
76417
76850
  skills: resultSkills
76418
76851
  };
76419
- const hydrationManifestPath = join36(dirname13(cacheRoot), `hydration-${options.stationId}.json`);
76420
- mkdirSync17(dirname13(hydrationManifestPath), { recursive: true });
76421
- writeFileSync17(hydrationManifestPath, `${JSON.stringify(hydration, null, 2)}
76852
+ const hydrationManifestPath = join37(dirname14(cacheRoot), `hydration-${options.stationId}.json`);
76853
+ mkdirSync18(dirname14(hydrationManifestPath), { recursive: true });
76854
+ writeFileSync18(hydrationManifestPath, `${JSON.stringify(hydration, null, 2)}
76422
76855
  `);
76423
76856
  return {
76424
76857
  ...base2,
@@ -76846,8 +77279,8 @@ var init_schedule = __esm(() => {
76846
77279
  });
76847
77280
 
76848
77281
  // src/lib/registry-sync.ts
76849
- import { mkdirSync as mkdirSync18, writeFileSync as writeFileSync18 } from "fs";
76850
- import { dirname as dirname14, relative as relative6 } from "path";
77282
+ import { mkdirSync as mkdirSync19, writeFileSync as writeFileSync19 } from "fs";
77283
+ import { dirname as dirname15, relative as relative6 } from "path";
76851
77284
  function createRegistrySyncArtifact(options = {}) {
76852
77285
  const profile = options.profile ?? "all";
76853
77286
  const includeDocs = options.includeDocs ?? true;
@@ -76904,8 +77337,8 @@ function createRegistrySyncArtifact(options = {}) {
76904
77337
  };
76905
77338
  }
76906
77339
  function writeRegistrySyncArtifact(path, artifact) {
76907
- mkdirSync18(dirname14(path), { recursive: true });
76908
- writeFileSync18(path, `${JSON.stringify(artifact, null, 2)}
77340
+ mkdirSync19(dirname15(path), { recursive: true });
77341
+ writeFileSync19(path, `${JSON.stringify(artifact, null, 2)}
76909
77342
  `);
76910
77343
  }
76911
77344
  function buildDocs(name) {
@@ -76935,10 +77368,10 @@ function registerRegistry(parent) {
76935
77368
  registry2.command("sync").description("Generate a deterministic registry sync artifact").option("--profile <profile>", "Registry profile: basic or all", "all").option("--output <path>", "Write artifact to a JSON file").option("--no-docs", "Exclude skill documentation content").option("--no-requirements", "Exclude extracted skill requirements").option("--no-validation", "Exclude validation results").option("--json", "Print artifact JSON to stdout", false).action((options) => handleRegistrySync(options));
76936
77369
  }
76937
77370
  async function writeJson2(value, space) {
76938
- const text = `${JSON.stringify(value, null, space)}
77371
+ const text2 = `${JSON.stringify(value, null, space)}
76939
77372
  `;
76940
77373
  await new Promise((resolve5, reject2) => {
76941
- process.stdout.write(text, (error2) => {
77374
+ process.stdout.write(text2, (error2) => {
76942
77375
  if (error2)
76943
77376
  reject2(error2);
76944
77377
  else
@@ -76970,10 +77403,10 @@ async function handleRegistrySync(options) {
76970
77403
  await writeJson2(artifact, 2);
76971
77404
  return;
76972
77405
  }
76973
- const invalid = artifact.summary.invalidSkillCount ?? "not checked";
77406
+ const invalid2 = artifact.summary.invalidSkillCount ?? "not checked";
76974
77407
  console.log(source_default.green(`Registry sync artifact written to ${options.output}`));
76975
77408
  console.log(source_default.dim(` Skills: ${artifact.summary.skillCount}`));
76976
- console.log(source_default.dim(` Invalid: ${invalid}`));
77409
+ console.log(source_default.dim(` Invalid: ${invalid2}`));
76977
77410
  }
76978
77411
  function registerPull(parent) {
76979
77412
  parent.command("pull").argument("[names...]", "Skills to pull from the configured instance (name or name@version)").option("--all", "Pull every skill the instance serves", false).option("--for-machine", "Prepare this machine with the instance's full catalog (implies --all)", false).option("--json", "Output results as JSON", false).description("Fetch skills from the configured Skills instance into this machine's corpus").action(async (names, options) => {
@@ -77078,9 +77511,9 @@ __export(exports_publish, {
77078
77511
  PushSkillError: () => PushSkillError
77079
77512
  });
77080
77513
  import { execFileSync } from "child_process";
77081
- import { existsSync as existsSync32, readFileSync as readFileSync29 } from "fs";
77514
+ import { existsSync as existsSync32, readFileSync as readFileSync30 } from "fs";
77082
77515
  import { hostname as hostname2 } from "os";
77083
- import { join as join37 } from "path";
77516
+ import { join as join38 } from "path";
77084
77517
  function registerPublish(parent) {
77085
77518
  parent.command("push").argument("<name>", "Name of a skill in the local corpus (~/.hasna/skills/installed or the migrated ~/.hasna/skills/skills)").option("--version <version>", "Override the version recorded on the instance").option("--force-new-version", "If name@version already exists with different content, publish as the next patch version", false).option("--dry-run", "Pack and validate without uploading", false).option("--json", "Output result as JSON", false).description("Publish a local skill to the configured skills instance").action(async (name, options) => {
77086
77519
  try {
@@ -77127,8 +77560,8 @@ async function pushSkill(name, options = {}) {
77127
77560
  }
77128
77561
  const packed = packSkillBundle(skill.path, { maxUnpackedBytes: MAX_UNPACKED_BYTES });
77129
77562
  const versionManifest = buildVersionManifest(skill.path, packed);
77130
- const skillMdPath = join37(skill.path, "SKILL.md");
77131
- const skillMd = existsSync32(skillMdPath) ? readFileSync29(skillMdPath, "utf-8") : undefined;
77563
+ const skillMdPath = join38(skill.path, "SKILL.md");
77564
+ const skillMd = existsSync32(skillMdPath) ? readFileSync30(skillMdPath, "utf-8") : undefined;
77132
77565
  const base2 = {
77133
77566
  slug: skill.name,
77134
77567
  path: skill.path,
@@ -77193,21 +77626,21 @@ async function readPublishRevision(client, slug) {
77193
77626
  throw new PushSkillError("Publishing was refused because the current skill revision could not be verified.", ["Check the configured instance and connection, then retry the push. No upload was attempted."]);
77194
77627
  }
77195
77628
  const body = lookup.body;
77196
- const record4 = body !== null && typeof body === "object" && !Array.isArray(body) ? body : undefined;
77197
- const nestedError = record4?.error;
77198
- const code = typeof record4?.code === "string" ? record4.code : nestedError !== null && typeof nestedError === "object" && !Array.isArray(nestedError) ? nestedError.code : undefined;
77629
+ const record5 = body !== null && typeof body === "object" && !Array.isArray(body) ? body : undefined;
77630
+ const nestedError = record5?.error;
77631
+ const code = typeof record5?.code === "string" ? record5.code : nestedError !== null && typeof nestedError === "object" && !Array.isArray(nestedError) ? nestedError.code : undefined;
77199
77632
  if (lookup.status === 404 && code === "SKILL_NOT_FOUND")
77200
77633
  return;
77201
77634
  if (lookup.status < 200 || lookup.status >= 300) {
77202
77635
  throw new PushSkillError(`Publishing was refused because the current skill lookup failed: HTTP ${lookup.status}.`, ["Only an explicit SKILL_NOT_FOUND response establishes an initial publish. Check access and server compatibility before retrying."]);
77203
77636
  }
77204
- const revision = record4?.revisionId;
77205
- if (record4?.publicationState === "catalogue-only") {
77206
- if (record4.name === slug && (record4.slug === undefined || record4.slug === slug) && revision === null)
77637
+ const revision = record5?.revisionId;
77638
+ if (record5?.publicationState === "catalogue-only") {
77639
+ if (record5.name === slug && (record5.slug === undefined || record5.slug === slug) && revision === null)
77207
77640
  return;
77208
77641
  throw new PushSkillError("Publishing was refused because the catalogue-only response had contradictory identity or revision state.", ["Check the configured instance and server compatibility. No upload was attempted."]);
77209
77642
  }
77210
- if (record4?.slug !== slug || typeof revision !== "string" || revision.length === 0 || revision !== revision.trim() || !/^[\x21-\x7e]+$/.test(revision)) {
77643
+ if (record5?.slug !== slug || typeof revision !== "string" || revision.length === 0 || revision !== revision.trim() || !/^[\x21-\x7e]+$/.test(revision)) {
77211
77644
  throw new PushSkillError("Publishing was refused because the current skill response did not contain a matching slug and valid revision.", ["Check the configured instance and server compatibility. No upload was attempted."]);
77212
77645
  }
77213
77646
  return revision;
@@ -77310,13 +77743,13 @@ Dry run: '${result2.slug}' would be published
77310
77743
  console.log("");
77311
77744
  }
77312
77745
  async function readBody(response) {
77313
- const text = await response.text();
77314
- if (!text.trim())
77746
+ const text2 = await response.text();
77747
+ if (!text2.trim())
77315
77748
  return null;
77316
77749
  try {
77317
- return JSON.parse(text);
77750
+ return JSON.parse(text2);
77318
77751
  } catch {
77319
- return text;
77752
+ return text2;
77320
77753
  }
77321
77754
  }
77322
77755
  function describeError(payload) {
@@ -77349,6 +77782,152 @@ var init_publish = __esm(() => {
77349
77782
  };
77350
77783
  });
77351
77784
 
77785
+ // src/cli/commands/customer-verification.ts
77786
+ import { emitKeypressEvents } from "readline";
77787
+ async function readCode() {
77788
+ if (process.stdin.isTTY)
77789
+ throw new NameInputError("Pipe a fresh six-digit verification code when using --code-stdin.");
77790
+ let text2 = "";
77791
+ for await (const chunk2 of process.stdin) {
77792
+ text2 += chunk2.toString();
77793
+ if (text2.length > 32)
77794
+ throw new NameInputError("Supply only a six-digit verification code on stdin.");
77795
+ }
77796
+ const code = text2.trim();
77797
+ if (!/^\d{6}$/.test(code))
77798
+ throw new NameInputError("Supply only a six-digit verification code on stdin.");
77799
+ return code;
77800
+ }
77801
+ function promptCode() {
77802
+ const { stdin, stderr: output } = process;
77803
+ const { isRaw: wasRaw, readableFlowing: wasFlowing } = stdin;
77804
+ return new Promise((resolve5) => {
77805
+ let value = "", settled = false;
77806
+ const finish = (answer) => {
77807
+ if (settled)
77808
+ return;
77809
+ settled = true;
77810
+ clearTimeout(timer);
77811
+ stdin.off("keypress", keypress);
77812
+ stdin.off("end", cancel);
77813
+ process.off("SIGINT", cancel);
77814
+ stdin.setRawMode(wasRaw);
77815
+ if (wasFlowing !== true)
77816
+ stdin.pause();
77817
+ output.write(`
77818
+ `);
77819
+ if (answer === null)
77820
+ process.exitCode = 130;
77821
+ resolve5(answer);
77822
+ };
77823
+ const cancel = () => finish(null);
77824
+ const keypress = (text2, key) => {
77825
+ if (key.ctrl && ["c", "d"].includes(key.name ?? "") || key.name === "escape")
77826
+ return cancel();
77827
+ if (key.name === "return" || key.name === "enter") {
77828
+ if (value.length === 6)
77829
+ return finish(value);
77830
+ output.write(`
77831
+ Enter all six digits: `);
77832
+ value = "";
77833
+ return;
77834
+ }
77835
+ if (key.name === "backspace") {
77836
+ if (value) {
77837
+ value = value.slice(0, -1);
77838
+ output.write("\b \b");
77839
+ }
77840
+ } else if (/^[0-9]$/.test(text2) && value.length < 6) {
77841
+ value += text2;
77842
+ output.write("*");
77843
+ }
77844
+ };
77845
+ const timer = setTimeout(cancel, 5 * 60 * 1000);
77846
+ emitKeypressEvents(stdin);
77847
+ stdin.setRawMode(true);
77848
+ stdin.on("keypress", keypress);
77849
+ stdin.once("end", cancel);
77850
+ process.once("SIGINT", cancel);
77851
+ output.write("Enter the six-digit code sent to your email: ");
77852
+ stdin.resume();
77853
+ });
77854
+ }
77855
+ var NameInputError;
77856
+ var init_customer_verification = __esm(() => {
77857
+ NameInputError = class NameInputError extends Error {
77858
+ };
77859
+ });
77860
+
77861
+ // src/cli/commands/workspace-selection.ts
77862
+ async function codeFor(client, options) {
77863
+ if (!options.email?.includes("@"))
77864
+ throw new NameInputError("Provide the account email with --email.");
77865
+ if (options.codeStdin)
77866
+ return readCode();
77867
+ if (options.json || !process.stdin.isTTY || !process.stderr.isTTY)
77868
+ throw new NameInputError("Use --code-stdin with a fresh verification code for noninteractive requests.");
77869
+ await client.requestCode(options.email);
77870
+ return promptCode();
77871
+ }
77872
+ function errorResult(error2, json) {
77873
+ const message = error2 instanceof NameInputError || error2 instanceof WorkspaceProfileError ? error2.message : "Unable to complete workspace sign-in. Check the selected server, profile, account and fresh verification code.";
77874
+ if (json)
77875
+ console.log(JSON.stringify({ error: message }));
77876
+ else
77877
+ console.error(message);
77878
+ process.exitCode = 1;
77879
+ }
77880
+ function registerWorkspaceListCommand(workspace) {
77881
+ workspace.command("list").allowExcessArguments(false).description("Discover eligible workspaces with fresh sign-in; no credentials are saved").requiredOption("--email <email>", "Account email for fresh verification").option("--code-stdin", "Read a previously requested six-digit verification code from stdin").option("--json", "Output safe workspace identities as JSON").action(async (options) => {
77882
+ try {
77883
+ const origin = getApiUrl("Discover workspaces", { ...process.env });
77884
+ const client = new RemoteSkillsAuthClient(origin);
77885
+ const code = await codeFor(client, options);
77886
+ if (code === null)
77887
+ return;
77888
+ const result2 = await client.listAccountWorkspaces(options.email, code);
77889
+ if (options.json)
77890
+ console.log(JSON.stringify({ apiUrl: origin, ...result2 }));
77891
+ else {
77892
+ console.log(`Account: ${result2.userId}
77893
+ API: ${origin}`);
77894
+ for (const entry of result2.workspaces)
77895
+ console.log(`${entry.current ? "*" : " "} ${entry.organization.name} ${entry.role} ${entry.membershipId}`);
77896
+ console.log("* Initial sign-in workspace. Enroll a named profile with auth login --membership-id <id>.");
77897
+ }
77898
+ } catch (error2) {
77899
+ errorResult(error2, options.json);
77900
+ }
77901
+ });
77902
+ }
77903
+ async function loginWorkspace(options) {
77904
+ try {
77905
+ const enrollment = await prepareWorkspaceEnrollment(options.membershipId);
77906
+ const code = await codeFor(new RemoteSkillsAuthClient(enrollment.origin), options);
77907
+ if (code === null)
77908
+ return;
77909
+ const result2 = await enrollment.complete(options.email, code);
77910
+ if (options.json)
77911
+ console.log(JSON.stringify(result2));
77912
+ else
77913
+ console.log(`Signed in as ${result2.email}
77914
+ Profile: ${result2.profile}
77915
+ API: ${result2.apiUrl}
77916
+ Workspace: ${result2.organization} (${result2.organizationId})
77917
+ Membership: ${result2.membershipId}
77918
+ Role: ${result2.role}
77919
+ One workspace key saved. Use HASNA_PROFILE=${result2.profile} for subsequent commands.`);
77920
+ } catch (error2) {
77921
+ errorResult(error2, options.json);
77922
+ }
77923
+ }
77924
+ var init_workspace_selection = __esm(() => {
77925
+ init_auth_store();
77926
+ init_remote_auth();
77927
+ init_workspace_profile();
77928
+ init_customer_verification();
77929
+ });
77930
+
77352
77931
  // src/cli/commands/auth.ts
77353
77932
  var exports_auth = {};
77354
77933
  __export(exports_auth, {
@@ -77434,13 +78013,13 @@ function authIdentityPayload(authSource, live, cached2, offline = false) {
77434
78013
  const root = recordField(live) ?? {};
77435
78014
  const data = recordField(root.data);
77436
78015
  const user = recordField(root.user) ?? recordField(data?.user);
77437
- const organization = recordField(root.organization) ?? recordField(root.org) ?? recordField(data?.organization);
78016
+ const organization2 = recordField(root.organization) ?? recordField(root.org) ?? recordField(data?.organization);
77438
78017
  const email2 = stringField2(user?.email) ?? cached2?.email;
77439
- const orgSlug = stringField2(organization?.slug) ?? cached2?.orgSlug;
77440
- const orgName = stringField2(organization?.name);
78018
+ const orgSlug = stringField2(organization2?.slug) ?? cached2?.orgSlug;
78019
+ const orgName = stringField2(organization2?.name);
77441
78020
  const userId = stringField2(user?.id) ?? cached2?.userId;
77442
- const orgId = stringField2(organization?.id) ?? cached2?.orgId;
77443
- const role = stringField2(user?.role);
78021
+ const orgId = stringField2(organization2?.id) ?? cached2?.orgId;
78022
+ const role2 = stringField2(user?.role);
77444
78023
  return {
77445
78024
  status: "authenticated",
77446
78025
  authSource,
@@ -77450,7 +78029,7 @@ function authIdentityPayload(authSource, live, cached2, offline = false) {
77450
78029
  ...orgName ? { organizationName: orgName } : {},
77451
78030
  ...userId ? { userId } : {},
77452
78031
  ...orgId ? { orgId } : {},
77453
- ...role ? { role } : {}
78032
+ ...role2 ? { role: role2 } : {}
77454
78033
  };
77455
78034
  }
77456
78035
  function printWhoami(payload) {
@@ -77748,15 +78327,19 @@ function registerAuth(parent) {
77748
78327
  const keys2 = auth.command("keys").description("Manage API keys on the configured instance");
77749
78328
  keys2.command("list").option("--json", "Output as JSON", false).requiredOption("--email <email>", "Account email for fresh reauthentication").requiredOption("--code <code>", "Fresh OTP requested through auth signup/login").action(async (options) => {
77750
78329
  try {
77751
- console.log(JSON.stringify(await new RemoteSkillsAuthClient(getApiUrl("List API keys")).listApiKeys(options.email, options.code), null, 2));
78330
+ const target = await captureProfileWorkspace("List API keys");
78331
+ target.unchanged();
78332
+ console.log(JSON.stringify(await new RemoteSkillsAuthClient(target.origin).listApiKeys(options.email, options.code, target.context), null, 2));
77752
78333
  } catch (error2) {
77753
78334
  writeCommandError(error2, "Failed to list API keys", options.json);
77754
78335
  }
77755
78336
  });
77756
78337
  keys2.command("create").argument("<name>").option("--scope <scope>", "Limit key scope (repeatable)", (value, all) => [...all, value], []).option("--json", "Output the newly created key as JSON", false).requiredOption("--email <email>", "Account email for fresh reauthentication").requiredOption("--code <code>", "Fresh OTP requested through auth signup/login").description("Create a key; the returned secret is shown once and must be stored securely").action(async (name, options) => {
77757
78338
  try {
77758
- const client = new RemoteSkillsAuthClient(getApiUrl("Create API key"));
77759
- const created = await client.createApiKey(options.email, options.code, name, options.scope.length ? options.scope : undefined);
78339
+ const target = await captureProfileWorkspace("Create API key");
78340
+ const client = new RemoteSkillsAuthClient(target.origin);
78341
+ target.unchanged();
78342
+ const created = await client.createApiKey(options.email, options.code, name, options.scope.length ? options.scope : undefined, target.context);
77760
78343
  console.log(JSON.stringify(created, null, 2));
77761
78344
  } catch (error2) {
77762
78345
  writeCommandError(error2, "Failed to create API key", options.json);
@@ -77764,12 +78347,26 @@ function registerAuth(parent) {
77764
78347
  });
77765
78348
  keys2.command("revoke").argument("<key-id>").option("--json", "Output as JSON", false).requiredOption("--email <email>", "Account email for fresh reauthentication").requiredOption("--code <code>", "Fresh OTP requested through auth signup/login").action(async (id, options) => {
77766
78349
  try {
77767
- console.log(JSON.stringify(await new RemoteSkillsAuthClient(getApiUrl("Revoke API key")).revokeApiKey(options.email, options.code, id), null, 2));
78350
+ const target = await captureProfileWorkspace("Revoke API key");
78351
+ target.unchanged();
78352
+ console.log(JSON.stringify(await new RemoteSkillsAuthClient(target.origin).revokeApiKey(options.email, options.code, id, target.context), null, 2));
77768
78353
  } catch (error2) {
77769
78354
  writeCommandError(error2, "Failed to revoke API key", options.json);
77770
78355
  }
77771
78356
  });
77772
- auth.command("login").description("Sign in with browser/device code or email code").option("--email <email>", "Email address (non-interactive)").option("--code <code>", "Verification code (non-interactive)").option("--api-key <key>", "Verify and store an API key").option("--device", "Use browser/device-code login", false).option("--no-open", "Do not open a browser for device-code login").option("--poll", "Poll until browser authentication completes in non-interactive mode", false).option("--poll-timeout-ms <ms>", "Maximum time to wait for device-code login").option("--json", "Output result as JSON", false).action(async (options) => {
78357
+ auth.command("login").description("Sign in with browser/device code or email code").option("--email <email>", "Email address (non-interactive)").option("--code <code>", "Verification code (non-interactive)").option("--membership-id <id>", "Enroll an exact workspace membership into an explicit HASNA_PROFILE").option("--code-stdin", "Read a fresh six-digit code for workspace enrollment from stdin").option("--api-key <key>", "Verify and store an API key").option("--device", "Use browser/device-code login", false).option("--no-open", "Do not open a browser for device-code login").option("--poll", "Poll until browser authentication completes in non-interactive mode", false).option("--poll-timeout-ms <ms>", "Maximum time to wait for device-code login").option("--json", "Output result as JSON", false).action(async (options) => {
78358
+ if (options.membershipId !== undefined) {
78359
+ if (options.apiKey || options.device || options.code || options.poll) {
78360
+ writeCommandError(new Error("Workspace login uses email and --code-stdin; do not combine it with device, API key or --code login."), "Invalid login options", options.json);
78361
+ return;
78362
+ }
78363
+ await loginWorkspace({ ...options, membershipId: options.membershipId });
78364
+ return;
78365
+ }
78366
+ if (options.codeStdin) {
78367
+ writeCommandError(new Error("--code-stdin requires --membership-id for this login flow."), "Invalid login options", options.json);
78368
+ return;
78369
+ }
77773
78370
  if (options.apiKey) {
77774
78371
  await doApiKeyLogin(options.apiKey, options.json);
77775
78372
  return;
@@ -77877,6 +78474,8 @@ function registerAuth(parent) {
77877
78474
  }
77878
78475
  var isTTY, DEFAULT_DEVICE_POLL_TIMEOUT_MS, CONFIG_HINT_STATUSES;
77879
78476
  var init_auth = __esm(() => {
78477
+ init_workspace_selection();
78478
+ init_workspace_profile();
77880
78479
  init_source();
77881
78480
  init_auth_store();
77882
78481
  init_fleet_credentials();
@@ -77886,82 +78485,6 @@ var init_auth = __esm(() => {
77886
78485
  CONFIG_HINT_STATUSES = new Set([401, 403, 404, 405, 501]);
77887
78486
  });
77888
78487
 
77889
- // src/cli/commands/customer-verification.ts
77890
- import { emitKeypressEvents } from "readline";
77891
- async function readCode() {
77892
- if (process.stdin.isTTY)
77893
- throw new NameInputError("Pipe a fresh six-digit verification code when using --code-stdin.");
77894
- let text = "";
77895
- for await (const chunk2 of process.stdin) {
77896
- text += chunk2.toString();
77897
- if (text.length > 32)
77898
- throw new NameInputError("Supply only a six-digit verification code on stdin.");
77899
- }
77900
- const code = text.trim();
77901
- if (!/^\d{6}$/.test(code))
77902
- throw new NameInputError("Supply only a six-digit verification code on stdin.");
77903
- return code;
77904
- }
77905
- function promptCode() {
77906
- const { stdin, stderr: output } = process;
77907
- const { isRaw: wasRaw, readableFlowing: wasFlowing } = stdin;
77908
- return new Promise((resolve5) => {
77909
- let value = "", settled = false;
77910
- const finish = (answer) => {
77911
- if (settled)
77912
- return;
77913
- settled = true;
77914
- clearTimeout(timer);
77915
- stdin.off("keypress", keypress);
77916
- stdin.off("end", cancel);
77917
- process.off("SIGINT", cancel);
77918
- stdin.setRawMode(wasRaw);
77919
- if (wasFlowing !== true)
77920
- stdin.pause();
77921
- output.write(`
77922
- `);
77923
- if (answer === null)
77924
- process.exitCode = 130;
77925
- resolve5(answer);
77926
- };
77927
- const cancel = () => finish(null);
77928
- const keypress = (text, key) => {
77929
- if (key.ctrl && ["c", "d"].includes(key.name ?? "") || key.name === "escape")
77930
- return cancel();
77931
- if (key.name === "return" || key.name === "enter") {
77932
- if (value.length === 6)
77933
- return finish(value);
77934
- output.write(`
77935
- Enter all six digits: `);
77936
- value = "";
77937
- return;
77938
- }
77939
- if (key.name === "backspace") {
77940
- if (value) {
77941
- value = value.slice(0, -1);
77942
- output.write("\b \b");
77943
- }
77944
- } else if (/^[0-9]$/.test(text) && value.length < 6) {
77945
- value += text;
77946
- output.write("*");
77947
- }
77948
- };
77949
- const timer = setTimeout(cancel, 5 * 60 * 1000);
77950
- emitKeypressEvents(stdin);
77951
- stdin.setRawMode(true);
77952
- stdin.on("keypress", keypress);
77953
- stdin.once("end", cancel);
77954
- process.once("SIGINT", cancel);
77955
- output.write("Enter the six-digit code sent to your email: ");
77956
- stdin.resume();
77957
- });
77958
- }
77959
- var NameInputError;
77960
- var init_customer_verification = __esm(() => {
77961
- NameInputError = class NameInputError extends Error {
77962
- };
77963
- });
77964
-
77965
78488
  // src/cli/commands/workspace-members.ts
77966
78489
  function registerWorkspaceMembersCommand(workspace) {
77967
78490
  workspace.command("members").allowExcessArguments(false).description("List the current workspace roster with fresh owner/admin verification").requiredOption("--email <email>", "Account email for fresh verification").option("--code-stdin", "Read a previously requested six-digit verification code from stdin").option("--limit <count>", "Page size from 1 to 100 (server default: 50)").option("--cursor <cursor>", "Unchanged nextCursor from the preceding page").option("--json", "Output the complete page as JSON").action(async (options) => {
@@ -77970,7 +78493,8 @@ function registerWorkspaceMembersCommand(workspace) {
77970
78493
  throw new NameInputError("Use a roster limit from 1 to 100.");
77971
78494
  const page = { limit: options.limit === undefined ? undefined : Number(options.limit), cursor: options.cursor };
77972
78495
  workspaceMembersQuery(page);
77973
- const client = new RemoteSkillsAuthClient(getApiUrl("List workspace members"));
78496
+ const pending = prepareProfileWorkspace("List workspace members");
78497
+ const client = new RemoteSkillsAuthClient(pending.origin);
77974
78498
  if (!options.codeStdin && (options.json || !process.stdin.isTTY || !process.stderr.isTTY))
77975
78499
  throw new NameInputError("Use --code-stdin with a fresh verification code for JSON or noninteractive roster requests.");
77976
78500
  let code;
@@ -77982,16 +78506,18 @@ function registerWorkspaceMembersCommand(workspace) {
77982
78506
  }
77983
78507
  if (code === null)
77984
78508
  return;
77985
- const result2 = await client.listWorkspaceMembers(options.email, code, page);
78509
+ const target = await pending.resolve();
78510
+ target.unchanged();
78511
+ const result2 = await client.listWorkspaceMembers(options.email, code, page, target.context);
77986
78512
  if (options.json)
77987
78513
  console.log(JSON.stringify(result2));
77988
78514
  else {
77989
- const text = (value) => value.replace(/[\p{Cc}\p{Cs}\u2028\u2029]/gu, " ");
78515
+ const text2 = (value) => value.replace(/[\p{Cc}\p{Cs}\u2028\u2029]/gu, " ");
77990
78516
  console.log(`Workspace: ${result2.organizationId}`);
77991
78517
  if (!result2.members.length)
77992
78518
  console.log("No members in this page.");
77993
78519
  for (const member of result2.members)
77994
- console.log(`${text(member.email)} ${member.role} ${text(member.displayName ?? "")} ${member.membershipId} ${member.createdAt}`);
78520
+ console.log(`${text2(member.email)} ${member.role} ${text2(member.displayName ?? "")} ${member.membershipId} ${member.createdAt}`);
77995
78521
  if (result2.nextCursor !== null)
77996
78522
  console.log(`Next cursor: ${result2.nextCursor}`);
77997
78523
  }
@@ -78007,7 +78533,7 @@ function registerWorkspaceMembersCommand(workspace) {
78007
78533
  });
78008
78534
  }
78009
78535
  var init_workspace_members = __esm(() => {
78010
- init_auth_store();
78536
+ init_workspace_profile();
78011
78537
  init_remote_auth();
78012
78538
  init_remote_workspace();
78013
78539
  init_customer_verification();
@@ -78023,7 +78549,8 @@ function registerWorkspaceMemberMutationCommands(workspace) {
78023
78549
  command.action(async (membershipId, options) => {
78024
78550
  try {
78025
78551
  const captured = action === "role" ? { kind: "role", ...workspaceMemberRoleInput(membershipId, { role: options.role, expectedRole: options.expectedRole }) } : { kind: "remove", ...workspaceMemberRemovalInput(membershipId, { expectedRole: options.expectedRole }) };
78026
- const client = new RemoteSkillsAuthClient(getApiUrl("Manage workspace member"));
78552
+ const pending = prepareProfileWorkspace("Manage workspace member");
78553
+ const client = new RemoteSkillsAuthClient(pending.origin);
78027
78554
  if (!options.codeStdin && (options.json || !process.stdin.isTTY || !process.stderr.isTTY))
78028
78555
  throw new NameInputError("Use --code-stdin with a fresh verification code for JSON or noninteractive member actions.");
78029
78556
  let code;
@@ -78035,14 +78562,16 @@ function registerWorkspaceMemberMutationCommands(workspace) {
78035
78562
  }
78036
78563
  if (code === null)
78037
78564
  return;
78565
+ const target = await pending.resolve();
78566
+ target.unchanged();
78038
78567
  if (captured.kind === "role") {
78039
- const result2 = await client.setWorkspaceMemberRole(options.email, code, captured.membershipId, captured.body);
78568
+ const result2 = await client.setWorkspaceMemberRole(options.email, code, captured.membershipId, captured.body, target.context);
78040
78569
  if (options.json)
78041
78570
  console.log(JSON.stringify(result2));
78042
78571
  else
78043
78572
  console.log(result2.changed ? `Member role changed to ${result2.member.role}.` : `Member already has role ${result2.member.role}.`);
78044
78573
  } else {
78045
- const result2 = await client.removeWorkspaceMember(options.email, code, captured.membershipId, captured.body);
78574
+ const result2 = await client.removeWorkspaceMember(options.email, code, captured.membershipId, captured.body, target.context);
78046
78575
  if (options.json)
78047
78576
  console.log(JSON.stringify(result2));
78048
78577
  else
@@ -78062,7 +78591,7 @@ function registerWorkspaceMemberMutationCommands(workspace) {
78062
78591
  }
78063
78592
  }
78064
78593
  var init_workspace_member_mutations = __esm(() => {
78065
- init_auth_store();
78594
+ init_workspace_profile();
78066
78595
  init_remote_auth();
78067
78596
  init_remote_client();
78068
78597
  init_remote_workspace();
@@ -78077,6 +78606,7 @@ __export(exports_customer_profile, {
78077
78606
  function registerCustomerProfileCommands(program2) {
78078
78607
  const account = program2.command("account").description("Manage your account on the selected Skills server");
78079
78608
  const workspace = program2.command("workspace").description("Manage the current workspace on the selected Skills server");
78609
+ registerWorkspaceListCommand(workspace);
78080
78610
  registerWorkspaceMembersCommand(workspace);
78081
78611
  registerWorkspaceMemberMutationCommands(workspace);
78082
78612
  const commands = [
@@ -78086,7 +78616,8 @@ function registerCustomerProfileCommands(program2) {
78086
78616
  for (const { kind, command } of commands) {
78087
78617
  command.allowExcessArguments(false).description(kind === "account" ? "Update your display name with fresh email verification" : "Update the current workspace name as an owner or admin").requiredOption(kind === "account" ? "--display-name <name>" : "--name <name>", "New name (1\u2013100 characters)").requiredOption("--email <email>", "Account email for fresh verification").option("--code-stdin", "Read a previously requested six-digit verification code from stdin").option("--json", "Output JSON").action(async (options) => {
78088
78618
  try {
78089
- const client = new RemoteSkillsAuthClient(getApiUrl(`Update ${kind} name`));
78619
+ const pending = prepareProfileWorkspace(`Update ${kind} name`);
78620
+ const client = new RemoteSkillsAuthClient(pending.origin);
78090
78621
  customerNamePatch(kind === "account" ? { displayName: options.displayName } : { name: options.name }, kind === "account" ? "displayName" : "name");
78091
78622
  if (!options.codeStdin && (options.json || !process.stdin.isTTY || !process.stderr.isTTY)) {
78092
78623
  throw new NameInputError("Use --code-stdin with a fresh verification code for JSON or noninteractive updates.");
@@ -78100,7 +78631,9 @@ function registerCustomerProfileCommands(program2) {
78100
78631
  }
78101
78632
  if (code === null)
78102
78633
  return;
78103
- const result2 = kind === "account" ? await client.updateProfile(options.email, code, { displayName: options.displayName }) : await client.updateCurrentWorkspace(options.email, code, { name: options.name });
78634
+ const target = await pending.resolve();
78635
+ target.unchanged();
78636
+ const result2 = kind === "account" ? await client.updateProfile(options.email, code, { displayName: options.displayName }, target.context) : await client.updateCurrentWorkspace(options.email, code, { name: options.name }, target.context);
78104
78637
  if (options.json)
78105
78638
  console.log(JSON.stringify(result2));
78106
78639
  else
@@ -78118,7 +78651,8 @@ function registerCustomerProfileCommands(program2) {
78118
78651
  }
78119
78652
  }
78120
78653
  var init_customer_profile = __esm(() => {
78121
- init_auth_store();
78654
+ init_workspace_profile();
78655
+ init_workspace_selection();
78122
78656
  init_remote_auth();
78123
78657
  init_customer_verification();
78124
78658
  init_workspace_members();
@@ -78265,8 +78799,8 @@ var init_storage = __esm(() => {
78265
78799
  });
78266
78800
 
78267
78801
  // src/lib/registry-reconcile.ts
78268
- import { existsSync as existsSync33, readFileSync as readFileSync30, statSync as statSync20, writeFileSync as writeFileSync19 } from "fs";
78269
- import { join as join38 } from "path";
78802
+ import { existsSync as existsSync33, readFileSync as readFileSync31, statSync as statSync20, writeFileSync as writeFileSync20 } from "fs";
78803
+ import { join as join39 } from "path";
78270
78804
  function isDirectory2(path) {
78271
78805
  try {
78272
78806
  return statSync20(path).isDirectory();
@@ -78277,15 +78811,15 @@ function isDirectory2(path) {
78277
78811
  function migrationNeeded(options) {
78278
78812
  if (options.rootDir)
78279
78813
  return false;
78280
- const appDir = options.homeDir ? join38(options.homeDir, ".hasna", "skills") : getDataDir();
78281
- return !(isOwnerLayoutMigrated(appDir) && isDirectory2(join38(appDir, SKILLS_CACHE_DIRNAME)));
78814
+ const appDir = options.homeDir ? join39(options.homeDir, ".hasna", "skills") : getDataDir();
78815
+ return !(isOwnerLayoutMigrated(appDir) && isDirectory2(join39(appDir, SKILLS_CACHE_DIRNAME)));
78282
78816
  }
78283
78817
  function readBaseline(skillDir) {
78284
- const markerPath = join38(skillDir, PULL_MARKER_FILE);
78818
+ const markerPath = join39(skillDir, PULL_MARKER_FILE);
78285
78819
  if (!existsSync33(markerPath))
78286
78820
  return;
78287
78821
  try {
78288
- const marker = JSON.parse(readFileSync30(markerPath, "utf-8"));
78822
+ const marker = JSON.parse(readFileSync31(markerPath, "utf-8"));
78289
78823
  if (!isSkillsOwnershipMarker(marker))
78290
78824
  return;
78291
78825
  return {
@@ -78297,11 +78831,11 @@ function readBaseline(skillDir) {
78297
78831
  }
78298
78832
  }
78299
78833
  function readCursor(root) {
78300
- const path = join38(root, SYNC_CURSOR_FILE);
78834
+ const path = join39(root, SYNC_CURSOR_FILE);
78301
78835
  if (!existsSync33(path))
78302
78836
  return { runCount: 0 };
78303
78837
  try {
78304
- const cursor2 = JSON.parse(readFileSync30(path, "utf-8"));
78838
+ const cursor2 = JSON.parse(readFileSync31(path, "utf-8"));
78305
78839
  return { runCount: typeof cursor2.runCount === "number" ? cursor2.runCount : 0 };
78306
78840
  } catch {
78307
78841
  return { runCount: 0 };
@@ -78310,21 +78844,21 @@ function readCursor(root) {
78310
78844
  function resolveCorpusRootReadOnly(options) {
78311
78845
  if (options.rootDir)
78312
78846
  return { root: options.rootDir, migrationPending: false };
78313
- const appDir = options.homeDir ? join38(options.homeDir, ".hasna", "skills") : getDataDirReadOnly();
78314
- const cache3 = join38(appDir, SKILLS_CACHE_DIRNAME);
78847
+ const appDir = options.homeDir ? join39(options.homeDir, ".hasna", "skills") : getDataDirReadOnly();
78848
+ const cache3 = join39(appDir, SKILLS_CACHE_DIRNAME);
78315
78849
  if (isOwnerLayoutMigrated(appDir) && isDirectory2(cache3)) {
78316
78850
  return { root: cache3, migrationPending: false };
78317
78851
  }
78318
- return { root: join38(appDir, INSTALLED_SKILLS_DIRNAME), migrationPending: true };
78852
+ return { root: join39(appDir, INSTALLED_SKILLS_DIRNAME), migrationPending: true };
78319
78853
  }
78320
- function remoteRowToSkill(record4) {
78321
- const slug = typeof record4.slug === "string" ? record4.slug : typeof record4.name === "string" ? record4.name : undefined;
78854
+ function remoteRowToSkill(record5) {
78855
+ const slug = typeof record5.slug === "string" ? record5.slug : typeof record5.name === "string" ? record5.name : undefined;
78322
78856
  if (!slug)
78323
78857
  return;
78324
78858
  return {
78325
78859
  slug,
78326
- version: typeof record4.version === "string" ? record4.version : undefined,
78327
- sha256: typeof record4.bundleSha256 === "string" && record4.bundleSha256 ? record4.bundleSha256 : undefined
78860
+ version: typeof record5.version === "string" ? record5.version : undefined,
78861
+ sha256: typeof record5.bundleSha256 === "string" && record5.bundleSha256 ? record5.bundleSha256 : undefined
78328
78862
  };
78329
78863
  }
78330
78864
  function recheckLocalSide(plannedLocal, localDir, ops = {
@@ -78449,7 +78983,7 @@ async function reconcileRegistry(options = {}) {
78449
78983
  for (const slug of allSlugs) {
78450
78984
  const local = locals.get(slug);
78451
78985
  const remote = remotes.get(slug);
78452
- const baseline = local ? readBaseline(join38(root, slug)) : undefined;
78986
+ const baseline = local ? readBaseline(join39(root, slug)) : undefined;
78453
78987
  const { state, reason } = classifySkill(local, remote, baseline);
78454
78988
  let { action, reason: actionReason } = resolveAction(state, direction, conflict);
78455
78989
  if (state === "remote-only" && isDigestless(remote)) {
@@ -78508,7 +79042,7 @@ async function reconcileRegistry(options = {}) {
78508
79042
  try {
78509
79043
  await pushSkill(slug, { rootDir: root, client });
78510
79044
  const pushed = locals.get(slug);
78511
- writePullMarker(join38(root, slug), {
79045
+ writePullMarker(join39(root, slug), {
78512
79046
  skill: slug,
78513
79047
  ...pushed?.version ? { version: pushed.version } : {},
78514
79048
  ...pushed?.sha256 ? { contentHash: pushed.sha256 } : {},
@@ -78580,7 +79114,7 @@ async function reconcileRegistry(options = {}) {
78580
79114
  runCount: readCursor(root).runCount + 1,
78581
79115
  summary
78582
79116
  };
78583
- writeFileSync19(join38(root, SYNC_CURSOR_FILE), `${JSON.stringify(cursor2, null, 2)}
79117
+ writeFileSync20(join39(root, SYNC_CURSOR_FILE), `${JSON.stringify(cursor2, null, 2)}
78584
79118
  `);
78585
79119
  return {
78586
79120
  corpusRoot: root,