@serviceme/devtools-core 2.0.2 → 2.0.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.
Files changed (56) hide show
  1. package/dist/{device-CDDcwDY6.mjs → device-BVcUUQ9t.mjs} +54 -19
  2. package/dist/device-BVcUUQ9t.mjs.map +1 -0
  3. package/dist/device-DCo0rgUt.mjs +793 -0
  4. package/dist/device-DCo0rgUt.mjs.map +1 -0
  5. package/dist/{device-DuAYH8bk.js → device-ihxrFR-w.js} +52 -17
  6. package/dist/device-ihxrFR-w.js.map +1 -0
  7. package/dist/device-uFAQxlNt.js +874 -0
  8. package/dist/device-uFAQxlNt.js.map +1 -0
  9. package/dist/device-yWpY_Zds.js +874 -0
  10. package/dist/device-yWpY_Zds.js.map +1 -0
  11. package/dist/device.d.mts +1 -1
  12. package/dist/device.d.ts +1 -1
  13. package/dist/device.js +1 -1
  14. package/dist/device.mjs +1 -1
  15. package/dist/{index-BI11AfMH.d.ts → index-DGXYp8J5.d.mts} +30 -15
  16. package/dist/{index-BI11AfMH.d.mts → index-DGXYp8J5.d.ts} +30 -15
  17. package/dist/index.d.mts +13 -82
  18. package/dist/index.d.ts +13 -82
  19. package/dist/index.js +72 -138
  20. package/dist/index.js.map +1 -1
  21. package/dist/index.mjs +74 -135
  22. package/dist/index.mjs.map +1 -1
  23. package/dist/skill-linker.js +1 -1
  24. package/dist/skill-linker.mjs +1 -1
  25. package/dist/{submit-Cg7wSa3x.mjs → submit-6zQPPrOJ.mjs} +2 -2
  26. package/dist/{submit-Cg7wSa3x.mjs.map → submit-6zQPPrOJ.mjs.map} +1 -1
  27. package/dist/submit-BTdbGEAd.mjs +84 -0
  28. package/dist/submit-BTdbGEAd.mjs.map +1 -0
  29. package/dist/submit-CW9schoc.js +98 -0
  30. package/dist/submit-CW9schoc.js.map +1 -0
  31. package/dist/submit-Dy0KTHzm.js +98 -0
  32. package/dist/submit-Dy0KTHzm.js.map +1 -0
  33. package/dist/submit.js +1 -1
  34. package/dist/submit.mjs +1 -1
  35. package/dist/toolbox-BV7vLGXZ.js +614 -0
  36. package/dist/toolbox-BV7vLGXZ.js.map +1 -0
  37. package/dist/{toolbox-CbfxpNg-.mjs → toolbox-BxgnUyDU.mjs} +2 -2
  38. package/dist/{toolbox-CbfxpNg-.mjs.map → toolbox-BxgnUyDU.mjs.map} +1 -1
  39. package/dist/toolbox-GSWMRdts.js +614 -0
  40. package/dist/toolbox-GSWMRdts.js.map +1 -0
  41. package/dist/toolbox-UG4dA2TI.mjs +540 -0
  42. package/dist/toolbox-UG4dA2TI.mjs.map +1 -0
  43. package/dist/toolbox.js +1 -1
  44. package/dist/toolbox.mjs +1 -1
  45. package/dist/userHome-B97jBm5O.mjs +196 -0
  46. package/dist/userHome-B97jBm5O.mjs.map +1 -0
  47. package/dist/userHome-Baz205B7.js +498 -0
  48. package/dist/userHome-Baz205B7.js.map +1 -0
  49. package/dist/userHome-CLlsXCvW.js +518 -0
  50. package/dist/userHome-CLlsXCvW.js.map +1 -0
  51. package/dist/{userHome-CcnAQPG1.mjs → userHome-DOMLiHy7.mjs} +2 -4
  52. package/dist/userHome-DOMLiHy7.mjs.map +1 -0
  53. package/package.json +2 -2
  54. package/dist/device-CDDcwDY6.mjs.map +0 -1
  55. package/dist/device-DuAYH8bk.js.map +0 -1
  56. package/dist/userHome-CcnAQPG1.mjs.map +0 -1
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { A as KeyValueStore, C as AuthStateManagerOptions, D as AccessCheckResult, E as noopLogger, O as AccessControl, S as AuthStateManager, T as createConsoleLogger, _ as KeychainAccountKey, a as MicrosoftProviderNotHostedError, b as KeychainTokenMetadata, c as AuthCore, d as DeviceFlowUiCallback, f as ProviderRegistry, g as InMemoryKeychainAuthTokenStore, h as IAuthProviderUserInfo, i as MicrosoftAuthProvider, j as OrgMembershipFetcher, k as AccessControlOptions, l as AuthCoreOptions, m as IAuthProviderSession, n as isGitHubLocalEmail, o as GitHubAuthProvider, p as IAuthProvider, r as resolvePrimaryEmail, s as GitHubAuthProviderConfig, t as buildGitHubLocalEmail, u as CancellationCheck, v as KeychainAuthTokenStore, w as ServiceMeLogger, x as KeychainUnavailableError, y as KeychainTokenEnvelope } from "./index-CoA6y0MP.js";
2
- import { C as DeviceSignedHeaders, S as DeviceRequestSignatureParams, T as createDeviceRequestSignature, _ as DEVICE_JSON_SCHEMA_VERSION, a as DeviceCoreOptions, b as BuildSignedHeadersParams, c as EnrollRequestFn, d as EnrollerOptions, f as FsIdentityFileBackend, g as AtomicWriteResult, h as IdentityStoreOptions, i as DeviceCore, l as EnrollResponse, m as IdentityStore, n as fingerprintSource, o as DeviceReenrollRequiresAuthError, p as IdentityFileBackend, r as randomInstallationId, s as DeviceSecretVersionMismatchError, t as deriveInstallationId, u as Enroller, v as IdentityStoreHooks, w as buildSignedHeaders, x as DeviceAuthHeaders, y as PersistedDeviceIdentity } from "./index-BI11AfMH.js";
2
+ import { C as DeviceSignedHeaders, S as DeviceRequestSignatureParams, T as createDeviceRequestSignature, _ as DEVICE_JSON_SCHEMA_VERSION, a as DeviceCoreOptions, b as BuildSignedHeadersParams, c as EnrollRequestFn, d as EnrollerOptions, f as FsIdentityFileBackend, g as AtomicWriteResult, h as IdentityStoreOptions, i as DeviceCore, l as EnrollResponse, m as IdentityStore, n as fingerprintSource, o as DeviceReenrollRequiresAuthError, p as IdentityFileBackend, r as randomInstallationId, s as DeviceSecretVersionMismatchError, t as deriveInstallationId, u as Enroller, v as IdentityStoreHooks, w as buildSignedHeaders, x as DeviceAuthHeaders, y as PersistedDeviceIdentity } from "./index-DGXYp8J5.js";
3
3
  import { i as SkillKind, r as SkillFile } from "./types-BCV3IedE.js";
