@serviceme/devtools-core 0.3.3 → 0.3.4

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.
@@ -184,6 +184,24 @@ declare class StubGitSpawner implements GitSpawner {
184
184
  * RepoManager's `localSeed` use case.
185
185
  */
186
186
  declare function toFileUrl(absolutePath: string): string;
187
+ /** Path suffix appended to a server base URL to reach its git-proxy route. */
188
+ declare const GIT_PROXY_PATH_SUFFIX = "/git-proxy";
189
+ /**
190
+ * Single source of truth for deriving a {@link GitClientOptions.serverProxyBase}
191
+ * from an already-resolved, non-empty server base URL (e.g. the extension's
192
+ * verified marketplace server). Callers that derive `serverProxyBase` from a
193
+ * known server base URL — extension bootstrap, the sync scheduler, the CLI
194
+ * bridge subprocess env — should go through this helper instead of
195
+ * re-deriving the `/git-proxy` suffix locally, so the route contract only
196
+ * lives in one place. (Standalone CLI defaults such as
197
+ * `http://127.0.0.1:3000/git-proxy`, used when no server base URL is known
198
+ * at all, are a separate concern and don't go through this helper.)
199
+ *
200
+ * Callers MUST guard against an empty/falsy `serverBaseUrl` before calling —
201
+ * this function does not validate its input and will happily return the
202
+ * non-URL `"/git-proxy"` for an empty string.
203
+ */
204
+ declare function buildGitProxyBase(serverBaseUrl: string): string;
187
205
 
188
206
  /**
189
207
  * Skill & Agent v2 — SubmitClient Types (M4)
@@ -288,4 +306,4 @@ declare class SubmitClient {
288
306
  submit(repoId: string, skillName: string, files: SkillFile[], opts?: SubmitOptions): Promise<SubmitResult>;
289
307
  }
290
308
 
291
- export { GitClient as G, NodeGitSpawner as N, type PullResult as P, StubGitSpawner as S, GitError as a, SubmitClient as b, type SubmitClientOptions as c, SubmitError as d, type SubmitOptions as e, type SubmitResult as f, toFileUrl as t };
309
+ export { GitClient as G, NodeGitSpawner as N, type PullResult as P, StubGitSpawner as S, GIT_PROXY_PATH_SUFFIX as a, GitError as b, SubmitClient as c, type SubmitClientOptions as d, SubmitError as e, type SubmitOptions as f, type SubmitResult as g, buildGitProxyBase as h, toFileUrl as t };
@@ -184,6 +184,24 @@ declare class StubGitSpawner implements GitSpawner {
184
184
  * RepoManager's `localSeed` use case.
185
185
  */
186
186
  declare function toFileUrl(absolutePath: string): string;
187
+ /** Path suffix appended to a server base URL to reach its git-proxy route. */
188
+ declare const GIT_PROXY_PATH_SUFFIX = "/git-proxy";
189
+ /**
190
+ * Single source of truth for deriving a {@link GitClientOptions.serverProxyBase}
191
+ * from an already-resolved, non-empty server base URL (e.g. the extension's
192
+ * verified marketplace server). Callers that derive `serverProxyBase` from a
193
+ * known server base URL — extension bootstrap, the sync scheduler, the CLI
194
+ * bridge subprocess env — should go through this helper instead of
195
+ * re-deriving the `/git-proxy` suffix locally, so the route contract only
196
+ * lives in one place. (Standalone CLI defaults such as
197
+ * `http://127.0.0.1:3000/git-proxy`, used when no server base URL is known
198
+ * at all, are a separate concern and don't go through this helper.)
199
+ *
200
+ * Callers MUST guard against an empty/falsy `serverBaseUrl` before calling —
201
+ * this function does not validate its input and will happily return the
202
+ * non-URL `"/git-proxy"` for an empty string.
203
+ */
204
+ declare function buildGitProxyBase(serverBaseUrl: string): string;
187
205
 
188
206
  /**
189
207
  * Skill & Agent v2 — SubmitClient Types (M4)
@@ -288,4 +306,4 @@ declare class SubmitClient {
288
306
  submit(repoId: string, skillName: string, files: SkillFile[], opts?: SubmitOptions): Promise<SubmitResult>;
289
307
  }
290
308
 
291
- export { GitClient as G, NodeGitSpawner as N, type PullResult as P, StubGitSpawner as S, GitError as a, SubmitClient as b, type SubmitClientOptions as c, SubmitError as d, type SubmitOptions as e, type SubmitResult as f, toFileUrl as t };
309
+ export { GitClient as G, NodeGitSpawner as N, type PullResult as P, StubGitSpawner as S, GIT_PROXY_PATH_SUFFIX as a, GitError as b, SubmitClient as c, type SubmitClientOptions as d, SubmitError as e, type SubmitOptions as f, type SubmitResult as g, buildGitProxyBase as h, toFileUrl as t };
package/dist/index.d.mts CHANGED
@@ -4,8 +4,8 @@ import * as fs from 'node:fs/promises';
4
4
  export { A as AccessCheckResult, a as AccessControl, b as AccessControlOptions, c as AuthCore, d as AuthCoreOptions, e as AuthStateManager, f as AuthStateManagerOptions, C as CancellationCheck, D as DeviceFlowUiCallback, G as GitHubAuthProvider, g as GitHubAuthProviderConfig, I as IAuthProvider, h as IAuthProviderSession, i as IAuthProviderUserInfo, j as InMemoryKeychainAuthTokenStore, K as KeyValueStore, k as KeychainAccountKey, l as KeychainAuthTokenStore, m as KeychainTokenEnvelope, n as KeychainTokenMetadata, o as KeychainUnavailableError, M as MicrosoftAuthProvider, p as MicrosoftProviderNotHostedError, O as OrgMembershipFetcher, P as ProviderRegistry, S as ServiceMeLogger, q as buildGitHubLocalEmail, r as createConsoleLogger, s as isGitHubLocalEmail, t as noopLogger, u as resolvePrimaryEmail } from './index-87-_JvQi.mjs';
5
5
  export { AtomicWriteResult, BuildSignedHeadersParams, DEVICE_JSON_SCHEMA_VERSION, DeviceAuthHeaders, DeviceCore, DeviceCoreOptions, DeviceReenrollRequiresAuthError, DeviceRequestSignatureParams, DeviceSecretVersionMismatchError, DeviceSignedHeaders, EnrollRequestFn, EnrollResponse, Enroller, EnrollerOptions, FsIdentityFileBackend, IdentityFileBackend, IdentityStore, IdentityStoreHooks, IdentityStoreOptions, PersistedDeviceIdentity, buildSignedHeaders, createDeviceRequestSignature, deriveInstallationId, fingerprintSource, randomInstallationId } from './device.mjs';
6
6
  import { c as SkillKind, b as SkillFile } from './types-B9gk3dXH.mjs';
7
- import { G as GitClient, P as PullResult } from './index-GAigCT0j.mjs';
8
- export { a as GitError, N as NodeGitSpawner, S as StubGitSpawner, b as SubmitClient, c as SubmitClientOptions, d as SubmitError, e as SubmitOptions, f as SubmitResult, t as toFileUrl } from './index-GAigCT0j.mjs';
7
+ import { G as GitClient, P as PullResult } from './index-CXvNx2fp.mjs';
8
+ export { a as GIT_PROXY_PATH_SUFFIX, b as GitError, N as NodeGitSpawner, S as StubGitSpawner, c as SubmitClient, d as SubmitClientOptions, e as SubmitError, f as SubmitOptions, g as SubmitResult, h as buildGitProxyBase, t as toFileUrl } from './index-CXvNx2fp.mjs';
9
9
  import * as fs$1 from 'node:fs';
10
10
  import { z } from 'zod';
11
11
  export { BUILTIN_DEFAULT_TOOLS, DefaultToolImmutableError, DefaultToolSeed, FsToolboxFileBackend, PersistedToolbox, ResolvedToolbox, TOOLBOX_JSON_SCHEMA_VERSION, ToolboxCore, ToolboxCoreOptions, ToolboxFileBackend, ToolboxPatch, ToolboxStore, ToolboxStoreHooks, ToolboxStoreOptions, WORKSPACE_TOOLBOX_RELATIVE_PATH, mergeWithDefaults, reindexOrder, sortByRecentFirst, sortByUserOrder, touchLastUsedAt } from './toolbox.mjs';
@@ -254,10 +254,18 @@ interface EnvironmentInspectorOptions {
254
254
  * use this to exercise the Windows-specific branches of the inspector.
255
255
  */
256
256
  platform?: NodeJS.Platform;
257
+ /**
258
+ * Override the value returned by `$SHELL` for POSIX login-shell
259
+ * fallbacks. Defaults to `process.env.SHELL`. Tests pin this so the
260
+ * fallback chain stays deterministic regardless of the developer's
261
+ * host machine.
262
+ */
263
+ shell?: string;
257
264
  }
