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