@serviceme/devtools-cli 0.1.5 → 0.1.6

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 (3) hide show
  1. package/dist/bridgeServer.js +1173 -78
  2. package/dist/cli.js +2028 -223
  3. package/package.json +3 -3
package/dist/cli.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
+ var fs12 = require('fs/promises');
5
+ var path11 = require('path');
4
6
  var child_process = require('child_process');
5
- var fs2 = require('fs/promises');
6
- var path = require('path');
7
- var fs8 = require('fs');
7
+ var fs9 = require('fs');
8
8
  var crypto = require('crypto');
9
9
  var os = require('os');
10
10
  var readline = require('readline');
@@ -27,9 +27,9 @@ function _interopNamespace(e) {
27
27
  return Object.freeze(n);
28
28
  }
29
29
 
30
- var fs2__namespace = /*#__PURE__*/_interopNamespace(fs2);
31
- var path__namespace = /*#__PURE__*/_interopNamespace(path);
32
- var fs8__namespace = /*#__PURE__*/_interopNamespace(fs8);
30
+ var fs12__namespace = /*#__PURE__*/_interopNamespace(fs12);
31
+ var path11__namespace = /*#__PURE__*/_interopNamespace(path11);
32
+ var fs9__namespace = /*#__PURE__*/_interopNamespace(fs9);
33
33
  var os__namespace = /*#__PURE__*/_interopNamespace(os);
34
34
  var readline__namespace = /*#__PURE__*/_interopNamespace(readline);
35
35
 
@@ -72,12 +72,24 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
72
72
  mod
73
73
  ));
74
74
 
75
+ // ../../packages/serviceme-protocol/src/agent.ts
76
+ var init_agent = __esm({
77
+ "../../packages/serviceme-protocol/src/agent.ts"() {
78
+ }
79
+ });
80
+
75
81
  // ../../packages/serviceme-protocol/src/scheduled-tasks.ts
76
82
  var init_scheduled_tasks = __esm({
77
83
  "../../packages/serviceme-protocol/src/scheduled-tasks.ts"() {
78
84
  }
79
85
  });
80
86
 
87
+ // ../../packages/serviceme-protocol/src/skill.ts
88
+ var init_skill = __esm({
89
+ "../../packages/serviceme-protocol/src/skill.ts"() {
90
+ }
91
+ });
92
+
81
93
  // ../../packages/serviceme-protocol/src/bridge.ts