258
265
  declare class EnvironmentInspector {
259
266
  private readonly runCommandFn;
260
267
  private readonly platform;
268
+ private readonly shell;
261
269
  constructor(options?: EnvironmentInspectorOptions);
262
270
  checkEnvironment(): Promise<EnvironmentCheckResult>;
263
271
  checkTool(toolName: KnownEnvironmentTool): Promise<ToolCheckResult>;
package/dist/index.d.ts CHANGED
@@ -4,8 +4,8 @@ import * as fs from 'node:fs/promises';
4
4
  export { A as AccessCheckResult, a as AccessControl, b as AccessControlOptions, c as AuthCore, d as AuthCoreOptions, e as AuthStateManager, f as AuthStateManagerOptions, C as CancellationCheck, D as DeviceFlowUiCallback, G as GitHubAuthProvider, g as GitHubAuthProviderConfig, I as IAuthProvider, h as IAuthProviderSession, i as IAuthProviderUserInfo, j as InMemoryKeychainAuthTokenStore, K as KeyValueStore, k as KeychainAccountKey, l as KeychainAuthTokenStore, m as KeychainTokenEnvelope, n as KeychainTokenMetadata, o as KeychainUnavailableError, M as MicrosoftAuthProvider, p as MicrosoftProviderNotHostedError, O as OrgMembershipFetcher, P as ProviderRegistry, S as ServiceMeLogger, q as buildGitHubLocalEmail, r as createConsoleLogger, s as isGitHubLocalEmail, t as noopLogger, u as resolvePrimaryEmail } from './index-87-_JvQi.js';
5
5
  export { AtomicWriteResult, BuildSignedHeadersParams, DEVICE_JSON_SCHEMA_VERSION, DeviceAuthHeaders, DeviceCore, DeviceCoreOptions, DeviceReenrollRequiresAuthError, DeviceRequestSignatureParams, DeviceSecretVersionMismatchError, DeviceSignedHeaders, EnrollRequestFn, EnrollResponse, Enroller, EnrollerOptions, FsIdentityFileBackend, IdentityFileBackend, IdentityStore, IdentityStoreHooks, IdentityStoreOptions, PersistedDeviceIdentity, buildSignedHeaders, createDeviceRequestSignature, deriveInstallationId, fingerprintSource, randomInstallationId } from './device.js';
6
6
  import { c as SkillKind, b as SkillFile } from './types-B9gk3dXH.js';
7
- import { G as GitClient, P as PullResult } from './index-BmxS1A9G.js';
8
- export { a as GitError, N as NodeGitSpawner, S as StubGitSpawner, b as SubmitClient, c as SubmitClientOptions, d as SubmitError, e as SubmitOptions, f as SubmitResult, t as toFileUrl } from './index-BmxS1A9G.js';
7
+ import { G as GitClient, P as PullResult } from './index-CR1hbAnO.js';
8
+ export { a as GIT_PROXY_PATH_SUFFIX, b as GitError, N as NodeGitSpawner, S as StubGitSpawner, c as SubmitClient, d as SubmitClientOptions, e as SubmitError, f as SubmitOptions, g as SubmitResult, h as buildGitProxyBase, t as toFileUrl } from './index-CR1hbAnO.js';
9
9
  import * as fs$1 from 'node:fs';
10
10
  import { z } from 'zod';
11
11
  export { BUILTIN_DEFAULT_TOOLS, DefaultToolImmutableError, DefaultToolSeed, FsToolboxFileBackend, PersistedToolbox, ResolvedToolbox, TOOLBOX_JSON_SCHEMA_VERSION, ToolboxCore, ToolboxCoreOptions, ToolboxFileBackend, ToolboxPatch, ToolboxStore, ToolboxStoreHooks, ToolboxStoreOptions, WORKSPACE_TOOLBOX_RELATIVE_PATH, mergeWithDefaults, reindexOrder, sortByRecentFirst, sortByUserOrder, touchLastUsedAt } from './toolbox.js';
@@ -254,10 +254,18 @@ interface EnvironmentInspectorOptions {
254
254
  * use this to exercise the Windows-specific branches of the inspector.
255
255
  */
256
256
  platform?: NodeJS.Platform;
257
+ /**
258
+ * Override the value returned by `$SHELL` for POSIX login-shell
259
+ * fallbacks. Defaults to `process.env.SHELL`. Tests pin this so the
260
+ * fallback chain stays deterministic regardless of the developer's
261
+ * host machine.
262
+ */
263
+ shell?: string;
257
264
  }
258
265
  declare class EnvironmentInspector {
259
266
  private readonly runCommandFn;
260
267
  private readonly platform;
268
+ private readonly shell;
261
269
  constructor(options?: EnvironmentInspectorOptions);
262
270
  checkEnvironment(): Promise<EnvironmentCheckResult>;
263
271
  checkTool(toolName: KnownEnvironmentTool): Promise<ToolCheckResult>;
package/dist/index.js CHANGED
@@ -59,6 +59,7 @@ __export(src_exports, {
59
59
  EnvironmentInspector: () => EnvironmentInspector,
60
60
  FsIdentityFileBackend: () => FsIdentityFileBackend,
61
61
  FsToolboxFileBackend: () => FsToolboxFileBackend,
62
+ GIT_PROXY_PATH_SUFFIX: () => GIT_PROXY_PATH_SUFFIX,
62
63
  GitClient: () => GitClient,
63
64
  GitError: () => GitError,
64
65
  GitHubAuthProvider: () => GitHubAuthProvider,
@@ -125,6 +126,7 @@ __export(src_exports, {
125
126
  bootstrapPhase5Placeholders: () => bootstrapPhase5Placeholders,
126
127
  buildDefaultReposFile: () => buildDefaultReposFile,
127
128
  buildGitHubLocalEmail: () => buildGitHubLocalEmail,
129
+ buildGitProxyBase: () => buildGitProxyBase,
128
130
  buildSignedHeaders: () => buildSignedHeaders,
129
131
  copilotDoctor: () => copilotDoctor,
130
132
  copilotPrompt: () => copilotPrompt,
@@ -2733,10 +2735,33 @@ var POSIX_LOGIN_SHELL_FALLBACK_TOOLS = /* @__PURE__ */ new Set([
2733
2735
  ]);
2734
2736
  var ERROR_CODE_NOT_FOUND = 127;
2735
2737
  var ERROR_CODE_TIMEOUT = "ETIMEDOUT";
2738
+ var NVM_FALLBACK_DIRS = [
2739
+ "/opt/homebrew/opt/nvm",
2740
+ "/usr/local/opt/nvm",
2741
+ "$HOME/.nvm"
2742
+ ];
2743
+ function resolveUserLoginShell(platform3, envShell) {
2744
+ const shell = envShell?.trim();
2745
+ if (shell && shell.length > 0) {
2746
+ return shell;
2747
+ }
2748
+ return platform3 === "darwin" ? "/bin/zsh" : "/bin/bash";
2749
+ }
2750
+ function buildNvmSourcingSnippet() {
2751
+ const fallbackList = NVM_FALLBACK_DIRS.map((dir) => `"${dir}"`).join(" ");
2752
+ return `for d in $NVM_DIR ${fallbackList}; do [ -n "$d" ] && [ -s "$d/nvm.sh" ] && export NVM_DIR="$d" && . "$d/nvm.sh" && break; done`;
2753
+ }
2754
+ function posixLoginShellArgs(platform3, envShell, command) {
2755
+ return {
2756
+ command: resolveUserLoginShell(platform3, envShell),
2757
+ args: ["-lc", `${buildNvmSourcingSnippet()}; ${command}`]
2758
+ };
2759
+ }
2736
2760
  var EnvironmentInspector = class {
2737
2761
  constructor(options = {}) {
2738
2762
  this.runCommandFn = options.runCommand ?? runCommand;
2739
2763
  this.platform = options.platform ?? process.platform;
2764
+ this.shell = options.shell ?? process.env.SHELL;
2740
2765
  }
2741
2766
  async checkEnvironment() {
2742
2767
  const results = await Promise.all(
@@ -2783,11 +2808,9 @@ var EnvironmentInspector = class {
2783
2808
  }
2784
2809
  async getToolPathFromLoginShell(toolName) {
2785
2810
  try {
2786
- const result = await this.runCommandFn("/bin/bash", {
2787
- args: [
2788
- "-lc",
2789
- 'export NVM_DIR="$HOME/.nvm"; [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"; command -v ' + toolName
2790
- ],
2811
+ const spawnArgs = posixLoginShellArgs(this.platform, this.shell, `command -v ${toolName}`);
2812
+ const result = await this.runCommandFn(spawnArgs.command, {
2813
+ args: spawnArgs.args,
2791
2814
  timeoutMs: this.getToolTimeout(toolName)
2792
2815
  });
2793
2816
  return result.stdout.split(/\r?\n/).map((line) => line.trim()).find((line) => line.length > 0);
@@ -2826,11 +2849,9 @@ var EnvironmentInspector = class {
2826
2849
  if (!this.shouldUsePosixLoginShellFallback(toolName)) {
2827
2850
  throw error;
2828
2851
  }
2829
- const fallbackResult = await this.runCommandFn("/bin/bash", {
2830
- args: [
2831
- "-lc",
2832
- `export NVM_DIR="$HOME/.nvm"; [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"; ${toolName} --version`
2833
- ],
2852
+ const fallbackArgs = posixLoginShellArgs(this.platform, this.shell, `${toolName} --version`);
2853
+ const fallbackResult = await this.runCommandFn(fallbackArgs.command, {
2854
+ args: fallbackArgs.args,
2834
2855
  timeoutMs: this.getToolTimeout(toolName)
2835
2856
  });
2836
2857
  const fallbackOutput = (fallbackResult.stdout || fallbackResult.stderr).trim();
@@ -2863,11 +2884,9 @@ var EnvironmentInspector = class {
2863
2884
  }
2864
2885
  }
2865
2886
  try {
2866
- const result = await this.runCommandFn("/bin/bash", {
2867
- args: [
2868
- "-lc",
2869
- 'export NVM_DIR="$HOME/.nvm"; [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"; nvm --version'
2870
- ],
2887
+ const nvmArgs = posixLoginShellArgs(this.platform, this.shell, "nvm --version");
2888
+ const result = await this.runCommandFn(nvmArgs.command, {
2889
+ args: nvmArgs.args,
2871
2890
  timeoutMs: this.getToolTimeout("nvm")
2872
2891
  });
2873
2892
  return {
@@ -3054,7 +3073,9 @@ var GitClient = class {
3054
3073
  }
3055
3074
  const targetUrl = useProxy ? remoteUrl : originalUrl ?? remoteUrl;
3056
3075
  const proxyUrl = this.rewriteRemoteUrl(repoId, targetUrl, useProxy);
3057
- await this.runOrThrow(["remote", "set-url", "origin", proxyUrl], { cwd: localPath });
3076
+ await this.runOrThrow(["remote", "set-url", "origin", proxyUrl], {
3077
+ cwd: localPath
3078
+ });
3058
3079
  const before = await this.safeRevParse(localPath);
3059
3080
  await this.runOrThrow(["fetch", "origin"], { cwd: localPath });
3060
3081
  const after = await this.safeRevParse(localPath);
@@ -3090,7 +3111,9 @@ var GitClient = class {
3090
3111
  throw new Error(`no 'origin' remote configured at ${localPath}`);
3091
3112
  }
3092
3113
  const proxyUrl = this.rewriteRemoteUrl(repoId, remoteUrl, useProxy);
3093
- await this.runOrThrow(["remote", "set-url", "origin", proxyUrl], { cwd: localPath });
3114
+ await this.runOrThrow(["remote", "set-url", "origin", proxyUrl], {
3115
+ cwd: localPath
3116
+ });
3094
3117
  const result = await this.spawner.spawn(
3095
3118
  ["push", "origin", `refs/heads/${branch}:refs/heads/${branch}`],
3096
3119
  { cwd: localPath }
@@ -3144,7 +3167,9 @@ var GitClient = class {
3144
3167
  return { commitSha: sha };
3145
3168
  }
3146
3169
  async runOrThrow(args, opts) {
3147
- const result = await this.spawner.spawn(args, { cwd: opts.cwd ?? process.cwd() });
3170
+ const result = await this.spawner.spawn(args, {
3171
+ cwd: opts.cwd ?? process.cwd()
3172
+ });
3148
3173
  if (result.code !== 0) {
3149
3174
  throw new GitError(args, result);
3150
3175
  }
@@ -3159,7 +3184,9 @@ var GitClient = class {
3159
3184
  return url.length > 0 ? url : void 0;
3160
3185
  }
3161
3186
  async safeRevParse(localPath) {
3162
- const result = await this.spawner.spawn(["rev-parse", "HEAD"], { cwd: localPath });
3187
+ const result = await this.spawner.spawn(["rev-parse", "HEAD"], {
3188
+ cwd: localPath
3189
+ });
3163
3190
  if (result.code !== 0) return "";
3164
3191
  return result.stdout.trim();
3165
3192
  }
@@ -3206,7 +3233,11 @@ var StubGitSpawner = class {
3206
3233
  this.calls.push({ args, cwd: opts.cwd });
3207
3234
  const next = this.script.shift();
3208
3235
  if (!next) {
3209
- return { stdout: "", stderr: `stub: no scripted response for ${args.join(" ")}`, code: 1 };
3236
+ return {
3237
+ stdout: "",
3238
+ stderr: `stub: no scripted response for ${args.join(" ")}`,
3239
+ code: 1
3240
+ };
3210
3241
  }
3211
3242
  return next;
3212
3243
  }
@@ -3218,6 +3249,10 @@ function toFileUrl(absolutePath) {
3218
3249
  }
3219
3250
  return `file://${normalized}`;
3220
3251
  }
3252
+ var GIT_PROXY_PATH_SUFFIX = "/git-proxy";
3253
+ function buildGitProxyBase(serverBaseUrl) {
3254
+ return `${serverBaseUrl.replace(/\/+$/, "")}${GIT_PROXY_PATH_SUFFIX}`;
3255
+ }
3221
3256
 
3222
3257
  // src/image/imageTools.ts
3223
3258
  var fs5 = __toESM(require("fs/promises"));
@@ -7398,6 +7433,7 @@ var ToolboxCore = class {
7398
7433
  EnvironmentInspector,
7399
7434
  FsIdentityFileBackend,
7400
7435
  FsToolboxFileBackend,
7436
+ GIT_PROXY_PATH_SUFFIX,
7401
7437
  GitClient,
7402
7438
  GitError,
7403
7439
  GitHubAuthProvider,
@@ -7464,6 +7500,7 @@ var ToolboxCore = class {
7464
7500
  bootstrapPhase5Placeholders,
7465
7501
  buildDefaultReposFile,
7466
7502
  buildGitHubLocalEmail,
7503
+ buildGitProxyBase,
7467
7504
  buildSignedHeaders,
7468
7505
  copilotDoctor,
7469
7506
  copilotPrompt,