4
4
  import { a as SubmitError, c as NodeGitSpawner, d as toFileUrl, f as GitError, i as SubmitResult, l as StubGitSpawner, n as SubmitClientOptions, o as GIT_PROXY_PATH_SUFFIX, p as PullResult, r as SubmitOptions, s as GitClient, t as SubmitClient, u as buildGitProxyBase } from "./index-Dp6FwWKh.js";
5
5
  import { _ as reindexOrder, a as ToolboxFileBackend, b as touchLastUsedAt, c as ToolboxStoreOptions, d as DefaultToolSeed, f as PersistedToolbox, g as mergeWithDefaults, h as ToolboxPatch, i as FsToolboxFileBackend, l as WORKSPACE_TOOLBOX_RELATIVE_PATH, m as TOOLBOX_JSON_SCHEMA_VERSION, n as ToolboxCore, o as ToolboxStore, p as ResolvedToolbox, r as ToolboxCoreOptions, s as ToolboxStoreHooks, t as DefaultToolImmutableError, u as BUILTIN_DEFAULT_TOOLS, v as sortByRecentFirst, y as sortByUserOrder } from "./index-DaW7IYA-.js";
@@ -1682,8 +1682,6 @@ export declare const AGENT_DRAFTS_SUBDIR = "agents";
1682
1682
  export declare const REPOS_CONFIG_FILENAME = "repos.json";
