@serviceme/devtools-cli 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bridgeServer.js +280 -68
- package/dist/cli.js +648 -289
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
var child_process = require('child_process');
|
|
5
5
|
var fs2 = require('fs/promises');
|
|
6
6
|
var path = require('path');
|
|
7
|
-
var
|
|
7
|
+
var fs8 = require('fs');
|
|
8
8
|
var crypto = require('crypto');
|
|
9
|
+
var os = require('os');
|
|
9
10
|
var readline = require('readline');
|
|
10
11
|
|
|
11
12
|
function _interopNamespace(e) {
|
|
@@ -28,7 +29,8 @@ function _interopNamespace(e) {
|
|
|
28
29
|
|
|
29
30
|
var fs2__namespace = /*#__PURE__*/_interopNamespace(fs2);
|
|
30
31
|
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
31
|
-
var
|
|
32
|
+
var fs8__namespace = /*#__PURE__*/_interopNamespace(fs8);
|
|
33
|
+
var os__namespace = /*#__PURE__*/_interopNamespace(os);
|
|
32
34
|
var readline__namespace = /*#__PURE__*/_interopNamespace(readline);
|
|
33
35
|
|
|
34
36
|
var __create = Object.create;
|
|
@@ -360,7 +362,8 @@ async function runCommand(command, options2 = {}) {
|
|
|
360
362
|
cwd: options2.cwd,
|
|
361
363
|
env: options2.env,
|
|
362
364
|
shell: options2.shell,
|
|
363
|
-
stdio: "pipe"
|
|
365
|
+
stdio: "pipe",
|
|
366
|
+
windowsHide: true
|
|
364
367
|
});
|
|
365
368
|
let stdout = "";
|
|
366
369
|
let stderr = "";
|
|
@@ -1126,9 +1129,9 @@ var require_esprima = __commonJS({
|
|
|
1126
1129
|
});
|
|
1127
1130
|
};
|
|
1128
1131
|
CommentHandler2.prototype.visitComment = function(node, metadata) {
|
|
1129
|
-
var
|
|
1132
|
+
var type2 = node.type[0] === "L" ? "Line" : "Block";
|
|
1130
1133
|
var comment = {
|
|
1131
|
-
type,
|
|
1134
|
+
type: type2,
|
|
1132
1135
|
value: node.value
|
|
1133
1136
|
};
|
|
1134
1137
|
if (node.range) {
|
|
@@ -1141,7 +1144,7 @@ var require_esprima = __commonJS({
|
|
|
1141
1144
|
if (this.attach) {
|
|
1142
1145
|
var entry = {
|
|
1143
1146
|
comment: {
|
|
1144
|
-
type,
|
|
1147
|
+
type: type2,
|
|
1145
1148
|
value: node.value,
|
|
1146
1149
|
range: [metadata.start.offset, metadata.end.offset]
|
|
1147
1150
|
},
|
|
@@ -1150,7 +1153,7 @@ var require_esprima = __commonJS({
|
|
|
1150
1153
|
if (node.loc) {
|
|
1151
1154
|
entry.comment.loc = node.loc;
|
|
1152
1155
|
}
|
|
1153
|
-
node.type =
|
|
1156
|
+
node.type = type2;
|
|
1154
1157
|
this.leading.push(entry);
|
|
1155
1158
|
this.trailing.push(entry);
|
|
1156
1159
|
}
|
|
@@ -5965,28 +5968,28 @@ var require_esprima = __commonJS({
|
|
|
5965
5968
|
};
|
|
5966
5969
|
};
|
|
5967
5970
|
Scanner2.prototype.scanIdentifier = function() {
|
|
5968
|
-
var
|
|
5971
|
+
var type2;
|
|
5969
5972
|
var start = this.index;
|
|
5970
5973
|
var id = this.source.charCodeAt(start) === 92 ? this.getComplexIdentifier() : this.getIdentifier();
|
|
5971
5974
|
if (id.length === 1) {
|
|
5972
|
-
|
|
5975
|
+
type2 = 3;
|
|
5973
5976
|
} else if (this.isKeyword(id)) {
|
|
5974
|
-
|
|
5977
|
+
type2 = 4;
|
|
5975
5978
|
} else if (id === "null") {
|
|
5976
|
-
|
|
5979
|
+
type2 = 5;
|
|
5977
5980
|
} else if (id === "true" || id === "false") {
|
|
5978
|
-
|
|
5981
|
+
type2 = 1;
|
|
5979
5982
|
} else {
|
|
5980
|
-
|
|
5983
|
+
type2 = 3;
|
|
5981
5984
|
}
|
|
5982
|
-
if (
|
|
5985
|
+
if (type2 !== 3 && start + id.length !== this.index) {
|
|
5983
5986
|
var restore = this.index;
|
|
5984
5987
|
this.index = start;
|
|
5985
5988
|
this.tolerateUnexpectedToken(messages_1.Messages.InvalidEscapedReservedWord);
|
|
5986
5989
|
this.index = restore;
|
|
5987
5990
|
}
|
|
5988
5991
|
return {
|
|
5989
|
-
type,
|
|
5992
|
+
type: type2,
|
|
5990
5993
|
value: id,
|
|
5991
5994
|
lineNumber: this.lineNumber,
|
|
5992
5995
|
lineStart: this.lineStart,
|
|
@@ -8437,13 +8440,13 @@ var require_parse = __commonJS({
|
|
|
8437
8440
|
last = current;
|
|
8438
8441
|
current = new_token;
|
|
8439
8442
|
};
|
|
8440
|
-
var
|
|
8443
|
+
var type2 = () => {
|
|
8441
8444
|
if (!current) {
|
|
8442
8445
|
unexpected_end();
|
|
8443
8446
|
}
|
|
8444
8447
|
return current.type === "Punctuator" ? current.value : current.type;
|
|
8445
8448
|
};
|
|
8446
|
-
var is = (t) =>
|
|
8449
|
+
var is = (t) => type2() === t;
|
|
8447
8450
|
var expect = (a) => {
|
|
8448
8451
|
if (!is(a)) {
|
|
8449
8452
|
unexpected();
|
|
@@ -8598,7 +8601,7 @@ var require_parse = __commonJS({
|
|
|
8598
8601
|
return array;
|
|
8599
8602
|
};
|
|
8600
8603
|
function walk() {
|
|
8601
|
-
let tt =
|
|
8604
|
+
let tt = type2();
|
|
8602
8605
|
if (tt === CURLY_BRACKET_OPEN) {
|
|
8603
8606
|
next();
|
|
8604
8607
|
return {
|
|
@@ -8614,7 +8617,7 @@ var require_parse = __commonJS({
|
|
|
8614
8617
|
let negative = EMPTY;
|
|
8615
8618
|
if (tt === MINUS) {
|
|
8616
8619
|
next();
|
|
8617
|
-
tt =
|
|
8620
|
+
tt = type2();
|
|
8618
8621
|
negative = MINUS;
|
|
8619
8622
|
}
|
|
8620
8623
|
let v;
|
|
@@ -8740,11 +8743,11 @@ var require_stringify = __commonJS({
|
|
|
8740
8743
|
let is_line_comment = false;
|
|
8741
8744
|
const str = comments.reduce((prev, {
|
|
8742
8745
|
inline,
|
|
8743
|
-
type,
|
|
8746
|
+
type: type2,
|
|
8744
8747
|
value
|
|
8745
8748
|
}) => {
|
|
8746
8749
|
const delimiter = inline ? SPACE : LF + deeper_gap;
|
|
8747
|
-
is_line_comment =
|
|
8750
|
+
is_line_comment = type2 === "LineComment";
|
|
8748
8751
|
return prev + delimiter + comment_stringify(value, is_line_comment);
|
|
8749
8752
|
}, EMPTY);
|
|
8750
8753
|
return display_block || is_line_comment ? str + LF + deeper_gap : str;
|
|
@@ -8984,9 +8987,9 @@ function read() {
|
|
|
8984
8987
|
}
|
|
8985
8988
|
return c2;
|
|
8986
8989
|
}
|
|
8987
|
-
function newToken(
|
|
8990
|
+
function newToken(type2, value) {
|
|
8988
8991
|
return {
|
|
8989
|
-
type,
|
|
8992
|
+
type: type2,
|
|
8990
8993
|
value,
|
|
8991
8994
|
line,
|
|
8992
8995
|
column
|
|
@@ -10192,7 +10195,7 @@ var require_pend = __commonJS({
|
|
|
10192
10195
|
// ../../node_modules/.pnpm/yauzl@3.2.0/node_modules/yauzl/fd-slicer.js
|
|
10193
10196
|
var require_fd_slicer = __commonJS({
|
|
10194
10197
|
"../../node_modules/.pnpm/yauzl@3.2.0/node_modules/yauzl/fd-slicer.js"(exports$1) {
|
|
10195
|
-
var
|
|
10198
|
+
var fs13 = __require("fs");
|
|
10196
10199
|
var util2 = __require("util");
|
|
10197
10200
|
var stream = __require("stream");
|
|
10198
10201
|
var Readable = stream.Readable;
|
|
@@ -10217,7 +10220,7 @@ var require_fd_slicer = __commonJS({
|
|
|
10217
10220
|
FdSlicer.prototype.read = function(buffer2, offset, length, position, callback) {
|
|
10218
10221
|
var self = this;
|
|
10219
10222
|
self.pend.go(function(cb) {
|
|
10220
|
-
|
|
10223
|
+
fs13.read(self.fd, buffer2, offset, length, position, function(err, bytesRead, buffer3) {
|
|
10221
10224
|
cb();
|
|
10222
10225
|
callback(err, bytesRead, buffer3);
|
|
10223
10226
|
});
|
|
@@ -10226,7 +10229,7 @@ var require_fd_slicer = __commonJS({
|
|
|
10226
10229
|
FdSlicer.prototype.write = function(buffer2, offset, length, position, callback) {
|
|
10227
10230
|
var self = this;
|
|
10228
10231
|
self.pend.go(function(cb) {
|
|
10229
|
-
|
|
10232
|
+
fs13.write(self.fd, buffer2, offset, length, position, function(err, written, buffer3) {
|
|
10230
10233
|
cb();
|
|
10231
10234
|
callback(err, written, buffer3);
|
|
10232
10235
|
});
|
|
@@ -10247,7 +10250,7 @@ var require_fd_slicer = __commonJS({
|
|
|
10247
10250
|
if (self.refCount > 0) return;
|
|
10248
10251
|
if (self.refCount < 0) throw new Error("invalid unref");
|
|
10249
10252
|
if (self.autoClose) {
|
|
10250
|
-
|
|
10253
|
+
fs13.close(self.fd, onCloseDone);
|
|
10251
10254
|
}
|
|
10252
10255
|
function onCloseDone(err) {
|
|
10253
10256
|
if (err) {
|
|
@@ -10284,7 +10287,7 @@ var require_fd_slicer = __commonJS({
|
|
|
10284
10287
|
self.context.pend.go(function(cb) {
|
|
10285
10288
|
if (self.destroyed) return cb();
|
|
10286
10289
|
var buffer2 = Buffer.allocUnsafe(toRead);
|
|
10287
|
-
|
|
10290
|
+
fs13.read(self.context.fd, buffer2, 0, toRead, self.pos, function(err, bytesRead) {
|
|
10288
10291
|
if (err) {
|
|
10289
10292
|
self.destroy(err);
|
|
10290
10293
|
} else if (bytesRead === 0) {
|
|
@@ -10331,7 +10334,7 @@ var require_fd_slicer = __commonJS({
|
|
|
10331
10334
|
}
|
|
10332
10335
|
self.context.pend.go(function(cb) {
|
|
10333
10336
|
if (self.destroyed) return cb();
|
|
10334
|
-
|
|
10337
|
+
fs13.write(self.context.fd, buffer2, 0, buffer2.length, self.pos, function(err2, bytes) {
|
|
10335
10338
|
if (err2) {
|
|
10336
10339
|
self.destroy();
|
|
10337
10340
|
cb();
|
|
@@ -10769,7 +10772,7 @@ var require_buffer_crc32 = __commonJS({
|
|
|
10769
10772
|
// ../../node_modules/.pnpm/yauzl@3.2.0/node_modules/yauzl/index.js
|
|
10770
10773
|
var require_yauzl = __commonJS({
|
|
10771
10774
|
"../../node_modules/.pnpm/yauzl@3.2.0/node_modules/yauzl/index.js"(exports$1) {
|
|
10772
|
-
var
|
|
10775
|
+
var fs13 = __require("fs");
|
|
10773
10776
|
var zlib = __require("zlib");
|
|
10774
10777
|
var fd_slicer = require_fd_slicer();
|
|
10775
10778
|
var crc32 = require_buffer_crc32();
|
|
@@ -10790,7 +10793,7 @@ var require_yauzl = __commonJS({
|
|
|
10790
10793
|
exports$1.Entry = Entry;
|
|
10791
10794
|
exports$1.LocalFileHeader = LocalFileHeader;
|
|
10792
10795
|
exports$1.RandomAccessReader = RandomAccessReader;
|
|
10793
|
-
function open2(
|
|
10796
|
+
function open2(path9, options2, callback) {
|
|
10794
10797
|
if (typeof options2 === "function") {
|
|
10795
10798
|
callback = options2;
|
|
10796
10799
|
options2 = null;
|
|
@@ -10802,10 +10805,10 @@ var require_yauzl = __commonJS({
|
|
|
10802
10805
|
if (options2.validateEntrySizes == null) options2.validateEntrySizes = true;
|
|
10803
10806
|
if (options2.strictFileNames == null) options2.strictFileNames = false;
|
|
10804
10807
|
if (callback == null) callback = defaultCallback;
|
|
10805
|
-
|
|
10808
|
+
fs13.open(path9, "r", function(err, fd) {
|
|
10806
10809
|
if (err) return callback(err);
|
|
10807
10810
|
fromFd(fd, options2, function(err2, zipfile) {
|
|
10808
|
-
if (err2)
|
|
10811
|
+
if (err2) fs13.close(fd, defaultCallback);
|
|
10809
10812
|
callback(err2, zipfile);
|
|
10810
10813
|
});
|
|
10811
10814
|
});
|
|
@@ -10822,7 +10825,7 @@ var require_yauzl = __commonJS({
|
|
|
10822
10825
|
if (options2.validateEntrySizes == null) options2.validateEntrySizes = true;
|
|
10823
10826
|
if (options2.strictFileNames == null) options2.strictFileNames = false;
|
|
10824
10827
|
if (callback == null) callback = defaultCallback;
|
|
10825
|
-
|
|
10828
|
+
fs13.fstat(fd, function(err, stats) {
|
|
10826
10829
|
if (err) return callback(err);
|
|
10827
10830
|
var reader = fd_slicer.createFromFd(fd, { autoClose: true });
|
|
10828
10831
|
fromRandomAccessReader(reader, stats.size, options2, callback);
|
|
@@ -11534,7 +11537,7 @@ var init_fileUtils = __esm({
|
|
|
11534
11537
|
return reject(
|
|
11535
11538
|
new Error("Failed to open zip entry stream.")
|
|
11536
11539
|
);
|
|
11537
|
-
const writeStream =
|
|
11540
|
+
const writeStream = fs8.createWriteStream(outputPath);
|
|
11538
11541
|
readStream.on("error", reject);
|
|
11539
11542
|
writeStream.on("error", reject);
|
|
11540
11543
|
writeStream.on("close", () => {
|
|
@@ -11608,7 +11611,7 @@ var init_fileUtils = __esm({
|
|
|
11608
11611
|
const destFile = path.join(destDir, file);
|
|
11609
11612
|
if (!overwrite) {
|
|
11610
11613
|
try {
|
|
11611
|
-
await fs2.access(destFile,
|
|
11614
|
+
await fs2.access(destFile, fs8.constants.F_OK);
|
|
11612
11615
|
await fs2.rm(sourceFile, { recursive: true, force: true });
|
|
11613
11616
|
continue;
|
|
11614
11617
|
} catch {
|
|
@@ -11819,8 +11822,8 @@ var init_DaemonLogger = __esm({
|
|
|
11819
11822
|
constructor(workspacePath) {
|
|
11820
11823
|
this.logPath = path__namespace.join(workspacePath, CONFIG_DIR, LOG_FILE);
|
|
11821
11824
|
const dir = path__namespace.dirname(this.logPath);
|
|
11822
|
-
if (!
|
|
11823
|
-
|
|
11825
|
+
if (!fs8__namespace.existsSync(dir)) {
|
|
11826
|
+
fs8__namespace.mkdirSync(dir, { recursive: true });
|
|
11824
11827
|
}
|
|
11825
11828
|
}
|
|
11826
11829
|
getLogPath() {
|
|
@@ -11831,16 +11834,16 @@ var init_DaemonLogger = __esm({
|
|
|
11831
11834
|
const line2 = `[${ts}] [${level.toUpperCase()}] ${message}
|
|
11832
11835
|
`;
|
|
11833
11836
|
this.rotateIfNeeded();
|
|
11834
|
-
|
|
11837
|
+
fs8__namespace.appendFileSync(this.logPath, line2, "utf-8");
|
|
11835
11838
|
}
|
|
11836
11839
|
rotateIfNeeded() {
|
|
11837
11840
|
try {
|
|
11838
|
-
const stats =
|
|
11841
|
+
const stats = fs8__namespace.statSync(this.logPath);
|
|
11839
11842
|
if (stats.size > MAX_LOG_SIZE) {
|
|
11840
|
-
const content =
|
|
11843
|
+
const content = fs8__namespace.readFileSync(this.logPath, "utf-8");
|
|
11841
11844
|
const halfIdx = content.indexOf("\n", Math.floor(content.length / 2));
|
|
11842
11845
|
if (halfIdx > 0) {
|
|
11843
|
-
|
|
11846
|
+
fs8__namespace.writeFileSync(this.logPath, content.slice(halfIdx + 1), "utf-8");
|
|
11844
11847
|
}
|
|
11845
11848
|
}
|
|
11846
11849
|
} catch {
|
|
@@ -11863,20 +11866,20 @@ var init_PidManager = __esm({
|
|
|
11863
11866
|
}
|
|
11864
11867
|
writePid(pid) {
|
|
11865
11868
|
const dir = path__namespace.dirname(this.pidPath);
|
|
11866
|
-
if (!
|
|
11867
|
-
|
|
11869
|
+
if (!fs8__namespace.existsSync(dir)) {
|
|
11870
|
+
fs8__namespace.mkdirSync(dir, { recursive: true });
|
|
11868
11871
|
}
|
|
11869
|
-
|
|
11872
|
+
fs8__namespace.writeFileSync(this.pidPath, String(pid), "utf-8");
|
|
11870
11873
|
}
|
|
11871
11874
|
readPid() {
|
|
11872
|
-
if (!
|
|
11873
|
-
const raw =
|
|
11875
|
+
if (!fs8__namespace.existsSync(this.pidPath)) return null;
|
|
11876
|
+
const raw = fs8__namespace.readFileSync(this.pidPath, "utf-8").trim();
|
|
11874
11877
|
const pid = Number.parseInt(raw, 10);
|
|
11875
11878
|
return Number.isNaN(pid) ? null : pid;
|
|
11876
11879
|
}
|
|
11877
11880
|
removePid() {
|
|
11878
|
-
if (
|
|
11879
|
-
|
|
11881
|
+
if (fs8__namespace.existsSync(this.pidPath)) {
|
|
11882
|
+
fs8__namespace.unlinkSync(this.pidPath);
|
|
11880
11883
|
}
|
|
11881
11884
|
}
|
|
11882
11885
|
isProcessRunning(pid) {
|
|
@@ -11897,12 +11900,52 @@ var init_PidManager = __esm({
|
|
|
11897
11900
|
};
|
|
11898
11901
|
}
|
|
11899
11902
|
});
|
|
11900
|
-
|
|
11903
|
+
|
|
11904
|
+
// ../../packages/serviceme-core/src/scheduled-tasks/executors/timeout.ts
|
|
11905
|
+
function resolveConfiguredTimeoutMs(timeoutSeconds, defaultTimeoutMs) {
|
|
11906
|
+
if (timeoutSeconds === 0) {
|
|
11907
|
+
return void 0;
|
|
11908
|
+
}
|
|
11909
|
+
if (typeof timeoutSeconds !== "number" || !Number.isFinite(timeoutSeconds) || timeoutSeconds < 0) {
|
|
11910
|
+
return defaultTimeoutMs;
|
|
11911
|
+
}
|
|
11912
|
+
return timeoutSeconds * 1e3;
|
|
11913
|
+
}
|
|
11914
|
+
var init_timeout = __esm({
|
|
11915
|
+
"../../packages/serviceme-core/src/scheduled-tasks/executors/timeout.ts"() {
|
|
11916
|
+
}
|
|
11917
|
+
});
|
|
11918
|
+
function redactArgs(args) {
|
|
11919
|
+
const redacted = [];
|
|
11920
|
+
let redactNext = false;
|
|
11921
|
+
for (const arg of args) {
|
|
11922
|
+
if (redactNext) {
|
|
11923
|
+
redacted.push("<redacted>");
|
|
11924
|
+
redactNext = false;
|
|
11925
|
+
continue;
|
|
11926
|
+
}
|
|
11927
|
+
redacted.push(arg);
|
|
11928
|
+
if (arg === "--prompt") {
|
|
11929
|
+
redactNext = true;
|
|
11930
|
+
}
|
|
11931
|
+
}
|
|
11932
|
+
return redacted;
|
|
11933
|
+
}
|
|
11934
|
+
function writeDiagnostic(message) {
|
|
11935
|
+
const logPath = process.env.SERVICEME_SCHEDULER_LOG_PATH;
|
|
11936
|
+
if (logPath) {
|
|
11937
|
+
fs8__namespace.appendFileSync(logPath, message);
|
|
11938
|
+
return;
|
|
11939
|
+
}
|
|
11940
|
+
process.stderr.write(message);
|
|
11941
|
+
}
|
|
11942
|
+
var MAX_OUTPUT_BYTES, DEFAULT_TIMEOUT_MS2, GithubCopilotCliExecutor;
|
|
11901
11943
|
var init_GithubCopilotCliExecutor = __esm({
|
|
11902
11944
|
"../../packages/serviceme-core/src/scheduled-tasks/executors/GithubCopilotCliExecutor.ts"() {
|
|
11903
11945
|
init_doctor();
|
|
11904
|
-
|
|
11946
|
+
init_timeout();
|
|
11905
11947
|
MAX_OUTPUT_BYTES = 2 * 1024 * 1024;
|
|
11948
|
+
DEFAULT_TIMEOUT_MS2 = 3e5;
|
|
11906
11949
|
GithubCopilotCliExecutor = class {
|
|
11907
11950
|
async execute(payload, abortSignal) {
|
|
11908
11951
|
const authenticated = await isCopilotAuthenticated();
|
|
@@ -11925,7 +11968,7 @@ var init_GithubCopilotCliExecutor = __esm({
|
|
|
11925
11968
|
}
|
|
11926
11969
|
executeStreaming(payload, onOutput, abortSignal) {
|
|
11927
11970
|
const p = payload;
|
|
11928
|
-
const
|
|
11971
|
+
const timeoutMs = resolveConfiguredTimeoutMs(p.timeout, DEFAULT_TIMEOUT_MS2);
|
|
11929
11972
|
let resolve;
|
|
11930
11973
|
const resultPromise = new Promise((r) => {
|
|
11931
11974
|
resolve = r;
|
|
@@ -11934,7 +11977,7 @@ var init_GithubCopilotCliExecutor = __esm({
|
|
|
11934
11977
|
const settle = (result) => {
|
|
11935
11978
|
if (settled) return;
|
|
11936
11979
|
settled = true;
|
|
11937
|
-
clearTimeout(timer);
|
|
11980
|
+
if (timer) clearTimeout(timer);
|
|
11938
11981
|
resolve?.(result);
|
|
11939
11982
|
};
|
|
11940
11983
|
if (abortSignal?.aborted) {
|
|
@@ -11960,23 +12003,32 @@ var init_GithubCopilotCliExecutor = __esm({
|
|
|
11960
12003
|
if (p.agent) {
|
|
11961
12004
|
args.push("--agent", p.agent);
|
|
11962
12005
|
}
|
|
11963
|
-
|
|
11964
|
-
|
|
11965
|
-
|
|
12006
|
+
args.push("--timeout", String(p.timeout ?? 0));
|
|
12007
|
+
writeDiagnostic(
|
|
12008
|
+
`[GithubCopilotCliExecutor] spawn: command=serviceme, args=${JSON.stringify(redactArgs(args))}, promptLen=${p.prompt.length}, cwd=${p.workspace ?? "(default)"}, platform=${process.platform}, windowsHide=true, pid=${process.pid}
|
|
12009
|
+
`
|
|
12010
|
+
);
|
|
11966
12011
|
const child = child_process.spawn("serviceme", args, {
|
|
11967
12012
|
cwd: p.workspace,
|
|
11968
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
12013
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
12014
|
+
windowsHide: true
|
|
11969
12015
|
});
|
|
11970
|
-
|
|
12016
|
+
if (child.pid) {
|
|
12017
|
+
writeDiagnostic(
|
|
12018
|
+
`[GithubCopilotCliExecutor] spawned child PID=${child.pid}
|
|
12019
|
+
`
|
|
12020
|
+
);
|
|
12021
|
+
}
|
|
12022
|
+
const timer = timeoutMs != null ? setTimeout(() => {
|
|
11971
12023
|
child.kill("SIGTERM");
|
|
11972
12024
|
setTimeout(() => {
|
|
11973
12025
|
if (!child.killed) child.kill("SIGKILL");
|
|
11974
12026
|
}, 5e3);
|
|
11975
12027
|
settle({
|
|
11976
12028
|
status: "timeout",
|
|
11977
|
-
error: `Copilot CLI execution timed out after ${
|
|
12029
|
+
error: `Copilot CLI execution timed out after ${timeoutMs / 1e3}s`
|
|
11978
12030
|
});
|
|
11979
|
-
},
|
|
12031
|
+
}, timeoutMs) : void 0;
|
|
11980
12032
|
let stdoutBuf = "";
|
|
11981
12033
|
let stderrBuf = "";
|
|
11982
12034
|
child.stdout.on("data", (chunk) => {
|
|
@@ -12022,20 +12074,23 @@ var init_GithubCopilotCliExecutor = __esm({
|
|
|
12022
12074
|
});
|
|
12023
12075
|
|
|
12024
12076
|
// ../../packages/serviceme-core/src/scheduled-tasks/executors/HttpRequestExecutor.ts
|
|
12025
|
-
var
|
|
12077
|
+
var DEFAULT_TIMEOUT_MS3, HttpRequestExecutor;
|
|
12026
12078
|
var init_HttpRequestExecutor = __esm({
|
|
12027
12079
|
"../../packages/serviceme-core/src/scheduled-tasks/executors/HttpRequestExecutor.ts"() {
|
|
12028
|
-
|
|
12080
|
+
init_timeout();
|
|
12081
|
+
DEFAULT_TIMEOUT_MS3 = 3e4;
|
|
12029
12082
|
HttpRequestExecutor = class {
|
|
12030
12083
|
async execute(payload, abortSignal) {
|
|
12031
12084
|
const p = payload;
|
|
12032
|
-
const
|
|
12085
|
+
const timeoutMs = resolveConfiguredTimeoutMs(p.timeout, DEFAULT_TIMEOUT_MS3);
|
|
12033
12086
|
const ac = new AbortController();
|
|
12034
|
-
|
|
12087
|
+
let timedOut = false;
|
|
12088
|
+
const timer = timeoutMs != null ? setTimeout(() => {
|
|
12089
|
+
timedOut = true;
|
|
12035
12090
|
ac.abort();
|
|
12036
|
-
},
|
|
12091
|
+
}, timeoutMs) : void 0;
|
|
12037
12092
|
if (abortSignal?.aborted) {
|
|
12038
|
-
clearTimeout(timer);
|
|
12093
|
+
if (timer) clearTimeout(timer);
|
|
12039
12094
|
return { status: "cancelled", error: "Execution aborted" };
|
|
12040
12095
|
}
|
|
12041
12096
|
let externalAbort = false;
|
|
@@ -12043,7 +12098,7 @@ var init_HttpRequestExecutor = __esm({
|
|
|
12043
12098
|
"abort",
|
|
12044
12099
|
() => {
|
|
12045
12100
|
externalAbort = true;
|
|
12046
|
-
clearTimeout(timer);
|
|
12101
|
+
if (timer) clearTimeout(timer);
|
|
12047
12102
|
ac.abort();
|
|
12048
12103
|
},
|
|
12049
12104
|
{ once: true }
|
|
@@ -12055,7 +12110,7 @@ var init_HttpRequestExecutor = __esm({
|
|
|
12055
12110
|
body: p.body,
|
|
12056
12111
|
signal: ac.signal
|
|
12057
12112
|
});
|
|
12058
|
-
clearTimeout(timer);
|
|
12113
|
+
if (timer) clearTimeout(timer);
|
|
12059
12114
|
const body = await response.text();
|
|
12060
12115
|
if (response.ok) {
|
|
12061
12116
|
return {
|
|
@@ -12070,14 +12125,17 @@ ${body}`.trim()
|
|
|
12070
12125
|
${body}`.trim()
|
|
12071
12126
|
};
|
|
12072
12127
|
} catch (err) {
|
|
12073
|
-
clearTimeout(timer);
|
|
12128
|
+
if (timer) clearTimeout(timer);
|
|
12074
12129
|
if (err instanceof Error && err.name === "AbortError") {
|
|
12075
12130
|
if (externalAbort) {
|
|
12076
12131
|
return { status: "cancelled", error: "Execution cancelled" };
|
|
12077
12132
|
}
|
|
12133
|
+
if (!timedOut || timeoutMs == null) {
|
|
12134
|
+
return { status: "failure", error: err.message };
|
|
12135
|
+
}
|
|
12078
12136
|
return {
|
|
12079
12137
|
status: "timeout",
|
|
12080
|
-
error: `HTTP request timed out after ${
|
|
12138
|
+
error: `HTTP request timed out after ${timeoutMs / 1e3}s`
|
|
12081
12139
|
};
|
|
12082
12140
|
}
|
|
12083
12141
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -12087,11 +12145,84 @@ ${body}`.trim()
|
|
|
12087
12145
|
};
|
|
12088
12146
|
}
|
|
12089
12147
|
});
|
|
12090
|
-
|
|
12148
|
+
function resolveShellExecution(script, options2 = {}) {
|
|
12149
|
+
const platform = options2.platform ?? process.platform;
|
|
12150
|
+
const env = options2.env ?? process.env;
|
|
12151
|
+
const fileExists = options2.fileExists ?? fs8__namespace.existsSync;
|
|
12152
|
+
if (platform === "win32") {
|
|
12153
|
+
const posixShell = usesPosixShellSyntax(script) ? findWindowsPosixShell(env, fileExists) : null;
|
|
12154
|
+
if (posixShell) {
|
|
12155
|
+
return {
|
|
12156
|
+
command: posixShell,
|
|
12157
|
+
args: ["-s"],
|
|
12158
|
+
stdinScript: script,
|
|
12159
|
+
outputEncoding: "utf8",
|
|
12160
|
+
shellKind: "posix"
|
|
12161
|
+
};
|
|
12162
|
+
}
|
|
12163
|
+
return {
|
|
12164
|
+
command: env.ComSpec ?? env.COMSPEC ?? "cmd.exe",
|
|
12165
|
+
args: ["/d", "/s", "/c", script],
|
|
12166
|
+
outputEncoding: "utf8",
|
|
12167
|
+
shellKind: "cmd"
|
|
12168
|
+
};
|
|
12169
|
+
}
|
|
12170
|
+
return {
|
|
12171
|
+
command: "sh",
|
|
12172
|
+
args: ["-s"],
|
|
12173
|
+
stdinScript: script,
|
|
12174
|
+
outputEncoding: "utf8",
|
|
12175
|
+
shellKind: "posix"
|
|
12176
|
+
};
|
|
12177
|
+
}
|
|
12178
|
+
function usesPosixShellSyntax(script) {
|
|
12179
|
+
return /\$\([^)]*\)|`[^`]*`/.test(script);
|
|
12180
|
+
}
|
|
12181
|
+
function findWindowsPosixShell(env, fileExists) {
|
|
12182
|
+
const explicitShell = env.SERVICEME_POSIX_SHELL;
|
|
12183
|
+
if (explicitShell && fileExists(explicitShell)) {
|
|
12184
|
+
return explicitShell;
|
|
12185
|
+
}
|
|
12186
|
+
const knownGitBashPaths = [
|
|
12187
|
+
"C:\\Program Files\\Git\\bin\\bash.exe",
|
|
12188
|
+
"C:\\Program Files\\Git\\usr\\bin\\bash.exe",
|
|
12189
|
+
"C:\\Program Files (x86)\\Git\\bin\\bash.exe",
|
|
12190
|
+
"C:\\Program Files (x86)\\Git\\usr\\bin\\bash.exe"
|
|
12191
|
+
];
|
|
12192
|
+
for (const candidate of knownGitBashPaths) {
|
|
12193
|
+
if (fileExists(candidate)) return candidate;
|
|
12194
|
+
}
|
|
12195
|
+
const pathValue = env.Path ?? env.PATH ?? "";
|
|
12196
|
+
for (const dir of pathValue.split(path__namespace.win32.delimiter)) {
|
|
12197
|
+
if (!dir) continue;
|
|
12198
|
+
for (const executable of POSIX_SHELL_CANDIDATES) {
|
|
12199
|
+
const candidate = path__namespace.win32.join(dir, executable);
|
|
12200
|
+
if (fileExists(candidate) && !isWindowsWslLauncher(candidate)) {
|
|
12201
|
+
return candidate;
|
|
12202
|
+
}
|
|
12203
|
+
}
|
|
12204
|
+
}
|
|
12205
|
+
return null;
|
|
12206
|
+
}
|
|
12207
|
+
function isWindowsWslLauncher(candidate) {
|
|
12208
|
+
const normalized = path__namespace.win32.normalize(candidate).toLowerCase();
|
|
12209
|
+
return normalized.endsWith("\\windows\\system32\\bash.exe") || normalized.endsWith("\\windows\\syswow64\\bash.exe");
|
|
12210
|
+
}
|
|
12211
|
+
function writeDiagnostic2(message) {
|
|
12212
|
+
const logPath = process.env.SERVICEME_SCHEDULER_LOG_PATH;
|
|
12213
|
+
if (logPath) {
|
|
12214
|
+
fs8__namespace.appendFileSync(logPath, message);
|
|
12215
|
+
return;
|
|
12216
|
+
}
|
|
12217
|
+
process.stderr.write(message);
|
|
12218
|
+
}
|
|
12219
|
+
var MAX_OUTPUT_BYTES2, DEFAULT_TIMEOUT_MS4, POSIX_SHELL_CANDIDATES, ShellExecutor;
|
|
12091
12220
|
var init_ShellExecutor = __esm({
|
|
12092
12221
|
"../../packages/serviceme-core/src/scheduled-tasks/executors/ShellExecutor.ts"() {
|
|
12093
|
-
|
|
12222
|
+
init_timeout();
|
|
12094
12223
|
MAX_OUTPUT_BYTES2 = 1024 * 1024;
|
|
12224
|
+
DEFAULT_TIMEOUT_MS4 = 6e4;
|
|
12225
|
+
POSIX_SHELL_CANDIDATES = ["bash.exe", "sh.exe"];
|
|
12095
12226
|
ShellExecutor = class {
|
|
12096
12227
|
async execute(payload, abortSignal) {
|
|
12097
12228
|
let output = "";
|
|
@@ -12107,7 +12238,7 @@ var init_ShellExecutor = __esm({
|
|
|
12107
12238
|
}
|
|
12108
12239
|
executeStreaming(payload, onOutput, abortSignal) {
|
|
12109
12240
|
const p = payload;
|
|
12110
|
-
const
|
|
12241
|
+
const timeoutMs = resolveConfiguredTimeoutMs(p.timeout, DEFAULT_TIMEOUT_MS4);
|
|
12111
12242
|
let resolve;
|
|
12112
12243
|
const resultPromise = new Promise((r) => {
|
|
12113
12244
|
resolve = r;
|
|
@@ -12116,7 +12247,7 @@ var init_ShellExecutor = __esm({
|
|
|
12116
12247
|
const settle = (result) => {
|
|
12117
12248
|
if (settled) return;
|
|
12118
12249
|
settled = true;
|
|
12119
|
-
clearTimeout(timer);
|
|
12250
|
+
if (timer) clearTimeout(timer);
|
|
12120
12251
|
resolve?.(result);
|
|
12121
12252
|
};
|
|
12122
12253
|
if (abortSignal?.aborted) {
|
|
@@ -12129,37 +12260,65 @@ var init_ShellExecutor = __esm({
|
|
|
12129
12260
|
}
|
|
12130
12261
|
};
|
|
12131
12262
|
}
|
|
12132
|
-
const
|
|
12263
|
+
const shellExecution = resolveShellExecution(p.script);
|
|
12264
|
+
const spawnOpts = {
|
|
12133
12265
|
cwd: p.cwd,
|
|
12134
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
12135
|
-
|
|
12136
|
-
|
|
12266
|
+
stdio: [shellExecution.stdinScript ? "pipe" : "ignore", "pipe", "pipe"],
|
|
12267
|
+
windowsHide: true
|
|
12268
|
+
};
|
|
12269
|
+
writeDiagnostic2(
|
|
12270
|
+
`[ShellExecutor] spawn:
|
|
12271
|
+
platform=${process.platform}
|
|
12272
|
+
shell=${shellExecution.shellKind}
|
|
12273
|
+
command=${shellExecution.command}
|
|
12274
|
+
args=${JSON.stringify(shellExecution.args.filter((a) => a !== p.script))}
|
|
12275
|
+
stdin=${shellExecution.stdinScript ? "true" : "false"}
|
|
12276
|
+
cwd=${p.cwd ?? "(default)"}
|
|
12277
|
+
timeout=${timeoutMs != null ? `${timeoutMs}ms` : "unlimited"}
|
|
12278
|
+
scriptLen=${p.script.length}
|
|
12279
|
+
windowsHide=true
|
|
12280
|
+
daemonPid=${process.pid}
|
|
12281
|
+
`
|
|
12282
|
+
);
|
|
12283
|
+
const child = child_process.spawn(shellExecution.command, shellExecution.args, spawnOpts);
|
|
12284
|
+
if (shellExecution.stdinScript && child.stdin) {
|
|
12285
|
+
child.stdin.end(shellExecution.stdinScript);
|
|
12286
|
+
}
|
|
12287
|
+
if (child.pid) {
|
|
12288
|
+
writeDiagnostic2(`[ShellExecutor] spawned child PID=${child.pid}
|
|
12289
|
+
`);
|
|
12290
|
+
}
|
|
12291
|
+
const timer = timeoutMs != null ? setTimeout(() => {
|
|
12137
12292
|
child.kill("SIGTERM");
|
|
12138
12293
|
setTimeout(() => {
|
|
12139
12294
|
if (!child.killed) child.kill("SIGKILL");
|
|
12140
12295
|
}, 5e3);
|
|
12141
12296
|
settle({
|
|
12142
12297
|
status: "timeout",
|
|
12143
|
-
error: `Shell execution timed out after ${
|
|
12298
|
+
error: `Shell execution timed out after ${timeoutMs / 1e3}s`
|
|
12144
12299
|
});
|
|
12145
|
-
},
|
|
12300
|
+
}, timeoutMs) : void 0;
|
|
12146
12301
|
let stdoutBuf = "";
|
|
12147
12302
|
let stderrBuf = "";
|
|
12148
|
-
child.stdout
|
|
12149
|
-
const data = chunk.toString();
|
|
12303
|
+
child.stdout?.on("data", (chunk) => {
|
|
12304
|
+
const data = chunk.toString(shellExecution.outputEncoding);
|
|
12150
12305
|
stdoutBuf += data;
|
|
12151
12306
|
if (stdoutBuf.length > MAX_OUTPUT_BYTES2)
|
|
12152
12307
|
stdoutBuf = stdoutBuf.slice(-MAX_OUTPUT_BYTES2);
|
|
12153
12308
|
onOutput("stdout", data);
|
|
12154
12309
|
});
|
|
12155
|
-
child.stderr
|
|
12156
|
-
const data = chunk.toString();
|
|
12310
|
+
child.stderr?.on("data", (chunk) => {
|
|
12311
|
+
const data = chunk.toString(shellExecution.outputEncoding);
|
|
12157
12312
|
stderrBuf += data;
|
|
12158
12313
|
if (stderrBuf.length > MAX_OUTPUT_BYTES2)
|
|
12159
12314
|
stderrBuf = stderrBuf.slice(-MAX_OUTPUT_BYTES2);
|
|
12160
12315
|
onOutput("stderr", data);
|
|
12161
12316
|
});
|
|
12162
12317
|
child.on("close", (code) => {
|
|
12318
|
+
writeDiagnostic2(
|
|
12319
|
+
`[ShellExecutor] child PID=${child.pid} exited: code=${code}
|
|
12320
|
+
`
|
|
12321
|
+
);
|
|
12163
12322
|
if (code === 0) {
|
|
12164
12323
|
settle({ status: "success", output: stdoutBuf || void 0 });
|
|
12165
12324
|
} else {
|
|
@@ -12221,9 +12380,38 @@ var init_executors = __esm({
|
|
|
12221
12380
|
function emptyConfig() {
|
|
12222
12381
|
return { version: 1, tasks: [] };
|
|
12223
12382
|
}
|
|
12383
|
+
function isRecord3(value) {
|
|
12384
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
12385
|
+
}
|
|
12386
|
+
function requireNonEmptyString(payload, field, taskType) {
|
|
12387
|
+
if (!isRecord3(payload) || typeof payload[field] !== "string" || !payload[field].trim()) {
|
|
12388
|
+
throw createServicemeError(
|
|
12389
|
+
"invalid_payload",
|
|
12390
|
+
`${taskType} payload ${field} is required`
|
|
12391
|
+
);
|
|
12392
|
+
}
|
|
12393
|
+
}
|
|
12394
|
+
function validateTaskPayload(taskType, payload) {
|
|
12395
|
+
switch (taskType) {
|
|
12396
|
+
case "command":
|
|
12397
|
+
requireNonEmptyString(payload, "command", taskType);
|
|
12398
|
+
return;
|
|
12399
|
+
case "shell":
|
|
12400
|
+
requireNonEmptyString(payload, "script", taskType);
|
|
12401
|
+
return;
|
|
12402
|
+
case "http_request":
|
|
12403
|
+
requireNonEmptyString(payload, "url", taskType);
|
|
12404
|
+
requireNonEmptyString(payload, "method", taskType);
|
|
12405
|
+
return;
|
|
12406
|
+
case "github_copilot_cli":
|
|
12407
|
+
requireNonEmptyString(payload, "prompt", taskType);
|
|
12408
|
+
return;
|
|
12409
|
+
}
|
|
12410
|
+
}
|
|
12224
12411
|
var CONFIG_DIR3, CONFIG_FILE, TaskConfigManager;
|
|
12225
12412
|
var init_TaskConfigManager = __esm({
|
|
12226
12413
|
"../../packages/serviceme-core/src/scheduled-tasks/TaskConfigManager.ts"() {
|
|
12414
|
+
init_src();
|
|
12227
12415
|
CONFIG_DIR3 = ".serviceme";
|
|
12228
12416
|
CONFIG_FILE = "scheduled-tasks.json";
|
|
12229
12417
|
TaskConfigManager = class {
|
|
@@ -12234,21 +12422,21 @@ var init_TaskConfigManager = __esm({
|
|
|
12234
12422
|
return this.configPath;
|
|
12235
12423
|
}
|
|
12236
12424
|
readConfig() {
|
|
12237
|
-
if (!
|
|
12425
|
+
if (!fs8__namespace.existsSync(this.configPath)) {
|
|
12238
12426
|
return emptyConfig();
|
|
12239
12427
|
}
|
|
12240
|
-
const raw =
|
|
12428
|
+
const raw = fs8__namespace.readFileSync(this.configPath, "utf-8");
|
|
12241
12429
|
const parsed = JSON.parse(raw);
|
|
12242
12430
|
return parsed;
|
|
12243
12431
|
}
|
|
12244
12432
|
writeConfig(config) {
|
|
12245
12433
|
const dir = path__namespace.dirname(this.configPath);
|
|
12246
|
-
if (!
|
|
12247
|
-
|
|
12434
|
+
if (!fs8__namespace.existsSync(dir)) {
|
|
12435
|
+
fs8__namespace.mkdirSync(dir, { recursive: true });
|
|
12248
12436
|
}
|
|
12249
12437
|
const tmp = `${this.configPath}.tmp`;
|
|
12250
|
-
|
|
12251
|
-
|
|
12438
|
+
fs8__namespace.writeFileSync(tmp, JSON.stringify(config, null, " "), "utf-8");
|
|
12439
|
+
fs8__namespace.renameSync(tmp, this.configPath);
|
|
12252
12440
|
}
|
|
12253
12441
|
listTasks() {
|
|
12254
12442
|
return this.readConfig().tasks;
|
|
@@ -12260,6 +12448,7 @@ var init_TaskConfigManager = __esm({
|
|
|
12260
12448
|
return this.readConfig().tasks.find((t) => t.name === name);
|
|
12261
12449
|
}
|
|
12262
12450
|
createTask(input) {
|
|
12451
|
+
validateTaskPayload(input.taskType, input.payload);
|
|
12263
12452
|
const config = this.readConfig();
|
|
12264
12453
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12265
12454
|
const task = {
|
|
@@ -12288,6 +12477,9 @@ var init_TaskConfigManager = __esm({
|
|
|
12288
12477
|
if (!existing) {
|
|
12289
12478
|
throw new Error(`Task '${id}' not found`);
|
|
12290
12479
|
}
|
|
12480
|
+
const nextTaskType = input.taskType ?? existing.taskType;
|
|
12481
|
+
const nextPayload = input.payload ?? existing.payload;
|
|
12482
|
+
validateTaskPayload(nextTaskType, nextPayload);
|
|
12291
12483
|
const updated = {
|
|
12292
12484
|
...existing,
|
|
12293
12485
|
...input.name !== void 0 && { name: input.name },
|
|
@@ -12327,6 +12519,200 @@ var init_TaskConfigManager = __esm({
|
|
|
12327
12519
|
};
|
|
12328
12520
|
}
|
|
12329
12521
|
});
|
|
12522
|
+
|
|
12523
|
+
// ../../packages/serviceme-core/src/scheduled-tasks/TaskExecutionEngine.ts
|
|
12524
|
+
function hasNonEmptyString(value) {
|
|
12525
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
12526
|
+
}
|
|
12527
|
+
function resolveTaskExecutionPayload(taskType, payload, workspacePath) {
|
|
12528
|
+
if (!hasNonEmptyString(workspacePath)) {
|
|
12529
|
+
return payload;
|
|
12530
|
+
}
|
|
12531
|
+
if (taskType === "shell") {
|
|
12532
|
+
const shellPayload = payload;
|
|
12533
|
+
if (hasNonEmptyString(shellPayload.cwd)) {
|
|
12534
|
+
return shellPayload;
|
|
12535
|
+
}
|
|
12536
|
+
return { ...shellPayload, cwd: workspacePath };
|
|
12537
|
+
}
|
|
12538
|
+
if (taskType === "github_copilot_cli") {
|
|
12539
|
+
const copilotPayload = payload;
|
|
12540
|
+
if (hasNonEmptyString(copilotPayload.workspace)) {
|
|
12541
|
+
return copilotPayload;
|
|
12542
|
+
}
|
|
12543
|
+
return { ...copilotPayload, workspace: workspacePath };
|
|
12544
|
+
}
|
|
12545
|
+
return payload;
|
|
12546
|
+
}
|
|
12547
|
+
var TaskExecutionEngine;
|
|
12548
|
+
var init_TaskExecutionEngine = __esm({
|
|
12549
|
+
"../../packages/serviceme-core/src/scheduled-tasks/TaskExecutionEngine.ts"() {
|
|
12550
|
+
init_types();
|
|
12551
|
+
init_TaskConfigManager();
|
|
12552
|
+
TaskExecutionEngine = class {
|
|
12553
|
+
constructor(getExecutor2) {
|
|
12554
|
+
this.getExecutor = getExecutor2;
|
|
12555
|
+
this.running = /* @__PURE__ */ new Map();
|
|
12556
|
+
this.taskExecutions = /* @__PURE__ */ new Map();
|
|
12557
|
+
this.listener = null;
|
|
12558
|
+
}
|
|
12559
|
+
setListener(listener) {
|
|
12560
|
+
this.listener = listener;
|
|
12561
|
+
}
|
|
12562
|
+
async execute(snapshot) {
|
|
12563
|
+
const policy = snapshot.concurrencyPolicy ?? "reject";
|
|
12564
|
+
if (policy === "reject") {
|
|
12565
|
+
const existingIds = this.taskExecutions.get(snapshot.taskId);
|
|
12566
|
+
if (existingIds && existingIds.size > 0) {
|
|
12567
|
+
throw new Error(
|
|
12568
|
+
`TASK_ALREADY_RUNNING: Task ${snapshot.taskId} is already running`
|
|
12569
|
+
);
|
|
12570
|
+
}
|
|
12571
|
+
}
|
|
12572
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
12573
|
+
if (!this.taskExecutions.has(snapshot.taskId)) {
|
|
12574
|
+
this.taskExecutions.set(snapshot.taskId, /* @__PURE__ */ new Set());
|
|
12575
|
+
}
|
|
12576
|
+
this.taskExecutions.get(snapshot.taskId)?.add(snapshot.executionId);
|
|
12577
|
+
const ac = new AbortController();
|
|
12578
|
+
const runningExec = {
|
|
12579
|
+
executionId: snapshot.executionId,
|
|
12580
|
+
taskId: snapshot.taskId,
|
|
12581
|
+
startedAt,
|
|
12582
|
+
cancel: () => ac.abort()
|
|
12583
|
+
};
|
|
12584
|
+
this.running.set(snapshot.executionId, runningExec);
|
|
12585
|
+
this.listener?.onStarted({
|
|
12586
|
+
executionId: snapshot.executionId,
|
|
12587
|
+
taskId: snapshot.taskId,
|
|
12588
|
+
startedAt
|
|
12589
|
+
});
|
|
12590
|
+
try {
|
|
12591
|
+
const executionPayload = resolveTaskExecutionPayload(
|
|
12592
|
+
snapshot.type,
|
|
12593
|
+
snapshot.payload,
|
|
12594
|
+
snapshot.workspacePath
|
|
12595
|
+
);
|
|
12596
|
+
validateTaskPayload(snapshot.type, executionPayload);
|
|
12597
|
+
const executor = this.getExecutor(snapshot.type);
|
|
12598
|
+
let result;
|
|
12599
|
+
if (isStreamingTaskExecutor(executor)) {
|
|
12600
|
+
const handle = executor.executeStreaming(
|
|
12601
|
+
executionPayload,
|
|
12602
|
+
(stream, data) => {
|
|
12603
|
+
this.listener?.onOutput({
|
|
12604
|
+
executionId: snapshot.executionId,
|
|
12605
|
+
stream,
|
|
12606
|
+
data
|
|
12607
|
+
});
|
|
12608
|
+
},
|
|
12609
|
+
ac.signal
|
|
12610
|
+
);
|
|
12611
|
+
runningExec.cancel = () => {
|
|
12612
|
+
handle.cancel();
|
|
12613
|
+
ac.abort();
|
|
12614
|
+
};
|
|
12615
|
+
result = await handle.result;
|
|
12616
|
+
} else {
|
|
12617
|
+
result = await executor.execute(executionPayload, ac.signal);
|
|
12618
|
+
}
|
|
12619
|
+
const log = {
|
|
12620
|
+
id: snapshot.executionId,
|
|
12621
|
+
taskId: snapshot.taskId,
|
|
12622
|
+
taskName: snapshot.name,
|
|
12623
|
+
startedAt,
|
|
12624
|
+
finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12625
|
+
status: result.status === "running" ? "failure" : result.status,
|
|
12626
|
+
output: result.output,
|
|
12627
|
+
error: result.error
|
|
12628
|
+
};
|
|
12629
|
+
switch (log.status) {
|
|
12630
|
+
case "success":
|
|
12631
|
+
this.listener?.onCompleted({
|
|
12632
|
+
executionId: snapshot.executionId,
|
|
12633
|
+
log
|
|
12634
|
+
});
|
|
12635
|
+
break;
|
|
12636
|
+
case "cancelled":
|
|
12637
|
+
this.listener?.onCancelled({
|
|
12638
|
+
executionId: snapshot.executionId,
|
|
12639
|
+
log
|
|
12640
|
+
});
|
|
12641
|
+
break;
|
|
12642
|
+
case "timeout":
|
|
12643
|
+
this.listener?.onFailed({
|
|
12644
|
+
executionId: snapshot.executionId,
|
|
12645
|
+
status: "timeout",
|
|
12646
|
+
reason: "timeout",
|
|
12647
|
+
log
|
|
12648
|
+
});
|
|
12649
|
+
break;
|
|
12650
|
+
default:
|
|
12651
|
+
this.listener?.onFailed({
|
|
12652
|
+
executionId: snapshot.executionId,
|
|
12653
|
+
status: "failure",
|
|
12654
|
+
reason: "error",
|
|
12655
|
+
log
|
|
12656
|
+
});
|
|
12657
|
+
break;
|
|
12658
|
+
}
|
|
12659
|
+
} catch (err) {
|
|
12660
|
+
const log = {
|
|
12661
|
+
id: snapshot.executionId,
|
|
12662
|
+
taskId: snapshot.taskId,
|
|
12663
|
+
taskName: snapshot.name,
|
|
12664
|
+
startedAt,
|
|
12665
|
+
finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12666
|
+
status: ac.signal.aborted ? "cancelled" : "failure",
|
|
12667
|
+
error: err instanceof Error ? err.message : String(err)
|
|
12668
|
+
};
|
|
12669
|
+
if (ac.signal.aborted) {
|
|
12670
|
+
this.listener?.onCancelled({
|
|
12671
|
+
executionId: snapshot.executionId,
|
|
12672
|
+
log
|
|
12673
|
+
});
|
|
12674
|
+
} else {
|
|
12675
|
+
this.listener?.onFailed({
|
|
12676
|
+
executionId: snapshot.executionId,
|
|
12677
|
+
status: "failure",
|
|
12678
|
+
reason: "error",
|
|
12679
|
+
log
|
|
12680
|
+
});
|
|
12681
|
+
}
|
|
12682
|
+
} finally {
|
|
12683
|
+
this.running.delete(snapshot.executionId);
|
|
12684
|
+
const taskExecIds = this.taskExecutions.get(snapshot.taskId);
|
|
12685
|
+
if (taskExecIds) {
|
|
12686
|
+
taskExecIds.delete(snapshot.executionId);
|
|
12687
|
+
if (taskExecIds.size === 0) {
|
|
12688
|
+
this.taskExecutions.delete(snapshot.taskId);
|
|
12689
|
+
}
|
|
12690
|
+
}
|
|
12691
|
+
}
|
|
12692
|
+
}
|
|
12693
|
+
cancel(executionId) {
|
|
12694
|
+
const exec = this.running.get(executionId);
|
|
12695
|
+
if (!exec) return false;
|
|
12696
|
+
exec.cancel();
|
|
12697
|
+
return true;
|
|
12698
|
+
}
|
|
12699
|
+
listRunning() {
|
|
12700
|
+
return Array.from(this.running.values()).map((e) => ({
|
|
12701
|
+
executionId: e.executionId,
|
|
12702
|
+
taskId: e.taskId,
|
|
12703
|
+
startedAt: e.startedAt
|
|
12704
|
+
}));
|
|
12705
|
+
}
|
|
12706
|
+
dispose() {
|
|
12707
|
+
for (const exec of this.running.values()) {
|
|
12708
|
+
exec.cancel();
|
|
12709
|
+
}
|
|
12710
|
+
this.running.clear();
|
|
12711
|
+
this.taskExecutions.clear();
|
|
12712
|
+
}
|
|
12713
|
+
};
|
|
12714
|
+
}
|
|
12715
|
+
});
|
|
12330
12716
|
function emptyLogFile() {
|
|
12331
12717
|
return { logs: [] };
|
|
12332
12718
|
}
|
|
@@ -12360,11 +12746,11 @@ var init_TaskLogManager = __esm({
|
|
|
12360
12746
|
return this.logPath;
|
|
12361
12747
|
}
|
|
12362
12748
|
readLogFile() {
|
|
12363
|
-
if (!
|
|
12749
|
+
if (!fs8__namespace.existsSync(this.logPath)) {
|
|
12364
12750
|
return emptyLogFile();
|
|
12365
12751
|
}
|
|
12366
12752
|
try {
|
|
12367
|
-
const raw =
|
|
12753
|
+
const raw = fs8__namespace.readFileSync(this.logPath, "utf-8");
|
|
12368
12754
|
const parsed = JSON.parse(raw);
|
|
12369
12755
|
const file = validateAndRepairLogFile(parsed);
|
|
12370
12756
|
if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.logs) || parsed.logs.length !== file.logs.length) {
|
|
@@ -12380,21 +12766,21 @@ var init_TaskLogManager = __esm({
|
|
|
12380
12766
|
}
|
|
12381
12767
|
backupCorruptedFile() {
|
|
12382
12768
|
try {
|
|
12383
|
-
if (
|
|
12769
|
+
if (fs8__namespace.existsSync(this.logPath)) {
|
|
12384
12770
|
const backupPath = `${this.logPath}.corrupted.${Date.now()}`;
|
|
12385
|
-
|
|
12771
|
+
fs8__namespace.copyFileSync(this.logPath, backupPath);
|
|
12386
12772
|
}
|
|
12387
12773
|
} catch {
|
|
12388
12774
|
}
|
|
12389
12775
|
}
|
|
12390
12776
|
writeLogFile(file) {
|
|
12391
12777
|
const dir = path__namespace.dirname(this.logPath);
|
|
12392
|
-
if (!
|
|
12393
|
-
|
|
12778
|
+
if (!fs8__namespace.existsSync(dir)) {
|
|
12779
|
+
fs8__namespace.mkdirSync(dir, { recursive: true });
|
|
12394
12780
|
}
|
|
12395
12781
|
const tmp = `${this.logPath}.tmp`;
|
|
12396
|
-
|
|
12397
|
-
|
|
12782
|
+
fs8__namespace.writeFileSync(tmp, JSON.stringify(file, null, " "), "utf-8");
|
|
12783
|
+
fs8__namespace.renameSync(tmp, this.logPath);
|
|
12398
12784
|
}
|
|
12399
12785
|
appendLog(input) {
|
|
12400
12786
|
const file = this.readLogFile();
|
|
@@ -12486,6 +12872,7 @@ var init_SchedulerDaemon = __esm({
|
|
|
12486
12872
|
"../../packages/serviceme-core/src/scheduled-tasks/daemon/SchedulerDaemon.ts"() {
|
|
12487
12873
|
init_executors();
|
|
12488
12874
|
init_TaskConfigManager();
|
|
12875
|
+
init_TaskExecutionEngine();
|
|
12489
12876
|
init_TaskLogManager();
|
|
12490
12877
|
init_DaemonLogger();
|
|
12491
12878
|
init_PidManager();
|
|
@@ -12511,7 +12898,23 @@ var init_SchedulerDaemon = __esm({
|
|
|
12511
12898
|
this.running = true;
|
|
12512
12899
|
this.startTime = Date.now();
|
|
12513
12900
|
this.pidManager.writePid(process.pid);
|
|
12514
|
-
this.
|
|
12901
|
+
const configPath = this.configManager.getConfigPath();
|
|
12902
|
+
const logPath = this.logger.getLogPath();
|
|
12903
|
+
this.logger.log("info", "=".repeat(60));
|
|
12904
|
+
this.logger.log(
|
|
12905
|
+
"info",
|
|
12906
|
+
`Scheduler daemon started
|
|
12907
|
+
PID: ${process.pid}
|
|
12908
|
+
Node: ${process.version}
|
|
12909
|
+
OS: ${os__namespace.type()} ${os__namespace.release()} (${process.arch})
|
|
12910
|
+
Platform: ${process.platform}
|
|
12911
|
+
Hostname: ${os__namespace.hostname()}
|
|
12912
|
+
User: ${os__namespace.userInfo().username}
|
|
12913
|
+
Workspace: ${this.workspacePath}
|
|
12914
|
+
Config: ${configPath}
|
|
12915
|
+
LogPath: ${logPath}
|
|
12916
|
+
ExecPath: ${process.execPath}`
|
|
12917
|
+
);
|
|
12515
12918
|
this.tickTimer = setInterval(() => this.tick(), TICK_INTERVAL);
|
|
12516
12919
|
this.setupConfigWatch();
|
|
12517
12920
|
process.on("SIGTERM", () => this.stop());
|
|
@@ -12536,8 +12939,8 @@ var init_SchedulerDaemon = __esm({
|
|
|
12536
12939
|
const configPath = this.configManager.getConfigPath();
|
|
12537
12940
|
const dir = configPath.substring(0, configPath.lastIndexOf("/"));
|
|
12538
12941
|
try {
|
|
12539
|
-
if (
|
|
12540
|
-
this.watcher =
|
|
12942
|
+
if (fs8__namespace.existsSync(dir)) {
|
|
12943
|
+
this.watcher = fs8__namespace.watch(dir, (_eventType, filename) => {
|
|
12541
12944
|
if (filename === "scheduled-tasks.json") {
|
|
12542
12945
|
this.logger.log("info", "Config file changed, reconciling...");
|
|
12543
12946
|
}
|
|
@@ -12553,7 +12956,11 @@ var init_SchedulerDaemon = __esm({
|
|
|
12553
12956
|
for (const task of config.tasks) {
|
|
12554
12957
|
if (!task.enabled) continue;
|
|
12555
12958
|
if (this.taskRunning.has(task.id)) continue;
|
|
12556
|
-
|
|
12959
|
+
let lastExec = this.lastRun.get(task.id);
|
|
12960
|
+
if (lastExec === void 0) {
|
|
12961
|
+
this.lastRun.set(task.id, now);
|
|
12962
|
+
lastExec = now;
|
|
12963
|
+
}
|
|
12557
12964
|
if (this.shouldRun(task, lastExec, now)) {
|
|
12558
12965
|
this.executeTask(task, now);
|
|
12559
12966
|
}
|
|
@@ -12575,11 +12982,25 @@ var init_SchedulerDaemon = __esm({
|
|
|
12575
12982
|
this.taskRunning.add(task.id);
|
|
12576
12983
|
this.lastRun.set(task.id, now);
|
|
12577
12984
|
const startedAt = new Date(now).toISOString();
|
|
12578
|
-
|
|
12985
|
+
const startMs = Date.now();
|
|
12986
|
+
this.logger.log(
|
|
12987
|
+
"info",
|
|
12988
|
+
`Executing task: ${task.name} (${task.id})
|
|
12989
|
+
type: ${task.taskType}
|
|
12990
|
+
schedule: ${task.schedule} (${task.scheduleType})
|
|
12991
|
+
enabled: ${task.enabled}`
|
|
12992
|
+
);
|
|
12579
12993
|
try {
|
|
12994
|
+
const executionPayload = resolveTaskExecutionPayload(
|
|
12995
|
+
task.taskType,
|
|
12996
|
+
task.payload,
|
|
12997
|
+
this.workspacePath
|
|
12998
|
+
);
|
|
12999
|
+
validateTaskPayload(task.taskType, executionPayload);
|
|
12580
13000
|
const executor = getExecutor(task.taskType);
|
|
12581
|
-
const result = await executor.execute(
|
|
13001
|
+
const result = await executor.execute(executionPayload);
|
|
12582
13002
|
const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
13003
|
+
const durationMs = Date.now() - startMs;
|
|
12583
13004
|
this.logManager.appendLog({
|
|
12584
13005
|
taskId: task.id,
|
|
12585
13006
|
taskName: task.name,
|
|
@@ -12589,9 +13010,17 @@ var init_SchedulerDaemon = __esm({
|
|
|
12589
13010
|
output: result.output,
|
|
12590
13011
|
error: result.error
|
|
12591
13012
|
});
|
|
12592
|
-
|
|
13013
|
+
const outputBytes = result.output ? Buffer.byteLength(result.output) : 0;
|
|
13014
|
+
this.logger.log(
|
|
13015
|
+
"info",
|
|
13016
|
+
`Task completed: ${task.name} (${task.id})
|
|
13017
|
+
status: ${result.status}
|
|
13018
|
+
duration: ${durationMs}ms
|
|
13019
|
+
outputBytes: ${outputBytes}`
|
|
13020
|
+
);
|
|
12593
13021
|
} catch (err) {
|
|
12594
13022
|
const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
13023
|
+
const durationMs = Date.now() - startMs;
|
|
12595
13024
|
const message = err instanceof Error ? err.message : String(err);
|
|
12596
13025
|
this.logManager.appendLog({
|
|
12597
13026
|
taskId: task.id,
|
|
@@ -12601,7 +13030,12 @@ var init_SchedulerDaemon = __esm({
|
|
|
12601
13030
|
status: "failure",
|
|
12602
13031
|
error: message
|
|
12603
13032
|
});
|
|
12604
|
-
this.logger.log(
|
|
13033
|
+
this.logger.log(
|
|
13034
|
+
"error",
|
|
13035
|
+
`Task failed: ${task.name} (${task.id})
|
|
13036
|
+
duration: ${durationMs}ms
|
|
13037
|
+
error: ${message}`
|
|
13038
|
+
);
|
|
12605
13039
|
} finally {
|
|
12606
13040
|
this.taskRunning.delete(task.id);
|
|
12607
13041
|
}
|
|
@@ -12631,170 +13065,6 @@ var init_daemon = __esm({
|
|
|
12631
13065
|
}
|
|
12632
13066
|
});
|
|
12633
13067
|
|
|
12634
|
-
// ../../packages/serviceme-core/src/scheduled-tasks/TaskExecutionEngine.ts
|
|
12635
|
-
var TaskExecutionEngine;
|
|
12636
|
-
var init_TaskExecutionEngine = __esm({
|
|
12637
|
-
"../../packages/serviceme-core/src/scheduled-tasks/TaskExecutionEngine.ts"() {
|
|
12638
|
-
init_types();
|
|
12639
|
-
TaskExecutionEngine = class {
|
|
12640
|
-
constructor(getExecutor2) {
|
|
12641
|
-
this.getExecutor = getExecutor2;
|
|
12642
|
-
this.running = /* @__PURE__ */ new Map();
|
|
12643
|
-
this.taskExecutions = /* @__PURE__ */ new Map();
|
|
12644
|
-
this.listener = null;
|
|
12645
|
-
}
|
|
12646
|
-
setListener(listener) {
|
|
12647
|
-
this.listener = listener;
|
|
12648
|
-
}
|
|
12649
|
-
async execute(snapshot) {
|
|
12650
|
-
const policy = snapshot.concurrencyPolicy ?? "reject";
|
|
12651
|
-
if (policy === "reject") {
|
|
12652
|
-
const existingIds = this.taskExecutions.get(snapshot.taskId);
|
|
12653
|
-
if (existingIds && existingIds.size > 0) {
|
|
12654
|
-
throw new Error(
|
|
12655
|
-
`TASK_ALREADY_RUNNING: Task ${snapshot.taskId} is already running`
|
|
12656
|
-
);
|
|
12657
|
-
}
|
|
12658
|
-
}
|
|
12659
|
-
const executor = this.getExecutor(snapshot.type);
|
|
12660
|
-
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
12661
|
-
if (!this.taskExecutions.has(snapshot.taskId)) {
|
|
12662
|
-
this.taskExecutions.set(snapshot.taskId, /* @__PURE__ */ new Set());
|
|
12663
|
-
}
|
|
12664
|
-
this.taskExecutions.get(snapshot.taskId)?.add(snapshot.executionId);
|
|
12665
|
-
const ac = new AbortController();
|
|
12666
|
-
const runningExec = {
|
|
12667
|
-
executionId: snapshot.executionId,
|
|
12668
|
-
taskId: snapshot.taskId,
|
|
12669
|
-
startedAt,
|
|
12670
|
-
cancel: () => ac.abort()
|
|
12671
|
-
};
|
|
12672
|
-
this.running.set(snapshot.executionId, runningExec);
|
|
12673
|
-
this.listener?.onStarted({
|
|
12674
|
-
executionId: snapshot.executionId,
|
|
12675
|
-
taskId: snapshot.taskId,
|
|
12676
|
-
startedAt
|
|
12677
|
-
});
|
|
12678
|
-
try {
|
|
12679
|
-
let result;
|
|
12680
|
-
if (isStreamingTaskExecutor(executor)) {
|
|
12681
|
-
const handle = executor.executeStreaming(
|
|
12682
|
-
snapshot.payload,
|
|
12683
|
-
(stream, data) => {
|
|
12684
|
-
this.listener?.onOutput({
|
|
12685
|
-
executionId: snapshot.executionId,
|
|
12686
|
-
stream,
|
|
12687
|
-
data
|
|
12688
|
-
});
|
|
12689
|
-
},
|
|
12690
|
-
ac.signal
|
|
12691
|
-
);
|
|
12692
|
-
runningExec.cancel = () => {
|
|
12693
|
-
handle.cancel();
|
|
12694
|
-
ac.abort();
|
|
12695
|
-
};
|
|
12696
|
-
result = await handle.result;
|
|
12697
|
-
} else {
|
|
12698
|
-
result = await executor.execute(snapshot.payload, ac.signal);
|
|
12699
|
-
}
|
|
12700
|
-
const log = {
|
|
12701
|
-
id: snapshot.executionId,
|
|
12702
|
-
taskId: snapshot.taskId,
|
|
12703
|
-
taskName: snapshot.name,
|
|
12704
|
-
startedAt,
|
|
12705
|
-
finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12706
|
-
status: result.status === "running" ? "failure" : result.status,
|
|
12707
|
-
output: result.output,
|
|
12708
|
-
error: result.error
|
|
12709
|
-
};
|
|
12710
|
-
switch (log.status) {
|
|
12711
|
-
case "success":
|
|
12712
|
-
this.listener?.onCompleted({
|
|
12713
|
-
executionId: snapshot.executionId,
|
|
12714
|
-
log
|
|
12715
|
-
});
|
|
12716
|
-
break;
|
|
12717
|
-
case "cancelled":
|
|
12718
|
-
this.listener?.onCancelled({
|
|
12719
|
-
executionId: snapshot.executionId,
|
|
12720
|
-
log
|
|
12721
|
-
});
|
|
12722
|
-
break;
|
|
12723
|
-
case "timeout":
|
|
12724
|
-
this.listener?.onFailed({
|
|
12725
|
-
executionId: snapshot.executionId,
|
|
12726
|
-
status: "timeout",
|
|
12727
|
-
reason: "timeout",
|
|
12728
|
-
log
|
|
12729
|
-
});
|
|
12730
|
-
break;
|
|
12731
|
-
default:
|
|
12732
|
-
this.listener?.onFailed({
|
|
12733
|
-
executionId: snapshot.executionId,
|
|
12734
|
-
status: "failure",
|
|
12735
|
-
reason: "error",
|
|
12736
|
-
log
|
|
12737
|
-
});
|
|
12738
|
-
break;
|
|
12739
|
-
}
|
|
12740
|
-
} catch (err) {
|
|
12741
|
-
const log = {
|
|
12742
|
-
id: snapshot.executionId,
|
|
12743
|
-
taskId: snapshot.taskId,
|
|
12744
|
-
taskName: snapshot.name,
|
|
12745
|
-
startedAt,
|
|
12746
|
-
finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12747
|
-
status: ac.signal.aborted ? "cancelled" : "failure",
|
|
12748
|
-
error: err instanceof Error ? err.message : String(err)
|
|
12749
|
-
};
|
|
12750
|
-
if (ac.signal.aborted) {
|
|
12751
|
-
this.listener?.onCancelled({
|
|
12752
|
-
executionId: snapshot.executionId,
|
|
12753
|
-
log
|
|
12754
|
-
});
|
|
12755
|
-
} else {
|
|
12756
|
-
this.listener?.onFailed({
|
|
12757
|
-
executionId: snapshot.executionId,
|
|
12758
|
-
status: "failure",
|
|
12759
|
-
reason: "error",
|
|
12760
|
-
log
|
|
12761
|
-
});
|
|
12762
|
-
}
|
|
12763
|
-
} finally {
|
|
12764
|
-
this.running.delete(snapshot.executionId);
|
|
12765
|
-
const taskExecIds = this.taskExecutions.get(snapshot.taskId);
|
|
12766
|
-
if (taskExecIds) {
|
|
12767
|
-
taskExecIds.delete(snapshot.executionId);
|
|
12768
|
-
if (taskExecIds.size === 0) {
|
|
12769
|
-
this.taskExecutions.delete(snapshot.taskId);
|
|
12770
|
-
}
|
|
12771
|
-
}
|
|
12772
|
-
}
|
|
12773
|
-
}
|
|
12774
|
-
cancel(executionId) {
|
|
12775
|
-
const exec = this.running.get(executionId);
|
|
12776
|
-
if (!exec) return false;
|
|
12777
|
-
exec.cancel();
|
|
12778
|
-
return true;
|
|
12779
|
-
}
|
|
12780
|
-
listRunning() {
|
|
12781
|
-
return Array.from(this.running.values()).map((e) => ({
|
|
12782
|
-
executionId: e.executionId,
|
|
12783
|
-
taskId: e.taskId,
|
|
12784
|
-
startedAt: e.startedAt
|
|
12785
|
-
}));
|
|
12786
|
-
}
|
|
12787
|
-
dispose() {
|
|
12788
|
-
for (const exec of this.running.values()) {
|
|
12789
|
-
exec.cancel();
|
|
12790
|
-
}
|
|
12791
|
-
this.running.clear();
|
|
12792
|
-
this.taskExecutions.clear();
|
|
12793
|
-
}
|
|
12794
|
-
};
|
|
12795
|
-
}
|
|
12796
|
-
});
|
|
12797
|
-
|
|
12798
13068
|
// ../../packages/serviceme-core/src/scheduled-tasks/index.ts
|
|
12799
13069
|
var init_scheduled_tasks2 = __esm({
|
|
12800
13070
|
"../../packages/serviceme-core/src/scheduled-tasks/index.ts"() {
|
|
@@ -12836,7 +13106,9 @@ __export(src_exports, {
|
|
|
12836
13106
|
moveFiles: () => moveFiles,
|
|
12837
13107
|
noopLogger: () => noopLogger,
|
|
12838
13108
|
parseIntervalMs: () => parseIntervalMs,
|
|
12839
|
-
|
|
13109
|
+
resolveTaskExecutionPayload: () => resolveTaskExecutionPayload,
|
|
13110
|
+
unzipFile: () => unzipFile,
|
|
13111
|
+
validateTaskPayload: () => validateTaskPayload
|
|
12840
13112
|
});
|
|
12841
13113
|
var init_src2 = __esm({
|
|
12842
13114
|
"../../packages/serviceme-core/src/index.ts"() {
|
|
@@ -12905,7 +13177,7 @@ init_src();
|
|
|
12905
13177
|
|
|
12906
13178
|
// src/version.ts
|
|
12907
13179
|
var SERVICEME_CLI_NAME = "serviceme";
|
|
12908
|
-
var SERVICEME_CLI_VERSION = "0.1.
|
|
13180
|
+
var SERVICEME_CLI_VERSION = "0.1.4";
|
|
12909
13181
|
|
|
12910
13182
|
// src/bridge/ndjson.ts
|
|
12911
13183
|
function writeBridgeMessage(message) {
|
|
@@ -13432,7 +13704,7 @@ function requireWorkspace(parsed) {
|
|
|
13432
13704
|
"Missing required flag: --workspacePath"
|
|
13433
13705
|
);
|
|
13434
13706
|
}
|
|
13435
|
-
if (!
|
|
13707
|
+
if (!fs8__namespace.existsSync(wp)) {
|
|
13436
13708
|
throw createServicemeError(
|
|
13437
13709
|
"workspace_not_found",
|
|
13438
13710
|
`Workspace path does not exist: ${wp}`
|
|
@@ -13765,8 +14037,14 @@ async function handleTrigger(parsed) {
|
|
|
13765
14037
|
);
|
|
13766
14038
|
}
|
|
13767
14039
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
14040
|
+
const executionPayload = resolveTaskExecutionPayload(
|
|
14041
|
+
task.taskType,
|
|
14042
|
+
task.payload,
|
|
14043
|
+
wp
|
|
14044
|
+
);
|
|
14045
|
+
validateTaskPayload(task.taskType, executionPayload);
|
|
13768
14046
|
const executor = getExecutor(task.taskType);
|
|
13769
|
-
const result = await executor.execute(
|
|
14047
|
+
const result = await executor.execute(executionPayload);
|
|
13770
14048
|
const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
13771
14049
|
const logMgr = new TaskLogManager(wp);
|
|
13772
14050
|
const log = logMgr.appendLog({
|
|
@@ -13995,7 +14273,7 @@ function requireWorkspace2(parsed) {
|
|
|
13995
14273
|
"Missing required flag: --workspacePath"
|
|
13996
14274
|
);
|
|
13997
14275
|
}
|
|
13998
|
-
if (!
|
|
14276
|
+
if (!fs8__namespace.existsSync(wp)) {
|
|
13999
14277
|
throw createServicemeError(
|
|
14000
14278
|
"workspace_not_found",
|
|
14001
14279
|
`Workspace path does not exist: ${wp}`
|
|
@@ -14024,20 +14302,43 @@ function handleStart(parsed) {
|
|
|
14024
14302
|
}
|
|
14025
14303
|
const logPath = path__namespace.join(wp, ".serviceme", "scheduler.log");
|
|
14026
14304
|
const logDir = path__namespace.dirname(logPath);
|
|
14027
|
-
if (!
|
|
14028
|
-
|
|
14029
|
-
}
|
|
14030
|
-
const
|
|
14031
|
-
const
|
|
14032
|
-
|
|
14033
|
-
|
|
14034
|
-
|
|
14035
|
-
|
|
14036
|
-
|
|
14037
|
-
|
|
14038
|
-
|
|
14039
|
-
|
|
14305
|
+
if (!fs8__namespace.existsSync(logDir)) {
|
|
14306
|
+
fs8__namespace.mkdirSync(logDir, { recursive: true });
|
|
14307
|
+
}
|
|
14308
|
+
const spawnCmd = process.execPath;
|
|
14309
|
+
const spawnArgs = [
|
|
14310
|
+
cliPath,
|
|
14311
|
+
"scheduler",
|
|
14312
|
+
"__daemon",
|
|
14313
|
+
"--workspacePath",
|
|
14314
|
+
wp,
|
|
14315
|
+
"--logPath",
|
|
14316
|
+
logPath
|
|
14317
|
+
];
|
|
14318
|
+
if (process.platform === "win32") {
|
|
14319
|
+
fs8__namespace.appendFileSync(
|
|
14320
|
+
logPath,
|
|
14321
|
+
`[scheduler:start] spawning daemon via hidden PowerShell Start-Process: cmd=${spawnCmd}, args=${JSON.stringify(spawnArgs)}, platform=${process.platform}, windowsHide=true
|
|
14322
|
+
`
|
|
14323
|
+
);
|
|
14324
|
+
const pid2 = startWindowsDaemon(spawnCmd, spawnArgs);
|
|
14325
|
+
pidMgr.writePid(pid2);
|
|
14326
|
+
writeSuccess({ pid: pid2, status: "started", workspacePath: wp });
|
|
14327
|
+
return;
|
|
14328
|
+
}
|
|
14329
|
+
const out = fs8__namespace.openSync(logPath, "a");
|
|
14330
|
+
const err = fs8__namespace.openSync(logPath, "a");
|
|
14331
|
+
fs8__namespace.appendFileSync(
|
|
14332
|
+
logPath,
|
|
14333
|
+
`[scheduler:start] spawning daemon: cmd=${spawnCmd}, args=${JSON.stringify(spawnArgs)}, platform=${process.platform}, detached=true, windowsHide=true
|
|
14334
|
+
`
|
|
14040
14335
|
);
|
|
14336
|
+
const child = child_process.spawn(spawnCmd, spawnArgs, {
|
|
14337
|
+
detached: true,
|
|
14338
|
+
stdio: ["ignore", out, err],
|
|
14339
|
+
env: { ...process.env },
|
|
14340
|
+
windowsHide: true
|
|
14341
|
+
});
|
|
14041
14342
|
child.unref();
|
|
14042
14343
|
const pid = child.pid;
|
|
14043
14344
|
if (pid === void 0) {
|
|
@@ -14049,6 +14350,60 @@ function handleStart(parsed) {
|
|
|
14049
14350
|
pidMgr.writePid(pid);
|
|
14050
14351
|
writeSuccess({ pid, status: "started", workspacePath: wp });
|
|
14051
14352
|
}
|
|
14353
|
+
function startWindowsDaemon(command, args) {
|
|
14354
|
+
const argumentLine = args.map(quoteWindowsArgument).join(" ");
|
|
14355
|
+
const script = [
|
|
14356
|
+
"$ErrorActionPreference = 'Stop'",
|
|
14357
|
+
`$process = Start-Process -FilePath ${quotePowerShellString(command)} -ArgumentList ${quotePowerShellString(argumentLine)} -WindowStyle Hidden -PassThru`,
|
|
14358
|
+
"Write-Output $process.Id"
|
|
14359
|
+
].join("; ");
|
|
14360
|
+
const encodedCommand = Buffer.from(script, "utf16le").toString("base64");
|
|
14361
|
+
const result = child_process.spawnSync(
|
|
14362
|
+
"powershell.exe",
|
|
14363
|
+
[
|
|
14364
|
+
"-NoProfile",
|
|
14365
|
+
"-NonInteractive",
|
|
14366
|
+
"-ExecutionPolicy",
|
|
14367
|
+
"Bypass",
|
|
14368
|
+
"-WindowStyle",
|
|
14369
|
+
"Hidden",
|
|
14370
|
+
"-EncodedCommand",
|
|
14371
|
+
encodedCommand
|
|
14372
|
+
],
|
|
14373
|
+
{
|
|
14374
|
+
encoding: "utf8",
|
|
14375
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
14376
|
+
windowsHide: true
|
|
14377
|
+
}
|
|
14378
|
+
);
|
|
14379
|
+
if (result.error) {
|
|
14380
|
+
throw createServicemeError(
|
|
14381
|
+
"internal_error",
|
|
14382
|
+
`Failed to start scheduler daemon: ${result.error.message}`
|
|
14383
|
+
);
|
|
14384
|
+
}
|
|
14385
|
+
if (result.status !== 0) {
|
|
14386
|
+
const stderr = result.stderr.trim();
|
|
14387
|
+
throw createServicemeError(
|
|
14388
|
+
"internal_error",
|
|
14389
|
+
`Failed to start scheduler daemon${stderr ? `: ${stderr}` : ""}`
|
|
14390
|
+
);
|
|
14391
|
+
}
|
|
14392
|
+
const pid = Number.parseInt(result.stdout.trim(), 10);
|
|
14393
|
+
if (!Number.isFinite(pid)) {
|
|
14394
|
+
throw createServicemeError(
|
|
14395
|
+
"internal_error",
|
|
14396
|
+
`Failed to parse scheduler daemon PID: ${result.stdout.trim()}`
|
|
14397
|
+
);
|
|
14398
|
+
}
|
|
14399
|
+
return pid;
|
|
14400
|
+
}
|
|
14401
|
+
function quotePowerShellString(value) {
|
|
14402
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
14403
|
+
}
|
|
14404
|
+
function quoteWindowsArgument(value) {
|
|
14405
|
+
return `"${value.replace(/(\\*)"/g, '$1$1\\"').replace(/\\+$/g, "$&$&")}"`;
|
|
14406
|
+
}
|
|
14052
14407
|
function handleStop(parsed) {
|
|
14053
14408
|
const wp = requireWorkspace2(parsed);
|
|
14054
14409
|
if (!getBooleanFlag(parsed, "yes")) {
|
|
@@ -14084,7 +14439,7 @@ function handleStatus(parsed) {
|
|
|
14084
14439
|
let uptimeSeconds = null;
|
|
14085
14440
|
if (pid !== null) {
|
|
14086
14441
|
try {
|
|
14087
|
-
const stat2 =
|
|
14442
|
+
const stat2 = fs8__namespace.statSync(pidMgr.getPidPath());
|
|
14088
14443
|
uptimeSeconds = Math.floor((Date.now() - stat2.mtimeMs) / 1e3);
|
|
14089
14444
|
} catch {
|
|
14090
14445
|
uptimeSeconds = null;
|
|
@@ -14103,6 +14458,10 @@ function handleStatus(parsed) {
|
|
|
14103
14458
|
}
|
|
14104
14459
|
async function runDaemon(parsed) {
|
|
14105
14460
|
const wp = requireWorkspace2(parsed);
|
|
14461
|
+
const logPath = getStringFlag(parsed, "logPath");
|
|
14462
|
+
if (logPath) {
|
|
14463
|
+
process.env.SERVICEME_SCHEDULER_LOG_PATH = logPath;
|
|
14464
|
+
}
|
|
14106
14465
|
const pidMgr = new PidManager(wp);
|
|
14107
14466
|
const existingPid = pidMgr.getRunningPid();
|
|
14108
14467
|
if (existingPid !== null && existingPid !== process.pid) {
|