@serviceme/devtools-core 0.1.7 → 0.1.9
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/index.d.mts +75 -33
- package/dist/index.d.ts +75 -33
- package/dist/index.js +81 -111
- package/dist/index.mjs +84 -121
- package/package.json +3 -2
package/dist/index.d.mts
CHANGED
|
@@ -109,7 +109,39 @@ declare function createCopilotAuthRequiredError(): _serviceme_devtools_protocol.
|
|
|
109
109
|
|
|
110
110
|
declare function copilotPrompt(options: CopilotPromptOptions): Promise<CopilotPromptResult>;
|
|
111
111
|
|
|
112
|
+
interface RunCommandOptions {
|
|
113
|
+
args?: string[];
|
|
114
|
+
cwd?: string;
|
|
115
|
+
env?: NodeJS.ProcessEnv;
|
|
116
|
+
timeoutMs?: number;
|
|
117
|
+
stdin?: string;
|
|
118
|
+
shell?: boolean;
|
|
119
|
+
}
|
|
120
|
+
interface RunCommandResult {
|
|
121
|
+
stdout: string;
|
|
122
|
+
stderr: string;
|
|
123
|
+
code: number;
|
|
124
|
+
}
|
|
125
|
+
declare function runCommand(command: string, options?: RunCommandOptions): Promise<RunCommandResult>;
|
|
126
|
+
|
|
127
|
+
interface EnvironmentInspectorOptions {
|
|
128
|
+
/**
|
|
129
|
+
* Override the command runner. Production callers should leave this
|
|
130
|
+
* undefined and rely on the default `runCommand` from `../process/runCommand`;
|
|
131
|
+
* tests inject a fake to drive error/edge branches without spawning
|
|
132
|
+
* real subprocesses.
|
|
133
|
+
*/
|
|
134
|
+
runCommand?: typeof runCommand;
|
|
135
|
+
/**
|
|
136
|
+
* Override the detected platform. Defaults to `process.platform`. Tests
|
|
137
|
+
* use this to exercise the Windows-specific branches of the inspector.
|
|
138
|
+
*/
|
|
139
|
+
platform?: NodeJS.Platform;
|
|
140
|
+
}
|
|
112
141
|
declare class EnvironmentInspector {
|
|
142
|
+
private readonly runCommandFn;
|
|
143
|
+
private readonly platform;
|
|
144
|
+
constructor(options?: EnvironmentInspectorOptions);
|
|
113
145
|
checkEnvironment(): Promise<EnvironmentCheckResult>;
|
|
114
146
|
checkTool(toolName: KnownEnvironmentTool): Promise<ToolCheckResult>;
|
|
115
147
|
private getToolPath;
|
|
@@ -194,38 +226,6 @@ declare class PidManager {
|
|
|
194
226
|
getRunningPid(): number | null;
|
|
195
227
|
}
|
|
196
228
|
|
|
197
|
-
declare class SchedulerDaemon {
|
|
198
|
-
private readonly workspacePath;
|
|
199
|
-
private readonly configManager;
|
|
200
|
-
private readonly logManager;
|
|
201
|
-
private readonly pidManager;
|
|
202
|
-
private readonly logger;
|
|
203
|
-
private tickTimer;
|
|
204
|
-
private watcher;
|
|
205
|
-
private running;
|
|
206
|
-
private startTime;
|
|
207
|
-
private lastRun;
|
|
208
|
-
private taskRunning;
|
|
209
|
-
constructor(workspacePath: string);
|
|
210
|
-
start(): void;
|
|
211
|
-
stop(): void;
|
|
212
|
-
private setupConfigWatch;
|
|
213
|
-
private tick;
|
|
214
|
-
private shouldRun;
|
|
215
|
-
private executeTask;
|
|
216
|
-
getStatus(): {
|
|
217
|
-
running: boolean;
|
|
218
|
-
pid: number;
|
|
219
|
-
uptimeSeconds: number | null;
|
|
220
|
-
tasksRegistered: number;
|
|
221
|
-
tasksEnabled: number;
|
|
222
|
-
workspacePath: string;
|
|
223
|
-
pidFile: string;
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
declare function parseIntervalMs(schedule: string): number;
|
|
227
|
-
declare function matchesCron(expression: string, date: Date): boolean;
|
|
228
|
-
|
|
229
229
|
interface ExecutorResult {
|
|
230
230
|
status: TaskExecutionStatus;
|
|
231
231
|
output?: string;
|
|
@@ -260,6 +260,48 @@ declare class ShellExecutor implements StreamingTaskExecutor {
|
|
|
260
260
|
|
|
261
261
|
declare function getExecutor(taskType: ScheduledTaskType): TaskExecutor;
|
|
262
262
|
|
|
263
|
+
interface SchedulerDaemonOptions {
|
|
264
|
+
/**
|
|
265
|
+
* Override the executor factory. Production callers should leave this
|
|
266
|
+
* undefined and rely on the default `getExecutor` from `../executors`;
|
|
267
|
+
* tests inject a fake to drive the execution branch without spawning
|
|
268
|
+
* real subprocesses.
|
|
269
|
+
*/
|
|
270
|
+
getExecutor?: typeof getExecutor;
|
|
271
|
+
}
|
|
272
|
+
declare class SchedulerDaemon {
|
|
273
|
+
private readonly workspacePath;
|
|
274
|
+
private readonly configManager;
|
|
275
|
+
private readonly logManager;
|
|
276
|
+
private readonly pidManager;
|
|
277
|
+
private readonly logger;
|
|
278
|
+
private readonly getExecutor;
|
|
279
|
+
private tickTimer;
|
|
280
|
+
private watcher;
|
|
281
|
+
private running;
|
|
282
|
+
private startTime;
|
|
283
|
+
private lastRun;
|
|
284
|
+
private taskRunning;
|
|
285
|
+
constructor(workspacePath: string, options?: SchedulerDaemonOptions);
|
|
286
|
+
start(): void;
|
|
287
|
+
stop(): void;
|
|
288
|
+
private setupConfigWatch;
|
|
289
|
+
private tick;
|
|
290
|
+
private shouldRun;
|
|
291
|
+
private executeTask;
|
|
292
|
+
getStatus(): {
|
|
293
|
+
running: boolean;
|
|
294
|
+
pid: number;
|
|
295
|
+
uptimeSeconds: number | null;
|
|
296
|
+
tasksRegistered: number;
|
|
297
|
+
tasksEnabled: number;
|
|
298
|
+
workspacePath: string;
|
|
299
|
+
pidFile: string;
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
declare function parseIntervalMs(schedule: string): number;
|
|
303
|
+
declare function matchesCron(expression: string, date: Date): boolean;
|
|
304
|
+
|
|
263
305
|
declare function validateTaskPayload(taskType: ScheduledTaskType, payload: TaskPayload): void;
|
|
264
306
|
interface CreateTaskInput {
|
|
265
307
|
name: string;
|
|
@@ -429,4 +471,4 @@ declare class SkillStore {
|
|
|
429
471
|
declare const unzipFile: (zipPath: string, dest: string) => Promise<void>;
|
|
430
472
|
declare const moveFiles: (sourceDir: string, destDir: string, overwrite?: boolean) => Promise<void>;
|
|
431
473
|
|
|
432
|
-
export { type AgentCatalog, AgentCatalogClient, type AgentCatalogClientOptions, type AgentDownloadFile, type AgentInstallScope, type AgentMutateResult, AgentReconciler, type AgentReconcilerDependencies, AgentStore, type AgentStoreFileSystem, type AgentStoreOptions, type AgentsStateFile, type AppendLogInput, type CreateTaskInput, DaemonLogger, type EditTaskInput, EnvironmentInspector, type ExecutorResult, GithubCopilotCliExecutor, HttpRequestExecutor, ImageTools, type InstalledAgent, type JsonTools, type OutputEventCallback, PidManager, ProjectTools, SchedulerDaemon, type ServiceMeLogger, ShellExecutor, type SkillCatalog, SkillCatalogClient, type SkillCatalogClientOptions, type SkillDownloadFile, type SkillMutateResult, SkillReconciler, type SkillReconcilerDependencies, SkillStore, type SkillStoreFileSystem, type SkillStoreOptions, type StreamingExecutorHandle, type StreamingTaskExecutor, TOOL_RISK_MAP, TaskConfigManager, type TaskEventListener, TaskExecutionEngine, type TaskExecutor, TaskLogManager, copilotDoctor, copilotPrompt, createConsoleLogger, createCopilotAuthRequiredError, createCopilotNotInstalledError, createImageTools, createJsonTools, createProjectTools, getExecutor, isCopilotAuthenticated, isStreamingTaskExecutor, matchesCron, moveFiles, noopLogger, parseAgentToolPermissions, parseIntervalMs, resolveTaskExecutionPayload, unzipFile, validateTaskPayload };
|
|
474
|
+
export { type AgentCatalog, AgentCatalogClient, type AgentCatalogClientOptions, type AgentDownloadFile, type AgentInstallScope, type AgentMutateResult, AgentReconciler, type AgentReconcilerDependencies, AgentStore, type AgentStoreFileSystem, type AgentStoreOptions, type AgentsStateFile, type AppendLogInput, type CreateTaskInput, DaemonLogger, type EditTaskInput, EnvironmentInspector, type EnvironmentInspectorOptions, type ExecutorResult, GithubCopilotCliExecutor, HttpRequestExecutor, ImageTools, type InstalledAgent, type JsonTools, type OutputEventCallback, PidManager, ProjectTools, SchedulerDaemon, type ServiceMeLogger, ShellExecutor, type SkillCatalog, SkillCatalogClient, type SkillCatalogClientOptions, type SkillDownloadFile, type SkillMutateResult, SkillReconciler, type SkillReconcilerDependencies, SkillStore, type SkillStoreFileSystem, type SkillStoreOptions, type StreamingExecutorHandle, type StreamingTaskExecutor, TOOL_RISK_MAP, TaskConfigManager, type TaskEventListener, TaskExecutionEngine, type TaskExecutor, TaskLogManager, copilotDoctor, copilotPrompt, createConsoleLogger, createCopilotAuthRequiredError, createCopilotNotInstalledError, createImageTools, createJsonTools, createProjectTools, getExecutor, isCopilotAuthenticated, isStreamingTaskExecutor, matchesCron, moveFiles, noopLogger, parseAgentToolPermissions, parseIntervalMs, resolveTaskExecutionPayload, unzipFile, validateTaskPayload };
|
package/dist/index.d.ts
CHANGED
|
@@ -109,7 +109,39 @@ declare function createCopilotAuthRequiredError(): _serviceme_devtools_protocol.
|
|
|
109
109
|
|
|
110
110
|
declare function copilotPrompt(options: CopilotPromptOptions): Promise<CopilotPromptResult>;
|
|
111
111
|
|
|
112
|
+
interface RunCommandOptions {
|
|
113
|
+
args?: string[];
|
|
114
|
+
cwd?: string;
|
|
115
|
+
env?: NodeJS.ProcessEnv;
|
|
116
|
+
timeoutMs?: number;
|
|
117
|
+
stdin?: string;
|
|
118
|
+
shell?: boolean;
|
|
119
|
+
}
|
|
120
|
+
interface RunCommandResult {
|
|
121
|
+
stdout: string;
|
|
122
|
+
stderr: string;
|
|
123
|
+
code: number;
|
|
124
|
+
}
|
|
125
|
+
declare function runCommand(command: string, options?: RunCommandOptions): Promise<RunCommandResult>;
|
|
126
|
+
|
|
127
|
+
interface EnvironmentInspectorOptions {
|
|
128
|
+
/**
|
|
129
|
+
* Override the command runner. Production callers should leave this
|
|
130
|
+
* undefined and rely on the default `runCommand` from `../process/runCommand`;
|
|
131
|
+
* tests inject a fake to drive error/edge branches without spawning
|
|
132
|
+
* real subprocesses.
|
|
133
|
+
*/
|
|
134
|
+
runCommand?: typeof runCommand;
|
|
135
|
+
/**
|
|
136
|
+
* Override the detected platform. Defaults to `process.platform`. Tests
|
|
137
|
+
* use this to exercise the Windows-specific branches of the inspector.
|
|
138
|
+
*/
|
|
139
|
+
platform?: NodeJS.Platform;
|
|
140
|
+
}
|
|
112
141
|
declare class EnvironmentInspector {
|
|
142
|
+
private readonly runCommandFn;
|
|
143
|
+
private readonly platform;
|
|
144
|
+
constructor(options?: EnvironmentInspectorOptions);
|
|
113
145
|
checkEnvironment(): Promise<EnvironmentCheckResult>;
|
|
114
146
|
checkTool(toolName: KnownEnvironmentTool): Promise<ToolCheckResult>;
|
|
115
147
|
private getToolPath;
|
|
@@ -194,38 +226,6 @@ declare class PidManager {
|
|
|
194
226
|
getRunningPid(): number | null;
|
|
195
227
|
}
|
|
196
228
|
|
|
197
|
-
declare class SchedulerDaemon {
|
|
198
|
-
private readonly workspacePath;
|
|
199
|
-
private readonly configManager;
|
|
200
|
-
private readonly logManager;
|
|
201
|
-
private readonly pidManager;
|
|
202
|
-
private readonly logger;
|
|
203
|
-
private tickTimer;
|
|
204
|
-
private watcher;
|
|
205
|
-
private running;
|
|
206
|
-
private startTime;
|
|
207
|
-
private lastRun;
|
|
208
|
-
private taskRunning;
|
|
209
|
-
constructor(workspacePath: string);
|
|
210
|
-
start(): void;
|
|
211
|
-
stop(): void;
|
|
212
|
-
private setupConfigWatch;
|
|
213
|
-
private tick;
|
|
214
|
-
private shouldRun;
|
|
215
|
-
private executeTask;
|
|
216
|
-
getStatus(): {
|
|
217
|
-
running: boolean;
|
|
218
|
-
pid: number;
|
|
219
|
-
uptimeSeconds: number | null;
|
|
220
|
-
tasksRegistered: number;
|
|
221
|
-
tasksEnabled: number;
|
|
222
|
-
workspacePath: string;
|
|
223
|
-
pidFile: string;
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
declare function parseIntervalMs(schedule: string): number;
|
|
227
|
-
declare function matchesCron(expression: string, date: Date): boolean;
|
|
228
|
-
|
|
229
229
|
interface ExecutorResult {
|
|
230
230
|
status: TaskExecutionStatus;
|
|
231
231
|
output?: string;
|
|
@@ -260,6 +260,48 @@ declare class ShellExecutor implements StreamingTaskExecutor {
|
|
|
260
260
|
|
|
261
261
|
declare function getExecutor(taskType: ScheduledTaskType): TaskExecutor;
|
|
262
262
|
|
|
263
|
+
interface SchedulerDaemonOptions {
|
|
264
|
+
/**
|
|
265
|
+
* Override the executor factory. Production callers should leave this
|
|
266
|
+
* undefined and rely on the default `getExecutor` from `../executors`;
|
|
267
|
+
* tests inject a fake to drive the execution branch without spawning
|
|
268
|
+
* real subprocesses.
|
|
269
|
+
*/
|
|
270
|
+
getExecutor?: typeof getExecutor;
|
|
271
|
+
}
|
|
272
|
+
declare class SchedulerDaemon {
|
|
273
|
+
private readonly workspacePath;
|
|
274
|
+
private readonly configManager;
|
|
275
|
+
private readonly logManager;
|
|
276
|
+
private readonly pidManager;
|
|
277
|
+
private readonly logger;
|
|
278
|
+
private readonly getExecutor;
|
|
279
|
+
private tickTimer;
|
|
280
|
+
private watcher;
|
|
281
|
+
private running;
|
|
282
|
+
private startTime;
|
|
283
|
+
private lastRun;
|
|
284
|
+
private taskRunning;
|
|
285
|
+
constructor(workspacePath: string, options?: SchedulerDaemonOptions);
|
|
286
|
+
start(): void;
|
|
287
|
+
stop(): void;
|
|
288
|
+
private setupConfigWatch;
|
|
289
|
+
private tick;
|
|
290
|
+
private shouldRun;
|
|
291
|
+
private executeTask;
|
|
292
|
+
getStatus(): {
|
|
293
|
+
running: boolean;
|
|
294
|
+
pid: number;
|
|
295
|
+
uptimeSeconds: number | null;
|
|
296
|
+
tasksRegistered: number;
|
|
297
|
+
tasksEnabled: number;
|
|
298
|
+
workspacePath: string;
|
|
299
|
+
pidFile: string;
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
declare function parseIntervalMs(schedule: string): number;
|
|
303
|
+
declare function matchesCron(expression: string, date: Date): boolean;
|
|
304
|
+
|
|
263
305
|
declare function validateTaskPayload(taskType: ScheduledTaskType, payload: TaskPayload): void;
|
|
264
306
|
interface CreateTaskInput {
|
|
265
307
|
name: string;
|
|
@@ -429,4 +471,4 @@ declare class SkillStore {
|
|
|
429
471
|
declare const unzipFile: (zipPath: string, dest: string) => Promise<void>;
|
|
430
472
|
declare const moveFiles: (sourceDir: string, destDir: string, overwrite?: boolean) => Promise<void>;
|
|
431
473
|
|
|
432
|
-
export { type AgentCatalog, AgentCatalogClient, type AgentCatalogClientOptions, type AgentDownloadFile, type AgentInstallScope, type AgentMutateResult, AgentReconciler, type AgentReconcilerDependencies, AgentStore, type AgentStoreFileSystem, type AgentStoreOptions, type AgentsStateFile, type AppendLogInput, type CreateTaskInput, DaemonLogger, type EditTaskInput, EnvironmentInspector, type ExecutorResult, GithubCopilotCliExecutor, HttpRequestExecutor, ImageTools, type InstalledAgent, type JsonTools, type OutputEventCallback, PidManager, ProjectTools, SchedulerDaemon, type ServiceMeLogger, ShellExecutor, type SkillCatalog, SkillCatalogClient, type SkillCatalogClientOptions, type SkillDownloadFile, type SkillMutateResult, SkillReconciler, type SkillReconcilerDependencies, SkillStore, type SkillStoreFileSystem, type SkillStoreOptions, type StreamingExecutorHandle, type StreamingTaskExecutor, TOOL_RISK_MAP, TaskConfigManager, type TaskEventListener, TaskExecutionEngine, type TaskExecutor, TaskLogManager, copilotDoctor, copilotPrompt, createConsoleLogger, createCopilotAuthRequiredError, createCopilotNotInstalledError, createImageTools, createJsonTools, createProjectTools, getExecutor, isCopilotAuthenticated, isStreamingTaskExecutor, matchesCron, moveFiles, noopLogger, parseAgentToolPermissions, parseIntervalMs, resolveTaskExecutionPayload, unzipFile, validateTaskPayload };
|
|
474
|
+
export { type AgentCatalog, AgentCatalogClient, type AgentCatalogClientOptions, type AgentDownloadFile, type AgentInstallScope, type AgentMutateResult, AgentReconciler, type AgentReconcilerDependencies, AgentStore, type AgentStoreFileSystem, type AgentStoreOptions, type AgentsStateFile, type AppendLogInput, type CreateTaskInput, DaemonLogger, type EditTaskInput, EnvironmentInspector, type EnvironmentInspectorOptions, type ExecutorResult, GithubCopilotCliExecutor, HttpRequestExecutor, ImageTools, type InstalledAgent, type JsonTools, type OutputEventCallback, PidManager, ProjectTools, SchedulerDaemon, type ServiceMeLogger, ShellExecutor, type SkillCatalog, SkillCatalogClient, type SkillCatalogClientOptions, type SkillDownloadFile, type SkillMutateResult, SkillReconciler, type SkillReconcilerDependencies, SkillStore, type SkillStoreFileSystem, type SkillStoreOptions, type StreamingExecutorHandle, type StreamingTaskExecutor, TOOL_RISK_MAP, TaskConfigManager, type TaskEventListener, TaskExecutionEngine, type TaskExecutor, TaskLogManager, copilotDoctor, copilotPrompt, createConsoleLogger, createCopilotAuthRequiredError, createCopilotNotInstalledError, createImageTools, createJsonTools, createProjectTools, getExecutor, isCopilotAuthenticated, isStreamingTaskExecutor, matchesCron, moveFiles, noopLogger, parseAgentToolPermissions, parseIntervalMs, resolveTaskExecutionPayload, unzipFile, validateTaskPayload };
|
package/dist/index.js
CHANGED
|
@@ -80,10 +80,10 @@ var AgentCatalogClient = class {
|
|
|
80
80
|
}
|
|
81
81
|
async getCatalog() {
|
|
82
82
|
if (!this.baseUrl) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
throw (0, import_devtools_protocol.createServicemeError)(
|
|
84
|
+
"workspace_not_found",
|
|
85
|
+
"Agent catalog baseUrl is not configured."
|
|
86
|
+
);
|
|
87
87
|
}
|
|
88
88
|
const response = await this.fetchImpl(
|
|
89
89
|
`${this.baseUrl}/api/v1/marketplace/agents`
|
|
@@ -577,6 +577,9 @@ async function copilotPrompt(options) {
|
|
|
577
577
|
}
|
|
578
578
|
return { output, exitCode: 0 };
|
|
579
579
|
} catch (error) {
|
|
580
|
+
if (error instanceof import_devtools_protocol3.ServicemeProtocolError) {
|
|
581
|
+
throw error;
|
|
582
|
+
}
|
|
580
583
|
const err = error;
|
|
581
584
|
if (err.code === "ETIMEDOUT") {
|
|
582
585
|
throw (0, import_devtools_protocol3.createServicemeError)(
|
|
@@ -622,11 +625,13 @@ var TOOL_CHECK_TIMEOUT_MS = {
|
|
|
622
625
|
var ERROR_CODE_NOT_FOUND = 127;
|
|
623
626
|
var ERROR_CODE_TIMEOUT = "ETIMEDOUT";
|
|
624
627
|
var EnvironmentInspector = class {
|
|
628
|
+
constructor(options = {}) {
|
|
629
|
+
this.runCommandFn = options.runCommand ?? runCommand;
|
|
630
|
+
this.platform = options.platform ?? process.platform;
|
|
631
|
+
}
|
|
625
632
|
async checkEnvironment() {
|
|
626
633
|
const results = await Promise.all(
|
|
627
|
-
import_devtools_protocol4.KNOWN_ENVIRONMENT_TOOLS.map(
|
|
628
|
-
async (tool) => [tool, await this.checkTool(tool)]
|
|
629
|
-
)
|
|
634
|
+
import_devtools_protocol4.KNOWN_ENVIRONMENT_TOOLS.map(async (tool) => [tool, await this.checkTool(tool)])
|
|
630
635
|
);
|
|
631
636
|
return Object.fromEntries(results);
|
|
632
637
|
}
|
|
@@ -654,8 +659,8 @@ var EnvironmentInspector = class {
|
|
|
654
659
|
}
|
|
655
660
|
async getToolPath(toolName) {
|
|
656
661
|
try {
|
|
657
|
-
const isWindows =
|
|
658
|
-
const result = await
|
|
662
|
+
const isWindows = this.platform === "win32";
|
|
663
|
+
const result = await this.runCommandFn(isWindows ? "where" : "which", {
|
|
659
664
|
args: [toolName],
|
|
660
665
|
timeoutMs: this.getToolTimeout(toolName)
|
|
661
666
|
});
|
|
@@ -672,14 +677,12 @@ var EnvironmentInspector = class {
|
|
|
672
677
|
*/
|
|
673
678
|
async getToolShimPath(toolName) {
|
|
674
679
|
try {
|
|
675
|
-
const result = await
|
|
680
|
+
const result = await this.runCommandFn("where", {
|
|
676
681
|
args: [toolName],
|
|
677
682
|
timeoutMs: this.getToolTimeout(toolName)
|
|
678
683
|
});
|
|
679
684
|
const candidates = result.stdout.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
680
|
-
const cmdShim = candidates.find(
|
|
681
|
-
(line) => line.toLowerCase().endsWith(".cmd")
|
|
682
|
-
);
|
|
685
|
+
const cmdShim = candidates.find((line) => line.toLowerCase().endsWith(".cmd"));
|
|
683
686
|
return cmdShim ?? candidates[0];
|
|
684
687
|
} catch {
|
|
685
688
|
return void 0;
|
|
@@ -687,16 +690,16 @@ var EnvironmentInspector = class {
|
|
|
687
690
|
}
|
|
688
691
|
async getToolVersion(toolName) {
|
|
689
692
|
const invocation = await this.getVersionInvocation(toolName);
|
|
690
|
-
const result = await
|
|
693
|
+
const result = await this.runCommandFn(invocation.command, {
|
|
691
694
|
args: invocation.args,
|
|
692
695
|
timeoutMs: this.getToolTimeout(toolName)
|
|
693
696
|
});
|
|
694
697
|
return this.parseVersion(toolName, result.stdout || result.stderr);
|
|
695
698
|
}
|
|
696
699
|
async checkNvm() {
|
|
697
|
-
if (
|
|
700
|
+
if (this.platform === "win32") {
|
|
698
701
|
try {
|
|
699
|
-
const result = await
|
|
702
|
+
const result = await this.runCommandFn("cmd.exe", {
|
|
700
703
|
args: ["/c", "nvm version"],
|
|
701
704
|
timeoutMs: this.getToolTimeout("nvm")
|
|
702
705
|
});
|
|
@@ -713,7 +716,7 @@ var EnvironmentInspector = class {
|
|
|
713
716
|
}
|
|
714
717
|
}
|
|
715
718
|
try {
|
|
716
|
-
const result = await
|
|
719
|
+
const result = await this.runCommandFn("/bin/bash", {
|
|
717
720
|
args: [
|
|
718
721
|
"-lc",
|
|
719
722
|
'export NVM_DIR="$HOME/.nvm"; [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"; nvm --version'
|
|
@@ -741,7 +744,7 @@ var EnvironmentInspector = class {
|
|
|
741
744
|
};
|
|
742
745
|
}
|
|
743
746
|
try {
|
|
744
|
-
const result = await
|
|
747
|
+
const result = await this.runCommandFn("dotnet", {
|
|
745
748
|
args: ["nuget", "list", "source"],
|
|
746
749
|
timeoutMs: this.getToolTimeout("nuget")
|
|
747
750
|
});
|
|
@@ -762,7 +765,7 @@ var EnvironmentInspector = class {
|
|
|
762
765
|
}
|
|
763
766
|
}
|
|
764
767
|
async getVersionInvocation(toolName) {
|
|
765
|
-
const isWindows =
|
|
768
|
+
const isWindows = this.platform === "win32";
|
|
766
769
|
if (isWindows && ["npm", "pnpm", "nrm"].includes(toolName)) {
|
|
767
770
|
const shim = await this.getToolShimPath(toolName);
|
|
768
771
|
if (shim) {
|
|
@@ -1100,52 +1103,45 @@ var import_devtools_protocol7 = require("@serviceme/devtools-protocol");
|
|
|
1100
1103
|
var import_node_fs = require("fs");
|
|
1101
1104
|
var import_promises = require("fs/promises");
|
|
1102
1105
|
var import_node_path = require("path");
|
|
1103
|
-
var import_yauzl = require("yauzl");
|
|
1106
|
+
var import_yauzl = __toESM(require("yauzl"));
|
|
1104
1107
|
var unzipFile = (zipPath, dest) => {
|
|
1105
1108
|
return new Promise((resolve, reject) => {
|
|
1106
|
-
(
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
(
|
|
1110
|
-
|
|
1111
|
-
if (
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
entry
|
|
1123
|
-
(
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
resolve();
|
|
1143
|
-
});
|
|
1144
|
-
zipfile.on("error", (zipError) => {
|
|
1145
|
-
reject(zipError);
|
|
1146
|
-
});
|
|
1147
|
-
}
|
|
1148
|
-
);
|
|
1109
|
+
import_yauzl.default.open(zipPath, { lazyEntries: true }, (err, zipfile) => {
|
|
1110
|
+
if (err) return reject(err);
|
|
1111
|
+
if (!zipfile) return reject(new Error("Failed to open zip file."));
|
|
1112
|
+
zipfile.readEntry();
|
|
1113
|
+
zipfile.on("entry", (entry) => {
|
|
1114
|
+
if (/\/$/.test(entry.fileName)) {
|
|
1115
|
+
void (0, import_promises.mkdir)((0, import_node_path.join)(dest, entry.fileName), { recursive: true }).then(() => {
|
|
1116
|
+
zipfile.readEntry();
|
|
1117
|
+
}).catch(reject);
|
|
1118
|
+
} else {
|
|
1119
|
+
const outputPath = (0, import_node_path.join)(dest, entry.fileName);
|
|
1120
|
+
void (0, import_promises.mkdir)((0, import_node_path.dirname)(outputPath), { recursive: true }).then(() => {
|
|
1121
|
+
zipfile.openReadStream(
|
|
1122
|
+
entry,
|
|
1123
|
+
(streamError, readStream) => {
|
|
1124
|
+
if (streamError) return reject(streamError);
|
|
1125
|
+
if (!readStream) return reject(new Error("Failed to open zip entry stream."));
|
|
1126
|
+
const writeStream = (0, import_node_fs.createWriteStream)(outputPath);
|
|
1127
|
+
readStream.on("error", reject);
|
|
1128
|
+
writeStream.on("error", reject);
|
|
1129
|
+
writeStream.on("close", () => {
|
|
1130
|
+
zipfile.readEntry();
|
|
1131
|
+
});
|
|
1132
|
+
readStream.pipe(writeStream);
|
|
1133
|
+
}
|
|
1134
|
+
);
|
|
1135
|
+
}).catch(reject);
|
|
1136
|
+
}
|
|
1137
|
+
});
|
|
1138
|
+
zipfile.on("end", () => {
|
|
1139
|
+
resolve();
|
|
1140
|
+
});
|
|
1141
|
+
zipfile.on("error", (zipError) => {
|
|
1142
|
+
reject(zipError);
|
|
1143
|
+
});
|
|
1144
|
+
});
|
|
1149
1145
|
});
|
|
1150
1146
|
};
|
|
1151
1147
|
var tryLstat = async (targetPath) => {
|
|
@@ -1169,11 +1165,7 @@ var mergeEntry = async (sourcePath, destPath, overwrite) => {
|
|
|
1169
1165
|
await (0, import_promises.mkdir)(destPath, { recursive: true });
|
|
1170
1166
|
const children = await (0, import_promises.readdir)(sourcePath);
|
|
1171
1167
|
for (const child of children) {
|
|
1172
|
-
await mergeEntry(
|
|
1173
|
-
(0, import_node_path.join)(sourcePath, child),
|
|
1174
|
-
(0, import_node_path.join)(destPath, child),
|
|
1175
|
-
overwrite
|
|
1176
|
-
);
|
|
1168
|
+
await mergeEntry((0, import_node_path.join)(sourcePath, child), (0, import_node_path.join)(destPath, child), overwrite);
|
|
1177
1169
|
}
|
|
1178
1170
|
await (0, import_promises.rm)(sourcePath, { recursive: true, force: true });
|
|
1179
1171
|
return;
|
|
@@ -1263,23 +1255,15 @@ var ProjectTools = class {
|
|
|
1263
1255
|
}
|
|
1264
1256
|
async makeScriptsExecutable(workspacePath) {
|
|
1265
1257
|
const isWindows = process.platform === "win32";
|
|
1266
|
-
const scripts = await this.findScripts(
|
|
1267
|
-
workspacePath,
|
|
1268
|
-
isWindows ? [".ps1", ".bat"] : [".sh"]
|
|
1269
|
-
);
|
|
1258
|
+
const scripts = await this.findScripts(workspacePath, isWindows ? [".ps1", ".bat"] : [".sh"]);
|
|
1270
1259
|
let updatedCount = 0;
|
|
1271
1260
|
if (isWindows) {
|
|
1272
|
-
for (const scriptPath of scripts.filter(
|
|
1273
|
-
(script) => script.endsWith(".ps1")
|
|
1274
|
-
)) {
|
|
1261
|
+
for (const scriptPath of scripts.filter((script) => script.endsWith(".ps1"))) {
|
|
1275
1262
|
try {
|
|
1276
|
-
await runCommand(
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
shell: true
|
|
1281
|
-
}
|
|
1282
|
-
);
|
|
1263
|
+
await runCommand(`powershell -Command "Unblock-File -Path '${scriptPath}'"`, {
|
|
1264
|
+
cwd: workspacePath,
|
|
1265
|
+
shell: true
|
|
1266
|
+
});
|
|
1283
1267
|
updatedCount += 1;
|
|
1284
1268
|
} catch {
|
|
1285
1269
|
}
|
|
@@ -1344,11 +1328,7 @@ var ProjectTools = class {
|
|
|
1344
1328
|
if (await this.pathExists(presetManifestPath)) {
|
|
1345
1329
|
return;
|
|
1346
1330
|
}
|
|
1347
|
-
const projectModePath = path3.join(
|
|
1348
|
-
workspacePath,
|
|
1349
|
-
".ms-scaffold",
|
|
1350
|
-
"project-mode.json"
|
|
1351
|
-
);
|
|
1331
|
+
const projectModePath = path3.join(workspacePath, ".ms-scaffold", "project-mode.json");
|
|
1352
1332
|
if (!await this.pathExists(projectModePath)) {
|
|
1353
1333
|
return;
|
|
1354
1334
|
}
|
|
@@ -1402,9 +1382,7 @@ var ProjectTools = class {
|
|
|
1402
1382
|
if (directoryNames.length === 1) {
|
|
1403
1383
|
return directoryNames[0] ?? null;
|
|
1404
1384
|
}
|
|
1405
|
-
const exactMatch = directoryNames.find(
|
|
1406
|
-
(directoryName) => directoryName === expectedDirName
|
|
1407
|
-
);
|
|
1385
|
+
const exactMatch = directoryNames.find((directoryName) => directoryName === expectedDirName);
|
|
1408
1386
|
if (exactMatch) {
|
|
1409
1387
|
return exactMatch;
|
|
1410
1388
|
}
|
|
@@ -1645,10 +1623,8 @@ var GithubCopilotCliExecutor = class {
|
|
|
1645
1623
|
windowsHide: true
|
|
1646
1624
|
});
|
|
1647
1625
|
if (child.pid) {
|
|
1648
|
-
writeDiagnostic(
|
|
1649
|
-
|
|
1650
|
-
`
|
|
1651
|
-
);
|
|
1626
|
+
writeDiagnostic(`[GithubCopilotCliExecutor] spawned child PID=${child.pid}
|
|
1627
|
+
`);
|
|
1652
1628
|
}
|
|
1653
1629
|
const timeoutMs = execution.timeoutMs;
|
|
1654
1630
|
const timer = timeoutMs != null ? setTimeout(() => {
|
|
@@ -1666,15 +1642,13 @@ var GithubCopilotCliExecutor = class {
|
|
|
1666
1642
|
child.stdout.on("data", (chunk) => {
|
|
1667
1643
|
const data = chunk.toString();
|
|
1668
1644
|
stdoutBuf += data;
|
|
1669
|
-
if (stdoutBuf.length > MAX_OUTPUT_BYTES)
|
|
1670
|
-
stdoutBuf = stdoutBuf.slice(-MAX_OUTPUT_BYTES);
|
|
1645
|
+
if (stdoutBuf.length > MAX_OUTPUT_BYTES) stdoutBuf = stdoutBuf.slice(-MAX_OUTPUT_BYTES);
|
|
1671
1646
|
onOutput("stdout", data);
|
|
1672
1647
|
});
|
|
1673
1648
|
child.stderr.on("data", (chunk) => {
|
|
1674
1649
|
const data = chunk.toString();
|
|
1675
1650
|
stderrBuf += data;
|
|
1676
|
-
if (stderrBuf.length > MAX_OUTPUT_BYTES)
|
|
1677
|
-
stderrBuf = stderrBuf.slice(-MAX_OUTPUT_BYTES);
|
|
1651
|
+
if (stderrBuf.length > MAX_OUTPUT_BYTES) stderrBuf = stderrBuf.slice(-MAX_OUTPUT_BYTES);
|
|
1678
1652
|
onOutput("stderr", data);
|
|
1679
1653
|
});
|
|
1680
1654
|
child.on("close", (code) => {
|
|
@@ -2003,10 +1977,7 @@ function isRecord(value) {
|
|
|
2003
1977
|
}
|
|
2004
1978
|
function requireNonEmptyString(payload, field, taskType) {
|
|
2005
1979
|
if (!isRecord(payload) || typeof payload[field] !== "string" || !payload[field].trim()) {
|
|
2006
|
-
throw (0, import_devtools_protocol8.createServicemeError)(
|
|
2007
|
-
"invalid_payload",
|
|
2008
|
-
`${taskType} payload ${field} is required`
|
|
2009
|
-
);
|
|
1980
|
+
throw (0, import_devtools_protocol8.createServicemeError)("invalid_payload", `${taskType} payload ${field} is required`);
|
|
2010
1981
|
}
|
|
2011
1982
|
}
|
|
2012
1983
|
function validateTaskPayload(taskType, payload) {
|
|
@@ -2169,9 +2140,7 @@ var TaskExecutionEngine = class {
|
|
|
2169
2140
|
if (policy === "reject") {
|
|
2170
2141
|
const existingIds = this.taskExecutions.get(snapshot.taskId);
|
|
2171
2142
|
if (existingIds && existingIds.size > 0) {
|
|
2172
|
-
throw new Error(
|
|
2173
|
-
`TASK_ALREADY_RUNNING: Task ${snapshot.taskId} is already running`
|
|
2174
|
-
);
|
|
2143
|
+
throw new Error(`TASK_ALREADY_RUNNING: Task ${snapshot.taskId} is already running`);
|
|
2175
2144
|
}
|
|
2176
2145
|
}
|
|
2177
2146
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -2436,7 +2405,7 @@ var TaskLogManager = class {
|
|
|
2436
2405
|
var TICK_INTERVAL = 1e3;
|
|
2437
2406
|
var MIN_SCHEDULE_INTERVAL = 1e3;
|
|
2438
2407
|
var SchedulerDaemon = class {
|
|
2439
|
-
constructor(workspacePath) {
|
|
2408
|
+
constructor(workspacePath, options = {}) {
|
|
2440
2409
|
this.tickTimer = null;
|
|
2441
2410
|
this.watcher = null;
|
|
2442
2411
|
this.running = false;
|
|
@@ -2449,6 +2418,7 @@ var SchedulerDaemon = class {
|
|
|
2449
2418
|
this.logManager = new TaskLogManager(workspacePath);
|
|
2450
2419
|
this.pidManager = new PidManager(workspacePath);
|
|
2451
2420
|
this.logger = new DaemonLogger(workspacePath);
|
|
2421
|
+
this.getExecutor = options.getExecutor ?? getExecutor;
|
|
2452
2422
|
}
|
|
2453
2423
|
start() {
|
|
2454
2424
|
if (this.running) return;
|
|
@@ -2554,7 +2524,7 @@ var SchedulerDaemon = class {
|
|
|
2554
2524
|
this.workspacePath
|
|
2555
2525
|
);
|
|
2556
2526
|
validateTaskPayload(task.taskType, executionPayload);
|
|
2557
|
-
const executor = getExecutor(task.taskType);
|
|
2527
|
+
const executor = this.getExecutor(task.taskType);
|
|
2558
2528
|
const result = await executor.execute(executionPayload);
|
|
2559
2529
|
const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2560
2530
|
const durationMs = Date.now() - startMs;
|
|
@@ -2659,10 +2629,10 @@ var SkillCatalogClient = class {
|
|
|
2659
2629
|
}
|
|
2660
2630
|
async getCatalog() {
|
|
2661
2631
|
if (!this.baseUrl) {
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2632
|
+
throw (0, import_devtools_protocol9.createServicemeError)(
|
|
2633
|
+
"workspace_not_found",
|
|
2634
|
+
"Skill catalog baseUrl is not configured."
|
|
2635
|
+
);
|
|
2666
2636
|
}
|
|
2667
2637
|
const response = await this.fetchImpl(
|
|
2668
2638
|
`${this.baseUrl}/api/v1/marketplace/skills`
|
package/dist/index.mjs
CHANGED
|
@@ -14,10 +14,10 @@ var AgentCatalogClient = class {
|
|
|
14
14
|
}
|
|
15
15
|
async getCatalog() {
|
|
16
16
|
if (!this.baseUrl) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
throw createServicemeError(
|
|
18
|
+
"workspace_not_found",
|
|
19
|
+
"Agent catalog baseUrl is not configured."
|
|
20
|
+
);
|
|
21
21
|
}
|
|
22
22
|
const response = await this.fetchImpl(
|
|
23
23
|
`${this.baseUrl}/api/v1/marketplace/agents`
|
|
@@ -474,7 +474,8 @@ function createCopilotAuthRequiredError() {
|
|
|
474
474
|
// src/copilot/prompt.ts
|
|
475
475
|
import {
|
|
476
476
|
COPILOT_ERROR_CODES as COPILOT_ERROR_CODES2,
|
|
477
|
-
createServicemeError as createServicemeError3
|
|
477
|
+
createServicemeError as createServicemeError3,
|
|
478
|
+
ServicemeProtocolError
|
|
478
479
|
} from "@serviceme/devtools-protocol";
|
|
479
480
|
var COPILOT_COMMAND2 = "copilot";
|
|
480
481
|
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
@@ -517,6 +518,9 @@ async function copilotPrompt(options) {
|
|
|
517
518
|
}
|
|
518
519
|
return { output, exitCode: 0 };
|
|
519
520
|
} catch (error) {
|
|
521
|
+
if (error instanceof ServicemeProtocolError) {
|
|
522
|
+
throw error;
|
|
523
|
+
}
|
|
520
524
|
const err = error;
|
|
521
525
|
if (err.code === "ETIMEDOUT") {
|
|
522
526
|
throw createServicemeError3(
|
|
@@ -565,11 +569,13 @@ var TOOL_CHECK_TIMEOUT_MS = {
|
|
|
565
569
|
var ERROR_CODE_NOT_FOUND = 127;
|
|
566
570
|
var ERROR_CODE_TIMEOUT = "ETIMEDOUT";
|
|
567
571
|
var EnvironmentInspector = class {
|
|
572
|
+
constructor(options = {}) {
|
|
573
|
+
this.runCommandFn = options.runCommand ?? runCommand;
|
|
574
|
+
this.platform = options.platform ?? process.platform;
|
|
575
|
+
}
|
|
568
576
|
async checkEnvironment() {
|
|
569
577
|
const results = await Promise.all(
|
|
570
|
-
KNOWN_ENVIRONMENT_TOOLS.map(
|
|
571
|
-
async (tool) => [tool, await this.checkTool(tool)]
|
|
572
|
-
)
|
|
578
|
+
KNOWN_ENVIRONMENT_TOOLS.map(async (tool) => [tool, await this.checkTool(tool)])
|
|
573
579
|
);
|
|
574
580
|
return Object.fromEntries(results);
|
|
575
581
|
}
|
|
@@ -597,8 +603,8 @@ var EnvironmentInspector = class {
|
|
|
597
603
|
}
|
|
598
604
|
async getToolPath(toolName) {
|
|
599
605
|
try {
|
|
600
|
-
const isWindows =
|
|
601
|
-
const result = await
|
|
606
|
+
const isWindows = this.platform === "win32";
|
|
607
|
+
const result = await this.runCommandFn(isWindows ? "where" : "which", {
|
|
602
608
|
args: [toolName],
|
|
603
609
|
timeoutMs: this.getToolTimeout(toolName)
|
|
604
610
|
});
|
|
@@ -615,14 +621,12 @@ var EnvironmentInspector = class {
|
|
|
615
621
|
*/
|
|
616
622
|
async getToolShimPath(toolName) {
|
|
617
623
|
try {
|
|
618
|
-
const result = await
|
|
624
|
+
const result = await this.runCommandFn("where", {
|
|
619
625
|
args: [toolName],
|
|
620
626
|
timeoutMs: this.getToolTimeout(toolName)
|
|
621
627
|
});
|
|
622
628
|
const candidates = result.stdout.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
623
|
-
const cmdShim = candidates.find(
|
|
624
|
-
(line) => line.toLowerCase().endsWith(".cmd")
|
|
625
|
-
);
|
|
629
|
+
const cmdShim = candidates.find((line) => line.toLowerCase().endsWith(".cmd"));
|
|
626
630
|
return cmdShim ?? candidates[0];
|
|
627
631
|
} catch {
|
|
628
632
|
return void 0;
|
|
@@ -630,16 +634,16 @@ var EnvironmentInspector = class {
|
|
|
630
634
|
}
|
|
631
635
|
async getToolVersion(toolName) {
|
|
632
636
|
const invocation = await this.getVersionInvocation(toolName);
|
|
633
|
-
const result = await
|
|
637
|
+
const result = await this.runCommandFn(invocation.command, {
|
|
634
638
|
args: invocation.args,
|
|
635
639
|
timeoutMs: this.getToolTimeout(toolName)
|
|
636
640
|
});
|
|
637
641
|
return this.parseVersion(toolName, result.stdout || result.stderr);
|
|
638
642
|
}
|
|
639
643
|
async checkNvm() {
|
|
640
|
-
if (
|
|
644
|
+
if (this.platform === "win32") {
|
|
641
645
|
try {
|
|
642
|
-
const result = await
|
|
646
|
+
const result = await this.runCommandFn("cmd.exe", {
|
|
643
647
|
args: ["/c", "nvm version"],
|
|
644
648
|
timeoutMs: this.getToolTimeout("nvm")
|
|
645
649
|
});
|
|
@@ -656,7 +660,7 @@ var EnvironmentInspector = class {
|
|
|
656
660
|
}
|
|
657
661
|
}
|
|
658
662
|
try {
|
|
659
|
-
const result = await
|
|
663
|
+
const result = await this.runCommandFn("/bin/bash", {
|
|
660
664
|
args: [
|
|
661
665
|
"-lc",
|
|
662
666
|
'export NVM_DIR="$HOME/.nvm"; [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"; nvm --version'
|
|
@@ -684,7 +688,7 @@ var EnvironmentInspector = class {
|
|
|
684
688
|
};
|
|
685
689
|
}
|
|
686
690
|
try {
|
|
687
|
-
const result = await
|
|
691
|
+
const result = await this.runCommandFn("dotnet", {
|
|
688
692
|
args: ["nuget", "list", "source"],
|
|
689
693
|
timeoutMs: this.getToolTimeout("nuget")
|
|
690
694
|
});
|
|
@@ -705,7 +709,7 @@ var EnvironmentInspector = class {
|
|
|
705
709
|
}
|
|
706
710
|
}
|
|
707
711
|
async getVersionInvocation(toolName) {
|
|
708
|
-
const isWindows =
|
|
712
|
+
const isWindows = this.platform === "win32";
|
|
709
713
|
if (isWindows && ["npm", "pnpm", "nrm"].includes(toolName)) {
|
|
710
714
|
const shim = await this.getToolShimPath(toolName);
|
|
711
715
|
if (shim) {
|
|
@@ -1048,62 +1052,47 @@ import {
|
|
|
1048
1052
|
|
|
1049
1053
|
// src/utils/fileUtils.ts
|
|
1050
1054
|
import { constants, createWriteStream } from "fs";
|
|
1051
|
-
import {
|
|
1052
|
-
access as access2,
|
|
1053
|
-
copyFile,
|
|
1054
|
-
lstat,
|
|
1055
|
-
mkdir,
|
|
1056
|
-
readdir,
|
|
1057
|
-
rename,
|
|
1058
|
-
rm
|
|
1059
|
-
} from "fs/promises";
|
|
1055
|
+
import { access as access2, copyFile, lstat, mkdir, readdir, rename, rm } from "fs/promises";
|
|
1060
1056
|
import { dirname as dirname3, join as join3 } from "path";
|
|
1061
|
-
import
|
|
1057
|
+
import yauzl from "yauzl";
|
|
1062
1058
|
var unzipFile = (zipPath, dest) => {
|
|
1063
1059
|
return new Promise((resolve, reject) => {
|
|
1064
|
-
open(
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
(
|
|
1068
|
-
|
|
1069
|
-
if (
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
entry
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
resolve();
|
|
1101
|
-
});
|
|
1102
|
-
zipfile.on("error", (zipError) => {
|
|
1103
|
-
reject(zipError);
|
|
1104
|
-
});
|
|
1105
|
-
}
|
|
1106
|
-
);
|
|
1060
|
+
yauzl.open(zipPath, { lazyEntries: true }, (err, zipfile) => {
|
|
1061
|
+
if (err) return reject(err);
|
|
1062
|
+
if (!zipfile) return reject(new Error("Failed to open zip file."));
|
|
1063
|
+
zipfile.readEntry();
|
|
1064
|
+
zipfile.on("entry", (entry) => {
|
|
1065
|
+
if (/\/$/.test(entry.fileName)) {
|
|
1066
|
+
void mkdir(join3(dest, entry.fileName), { recursive: true }).then(() => {
|
|
1067
|
+
zipfile.readEntry();
|
|
1068
|
+
}).catch(reject);
|
|
1069
|
+
} else {
|
|
1070
|
+
const outputPath = join3(dest, entry.fileName);
|
|
1071
|
+
void mkdir(dirname3(outputPath), { recursive: true }).then(() => {
|
|
1072
|
+
zipfile.openReadStream(
|
|
1073
|
+
entry,
|
|
1074
|
+
(streamError, readStream) => {
|
|
1075
|
+
if (streamError) return reject(streamError);
|
|
1076
|
+
if (!readStream) return reject(new Error("Failed to open zip entry stream."));
|
|
1077
|
+
const writeStream = createWriteStream(outputPath);
|
|
1078
|
+
readStream.on("error", reject);
|
|
1079
|
+
writeStream.on("error", reject);
|
|
1080
|
+
writeStream.on("close", () => {
|
|
1081
|
+
zipfile.readEntry();
|
|
1082
|
+
});
|
|
1083
|
+
readStream.pipe(writeStream);
|
|
1084
|
+
}
|
|
1085
|
+
);
|
|
1086
|
+
}).catch(reject);
|
|
1087
|
+
}
|
|
1088
|
+
});
|
|
1089
|
+
zipfile.on("end", () => {
|
|
1090
|
+
resolve();
|
|
1091
|
+
});
|
|
1092
|
+
zipfile.on("error", (zipError) => {
|
|
1093
|
+
reject(zipError);
|
|
1094
|
+
});
|
|
1095
|
+
});
|
|
1107
1096
|
});
|
|
1108
1097
|
};
|
|
1109
1098
|
var tryLstat = async (targetPath) => {
|
|
@@ -1127,11 +1116,7 @@ var mergeEntry = async (sourcePath, destPath, overwrite) => {
|
|
|
1127
1116
|
await mkdir(destPath, { recursive: true });
|
|
1128
1117
|
const children = await readdir(sourcePath);
|
|
1129
1118
|
for (const child of children) {
|
|
1130
|
-
await mergeEntry(
|
|
1131
|
-
join3(sourcePath, child),
|
|
1132
|
-
join3(destPath, child),
|
|
1133
|
-
overwrite
|
|
1134
|
-
);
|
|
1119
|
+
await mergeEntry(join3(sourcePath, child), join3(destPath, child), overwrite);
|
|
1135
1120
|
}
|
|
1136
1121
|
await rm(sourcePath, { recursive: true, force: true });
|
|
1137
1122
|
return;
|
|
@@ -1221,23 +1206,15 @@ var ProjectTools = class {
|
|
|
1221
1206
|
}
|
|
1222
1207
|
async makeScriptsExecutable(workspacePath) {
|
|
1223
1208
|
const isWindows = process.platform === "win32";
|
|
1224
|
-
const scripts = await this.findScripts(
|
|
1225
|
-
workspacePath,
|
|
1226
|
-
isWindows ? [".ps1", ".bat"] : [".sh"]
|
|
1227
|
-
);
|
|
1209
|
+
const scripts = await this.findScripts(workspacePath, isWindows ? [".ps1", ".bat"] : [".sh"]);
|
|
1228
1210
|
let updatedCount = 0;
|
|
1229
1211
|
if (isWindows) {
|
|
1230
|
-
for (const scriptPath of scripts.filter(
|
|
1231
|
-
(script) => script.endsWith(".ps1")
|
|
1232
|
-
)) {
|
|
1212
|
+
for (const scriptPath of scripts.filter((script) => script.endsWith(".ps1"))) {
|
|
1233
1213
|
try {
|
|
1234
|
-
await runCommand(
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
shell: true
|
|
1239
|
-
}
|
|
1240
|
-
);
|
|
1214
|
+
await runCommand(`powershell -Command "Unblock-File -Path '${scriptPath}'"`, {
|
|
1215
|
+
cwd: workspacePath,
|
|
1216
|
+
shell: true
|
|
1217
|
+
});
|
|
1241
1218
|
updatedCount += 1;
|
|
1242
1219
|
} catch {
|
|
1243
1220
|
}
|
|
@@ -1302,11 +1279,7 @@ var ProjectTools = class {
|
|
|
1302
1279
|
if (await this.pathExists(presetManifestPath)) {
|
|
1303
1280
|
return;
|
|
1304
1281
|
}
|
|
1305
|
-
const projectModePath = path3.join(
|
|
1306
|
-
workspacePath,
|
|
1307
|
-
".ms-scaffold",
|
|
1308
|
-
"project-mode.json"
|
|
1309
|
-
);
|
|
1282
|
+
const projectModePath = path3.join(workspacePath, ".ms-scaffold", "project-mode.json");
|
|
1310
1283
|
if (!await this.pathExists(projectModePath)) {
|
|
1311
1284
|
return;
|
|
1312
1285
|
}
|
|
@@ -1360,9 +1333,7 @@ var ProjectTools = class {
|
|
|
1360
1333
|
if (directoryNames.length === 1) {
|
|
1361
1334
|
return directoryNames[0] ?? null;
|
|
1362
1335
|
}
|
|
1363
|
-
const exactMatch = directoryNames.find(
|
|
1364
|
-
(directoryName) => directoryName === expectedDirName
|
|
1365
|
-
);
|
|
1336
|
+
const exactMatch = directoryNames.find((directoryName) => directoryName === expectedDirName);
|
|
1366
1337
|
if (exactMatch) {
|
|
1367
1338
|
return exactMatch;
|
|
1368
1339
|
}
|
|
@@ -1603,10 +1574,8 @@ var GithubCopilotCliExecutor = class {
|
|
|
1603
1574
|
windowsHide: true
|
|
1604
1575
|
});
|
|
1605
1576
|
if (child.pid) {
|
|
1606
|
-
writeDiagnostic(
|
|
1607
|
-
|
|
1608
|
-
`
|
|
1609
|
-
);
|
|
1577
|
+
writeDiagnostic(`[GithubCopilotCliExecutor] spawned child PID=${child.pid}
|
|
1578
|
+
`);
|
|
1610
1579
|
}
|
|
1611
1580
|
const timeoutMs = execution.timeoutMs;
|
|
1612
1581
|
const timer = timeoutMs != null ? setTimeout(() => {
|
|
@@ -1624,15 +1593,13 @@ var GithubCopilotCliExecutor = class {
|
|
|
1624
1593
|
child.stdout.on("data", (chunk) => {
|
|
1625
1594
|
const data = chunk.toString();
|
|
1626
1595
|
stdoutBuf += data;
|
|
1627
|
-
if (stdoutBuf.length > MAX_OUTPUT_BYTES)
|
|
1628
|
-
stdoutBuf = stdoutBuf.slice(-MAX_OUTPUT_BYTES);
|
|
1596
|
+
if (stdoutBuf.length > MAX_OUTPUT_BYTES) stdoutBuf = stdoutBuf.slice(-MAX_OUTPUT_BYTES);
|
|
1629
1597
|
onOutput("stdout", data);
|
|
1630
1598
|
});
|
|
1631
1599
|
child.stderr.on("data", (chunk) => {
|
|
1632
1600
|
const data = chunk.toString();
|
|
1633
1601
|
stderrBuf += data;
|
|
1634
|
-
if (stderrBuf.length > MAX_OUTPUT_BYTES)
|
|
1635
|
-
stderrBuf = stderrBuf.slice(-MAX_OUTPUT_BYTES);
|
|
1602
|
+
if (stderrBuf.length > MAX_OUTPUT_BYTES) stderrBuf = stderrBuf.slice(-MAX_OUTPUT_BYTES);
|
|
1636
1603
|
onOutput("stderr", data);
|
|
1637
1604
|
});
|
|
1638
1605
|
child.on("close", (code) => {
|
|
@@ -1961,10 +1928,7 @@ function isRecord(value) {
|
|
|
1961
1928
|
}
|
|
1962
1929
|
function requireNonEmptyString(payload, field, taskType) {
|
|
1963
1930
|
if (!isRecord(payload) || typeof payload[field] !== "string" || !payload[field].trim()) {
|
|
1964
|
-
throw createServicemeError8(
|
|
1965
|
-
"invalid_payload",
|
|
1966
|
-
`${taskType} payload ${field} is required`
|
|
1967
|
-
);
|
|
1931
|
+
throw createServicemeError8("invalid_payload", `${taskType} payload ${field} is required`);
|
|
1968
1932
|
}
|
|
1969
1933
|
}
|
|
1970
1934
|
function validateTaskPayload(taskType, payload) {
|
|
@@ -2127,9 +2091,7 @@ var TaskExecutionEngine = class {
|
|
|
2127
2091
|
if (policy === "reject") {
|
|
2128
2092
|
const existingIds = this.taskExecutions.get(snapshot.taskId);
|
|
2129
2093
|
if (existingIds && existingIds.size > 0) {
|
|
2130
|
-
throw new Error(
|
|
2131
|
-
`TASK_ALREADY_RUNNING: Task ${snapshot.taskId} is already running`
|
|
2132
|
-
);
|
|
2094
|
+
throw new Error(`TASK_ALREADY_RUNNING: Task ${snapshot.taskId} is already running`);
|
|
2133
2095
|
}
|
|
2134
2096
|
}
|
|
2135
2097
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -2394,7 +2356,7 @@ var TaskLogManager = class {
|
|
|
2394
2356
|
var TICK_INTERVAL = 1e3;
|
|
2395
2357
|
var MIN_SCHEDULE_INTERVAL = 1e3;
|
|
2396
2358
|
var SchedulerDaemon = class {
|
|
2397
|
-
constructor(workspacePath) {
|
|
2359
|
+
constructor(workspacePath, options = {}) {
|
|
2398
2360
|
this.tickTimer = null;
|
|
2399
2361
|
this.watcher = null;
|
|
2400
2362
|
this.running = false;
|
|
@@ -2407,6 +2369,7 @@ var SchedulerDaemon = class {
|
|
|
2407
2369
|
this.logManager = new TaskLogManager(workspacePath);
|
|
2408
2370
|
this.pidManager = new PidManager(workspacePath);
|
|
2409
2371
|
this.logger = new DaemonLogger(workspacePath);
|
|
2372
|
+
this.getExecutor = options.getExecutor ?? getExecutor;
|
|
2410
2373
|
}
|
|
2411
2374
|
start() {
|
|
2412
2375
|
if (this.running) return;
|
|
@@ -2512,7 +2475,7 @@ var SchedulerDaemon = class {
|
|
|
2512
2475
|
this.workspacePath
|
|
2513
2476
|
);
|
|
2514
2477
|
validateTaskPayload(task.taskType, executionPayload);
|
|
2515
|
-
const executor = getExecutor(task.taskType);
|
|
2478
|
+
const executor = this.getExecutor(task.taskType);
|
|
2516
2479
|
const result = await executor.execute(executionPayload);
|
|
2517
2480
|
const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2518
2481
|
const durationMs = Date.now() - startMs;
|
|
@@ -2617,10 +2580,10 @@ var SkillCatalogClient = class {
|
|
|
2617
2580
|
}
|
|
2618
2581
|
async getCatalog() {
|
|
2619
2582
|
if (!this.baseUrl) {
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2583
|
+
throw createServicemeError9(
|
|
2584
|
+
"workspace_not_found",
|
|
2585
|
+
"Skill catalog baseUrl is not configured."
|
|
2586
|
+
);
|
|
2624
2587
|
}
|
|
2625
2588
|
const response = await this.fetchImpl(
|
|
2626
2589
|
`${this.baseUrl}/api/v1/marketplace/skills`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@serviceme/devtools-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "Reusable Node.js core capabilities powering the SERVICEME CLI and integrations.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"repository": {
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"comment-json": "^4.5.1",
|
|
37
37
|
"json5": "^2.2.3",
|
|
38
38
|
"yauzl": "^3.2.0",
|
|
39
|
-
"@serviceme/devtools-protocol": "0.1.
|
|
39
|
+
"@serviceme/devtools-protocol": "0.1.9"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/node": "^24",
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
},
|
|
48
48
|
"scripts": {
|
|
49
49
|
"watch": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
50
|
+
"lint": "biome check src test",
|
|
50
51
|
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
51
52
|
"typecheck": "tsc --noEmit",
|
|
52
53
|
"test": "pnpm run build && node --test test/**/*.test.js && node --import tsx --test src/**/__tests__/**/*.test.ts",
|