1683
1683
  export declare const WORKSPACES_SUBDIR = "workspaces";
1684
1684
  export declare const WORKSPACE_CONTENT_STATE_FILENAME = "copilot-content-state.json";
1685
- /** rev.20 — r7 BYOM Server Proxy toggle self-state (read by ext + CLI + server). */
1686
- export declare const SERVER_PROXY_GLOBAL_FILENAME = "server-proxy.json";
1687
1685
  /**
1688
1686
  * Repo id regex — used to validate any `repoId` argument before it is joined
1689
1687
  * into a filesystem path. Keeps path traversal attempts out and gives us a
@@ -1770,18 +1768,6 @@ export declare function getSchedulerLogPath(): string;
1770
1768
  export declare function getMigrationFailuresPath(): string;
1771
1769
  /** `~/.serviceme/known-workspaces.json` — workspace list the extension has seen. */
1772
1770
  export declare function getKnownWorkspacesPath(): string;
1773
- /**
1774
- * `~/.serviceme/server-proxy.json` — r7 BYOM Server Proxy toggle
1775
- * self-state. Written by the extension's `ProxyConfigService`, readable
1776
- * by the CLI / Server so they can decide whether to route traffic
1777
- * through the corporate proxy without booting VS Code.
1778
- *
1779
- * Lives under user-level `~/.serviceme/` (not under a workspace) because
1780
- * the toggle is a *user preference* — the same human enabling it on
1781
- * machine A should be able to rely on it on machine B after sync, not
1782
- * have it disappear when they switch repos.
1783
- */
1784
- export declare function getServerProxyGlobalPath(): string;
1785
1771
  /** Layout constants for the Phase 5 client-side state files. The server
1786
1772
  * already has the corresponding routes (`/api/v1/auth/...`,
1787
1773
  * `/api/v1/device/...`, etc.) — the client just needs the on-disk
@@ -1803,72 +1789,6 @@ export declare function getMachineIdPath(): string;
1803
1789
  /** `~/.serviceme/profiles.json` — cached projection of server-side profile rows; refresh on demand. */
1804
1790
  export declare function getProfilesJsonPath(): string;
1805
1791
  //#endregion
1806
- //#region src/paths/serverProxyGlobal.d.ts
1807
- /** On-disk shape for `~/.serviceme/server-proxy.json`. */
1808
- export interface ServerProxyGlobalState {
1809
- /** Whether the user has previously enabled Server Proxy. */
1810
- enabled: boolean;
1811
- /** Last server URL we toggled ON with. Used for re-toggling and UI hint. */
1812
- lastServerUrl: string | undefined;
1813
- /**
1814
- * rev.21 — explicit opt-in to enable Server Proxy even when
1815
- * `http.proxySupport === "override"`. `override` mode forces ALL
1816
- * extensions to route through `http.proxy`; defaulting to `false`
1817
- * keeps the legacy defensive guard against accidental global
1818
- * hijack. Power users (e.g. corp environments that WANT all
1819
- * extensions including GitHub Copilot Chat to route through the
1820
- * corp tunnel) can flip this on via the Webview's "Allow under
1821
- * proxySupport=override" affordance.
1822
- *
1823
- * Note: stored in the global file alongside `enabled` because
1824
- * this is *our* self-flag — it has nothing to do with VS Code's
1825
- * `http.*` schema.
1826
- */
1827
- allowOverride: boolean;
1828
- /** ISO 8601 timestamp of the most recent write. Diagnostic only. */
1829
- updatedAt: string;
1830
- }
1831
- /**
1832
- * Patch semantics (mirrors `vscode.workspace.getConfiguration().update(...)`):
1833
- * - Field omitted / `undefined` → leave the existing value alone.
1834
- * - Field set to `null` → explicitly clear the field.
1835
- *
1836
- * Only `lastServerUrl` distinguishes "leave alone" from "clear"; `enabled`
1837
- * and `allowOverride` are plain `boolean | undefined` because boolean is
1838
- * the natural unit (false = "the user disabled it").
1839
- */
1840
- export interface ServerProxyGlobalPatch {
1841
- enabled?: boolean;
1842
- allowOverride?: boolean;
1843
- lastServerUrl?: string | null;
1844
- }
1845
- /**
1846
- * Reads the global config file. Returns `null` if the file does not
1847
- * exist (first-run case) — does NOT throw. Throws on parse errors or
1848
- * permission issues, so callers can surface those to the user.
1849
- */
1850
- export declare function readServerProxyGlobal(): Promise<ServerProxyGlobalState | null>;
1851
- /**
1852
- * Merges a partial patch into the existing state and writes back
1853
- * atomically. Creates `~/.serviceme/` if missing.
1854
- *
1855
- * Returns the post-write state. Throws on IO/JSON errors.
1856
- */
1857
- export declare function writeServerProxyGlobal(patch: ServerProxyGlobalPatch): Promise<ServerProxyGlobalState>;
1858
- /**
1859
- * Best-effort migration of a legacy `enabled` flag (typically read from
1860
- * VS Code's `settings.json` at `serverProxy.enabled`) into the global
1861
- * config file.
1862
- *
1863
- * Reads via the provided accessor (so tests can stub it), writes the
1864
- * global flag if present, then **clears** the legacy flag via the
1865
- * provided writer — never silently leaves the migration half-done.
1866
- *
1867
- * Returns the migrated state, or `null` if no migration was needed
1868
- * (legacy flag absent OR global config already up to date).
1869
- */
1870
- export declare function migrateLegacyServerProxyEnabled(readLegacy: () => boolean | undefined, clearLegacy: () => Promise<void>): Promise<ServerProxyGlobalState | null>;
1871
- //#endregion
1872
1792
  //#region src/permissions/agent-permissions.d.ts
