@serviceme/devtools-cli 0.1.4 → 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 +1202 -96
  2. package/dist/cli.js +2087 -253
  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
  });
@@ -159,6 +180,7 @@ var init_env = __esm({
159
180
  "pnpm",
160
181
  "nvm",
161
182
  "nrm",
183
+ "rtk",
162
184
  "dotnet",
163
185
  "nuget"
164
186
  ];
@@ -324,6 +346,7 @@ var init_project = __esm({
324
346
  // ../../packages/serviceme-protocol/src/index.ts
325
347
  var init_src = __esm({
326
348
  "../../packages/serviceme-protocol/src/index.ts"() {
349
+ init_agent();
327
350
  init_bridge();
328
351
  init_cli();
329
352
  init_copilot();
@@ -334,6 +357,328 @@ var init_src = __esm({
334
357
  init_metadata();
335
358
  init_project();
336
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();
337
682
  }
338
683
  });
339
684
  function terminateCommandProcess(child) {
@@ -585,13 +930,25 @@ var init_copilot2 = __esm({
585
930
  });
586
931
 
587
932
  // ../../packages/serviceme-core/src/env/environmentInspector.ts
588
- var TOOL_CHECK_TIMEOUT_MS, ERROR_CODE_NOT_FOUND, EnvironmentInspector;
933
+ var DEFAULT_TOOL_CHECK_TIMEOUT_MS, TOOL_CHECK_TIMEOUT_MS, ERROR_CODE_NOT_FOUND, ERROR_CODE_TIMEOUT, EnvironmentInspector;
589
934
  var init_environmentInspector = __esm({
590
935
  "../../packages/serviceme-core/src/env/environmentInspector.ts"() {
591
936
  init_src();
592
937
  init_runCommand();
593
- TOOL_CHECK_TIMEOUT_MS = 5e3;
938
+ DEFAULT_TOOL_CHECK_TIMEOUT_MS = 5e3;
939
+ TOOL_CHECK_TIMEOUT_MS = {
940
+ nuget: 12e3,
941
+ nvm: 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
949
+ };
594
950
  ERROR_CODE_NOT_FOUND = 127;
951
+ ERROR_CODE_TIMEOUT = "ETIMEDOUT";
595
952
  EnvironmentInspector = class {
596
953
  async checkEnvironment() {
597
954
  const results = await Promise.all(
@@ -628,19 +985,39 @@ var init_environmentInspector = __esm({
628
985
  const isWindows = process.platform === "win32";
629
986
  const result = await runCommand(isWindows ? "where" : "which", {
630
987
  args: [toolName],
631
- timeoutMs: TOOL_CHECK_TIMEOUT_MS
988
+ timeoutMs: this.getToolTimeout(toolName)
989
+ });
990
+ return result.stdout.split(/\r?\n/).map((line2) => line2.trim()).find((line2) => line2.length > 0);
991
+ } catch {
992
+ return void 0;
993
+ }
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)
632
1006
  });
633
- return result.stdout.trim().split("\n")[0];
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];
634
1012
  } catch {
635
1013
  return void 0;
636
1014
  }
637
1015
  }
638
1016
  async getToolVersion(toolName) {
639
- const command = this.getVersionCommand(toolName);
640
- const isWindows = process.platform === "win32";
641
- const result = await runCommand(isWindows ? "cmd.exe" : "/bin/bash", {
642
- args: isWindows ? ["/c", command] : ["-lc", command],
643
- timeoutMs: TOOL_CHECK_TIMEOUT_MS
1017
+ const invocation = await this.getVersionInvocation(toolName);
1018
+ const result = await runCommand(invocation.command, {
1019
+ args: invocation.args,
1020
+ timeoutMs: this.getToolTimeout(toolName)
644
1021
  });
645
1022
  return this.parseVersion(toolName, result.stdout || result.stderr);
646
1023
  }
@@ -649,7 +1026,7 @@ var init_environmentInspector = __esm({
649
1026
  try {
650
1027
  const result = await runCommand("cmd.exe", {
651
1028
  args: ["/c", "nvm version"],
652
- timeoutMs: TOOL_CHECK_TIMEOUT_MS
1029
+ timeoutMs: this.getToolTimeout("nvm")
653
1030
  });
654
1031
  return {
655
1032
  installed: true,
@@ -669,7 +1046,7 @@ var init_environmentInspector = __esm({
669
1046
  "-lc",
670
1047
  'export NVM_DIR="$HOME/.nvm"; [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"; nvm --version'
671
1048
  ],
672
- timeoutMs: TOOL_CHECK_TIMEOUT_MS
1049
+ timeoutMs: this.getToolTimeout("nvm")
673
1050
  });
674
1051
  return {
675
1052
  installed: true,
@@ -694,7 +1071,7 @@ var init_environmentInspector = __esm({
694
1071
  try {
695
1072
  const result = await runCommand("dotnet", {
696
1073
  args: ["nuget", "list", "source"],
697
- timeoutMs: TOOL_CHECK_TIMEOUT_MS
1074
+ timeoutMs: this.getToolTimeout("nuget")
698
1075
  });
699
1076
  const privateSourceUrl = "http://192.168.20.209:10010/nuget";
700
1077
  if (result.stdout.includes(privateSourceUrl)) {
@@ -712,17 +1089,35 @@ var init_environmentInspector = __esm({
712
1089
  return this.handleToolCheckError(error);
713
1090
  }
714
1091
  }
715
- getVersionCommand(toolName) {
1092
+ async getVersionInvocation(toolName) {
1093
+ const isWindows = process.platform === "win32";
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
+ }
1102
+ return {
1103
+ command: "cmd.exe",
1104
+ args: ["/c", toolName, "--version"]
1105
+ };
1106
+ }
716
1107
  const commands = {
717
- git: "git --version",
718
- node: "node --version",
719
- npm: "npm --version",
720
- pnpm: "pnpm --version",
721
- nvm: "nvm --version",
722
- nrm: "nrm --version",
723
- dotnet: "dotnet --version"
1108
+ git: { command: "git", args: ["--version"] },
1109
+ node: { command: "node", args: ["--version"] },
1110
+ npm: { command: "npm", args: ["--version"] },
1111
+ pnpm: { command: "pnpm", args: ["--version"] },
1112
+ nvm: { command: "nvm", args: ["--version"] },
1113
+ nrm: { command: "nrm", args: ["--version"] },
1114
+ rtk: { command: "rtk", args: ["--version"] },
1115
+ dotnet: { command: "dotnet", args: ["--version"] }
724
1116
  };
725
- return commands[toolName] || `${toolName} --version`;
1117
+ return commands[toolName] || { command: toolName, args: ["--version"] };
1118
+ }
1119
+ getToolTimeout(toolName) {
1120
+ return TOOL_CHECK_TIMEOUT_MS[toolName] ?? DEFAULT_TOOL_CHECK_TIMEOUT_MS;
726
1121
  }
727
1122
  parseVersion(toolName, output) {
728
1123
  const cleaned = output.trim();
@@ -749,10 +1144,11 @@ var init_environmentInspector = __esm({
749
1144
  const execError = error;
750
1145
  const message = execError.message || String(error);
751
1146
  const code = execError.code;
752
- const isNotFound = message.includes("command not found") || message.includes("not recognized") || code === ERROR_CODE_NOT_FOUND;
1147
+ const isNotFound = message.includes("command not found") || message.includes("not recognized") || message.includes("ENOENT") || code === "ENOENT" || code === ERROR_CODE_NOT_FOUND;
1148
+ const isTimeout = code === ERROR_CODE_TIMEOUT || message.toLowerCase().includes("timed out");
753
1149
  return {
754
1150
  installed: false,
755
- error: isNotFound ? "Not installed" : message
1151
+ error: isNotFound ? "Not installed" : isTimeout ? "Check timed out" : message
756
1152
  };
757
1153
  }
758
1154
  };
@@ -784,7 +1180,7 @@ var init_imageTools = __esm({
784
1180
  if (!await this.pathExists(filePath)) {
785
1181
  return { valid: false };
786
1182
  }
787
- if (!SUPPORTED_FORMATS.includes(path__namespace.extname(filePath).toLowerCase())) {
1183
+ if (!SUPPORTED_FORMATS.includes(path11__namespace.extname(filePath).toLowerCase())) {
788
1184
  return { valid: false };
789
1185
  }
790
1186
  await this.getInfo(filePath, sharpModulePath);
@@ -796,7 +1192,7 @@ var init_imageTools = __esm({
796
1192
  async getInfo(imagePath, sharpModulePath) {
797
1193
  const sharp = this.loadSharp(sharpModulePath);
798
1194
  const metadata = await sharp(imagePath).metadata();
799
- const stats = await fs2__namespace.stat(imagePath);
1195
+ const stats = await fs12__namespace.stat(imagePath);
800
1196
  return {
801
1197
  width: metadata.width ?? 0,
802
1198
  height: metadata.height ?? 0,
@@ -813,7 +1209,7 @@ var init_imageTools = __esm({
813
1209
  `Invalid image file: ${imagePath}`
814
1210
  );
815
1211
  }
816
- const originalStats = await fs2__namespace.stat(imagePath);
1212
+ const originalStats = await fs12__namespace.stat(imagePath);
817
1213
  const originalSize = originalStats.size;
818
1214
  const outputPath = this.getOutputPath(imagePath, options2);
819
1215
  const compressedBuffer = await this.compressWithSharp(imagePath, options2);
@@ -828,7 +1224,7 @@ var init_imageTools = __esm({
828
1224
  outputPath: imagePath
829
1225
  };
830
1226
  }
831
- await fs2__namespace.writeFile(outputPath, compressedBuffer);
1227
+ await fs12__namespace.writeFile(outputPath, compressedBuffer);
832
1228
  return {
833
1229
  originalSize,
834
1230
  compressedSize,
@@ -839,7 +1235,7 @@ var init_imageTools = __esm({
839
1235
  async compressWithSharp(imagePath, options2) {
840
1236
  const sharp = this.loadSharp(options2.sharpModulePath);
841
1237
  let pipeline = sharp(imagePath);
842
- switch (options2.format ?? path__namespace.extname(imagePath).toLowerCase().slice(1)) {
1238
+ switch (options2.format ?? path11__namespace.extname(imagePath).toLowerCase().slice(1)) {
843
1239
  case "jpg":
844
1240
  case "jpeg":
845
1241
  pipeline = pipeline.jpeg({ quality: options2.quality });
@@ -865,14 +1261,14 @@ var init_imageTools = __esm({
865
1261
  if (options2.replaceOriginImage) {
866
1262
  return inputPath;
867
1263
  }
868
- const dir = path__namespace.dirname(inputPath);
869
- const ext = path__namespace.extname(inputPath);
870
- const name = path__namespace.basename(inputPath, ext);
871
- 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}`);
872
1268
  }
873
1269
  async pathExists(targetPath) {
874
1270
  try {
875
- await fs2__namespace.access(targetPath);
1271
+ await fs12__namespace.access(targetPath);
876
1272
  return true;
877
1273
  } catch {
878
1274
  return false;
@@ -1379,8 +1775,8 @@ var require_esprima = __commonJS({
1379
1775
  return result;
1380
1776
  };
1381
1777
  JSXParser2.prototype.lexJSX = function() {
1382
- var cp = this.scanner.source.charCodeAt(this.scanner.index);
1383
- 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) {
1384
1780
  var value = this.scanner.source[this.scanner.index++];
1385
1781
  return {
1386
1782
  type: 7,
@@ -1391,7 +1787,7 @@ var require_esprima = __commonJS({
1391
1787
  end: this.scanner.index
1392
1788
  };
1393
1789
  }
1394
- if (cp === 34 || cp === 39) {
1790
+ if (cp5 === 34 || cp5 === 39) {
1395
1791
  var start = this.scanner.index;
1396
1792
  var quote = this.scanner.source[this.scanner.index++];
1397
1793
  var str = "";
@@ -1414,7 +1810,7 @@ var require_esprima = __commonJS({
1414
1810
  end: this.scanner.index
1415
1811
  };
1416
1812
  }
1417
- if (cp === 46) {
1813
+ if (cp5 === 46) {
1418
1814
  var n1 = this.scanner.source.charCodeAt(this.scanner.index + 1);
1419
1815
  var n2 = this.scanner.source.charCodeAt(this.scanner.index + 2);
1420
1816
  var value = n1 === 46 && n2 === 46 ? "..." : ".";
@@ -1429,7 +1825,7 @@ var require_esprima = __commonJS({
1429
1825
  end: this.scanner.index
1430
1826
  };
1431
1827
  }
1432
- if (cp === 96) {
1828
+ if (cp5 === 96) {
1433
1829
  return {
1434
1830
  type: 10,
1435
1831
  value: "",
@@ -1439,7 +1835,7 @@ var require_esprima = __commonJS({
1439
1835
  end: this.scanner.index
1440
1836
  };
1441
1837
  }
1442
- if (character_1.Character.isIdentifierStart(cp) && cp !== 92) {
1838
+ if (character_1.Character.isIdentifierStart(cp5) && cp5 !== 92) {
1443
1839
  var start = this.scanner.index;
1444
1840
  ++this.scanner.index;
1445
1841
  while (!this.scanner.eof()) {
@@ -1768,33 +2164,33 @@ var require_esprima = __commonJS({
1768
2164
  };
1769
2165
  exports2.Character = {
1770
2166
  /* tslint:disable:no-bitwise */
1771
- fromCodePoint: function(cp) {
1772
- 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));
1773
2169
  },
1774
2170
  // https://tc39.github.io/ecma262/#sec-white-space
1775
- isWhiteSpace: function(cp) {
1776
- 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;
1777
2173
  },
1778
2174
  // https://tc39.github.io/ecma262/#sec-line-terminators
1779
- isLineTerminator: function(cp) {
1780
- return cp === 10 || cp === 13 || cp === 8232 || cp === 8233;
2175
+ isLineTerminator: function(cp5) {
2176
+ return cp5 === 10 || cp5 === 13 || cp5 === 8232 || cp5 === 8233;
1781
2177
  },
1782
2178
  // https://tc39.github.io/ecma262/#sec-names-and-keywords
1783
- isIdentifierStart: function(cp) {
1784
- 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));
1785
2181
  },
1786
- isIdentifierPart: function(cp) {
1787
- 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));
1788
2184
  },
1789
2185
  // https://tc39.github.io/ecma262/#sec-literals-numeric-literals
1790
- isDecimalDigit: function(cp) {
1791
- return cp >= 48 && cp <= 57;
2186
+ isDecimalDigit: function(cp5) {
2187
+ return cp5 >= 48 && cp5 <= 57;
1792
2188
  },
1793
- isHexDigit: function(cp) {
1794
- 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;
1795
2191
  },
1796
- isOctalDigit: function(cp) {
1797
- return cp >= 48 && cp <= 55;
2192
+ isOctalDigit: function(cp5) {
2193
+ return cp5 >= 48 && cp5 <= 55;
1798
2194
  }
1799
2195
  };
1800
2196
  },
@@ -5844,15 +6240,15 @@ var require_esprima = __commonJS({
5844
6240
  }
5845
6241
  };
5846
6242
  Scanner2.prototype.codePointAt = function(i) {
5847
- var cp = this.source.charCodeAt(i);
5848
- if (cp >= 55296 && cp <= 56319) {
6243
+ var cp5 = this.source.charCodeAt(i);
6244
+ if (cp5 >= 55296 && cp5 <= 56319) {
5849
6245
  var second = this.source.charCodeAt(i + 1);
5850
6246
  if (second >= 56320 && second <= 57343) {
5851
- var first = cp;
5852
- cp = (first - 55296) * 1024 + second - 56320 + 65536;
6247
+ var first = cp5;
6248
+ cp5 = (first - 55296) * 1024 + second - 56320 + 65536;
5853
6249
  }
5854
6250
  }
5855
- return cp;
6251
+ return cp5;
5856
6252
  };
5857
6253
  Scanner2.prototype.scanHexEscape = function(prefix) {
5858
6254
  var len = prefix === "u" ? 4 : 2;
@@ -5904,11 +6300,11 @@ var require_esprima = __commonJS({
5904
6300
  return this.source.slice(start, this.index);
5905
6301
  };
5906
6302
  Scanner2.prototype.getComplexIdentifier = function() {
5907
- var cp = this.codePointAt(this.index);
5908
- var id = character_1.Character.fromCodePoint(cp);
6303
+ var cp5 = this.codePointAt(this.index);
6304
+ var id = character_1.Character.fromCodePoint(cp5);
5909
6305
  this.index += id.length;
5910
6306
  var ch;
5911
- if (cp === 92) {
6307
+ if (cp5 === 92) {
5912
6308
  if (this.source.charCodeAt(this.index) !== 117) {
5913
6309
  this.throwUnexpectedToken();
5914
6310
  }
@@ -5925,14 +6321,14 @@ var require_esprima = __commonJS({
5925
6321
  id = ch;
5926
6322
  }
5927
6323
  while (!this.eof()) {
5928
- cp = this.codePointAt(this.index);
5929
- if (!character_1.Character.isIdentifierPart(cp)) {
6324
+ cp5 = this.codePointAt(this.index);
6325
+ if (!character_1.Character.isIdentifierPart(cp5)) {
5930
6326
  break;
5931
6327
  }
5932
- ch = character_1.Character.fromCodePoint(cp);
6328
+ ch = character_1.Character.fromCodePoint(cp5);
5933
6329
  id += ch;
5934
6330
  this.index += ch.length;
5935
- if (cp === 92) {
6331
+ if (cp5 === 92) {
5936
6332
  id = id.substr(0, id.length - 1);
5937
6333
  if (this.source.charCodeAt(this.index) !== 117) {
5938
6334
  this.throwUnexpectedToken();
@@ -6558,29 +6954,29 @@ var require_esprima = __commonJS({
6558
6954
  end: this.index
6559
6955
  };
6560
6956
  }
6561
- var cp = this.source.charCodeAt(this.index);
6562
- if (character_1.Character.isIdentifierStart(cp)) {
6957
+ var cp5 = this.source.charCodeAt(this.index);
6958
+ if (character_1.Character.isIdentifierStart(cp5)) {
6563
6959
  return this.scanIdentifier();
6564
6960
  }
6565
- if (cp === 40 || cp === 41 || cp === 59) {
6961
+ if (cp5 === 40 || cp5 === 41 || cp5 === 59) {
6566
6962
  return this.scanPunctuator();
6567
6963
  }
6568
- if (cp === 39 || cp === 34) {
6964
+ if (cp5 === 39 || cp5 === 34) {
6569
6965
  return this.scanStringLiteral();
6570
6966
  }
6571
- if (cp === 46) {
6967
+ if (cp5 === 46) {
6572
6968
  if (character_1.Character.isDecimalDigit(this.source.charCodeAt(this.index + 1))) {
6573
6969
  return this.scanNumericLiteral();
6574
6970
  }
6575
6971
  return this.scanPunctuator();
6576
6972
  }
6577
- if (character_1.Character.isDecimalDigit(cp)) {
6973
+ if (character_1.Character.isDecimalDigit(cp5)) {
6578
6974
  return this.scanNumericLiteral();
6579
6975
  }
6580
- if (cp === 96 || cp === 125 && this.curlyStack[this.curlyStack.length - 1] === "${") {
6976
+ if (cp5 === 96 || cp5 === 125 && this.curlyStack[this.curlyStack.length - 1] === "${") {
6581
6977
  return this.scanTemplate();
6582
6978
  }
6583
- if (cp >= 55296 && cp < 57343) {
6979
+ if (cp5 >= 55296 && cp5 < 57343) {
6584
6980
  if (character_1.Character.isIdentifierStart(this.codePointAt(this.index))) {
6585
6981
  return this.scanIdentifier();
6586
6982
  }
@@ -8758,10 +9154,10 @@ var require_stringify = __commonJS({
8758
9154
  replacer = null;
8759
9155
  indent = EMPTY;
8760
9156
  };
8761
- 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;
8762
9158
  var join_content = (inside, value, gap) => {
8763
9159
  const comment = process_comments(value, PREFIX_BEFORE, gap + indent, true);
8764
- return join9(comment, inside, gap);
9160
+ return join15(comment, inside, gap);
8765
9161
  };
8766
9162
  var array_stringify = (value, gap) => {
8767
9163
  const deeper_gap = gap + indent;
@@ -8772,7 +9168,7 @@ var require_stringify = __commonJS({
8772
9168
  if (i !== 0) {
8773
9169
  inside += COMMA;
8774
9170
  }
8775
- const before = join9(
9171
+ const before = join15(
8776
9172
  after_comma,
8777
9173
  process_comments(value, BEFORE(i), deeper_gap),
8778
9174
  deeper_gap
@@ -8782,7 +9178,7 @@ var require_stringify = __commonJS({
8782
9178
  inside += process_comments(value, AFTER_VALUE(i), deeper_gap);
8783
9179
  after_comma = process_comments(value, AFTER(i), deeper_gap);
8784
9180
  }
8785
- inside += join9(
9181
+ inside += join15(
8786
9182
  after_comma,
8787
9183
  process_comments(value, PREFIX_AFTER, deeper_gap),
8788
9184
  deeper_gap
@@ -8807,7 +9203,7 @@ var require_stringify = __commonJS({
8807
9203
  inside += COMMA;
8808
9204
  }
8809
9205
  first = false;
8810
- const before = join9(
9206
+ const before = join15(
8811
9207
  after_comma,
8812
9208
  process_comments(value, BEFORE(key2), deeper_gap),
8813
9209
  deeper_gap
@@ -8817,7 +9213,7 @@ var require_stringify = __commonJS({
8817
9213
  after_comma = process_comments(value, AFTER(key2), deeper_gap);
8818
9214
  };
8819
9215
  keys.forEach(iteratee);
8820
- inside += join9(
9216
+ inside += join15(
8821
9217
  after_comma,
8822
9218
  process_comments(value, PREFIX_AFTER, deeper_gap),
8823
9219
  deeper_gap
@@ -10195,7 +10591,7 @@ var require_pend = __commonJS({
10195
10591
  // ../../node_modules/.pnpm/yauzl@3.2.0/node_modules/yauzl/fd-slicer.js
10196
10592
  var require_fd_slicer = __commonJS({
10197
10593
  "../../node_modules/.pnpm/yauzl@3.2.0/node_modules/yauzl/fd-slicer.js"(exports$1) {
10198
- var fs13 = __require("fs");
10594
+ var fs19 = __require("fs");
10199
10595
  var util2 = __require("util");
10200
10596
  var stream = __require("stream");
10201
10597
  var Readable = stream.Readable;
@@ -10220,7 +10616,7 @@ var require_fd_slicer = __commonJS({
10220
10616
  FdSlicer.prototype.read = function(buffer2, offset, length, position, callback) {
10221
10617
  var self = this;
10222
10618
  self.pend.go(function(cb) {
10223
- 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) {
10224
10620
  cb();
10225
10621
  callback(err, bytesRead, buffer3);
10226
10622
  });
@@ -10229,7 +10625,7 @@ var require_fd_slicer = __commonJS({
10229
10625
  FdSlicer.prototype.write = function(buffer2, offset, length, position, callback) {
10230
10626
  var self = this;
10231
10627
  self.pend.go(function(cb) {
10232
- 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) {
10233
10629
  cb();
10234
10630
  callback(err, written, buffer3);
10235
10631
  });
@@ -10250,7 +10646,7 @@ var require_fd_slicer = __commonJS({
10250
10646
  if (self.refCount > 0) return;
10251
10647
  if (self.refCount < 0) throw new Error("invalid unref");
10252
10648
  if (self.autoClose) {
10253
- fs13.close(self.fd, onCloseDone);
10649
+ fs19.close(self.fd, onCloseDone);
10254
10650
  }
10255
10651
  function onCloseDone(err) {
10256
10652
  if (err) {
@@ -10287,7 +10683,7 @@ var require_fd_slicer = __commonJS({
10287
10683
  self.context.pend.go(function(cb) {
10288
10684
  if (self.destroyed) return cb();
10289
10685
  var buffer2 = Buffer.allocUnsafe(toRead);
10290
- 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) {
10291
10687
  if (err) {
10292
10688
  self.destroy(err);
10293
10689
  } else if (bytesRead === 0) {
@@ -10334,7 +10730,7 @@ var require_fd_slicer = __commonJS({
10334
10730
  }
10335
10731
  self.context.pend.go(function(cb) {
10336
10732
  if (self.destroyed) return cb();
10337
- 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) {
10338
10734
  if (err2) {
10339
10735
  self.destroy();
10340
10736
  cb();
@@ -10772,7 +11168,7 @@ var require_buffer_crc32 = __commonJS({
10772
11168
  // ../../node_modules/.pnpm/yauzl@3.2.0/node_modules/yauzl/index.js
10773
11169
  var require_yauzl = __commonJS({
10774
11170
  "../../node_modules/.pnpm/yauzl@3.2.0/node_modules/yauzl/index.js"(exports$1) {
10775
- var fs13 = __require("fs");
11171
+ var fs19 = __require("fs");
10776
11172
  var zlib = __require("zlib");
10777
11173
  var fd_slicer = require_fd_slicer();
10778
11174
  var crc32 = require_buffer_crc32();
@@ -10793,7 +11189,7 @@ var require_yauzl = __commonJS({
10793
11189
  exports$1.Entry = Entry;
10794
11190
  exports$1.LocalFileHeader = LocalFileHeader;
10795
11191
  exports$1.RandomAccessReader = RandomAccessReader;
10796
- function open2(path9, options2, callback) {
11192
+ function open2(path15, options2, callback) {
10797
11193
  if (typeof options2 === "function") {
10798
11194
  callback = options2;
10799
11195
  options2 = null;
@@ -10805,10 +11201,10 @@ var require_yauzl = __commonJS({
10805
11201
  if (options2.validateEntrySizes == null) options2.validateEntrySizes = true;
10806
11202
  if (options2.strictFileNames == null) options2.strictFileNames = false;
10807
11203
  if (callback == null) callback = defaultCallback;
10808
- fs13.open(path9, "r", function(err, fd) {
11204
+ fs19.open(path15, "r", function(err, fd) {
10809
11205
  if (err) return callback(err);
10810
11206
  fromFd(fd, options2, function(err2, zipfile) {
10811
- if (err2) fs13.close(fd, defaultCallback);
11207
+ if (err2) fs19.close(fd, defaultCallback);
10812
11208
  callback(err2, zipfile);
10813
11209
  });
10814
11210
  });
@@ -10825,7 +11221,7 @@ var require_yauzl = __commonJS({
10825
11221
  if (options2.validateEntrySizes == null) options2.validateEntrySizes = true;
10826
11222
  if (options2.strictFileNames == null) options2.strictFileNames = false;
10827
11223
  if (callback == null) callback = defaultCallback;
10828
- fs13.fstat(fd, function(err, stats) {
11224
+ fs19.fstat(fd, function(err, stats) {
10829
11225
  if (err) return callback(err);
10830
11226
  var reader = fd_slicer.createFromFd(fd, { autoClose: true });
10831
11227
  fromRandomAccessReader(reader, stats.size, options2, callback);
@@ -11523,12 +11919,12 @@ var init_fileUtils = __esm({
11523
11919
  zipfile.readEntry();
11524
11920
  zipfile.on("entry", (entry) => {
11525
11921
  if (/\/$/.test(entry.fileName)) {
11526
- void fs2.mkdir(path.join(dest, entry.fileName), { recursive: true }).then(() => {
11922
+ void fs12.mkdir(path11.join(dest, entry.fileName), { recursive: true }).then(() => {
11527
11923
  zipfile.readEntry();
11528
11924
  }).catch(reject);
11529
11925
  } else {
11530
- const outputPath = path.join(dest, entry.fileName);
11531
- 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(() => {
11532
11928
  zipfile.openReadStream(
11533
11929
  entry,
11534
11930
  (streamError, readStream) => {
@@ -11537,7 +11933,7 @@ var init_fileUtils = __esm({
11537
11933
  return reject(
11538
11934
  new Error("Failed to open zip entry stream.")
11539
11935
  );
11540
- const writeStream = fs8.createWriteStream(outputPath);
11936
+ const writeStream = fs9.createWriteStream(outputPath);
11541
11937
  readStream.on("error", reject);
11542
11938
  writeStream.on("error", reject);
11543
11939
  writeStream.on("close", () => {
@@ -11561,58 +11957,58 @@ var init_fileUtils = __esm({
11561
11957
  };
11562
11958
  tryLstat = async (targetPath) => {
11563
11959
  try {
11564
- return await fs2.lstat(targetPath);
11960
+ return await fs12.lstat(targetPath);
11565
11961
  } catch {
11566
11962
  return null;
11567
11963
  }
11568
11964
  };
11569
11965
  mergeEntry = async (sourcePath, destPath, overwrite) => {
11570
- const sourceStat = await fs2.lstat(sourcePath);
11966
+ const sourceStat = await fs12.lstat(sourcePath);
11571
11967
  const destStat = await tryLstat(destPath);
11572
11968
  if (sourceStat.isDirectory()) {
11573
11969
  if (destStat && !destStat.isDirectory()) {
11574
11970
  if (!overwrite) {
11575
- await fs2.rm(sourcePath, { recursive: true, force: true });
11971
+ await fs12.rm(sourcePath, { recursive: true, force: true });
11576
11972
  return;
11577
11973
  }
11578
- await fs2.rm(destPath, { recursive: true, force: true });
11974
+ await fs12.rm(destPath, { recursive: true, force: true });
11579
11975
  }
11580
- await fs2.mkdir(destPath, { recursive: true });
11581
- const children = await fs2.readdir(sourcePath);
11976
+ await fs12.mkdir(destPath, { recursive: true });
11977
+ const children = await fs12.readdir(sourcePath);
11582
11978
  for (const child of children) {
11583
11979
  await mergeEntry(
11584
- path.join(sourcePath, child),
11585
- path.join(destPath, child),
11980
+ path11.join(sourcePath, child),
11981
+ path11.join(destPath, child),
11586
11982
  overwrite
11587
11983
  );
11588
11984
  }
11589
- await fs2.rm(sourcePath, { recursive: true, force: true });
11985
+ await fs12.rm(sourcePath, { recursive: true, force: true });
11590
11986
  return;
11591
11987
  }
11592
11988
  if (destStat) {
11593
11989
  if (!overwrite) {
11594
- await fs2.rm(sourcePath, { recursive: true, force: true });
11990
+ await fs12.rm(sourcePath, { recursive: true, force: true });
11595
11991
  return;
11596
11992
  }
11597
- await fs2.rm(destPath, { recursive: true, force: true });
11993
+ await fs12.rm(destPath, { recursive: true, force: true });
11598
11994
  }
11599
11995
  try {
11600
- await fs2.rename(sourcePath, destPath);
11996
+ await fs12.rename(sourcePath, destPath);
11601
11997
  } catch {
11602
- await fs2.copyFile(sourcePath, destPath);
11603
- await fs2.rm(sourcePath, { recursive: true, force: true });
11998
+ await fs12.copyFile(sourcePath, destPath);
11999
+ await fs12.rm(sourcePath, { recursive: true, force: true });
11604
12000
  }
11605
12001
  };
11606
12002
  moveFiles = async (sourceDir, destDir, overwrite = false) => {
11607
- await fs2.mkdir(destDir, { recursive: true });
11608
- const files = await fs2.readdir(sourceDir);
12003
+ await fs12.mkdir(destDir, { recursive: true });
12004
+ const files = await fs12.readdir(sourceDir);
11609
12005
  for (const file of files) {
11610
- const sourceFile = path.join(sourceDir, file);
11611
- const destFile = path.join(destDir, file);
12006
+ const sourceFile = path11.join(sourceDir, file);
12007
+ const destFile = path11.join(destDir, file);
11612
12008
  if (!overwrite) {
11613
12009
  try {
11614
- await fs2.access(destFile, fs8.constants.F_OK);
11615
- 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 });
11616
12012
  continue;
11617
12013
  } catch {
11618
12014
  }
@@ -11634,10 +12030,10 @@ var init_projectTools = __esm({
11634
12030
  ProjectTools = class {
11635
12031
  async extractTemplate(zipPath, workspacePath, tempExtractDir, input) {
11636
12032
  await unzipFile(zipPath, tempExtractDir);
11637
- let sourceDir = path__namespace.join(tempExtractDir, input.extractedDirName);
12033
+ let sourceDir = path11__namespace.join(tempExtractDir, input.extractedDirName);
11638
12034
  let actualDirName = input.extractedDirName;
11639
12035
  if (!await this.pathExists(sourceDir)) {
11640
- const entries = await fs2__namespace.readdir(tempExtractDir, { withFileTypes: true });
12036
+ const entries = await fs12__namespace.readdir(tempExtractDir, { withFileTypes: true });
11641
12037
  const directories = entries.filter(
11642
12038
  (entry) => entry.isDirectory() && !entry.name.startsWith(".")
11643
12039
  );
@@ -11649,7 +12045,7 @@ var init_projectTools = __esm({
11649
12045
  );
11650
12046
  if (selectedDirectory) {
11651
12047
  actualDirName = selectedDirectory;
11652
- sourceDir = path__namespace.join(tempExtractDir, actualDirName);
12048
+ sourceDir = path11__namespace.join(tempExtractDir, actualDirName);
11653
12049
  } else if (directories.length === 0) {
11654
12050
  throw new Error(
11655
12051
  `No directory found after extraction. Expected directory: ${input.extractedDirName}`
@@ -11707,7 +12103,7 @@ var init_projectTools = __esm({
11707
12103
  } else {
11708
12104
  for (const scriptPath of scripts) {
11709
12105
  try {
11710
- await fs2__namespace.chmod(scriptPath, 493);
12106
+ await fs12__namespace.chmod(scriptPath, 493);
11711
12107
  updatedCount += 1;
11712
12108
  } catch {
11713
12109
  }
@@ -11755,12 +12151,12 @@ var init_projectTools = __esm({
11755
12151
  const results = [];
11756
12152
  let entries;
11757
12153
  try {
11758
- entries = await fs2__namespace.readdir(dir, { withFileTypes: true });
12154
+ entries = await fs12__namespace.readdir(dir, { withFileTypes: true });
11759
12155
  } catch {
11760
12156
  return results;
11761
12157
  }
11762
12158
  for (const entry of entries) {
11763
- const fullPath = path__namespace.join(dir, entry.name);
12159
+ const fullPath = path11__namespace.join(dir, entry.name);
11764
12160
  if (entry.isDirectory() && entry.name !== "node_modules" && !entry.name.startsWith(".")) {
11765
12161
  results.push(...await this.findScripts(fullPath, extensions));
11766
12162
  } else if (entry.isFile() && extensions.some((ext) => entry.name.endsWith(ext))) {
@@ -11771,7 +12167,7 @@ var init_projectTools = __esm({
11771
12167
  }
11772
12168
  async pathExists(targetPath) {
11773
12169
  try {
11774
- await fs2__namespace.access(targetPath);
12170
+ await fs12__namespace.access(targetPath);
11775
12171
  return true;
11776
12172
  } catch {
11777
12173
  return false;
@@ -11790,7 +12186,7 @@ var init_projectTools = __esm({
11790
12186
  const matches = [];
11791
12187
  for (const directoryName of directoryNames) {
11792
12188
  if (await this.directoryMatchesProjectPattern(
11793
- path__namespace.join(tempExtractDir, directoryName),
12189
+ path11__namespace.join(tempExtractDir, directoryName),
11794
12190
  projectFilePattern
11795
12191
  )) {
11796
12192
  matches.push(directoryName);
@@ -11802,7 +12198,7 @@ var init_projectTools = __esm({
11802
12198
  return null;
11803
12199
  }
11804
12200
  async directoryMatchesProjectPattern(directoryPath, projectFilePattern) {
11805
- const entries = await fs2__namespace.readdir(directoryPath);
12201
+ const entries = await fs12__namespace.readdir(directoryPath);
11806
12202
  if (projectFilePattern.includes("*")) {
11807
12203
  const regex = new RegExp(`^${projectFilePattern.replace("*", ".*")}$`);
11808
12204
  return entries.some((entry) => regex.test(entry));
@@ -11820,10 +12216,10 @@ var init_DaemonLogger = __esm({
11820
12216
  MAX_LOG_SIZE = 1024 * 1024;
11821
12217
  DaemonLogger = class {
11822
12218
  constructor(workspacePath) {
11823
- this.logPath = path__namespace.join(workspacePath, CONFIG_DIR, LOG_FILE);
11824
- const dir = path__namespace.dirname(this.logPath);
11825
- if (!fs8__namespace.existsSync(dir)) {
11826
- 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 });
11827
12223
  }
11828
12224
  }
11829
12225
  getLogPath() {
@@ -11834,16 +12230,16 @@ var init_DaemonLogger = __esm({
11834
12230
  const line2 = `[${ts}] [${level.toUpperCase()}] ${message}
11835
12231
  `;
11836
12232
  this.rotateIfNeeded();
11837
- fs8__namespace.appendFileSync(this.logPath, line2, "utf-8");
12233
+ fs9__namespace.appendFileSync(this.logPath, line2, "utf-8");
11838
12234
  }
11839
12235
  rotateIfNeeded() {
11840
12236
  try {
11841
- const stats = fs8__namespace.statSync(this.logPath);
12237
+ const stats = fs9__namespace.statSync(this.logPath);
11842
12238
  if (stats.size > MAX_LOG_SIZE) {
11843
- const content = fs8__namespace.readFileSync(this.logPath, "utf-8");
12239
+ const content = fs9__namespace.readFileSync(this.logPath, "utf-8");
11844
12240
  const halfIdx = content.indexOf("\n", Math.floor(content.length / 2));
11845
12241
  if (halfIdx > 0) {
11846
- fs8__namespace.writeFileSync(this.logPath, content.slice(halfIdx + 1), "utf-8");
12242
+ fs9__namespace.writeFileSync(this.logPath, content.slice(halfIdx + 1), "utf-8");
11847
12243
  }
11848
12244
  }
11849
12245
  } catch {
@@ -11859,27 +12255,27 @@ var init_PidManager = __esm({
11859
12255
  PID_FILE = "scheduler.pid";
11860
12256
  PidManager = class {
11861
12257
  constructor(workspacePath) {
11862
- this.pidPath = path__namespace.join(workspacePath, CONFIG_DIR2, PID_FILE);
12258
+ this.pidPath = path11__namespace.join(workspacePath, CONFIG_DIR2, PID_FILE);
11863
12259
  }
11864
12260
  getPidPath() {
11865
12261
  return this.pidPath;
11866
12262
  }
11867
12263
  writePid(pid) {
11868
- const dir = path__namespace.dirname(this.pidPath);
11869
- if (!fs8__namespace.existsSync(dir)) {
11870
- 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 });
11871
12267
  }
11872
- fs8__namespace.writeFileSync(this.pidPath, String(pid), "utf-8");
12268
+ fs9__namespace.writeFileSync(this.pidPath, String(pid), "utf-8");
11873
12269
  }
11874
12270
  readPid() {
11875
- if (!fs8__namespace.existsSync(this.pidPath)) return null;
11876
- 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();
11877
12273
  const pid = Number.parseInt(raw, 10);
11878
12274
  return Number.isNaN(pid) ? null : pid;
11879
12275
  }
11880
12276
  removePid() {
11881
- if (fs8__namespace.existsSync(this.pidPath)) {
11882
- fs8__namespace.unlinkSync(this.pidPath);
12277
+ if (fs9__namespace.existsSync(this.pidPath)) {
12278
+ fs9__namespace.unlinkSync(this.pidPath);
11883
12279
  }
11884
12280
  }
11885
12281
  isProcessRunning(pid) {
@@ -11934,11 +12330,35 @@ function redactArgs(args) {
11934
12330
  function writeDiagnostic(message) {
11935
12331
  const logPath = process.env.SERVICEME_SCHEDULER_LOG_PATH;
11936
12332
  if (logPath) {
11937
- fs8__namespace.appendFileSync(logPath, message);
12333
+ fs9__namespace.appendFileSync(logPath, message);
11938
12334
  return;
11939
12335
  }
11940
12336
  process.stderr.write(message);
11941
12337
  }
12338
+ function resolveGithubCopilotCliExecution(payload) {
12339
+ const args = ["copilot", "prompt", "--prompt", payload.prompt];
12340
+ if (payload.autopilot) {
12341
+ args.push("--autopilot");
12342
+ }
12343
+ if (payload.allowTools && payload.allowTools.length > 0) {
12344
+ args.push("--allow-tools", payload.allowTools.join(","));
12345
+ }
12346
+ if (payload.model) {
12347
+ args.push("--model", payload.model);
12348
+ }
12349
+ if (payload.agent) {
12350
+ args.push("--agent", payload.agent);
12351
+ }
12352
+ args.push("--timeout", String(payload.timeout ?? 0));
12353
+ return {
12354
+ command: "serviceme",
12355
+ args,
12356
+ cwd: payload.workspace,
12357
+ timeoutMs: resolveConfiguredTimeoutMs(payload.timeout, DEFAULT_TIMEOUT_MS2),
12358
+ diagnosticArgs: redactArgs(args),
12359
+ promptLen: payload.prompt.length
12360
+ };
12361
+ }
11942
12362
  var MAX_OUTPUT_BYTES, DEFAULT_TIMEOUT_MS2, GithubCopilotCliExecutor;
11943
12363
  var init_GithubCopilotCliExecutor = __esm({
11944
12364
  "../../packages/serviceme-core/src/scheduled-tasks/executors/GithubCopilotCliExecutor.ts"() {
@@ -11968,7 +12388,7 @@ var init_GithubCopilotCliExecutor = __esm({
11968
12388
  }
11969
12389
  executeStreaming(payload, onOutput, abortSignal) {
11970
12390
  const p = payload;
11971
- const timeoutMs = resolveConfiguredTimeoutMs(p.timeout, DEFAULT_TIMEOUT_MS2);
12391
+ const execution = resolveGithubCopilotCliExecution(p);
11972
12392
  let resolve;
11973
12393
  const resultPromise = new Promise((r) => {
11974
12394
  resolve = r;
@@ -11990,26 +12410,12 @@ var init_GithubCopilotCliExecutor = __esm({
11990
12410
  }
11991
12411
  };
11992
12412
  }
11993
- const args = ["copilot", "prompt", "--prompt", p.prompt];
11994
- if (p.autopilot) {
11995
- args.push("--autopilot");
11996
- }
11997
- if (p.allowTools && p.allowTools.length > 0) {
11998
- args.push("--allow-tools", p.allowTools.join(","));
11999
- }
12000
- if (p.model) {
12001
- args.push("--model", p.model);
12002
- }
12003
- if (p.agent) {
12004
- args.push("--agent", p.agent);
12005
- }
12006
- args.push("--timeout", String(p.timeout ?? 0));
12007
12413
  writeDiagnostic(
12008
- `[GithubCopilotCliExecutor] spawn: command=serviceme, args=${JSON.stringify(redactArgs(args))}, promptLen=${p.prompt.length}, cwd=${p.workspace ?? "(default)"}, platform=${process.platform}, windowsHide=true, pid=${process.pid}
12414
+ `[GithubCopilotCliExecutor] spawn: command=${execution.command}, args=${JSON.stringify(execution.diagnosticArgs)}, promptLen=${execution.promptLen}, cwd=${execution.cwd ?? "(default)"}, platform=${process.platform}, windowsHide=true, pid=${process.pid}
12009
12415
  `
12010
12416
  );
12011
- const child = child_process.spawn("serviceme", args, {
12012
- cwd: p.workspace,
12417
+ const child = child_process.spawn(execution.command, execution.args, {
12418
+ cwd: execution.cwd,
12013
12419
  stdio: ["ignore", "pipe", "pipe"],
12014
12420
  windowsHide: true
12015
12421
  });
@@ -12019,6 +12425,7 @@ var init_GithubCopilotCliExecutor = __esm({
12019
12425
  `
12020
12426
  );
12021
12427
  }
12428
+ const timeoutMs = execution.timeoutMs;
12022
12429
  const timer = timeoutMs != null ? setTimeout(() => {
12023
12430
  child.kill("SIGTERM");
12024
12431
  setTimeout(() => {
@@ -12148,7 +12555,7 @@ ${body}`.trim()
12148
12555
  function resolveShellExecution(script, options2 = {}) {
12149
12556
  const platform = options2.platform ?? process.platform;
12150
12557
  const env = options2.env ?? process.env;
12151
- const fileExists = options2.fileExists ?? fs8__namespace.existsSync;
12558
+ const fileExists = options2.fileExists ?? fs9__namespace.existsSync;
12152
12559
  if (platform === "win32") {
12153
12560
  const posixShell = usesPosixShellSyntax(script) ? findWindowsPosixShell(env, fileExists) : null;
12154
12561
  if (posixShell) {
@@ -12193,10 +12600,10 @@ function findWindowsPosixShell(env, fileExists) {
12193
12600
  if (fileExists(candidate)) return candidate;
12194
12601
  }
12195
12602
  const pathValue = env.Path ?? env.PATH ?? "";
12196
- for (const dir of pathValue.split(path__namespace.win32.delimiter)) {
12603
+ for (const dir of pathValue.split(path11__namespace.win32.delimiter)) {
12197
12604
  if (!dir) continue;
12198
12605
  for (const executable of POSIX_SHELL_CANDIDATES) {
12199
- const candidate = path__namespace.win32.join(dir, executable);
12606
+ const candidate = path11__namespace.win32.join(dir, executable);
12200
12607
  if (fileExists(candidate) && !isWindowsWslLauncher(candidate)) {
12201
12608
  return candidate;
12202
12609
  }
@@ -12205,13 +12612,13 @@ function findWindowsPosixShell(env, fileExists) {
12205
12612
  return null;
12206
12613
  }
12207
12614
  function isWindowsWslLauncher(candidate) {
12208
- const normalized = path__namespace.win32.normalize(candidate).toLowerCase();
12615
+ const normalized = path11__namespace.win32.normalize(candidate).toLowerCase();
12209
12616
  return normalized.endsWith("\\windows\\system32\\bash.exe") || normalized.endsWith("\\windows\\syswow64\\bash.exe");
12210
12617
  }
12211
12618
  function writeDiagnostic2(message) {
12212
12619
  const logPath = process.env.SERVICEME_SCHEDULER_LOG_PATH;
12213
12620
  if (logPath) {
12214
- fs8__namespace.appendFileSync(logPath, message);
12621
+ fs9__namespace.appendFileSync(logPath, message);
12215
12622
  return;
12216
12623
  }
12217
12624
  process.stderr.write(message);
@@ -12350,7 +12757,7 @@ var init_ShellExecutor = __esm({
12350
12757
  function isStreamingTaskExecutor(executor) {
12351
12758
  return "executeStreaming" in executor && typeof executor.executeStreaming === "function";
12352
12759
  }
12353
- var init_types = __esm({
12760
+ var init_types2 = __esm({
12354
12761
  "../../packages/serviceme-core/src/scheduled-tasks/executors/types.ts"() {
12355
12762
  }
12356
12763
  });
@@ -12369,7 +12776,7 @@ var init_executors = __esm({
12369
12776
  init_GithubCopilotCliExecutor();
12370
12777
  init_HttpRequestExecutor();
12371
12778
  init_ShellExecutor();
12372
- init_types();
12779
+ init_types2();
12373
12780
  executors = {
12374
12781
  shell: new ShellExecutor(),
12375
12782
  http_request: new HttpRequestExecutor(),
@@ -12416,27 +12823,27 @@ var init_TaskConfigManager = __esm({
12416
12823
  CONFIG_FILE = "scheduled-tasks.json";
12417
12824
  TaskConfigManager = class {
12418
12825
  constructor(workspacePath) {
12419
- this.configPath = path__namespace.join(workspacePath, CONFIG_DIR3, CONFIG_FILE);
12826
+ this.configPath = path11__namespace.join(workspacePath, CONFIG_DIR3, CONFIG_FILE);
12420
12827
  }
12421
12828
  getConfigPath() {
12422
12829
  return this.configPath;
12423
12830
  }
12424
12831
  readConfig() {
12425
- if (!fs8__namespace.existsSync(this.configPath)) {
12832
+ if (!fs9__namespace.existsSync(this.configPath)) {
12426
12833
  return emptyConfig();
12427
12834
  }
12428
- const raw = fs8__namespace.readFileSync(this.configPath, "utf-8");
12835
+ const raw = fs9__namespace.readFileSync(this.configPath, "utf-8");
12429
12836
  const parsed = JSON.parse(raw);
12430
12837
  return parsed;
12431
12838
  }
12432
12839
  writeConfig(config) {
12433
- const dir = path__namespace.dirname(this.configPath);
12434
- if (!fs8__namespace.existsSync(dir)) {
12435
- 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 });
12436
12843
  }
12437
12844
  const tmp = `${this.configPath}.tmp`;
12438
- fs8__namespace.writeFileSync(tmp, JSON.stringify(config, null, " "), "utf-8");
12439
- fs8__namespace.renameSync(tmp, this.configPath);
12845
+ fs9__namespace.writeFileSync(tmp, JSON.stringify(config, null, " "), "utf-8");
12846
+ fs9__namespace.renameSync(tmp, this.configPath);
12440
12847
  }
12441
12848
  listTasks() {
12442
12849
  return this.readConfig().tasks;
@@ -12547,7 +12954,7 @@ function resolveTaskExecutionPayload(taskType, payload, workspacePath) {
12547
12954
  var TaskExecutionEngine;
12548
12955
  var init_TaskExecutionEngine = __esm({
12549
12956
  "../../packages/serviceme-core/src/scheduled-tasks/TaskExecutionEngine.ts"() {
12550
- init_types();
12957
+ init_types2();
12551
12958
  init_TaskConfigManager();
12552
12959
  TaskExecutionEngine = class {
12553
12960
  constructor(getExecutor2) {
@@ -12740,17 +13147,17 @@ var init_TaskLogManager = __esm({
12740
13147
  MAX_LOGS = 200;
12741
13148
  TaskLogManager = class {
12742
13149
  constructor(workspacePath) {
12743
- this.logPath = path__namespace.join(workspacePath, CONFIG_DIR4, LOG_FILE2);
13150
+ this.logPath = path11__namespace.join(workspacePath, CONFIG_DIR4, LOG_FILE2);
12744
13151
  }
12745
13152
  getLogPath() {
12746
13153
  return this.logPath;
12747
13154
  }
12748
13155
  readLogFile() {
12749
- if (!fs8__namespace.existsSync(this.logPath)) {
13156
+ if (!fs9__namespace.existsSync(this.logPath)) {
12750
13157
  return emptyLogFile();
12751
13158
  }
12752
13159
  try {
12753
- const raw = fs8__namespace.readFileSync(this.logPath, "utf-8");
13160
+ const raw = fs9__namespace.readFileSync(this.logPath, "utf-8");
12754
13161
  const parsed = JSON.parse(raw);
12755
13162
  const file = validateAndRepairLogFile(parsed);
12756
13163
  if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.logs) || parsed.logs.length !== file.logs.length) {
@@ -12766,21 +13173,21 @@ var init_TaskLogManager = __esm({
12766
13173
  }
12767
13174
  backupCorruptedFile() {
12768
13175
  try {
12769
- if (fs8__namespace.existsSync(this.logPath)) {
13176
+ if (fs9__namespace.existsSync(this.logPath)) {
12770
13177
  const backupPath = `${this.logPath}.corrupted.${Date.now()}`;
12771
- fs8__namespace.copyFileSync(this.logPath, backupPath);
13178
+ fs9__namespace.copyFileSync(this.logPath, backupPath);
12772
13179
  }
12773
13180
  } catch {
12774
13181
  }
12775
13182
  }
12776
13183
  writeLogFile(file) {
12777
- const dir = path__namespace.dirname(this.logPath);
12778
- if (!fs8__namespace.existsSync(dir)) {
12779
- 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 });
12780
13187
  }
12781
13188
  const tmp = `${this.logPath}.tmp`;
12782
- fs8__namespace.writeFileSync(tmp, JSON.stringify(file, null, " "), "utf-8");
12783
- fs8__namespace.renameSync(tmp, this.logPath);
13189
+ fs9__namespace.writeFileSync(tmp, JSON.stringify(file, null, " "), "utf-8");
13190
+ fs9__namespace.renameSync(tmp, this.logPath);
12784
13191
  }
12785
13192
  appendLog(input) {
12786
13193
  const file = this.readLogFile();
@@ -12939,8 +13346,8 @@ var init_SchedulerDaemon = __esm({
12939
13346
  const configPath = this.configManager.getConfigPath();
12940
13347
  const dir = configPath.substring(0, configPath.lastIndexOf("/"));
12941
13348
  try {
12942
- if (fs8__namespace.existsSync(dir)) {
12943
- this.watcher = fs8__namespace.watch(dir, (_eventType, filename) => {
13349
+ if (fs9__namespace.existsSync(dir)) {
13350
+ this.watcher = fs9__namespace.watch(dir, (_eventType, filename) => {
12944
13351
  if (filename === "scheduled-tasks.json") {
12945
13352
  this.logger.log("info", "Config file changed, reconciling...");
12946
13353
  }
@@ -13076,9 +13483,202 @@ var init_scheduled_tasks2 = __esm({
13076
13483
  }
13077
13484
  });
13078
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
+
13079
13676
  // ../../packages/serviceme-core/src/index.ts
13080
13677
  var src_exports = {};
13081
13678
  __export(src_exports, {
13679
+ AgentCatalogClient: () => AgentCatalogClient,
13680
+ AgentReconciler: () => AgentReconciler,
13681
+ AgentStore: () => AgentStore,
13082
13682
  DaemonLogger: () => DaemonLogger,
13083
13683
  EnvironmentInspector: () => EnvironmentInspector,
13084
13684
  GithubCopilotCliExecutor: () => GithubCopilotCliExecutor,
@@ -13088,6 +13688,10 @@ __export(src_exports, {
13088
13688
  ProjectTools: () => ProjectTools,
13089
13689
  SchedulerDaemon: () => SchedulerDaemon,
13090
13690
  ShellExecutor: () => ShellExecutor,
13691
+ SkillCatalogClient: () => SkillCatalogClient,
13692
+ SkillReconciler: () => SkillReconciler,
13693
+ SkillStore: () => SkillStore,
13694
+ TOOL_RISK_MAP: () => TOOL_RISK_MAP,
13091
13695
  TaskConfigManager: () => TaskConfigManager,
13092
13696
  TaskExecutionEngine: () => TaskExecutionEngine,
13093
13697
  TaskLogManager: () => TaskLogManager,
@@ -13105,6 +13709,7 @@ __export(src_exports, {
13105
13709
  matchesCron: () => matchesCron,
13106
13710
  moveFiles: () => moveFiles,
13107
13711
  noopLogger: () => noopLogger,
13712
+ parseAgentToolPermissions: () => parseAgentToolPermissions,
13108
13713
  parseIntervalMs: () => parseIntervalMs,
13109
13714
  resolveTaskExecutionPayload: () => resolveTaskExecutionPayload,
13110
13715
  unzipFile: () => unzipFile,
@@ -13112,13 +13717,16 @@ __export(src_exports, {
13112
13717
  });
13113
13718
  var init_src2 = __esm({
13114
13719
  "../../packages/serviceme-core/src/index.ts"() {
13720
+ init_agents();
13115
13721
  init_copilot2();
13116
13722
  init_environmentInspector();
13117
13723
  init_imageTools();
13118
13724
  init_jsonTools();
13119
13725
  init_logger();
13726
+ init_permissions();
13120
13727
  init_projectTools();
13121
13728
  init_scheduled_tasks2();
13729
+ init_skills();
13122
13730
  init_fileUtils();
13123
13731
  }
13124
13732
  });
@@ -13169,39 +13777,945 @@ function getStringFlag(parsed, name) {
13169
13777
  return typeof value === "string" ? value : void 0;
13170
13778
  }
13171
13779
 
13172
- // src/commands/bridge.ts
13780
+ // src/commands/agent.ts
13173
13781
  init_src2();
13174
-
13175
- // src/bridge/BridgeServer.ts
13176
13782
  init_src();
13177
13783
 
13178
- // src/version.ts
13179
- var SERVICEME_CLI_NAME = "serviceme";
13180
- var SERVICEME_CLI_VERSION = "0.1.4";
13181
-
13182
- // src/bridge/ndjson.ts
13183
- function writeBridgeMessage(message) {
13184
- process.stdout.write(`${JSON.stringify(message)}
13784
+ // src/output.ts
13785
+ init_src();
13786
+ function writeJson(value) {
13787
+ process.stdout.write(`${JSON.stringify(value)}
13185
13788
  `);
13186
13789
  }
13790
+ function writeSuccess(data) {
13791
+ writeJson(createCliSuccess(data));
13792
+ }
13793
+ function writeFailure(error) {
13794
+ writeJson(createCliFailure(normalizeServicemeError(error)));
13795
+ }
13187
13796
 
13188
- // src/bridge/TaskBridgeHandler.ts
13189
- init_src2();
13190
- var TaskBridgeHandler = class {
13191
- constructor(logger, emitEvent) {
13192
- this.logger = logger;
13193
- this.emitEvent = emitEvent;
13194
- this.engine = new TaskExecutionEngine(
13195
- (taskType) => getExecutor(taskType)
13196
- );
13197
- this.engine.setListener({
13198
- onStarted: (params) => this.emitEvent("task.started", params),
13199
- onOutput: (params) => this.emitEvent("task.output", params),
13200
- onCompleted: (params) => this.emitEvent("task.completed", params),
13201
- onFailed: (params) => this.emitEvent("task.failed", params),
13202
- onCancelled: (params) => this.emitEvent("task.cancelled", params)
13203
- });
13204
- }
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>."
13812
+ );
13813
+ }
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
+ }
13205
14719
  async execute(snapshot) {
13206
14720
  let earlyError;
13207
14721
  const executePromise = this.engine.execute(snapshot).catch((err) => {
@@ -13233,7 +14747,9 @@ var CAPABILITIES = {
13233
14747
  bridge: true,
13234
14748
  json: 1,
13235
14749
  env: 1,
13236
- tasks: 1
14750
+ tasks: 1,
14751
+ skills: 1,
14752
+ agents: 1
13237
14753
  };
13238
14754
  var BridgeServer = class {
13239
14755
  constructor(logger) {
@@ -13242,6 +14758,8 @@ var BridgeServer = class {
13242
14758
  this.taskHandler = new TaskBridgeHandler(logger, (event, params) => {
13243
14759
  this.writeEvent(event, params);
13244
14760
  });
14761
+ this.skillHandler = new SkillBridgeHandler();
14762
+ this.agentHandler = new AgentBridgeHandler();
13245
14763
  }
13246
14764
  async run() {
13247
14765
  const reader = readline__namespace.createInterface({
@@ -13347,6 +14865,56 @@ var BridgeServer = class {
13347
14865
  this.writeSuccess(request.id, result);
13348
14866
  return;
13349
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
+ }
13350
14918
  default:
13351
14919
  this.writeError(
13352
14920
  request.id,
@@ -13396,21 +14964,6 @@ async function runBridgeCommand() {
13396
14964
 
13397
14965
  // src/commands/copilot.ts
13398
14966
  init_src2();
13399
-
13400
- // src/output.ts
13401
- init_src();
13402
- function writeJson(value) {
13403
- process.stdout.write(`${JSON.stringify(value)}
13404
- `);
13405
- }
13406
- function writeSuccess(data) {
13407
- writeJson(createCliSuccess(data));
13408
- }
13409
- function writeFailure(error) {
13410
- writeJson(createCliFailure(normalizeServicemeError(error)));
13411
- }
13412
-
13413
- // src/commands/copilot.ts
13414
14967
  async function runCopilotCommand(parsed) {
13415
14968
  const action = parsed.positionals[1];
13416
14969
  switch (action) {
@@ -13530,7 +15083,7 @@ async function runImageCommand(parsed) {
13530
15083
  init_src2();
13531
15084
  async function readCommandInput(options2) {
13532
15085
  if (options2.filePath) {
13533
- return fs2__namespace.readFile(options2.filePath, "utf8");
15086
+ return fs12__namespace.readFile(options2.filePath, "utf8");
13534
15087
  }
13535
15088
  if (options2.stdin) {
13536
15089
  return readStdin();
@@ -13669,7 +15222,7 @@ async function runScheduleCommand(parsed) {
13669
15222
  await handleCreate(parsed);
13670
15223
  return;
13671
15224
  case "list":
13672
- handleList(parsed);
15225
+ handleList2(parsed);
13673
15226
  return;
13674
15227
  case "get":
13675
15228
  handleGet(parsed);
@@ -13704,7 +15257,7 @@ function requireWorkspace(parsed) {
13704
15257
  "Missing required flag: --workspacePath"
13705
15258
  );
13706
15259
  }
13707
- if (!fs8__namespace.existsSync(wp)) {
15260
+ if (!fs9__namespace.existsSync(wp)) {
13708
15261
  throw createServicemeError(
13709
15262
  "workspace_not_found",
13710
15263
  `Workspace path does not exist: ${wp}`
@@ -13901,7 +15454,7 @@ async function handleCreate(parsed) {
13901
15454
  const task = mgr.createTask(input);
13902
15455
  writeSuccess({ task });
13903
15456
  }
13904
- function handleList(parsed) {
15457
+ function handleList2(parsed) {
13905
15458
  const wp = requireWorkspace(parsed);
13906
15459
  const mgr = new TaskConfigManager(wp);
13907
15460
  const tasks = mgr.listTasks();
@@ -14273,7 +15826,7 @@ function requireWorkspace2(parsed) {
14273
15826
  "Missing required flag: --workspacePath"
14274
15827
  );
14275
15828
  }
14276
- if (!fs8__namespace.existsSync(wp)) {
15829
+ if (!fs9__namespace.existsSync(wp)) {
14277
15830
  throw createServicemeError(
14278
15831
  "workspace_not_found",
14279
15832
  `Workspace path does not exist: ${wp}`
@@ -14300,10 +15853,10 @@ function handleStart(parsed) {
14300
15853
  "Cannot determine CLI path for daemon spawn"
14301
15854
  );
14302
15855
  }
14303
- const logPath = path__namespace.join(wp, ".serviceme", "scheduler.log");
14304
- const logDir = path__namespace.dirname(logPath);
14305
- if (!fs8__namespace.existsSync(logDir)) {
14306
- 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 });
14307
15860
  }
14308
15861
  const spawnCmd = process.execPath;
14309
15862
  const spawnArgs = [
@@ -14316,7 +15869,7 @@ function handleStart(parsed) {
14316
15869
  logPath
14317
15870
  ];
14318
15871
  if (process.platform === "win32") {
14319
- fs8__namespace.appendFileSync(
15872
+ fs9__namespace.appendFileSync(
14320
15873
  logPath,
14321
15874
  `[scheduler:start] spawning daemon via hidden PowerShell Start-Process: cmd=${spawnCmd}, args=${JSON.stringify(spawnArgs)}, platform=${process.platform}, windowsHide=true
14322
15875
  `
@@ -14326,9 +15879,9 @@ function handleStart(parsed) {
14326
15879
  writeSuccess({ pid: pid2, status: "started", workspacePath: wp });
14327
15880
  return;
14328
15881
  }
14329
- const out = fs8__namespace.openSync(logPath, "a");
14330
- const err = fs8__namespace.openSync(logPath, "a");
14331
- fs8__namespace.appendFileSync(
15882
+ const out = fs9__namespace.openSync(logPath, "a");
15883
+ const err = fs9__namespace.openSync(logPath, "a");
15884
+ fs9__namespace.appendFileSync(
14332
15885
  logPath,
14333
15886
  `[scheduler:start] spawning daemon: cmd=${spawnCmd}, args=${JSON.stringify(spawnArgs)}, platform=${process.platform}, detached=true, windowsHide=true
14334
15887
  `
@@ -14439,7 +15992,7 @@ function handleStatus(parsed) {
14439
15992
  let uptimeSeconds = null;
14440
15993
  if (pid !== null) {
14441
15994
  try {
14442
- const stat2 = fs8__namespace.statSync(pidMgr.getPidPath());
15995
+ const stat2 = fs9__namespace.statSync(pidMgr.getPidPath());
14443
15996
  uptimeSeconds = Math.floor((Date.now() - stat2.mtimeMs) / 1e3);
14444
15997
  } catch {
14445
15998
  uptimeSeconds = null;
@@ -14510,6 +16063,279 @@ function writeDescribe2(action) {
14510
16063
  }
14511
16064
  }
14512
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
+
14513
16339
  // src/commands/version.ts
14514
16340
  init_src();
14515
16341
  async function runVersionCommand() {
@@ -14538,6 +16364,8 @@ function printUsage() {
14538
16364
  " serviceme env check --json",
14539
16365
  " serviceme copilot doctor --json",
14540
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",
14541
16369
  " serviceme schedule <create|list|get|edit|delete|toggle|trigger|logs> --workspacePath <path> --json",
14542
16370
  " serviceme scheduler <start|stop|status> --workspacePath <path> --json"
14543
16371
  ].join("\n")}
@@ -14574,6 +16402,12 @@ async function main() {
14574
16402
  case "copilot":
14575
16403
  await runCopilotCommand(parsed);
14576
16404
  return;
16405
+ case "skill":
16406
+ await runSkillCommand(parsed);
16407
+ return;
16408
+ case "agent":
16409
+ await runAgentCommand(parsed);
16410
+ return;
14577
16411
  case "schedule":
14578
16412
  await runScheduleCommand(parsed);
14579
16413
  return;