ework-daemon 0.4.33 → 0.4.35
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/package.json +1 -1
- package/src/config.ts +6 -1
- package/src/opencode.ts +15 -3
- package/src/server.ts +1 -0
package/package.json
CHANGED
package/src/config.ts
CHANGED
|
@@ -25,6 +25,7 @@ export const configSchema = z.object({
|
|
|
25
25
|
port: z.coerce.number().default(3101),
|
|
26
26
|
host: z.string().default("0.0.0.0"),
|
|
27
27
|
endpoint: z.string().default(""),
|
|
28
|
+
nonWakingAuthors: z.array(z.string()).default([]),
|
|
28
29
|
}),
|
|
29
30
|
opencode: z.object({
|
|
30
31
|
binary: z.string().default("opencode"),
|
|
@@ -45,6 +46,7 @@ export const configSchema = z.object({
|
|
|
45
46
|
work: z.object({
|
|
46
47
|
capacity: z.coerce.number().int().positive().default(4),
|
|
47
48
|
maxConcurrent: z.coerce.number().int().positive().default(4),
|
|
49
|
+
maxConcurrentExplicit: z.boolean().default(false),
|
|
48
50
|
heartbeatMs: z.coerce.number().int().positive().default(10_000),
|
|
49
51
|
leaseTtlMs: z.coerce.number().int().positive().default(60_000),
|
|
50
52
|
}),
|
|
@@ -95,9 +97,11 @@ const TEST_DEFAULTS = {
|
|
|
95
97
|
|
|
96
98
|
function readWorkSection() {
|
|
97
99
|
const capacity = process.env.WORK_DAEMON_CAPACITY ? Number(process.env.WORK_DAEMON_CAPACITY) : 4;
|
|
100
|
+
const maxConcurrentExplicit = process.env.WORK_MAX_CONCURRENT != null;
|
|
98
101
|
return {
|
|
99
102
|
capacity,
|
|
100
|
-
maxConcurrent:
|
|
103
|
+
maxConcurrent: maxConcurrentExplicit ? Number(process.env.WORK_MAX_CONCURRENT) : capacity,
|
|
104
|
+
maxConcurrentExplicit,
|
|
101
105
|
heartbeatMs: process.env.WORK_DAEMON_HEARTBEAT_MS ? Number(process.env.WORK_DAEMON_HEARTBEAT_MS) : 10_000,
|
|
102
106
|
leaseTtlMs: process.env.WORK_DAEMON_LEASE_TTL_MS ? Number(process.env.WORK_DAEMON_LEASE_TTL_MS) : 60_000,
|
|
103
107
|
};
|
|
@@ -139,6 +143,7 @@ export function loadConfig(): Config {
|
|
|
139
143
|
port: process.env.DAEMON_PORT ?? TEST_DEFAULTS.daemon.port,
|
|
140
144
|
host: process.env.DAEMON_HOST ?? TEST_DEFAULTS.daemon.host,
|
|
141
145
|
endpoint: process.env.DAEMON_ENDPOINT ?? "",
|
|
146
|
+
nonWakingAuthors: (process.env.WORK_NON_WAKING_AUTHORS ?? "").split(",").map((s) => s.trim()).filter(Boolean),
|
|
142
147
|
},
|
|
143
148
|
opencode: {
|
|
144
149
|
binary: process.env.OPENCODE_BINARY ?? TEST_DEFAULTS.opencode.binary,
|
package/src/opencode.ts
CHANGED
|
@@ -301,6 +301,7 @@ export class Engine {
|
|
|
301
301
|
private readonly backend: RuntimeBackend;
|
|
302
302
|
private heartbeatTimer?: ReturnType<typeof setInterval>;
|
|
303
303
|
private maxConcurrent: number;
|
|
304
|
+
private maxConcurrentExplicit: boolean;
|
|
304
305
|
|
|
305
306
|
// Runtime state keyed by session key (trackerType:scopeKey#issueId@sessionName)
|
|
306
307
|
private processes = new Map<string, RuntimeHandle>();
|
|
@@ -350,6 +351,7 @@ export class Engine {
|
|
|
350
351
|
this.takeover = opts.takeover ?? new RecloneStrategy(cfg);
|
|
351
352
|
this.backend = opts.backend ?? createDefaultBackend(cfg);
|
|
352
353
|
this.maxConcurrent = cfg.work.maxConcurrent;
|
|
354
|
+
this.maxConcurrentExplicit = cfg.work.maxConcurrentExplicit;
|
|
353
355
|
this.startGlobalObserver();
|
|
354
356
|
void this.recover();
|
|
355
357
|
}
|
|
@@ -376,6 +378,7 @@ export class Engine {
|
|
|
376
378
|
}
|
|
377
379
|
|
|
378
380
|
private async syncMaxConcurrent(): Promise<void> {
|
|
381
|
+
if (this.maxConcurrentExplicit) return;
|
|
379
382
|
try {
|
|
380
383
|
const cap = await this.store.getDaemonCapacity(this.daemonId);
|
|
381
384
|
if (cap != null && cap > 0 && cap !== this.maxConcurrent) {
|
|
@@ -388,7 +391,8 @@ export class Engine {
|
|
|
388
391
|
setMaxConcurrent(n: number): void {
|
|
389
392
|
if (!Number.isFinite(n) || n < 1) return;
|
|
390
393
|
this.maxConcurrent = Math.floor(n);
|
|
391
|
-
|
|
394
|
+
this.maxConcurrentExplicit = true;
|
|
395
|
+
log.info(`engine: maxConcurrent set to ${this.maxConcurrent} (explicit — DB sync disabled)`);
|
|
392
396
|
}
|
|
393
397
|
|
|
394
398
|
getMaxConcurrent(): number {
|
|
@@ -590,11 +594,19 @@ export class Engine {
|
|
|
590
594
|
return;
|
|
591
595
|
}
|
|
592
596
|
|
|
593
|
-
if (issueData.ai_status === "halted" && (event.type === "issue_opened" || event.type === "comment_created")) {
|
|
594
|
-
log.info(`engine: issue
|
|
597
|
+
if ((issueData.ai_status === "halted" || issueData.ai_status === "dispatch_off") && (event.type === "issue_opened" || event.type === "comment_created")) {
|
|
598
|
+
log.info(`engine: issue ${issueData.ai_status} — skipping ${event.type} for ${ref.trackerType}:${scopeKey}#${ref.issueId}`);
|
|
595
599
|
return;
|
|
596
600
|
}
|
|
597
601
|
|
|
602
|
+
if (event.type === "comment_created" && event.comment?.author) {
|
|
603
|
+
const author = event.comment.author;
|
|
604
|
+
if (this.cfg.daemon.nonWakingAuthors.includes(author)) {
|
|
605
|
+
log.info(`engine: non-waking author ${author} — skipping comment_created for ${ref.trackerType}:${scopeKey}#${ref.issueId}`);
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
|
|
598
610
|
const issueMapKey = `${ref.trackerType}:${scopeKey}#${ref.issueId}`;
|
|
599
611
|
if (groupConfig) {
|
|
600
612
|
this.groupConfigs.set(issueMapKey, groupConfig);
|
package/src/server.ts
CHANGED
|
@@ -81,6 +81,7 @@ export function createServer(
|
|
|
81
81
|
running: status.runningCount,
|
|
82
82
|
pending: status.pendingCount,
|
|
83
83
|
processes: status.processCount,
|
|
84
|
+
maxConcurrent: engine.getMaxConcurrent(),
|
|
84
85
|
observedIssues: status.observedIssues,
|
|
85
86
|
issues: (await store.listAllIssues()).length,
|
|
86
87
|
sessions: (await store.listAllSessions()).length,
|