82
94
  function isRecord(value) {
83
95
  return typeof value === "object" && value !== null;
@@ -97,7 +109,9 @@ function isBridgeRequest(value) {
97
109
  var SERVICEME_PROTOCOL_VERSION, BRIDGE_METHODS;
98
110
  var init_bridge = __esm({
99
111
  "../../packages/serviceme-protocol/src/bridge.ts"() {
112
+ init_agent();
100
113
  init_scheduled_tasks();
114
+ init_skill();
101
115
  SERVICEME_PROTOCOL_VERSION = 2;
102
116
  BRIDGE_METHODS = [
103
117
  "system.hello",
@@ -105,7 +119,14 @@ var init_bridge = __esm({
105
119
  "system.shutdown",
106
120
  "task.execute",
107
121
  "task.cancel",
108
- "task.list-running"
122
+ "task.list-running",
123
+ "skill.marketplace-state",
124
+ "skill.mutate",
125
+ "skill.reconcile",
126
+ "skill.publishable",
127
+ "agent.marketplace-state",
128
+ "agent.mutate",
129
+ "agent.permissions"
109
130
  ];
110
131
  }
111
132
  });
@@ -325,6 +346,7 @@ var init_project = __esm({
325
346
  // ../../packages/serviceme-protocol/src/index.ts
326
347
  var init_src = __esm({
327
348
  "../../packages/serviceme-protocol/src/index.ts"() {
349
+ init_agent();
328
350
  init_bridge();
329
351
  init_cli();
330
352
  init_copilot();
@@ -335,6 +357,328 @@ var init_src = __esm({
335
357
  init_metadata();
336
358
  init_project();
337
359
  init_scheduled_tasks();
360
+ init_skill();
361
+ }
362
+ });
363
+
364
+ // ../../packages/serviceme-core/src/agents/AgentCatalogClient.ts
365
+ var AgentCatalogClient;
366
+ var init_AgentCatalogClient = __esm({
367
+ "../../packages/serviceme-core/src/agents/AgentCatalogClient.ts"() {
368
+ AgentCatalogClient = class {
369
+ constructor(options2 = {}) {
370
+ this.fetchImpl = options2.fetchImpl ?? fetch;
371
+ this.baseUrl = options2.baseUrl;
372
+ }
373
+ async getCatalog() {
374
+ if (!this.baseUrl) {
375
+ return {
376
+ agents: [],
377
+ fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
378
+ };
379
+ }
380
+ const response = await this.fetchImpl(
381
+ `${this.baseUrl}/api/v1/marketplace/agents`
382
+ );
383
+ if (!response.ok) {
384
+ throw new Error(`Failed to fetch agents catalog: ${response.status}`);
385
+ }
386
+ const data = await response.json();
387
+ return {
388
+ agents: data.agents ?? [],
389
+ fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
390
+ };
391
+ }
392
+ };
393
+ }
394
+ });
395
+
396
+ // ../../packages/serviceme-core/src/permissions/agent-permissions.ts
397
+ function parseAgentToolPermissions(content) {
398
+ const fmMatch = content.match(FRONTMATTER_REGEX);
399
+ if (!fmMatch?.[1]) return [];
400
+ const frontmatter = fmMatch[1];
401
+ const inlineMatch = frontmatter.match(TOOLS_INLINE_REGEX);
402
+ if (inlineMatch?.[1] != null) {
403
+ const raw = inlineMatch[1];
404
+ return raw.split(",").map((t) => t.trim()).filter(Boolean).map((tool) => ({
405
+ tool,
406
+ riskLevel: TOOL_RISK_MAP[tool] ?? "medium"
407
+ }));
408
+ }
409
+ const blockMatch = frontmatter.match(TOOLS_LINE_REGEX);
410
+ if (!blockMatch?.[0]) return [];
411
+ const toolsStartIndex = frontmatter.indexOf(blockMatch[0]) + blockMatch[0].length;
412
+ const remaining = frontmatter.slice(toolsStartIndex);
413
+ const lines = remaining.split(/\r?\n/);
414
+ const tools = [];
415
+ for (const line2 of lines) {
416
+ const itemMatch = line2.match(LIST_ITEM_REGEX);
417
+ if (itemMatch?.[1]) {
418
+ const tool = itemMatch[1].trim();
419
+ tools.push({ tool, riskLevel: TOOL_RISK_MAP[tool] ?? "medium" });
420
+ } else if (line2.trim() !== "" && !line2.startsWith(" ") && !line2.startsWith(" ")) {
421
+ break;
422
+ }
423
+ }
424
+ return tools;
425
+ }
426
+ var TOOL_RISK_MAP, FRONTMATTER_REGEX, TOOLS_LINE_REGEX, TOOLS_INLINE_REGEX, LIST_ITEM_REGEX;
427
+ var init_agent_permissions = __esm({
428
+ "../../packages/serviceme-core/src/permissions/agent-permissions.ts"() {
429
+ TOOL_RISK_MAP = {
430
+ shell: "high",
431
+ terminal: "high",
432
+ run_in_terminal: "high",
433
+ execution_subagent: "high",
434
+ filesystem: "medium",
435
+ fetch: "medium",
436
+ fetch_webpage: "medium",
437
+ create_file: "medium",
438
+ replace_string_in_file: "medium",
439
+ multi_replace_string_in_file: "medium",
440
+ read_file: "low",
441
+ search: "low",
442
+ grep_search: "low",
443
+ file_search: "low",
444
+ semantic_search: "low",
445
+ list_dir: "low"
446
+ };
447
+ FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---/;
448
+ TOOLS_LINE_REGEX = /^tools:\s*$/m;
449
+ TOOLS_INLINE_REGEX = /^tools:\s*\[([^\]]*)\]/m;
450
+ LIST_ITEM_REGEX = /^\s*-\s+(.+)$/;
451
+ }
452
+ });
453
+
454
+ // ../../packages/serviceme-core/src/permissions/index.ts
455
+ var init_permissions = __esm({
456
+ "../../packages/serviceme-core/src/permissions/index.ts"() {
457
+ init_agent_permissions();
458
+ }
459
+ });
460
+
461
+ // ../../packages/serviceme-core/src/agents/AgentReconciler.ts
462
+ var AgentReconciler;
463
+ var init_AgentReconciler = __esm({
464
+ "../../packages/serviceme-core/src/agents/AgentReconciler.ts"() {
465
+ init_permissions();
466
+ AgentReconciler = class {
467
+ constructor(deps) {
468
+ this.deps = deps;
469
+ }
470
+ async mutate(request) {
471
+ if (request.targetScope !== "workspace" && request.targetScope !== "user") {
472
+ throw new Error(`Invalid target scope: ${String(request.targetScope)}`);
473
+ }
474
+ if (request.action === "uninstall" || request.action === "move" || request.action === "removeExternal") {
475
+ return {
476
+ status: "success",
477
+ changed: true,
478
+ message: `Agent ${request.action} completed.`
479
+ };
480
+ }
481
+ if (request.action !== "install") {
482
+ return {
483
+ status: "blocked",
484
+ changed: false,
485
+ message: `Agent action is not supported by bridge reconciler: ${request.action}`
486
+ };
487
+ }
488
+ const catalog = await this.deps.catalogClient.getCatalog();
489
+ const remoteAgent = catalog.agents.find(
490
+ (agent) => this.deps.agentStore.normalizeRemoteAgentId(agent.id) === request.agentId
491
+ );
492
+ if (!remoteAgent) {
493
+ return {
494
+ status: "blocked",
495
+ changed: false,
496
+ message: "Agent not found in catalog."
497
+ };
498
+ }
499
+ if (!request.confirmed && this.hasHighRiskTool(remoteAgent.tools)) {
500
+ return {
501
+ status: "requires_confirmation",
502
+ changed: false,
503
+ message: "This agent uses high-risk tools that require confirmation.",
504
+ tools: remoteAgent.tools
505
+ };
506
+ }
507
+ return {
508
+ status: "success",
509
+ changed: true,
510
+ message: "Agent installed."
511
+ };
512
+ }
513
+ getPermissionSummary(agentId, agentName, content) {
514
+ const tools = parseAgentToolPermissions(content);
515
+ return {
516
+ agentId,
517
+ agentName,
518
+ tools,
519
+ highRiskCount: tools.filter((tool) => tool.riskLevel === "high").length,
520
+ mediumRiskCount: tools.filter((tool) => tool.riskLevel === "medium").length,
521
+ lowRiskCount: tools.filter((tool) => tool.riskLevel === "low").length
522
+ };
523
+ }
524
+ hasHighRiskTool(tools) {
525
+ return tools.some((tool) => TOOL_RISK_MAP[tool] === "high");
526
+ }
527
+ };
528
+ }
529
+ });
530
+ function assertSafeLocalAgentId(agentId) {
531
+ if (typeof agentId !== "string" || agentId.length === 0 || agentId === "." || agentId === ".." || agentId.includes("/") || agentId.includes("\\") || !SAFE_LOCAL_ID_PATTERN.test(agentId)) {
532
+ throw new Error(`Invalid agent id: ${agentId}`);
533
+ }
534
+ return agentId;
535
+ }
536
+ var WORKSPACE_AGENTS_ROOT_RELATIVE, WORKSPACE_AGENTS_STATE_RELATIVE, SAFE_LOCAL_ID_PATTERN, AgentStore;
537
+ var init_AgentStore = __esm({
538
+ "../../packages/serviceme-core/src/agents/AgentStore.ts"() {
539
+ WORKSPACE_AGENTS_ROOT_RELATIVE = ".github/agents";
540
+ WORKSPACE_AGENTS_STATE_RELATIVE = ".github/.ms-devtools-agents.yml";
541
+ SAFE_LOCAL_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
542
+ AgentStore = class {
543
+ constructor(options2) {
544
+ this.workspacePath = options2.workspacePath;
545
+ this.userAgentsRoot = options2.userAgentsRoot;
546
+ this.fileSystem = options2.fileSystem ?? fs12__namespace;
547
+ this.schemaVersion = options2.schemaVersion ?? 1;
548
+ }
549
+ normalizeRemoteAgentId(remoteId) {
550
+ if (remoteId.startsWith("official/")) {
551
+ return assertSafeLocalAgentId(remoteId.slice("official/".length));
552
+ }
553
+ if (remoteId.startsWith("community/")) {
554
+ const lastSlash = remoteId.lastIndexOf("/");
555
+ return assertSafeLocalAgentId(remoteId.slice(lastSlash + 1));
556
+ }
557
+ return assertSafeLocalAgentId(remoteId);
558
+ }
559
+ getWorkspaceAgentsRootPath() {
560
+ return WORKSPACE_AGENTS_ROOT_RELATIVE;
561
+ }
562
+ getWorkspaceStateFilePath() {
563
+ return WORKSPACE_AGENTS_STATE_RELATIVE;
564
+ }
565
+ getUserAgentsRootPath() {
566
+ return this.userAgentsRoot;
567
+ }
568
+ async listWorkspaceAgentIds() {
569
+ return this.listAgentIds(
570
+ path11__namespace.join(this.workspacePath, WORKSPACE_AGENTS_ROOT_RELATIVE)
571
+ );
572
+ }
573
+ async listUserAgentIds() {
574
+ return this.listAgentIds(this.userAgentsRoot);
575
+ }
576
+ async readState() {
577
+ try {
578
+ const raw = await this.fileSystem.readFile(
579
+ path11__namespace.join(this.workspacePath, WORKSPACE_AGENTS_STATE_RELATIVE),
580
+ "utf-8"
581
+ );
582
+ const parsed = JSON.parse(raw);
583
+ if (typeof parsed.schemaVersion !== "number" || !Array.isArray(parsed.installedAgents)) {
584
+ return null;
585
+ }
586
+ return parsed;
587
+ } catch {
588
+ return null;
589
+ }
590
+ }
591
+ async writeState(state) {
592
+ const statePath = path11__namespace.join(
593
+ this.workspacePath,
594
+ WORKSPACE_AGENTS_STATE_RELATIVE
595
+ );
596
+ await this.fileSystem.mkdir(path11__namespace.dirname(statePath), { recursive: true });
597
+ await this.fileSystem.writeFile(
598
+ statePath,
599
+ JSON.stringify(state, null, 2),
600
+ "utf-8"
601
+ );
602
+ }
603
+ async addInstalledAgent(entry) {
604
+ const state = await this.readState() ?? {
605
+ schemaVersion: this.schemaVersion,
606
+ installedAgents: []
607
+ };
608
+ state.installedAgents = state.installedAgents.filter(
609
+ (agent) => agent.id !== entry.id
610
+ );
611
+ state.installedAgents.push(entry);
612
+ await this.writeState(state);
613
+ }
614
+ async removeInstalledAgent(agentId) {
615
+ const state = await this.readState();
616
+ if (!state) {
617
+ return;
618
+ }
619
+ state.installedAgents = state.installedAgents.filter(
620
+ (agent) => agent.id !== agentId
621
+ );
622
+ await this.writeState(state);
623
+ }
624
+ async writeAgentFiles(agentId, scope, files) {
625
+ const root2 = scope === "workspace" ? path11__namespace.join(this.workspacePath, WORKSPACE_AGENTS_ROOT_RELATIVE) : this.userAgentsRoot;
626
+ const firstFile = files[0];
627
+ const isSingleFlatFile = files.length === 1 && firstFile !== void 0 && firstFile.path === `${agentId}.agent.md` && !firstFile.path.includes("/");
628
+ const targetDir = isSingleFlatFile ? root2 : path11__namespace.join(root2, agentId);
629
+ await this.fileSystem.mkdir(targetDir, { recursive: true });
630
+ for (const file of files) {
631
+ const filePath = path11__namespace.join(targetDir, file.path);
632
+ await this.fileSystem.mkdir(path11__namespace.dirname(filePath), { recursive: true });
633
+ await this.fileSystem.writeFile(filePath, file.content, "utf-8");
634
+ if (file.executable) {
635
+ try {
636
+ await this.fileSystem.chmod(filePath, 493);
637
+ } catch {
638
+ }
639
+ }
640
+ }
641
+ }
642
+ async listAgentIds(dir) {
643
+ try {
644
+ const entries = await this.fileSystem.readdir(dir, {
645
+ withFileTypes: true
646
+ });
647
+ const ids = [];
648
+ for (const entry of entries) {
649
+ if (entry.name.startsWith(".")) {
650
+ continue;
651
+ }
652
+ if (entry.isDirectory()) {
653
+ ids.push(entry.name);
654
+ continue;
655
+ }
656
+ if (entry.isFile() && entry.name.endsWith(".agent.md")) {
657
+ ids.push(entry.name.replace(/\.agent\.md$/, ""));
658
+ }
659
+ }
660
+ return ids.sort();
661
+ } catch {
662
+ return [];
663
+ }
664
+ }
665
+ };
666
+ }
667
+ });
668
+
669
+ // ../../packages/serviceme-core/src/agents/types.ts
670
+ var init_types = __esm({
671
+ "../../packages/serviceme-core/src/agents/types.ts"() {
672
+ }
673
+ });
674
+
675
+ // ../../packages/serviceme-core/src/agents/index.ts
676
+ var init_agents = __esm({
677
+ "../../packages/serviceme-core/src/agents/index.ts"() {
678
+ init_AgentCatalogClient();
679
+ init_AgentReconciler();
680
+ init_AgentStore();
681
+ init_types();
338
682
  }
339
683
  });
340
684
  function terminateCommandProcess(child) {
@@ -595,7 +939,13 @@ var init_environmentInspector = __esm({
595
939
  TOOL_CHECK_TIMEOUT_MS = {
596
940
  nuget: 12e3,
597
941
  nvm: 8e3,
598
- dotnet: 8e3
942
+ dotnet: 8e3,
943
+ // nvm4w/npm shims and globally-installed .cmd tools (pnpm, nrm) are slow to
944
+ // resolve on cold PATHs. Give them extra headroom so the version probe
945
+ // doesn't fall through to the generic 5s default.
946
+ npm: 15e3,
947
+ pnpm: 15e3,
948
+ nrm: 15e3
599
949
  };
600
950
  ERROR_CODE_NOT_FOUND = 127;
601
951
  ERROR_CODE_TIMEOUT = "ETIMEDOUT";
@@ -642,8 +992,29 @@ var init_environmentInspector = __esm({
642
992
  return void 0;
643
993
  }
644
994
  }
995
+ /**
996
+ * On Windows, prefer the `.cmd` shim for npm/pnpm/nrm. nvm4w registers
997
+ * BOTH an extensionless entry (pointing to node.exe) and a `<tool>.cmd`
998
+ * wrapper; `where` returns them in that order, and the extensionless one
999
+ * would just print node's own version.
1000
+ */
1001
+ async getToolShimPath(toolName) {
1002
+ try {
1003
+ const result = await runCommand("where", {
1004
+ args: [toolName],
1005
+ timeoutMs: this.getToolTimeout(toolName)
1006
+ });
1007
+ const candidates = result.stdout.split(/\r?\n/).map((line2) => line2.trim()).filter((line2) => line2.length > 0);
1008
+ const cmdShim = candidates.find(
1009
+ (line2) => line2.toLowerCase().endsWith(".cmd")
1010
+ );
1011
+ return cmdShim ?? candidates[0];
1012
+ } catch {
1013
+ return void 0;
1014
+ }
1015
+ }
645
1016
  async getToolVersion(toolName) {
646
- const invocation = this.getVersionInvocation(toolName);
1017
+ const invocation = await this.getVersionInvocation(toolName);
647
1018
  const result = await runCommand(invocation.command, {
648
1019
  args: invocation.args,
649
1020
  timeoutMs: this.getToolTimeout(toolName)
@@ -718,12 +1089,19 @@ var init_environmentInspector = __esm({
718
1089
  return this.handleToolCheckError(error);
719
1090
  }
720
1091
  }
721
- getVersionInvocation(toolName) {
1092
+ async getVersionInvocation(toolName) {
722
1093
  const isWindows = process.platform === "win32";
723
1094
  if (isWindows && ["npm", "pnpm", "nrm"].includes(toolName)) {
1095
+ const shim = await this.getToolShimPath(toolName);
1096
+ if (shim) {
1097
+ return {
1098
+ command: "cmd.exe",
1099
+ args: ["/c", shim, "--version"]
1100
+ };
1101
+ }
724
1102
  return {
725
1103
  command: "cmd.exe",
726
- args: ["/d", "/s", "/c", `${toolName} --version`]
1104
+ args: ["/c", toolName, "--version"]
727
1105
  };
728
1106
  }
729
1107
  const commands = {
@@ -802,7 +1180,7 @@ var init_imageTools = __esm({
802
1180
  if (!await this.pathExists(filePath)) {
803
1181
  return { valid: false };
804
1182
  }
805
- if (!SUPPORTED_FORMATS.includes(path__namespace.extname(filePath).toLowerCase())) {
1183
+ if (!SUPPORTED_FORMATS.includes(path11__namespace.extname(filePath).toLowerCase())) {
806
1184
  return { valid: false };
807
1185
  }
808
1186
  await this.getInfo(filePath, sharpModulePath);
@@ -814,7 +1192,7 @@ var init_imageTools = __esm({
814
1192
  async getInfo(imagePath, sharpModulePath) {
815
1193
  const sharp = this.loadSharp(sharpModulePath);
816
1194
  const metadata = await sharp(imagePath).metadata();
817
- const stats = await fs2__namespace.stat(imagePath);
1195
+ const stats = await fs12__namespace.stat(imagePath);
818
1196
  return {
819
1197
  width: metadata.width ?? 0,
820
1198
  height: metadata.height ?? 0,
@@ -831,7 +1209,7 @@ var init_imageTools = __esm({
831
1209
  `Invalid image file: ${imagePath}`
832
1210
  );
833
1211
  }
834
- const originalStats = await fs2__namespace.stat(imagePath);
1212
+ const originalStats = await fs12__namespace.stat(imagePath);
835
1213
  const originalSize = originalStats.size;
836
1214
  const outputPath = this.getOutputPath(imagePath, options2);
837
1215
  const compressedBuffer = await this.compressWithSharp(imagePath, options2);
@@ -846,7 +1224,7 @@ var init_imageTools = __esm({
846
1224
  outputPath: imagePath
847
1225
  };
848
1226
  }
849
- await fs2__namespace.writeFile(outputPath, compressedBuffer);
1227
+ await fs12__namespace.writeFile(outputPath, compressedBuffer);
850
1228
  return {
851
1229
  originalSize,
852
1230
  compressedSize,
@@ -857,7 +1235,7 @@ var init_imageTools = __esm({
857
1235
  async compressWithSharp(imagePath, options2) {
858
1236
  const sharp = this.loadSharp(options2.sharpModulePath);
859
1237
  let pipeline = sharp(imagePath);
860
- switch (options2.format ?? path__namespace.extname(imagePath).toLowerCase().slice(1)) {
1238
+ switch (options2.format ?? path11__namespace.extname(imagePath).toLowerCase().slice(1)) {
861
1239
  case "jpg":
862
1240
  case "jpeg":
863
1241
  pipeline = pipeline.jpeg({ quality: options2.quality });
@@ -883,14 +1261,14 @@ var init_imageTools = __esm({
883
1261
  if (options2.replaceOriginImage) {
884
1262
  return inputPath;
885
1263
  }
886
- const dir = path__namespace.dirname(inputPath);
887
- const ext = path__namespace.extname(inputPath);
888
- const name = path__namespace.basename(inputPath, ext);
889
- return path__namespace.join(dir, `${name}_compressed${ext}`);
1264
+ const dir = path11__namespace.dirname(inputPath);
1265
+ const ext = path11__namespace.extname(inputPath);
1266
+ const name = path11__namespace.basename(inputPath, ext);
1267
+ return path11__namespace.join(dir, `${name}_compressed${ext}`);
890
1268
  }
891
1269
  async pathExists(targetPath) {
892
1270
  try {
893
- await fs2__namespace.access(targetPath);
1271
+ await fs12__namespace.access(targetPath);
894
1272
  return true;
895
1273
  } catch {
896
1274
  return false;
@@ -1397,8 +1775,8 @@ var require_esprima = __commonJS({
1397
1775
  return result;
1398
1776
  };
1399
1777
  JSXParser2.prototype.lexJSX = function() {
1400
- var cp = this.scanner.source.charCodeAt(this.scanner.index);
1401
- if (cp === 60 || cp === 62 || cp === 47 || cp === 58 || cp === 61 || cp === 123 || cp === 125) {
1778
+ var cp5 = this.scanner.source.charCodeAt(this.scanner.index);
1779
+ if (cp5 === 60 || cp5 === 62 || cp5 === 47 || cp5 === 58 || cp5 === 61 || cp5 === 123 || cp5 === 125) {
1402
1780
  var value = this.scanner.source[this.scanner.index++];
1403
1781
  return {
1404
1782
  type: 7,
@@ -1409,7 +1787,7 @@ var require_esprima = __commonJS({
1409
1787
  end: this.scanner.index
1410
1788
  };
1411
1789
  }
1412
- if (cp === 34 || cp === 39) {
1790
+ if (cp5 === 34 || cp5 === 39) {
1413
1791
  var start = this.scanner.index;
1414
1792
  var quote = this.scanner.source[this.scanner.index++];
1415
1793
  var str = "";
@@ -1432,7 +1810,7 @@ var require_esprima = __commonJS({
1432
1810
  end: this.scanner.index
1433
1811
  };
1434
1812
  }
1435
- if (cp === 46) {
1813
+ if (cp5 === 46) {
1436
1814
  var n1 = this.scanner.source.charCodeAt(this.scanner.index + 1);
1437
1815
  var n2 = this.scanner.source.charCodeAt(this.scanner.index + 2);
1438
1816
  var value = n1 === 46 && n2 === 46 ? "..." : ".";
@@ -1447,7 +1825,7 @@ var require_esprima = __commonJS({
1447
1825
  end: this.scanner.index
1448
1826
  };
1449
1827
  }
1450
- if (cp === 96) {
1828
+ if (cp5 === 96) {
1451
1829
  return {
1452
1830
  type: 10,
1453
1831
  value: "",
@@ -1457,7 +1835,7 @@ var require_esprima = __commonJS({
1457
1835
  end: this.scanner.index
1458
1836
  };
1459
1837
  }
1460
- if (character_1.Character.isIdentifierStart(cp) && cp !== 92) {
1838
+ if (character_1.Character.isIdentifierStart(cp5) && cp5 !== 92) {
1461
1839
  var start = this.scanner.index;
1462
1840
  ++this.scanner.index;
1463
1841
  while (!this.scanner.eof()) {
@@ -1786,33 +2164,33 @@ var require_esprima = __commonJS({
1786
2164
  };
1787
2165
  exports2.Character = {
1788
2166
  /* tslint:disable:no-bitwise */
1789
- fromCodePoint: function(cp) {
1790
- return cp < 65536 ? String.fromCharCode(cp) : String.fromCharCode(55296 + (cp - 65536 >> 10)) + String.fromCharCode(56320 + (cp - 65536 & 1023));
2167
+ fromCodePoint: function(cp5) {
2168
+ return cp5 < 65536 ? String.fromCharCode(cp5) : String.fromCharCode(55296 + (cp5 - 65536 >> 10)) + String.fromCharCode(56320 + (cp5 - 65536 & 1023));
1791
2169
  },
1792
2170
  // https://tc39.github.io/ecma262/#sec-white-space
1793
- isWhiteSpace: function(cp) {
1794
- return cp === 32 || cp === 9 || cp === 11 || cp === 12 || cp === 160 || cp >= 5760 && [5760, 8192, 8193, 8194, 8195, 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8239, 8287, 12288, 65279].indexOf(cp) >= 0;
2171
+ isWhiteSpace: function(cp5) {
2172
+ return cp5 === 32 || cp5 === 9 || cp5 === 11 || cp5 === 12 || cp5 === 160 || cp5 >= 5760 && [5760, 8192, 8193, 8194, 8195, 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8239, 8287, 12288, 65279].indexOf(cp5) >= 0;
1795
2173
  },
1796
2174
  // https://tc39.github.io/ecma262/#sec-line-terminators
1797
- isLineTerminator: function(cp) {
1798
- return cp === 10 || cp === 13 || cp === 8232 || cp === 8233;
2175
+ isLineTerminator: function(cp5) {
2176
+ return cp5 === 10 || cp5 === 13 || cp5 === 8232 || cp5 === 8233;
1799
2177
  },
1800
2178
  // https://tc39.github.io/ecma262/#sec-names-and-keywords
1801
- isIdentifierStart: function(cp) {
1802
- return cp === 36 || cp === 95 || cp >= 65 && cp <= 90 || cp >= 97 && cp <= 122 || cp === 92 || cp >= 128 && Regex.NonAsciiIdentifierStart.test(exports2.Character.fromCodePoint(cp));
2179
+ isIdentifierStart: function(cp5) {
2180
+ return cp5 === 36 || cp5 === 95 || cp5 >= 65 && cp5 <= 90 || cp5 >= 97 && cp5 <= 122 || cp5 === 92 || cp5 >= 128 && Regex.NonAsciiIdentifierStart.test(exports2.Character.fromCodePoint(cp5));
1803
2181
  },
1804
- isIdentifierPart: function(cp) {
1805
- return cp === 36 || cp === 95 || cp >= 65 && cp <= 90 || cp >= 97 && cp <= 122 || cp >= 48 && cp <= 57 || cp === 92 || cp >= 128 && Regex.NonAsciiIdentifierPart.test(exports2.Character.fromCodePoint(cp));
2182
+ isIdentifierPart: function(cp5) {
2183
+ return cp5 === 36 || cp5 === 95 || cp5 >= 65 && cp5 <= 90 || cp5 >= 97 && cp5 <= 122 || cp5 >= 48 && cp5 <= 57 || cp5 === 92 || cp5 >= 128 && Regex.NonAsciiIdentifierPart.test(exports2.Character.fromCodePoint(cp5));
1806
2184
  },
1807
2185
  // https://tc39.github.io/ecma262/#sec-literals-numeric-literals
1808
- isDecimalDigit: function(cp) {
1809
- return cp >= 48 && cp <= 57;
2186
+ isDecimalDigit: function(cp5) {
2187
+ return cp5 >= 48 && cp5 <= 57;
1810
2188
  },
1811
- isHexDigit: function(cp) {
1812
- return cp >= 48 && cp <= 57 || cp >= 65 && cp <= 70 || cp >= 97 && cp <= 102;
2189
+ isHexDigit: function(cp5) {
2190
+ return cp5 >= 48 && cp5 <= 57 || cp5 >= 65 && cp5 <= 70 || cp5 >= 97 && cp5 <= 102;
1813
2191
  },
1814
- isOctalDigit: function(cp) {
1815
- return cp >= 48 && cp <= 55;
2192
+ isOctalDigit: function(cp5) {
2193
+ return cp5 >= 48 && cp5 <= 55;
1816
2194
  }
1817
2195
  };
1818
2196
  },
@@ -5862,15 +6240,15 @@ var require_esprima = __commonJS({
5862
6240
  }
5863
6241
  };
5864
6242
  Scanner2.prototype.codePointAt = function(i) {
5865
- var cp = this.source.charCodeAt(i);
5866
- if (cp >= 55296 && cp <= 56319) {
6243
+ var cp5 = this.source.charCodeAt(i);
6244
+ if (cp5 >= 55296 && cp5 <= 56319) {
5867
6245
  var second = this.source.charCodeAt(i + 1);
5868
6246
  if (second >= 56320 && second <= 57343) {
5869
- var first = cp;
5870
- cp = (first - 55296) * 1024 + second - 56320 + 65536;
6247
+ var first = cp5;
6248
+ cp5 = (first - 55296) * 1024 + second - 56320 + 65536;
5871
6249
  }
5872
6250
  }
5873
- return cp;
6251
+ return cp5;
5874
6252
  };
5875
6253
  Scanner2.prototype.scanHexEscape = function(prefix) {
5876
6254
  var len = prefix === "u" ? 4 : 2;
@@ -5922,11 +6300,11 @@ var require_esprima = __commonJS({
5922
6300
  return this.source.slice(start, this.index);
5923
6301
  };
5924
6302
  Scanner2.prototype.getComplexIdentifier = function() {
5925
- var cp = this.codePointAt(this.index);
5926
- var id = character_1.Character.fromCodePoint(cp);
6303
+ var cp5 = this.codePointAt(this.index);
6304
+ var id = character_1.Character.fromCodePoint(cp5);
5927
6305
  this.index += id.length;
5928
6306
  var ch;
5929
- if (cp === 92) {
6307
+ if (cp5 === 92) {
5930
6308
  if (this.source.charCodeAt(this.index) !== 117) {
5931
6309
  this.throwUnexpectedToken();
5932
6310
  }
@@ -5943,14 +6321,14 @@ var require_esprima = __commonJS({
5943
6321
  id = ch;
5944
6322
  }
5945
6323
  while (!this.eof()) {
5946
- cp = this.codePointAt(this.index);
5947
- if (!character_1.Character.isIdentifierPart(cp)) {
6324
+ cp5 = this.codePointAt(this.index);
6325
+ if (!character_1.Character.isIdentifierPart(cp5)) {
5948
6326
  break;
5949
6327
  }
5950
- ch = character_1.Character.fromCodePoint(cp);
6328
+ ch = character_1.Character.fromCodePoint(cp5);
5951
6329
  id += ch;
5952
6330
  this.index += ch.length;
5953
- if (cp === 92) {
6331
+ if (cp5 === 92) {
5954
6332
  id = id.substr(0, id.length - 1);
5955
6333
  if (this.source.charCodeAt(this.index) !== 117) {
5956
6334
  this.throwUnexpectedToken();
@@ -6576,29 +6954,29 @@ var require_esprima = __commonJS({
6576
6954
  end: this.index
6577
6955
  };
6578
6956
  }
6579
- var cp = this.source.charCodeAt(this.index);
6580
- if (character_1.Character.isIdentifierStart(cp)) {
6957
+ var cp5 = this.source.charCodeAt(this.index);
6958
+ if (character_1.Character.isIdentifierStart(cp5)) {
6581
6959
  return this.scanIdentifier();
6582
6960
  }
6583
- if (cp === 40 || cp === 41 || cp === 59) {
6961
+ if (cp5 === 40 || cp5 === 41 || cp5 === 59) {
6584
6962
  return this.scanPunctuator();
6585
6963
  }
6586
- if (cp === 39 || cp === 34) {
6964
+ if (cp5 === 39 || cp5 === 34) {
6587
6965
  return this.scanStringLiteral();
6588
6966
  }
6589
- if (cp === 46) {
6967
+ if (cp5 === 46) {
6590
6968
  if (character_1.Character.isDecimalDigit(this.source.charCodeAt(this.index + 1))) {
6591
6969
  return this.scanNumericLiteral();
6592
6970
  }
6593
6971
  return this.scanPunctuator();
6594
6972
  }
6595
- if (character_1.Character.isDecimalDigit(cp)) {
6973
+ if (character_1.Character.isDecimalDigit(cp5)) {
6596
6974
  return this.scanNumericLiteral();
6597
6975
  }
6598
- if (cp === 96 || cp === 125 && this.curlyStack[this.curlyStack.length - 1] === "${") {
6976
+ if (cp5 === 96 || cp5 === 125 && this.curlyStack[this.curlyStack.length - 1] === "${") {
6599
6977
  return this.scanTemplate();
6600
6978
  }
6601
- if (cp >= 55296 && cp < 57343) {
6979
+ if (cp5 >= 55296 && cp5 < 57343) {
6602
6980
  if (character_1.Character.isIdentifierStart(this.codePointAt(this.index))) {
6603
6981
  return this.scanIdentifier();
6604
6982
  }
@@ -8776,10 +9154,10 @@ var require_stringify = __commonJS({
8776
9154
  replacer = null;
8777
9155
  indent = EMPTY;
8778
9156
  };
8779
- var join9 = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + LF + gap : two ? two.trimRight() + LF + gap : EMPTY;
9157
+ var join15 = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + LF + gap : two ? two.trimRight() + LF + gap : EMPTY;
8780
9158
  var join_content = (inside, value, gap) => {
8781
9159
  const comment = process_comments(value, PREFIX_BEFORE, gap + indent, true);
8782
- return join9(comment, inside, gap);
9160
+ return join15(comment, inside, gap);
8783
9161
  };
8784
9162
  var array_stringify = (value, gap) => {
8785
9163
  const deeper_gap = gap + indent;
@@ -8790,7 +9168,7 @@ var require_stringify = __commonJS({
8790
9168
  if (i !== 0) {
8791
9169
  inside += COMMA;
8792
9170
  }
8793
- const before = join9(
9171
+ const before = join15(
8794
9172
  after_comma,
8795
9173
  process_comments(value, BEFORE(i), deeper_gap),
8796
9174
  deeper_gap
@@ -8800,7 +9178,7 @@ var require_stringify = __commonJS({
8800
9178
  inside += process_comments(value, AFTER_VALUE(i), deeper_gap);
8801
9179
  after_comma = process_comments(value, AFTER(i), deeper_gap);
8802
9180
  }
8803
- inside += join9(
9181
+ inside += join15(
8804
9182
  after_comma,
8805
9183
  process_comments(value, PREFIX_AFTER, deeper_gap),
8806
9184
  deeper_gap
@@ -8825,7 +9203,7 @@ var require_stringify = __commonJS({
8825
9203
  inside += COMMA;
8826
9204
  }
8827
9205
  first = false;
8828
- const before = join9(
9206
+ const before = join15(
8829
9207
  after_comma,
8830
9208
  process_comments(value, BEFORE(key2), deeper_gap),
8831
9209
  deeper_gap
@@ -8835,7 +9213,7 @@ var require_stringify = __commonJS({
8835
9213
  after_comma = process_comments(value, AFTER(key2), deeper_gap);
8836
9214
  };
8837
9215
  keys.forEach(iteratee);
8838
- inside += join9(
9216
+ inside += join15(
8839
9217
  after_comma,
8840
9218
  process_comments(value, PREFIX_AFTER, deeper_gap),
8841
9219
  deeper_gap
@@ -10213,7 +10591,7 @@ var require_pend = __commonJS({
10213
10591
  // ../../node_modules/.pnpm/yauzl@3.2.0/node_modules/yauzl/fd-slicer.js
10214
10592
  var require_fd_slicer = __commonJS({
10215
10593
  "../../node_modules/.pnpm/yauzl@3.2.0/node_modules/yauzl/fd-slicer.js"(exports$1) {
10216
- var fs13 = __require("fs");
10594
+ var fs19 = __require("fs");
10217
10595
  var util2 = __require("util");
10218
10596
  var stream = __require("stream");
10219
10597
  var Readable = stream.Readable;
@@ -10238,7 +10616,7 @@ var require_fd_slicer = __commonJS({
10238
10616
  FdSlicer.prototype.read = function(buffer2, offset, length, position, callback) {
10239
10617
  var self = this;
10240
10618
  self.pend.go(function(cb) {
10241
- fs13.read(self.fd, buffer2, offset, length, position, function(err, bytesRead, buffer3) {
10619
+ fs19.read(self.fd, buffer2, offset, length, position, function(err, bytesRead, buffer3) {
10242
10620
  cb();
10243
10621
  callback(err, bytesRead, buffer3);
10244
10622
  });
@@ -10247,7 +10625,7 @@ var require_fd_slicer = __commonJS({
10247
10625
  FdSlicer.prototype.write = function(buffer2, offset, length, position, callback) {
10248
10626
  var self = this;
10249
10627
  self.pend.go(function(cb) {
10250
- fs13.write(self.fd, buffer2, offset, length, position, function(err, written, buffer3) {
10628
+ fs19.write(self.fd, buffer2, offset, length, position, function(err, written, buffer3) {
10251
10629
  cb();
10252
10630
  callback(err, written, buffer3);
10253
10631
  });
@@ -10268,7 +10646,7 @@ var require_fd_slicer = __commonJS({
10268
10646
  if (self.refCount > 0) return;
10269
10647
  if (self.refCount < 0) throw new Error("invalid unref");
10270
10648
  if (self.autoClose) {
10271
- fs13.close(self.fd, onCloseDone);
10649
+ fs19.close(self.fd, onCloseDone);
10272
10650
  }
10273
10651
  function onCloseDone(err) {
10274
10652
  if (err) {
@@ -10305,7 +10683,7 @@ var require_fd_slicer = __commonJS({
10305
10683
  self.context.pend.go(function(cb) {
10306
10684
  if (self.destroyed) return cb();
10307
10685
  var buffer2 = Buffer.allocUnsafe(toRead);
10308
- fs13.read(self.context.fd, buffer2, 0, toRead, self.pos, function(err, bytesRead) {
10686
+ fs19.read(self.context.fd, buffer2, 0, toRead, self.pos, function(err, bytesRead) {
10309
10687
  if (err) {
10310
10688
  self.destroy(err);
10311
10689
  } else if (bytesRead === 0) {
@@ -10352,7 +10730,7 @@ var require_fd_slicer = __commonJS({
10352
10730
  }
10353
10731
  self.context.pend.go(function(cb) {
10354
10732
  if (self.destroyed) return cb();
10355
- fs13.write(self.context.fd, buffer2, 0, buffer2.length, self.pos, function(err2, bytes) {
10733
+ fs19.write(self.context.fd, buffer2, 0, buffer2.length, self.pos, function(err2, bytes) {
10356
10734
  if (err2) {
10357
10735
  self.destroy();
10358
10736
  cb();
@@ -10790,7 +11168,7 @@ var require_buffer_crc32 = __commonJS({
10790
11168
  // ../../node_modules/.pnpm/yauzl@3.2.0/node_modules/yauzl/index.js
10791
11169
  var require_yauzl = __commonJS({
10792
11170
  "../../node_modules/.pnpm/yauzl@3.2.0/node_modules/yauzl/index.js"(exports$1) {
10793
- var fs13 = __require("fs");
11171
+ var fs19 = __require("fs");
10794
11172
  var zlib = __require("zlib");
10795
11173
  var fd_slicer = require_fd_slicer();
10796
11174
  var crc32 = require_buffer_crc32();
@@ -10811,7 +11189,7 @@ var require_yauzl = __commonJS({
10811
11189
  exports$1.Entry = Entry;
10812
11190
  exports$1.LocalFileHeader = LocalFileHeader;
10813
11191
  exports$1.RandomAccessReader = RandomAccessReader;
10814
- function open2(path9, options2, callback) {
11192
+ function open2(path15, options2, callback) {
10815
11193
  if (typeof options2 === "function") {
10816
11194
  callback = options2;
10817
11195
  options2 = null;
@@ -10823,10 +11201,10 @@ var require_yauzl = __commonJS({
10823
11201
  if (options2.validateEntrySizes == null) options2.validateEntrySizes = true;
10824
11202
  if (options2.strictFileNames == null) options2.strictFileNames = false;
10825
11203
  if (callback == null) callback = defaultCallback;
10826
- fs13.open(path9, "r", function(err, fd) {
11204
+ fs19.open(path15, "r", function(err, fd) {
10827
11205
  if (err) return callback(err);
10828
11206
  fromFd(fd, options2, function(err2, zipfile) {
10829
- if (err2) fs13.close(fd, defaultCallback);
11207
+ if (err2) fs19.close(fd, defaultCallback);
10830
11208
  callback(err2, zipfile);
10831
11209
  });
10832
11210
  });
@@ -10843,7 +11221,7 @@ var require_yauzl = __commonJS({
10843
11221
  if (options2.validateEntrySizes == null) options2.validateEntrySizes = true;
10844
11222
  if (options2.strictFileNames == null) options2.strictFileNames = false;
10845
11223
  if (callback == null) callback = defaultCallback;
10846
- fs13.fstat(fd, function(err, stats) {
11224
+ fs19.fstat(fd, function(err, stats) {
10847
11225
  if (err) return callback(err);
10848
11226
  var reader = fd_slicer.createFromFd(fd, { autoClose: true });
10849
11227
  fromRandomAccessReader(reader, stats.size, options2, callback);
@@ -11541,12 +11919,12 @@ var init_fileUtils = __esm({
11541
11919
  zipfile.readEntry();
11542
11920
  zipfile.on("entry", (entry) => {
11543
11921
  if (/\/$/.test(entry.fileName)) {
11544
- void fs2.mkdir(path.join(dest, entry.fileName), { recursive: true }).then(() => {
11922
+ void fs12.mkdir(path11.join(dest, entry.fileName), { recursive: true }).then(() => {
11545
11923
  zipfile.readEntry();
11546
11924
  }).catch(reject);
11547
11925
  } else {
11548
- const outputPath = path.join(dest, entry.fileName);
11549
- void fs2.mkdir(path.dirname(outputPath), { recursive: true }).then(() => {
11926
+ const outputPath = path11.join(dest, entry.fileName);
11927
+ void fs12.mkdir(path11.dirname(outputPath), { recursive: true }).then(() => {
11550
11928
  zipfile.openReadStream(
11551
11929
  entry,
11552
11930
  (streamError, readStream) => {
@@ -11555,7 +11933,7 @@ var init_fileUtils = __esm({
11555
11933
  return reject(
11556
11934
  new Error("Failed to open zip entry stream.")
11557
11935
  );
11558
- const writeStream = fs8.createWriteStream(outputPath);
11936
+ const writeStream = fs9.createWriteStream(outputPath);
11559
11937
  readStream.on("error", reject);
11560
11938
  writeStream.on("error", reject);
11561
11939
  writeStream.on("close", () => {
@@ -11579,58 +11957,58 @@ var init_fileUtils = __esm({
11579
11957
  };
11580
11958
  tryLstat = async (targetPath) => {
11581
11959
  try {
11582
- return await fs2.lstat(targetPath);
11960
+ return await fs12.lstat(targetPath);
11583
11961
  } catch {
11584
11962
  return null;
11585
11963
  }
11586
11964
  };
11587
11965
  mergeEntry = async (sourcePath, destPath, overwrite) => {
11588
- const sourceStat = await fs2.lstat(sourcePath);
11966
+ const sourceStat = await fs12.lstat(sourcePath);
11589
11967
  const destStat = await tryLstat(destPath);
11590
11968
  if (sourceStat.isDirectory()) {
11591
11969
  if (destStat && !destStat.isDirectory()) {
11592
11970
  if (!overwrite) {
11593
- await fs2.rm(sourcePath, { recursive: true, force: true });
11971
+ await fs12.rm(sourcePath, { recursive: true, force: true });
11594
11972
  return;
11595
11973
  }
11596
- await fs2.rm(destPath, { recursive: true, force: true });
11974
+ await fs12.rm(destPath, { recursive: true, force: true });
11597
11975
  }
11598
- await fs2.mkdir(destPath, { recursive: true });
11599
- const children = await fs2.readdir(sourcePath);
11976
+ await fs12.mkdir(destPath, { recursive: true });
11977
+ const children = await fs12.readdir(sourcePath);
11600
11978
  for (const child of children) {
11601
11979
  await mergeEntry(
11602
- path.join(sourcePath, child),
11603
- path.join(destPath, child),
11980
+ path11.join(sourcePath, child),
11981
+ path11.join(destPath, child),
11604
11982
  overwrite
11605
11983
  );
11606
11984
  }
11607
- await fs2.rm(sourcePath, { recursive: true, force: true });
11985
+ await fs12.rm(sourcePath, { recursive: true, force: true });
11608
11986
  return;
11609
11987
  }
11610
11988
  if (destStat) {
11611
11989
  if (!overwrite) {
11612
- await fs2.rm(sourcePath, { recursive: true, force: true });
11990
+ await fs12.rm(sourcePath, { recursive: true, force: true });
11613
11991
  return;
11614
11992
  }
11615
- await fs2.rm(destPath, { recursive: true, force: true });
11993
+ await fs12.rm(destPath, { recursive: true, force: true });
11616
11994
  }
11617
11995
  try {
11618
- await fs2.rename(sourcePath, destPath);
11996
+ await fs12.rename(sourcePath, destPath);
11619
11997
  } catch {
11620
- await fs2.copyFile(sourcePath, destPath);
11621
- await fs2.rm(sourcePath, { recursive: true, force: true });
11998
+ await fs12.copyFile(sourcePath, destPath);
11999
+ await fs12.rm(sourcePath, { recursive: true, force: true });
11622
12000
  }
11623
12001
  };
11624
12002
  moveFiles = async (sourceDir, destDir, overwrite = false) => {
11625
- await fs2.mkdir(destDir, { recursive: true });
11626
- const files = await fs2.readdir(sourceDir);
12003
+ await fs12.mkdir(destDir, { recursive: true });
12004
+ const files = await fs12.readdir(sourceDir);
11627
12005
  for (const file of files) {
11628
- const sourceFile = path.join(sourceDir, file);
11629
- const destFile = path.join(destDir, file);
12006
+ const sourceFile = path11.join(sourceDir, file);
12007
+ const destFile = path11.join(destDir, file);
11630
12008
  if (!overwrite) {
11631
12009
  try {
11632
- await fs2.access(destFile, fs8.constants.F_OK);
11633
- await fs2.rm(sourceFile, { recursive: true, force: true });
12010
+ await fs12.access(destFile, fs9.constants.F_OK);
12011
+ await fs12.rm(sourceFile, { recursive: true, force: true });
11634
12012
  continue;
11635
12013
  } catch {
11636
12014
  }
@@ -11652,10 +12030,10 @@ var init_projectTools = __esm({
11652
12030
  ProjectTools = class {
11653
12031
  async extractTemplate(zipPath, workspacePath, tempExtractDir, input) {
11654
12032
  await unzipFile(zipPath, tempExtractDir);
11655
- let sourceDir = path__namespace.join(tempExtractDir, input.extractedDirName);
12033
+ let sourceDir = path11__namespace.join(tempExtractDir, input.extractedDirName);
11656
12034
  let actualDirName = input.extractedDirName;
11657
12035
  if (!await this.pathExists(sourceDir)) {
11658
- const entries = await fs2__namespace.readdir(tempExtractDir, { withFileTypes: true });
12036
+ const entries = await fs12__namespace.readdir(tempExtractDir, { withFileTypes: true });
11659
12037
  const directories = entries.filter(
11660
12038
  (entry) => entry.isDirectory() && !entry.name.startsWith(".")
11661
12039
  );
@@ -11667,7 +12045,7 @@ var init_projectTools = __esm({
11667
12045
  );
11668
12046
  if (selectedDirectory) {
11669
12047
  actualDirName = selectedDirectory;
11670
- sourceDir = path__namespace.join(tempExtractDir, actualDirName);
12048
+ sourceDir = path11__namespace.join(tempExtractDir, actualDirName);
11671
12049
  } else if (directories.length === 0) {
11672
12050
  throw new Error(
11673
12051
  `No directory found after extraction. Expected directory: ${input.extractedDirName}`
@@ -11725,7 +12103,7 @@ var init_projectTools = __esm({
11725
12103
  } else {
11726
12104
  for (const scriptPath of scripts) {
11727
12105
  try {
11728
- await fs2__namespace.chmod(scriptPath, 493);
12106
+ await fs12__namespace.chmod(scriptPath, 493);
11729
12107
  updatedCount += 1;
11730
12108
  } catch {
11731
12109
  }
@@ -11773,12 +12151,12 @@ var init_projectTools = __esm({
11773
12151
  const results = [];
11774
12152
  let entries;
11775
12153
  try {
11776
- entries = await fs2__namespace.readdir(dir, { withFileTypes: true });
12154
+ entries = await fs12__namespace.readdir(dir, { withFileTypes: true });
11777
12155
  } catch {
11778
12156
  return results;
11779
12157
  }
11780
12158
  for (const entry of entries) {
11781
- const fullPath = path__namespace.join(dir, entry.name);
12159
+ const fullPath = path11__namespace.join(dir, entry.name);
11782
12160
  if (entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith(".")) {
11783
12161
  results.push(...await this.findScripts(fullPath, extensions));
11784
12162
  } else if (entry.isFile() && extensions.some((ext) => entry.name.endsWith(ext))) {
@@ -11789,7 +12167,7 @@ var init_projectTools = __esm({
11789
12167
  }
11790
12168
  async pathExists(targetPath) {
11791
12169
  try {
11792
- await fs2__namespace.access(targetPath);
12170
+ await fs12__namespace.access(targetPath);
11793
12171
  return true;
11794
12172
  } catch {
11795
12173
  return false;
@@ -11808,7 +12186,7 @@ var init_projectTools = __esm({
11808
12186
  const matches = [];
11809
12187
  for (const directoryName of directoryNames) {
11810
12188
  if (await this.directoryMatchesProjectPattern(
11811
- path__namespace.join(tempExtractDir, directoryName),
12189
+ path11__namespace.join(tempExtractDir, directoryName),
11812
12190
  projectFilePattern
11813
12191
  )) {
11814
12192
  matches.push(directoryName);
@@ -11820,7 +12198,7 @@ var init_projectTools = __esm({
11820
12198
  return null;
11821
12199
  }
11822
12200
  async directoryMatchesProjectPattern(directoryPath, projectFilePattern) {
11823
- const entries = await fs2__namespace.readdir(directoryPath);
12201
+ const entries = await fs12__namespace.readdir(directoryPath);
11824
12202
  if (projectFilePattern.includes("*")) {
11825
12203
  const regex = new RegExp(`^${projectFilePattern.replace("*", ".*")}$`);
11826
12204
  return entries.some((entry) => regex.test(entry));
@@ -11838,10 +12216,10 @@ var init_DaemonLogger = __esm({
11838
12216
  MAX_LOG_SIZE = 1024 * 1024;
11839
12217
  DaemonLogger = class {
11840
12218
  constructor(workspacePath) {
11841
- this.logPath = path__namespace.join(workspacePath, CONFIG_DIR, LOG_FILE);
11842
- const dir = path__namespace.dirname(this.logPath);
11843
- if (!fs8__namespace.existsSync(dir)) {
11844
- fs8__namespace.mkdirSync(dir, { recursive: true });
12219
+ this.logPath = path11__namespace.join(workspacePath, CONFIG_DIR, LOG_FILE);
12220
+ const dir = path11__namespace.dirname(this.logPath);
12221
+ if (!fs9__namespace.existsSync(dir)) {
12222
+ fs9__namespace.mkdirSync(dir, { recursive: true });
11845
12223
  }
11846
12224
  }
11847
12225
  getLogPath() {
@@ -11852,16 +12230,16 @@ var init_DaemonLogger = __esm({
11852
12230
  const line2 = `[${ts}] [${level.toUpperCase()}] ${message}
11853
12231
  `;
11854
12232
  this.rotateIfNeeded();
11855
- fs8__namespace.appendFileSync(this.logPath, line2, "utf-8");
12233
+ fs9__namespace.appendFileSync(this.logPath, line2, "utf-8");
11856
12234
  }
11857
12235
  rotateIfNeeded() {
11858
12236
  try {
11859
- const stats = fs8__namespace.statSync(this.logPath);
12237
+ const stats = fs9__namespace.statSync(this.logPath);
11860
12238
  if (stats.size > MAX_LOG_SIZE) {
11861
- const content = fs8__namespace.readFileSync(this.logPath, "utf-8");
12239
+ const content = fs9__namespace.readFileSync(this.logPath, "utf-8");
11862
12240
  const halfIdx = content.indexOf("\n", Math.floor(content.length / 2));
11863
12241
  if (halfIdx > 0) {
11864
- fs8__namespace.writeFileSync(this.logPath, content.slice(halfIdx + 1), "utf-8");
12242
+ fs9__namespace.writeFileSync(this.logPath, content.slice(halfIdx + 1), "utf-8");
11865
12243
  }
11866
12244
  }
11867
12245
  } catch {
@@ -11877,27 +12255,27 @@ var init_PidManager = __esm({
11877
12255
  PID_FILE = "scheduler.pid";
11878
12256
  PidManager = class {
11879
12257
  constructor(workspacePath) {
11880
- this.pidPath = path__namespace.join(workspacePath, CONFIG_DIR2, PID_FILE);
12258
+ this.pidPath = path11__namespace.join(workspacePath, CONFIG_DIR2, PID_FILE);
11881
12259
  }
11882
12260
  getPidPath() {
11883
12261
  return this.pidPath;
11884
12262
  }
11885
12263
  writePid(pid) {
11886
- const dir = path__namespace.dirname(this.pidPath);
11887
- if (!fs8__namespace.existsSync(dir)) {
11888
- fs8__namespace.mkdirSync(dir, { recursive: true });
12264
+ const dir = path11__namespace.dirname(this.pidPath);
12265
+ if (!fs9__namespace.existsSync(dir)) {
12266
+ fs9__namespace.mkdirSync(dir, { recursive: true });
11889
12267
  }
11890
- fs8__namespace.writeFileSync(this.pidPath, String(pid), "utf-8");
12268
+ fs9__namespace.writeFileSync(this.pidPath, String(pid), "utf-8");
11891
12269
  }
11892
12270
  readPid() {
11893
- if (!fs8__namespace.existsSync(this.pidPath)) return null;
11894
- const raw = fs8__namespace.readFileSync(this.pidPath, "utf-8").trim();
12271
+ if (!fs9__namespace.existsSync(this.pidPath)) return null;
12272
+ const raw = fs9__namespace.readFileSync(this.pidPath, "utf-8").trim();
11895
12273
  const pid = Number.parseInt(raw, 10);
11896
12274
  return Number.isNaN(pid) ? null : pid;
11897
12275
  }
11898
12276
  removePid() {
11899
- if (fs8__namespace.existsSync(this.pidPath)) {
11900
- fs8__namespace.unlinkSync(this.pidPath);
12277
+ if (fs9__namespace.existsSync(this.pidPath)) {
12278
+ fs9__namespace.unlinkSync(this.pidPath);
11901
12279
  }
11902
12280
  }
11903
12281
  isProcessRunning(pid) {
@@ -11952,7 +12330,7 @@ function redactArgs(args) {
11952
12330
  function writeDiagnostic(message) {
11953
12331
  const logPath = process.env.SERVICEME_SCHEDULER_LOG_PATH;
11954
12332
  if (logPath) {
11955
- fs8__namespace.appendFileSync(logPath, message);
12333
+ fs9__namespace.appendFileSync(logPath, message);
11956
12334
  return;
11957
12335
  }
11958
12336
  process.stderr.write(message);
@@ -12177,7 +12555,7 @@ ${body}`.trim()
12177
12555
  function resolveShellExecution(script, options2 = {}) {
12178
12556
  const platform = options2.platform ?? process.platform;
12179
12557
  const env = options2.env ?? process.env;
12180
- const fileExists = options2.fileExists ?? fs8__namespace.existsSync;
12558
+ const fileExists = options2.fileExists ?? fs9__namespace.existsSync;
12181
12559
  if (platform === "win32") {
12182
12560
  const posixShell = usesPosixShellSyntax(script) ? findWindowsPosixShell(env, fileExists) : null;
12183
12561
  if (posixShell) {
@@ -12222,10 +12600,10 @@ function findWindowsPosixShell(env, fileExists) {
12222
12600
  if (fileExists(candidate)) return candidate;
12223
12601
  }
12224
12602
  const pathValue = env.Path ?? env.PATH ?? "";
12225
- for (const dir of pathValue.split(path__namespace.win32.delimiter)) {
12603
+ for (const dir of pathValue.split(path11__namespace.win32.delimiter)) {
12226
12604
  if (!dir) continue;
12227
12605
  for (const executable of POSIX_SHELL_CANDIDATES) {
12228
- const candidate = path__namespace.win32.join(dir, executable);
12606
+ const candidate = path11__namespace.win32.join(dir, executable);
12229
12607
  if (fileExists(candidate) && !isWindowsWslLauncher(candidate)) {
12230
12608
  return candidate;
12231
12609
  }
@@ -12234,13 +12612,13 @@ function findWindowsPosixShell(env, fileExists) {
12234
12612
  return null;
12235
12613
  }
12236
12614
  function isWindowsWslLauncher(candidate) {
12237
- const normalized = path__namespace.win32.normalize(candidate).toLowerCase();
12615
+ const normalized = path11__namespace.win32.normalize(candidate).toLowerCase();
12238
12616
  return normalized.endsWith("\\windows\\system32\\bash.exe") || normalized.endsWith("\\windows\\syswow64\\bash.exe");
12239
12617
  }
12240
12618
  function writeDiagnostic2(message) {
12241
12619
  const logPath = process.env.SERVICEME_SCHEDULER_LOG_PATH;
12242
12620
  if (logPath) {
12243
- fs8__namespace.appendFileSync(logPath, message);
12621
+ fs9__namespace.appendFileSync(logPath, message);
12244
12622
  return;
12245
12623
  }
12246
12624
  process.stderr.write(message);
@@ -12379,7 +12757,7 @@ var init_ShellExecutor = __esm({
12379
12757
  function isStreamingTaskExecutor(executor) {
12380
12758
  return "executeStreaming" in executor && typeof executor.executeStreaming === "function";
12381
12759
  }
12382
- var init_types = __esm({
12760
+ var init_types2 = __esm({
12383
12761
  "../../packages/serviceme-core/src/scheduled-tasks/executors/types.ts"() {
12384
12762
  }
12385
12763
  });
@@ -12398,7 +12776,7 @@ var init_executors = __esm({
12398
12776
  init_GithubCopilotCliExecutor();
12399
12777
  init_HttpRequestExecutor();
12400
12778
  init_ShellExecutor();
12401
- init_types();
12779
+ init_types2();
12402
12780
  executors = {
12403
12781
  shell: new ShellExecutor(),
12404
12782
  http_request: new HttpRequestExecutor(),
@@ -12445,27 +12823,27 @@ var init_TaskConfigManager = __esm({
12445
12823
  CONFIG_FILE = "scheduled-tasks.json";
12446
12824
  TaskConfigManager = class {
12447
12825
  constructor(workspacePath) {
12448
- this.configPath = path__namespace.join(workspacePath, CONFIG_DIR3, CONFIG_FILE);
12826
+ this.configPath = path11__namespace.join(workspacePath, CONFIG_DIR3, CONFIG_FILE);
12449
12827
  }
12450
12828
  getConfigPath() {
12451
12829
  return this.configPath;
12452
12830
  }
12453
12831
  readConfig() {
12454
- if (!fs8__namespace.existsSync(this.configPath)) {
12832
+ if (!fs9__namespace.existsSync(this.configPath)) {
12455
12833
  return emptyConfig();
12456
12834
  }
12457
- const raw = fs8__namespace.readFileSync(this.configPath, "utf-8");
12835
+ const raw = fs9__namespace.readFileSync(this.configPath, "utf-8");
12458
12836
  const parsed = JSON.parse(raw);
12459
12837
  return parsed;
12460
12838
  }
12461
12839
  writeConfig(config) {
12462
- const dir = path__namespace.dirname(this.configPath);
12463
- if (!fs8__namespace.existsSync(dir)) {
12464
- fs8__namespace.mkdirSync(dir, { recursive: true });
12840
+ const dir = path11__namespace.dirname(this.configPath);
12841
+ if (!fs9__namespace.existsSync(dir)) {
12842
+ fs9__namespace.mkdirSync(dir, { recursive: true });
12465
12843
  }
12466
12844
  const tmp = `${this.configPath}.tmp`;
12467
- fs8__namespace.writeFileSync(tmp, JSON.stringify(config, null, " "), "utf-8");
12468
- fs8__namespace.renameSync(tmp, this.configPath);
12845
+ fs9__namespace.writeFileSync(tmp, JSON.stringify(config, null, " "), "utf-8");
12846
+ fs9__namespace.renameSync(tmp, this.configPath);
12469
12847
  }
12470
12848
  listTasks() {
12471
12849
  return this.readConfig().tasks;
@@ -12576,7 +12954,7 @@ function resolveTaskExecutionPayload(taskType, payload, workspacePath) {
12576
12954
  var TaskExecutionEngine;
12577
12955
  var init_TaskExecutionEngine = __esm({
12578
12956
  "../../packages/serviceme-core/src/scheduled-tasks/TaskExecutionEngine.ts"() {
12579
- init_types();
12957
+ init_types2();
12580
12958
  init_TaskConfigManager();
12581
12959
  TaskExecutionEngine = class {
12582
12960
  constructor(getExecutor2) {
@@ -12769,17 +13147,17 @@ var init_TaskLogManager = __esm({
12769
13147
  MAX_LOGS = 200;
12770
13148
  TaskLogManager = class {
12771
13149
  constructor(workspacePath) {
12772
- this.logPath = path__namespace.join(workspacePath, CONFIG_DIR4, LOG_FILE2);
13150
+ this.logPath = path11__namespace.join(workspacePath, CONFIG_DIR4, LOG_FILE2);
12773
13151
  }
12774
13152
  getLogPath() {
12775
13153
  return this.logPath;
12776
13154
  }
12777
13155
  readLogFile() {
12778
- if (!fs8__namespace.existsSync(this.logPath)) {
13156
+ if (!fs9__namespace.existsSync(this.logPath)) {
12779
13157
  return emptyLogFile();
12780
13158
  }
12781
13159
  try {
12782
- const raw = fs8__namespace.readFileSync(this.logPath, "utf-8");
13160
+ const raw = fs9__namespace.readFileSync(this.logPath, "utf-8");
12783
13161
  const parsed = JSON.parse(raw);
12784
13162
  const file = validateAndRepairLogFile(parsed);
12785
13163
  if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.logs) || parsed.logs.length !== file.logs.length) {
@@ -12795,21 +13173,21 @@ var init_TaskLogManager = __esm({
12795
13173
  }
12796
13174
  backupCorruptedFile() {
12797
13175
  try {
12798
- if (fs8__namespace.existsSync(this.logPath)) {
13176
+ if (fs9__namespace.existsSync(this.logPath)) {
12799
13177
  const backupPath = `${this.logPath}.corrupted.${Date.now()}`;
12800
- fs8__namespace.copyFileSync(this.logPath, backupPath);
13178
+ fs9__namespace.copyFileSync(this.logPath, backupPath);
12801
13179
  }
12802
13180
  } catch {
12803
13181
  }
12804
13182
  }
12805
13183
  writeLogFile(file) {
12806
- const dir = path__namespace.dirname(this.logPath);
12807
- if (!fs8__namespace.existsSync(dir)) {
12808
- fs8__namespace.mkdirSync(dir, { recursive: true });
13184
+ const dir = path11__namespace.dirname(this.logPath);
13185
+ if (!fs9__namespace.existsSync(dir)) {
13186
+ fs9__namespace.mkdirSync(dir, { recursive: true });
12809
13187
  }
12810
13188
  const tmp = `${this.logPath}.tmp`;
12811
- fs8__namespace.writeFileSync(tmp, JSON.stringify(file, null, " "), "utf-8");
12812
- fs8__namespace.renameSync(tmp, this.logPath);
13189
+ fs9__namespace.writeFileSync(tmp, JSON.stringify(file, null, " "), "utf-8");
13190
+ fs9__namespace.renameSync(tmp, this.logPath);
12813
13191
  }
12814
13192
  appendLog(input) {
12815
13193
  const file = this.readLogFile();
@@ -12968,8 +13346,8 @@ var init_SchedulerDaemon = __esm({
12968
13346
  const configPath = this.configManager.getConfigPath();
12969
13347
  const dir = configPath.substring(0, configPath.lastIndexOf("/"));
12970
13348
  try {
12971
- if (fs8__namespace.existsSync(dir)) {
12972
- this.watcher = fs8__namespace.watch(dir, (_eventType, filename) => {
13349
+ if (fs9__namespace.existsSync(dir)) {
13350
+ this.watcher = fs9__namespace.watch(dir, (_eventType, filename) => {
12973
13351
  if (filename === "scheduled-tasks.json") {
12974
13352
  this.logger.log("info", "Config file changed, reconciling...");
12975
13353
  }
@@ -13105,9 +13483,202 @@ var init_scheduled_tasks2 = __esm({
13105
13483
  }
13106
13484
  });
13107
13485
 
13486
+ // ../../packages/serviceme-core/src/skills/SkillCatalogClient.ts
13487
+ var SkillCatalogClient;
13488
+ var init_SkillCatalogClient = __esm({
13489
+ "../../packages/serviceme-core/src/skills/SkillCatalogClient.ts"() {
13490
+ SkillCatalogClient = class {
13491
+ constructor(options2 = {}) {
13492
+ this.fetchImpl = options2.fetchImpl ?? fetch;
13493
+ this.baseUrl = options2.baseUrl;
13494
+ }
13495
+ async getCatalog() {
13496
+ if (!this.baseUrl) {
13497
+ return {
13498
+ skills: [],
13499
+ fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
13500
+ };
13501
+ }
13502
+ const response = await this.fetchImpl(
13503
+ `${this.baseUrl}/api/v1/marketplace/skills`
13504
+ );
13505
+ if (!response.ok) {
13506
+ throw new Error(`Failed to fetch skills catalog: ${response.status}`);
13507
+ }
13508
+ const data = await response.json();
13509
+ return {
13510
+ skills: data.skills ?? [],
13511
+ fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
13512
+ };
13513
+ }
13514
+ };
13515
+ }
13516
+ });
13517
+
13518
+ // ../../packages/serviceme-core/src/skills/SkillReconciler.ts
13519
+ var SkillReconciler;
13520
+ var init_SkillReconciler = __esm({
13521
+ "../../packages/serviceme-core/src/skills/SkillReconciler.ts"() {
13522
+ SkillReconciler = class {
13523
+ constructor(deps) {
13524
+ this.deps = deps;
13525
+ }
13526
+ async mutate(request) {
13527
+ if (request.targetScope !== "workspace" && request.targetScope !== "user") {
13528
+ throw new Error(`Invalid target scope: ${String(request.targetScope)}`);
13529
+ }
13530
+ if (request.action === "uninstall" || request.action === "move" || request.action === "removeExternal") {
13531
+ return {
13532
+ status: "success",
13533
+ changed: true,
13534
+ message: `Skill ${request.action} completed.`
13535
+ };
13536
+ }
13537
+ if (request.action !== "install") {
13538
+ return {
13539
+ status: "blocked",
13540
+ changed: false,
13541
+ message: `Skill action is not supported by bridge reconciler: ${request.action}`
13542
+ };
13543
+ }
13544
+ const catalog = await this.deps.catalogClient.getCatalog();
13545
+ const remoteSkill = catalog.skills.find(
13546
+ (skill) => this.deps.skillStore.normalizeRemoteSkillId(skill.id) === request.skillId
13547
+ );
13548
+ if (!remoteSkill) {
13549
+ return {
13550
+ status: "blocked",
13551
+ changed: false,
13552
+ message: "Skill not found in catalog."
13553
+ };
13554
+ }
13555
+ if (!request.confirmed && (remoteSkill.hasScripts || remoteSkill.hasHooks)) {
13556
+ return {
13557
+ status: "requires_confirmation",
13558
+ changed: false,
13559
+ hasScripts: Boolean(remoteSkill.hasScripts),
13560
+ hasHooks: Boolean(remoteSkill.hasHooks),
13561
+ message: "This skill contains executable scripts that require confirmation."
13562
+ };
13563
+ }
13564
+ return {
13565
+ status: "success",
13566
+ changed: true,
13567
+ message: "Skill installed."
13568
+ };
13569
+ }
13570
+ };
13571
+ }
13572
+ });
13573
+ function assertSafeLocalSkillId(skillId) {
13574
+ if (typeof skillId !== "string" || skillId.length === 0 || skillId === "." || skillId === ".." || skillId.includes("/") || skillId.includes("\\") || !SAFE_LOCAL_ID_PATTERN2.test(skillId)) {
13575
+ throw new Error(`Invalid skill id: ${skillId}`);
13576
+ }
13577
+ return skillId;
13578
+ }
13579
+ var USER_SKILL_MARKER_FILE, WORKSPACE_SKILLS_ROOT_RELATIVE, WORKSPACE_SKILLS_MARKER_RELATIVE, SAFE_LOCAL_ID_PATTERN2, SkillStore;
13580
+ var init_SkillStore = __esm({
13581
+ "../../packages/serviceme-core/src/skills/SkillStore.ts"() {
13582
+ USER_SKILL_MARKER_FILE = ".ms-devtools-skill.json";
13583
+ WORKSPACE_SKILLS_ROOT_RELATIVE = ".github/skills";
13584
+ WORKSPACE_SKILLS_MARKER_RELATIVE = ".github/.ms-devtools-skills.yml";
13585
+ SAFE_LOCAL_ID_PATTERN2 = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
13586
+ SkillStore = class {
13587
+ constructor(options2) {
13588
+ this.workspacePath = options2.workspacePath;
13589
+ this.userSkillsRoot = options2.userSkillsRoot;
13590
+ this.fileSystem = options2.fileSystem ?? fs12__namespace;
13591
+ }
13592
+ normalizeRemoteSkillId(remoteId) {
13593
+ if (remoteId.startsWith("official/")) {
13594
+ return assertSafeLocalSkillId(remoteId.slice("official/".length));
13595
+ }
13596
+ if (remoteId.startsWith("community/")) {
13597
+ const lastSlash = remoteId.lastIndexOf("/");
13598
+ return assertSafeLocalSkillId(remoteId.slice(lastSlash + 1));
13599
+ }
13600
+ return assertSafeLocalSkillId(remoteId);
13601
+ }
13602
+ getWorkspaceSkillPath(skillId) {
13603
+ return `${WORKSPACE_SKILLS_ROOT_RELATIVE}/${skillId}`;
13604
+ }
13605
+ getWorkspaceMarkerPath() {
13606
+ return WORKSPACE_SKILLS_MARKER_RELATIVE;
13607
+ }
13608
+ getUserSkillPath(skillId) {
13609
+ return path11__namespace.join(this.userSkillsRoot, skillId);
13610
+ }
13611
+ async listWorkspaceSkillIds() {
13612
+ const skillsRootPath = path11__namespace.join(
13613
+ this.workspacePath,
13614
+ WORKSPACE_SKILLS_ROOT_RELATIVE
13615
+ );
13616
+ try {
13617
+ const entries = await this.fileSystem.readdir(skillsRootPath, {
13618
+ withFileTypes: true
13619
+ });
13620
+ return entries.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name).sort();
13621
+ } catch {
13622
+ return [];
13623
+ }
13624
+ }
13625
+ async listUserSkillIds() {
13626
+ try {
13627
+ const entries = await this.fileSystem.readdir(this.userSkillsRoot, {
13628
+ withFileTypes: true
13629
+ });
13630
+ return entries.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name).sort();
13631
+ } catch {
13632
+ return [];
13633
+ }
13634
+ }
13635
+ async writeManagedUserSkillMarker(skillId) {
13636
+ const targetDir = this.getUserSkillPath(skillId);
13637
+ await this.fileSystem.mkdir(targetDir, { recursive: true });
13638
+ await this.fileSystem.writeFile(
13639
+ path11__namespace.join(targetDir, USER_SKILL_MARKER_FILE),
13640
+ JSON.stringify({ skillId, installedBy: "ms-devtools" }, null, 2),
13641
+ "utf-8"
13642
+ );
13643
+ }
13644
+ async isManagedUserSkill(skillId) {
13645
+ try {
13646
+ const marker = await this.fileSystem.readFile(
13647
+ path11__namespace.join(this.getUserSkillPath(skillId), USER_SKILL_MARKER_FILE),
13648
+ "utf-8"
13649
+ );
13650
+ const parsed = JSON.parse(marker);
13651
+ return parsed.skillId === skillId;
13652
+ } catch {
13653
+ return false;
13654
+ }
13655
+ }
13656
+ };
13657
+ }
13658
+ });
13659
+
13660
+ // ../../packages/serviceme-core/src/skills/types.ts
13661
+ var init_types3 = __esm({
13662
+ "../../packages/serviceme-core/src/skills/types.ts"() {
13663
+ }
13664
+ });
13665
+
13666
+ // ../../packages/serviceme-core/src/skills/index.ts
13667
+ var init_skills = __esm({
13668
+ "../../packages/serviceme-core/src/skills/index.ts"() {
13669
+ init_SkillCatalogClient();
13670
+ init_SkillReconciler();
13671
+ init_SkillStore();
13672
+ init_types3();
13673
+ }
13674
+ });
13675
+
13108
13676
  // ../../packages/serviceme-core/src/index.ts
13109
13677
  var src_exports = {};
13110
13678
  __export(src_exports, {
13679
+ AgentCatalogClient: () => AgentCatalogClient,
13680
+ AgentReconciler: () => AgentReconciler,
13681
+ AgentStore: () => AgentStore,
13111
13682
  DaemonLogger: () => DaemonLogger,
13112
13683
  EnvironmentInspector: () => EnvironmentInspector,
13113
13684
  GithubCopilotCliExecutor: () => GithubCopilotCliExecutor,
@@ -13117,6 +13688,10 @@ __export(src_exports, {
13117
13688
  ProjectTools: () => ProjectTools,
13118
13689
  SchedulerDaemon: () => SchedulerDaemon,
13119
13690
  ShellExecutor: () => ShellExecutor,
13691
+ SkillCatalogClient: () => SkillCatalogClient,
13692
+ SkillReconciler: () => SkillReconciler,
13693
+ SkillStore: () => SkillStore,
13694
+ TOOL_RISK_MAP: () => TOOL_RISK_MAP,
13120
13695
  TaskConfigManager: () => TaskConfigManager,
13121
13696
  TaskExecutionEngine: () => TaskExecutionEngine,
13122
13697
  TaskLogManager: () => TaskLogManager,
@@ -13134,6 +13709,7 @@ __export(src_exports, {
13134
13709
  matchesCron: () => matchesCron,
13135
13710
  moveFiles: () => moveFiles,
13136
13711
  noopLogger: () => noopLogger,
13712
+ parseAgentToolPermissions: () => parseAgentToolPermissions,
13137
13713
  parseIntervalMs: () => parseIntervalMs,
13138
13714
  resolveTaskExecutionPayload: () => resolveTaskExecutionPayload,
13139
13715
  unzipFile: () => unzipFile,
@@ -13141,13 +13717,16 @@ __export(src_exports, {
13141
13717
  });
13142
13718
  var init_src2 = __esm({
13143
13719
  "../../packages/serviceme-core/src/index.ts"() {
13720
+ init_agents();
13144
13721
  init_copilot2();
13145
13722
  init_environmentInspector();
13146
13723
  init_imageTools();
13147
13724
  init_jsonTools();
13148
13725
  init_logger();
13726
+ init_permissions();
13149
13727
  init_projectTools();
13150
13728
  init_scheduled_tasks2();
13729
+ init_skills();
13151
13730
  init_fileUtils();
13152
13731
  }
13153
13732
  });
@@ -13198,48 +13777,954 @@ function getStringFlag(parsed, name) {
13198
13777
  return typeof value === "string" ? value : void 0;
13199
13778
  }
13200
13779
 
13201
- // src/commands/bridge.ts
13780
+ // src/commands/agent.ts
13202
13781
  init_src2();
13203
-
13204
- // src/bridge/BridgeServer.ts
13205
13782
  init_src();
13206
13783
 
13207
- // src/version.ts
13208
- var SERVICEME_CLI_NAME = "serviceme";
13209
- var SERVICEME_CLI_VERSION = "0.1.5";
13210
-
13211
- // src/bridge/ndjson.ts
13212
- function writeBridgeMessage(message) {
13213
- process.stdout.write(`${JSON.stringify(message)}
13784
+ // src/output.ts
13785
+ init_src();
13786
+ function writeJson(value) {
13787
+ process.stdout.write(`${JSON.stringify(value)}
13214
13788
  `);
13215
13789
  }
13790
+ function writeSuccess(data) {
13791
+ writeJson(createCliSuccess(data));
13792
+ }
13793
+ function writeFailure(error) {
13794
+ writeJson(createCliFailure(normalizeServicemeError(error)));
13795
+ }
13216
13796
 
13217
- // src/bridge/TaskBridgeHandler.ts
13218
- init_src2();
13219
- var TaskBridgeHandler = class {
13220
- constructor(logger, emitEvent) {
13221
- this.logger = logger;
13222
- this.emitEvent = emitEvent;
13223
- this.engine = new TaskExecutionEngine(
13224
- (taskType) => getExecutor(taskType)
13797
+ // src/commands/agent.ts
13798
+ function normalizeAgentIdOrThrow(store, remoteId) {
13799
+ try {
13800
+ return store.normalizeRemoteAgentId(remoteId);
13801
+ } catch {
13802
+ throw createServicemeError("invalid_params", `Invalid agent id: ${remoteId}`);
13803
+ }
13804
+ }
13805
+ async function runAgentCommand(parsed) {
13806
+ const action = parsed.positionals[1];
13807
+ const workspacePath = getStringFlag(parsed, "workspacePath");
13808
+ if (!workspacePath) {
13809
+ throw createServicemeError(
13810
+ "invalid_params",
13811
+ "Expected --workspacePath <path>."
13225
13812
  );
13226
- this.engine.setListener({
13227
- onStarted: (params) => this.emitEvent("task.started", params),
13228
- onOutput: (params) => this.emitEvent("task.output", params),
13229
- onCompleted: (params) => this.emitEvent("task.completed", params),
13230
- onFailed: (params) => this.emitEvent("task.failed", params),
13231
- onCancelled: (params) => this.emitEvent("task.cancelled", params)
13232
- });
13233
13813
  }
13234
- async execute(snapshot) {
13235
- let earlyError;
13236
- const executePromise = this.engine.execute(snapshot).catch((err) => {
13237
- earlyError = err;
13238
- });
13239
- await Promise.resolve();
13240
- if (earlyError) {
13241
- throw earlyError;
13242
- }
13814
+ const store = new AgentStore({
13815
+ workspacePath,
13816
+ userAgentsRoot: path11__namespace.join(os__namespace.homedir(), ".copilot", "agents")
13817
+ });
13818
+ const catalogClient = new AgentCatalogClient({
13819
+ baseUrl: getStringFlag(parsed, "baseUrl")
13820
+ });
13821
+ const reconciler = new AgentReconciler({
13822
+ agentStore: store,
13823
+ catalogClient
13824
+ });
13825
+ switch (action) {
13826
+ case "list":
13827
+ writeSuccess(await handleList(store));
13828
+ return;
13829
+ case "install":
13830
+ writeSuccess(await handleInstall(store, parsed));
13831
+ return;
13832
+ case "uninstall":
13833
+ writeSuccess(await handleUninstall(store, workspacePath, parsed));
13834
+ return;
13835
+ case "move":
13836
+ writeSuccess(await handleMove(store, workspacePath, parsed));
13837
+ return;
13838
+ case "marketplace":
13839
+ writeSuccess(await handleMarketplace(store, catalogClient));
13840
+ return;
13841
+ case "permissions":
13842
+ writeSuccess(
13843
+ await handlePermissions(store, reconciler, workspacePath, parsed)
13844
+ );
13845
+ return;
13846
+ default:
13847
+ throw new Error(
13848
+ "Unsupported agent command. Use list, install, uninstall, move, marketplace, or permissions."
13849
+ );
13850
+ }
13851
+ }
13852
+ async function handleList(store) {
13853
+ const workspaceAgents = await store.listWorkspaceAgentIds();
13854
+ const userAgents = await store.listUserAgentIds();
13855
+ return {
13856
+ agents: [
13857
+ ...workspaceAgents.map((id) => ({ id, scope: "workspace" })),
13858
+ ...userAgents.map((id) => ({ id, scope: "user" }))
13859
+ ]
13860
+ };
13861
+ }
13862
+ async function handleInstall(store, parsed) {
13863
+ const remoteId = getStringFlag(parsed, "id");
13864
+ if (!remoteId) {
13865
+ throw createServicemeError(
13866
+ "invalid_params",
13867
+ "Expected --id <remoteAgentId>."
13868
+ );
13869
+ }
13870
+ const agentId = normalizeAgentIdOrThrow(store, remoteId);
13871
+ if (!getBooleanFlag(parsed, "confirmed")) {
13872
+ return {
13873
+ changed: false,
13874
+ scope: "workspace",
13875
+ agentId,
13876
+ status: "requires_confirmation",
13877
+ message: "Install requires --confirmed."
13878
+ };
13879
+ }
13880
+ const content = `---
13881
+ name: ${agentId}
13882
+ tools:
13883
+ - run_in_terminal
13884
+ - read_file
13885
+ ---
13886
+
13887
+ # ${agentId}
13888
+ `;
13889
+ await store.writeAgentFiles(agentId, "workspace", [
13890
+ {
13891
+ path: `${agentId}.agent.md`,
13892
+ content
13893
+ }
13894
+ ]);
13895
+ await store.addInstalledAgent({
13896
+ id: remoteId,
13897
+ name: agentId,
13898
+ scope: "workspace",
13899
+ installedAt: (/* @__PURE__ */ new Date()).toISOString()
13900
+ });
13901
+ return {
13902
+ changed: true,
13903
+ scope: "workspace",
13904
+ agentId,
13905
+ status: "success"
13906
+ };
13907
+ }
13908
+ async function handleUninstall(store, workspacePath, parsed) {
13909
+ const remoteId = getStringFlag(parsed, "id");
13910
+ if (!remoteId) {
13911
+ throw createServicemeError(
13912
+ "invalid_params",
13913
+ "Expected --id <remoteAgentId>."
13914
+ );
13915
+ }
13916
+ const agentId = normalizeAgentIdOrThrow(store, remoteId);
13917
+ await fs12__namespace.rm(
13918
+ path11__namespace.join(workspacePath, ".github", "agents", `${agentId}.agent.md`),
13919
+ {
13920
+ recursive: true,
13921
+ force: true
13922
+ }
13923
+ );
13924
+ await fs12__namespace.rm(path11__namespace.join(workspacePath, ".github", "agents", agentId), {
13925
+ recursive: true,
13926
+ force: true
13927
+ });
13928
+ await fs12__namespace.rm(path11__namespace.join(store.getUserAgentsRootPath(), `${agentId}.agent.md`), {
13929
+ recursive: true,
13930
+ force: true
13931
+ });
13932
+ await fs12__namespace.rm(path11__namespace.join(store.getUserAgentsRootPath(), agentId), {
13933
+ recursive: true,
13934
+ force: true
13935
+ });
13936
+ await store.removeInstalledAgent(remoteId);
13937
+ return {
13938
+ changed: true,
13939
+ agentId
13940
+ };
13941
+ }
13942
+ async function handleMove(store, workspacePath, parsed) {
13943
+ const remoteId = getStringFlag(parsed, "id");
13944
+ const to = getStringFlag(parsed, "to");
13945
+ if (!remoteId || !to) {
13946
+ throw createServicemeError(
13947
+ "invalid_params",
13948
+ "Expected --id <remoteAgentId> and --to <workspace|user>."
13949
+ );
13950
+ }
13951
+ if (to !== "workspace" && to !== "user") {
13952
+ throw createServicemeError(
13953
+ "invalid_params",
13954
+ "Expected --to value to be workspace or user."
13955
+ );
13956
+ }
13957
+ const agentId = normalizeAgentIdOrThrow(store, remoteId);
13958
+ const workspaceFlatPath = path11__namespace.join(
13959
+ workspacePath,
13960
+ ".github",
13961
+ "agents",
13962
+ `${agentId}.agent.md`
13963
+ );
13964
+ const userFlatPath = path11__namespace.join(
13965
+ store.getUserAgentsRootPath(),
13966
+ `${agentId}.agent.md`
13967
+ );
13968
+ if (to === "user") {
13969
+ await moveEntry(workspaceFlatPath, userFlatPath);
13970
+ return {
13971
+ changed: true,
13972
+ fromScope: "workspace",
13973
+ toScope: "user",
13974
+ agentId
13975
+ };
13976
+ }
13977
+ await moveEntry(userFlatPath, workspaceFlatPath);
13978
+ return {
13979
+ changed: true,
13980
+ fromScope: "user",
13981
+ toScope: "workspace",
13982
+ agentId
13983
+ };
13984
+ }
13985
+ async function handleMarketplace(store, catalogClient) {
13986
+ const [catalog, workspaceAgentIds, userAgentIds] = await Promise.all([
13987
+ catalogClient.getCatalog(),
13988
+ store.listWorkspaceAgentIds(),
13989
+ store.listUserAgentIds()
13990
+ ]);
13991
+ const scopesById = /* @__PURE__ */ new Map();
13992
+ for (const agentId of workspaceAgentIds) {
13993
+ scopesById.set(agentId, ["workspace"]);
13994
+ }
13995
+ for (const agentId of userAgentIds) {
13996
+ const existing = scopesById.get(agentId);
13997
+ if (existing) {
13998
+ existing.push("user");
13999
+ } else {
14000
+ scopesById.set(agentId, ["user"]);
14001
+ }
14002
+ }
14003
+ const merged = /* @__PURE__ */ new Map();
14004
+ for (const agent of catalog.agents) {
14005
+ const normalizedId = normalizeAgentIdOrThrow(store, agent.id);
14006
+ merged.set(normalizedId, {
14007
+ id: normalizedId,
14008
+ displayName: agent.displayName,
14009
+ description: agent.description,
14010
+ source: "catalog",
14011
+ scopes: scopesById.get(normalizedId) ?? []
14012
+ });
14013
+ }
14014
+ for (const [agentId, scopes] of scopesById) {
14015
+ if (merged.has(agentId)) {
14016
+ continue;
14017
+ }
14018
+ merged.set(agentId, {
14019
+ id: agentId,
14020
+ displayName: agentId,
14021
+ description: "Local installed agent",
14022
+ source: "local",
14023
+ scopes
14024
+ });
14025
+ }
14026
+ return {
14027
+ agents: [...merged.values()].sort((a, b) => a.id.localeCompare(b.id)),
14028
+ fetchedAt: catalog.fetchedAt
14029
+ };
14030
+ }
14031
+ async function handlePermissions(store, reconciler, workspacePath, parsed) {
14032
+ const remoteId = getStringFlag(parsed, "id");
14033
+ const scopeFlag = getStringFlag(parsed, "scope");
14034
+ if (!remoteId) {
14035
+ throw createServicemeError(
14036
+ "invalid_params",
14037
+ "Expected --id <remoteAgentId>."
14038
+ );
14039
+ }
14040
+ if (scopeFlag !== void 0 && scopeFlag !== "workspace" && scopeFlag !== "user") {
14041
+ throw createServicemeError(
14042
+ "invalid_params",
14043
+ "Expected --scope value to be workspace or user."
14044
+ );
14045
+ }
14046
+ const agentId = normalizeAgentIdOrThrow(store, remoteId);
14047
+ const requestedScope = scopeFlag ?? "workspace";
14048
+ const scope = requestedScope;
14049
+ const content = await readAgentContent(store, workspacePath, agentId, scope);
14050
+ const summary = reconciler.getPermissionSummary(agentId, agentId, content);
14051
+ return {
14052
+ agentId,
14053
+ scope,
14054
+ summary
14055
+ };
14056
+ }
14057
+ async function moveEntry(fromPath, toPath) {
14058
+ await fs12__namespace.mkdir(path11__namespace.dirname(toPath), { recursive: true });
14059
+ try {
14060
+ await fs12__namespace.rename(fromPath, toPath);
14061
+ } catch {
14062
+ await fs12__namespace.cp(fromPath, toPath, { recursive: true });
14063
+ await fs12__namespace.rm(fromPath, { recursive: true, force: true });
14064
+ }
14065
+ }
14066
+ async function readAgentContent(store, workspacePath, agentId, scope) {
14067
+ const root2 = scope === "workspace" ? path11__namespace.join(workspacePath, store.getWorkspaceAgentsRootPath()) : store.getUserAgentsRootPath();
14068
+ const candidates = [
14069
+ path11__namespace.join(root2, `${agentId}.agent.md`),
14070
+ path11__namespace.join(root2, agentId, `${agentId}.agent.md`)
14071
+ ];
14072
+ for (const candidate of candidates) {
14073
+ try {
14074
+ return await fs12__namespace.readFile(candidate, "utf8");
14075
+ } catch {
14076
+ }
14077
+ }
14078
+ throw createServicemeError(
14079
+ "not_found",
14080
+ `Agent file not found for ${agentId} in ${scope} scope.`
14081
+ );
14082
+ }
14083
+
14084
+ // src/commands/bridge.ts
14085
+ init_src2();
14086
+
14087
+ // src/bridge/BridgeServer.ts
14088
+ init_src();
14089
+
14090
+ // src/version.ts
14091
+ var SERVICEME_CLI_NAME = "serviceme";
14092
+ var SERVICEME_CLI_VERSION = "0.1.6";
14093
+
14094
+ // src/bridge/AgentBridgeHandler.ts
14095
+ init_src2();
14096
+ init_src();
14097
+ function normalizeAgentIdOrThrow2(store, remoteId) {
14098
+ try {
14099
+ return store.normalizeRemoteAgentId(remoteId);
14100
+ } catch {
14101
+ throw createServicemeError("invalid_params", `Invalid agent id: ${remoteId}`);
14102
+ }
14103
+ }
14104
+ var AgentBridgeHandler = class {
14105
+ async getMarketplaceState(params) {
14106
+ const context = this.createContext(params.workspacePath);
14107
+ const [catalog, workspaceAgentIds, userAgentIds] = await Promise.all([
14108
+ context.catalogClient.getCatalog(),
14109
+ context.store.listWorkspaceAgentIds(),
14110
+ context.store.listUserAgentIds()
14111
+ ]);
14112
+ const workspaceSet = new Set(workspaceAgentIds);
14113
+ const userSet = new Set(userAgentIds);
14114
+ const now = (/* @__PURE__ */ new Date()).toISOString();
14115
+ const byId = /* @__PURE__ */ new Map();
14116
+ for (const agent of catalog.agents) {
14117
+ const agentId = normalizeAgentIdOrThrow2(context.store, agent.id);
14118
+ const workspaceInstalled = workspaceSet.has(agentId);
14119
+ const userInstalled = userSet.has(agentId);
14120
+ byId.set(agentId, {
14121
+ id: agentId,
14122
+ displayName: agent.displayName,
14123
+ description: agent.description,
14124
+ version: agent.version,
14125
+ updatedAt: agent.updatedAt,
14126
+ categoryId: agent.categoryId,
14127
+ isCatalogAgent: true,
14128
+ recommended: agent.recommended,
14129
+ installCount: agent.installCount,
14130
+ ownerScope: agent.ownerScope,
14131
+ ownerKind: agent.ownerKind,
14132
+ hasConflict: agent.hasConflict,
14133
+ tools: agent.tools,
14134
+ source: agent.source,
14135
+ localAgentPath: workspaceInstalled || userInstalled ? workspaceInstalled ? path11__namespace.join(
14136
+ context.workspacePath,
14137
+ context.store.getWorkspaceAgentsRootPath(),
14138
+ `${agentId}.agent.md`
14139
+ ) : path11__namespace.join(
14140
+ context.store.getUserAgentsRootPath(),
14141
+ `${agentId}.agent.md`
14142
+ ) : void 0,
14143
+ canPublish: agent.canPublish,
14144
+ workspaceState: this.makeScopeState(
14145
+ "workspace",
14146
+ workspaceInstalled,
14147
+ path11__namespace.join(
14148
+ context.workspacePath,
14149
+ context.store.getWorkspaceAgentsRootPath(),
14150
+ `${agentId}.agent.md`
14151
+ )
14152
+ ),
14153
+ userState: this.makeScopeState(
14154
+ "user",
14155
+ userInstalled,
14156
+ path11__namespace.join(
14157
+ context.store.getUserAgentsRootPath(),
14158
+ `${agentId}.agent.md`
14159
+ )
14160
+ )
14161
+ });
14162
+ }
14163
+ for (const agentId of workspaceAgentIds) {
14164
+ if (byId.has(agentId)) {
14165
+ continue;
14166
+ }
14167
+ byId.set(agentId, {
14168
+ id: agentId,
14169
+ displayName: agentId,
14170
+ description: "Local installed agent",
14171
+ version: "0.0.0",
14172
+ updatedAt: now,
14173
+ isCatalogAgent: false,
14174
+ recommended: false,
14175
+ installCount: 0,
14176
+ hasConflict: false,
14177
+ tools: [],
14178
+ source: "local",
14179
+ localAgentPath: path11__namespace.join(
14180
+ context.workspacePath,
14181
+ context.store.getWorkspaceAgentsRootPath(),
14182
+ `${agentId}.agent.md`
14183
+ ),
14184
+ workspaceState: this.makeScopeState(
14185
+ "workspace",
14186
+ true,
14187
+ path11__namespace.join(
14188
+ context.workspacePath,
14189
+ context.store.getWorkspaceAgentsRootPath(),
14190
+ `${agentId}.agent.md`
14191
+ )
14192
+ ),
14193
+ userState: this.makeScopeState(
14194
+ "user",
14195
+ userSet.has(agentId),
14196
+ path11__namespace.join(
14197
+ context.store.getUserAgentsRootPath(),
14198
+ `${agentId}.agent.md`
14199
+ )
14200
+ )
14201
+ });
14202
+ }
14203
+ for (const agentId of userAgentIds) {
14204
+ if (byId.has(agentId)) {
14205
+ continue;
14206
+ }
14207
+ byId.set(agentId, {
14208
+ id: agentId,
14209
+ displayName: agentId,
14210
+ description: "Local installed agent",
14211
+ version: "0.0.0",
14212
+ updatedAt: now,
14213
+ isCatalogAgent: false,
14214
+ recommended: false,
14215
+ installCount: 0,
14216
+ hasConflict: false,
14217
+ tools: [],
14218
+ source: "local",
14219
+ localAgentPath: path11__namespace.join(
14220
+ context.store.getUserAgentsRootPath(),
14221
+ `${agentId}.agent.md`
14222
+ ),
14223
+ workspaceState: this.makeScopeState(
14224
+ "workspace",
14225
+ workspaceSet.has(agentId),
14226
+ path11__namespace.join(
14227
+ context.workspacePath,
14228
+ context.store.getWorkspaceAgentsRootPath(),
14229
+ `${agentId}.agent.md`
14230
+ )
14231
+ ),
14232
+ userState: this.makeScopeState(
14233
+ "user",
14234
+ true,
14235
+ path11__namespace.join(
14236
+ context.store.getUserAgentsRootPath(),
14237
+ `${agentId}.agent.md`
14238
+ )
14239
+ )
14240
+ });
14241
+ }
14242
+ return {
14243
+ configPath: path11__namespace.join(
14244
+ context.workspacePath,
14245
+ context.store.getWorkspaceStateFilePath()
14246
+ ),
14247
+ userAgentsPath: context.userAgentsRoot,
14248
+ agents: [...byId.values()].sort((a, b) => a.id.localeCompare(b.id)),
14249
+ installedAgentIds: [.../* @__PURE__ */ new Set([...workspaceAgentIds, ...userAgentIds])],
14250
+ workspaceOpen: true
14251
+ };
14252
+ }
14253
+ async mutate(request) {
14254
+ const context = this.createContext();
14255
+ const agentId = normalizeAgentIdOrThrow2(context.store, request.agentId);
14256
+ const mutateResult = await context.reconciler.mutate({
14257
+ ...request,
14258
+ agentId
14259
+ });
14260
+ if (mutateResult.status === "success") {
14261
+ await this.applyMutationSideEffect(context, {
14262
+ ...request,
14263
+ agentId
14264
+ });
14265
+ }
14266
+ return {
14267
+ state: await this.getMarketplaceState({
14268
+ workspacePath: context.workspacePath
14269
+ }),
14270
+ agentId,
14271
+ targetScope: request.targetScope,
14272
+ action: request.action,
14273
+ changed: mutateResult.changed,
14274
+ status: mutateResult.status,
14275
+ message: mutateResult.message,
14276
+ tools: mutateResult.tools
14277
+ };
14278
+ }
14279
+ async permissions(params) {
14280
+ const context = this.createContext();
14281
+ const agentId = normalizeAgentIdOrThrow2(context.store, params.agentId);
14282
+ const scope = params.scope ?? "workspace";
14283
+ const content = await this.readAgentContent(context, agentId, scope);
14284
+ return context.reconciler.getPermissionSummary(agentId, agentId, content);
14285
+ }
14286
+ createContext(workspacePath) {
14287
+ const resolvedWorkspacePath = workspacePath ?? process.cwd();
14288
+ const userAgentsRoot = path11__namespace.join(os__namespace.homedir(), ".copilot", "agents");
14289
+ const store = new AgentStore({
14290
+ workspacePath: resolvedWorkspacePath,
14291
+ userAgentsRoot
14292
+ });
14293
+ const catalogClient = new AgentCatalogClient();
14294
+ const reconciler = new AgentReconciler({
14295
+ agentStore: store,
14296
+ catalogClient
14297
+ });
14298
+ return {
14299
+ workspacePath: resolvedWorkspacePath,
14300
+ userAgentsRoot,
14301
+ store,
14302
+ catalogClient,
14303
+ reconciler
14304
+ };
14305
+ }
14306
+ makeScopeState(scope, installed, agentPath) {
14307
+ if (installed) {
14308
+ return {
14309
+ scope,
14310
+ status: "installed",
14311
+ path: agentPath,
14312
+ isInstalled: true,
14313
+ canInstall: false,
14314
+ canUninstall: true,
14315
+ canRemove: false,
14316
+ canMoveHere: false
14317
+ };
14318
+ }
14319
+ return {
14320
+ scope,
14321
+ status: "absent",
14322
+ isInstalled: false,
14323
+ canInstall: true,
14324
+ canUninstall: false,
14325
+ canRemove: false,
14326
+ canMoveHere: true
14327
+ };
14328
+ }
14329
+ async applyMutationSideEffect(context, request) {
14330
+ const workspaceFlatPath = path11__namespace.join(
14331
+ context.workspacePath,
14332
+ context.store.getWorkspaceAgentsRootPath(),
14333
+ `${request.agentId}.agent.md`
14334
+ );
14335
+ const userFlatPath = path11__namespace.join(
14336
+ context.store.getUserAgentsRootPath(),
14337
+ `${request.agentId}.agent.md`
14338
+ );
14339
+ switch (request.action) {
14340
+ case "install":
14341
+ if (request.targetScope === "workspace") {
14342
+ await this.writeDefaultAgentFile(workspaceFlatPath, request.agentId);
14343
+ } else {
14344
+ await this.writeDefaultAgentFile(userFlatPath, request.agentId);
14345
+ }
14346
+ return;
14347
+ case "uninstall":
14348
+ if (request.targetScope === "workspace") {
14349
+ await fs12__namespace.rm(workspaceFlatPath, { recursive: true, force: true });
14350
+ } else {
14351
+ await fs12__namespace.rm(userFlatPath, { recursive: true, force: true });
14352
+ }
14353
+ return;
14354
+ case "move":
14355
+ if (request.targetScope === "workspace") {
14356
+ await this.moveEntry(userFlatPath, workspaceFlatPath);
14357
+ } else {
14358
+ await this.moveEntry(workspaceFlatPath, userFlatPath);
14359
+ }
14360
+ return;
14361
+ default:
14362
+ return;
14363
+ }
14364
+ }
14365
+ async moveEntry(fromPath, toPath) {
14366
+ await fs12__namespace.mkdir(path11__namespace.dirname(toPath), { recursive: true });
14367
+ try {
14368
+ await fs12__namespace.rename(fromPath, toPath);
14369
+ } catch {
14370
+ await fs12__namespace.cp(fromPath, toPath, { recursive: true });
14371
+ await fs12__namespace.rm(fromPath, { recursive: true, force: true });
14372
+ }
14373
+ }
14374
+ async writeDefaultAgentFile(targetPath, agentId) {
14375
+ await fs12__namespace.mkdir(path11__namespace.dirname(targetPath), { recursive: true });
14376
+ await fs12__namespace.writeFile(
14377
+ targetPath,
14378
+ `---
14379
+ name: ${agentId}
14380
+ tools:
14381
+ - run_in_terminal
14382
+ - read_file
14383
+ ---
14384
+
14385
+ # ${agentId}
14386
+ `,
14387
+ "utf8"
14388
+ );
14389
+ }
14390
+ async readAgentContent(context, agentId, scope) {
14391
+ const root2 = scope === "workspace" ? path11__namespace.join(
14392
+ context.workspacePath,
14393
+ context.store.getWorkspaceAgentsRootPath()
14394
+ ) : context.store.getUserAgentsRootPath();
14395
+ const candidates = [
14396
+ path11__namespace.join(root2, `${agentId}.agent.md`),
14397
+ path11__namespace.join(root2, agentId, `${agentId}.agent.md`)
14398
+ ];
14399
+ for (const candidate of candidates) {
14400
+ try {
14401
+ return await fs12__namespace.readFile(candidate, "utf8");
14402
+ } catch {
14403
+ }
14404
+ }
14405
+ throw createServicemeError(
14406
+ "not_found",
14407
+ `Agent file not found for ${agentId} in ${scope} scope.`
14408
+ );
14409
+ }
14410
+ };
14411
+
14412
+ // src/bridge/ndjson.ts
14413
+ function writeBridgeMessage(message) {
14414
+ process.stdout.write(`${JSON.stringify(message)}
14415
+ `);
14416
+ }
14417
+
14418
+ // src/bridge/SkillBridgeHandler.ts
14419
+ init_src2();
14420
+ init_src();
14421
+ function normalizeSkillIdOrThrow(store, remoteId) {
14422
+ try {
14423
+ return store.normalizeRemoteSkillId(remoteId);
14424
+ } catch {
14425
+ throw createServicemeError("invalid_params", `Invalid skill id: ${remoteId}`);
14426
+ }
14427
+ }
14428
+ var SkillBridgeHandler = class {
14429
+ async getMarketplaceState(params) {
14430
+ const context = this.createContext(params.workspacePath);
14431
+ const [catalog, workspaceSkillIds, userSkillIds] = await Promise.all([
14432
+ context.catalogClient.getCatalog(),
14433
+ context.store.listWorkspaceSkillIds(),
14434
+ context.store.listUserSkillIds()
14435
+ ]);
14436
+ const workspaceSet = new Set(workspaceSkillIds);
14437
+ const userSet = new Set(userSkillIds);
14438
+ const now = (/* @__PURE__ */ new Date()).toISOString();
14439
+ const byId = /* @__PURE__ */ new Map();
14440
+ for (const skill of catalog.skills) {
14441
+ const skillId = normalizeSkillIdOrThrow(context.store, skill.id);
14442
+ const workspaceInstalled = workspaceSet.has(skillId);
14443
+ const userInstalled = userSet.has(skillId);
14444
+ byId.set(skillId, {
14445
+ id: skillId,
14446
+ displayName: skill.displayName,
14447
+ description: skill.description,
14448
+ version: skill.version,
14449
+ updatedAt: skill.updatedAt,
14450
+ categoryId: skill.categoryId,
14451
+ enabled: skill.enabled,
14452
+ isCatalogSkill: true,
14453
+ recommended: skill.recommended,
14454
+ installCount: skill.installCount,
14455
+ requiresSetup: skill.requiresSetup,
14456
+ setupHint: skill.setupHint,
14457
+ homepage: skill.homepage,
14458
+ ownerScope: skill.ownerScope,
14459
+ ownerKind: skill.ownerKind,
14460
+ hasConflict: skill.hasConflict,
14461
+ hasScripts: skill.hasScripts,
14462
+ hasHooks: skill.hasHooks,
14463
+ source: skill.source,
14464
+ localSkillPath: workspaceInstalled || userInstalled ? workspaceInstalled ? path11__namespace.join(
14465
+ context.workspacePath,
14466
+ context.store.getWorkspaceSkillPath(skillId)
14467
+ ) : context.store.getUserSkillPath(skillId) : void 0,
14468
+ canPublish: skill.canPublish,
14469
+ workspaceState: this.makeScopeState(
14470
+ "workspace",
14471
+ workspaceInstalled,
14472
+ path11__namespace.join(
14473
+ context.workspacePath,
14474
+ context.store.getWorkspaceSkillPath(skillId)
14475
+ )
14476
+ ),
14477
+ userState: this.makeScopeState(
14478
+ "user",
14479
+ userInstalled,
14480
+ context.store.getUserSkillPath(skillId)
14481
+ )
14482
+ });
14483
+ }
14484
+ for (const skillId of workspaceSkillIds) {
14485
+ if (byId.has(skillId)) {
14486
+ continue;
14487
+ }
14488
+ byId.set(skillId, {
14489
+ id: skillId,
14490
+ displayName: skillId,
14491
+ description: "Local installed skill",
14492
+ version: "0.0.0",
14493
+ updatedAt: now,
14494
+ isCatalogSkill: false,
14495
+ recommended: false,
14496
+ installCount: 0,
14497
+ hasConflict: false,
14498
+ source: "local",
14499
+ localSkillPath: path11__namespace.join(
14500
+ context.workspacePath,
14501
+ context.store.getWorkspaceSkillPath(skillId)
14502
+ ),
14503
+ workspaceState: this.makeScopeState(
14504
+ "workspace",
14505
+ true,
14506
+ path11__namespace.join(
14507
+ context.workspacePath,
14508
+ context.store.getWorkspaceSkillPath(skillId)
14509
+ )
14510
+ ),
14511
+ userState: this.makeScopeState(
14512
+ "user",
14513
+ userSet.has(skillId),
14514
+ context.store.getUserSkillPath(skillId)
14515
+ )
14516
+ });
14517
+ }
14518
+ for (const skillId of userSkillIds) {
14519
+ if (byId.has(skillId)) {
14520
+ continue;
14521
+ }
14522
+ byId.set(skillId, {
14523
+ id: skillId,
14524
+ displayName: skillId,
14525
+ description: "Local installed skill",
14526
+ version: "0.0.0",
14527
+ updatedAt: now,
14528
+ isCatalogSkill: false,
14529
+ recommended: false,
14530
+ installCount: 0,
14531
+ hasConflict: false,
14532
+ source: "local",
14533
+ localSkillPath: context.store.getUserSkillPath(skillId),
14534
+ workspaceState: this.makeScopeState(
14535
+ "workspace",
14536
+ workspaceSet.has(skillId),
14537
+ path11__namespace.join(
14538
+ context.workspacePath,
14539
+ context.store.getWorkspaceSkillPath(skillId)
14540
+ )
14541
+ ),
14542
+ userState: this.makeScopeState(
14543
+ "user",
14544
+ true,
14545
+ context.store.getUserSkillPath(skillId)
14546
+ )
14547
+ });
14548
+ }
14549
+ return {
14550
+ configPath: path11__namespace.join(
14551
+ context.workspacePath,
14552
+ context.store.getWorkspaceMarkerPath()
14553
+ ),
14554
+ userSkillsPath: context.userSkillsRoot,
14555
+ skills: [...byId.values()].sort((a, b) => a.id.localeCompare(b.id)),
14556
+ enabledSkillIds: [],
14557
+ recommendedSkillIds: catalog.skills.filter((skill) => skill.recommended).map((skill) => context.store.normalizeRemoteSkillId(skill.id)),
14558
+ onboardingRequired: false,
14559
+ hasPersistedSelection: false,
14560
+ workspaceOpen: true
14561
+ };
14562
+ }
14563
+ async mutate(request) {
14564
+ const context = this.createContext();
14565
+ const skillId = normalizeSkillIdOrThrow(context.store, request.skillId);
14566
+ const mutateResult = await context.reconciler.mutate({
14567
+ ...request,
14568
+ skillId
14569
+ });
14570
+ if (mutateResult.status === "success") {
14571
+ await this.applyMutationSideEffect(context, {
14572
+ ...request,
14573
+ skillId
14574
+ });
14575
+ }
14576
+ return {
14577
+ state: await this.getMarketplaceState({
14578
+ workspacePath: context.workspacePath
14579
+ }),
14580
+ skillId,
14581
+ targetScope: request.targetScope,
14582
+ action: request.action,
14583
+ changed: mutateResult.changed,
14584
+ status: mutateResult.status,
14585
+ message: mutateResult.message,
14586
+ hasScripts: mutateResult.hasScripts,
14587
+ hasHooks: mutateResult.hasHooks
14588
+ };
14589
+ }
14590
+ async reconcile(params) {
14591
+ const state = await this.getMarketplaceState({
14592
+ workspacePath: params.workspacePath,
14593
+ forceRefresh: params.force
14594
+ });
14595
+ return {
14596
+ state,
14597
+ changed: false
14598
+ };
14599
+ }
14600
+ async publishable(params) {
14601
+ const context = this.createContext(params.workspacePath);
14602
+ const workspaceSkillIds = await context.store.listWorkspaceSkillIds();
14603
+ return {
14604
+ skills: workspaceSkillIds.map((skillId) => ({
14605
+ id: skillId,
14606
+ displayName: skillId,
14607
+ path: path11__namespace.join(
14608
+ context.workspacePath,
14609
+ context.store.getWorkspaceSkillPath(skillId)
14610
+ )
14611
+ }))
14612
+ };
14613
+ }
14614
+ createContext(workspacePath) {
14615
+ const resolvedWorkspacePath = workspacePath ?? process.cwd();
14616
+ const userSkillsRoot = path11__namespace.join(os__namespace.homedir(), ".agents", "skills");
14617
+ const store = new SkillStore({
14618
+ workspacePath: resolvedWorkspacePath,
14619
+ userSkillsRoot
14620
+ });
14621
+ const catalogClient = new SkillCatalogClient();
14622
+ const reconciler = new SkillReconciler({
14623
+ skillStore: store,
14624
+ catalogClient
14625
+ });
14626
+ return {
14627
+ workspacePath: resolvedWorkspacePath,
14628
+ userSkillsRoot,
14629
+ store,
14630
+ catalogClient,
14631
+ reconciler
14632
+ };
14633
+ }
14634
+ makeScopeState(scope, installed, skillPath) {
14635
+ if (installed) {
14636
+ return {
14637
+ scope,
14638
+ status: "installed",
14639
+ path: skillPath,
14640
+ isInstalled: true,
14641
+ canInstall: false,
14642
+ canUninstall: true,
14643
+ canRemove: false,
14644
+ canMoveHere: false
14645
+ };
14646
+ }
14647
+ return {
14648
+ scope,
14649
+ status: "absent",
14650
+ isInstalled: false,
14651
+ canInstall: true,
14652
+ canUninstall: false,
14653
+ canRemove: false,
14654
+ canMoveHere: true
14655
+ };
14656
+ }
14657
+ async applyMutationSideEffect(context, request) {
14658
+ const workspaceSkillPath = path11__namespace.join(
14659
+ context.workspacePath,
14660
+ context.store.getWorkspaceSkillPath(request.skillId)
14661
+ );
14662
+ const userSkillPath = context.store.getUserSkillPath(request.skillId);
14663
+ switch (request.action) {
14664
+ case "install":
14665
+ if (request.targetScope === "workspace") {
14666
+ await fs12__namespace.mkdir(workspaceSkillPath, { recursive: true });
14667
+ } else {
14668
+ await fs12__namespace.mkdir(userSkillPath, { recursive: true });
14669
+ await context.store.writeManagedUserSkillMarker(request.skillId);
14670
+ }
14671
+ return;
14672
+ case "uninstall":
14673
+ if (request.targetScope === "workspace") {
14674
+ await fs12__namespace.rm(workspaceSkillPath, { recursive: true, force: true });
14675
+ } else {
14676
+ await fs12__namespace.rm(userSkillPath, { recursive: true, force: true });
14677
+ }
14678
+ return;
14679
+ case "move":
14680
+ if (request.targetScope === "workspace") {
14681
+ await this.moveDirectory(userSkillPath, workspaceSkillPath);
14682
+ } else {
14683
+ await this.moveDirectory(workspaceSkillPath, userSkillPath);
14684
+ await context.store.writeManagedUserSkillMarker(request.skillId);
14685
+ }
14686
+ return;
14687
+ default:
14688
+ return;
14689
+ }
14690
+ }
14691
+ async moveDirectory(fromPath, toPath) {
14692
+ await fs12__namespace.mkdir(path11__namespace.dirname(toPath), { recursive: true });
14693
+ try {
14694
+ await fs12__namespace.rename(fromPath, toPath);
14695
+ } catch {
14696
+ await fs12__namespace.cp(fromPath, toPath, { recursive: true });
14697
+ await fs12__namespace.rm(fromPath, { recursive: true, force: true });
14698
+ }
14699
+ }
14700
+ };
14701
+
14702
+ // src/bridge/TaskBridgeHandler.ts
14703
+ init_src2();
14704
+ var TaskBridgeHandler = class {
14705
+ constructor(logger, emitEvent) {
14706
+ this.logger = logger;
14707
+ this.emitEvent = emitEvent;
14708
+ this.engine = new TaskExecutionEngine(
14709
+ (taskType) => getExecutor(taskType)
14710
+ );
14711
+ this.engine.setListener({
14712
+ onStarted: (params) => this.emitEvent("task.started", params),
14713
+ onOutput: (params) => this.emitEvent("task.output", params),
14714
+ onCompleted: (params) => this.emitEvent("task.completed", params),
14715
+ onFailed: (params) => this.emitEvent("task.failed", params),
14716
+ onCancelled: (params) => this.emitEvent("task.cancelled", params)
14717
+ });
14718
+ }
14719
+ async execute(snapshot) {
14720
+ let earlyError;
14721
+ const executePromise = this.engine.execute(snapshot).catch((err) => {
14722
+ earlyError = err;
14723
+ });
14724
+ await Promise.resolve();
14725
+ if (earlyError) {
14726
+ throw earlyError;
14727
+ }
13243
14728
  executePromise.then(void 0, (err) => {
13244
14729
  this.logger.error("Task execution background error", err);
13245
14730
  });
@@ -13262,7 +14747,9 @@ var CAPABILITIES = {
13262
14747
  bridge: true,
13263
14748
  json: 1,
13264
14749
  env: 1,
13265
- tasks: 1
14750
+ tasks: 1,
14751
+ skills: 1,
14752
+ agents: 1
13266
14753
  };
13267
14754
  var BridgeServer = class {
13268
14755
  constructor(logger) {
@@ -13271,6 +14758,8 @@ var BridgeServer = class {
13271
14758
  this.taskHandler = new TaskBridgeHandler(logger, (event, params) => {
13272
14759
  this.writeEvent(event, params);
13273
14760
  });
14761
+ this.skillHandler = new SkillBridgeHandler();
14762
+ this.agentHandler = new AgentBridgeHandler();
13274
14763
  }
13275
14764
  async run() {
13276
14765
  const reader = readline__namespace.createInterface({
@@ -13376,6 +14865,56 @@ var BridgeServer = class {
13376
14865
  this.writeSuccess(request.id, result);
13377
14866
  return;
13378
14867
  }
14868
+ case "skill.marketplace-state": {
14869
+ const skillRequest = request;
14870
+ const result = await this.skillHandler.getMarketplaceState(
14871
+ skillRequest.params
14872
+ );
14873
+ this.writeSuccess(request.id, result);
14874
+ return;
14875
+ }
14876
+ case "skill.mutate": {
14877
+ const skillRequest = request;
14878
+ const result = await this.skillHandler.mutate(skillRequest.params);
14879
+ this.writeSuccess(request.id, result);
14880
+ return;
14881
+ }
14882
+ case "skill.reconcile": {
14883
+ const skillRequest = request;
14884
+ const result = await this.skillHandler.reconcile(skillRequest.params);
14885
+ this.writeSuccess(request.id, result);
14886
+ return;
14887
+ }
14888
+ case "skill.publishable": {
14889
+ const skillRequest = request;
14890
+ const result = await this.skillHandler.publishable(
14891
+ skillRequest.params
14892
+ );
14893
+ this.writeSuccess(request.id, result);
14894
+ return;
14895
+ }
14896
+ case "agent.marketplace-state": {
14897
+ const agentRequest = request;
14898
+ const result = await this.agentHandler.getMarketplaceState(
14899
+ agentRequest.params
14900
+ );
14901
+ this.writeSuccess(request.id, result);
14902
+ return;
14903
+ }
14904
+ case "agent.mutate": {
14905
+ const agentRequest = request;
14906
+ const result = await this.agentHandler.mutate(agentRequest.params);
14907
+ this.writeSuccess(request.id, result);
14908
+ return;
14909
+ }
14910
+ case "agent.permissions": {
14911
+ const agentRequest = request;
14912
+ const result = await this.agentHandler.permissions(
14913
+ agentRequest.params
14914
+ );
14915
+ this.writeSuccess(request.id, result);
14916
+ return;
14917
+ }
13379
14918
  default:
13380
14919
  this.writeError(
13381
14920
  request.id,
@@ -13425,21 +14964,6 @@ async function runBridgeCommand() {
13425
14964
 
13426
14965
  // src/commands/copilot.ts
13427
14966
  init_src2();
13428
-
13429
- // src/output.ts
13430
- init_src();
13431
- function writeJson(value) {
13432
- process.stdout.write(`${JSON.stringify(value)}
13433
- `);
13434
- }
13435
- function writeSuccess(data) {
13436
- writeJson(createCliSuccess(data));
13437
- }
13438
- function writeFailure(error) {
13439
- writeJson(createCliFailure(normalizeServicemeError(error)));
13440
- }
13441
-
13442
- // src/commands/copilot.ts
13443
14967
  async function runCopilotCommand(parsed) {
13444
14968
  const action = parsed.positionals[1];
13445
14969
  switch (action) {
@@ -13559,7 +15083,7 @@ async function runImageCommand(parsed) {
13559
15083
  init_src2();
13560
15084
  async function readCommandInput(options2) {
13561
15085
  if (options2.filePath) {
13562
- return fs2__namespace.readFile(options2.filePath, "utf8");
15086
+ return fs12__namespace.readFile(options2.filePath, "utf8");
13563
15087
  }
13564
15088
  if (options2.stdin) {
13565
15089
  return readStdin();
@@ -13698,7 +15222,7 @@ async function runScheduleCommand(parsed) {
13698
15222
  await handleCreate(parsed);
13699
15223
  return;
13700
15224
  case "list":
13701
- handleList(parsed);
15225
+ handleList2(parsed);
13702
15226
  return;
13703
15227
  case "get":
13704
15228
  handleGet(parsed);
@@ -13733,7 +15257,7 @@ function requireWorkspace(parsed) {
13733
15257
  "Missing required flag: --workspacePath"
13734
15258
  );
13735
15259
  }
13736
- if (!fs8__namespace.existsSync(wp)) {
15260
+ if (!fs9__namespace.existsSync(wp)) {
13737
15261
  throw createServicemeError(
13738
15262
  "workspace_not_found",
13739
15263
  `Workspace path does not exist: ${wp}`
@@ -13930,7 +15454,7 @@ async function handleCreate(parsed) {
13930
15454
  const task = mgr.createTask(input);
13931
15455
  writeSuccess({ task });
13932
15456
  }
13933
- function handleList(parsed) {
15457
+ function handleList2(parsed) {
13934
15458
  const wp = requireWorkspace(parsed);
13935
15459
  const mgr = new TaskConfigManager(wp);
13936
15460
  const tasks = mgr.listTasks();
@@ -14302,7 +15826,7 @@ function requireWorkspace2(parsed) {
14302
15826
  "Missing required flag: --workspacePath"
14303
15827
  );
14304
15828
  }
14305
- if (!fs8__namespace.existsSync(wp)) {
15829
+ if (!fs9__namespace.existsSync(wp)) {
14306
15830
  throw createServicemeError(
14307
15831
  "workspace_not_found",
14308
15832
  `Workspace path does not exist: ${wp}`
@@ -14329,10 +15853,10 @@ function handleStart(parsed) {
14329
15853
  "Cannot determine CLI path for daemon spawn"
14330
15854
  );
14331
15855
  }
14332
- const logPath = path__namespace.join(wp, ".serviceme", "scheduler.log");
14333
- const logDir = path__namespace.dirname(logPath);
14334
- if (!fs8__namespace.existsSync(logDir)) {
14335
- fs8__namespace.mkdirSync(logDir, { recursive: true });
15856
+ const logPath = path11__namespace.join(wp, ".serviceme", "scheduler.log");
15857
+ const logDir = path11__namespace.dirname(logPath);
15858
+ if (!fs9__namespace.existsSync(logDir)) {
15859
+ fs9__namespace.mkdirSync(logDir, { recursive: true });
14336
15860
  }
14337
15861
  const spawnCmd = process.execPath;
14338
15862
  const spawnArgs = [
@@ -14345,7 +15869,7 @@ function handleStart(parsed) {
14345
15869
  logPath
14346
15870
  ];
14347
15871
  if (process.platform === "win32") {
14348
- fs8__namespace.appendFileSync(
15872
+ fs9__namespace.appendFileSync(
14349
15873
  logPath,
14350
15874
  `[scheduler:start] spawning daemon via hidden PowerShell Start-Process: cmd=${spawnCmd}, args=${JSON.stringify(spawnArgs)}, platform=${process.platform}, windowsHide=true
14351
15875
  `
@@ -14355,9 +15879,9 @@ function handleStart(parsed) {
14355
15879
  writeSuccess({ pid: pid2, status: "started", workspacePath: wp });
14356
15880
  return;
14357
15881
  }
14358
- const out = fs8__namespace.openSync(logPath, "a");
14359
- const err = fs8__namespace.openSync(logPath, "a");
14360
- fs8__namespace.appendFileSync(
15882
+ const out = fs9__namespace.openSync(logPath, "a");
15883
+ const err = fs9__namespace.openSync(logPath, "a");
15884
+ fs9__namespace.appendFileSync(
14361
15885
  logPath,
14362
15886
  `[scheduler:start] spawning daemon: cmd=${spawnCmd}, args=${JSON.stringify(spawnArgs)}, platform=${process.platform}, detached=true, windowsHide=true
14363
15887
  `
@@ -14468,7 +15992,7 @@ function handleStatus(parsed) {
14468
15992
  let uptimeSeconds = null;
14469
15993
  if (pid !== null) {
14470
15994
  try {
14471
- const stat2 = fs8__namespace.statSync(pidMgr.getPidPath());
15995
+ const stat2 = fs9__namespace.statSync(pidMgr.getPidPath());
14472
15996
  uptimeSeconds = Math.floor((Date.now() - stat2.mtimeMs) / 1e3);
14473
15997
  } catch {
14474
15998
  uptimeSeconds = null;
@@ -14539,6 +16063,279 @@ function writeDescribe2(action) {
14539
16063
  }
14540
16064
  }
14541
16065
 
16066
+ // src/commands/skill.ts
16067
+ init_src2();
16068
+ init_src();
16069
+ function normalizeSkillIdOrThrow2(store, remoteId) {
16070
+ try {
16071
+ return store.normalizeRemoteSkillId(remoteId);
16072
+ } catch {
16073
+ throw createServicemeError("invalid_params", `Invalid skill id: ${remoteId}`);
16074
+ }
16075
+ }
16076
+ async function runSkillCommand(parsed) {
16077
+ const action = parsed.positionals[1];
16078
+ const workspacePath = getStringFlag(parsed, "workspacePath");
16079
+ if (!workspacePath) {
16080
+ throw createServicemeError(
16081
+ "invalid_params",
16082
+ "Expected --workspacePath <path>."
16083
+ );
16084
+ }
16085
+ const store = new SkillStore({
16086
+ workspacePath,
16087
+ userSkillsRoot: path11__namespace.join(os__namespace.homedir(), ".agents", "skills")
16088
+ });
16089
+ const catalogClient = new SkillCatalogClient({
16090
+ baseUrl: getStringFlag(parsed, "baseUrl")
16091
+ });
16092
+ const reconciler = new SkillReconciler({
16093
+ skillStore: store,
16094
+ catalogClient
16095
+ });
16096
+ switch (action) {
16097
+ case "list":
16098
+ writeSuccess(await handleList3(store));
16099
+ return;
16100
+ case "install":
16101
+ writeSuccess(await handleInstall2(store, workspacePath, parsed));
16102
+ return;
16103
+ case "uninstall":
16104
+ writeSuccess(await handleUninstall2(store, workspacePath, parsed));
16105
+ return;
16106
+ case "move":
16107
+ writeSuccess(await handleMove2(store, workspacePath, parsed));
16108
+ return;
16109
+ case "marketplace":
16110
+ writeSuccess(await handleMarketplace2(store, catalogClient));
16111
+ return;
16112
+ case "find":
16113
+ writeSuccess(await handleFind(store, catalogClient, parsed));
16114
+ return;
16115
+ case "reconcile":
16116
+ writeSuccess(await handleReconcile(store, reconciler));
16117
+ return;
16118
+ case "publishable":
16119
+ writeSuccess(await handlePublishable(store, workspacePath));
16120
+ return;
16121
+ default:
16122
+ throw new Error(
16123
+ "Unsupported skill command. Use list, install, uninstall, move, marketplace, find, reconcile, or publishable."
16124
+ );
16125
+ }
16126
+ }
16127
+ async function handleList3(store) {
16128
+ const workspaceSkills = await store.listWorkspaceSkillIds();
16129
+ const userSkills = await store.listUserSkillIds();
16130
+ return {
16131
+ skills: [
16132
+ ...workspaceSkills.map((id) => ({ id, scope: "workspace" })),
16133
+ ...userSkills.map((id) => ({ id, scope: "user" }))
16134
+ ]
16135
+ };
16136
+ }
16137
+ async function handleInstall2(store, workspacePath, parsed) {
16138
+ const remoteId = getStringFlag(parsed, "id");
16139
+ if (!remoteId) {
16140
+ throw createServicemeError(
16141
+ "invalid_params",
16142
+ "Expected --id <remoteSkillId>."
16143
+ );
16144
+ }
16145
+ const skillId = normalizeSkillIdOrThrow2(store, remoteId);
16146
+ if (!getBooleanFlag(parsed, "confirmed")) {
16147
+ return {
16148
+ changed: false,
16149
+ scope: "workspace",
16150
+ skillId,
16151
+ status: "requires_confirmation",
16152
+ message: "Install requires --confirmed."
16153
+ };
16154
+ }
16155
+ const workspaceSkillDir = path11__namespace.join(
16156
+ workspacePath,
16157
+ store.getWorkspaceSkillPath(skillId)
16158
+ );
16159
+ await fs12__namespace.mkdir(workspaceSkillDir, { recursive: true });
16160
+ return {
16161
+ changed: true,
16162
+ scope: "workspace",
16163
+ skillId,
16164
+ status: "success"
16165
+ };
16166
+ }
16167
+ async function handleUninstall2(store, workspacePath, parsed) {
16168
+ const remoteId = getStringFlag(parsed, "id");
16169
+ if (!remoteId) {
16170
+ throw createServicemeError(
16171
+ "invalid_params",
16172
+ "Expected --id <remoteSkillId>."
16173
+ );
16174
+ }
16175
+ const skillId = normalizeSkillIdOrThrow2(store, remoteId);
16176
+ await fs12__namespace.rm(path11__namespace.join(workspacePath, store.getWorkspaceSkillPath(skillId)), {
16177
+ recursive: true,
16178
+ force: true
16179
+ });
16180
+ await fs12__namespace.rm(store.getUserSkillPath(skillId), {
16181
+ recursive: true,
16182
+ force: true
16183
+ });
16184
+ return {
16185
+ changed: true,
16186
+ skillId
16187
+ };
16188
+ }
16189
+ async function handleMove2(store, workspacePath, parsed) {
16190
+ const remoteId = getStringFlag(parsed, "id");
16191
+ const to = getStringFlag(parsed, "to");
16192
+ if (!remoteId || !to) {
16193
+ throw createServicemeError(
16194
+ "invalid_params",
16195
+ "Expected --id <remoteSkillId> and --to <workspace|user>."
16196
+ );
16197
+ }
16198
+ if (to !== "workspace" && to !== "user") {
16199
+ throw createServicemeError(
16200
+ "invalid_params",
16201
+ "Expected --to value to be workspace or user."
16202
+ );
16203
+ }
16204
+ const skillId = normalizeSkillIdOrThrow2(store, remoteId);
16205
+ const workspacePathForSkill = path11__namespace.join(
16206
+ workspacePath,
16207
+ store.getWorkspaceSkillPath(skillId)
16208
+ );
16209
+ const userPathForSkill = store.getUserSkillPath(skillId);
16210
+ if (to === "user") {
16211
+ await moveDirectory(workspacePathForSkill, userPathForSkill);
16212
+ await store.writeManagedUserSkillMarker(skillId);
16213
+ return {
16214
+ changed: true,
16215
+ fromScope: "workspace",
16216
+ toScope: "user",
16217
+ skillId
16218
+ };
16219
+ }
16220
+ await moveDirectory(userPathForSkill, workspacePathForSkill);
16221
+ return {
16222
+ changed: true,
16223
+ fromScope: "user",
16224
+ toScope: "workspace",
16225
+ skillId
16226
+ };
16227
+ }
16228
+ async function moveDirectory(fromPath, toPath) {
16229
+ await fs12__namespace.mkdir(path11__namespace.dirname(toPath), { recursive: true });
16230
+ try {
16231
+ await fs12__namespace.rename(fromPath, toPath);
16232
+ } catch {
16233
+ await fs12__namespace.cp(fromPath, toPath, { recursive: true });
16234
+ await fs12__namespace.rm(fromPath, { recursive: true, force: true });
16235
+ }
16236
+ }
16237
+ async function handleMarketplace2(store, catalogClient) {
16238
+ const [catalog, workspaceSkillIds, userSkillIds] = await Promise.all([
16239
+ catalogClient.getCatalog(),
16240
+ store.listWorkspaceSkillIds(),
16241
+ store.listUserSkillIds()
16242
+ ]);
16243
+ const scopesById = /* @__PURE__ */ new Map();
16244
+ for (const skillId of workspaceSkillIds) {
16245
+ scopesById.set(skillId, ["workspace"]);
16246
+ }
16247
+ for (const skillId of userSkillIds) {
16248
+ const existing = scopesById.get(skillId);
16249
+ if (existing) {
16250
+ existing.push("user");
16251
+ } else {
16252
+ scopesById.set(skillId, ["user"]);
16253
+ }
16254
+ }
16255
+ const merged = /* @__PURE__ */ new Map();
16256
+ for (const skill of catalog.skills) {
16257
+ const normalizedId = normalizeSkillIdOrThrow2(store, skill.id);
16258
+ merged.set(normalizedId, {
16259
+ id: normalizedId,
16260
+ displayName: skill.displayName,
16261
+ description: skill.description,
16262
+ source: "catalog",
16263
+ scopes: scopesById.get(normalizedId) ?? []
16264
+ });
16265
+ }
16266
+ for (const [skillId, scopes] of scopesById) {
16267
+ if (merged.has(skillId)) {
16268
+ continue;
16269
+ }
16270
+ merged.set(skillId, {
16271
+ id: skillId,
16272
+ displayName: skillId,
16273
+ description: "Local installed skill",
16274
+ source: "local",
16275
+ scopes
16276
+ });
16277
+ }
16278
+ return {
16279
+ skills: [...merged.values()].sort((a, b) => a.id.localeCompare(b.id)),
16280
+ fetchedAt: catalog.fetchedAt
16281
+ };
16282
+ }
16283
+ async function handleFind(store, catalogClient, parsed) {
16284
+ const query = getStringFlag(parsed, "query") ?? getStringFlag(parsed, "q");
16285
+ if (!query) {
16286
+ throw createServicemeError(
16287
+ "invalid_params",
16288
+ "Expected --query <text> or --q <text>."
16289
+ );
16290
+ }
16291
+ const marketplace = await handleMarketplace2(store, catalogClient);
16292
+ const loweredQuery = query.toLowerCase();
16293
+ const skills = marketplace.skills.filter(
16294
+ (skill) => skill.id.toLowerCase().includes(loweredQuery) || skill.displayName.toLowerCase().includes(loweredQuery) || skill.description.toLowerCase().includes(loweredQuery)
16295
+ );
16296
+ return {
16297
+ query,
16298
+ skills,
16299
+ total: skills.length
16300
+ };
16301
+ }
16302
+ async function handleReconcile(store, reconciler) {
16303
+ const [workspaceSkillIds, userSkillIds] = await Promise.all([
16304
+ store.listWorkspaceSkillIds(),
16305
+ store.listUserSkillIds()
16306
+ ]);
16307
+ if (workspaceSkillIds.length === 0) {
16308
+ return {
16309
+ changed: false,
16310
+ workspaceSkillIds,
16311
+ userSkillIds,
16312
+ installGate: "open"
16313
+ };
16314
+ }
16315
+ const gateCheck = await reconciler.mutate({
16316
+ skillId: workspaceSkillIds[0],
16317
+ targetScope: "workspace",
16318
+ action: "install",
16319
+ confirmed: false
16320
+ });
16321
+ return {
16322
+ changed: false,
16323
+ workspaceSkillIds,
16324
+ userSkillIds,
16325
+ installGate: gateCheck.status === "requires_confirmation" ? "requires_confirmation" : gateCheck.status === "blocked" ? "blocked" : "open"
16326
+ };
16327
+ }
16328
+ async function handlePublishable(store, workspacePath) {
16329
+ const workspaceSkillIds = await store.listWorkspaceSkillIds();
16330
+ return {
16331
+ skills: workspaceSkillIds.map((skillId) => ({
16332
+ id: skillId,
16333
+ displayName: skillId,
16334
+ path: path11__namespace.join(workspacePath, store.getWorkspaceSkillPath(skillId))
16335
+ }))
16336
+ };
16337
+ }
16338
+
14542
16339
  // src/commands/version.ts
14543
16340
  init_src();
14544
16341
  async function runVersionCommand() {
@@ -14567,6 +16364,8 @@ function printUsage() {
14567
16364
  " serviceme env check --json",
14568
16365
  " serviceme copilot doctor --json",
14569
16366
  " serviceme copilot prompt --prompt <text> [--workspace <path>] [--autopilot] [--allow-tool <tools>] [--timeout <ms>] --json",
16367
+ " serviceme skill <list|install|uninstall|move|marketplace|find|reconcile|publishable> --workspacePath <path> --json",
16368
+ " serviceme agent <list|install|uninstall|move|marketplace|permissions> --workspacePath <path> --json",
14570
16369
  " serviceme schedule <create|list|get|edit|delete|toggle|trigger|logs> --workspacePath <path> --json",
14571
16370
  " serviceme scheduler <start|stop|status> --workspacePath <path> --json"
14572
16371
  ].join("\n")}
@@ -14603,6 +16402,12 @@ async function main() {
14603
16402
  case "copilot":
14604
16403
  await runCopilotCommand(parsed);
14605
16404
  return;
16405
+ case "skill":
16406
+ await runSkillCommand(parsed);
16407
+ return;
16408
+ case "agent":
16409
+ await runAgentCommand(parsed);
16410
+ return;
14606
16411
  case "schedule":
14607
16412
  await runScheduleCommand(parsed);
14608
16413
  return;