1873
1793
  export declare const TOOL_RISK_MAP: Record<string, AgentToolRiskLevel>;
1874
1794
  export declare function parseAgentToolPermissions(content: string): AgentToolPermission[];
@@ -1915,12 +1835,23 @@ interface BootstrapPhase5Result {
1915
1835
  export declare function bootstrapPhase5Placeholders(): Promise<BootstrapPhase5Result>;
1916
1836
  //#endregion
1917
1837
  //#region src/project/projectTools.d.ts
1838
+ export interface ScaffoldPruneOptions {
1839
+ /** Optional capability module ids to turn off (--no-module, repeatable). */
1840
+ disabledModules?: string[];
1841
+ }
1918
1842
  export declare class ProjectTools {
1919
1843
  extractTemplate(zipPath: string, workspacePath: string, tempExtractDir: string, input: ServiceMeProjectExtractTemplateInput): Promise<ServiceMeProjectExtractTemplateResult>;
1920
1844
  installDependencies(workspacePath: string, command?: string): Promise<ServiceMeProjectInstallDepsResult>;
1921
1845
  makeScriptsExecutable(workspacePath: string): Promise<ServiceMeProjectMakeScriptsExecutableResult>;
1922
1846
  initializeGit(workspacePath: string): Promise<ServiceMeProjectGitInitResult>;
1923
- runScaffoldPrune(workspacePath: string, preset?: string): Promise<ServiceMeProjectScaffoldPruneResult>;
1847
+ runScaffoldPrune(workspacePath: string, preset?: string, options?: ScaffoldPruneOptions): Promise<ServiceMeProjectScaffoldPruneResult>;
1848
+ /**
1849
+ * `prune.mjs --format json` prints its result object (pretty-printed) as
1850
+ * the only stdout payload, but stay tolerant: if log noise precedes it,
1851
+ * fall back to the last line-initial `{` and try from there. Any parse
1852
+ * failure degrades to an empty list — follow-ups are advisory.
1853
+ */
1854
+ private parseRecommendedNextSteps;
1924
1855
  private ensurePresetManifest;
1925
1856
  private findScripts;
1926
1857
  private pathExists;
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_rolldown_runtime = require("./rolldown-runtime-VH7oDXx4.js");
3
3
  const require_auth = require("./auth-DXam3c4S.js");
4
- const require_userHome = require("./userHome-BquDeFVE.js");
5
- const require_device = require("./device-DuAYH8bk.js");
4
+ const require_userHome = require("./userHome-Baz205B7.js");
5
+ const require_device = require("./device-yWpY_Zds.js");
6
6
  const require_skill_store = require("./skill-store-CJdYyyxu.js");
7
- const require_submit = require("./submit-CltE6YOZ.js");
8
- const require_toolbox = require("./toolbox-CxnOr-FY.js");
7
+ const require_submit = require("./submit-CW9schoc.js");
8
+ const require_toolbox = require("./toolbox-GSWMRdts.js");
9
9
  let _serviceme_devtools_protocol = require("@serviceme/devtools-protocol");
10
10
  let node_fs_promises = require("node:fs/promises");
11
11
  node_fs_promises = require_rolldown_runtime.__toESM(node_fs_promises);
@@ -5072,122 +5072,6 @@ function detectIndent(text) {
5072
5072
  return 2;
5073
5073
  }
5074
5074
  //#endregion
5075
- //#region src/paths/serverProxyGlobal.ts
5076
- /**
5077
- * serverProxyGlobal — `~/.serviceme/server-proxy.json` IO (rev.20).
5078
- *
5079
- * Persists the r7 BYOM Server Proxy toggle's self-state (`enabled` flag
5080
- * + last-known server URL) in a cross-tool global config file under
5081
- * `~/.serviceme/`. Mirrors the convention used by `scheduled-tasks.json`,
5082
- * `migration-failures.json`, etc.
5083
- *
5084
- * Originally lived in `apps/extension/src/services/proxy/globalConfigStore.ts`
5085
- * (rev.19). Promoted to `@serviceme/devtools-core` in rev.20 so the CLI
5086
- * and Server can read the same file without booting VS Code.
5087
- *
5088
- * Why a dedicated `server-proxy.json` rather than a unified config?
5089
- * - One file per concern = atomic writes = no shared-schema lock.
5090
- * `scheduled-tasks.json` already takes this approach.
5091
- *
5092
- * Atomic write protocol (rev.20):
5093
- * 1. Compute patch (read + merge).
5094
- * 2. Open `<target>.tmp-<randomUUID>` for write in the same dir.
5095
- * 3. `writeFile(content)` then `fh.sync()` (fsync) — flush to disk.
5096
- * 4. `fs.rename(tmp, target)` — POSIX atomic on the same filesystem.
5097
- *
5098
- * The `crypto.randomUUID()` suffix + `fh.sync()` address two hardening
5099
- * gaps identified in the rev.19 review:
5100
- * - Concurrency: tmp filename collisions under same-pid concurrent
5101
- * writes become effectively impossible.
5102
- * - Durability: without fsync, a power loss between `writeFile` and
5103
- * `rename` could surface as a stale target file (POSIX rename is
5104
- * atomic, but the data behind it might not have hit the platter).
5105
- */
5106
- /**
5107
- * Reads the global config file. Returns `null` if the file does not
5108
- * exist (first-run case) — does NOT throw. Throws on parse errors or
5109
- * permission issues, so callers can surface those to the user.
5110
- */
5111
- async function readServerProxyGlobal() {
5112
- const filePath = require_userHome.getServerProxyGlobalPath();
5113
- try {
5114
- const raw = await node_fs_promises.readFile(filePath, "utf8");
5115
- const parsed = JSON.parse(raw);
5116
- if (!isServerProxyGlobalState(parsed)) throw new Error(`Invalid ${require_userHome.SERVER_PROXY_GLOBAL_FILENAME}: expected {enabled: boolean, lastServerUrl?: string, updatedAt: string}, got ${JSON.stringify(parsed).slice(0, 80)}`);
5117
- return parsed;
5118
- } catch (err) {
5119
- if (isENOENT(err)) return null;
5120
- throw err;
5121
- }
5122
- }
5123
- /**
5124
- * Merges a partial patch into the existing state and writes back
5125
- * atomically. Creates `~/.serviceme/` if missing.
5126
- *
5127
- * Returns the post-write state. Throws on IO/JSON errors.
5128
- */
5129
- async function writeServerProxyGlobal(patch) {
5130
- const filePath = require_userHome.getServerProxyGlobalPath();
5131
- const dirPath = node_path.dirname(filePath);
5132
- await node_fs_promises.mkdir(dirPath, { recursive: true });
5133
- const current = await readServerProxyGlobal() ?? {
5134
- enabled: false,
5135
- allowOverride: false,
5136
- lastServerUrl: void 0,
5137
- updatedAt: (/* @__PURE__ */ new Date(0)).toISOString()
5138
- };
5139
- const next = {
5140
- enabled: patch.enabled !== void 0 ? patch.enabled : current.enabled,
5141
- allowOverride: patch.allowOverride !== void 0 ? patch.allowOverride : current.allowOverride,
5142
- lastServerUrl: patch.lastServerUrl === void 0 ? current.lastServerUrl : patch.lastServerUrl === null ? void 0 : patch.lastServerUrl,
5143
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
5144
- };
5145
- const tmpPath = `${filePath}.tmp-${(0, node_crypto.randomUUID)()}`;
5146
- const fh = await (0, node_fs_promises.open)(tmpPath, "w");
5147
- try {
5148
- await fh.writeFile(JSON.stringify(next, null, " "), "utf8");
5149
- await fh.sync();
5150
- } finally {
5151
- await fh.close();
5152
- }
5153
- await node_fs_promises.rename(tmpPath, filePath);
5154
- return next;
5155
- }
5156
- /**
5157
- * Best-effort migration of a legacy `enabled` flag (typically read from
5158
- * VS Code's `settings.json` at `serverProxy.enabled`) into the global
5159
- * config file.
5160
- *
5161
- * Reads via the provided accessor (so tests can stub it), writes the
5162
- * global flag if present, then **clears** the legacy flag via the
5163
- * provided writer — never silently leaves the migration half-done.
5164
- *
5165
- * Returns the migrated state, or `null` if no migration was needed
5166
- * (legacy flag absent OR global config already up to date).
5167
- */
5168
- async function migrateLegacyServerProxyEnabled(readLegacy, clearLegacy) {
5169
- if (readLegacy() !== true) return null;
5170
- if ((await readServerProxyGlobal())?.enabled === true) {
5171
- await clearLegacy();
5172
- return null;
5173
- }
5174
- const next = await writeServerProxyGlobal({ enabled: true });
5175
- await clearLegacy();
5176
- return next;
5177
- }
5178
- function isServerProxyGlobalState(v) {
5179
- if (!v || typeof v !== "object") return false;
5180
- const obj = v;
5181
- if (typeof obj.enabled !== "boolean") return false;
5182
- if (typeof obj.allowOverride !== "boolean") return false;
5183
- if (typeof obj.updatedAt !== "string") return false;
5184
- if (obj.lastServerUrl !== void 0 && obj.lastServerUrl !== null && typeof obj.lastServerUrl !== "string") return false;
5185
- return true;
5186
- }
5187
- function isENOENT(err) {
5188
- return typeof err === "object" && err !== null && "code" in err && err.code === "ENOENT";
5189
- }
5190
- //#endregion
5191
5075
  //#region src/phase5/bootstrap.ts
5192
5076
  /**
5193
5077
  * Spec §11.12 — Phase 5 client-side state bootstrap.
@@ -5400,6 +5284,8 @@ const moveFiles = async (sourceDir, destDir, overwrite = false) => {
5400
5284
  };
5401
5285
  //#endregion
5402
5286
  //#region src/project/projectTools.ts
5287
+ /** Master-side prune walks and deletes whole module trees — generous ceiling. */
5288
+ const SCAFFOLD_PRUNE_TIMEOUT_MS = 6e5;
5403
5289
  var ProjectTools = class {
5404
5290
  async extractTemplate(zipPath, workspacePath, tempExtractDir, input) {
5405
5291
  await unzipFile(zipPath, tempExtractDir);
@@ -5466,24 +5352,72 @@ var ProjectTools = class {
5466
5352
  command
5467
5353
  };
5468
5354
  }
5469
- async runScaffoldPrune(workspacePath, preset) {
5355
+ async runScaffoldPrune(workspacePath, preset, options) {
5470
5356
  if (!preset) throw (0, _serviceme_devtools_protocol.createServicemeError)("invalid_params", "Expected scaffold preset.");
5357
+ const disabledModules = options?.disabledModules ?? [];
5358
+ const pruneScript = node_path.join(workspacePath, "scripts", "scaffold", "prune.mjs");
5359
+ const modulesDir = node_path.join(workspacePath, ".ms-scaffold", "modules");
5360
+ if (!await this.pathExists(pruneScript) || !await this.pathExists(modulesDir)) throw (0, _serviceme_devtools_protocol.createServicemeError)("invalid_params", "Scaffold v2 assets not found in workspace (scripts/scaffold/prune.mjs, .ms-scaffold/modules) — an ms-full-stack v2 template is required.");
5471
5361
  await this.ensurePresetManifest(workspacePath, preset);
5472
- const pruneCommand = `pnpm run scaffold:prune -- --preset ${preset} --project-root .`;
5473
- const initMetadataCommand = `pnpm run scaffold:init-metadata -- --preset ${preset} --project-root . --force`;
5474
- const commands = [pruneCommand, initMetadataCommand];
5475
- for (const command of commands) {
5476
- if (command === initMetadataCommand) await this.ensurePresetManifest(workspacePath, preset);
5477
- await runCommand(command, {
5362
+ const stagingDir = await node_fs_promises.mkdtemp(node_path.join(node_os.tmpdir(), "serviceme-scaffold-master-"));
5363
+ try {
5364
+ await node_fs_promises.cp(workspacePath, stagingDir, {
5365
+ recursive: true,
5366
+ filter: (source) => {
5367
+ const base = node_path.basename(source);
5368
+ return base !== "node_modules" && base !== ".git";
5369
+ }
5370
+ });
5371
+ const args = [
5372
+ node_path.join(stagingDir, "scripts", "scaffold", "prune.mjs"),
5373
+ "--preset",
5374
+ preset,
5375
+ "--project-root",
5376
+ workspacePath,
5377
+ ...disabledModules.flatMap((moduleId) => ["--no-module", moduleId]),
5378
+ "--format",
5379
+ "json"
5380
+ ];
5381
+ const result = await runCommand(process.execPath, {
5382
+ args,
5478
5383
  cwd: workspacePath,
5479
- shell: true
5384
+ timeoutMs: SCAFFOLD_PRUNE_TIMEOUT_MS
5385
+ });
5386
+ return {
5387
+ applied: true,
5388
+ preset,
5389
+ projectRoot: workspacePath,
5390
+ disabledModules,
5391
+ recommendedNextSteps: this.parseRecommendedNextSteps(result.stdout),
5392
+ commands: [formatCommand(process.execPath, args)]
5393
+ };
5394
+ } finally {
5395
+ await node_fs_promises.rm(stagingDir, {
5396
+ recursive: true,
5397
+ force: true
5480
5398
  });
5481
5399
  }
5482
- return {
5483
- applied: true,
5484
- preset,
5485
- commands
5486
- };
5400
+ }
5401
+ /**
5402
+ * `prune.mjs --format json` prints its result object (pretty-printed) as
5403
+ * the only stdout payload, but stay tolerant: if log noise precedes it,
5404
+ * fall back to the last line-initial `{` and try from there. Any parse
5405
+ * failure degrades to an empty list — follow-ups are advisory.
5406
+ */
5407
+ parseRecommendedNextSteps(stdout) {
5408
+ const trimmed = stdout.trim();
5409
+ const payload = trimmed.startsWith("{") ? trimmed : (() => {
5410
+ const index = trimmed.lastIndexOf("\n{");
5411
+ return index >= 0 ? trimmed.slice(index + 1) : null;
5412
+ })();
5413
+ if (!payload) return [];
5414
+ try {
5415
+ const parsed = JSON.parse(payload);
5416
+ if (!Array.isArray(parsed.recommendedNextSteps)) return [];
5417
+ return parsed.recommendedNextSteps.filter((step) => typeof step === "string");
5418
+ } catch {
5419
+ return [];
5420
+ }
5487
5421
  }
5488
5422
  async ensurePresetManifest(workspacePath, preset) {
5489
5423
  const presetManifestPath = node_path.join(workspacePath, ".ms-scaffold", "presets", `${preset}.json`);
@@ -5546,6 +5480,11 @@ var ProjectTools = class {
5546
5480
  return entries.includes(projectFilePattern);
5547
5481
  }
5548
5482
  };
5483
+ /** Display form of an argv-style invocation (quote paths containing spaces). */
5484
+ function formatCommand(command, args) {
5485
+ const quote = (value) => /\s/.test(value) ? `"${value}"` : value;
5486
+ return [command, ...args].map(quote).join(" ");
5487
+ }
5549
5488
  function createProjectTools() {
5550
5489
  return new ProjectTools();
5551
5490
  }
@@ -8379,7 +8318,6 @@ exports.SCHEDULED_TASKS_LOG_FILENAME = require_userHome.SCHEDULED_TASKS_LOG_FILE
8379
8318
  exports.SCHEDULER_LOCK_FILENAME = require_userHome.SCHEDULER_LOCK_FILENAME;
8380
8319
  exports.SCHEDULER_LOG_FILENAME = require_userHome.SCHEDULER_LOG_FILENAME;
8381
8320
  exports.SCHEDULER_PID_FILENAME = require_userHome.SCHEDULER_PID_FILENAME;
8382
- exports.SERVER_PROXY_GLOBAL_FILENAME = require_userHome.SERVER_PROXY_GLOBAL_FILENAME;
8383
8321
  exports.SERVICEME_DIR_NAME = require_userHome.SERVICEME_DIR_NAME;
8384
8322
  exports.SERVICEME_HOME_ENV = require_userHome.SERVICEME_HOME_ENV;
8385
8323
  exports.SKILL_DRAFTS_SUBDIR = require_userHome.SKILL_DRAFTS_SUBDIR;
@@ -8466,7 +8404,6 @@ exports.getScheduledTasksLogPath = require_userHome.getScheduledTasksLogPath;
8466
8404
  exports.getSchedulerLockPath = require_userHome.getSchedulerLockPath;
8467
8405
  exports.getSchedulerLogPath = require_userHome.getSchedulerLogPath;
8468
8406
  exports.getSchedulerPidPath = require_userHome.getSchedulerPidPath;
8469
- exports.getServerProxyGlobalPath = require_userHome.getServerProxyGlobalPath;
8470
8407
  exports.getServicemeHome = require_userHome.getServicemeHome;
8471
8408
  exports.getSkillDraftsDir = require_userHome.getSkillDraftsDir;
8472
8409
  exports.getToolboxJsonPath = require_userHome.getToolboxJsonPath;
@@ -8484,7 +8421,6 @@ exports.isUserRepo = isUserRepo;
8484
8421
  exports.listPluginCatalog = listPluginCatalog;
8485
8422
  exports.loadWorkspaceCopilotManifest = loadWorkspaceCopilotManifest;
8486
8423
  exports.mergeWithDefaults = require_toolbox.mergeWithDefaults;
8487
- exports.migrateLegacyServerProxyEnabled = migrateLegacyServerProxyEnabled;
8488
8424
  exports.migrateLegacyUserContent = migrateLegacyUserContent;
8489
8425
  exports.migrateLegacyUserSkillContent = migrateLegacyUserSkillContent;
8490
8426
  exports.migrateToGlobal = migrateToGlobal;
@@ -8497,7 +8433,6 @@ exports.parseHooksJson = parseHooksJson;
8497
8433
  exports.parseMcpJson = parseMcpJson;
8498
8434
  exports.randomInstallationId = require_device.randomInstallationId;
8499
8435
  exports.readDeclaredWorkspaceInstallations = readDeclaredWorkspaceInstallations;
8500
- exports.readServerProxyGlobal = readServerProxyGlobal;
8501
8436
  exports.reindexOrder = require_toolbox.reindexOrder;
8502
8437
  exports.removeWorkspaceContentSelection = removeWorkspaceContentSelection;
8503
8438
  exports.replaceWorkspaceContentSelection = replaceWorkspaceContentSelection;
@@ -8523,7 +8458,6 @@ exports.upsertWorkspaceContentSelection = upsertWorkspaceContentSelection;
8523
8458
  exports.userRepoConfigSchema = userRepoSchema;
8524
8459
  exports.validateReposFile = validateReposFile;
8525
8460
  exports.validateTaskPayload = validateTaskPayload;
8526
- exports.writeServerProxyGlobal = writeServerProxyGlobal;
8527
8461
  exports.writeWorkspaceCopilotManifest = writeWorkspaceCopilotManifest;
8528
8462
 
8529
8463
  //# sourceMappingURL=index.js.map