@gethmy/agent 1.20.1 → 1.21.0
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/cli.js +107 -51
- package/dist/index.js +107 -51
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -3240,12 +3240,48 @@ ${summary}`,
|
|
|
3240
3240
|
agent_identifier: "harmony-agent"
|
|
3241
3241
|
};
|
|
3242
3242
|
}
|
|
3243
|
-
async function writeEpisode(client, input) {
|
|
3243
|
+
async function writeEpisode(client, input, options) {
|
|
3244
3244
|
const payload = buildEpisodePayload(input, input.card.project_id);
|
|
3245
|
+
let content = payload.content;
|
|
3246
|
+
if (options?.distiller) {
|
|
3247
|
+
try {
|
|
3248
|
+
const distilled = await options.distiller(input, payload.content);
|
|
3249
|
+
if (distilled && distilled.trim().length > 0) {
|
|
3250
|
+
content = distilled.trim();
|
|
3251
|
+
}
|
|
3252
|
+
} catch (err) {
|
|
3253
|
+
log.warn(TAG10, `episode distillation failed for #${input.card.short_id}`, {
|
|
3254
|
+
cardId: input.card.id,
|
|
3255
|
+
event: "episode_distill_failed",
|
|
3256
|
+
kind: input.kind,
|
|
3257
|
+
error: err instanceof Error ? err.message : String(err)
|
|
3258
|
+
});
|
|
3259
|
+
}
|
|
3260
|
+
}
|
|
3261
|
+
const metadata = payload.metadata;
|
|
3245
3262
|
try {
|
|
3263
|
+
const existingId = await findRollingEpisode(client, input.workspaceId, input.card.project_id, input.card.short_id, input.kind);
|
|
3264
|
+
if (existingId) {
|
|
3265
|
+
await client.updateMemoryEntity(existingId, {
|
|
3266
|
+
title: payload.title,
|
|
3267
|
+
content,
|
|
3268
|
+
metadata,
|
|
3269
|
+
confidence: payload.confidence,
|
|
3270
|
+
tags: payload.tags,
|
|
3271
|
+
type: payload.type
|
|
3272
|
+
});
|
|
3273
|
+
log.info(TAG10, `episode rolled for #${input.card.short_id}`, {
|
|
3274
|
+
cardId: input.card.id,
|
|
3275
|
+
event: "episode_rolled",
|
|
3276
|
+
kind: input.kind,
|
|
3277
|
+
entityId: existingId
|
|
3278
|
+
});
|
|
3279
|
+
return existingId;
|
|
3280
|
+
}
|
|
3246
3281
|
const { entity } = await client.createMemoryEntity({
|
|
3247
3282
|
...payload,
|
|
3248
|
-
|
|
3283
|
+
content,
|
|
3284
|
+
metadata
|
|
3249
3285
|
});
|
|
3250
3286
|
const id = entity && typeof entity === "object" && "id" in entity ? entity.id ?? null : null;
|
|
3251
3287
|
log.info(TAG10, `episode written for #${input.card.short_id}`, {
|
|
@@ -3264,31 +3300,44 @@ async function writeEpisode(client, input) {
|
|
|
3264
3300
|
return null;
|
|
3265
3301
|
}
|
|
3266
3302
|
}
|
|
3267
|
-
async function
|
|
3303
|
+
async function findRollingEpisode(client, workspaceId, projectId, cardShortId, kind) {
|
|
3304
|
+
const type = kind === "implement" ? ["solution", "error"] : ["decision"];
|
|
3268
3305
|
try {
|
|
3269
3306
|
const { entities } = await client.harmonyRecall({
|
|
3270
3307
|
workspaceId,
|
|
3271
3308
|
projectId,
|
|
3272
|
-
type
|
|
3309
|
+
type,
|
|
3273
3310
|
memory_tier: "episode",
|
|
3274
3311
|
scope: "project",
|
|
3275
3312
|
tags: [`card:${cardShortId}`],
|
|
3276
|
-
topK:
|
|
3313
|
+
topK: 10,
|
|
3314
|
+
includeEpisodes: true
|
|
3277
3315
|
});
|
|
3278
|
-
const
|
|
3279
|
-
|
|
3280
|
-
|
|
3316
|
+
for (const entity of entities) {
|
|
3317
|
+
if (!entity || typeof entity !== "object")
|
|
3318
|
+
continue;
|
|
3319
|
+
const meta = entity.metadata;
|
|
3320
|
+
if (meta?.episode_kind !== kind || meta?.origin?.source !== "agent-run") {
|
|
3321
|
+
continue;
|
|
3322
|
+
}
|
|
3323
|
+
const id = entity.id;
|
|
3324
|
+
if (typeof id === "string")
|
|
3325
|
+
return id;
|
|
3281
3326
|
}
|
|
3282
3327
|
return null;
|
|
3283
3328
|
} catch (err) {
|
|
3284
|
-
log.warn(TAG10, "
|
|
3329
|
+
log.warn(TAG10, "rolling-episode lookup failed", {
|
|
3285
3330
|
event: "episode_lookup_failed",
|
|
3286
3331
|
cardShortId,
|
|
3332
|
+
kind,
|
|
3287
3333
|
error: err instanceof Error ? err.message : String(err)
|
|
3288
3334
|
});
|
|
3289
3335
|
return null;
|
|
3290
3336
|
}
|
|
3291
3337
|
}
|
|
3338
|
+
async function findLatestImplementEpisode(client, workspaceId, projectId, cardShortId) {
|
|
3339
|
+
return findRollingEpisode(client, workspaceId, projectId, cardShortId, "implement");
|
|
3340
|
+
}
|
|
3292
3341
|
async function backfillReviewVerdict(client, originalEpisodeId, verdict, reviewEpisodeId) {
|
|
3293
3342
|
try {
|
|
3294
3343
|
if (verdict === "approved") {
|
|
@@ -8937,53 +8986,58 @@ class Pool {
|
|
|
8937
8986
|
}
|
|
8938
8987
|
}
|
|
8939
8988
|
async enqueue(card, column, labels, subtasks, mode = "implement") {
|
|
8940
|
-
if (this.
|
|
8941
|
-
log.debug(TAG31, `Card ${card.id} already queued or
|
|
8989
|
+
if (this.isCardKnown(card.id) || this.reservations.has(card.id)) {
|
|
8990
|
+
log.debug(TAG31, `Card ${card.id} already queued, active, or reserved, skipping`);
|
|
8942
8991
|
return;
|
|
8943
8992
|
}
|
|
8944
|
-
|
|
8945
|
-
|
|
8946
|
-
|
|
8947
|
-
|
|
8948
|
-
|
|
8949
|
-
|
|
8950
|
-
|
|
8951
|
-
|
|
8952
|
-
|
|
8953
|
-
|
|
8954
|
-
|
|
8955
|
-
|
|
8956
|
-
|
|
8957
|
-
|
|
8958
|
-
|
|
8959
|
-
|
|
8960
|
-
|
|
8961
|
-
|
|
8962
|
-
|
|
8993
|
+
this.reservations.add(card.id);
|
|
8994
|
+
try {
|
|
8995
|
+
if (mode === "implement") {
|
|
8996
|
+
if (this.authPaused) {
|
|
8997
|
+
log.debug(TAG31, `#${card.short_id} held — agent paused (auth error)`);
|
|
8998
|
+
await this.emitWaiting(card.id, "Agent paused — Anthropic auth error, check API credentials");
|
|
8999
|
+
return;
|
|
9000
|
+
}
|
|
9001
|
+
const cooldownMs = this.apiCooldownRemainingMs();
|
|
9002
|
+
if (cooldownMs > 0) {
|
|
9003
|
+
log.debug(TAG31, `#${card.short_id} held — API cooldown ${Math.round(cooldownMs / 1000)}s remaining`);
|
|
9004
|
+
await this.emitWaiting(card.id, `Paused — Anthropic API limit, retrying in ~${Math.round(cooldownMs / 1000)}s`);
|
|
9005
|
+
return;
|
|
9006
|
+
}
|
|
9007
|
+
const decision = this.budget.check(card.id);
|
|
9008
|
+
if (!decision.allow) {
|
|
9009
|
+
if (decision.reason === "daily_budget") {
|
|
9010
|
+
log.warn(TAG31, `#${card.short_id} skipped (daily_budget): ${decision.detail}`);
|
|
9011
|
+
await this.emitWaiting(card.id, `Daily budget reached — waiting for reset (${decision.detail})`);
|
|
9012
|
+
} else {
|
|
9013
|
+
log.debug(TAG31, `#${card.short_id} gave up: ${decision.detail}`);
|
|
9014
|
+
}
|
|
9015
|
+
return;
|
|
9016
|
+
}
|
|
9017
|
+
const blockers = await getUnresolvedBlockers(this.client, card, this.projectId);
|
|
9018
|
+
if (blockers === null) {
|
|
9019
|
+
log.warn(TAG31, `#${card.short_id} blocker check failed — deferring to next tick`);
|
|
9020
|
+
return;
|
|
9021
|
+
}
|
|
9022
|
+
if (blockers.length > 0) {
|
|
9023
|
+
const list = blockers.map((b) => `#${b.shortId}`).join(", ");
|
|
9024
|
+
log.info(TAG31, `#${card.short_id} blocked by ${list} — waiting`);
|
|
9025
|
+
await this.emitWaiting(card.id, `Blocked by ${list} — waiting for chain`);
|
|
9026
|
+
return;
|
|
8963
9027
|
}
|
|
8964
|
-
return;
|
|
8965
|
-
}
|
|
8966
|
-
const blockers = await getUnresolvedBlockers(this.client, card, this.projectId);
|
|
8967
|
-
if (blockers === null) {
|
|
8968
|
-
log.warn(TAG31, `#${card.short_id} blocker check failed — deferring to next tick`);
|
|
8969
|
-
return;
|
|
8970
9028
|
}
|
|
8971
|
-
|
|
8972
|
-
|
|
8973
|
-
|
|
8974
|
-
|
|
8975
|
-
|
|
9029
|
+
const queue = mode === "review" ? this.reviewQueue : this.implQueue;
|
|
9030
|
+
queue.enqueue(card, column, labels, mode);
|
|
9031
|
+
this.cardDataCache.set(card.id, { card, column, labels, subtasks, mode });
|
|
9032
|
+
const workers = mode === "review" ? this.reviewWorkers : this.implWorkers;
|
|
9033
|
+
const dispatched = this.tryDispatchFor(workers, queue, mode);
|
|
9034
|
+
if (!dispatched) {
|
|
9035
|
+
const position = queue.cardIds().indexOf(card.id) + 1;
|
|
9036
|
+
const total = queue.length;
|
|
9037
|
+
await this.emitWaiting(card.id, position > 0 ? `Queued (${position}/${total}) — waiting for ${mode} worker` : `Queued — waiting for ${mode} worker`);
|
|
8976
9038
|
}
|
|
8977
|
-
}
|
|
8978
|
-
|
|
8979
|
-
queue.enqueue(card, column, labels, mode);
|
|
8980
|
-
this.cardDataCache.set(card.id, { card, column, labels, subtasks, mode });
|
|
8981
|
-
const workers = mode === "review" ? this.reviewWorkers : this.implWorkers;
|
|
8982
|
-
const dispatched = this.tryDispatchFor(workers, queue, mode);
|
|
8983
|
-
if (!dispatched) {
|
|
8984
|
-
const position = queue.cardIds().indexOf(card.id) + 1;
|
|
8985
|
-
const total = queue.length;
|
|
8986
|
-
await this.emitWaiting(card.id, position > 0 ? `Queued (${position}/${total}) — waiting for ${mode} worker` : `Queued — waiting for ${mode} worker`);
|
|
9039
|
+
} finally {
|
|
9040
|
+
this.reservations.delete(card.id);
|
|
8987
9041
|
}
|
|
8988
9042
|
}
|
|
8989
9043
|
lastWaitingEmit = new Map;
|
|
@@ -9025,6 +9079,7 @@ class Pool {
|
|
|
9025
9079
|
async removeCard(cardId) {
|
|
9026
9080
|
await this.stateStore.resetAttempts(cardId);
|
|
9027
9081
|
this.lastWaitingEmit.delete(cardId);
|
|
9082
|
+
this.reservations.delete(cardId);
|
|
9028
9083
|
for (const queue of [this.implQueue, this.reviewQueue]) {
|
|
9029
9084
|
const removed = queue.remove(cardId);
|
|
9030
9085
|
if (removed) {
|
|
@@ -9129,6 +9184,7 @@ class Pool {
|
|
|
9129
9184
|
this.sleepGuard.stop();
|
|
9130
9185
|
log.info(TAG31, "Pool shutdown complete");
|
|
9131
9186
|
}
|
|
9187
|
+
reservations = new Set;
|
|
9132
9188
|
cardDataCache = new Map;
|
|
9133
9189
|
tryDispatchFor(workers, queue, label) {
|
|
9134
9190
|
if (this.shuttingDown)
|
package/dist/index.js
CHANGED
|
@@ -3239,12 +3239,48 @@ ${summary}`,
|
|
|
3239
3239
|
agent_identifier: "harmony-agent"
|
|
3240
3240
|
};
|
|
3241
3241
|
}
|
|
3242
|
-
async function writeEpisode(client, input) {
|
|
3242
|
+
async function writeEpisode(client, input, options) {
|
|
3243
3243
|
const payload = buildEpisodePayload(input, input.card.project_id);
|
|
3244
|
+
let content = payload.content;
|
|
3245
|
+
if (options?.distiller) {
|
|
3246
|
+
try {
|
|
3247
|
+
const distilled = await options.distiller(input, payload.content);
|
|
3248
|
+
if (distilled && distilled.trim().length > 0) {
|
|
3249
|
+
content = distilled.trim();
|
|
3250
|
+
}
|
|
3251
|
+
} catch (err) {
|
|
3252
|
+
log.warn(TAG10, `episode distillation failed for #${input.card.short_id}`, {
|
|
3253
|
+
cardId: input.card.id,
|
|
3254
|
+
event: "episode_distill_failed",
|
|
3255
|
+
kind: input.kind,
|
|
3256
|
+
error: err instanceof Error ? err.message : String(err)
|
|
3257
|
+
});
|
|
3258
|
+
}
|
|
3259
|
+
}
|
|
3260
|
+
const metadata = payload.metadata;
|
|
3244
3261
|
try {
|
|
3262
|
+
const existingId = await findRollingEpisode(client, input.workspaceId, input.card.project_id, input.card.short_id, input.kind);
|
|
3263
|
+
if (existingId) {
|
|
3264
|
+
await client.updateMemoryEntity(existingId, {
|
|
3265
|
+
title: payload.title,
|
|
3266
|
+
content,
|
|
3267
|
+
metadata,
|
|
3268
|
+
confidence: payload.confidence,
|
|
3269
|
+
tags: payload.tags,
|
|
3270
|
+
type: payload.type
|
|
3271
|
+
});
|
|
3272
|
+
log.info(TAG10, `episode rolled for #${input.card.short_id}`, {
|
|
3273
|
+
cardId: input.card.id,
|
|
3274
|
+
event: "episode_rolled",
|
|
3275
|
+
kind: input.kind,
|
|
3276
|
+
entityId: existingId
|
|
3277
|
+
});
|
|
3278
|
+
return existingId;
|
|
3279
|
+
}
|
|
3245
3280
|
const { entity } = await client.createMemoryEntity({
|
|
3246
3281
|
...payload,
|
|
3247
|
-
|
|
3282
|
+
content,
|
|
3283
|
+
metadata
|
|
3248
3284
|
});
|
|
3249
3285
|
const id = entity && typeof entity === "object" && "id" in entity ? entity.id ?? null : null;
|
|
3250
3286
|
log.info(TAG10, `episode written for #${input.card.short_id}`, {
|
|
@@ -3263,31 +3299,44 @@ async function writeEpisode(client, input) {
|
|
|
3263
3299
|
return null;
|
|
3264
3300
|
}
|
|
3265
3301
|
}
|
|
3266
|
-
async function
|
|
3302
|
+
async function findRollingEpisode(client, workspaceId, projectId, cardShortId, kind) {
|
|
3303
|
+
const type = kind === "implement" ? ["solution", "error"] : ["decision"];
|
|
3267
3304
|
try {
|
|
3268
3305
|
const { entities } = await client.harmonyRecall({
|
|
3269
3306
|
workspaceId,
|
|
3270
3307
|
projectId,
|
|
3271
|
-
type
|
|
3308
|
+
type,
|
|
3272
3309
|
memory_tier: "episode",
|
|
3273
3310
|
scope: "project",
|
|
3274
3311
|
tags: [`card:${cardShortId}`],
|
|
3275
|
-
topK:
|
|
3312
|
+
topK: 10,
|
|
3313
|
+
includeEpisodes: true
|
|
3276
3314
|
});
|
|
3277
|
-
const
|
|
3278
|
-
|
|
3279
|
-
|
|
3315
|
+
for (const entity of entities) {
|
|
3316
|
+
if (!entity || typeof entity !== "object")
|
|
3317
|
+
continue;
|
|
3318
|
+
const meta = entity.metadata;
|
|
3319
|
+
if (meta?.episode_kind !== kind || meta?.origin?.source !== "agent-run") {
|
|
3320
|
+
continue;
|
|
3321
|
+
}
|
|
3322
|
+
const id = entity.id;
|
|
3323
|
+
if (typeof id === "string")
|
|
3324
|
+
return id;
|
|
3280
3325
|
}
|
|
3281
3326
|
return null;
|
|
3282
3327
|
} catch (err) {
|
|
3283
|
-
log.warn(TAG10, "
|
|
3328
|
+
log.warn(TAG10, "rolling-episode lookup failed", {
|
|
3284
3329
|
event: "episode_lookup_failed",
|
|
3285
3330
|
cardShortId,
|
|
3331
|
+
kind,
|
|
3286
3332
|
error: err instanceof Error ? err.message : String(err)
|
|
3287
3333
|
});
|
|
3288
3334
|
return null;
|
|
3289
3335
|
}
|
|
3290
3336
|
}
|
|
3337
|
+
async function findLatestImplementEpisode(client, workspaceId, projectId, cardShortId) {
|
|
3338
|
+
return findRollingEpisode(client, workspaceId, projectId, cardShortId, "implement");
|
|
3339
|
+
}
|
|
3291
3340
|
async function backfillReviewVerdict(client, originalEpisodeId, verdict, reviewEpisodeId) {
|
|
3292
3341
|
try {
|
|
3293
3342
|
if (verdict === "approved") {
|
|
@@ -8936,53 +8985,58 @@ class Pool {
|
|
|
8936
8985
|
}
|
|
8937
8986
|
}
|
|
8938
8987
|
async enqueue(card, column, labels, subtasks, mode = "implement") {
|
|
8939
|
-
if (this.
|
|
8940
|
-
log.debug(TAG31, `Card ${card.id} already queued or
|
|
8988
|
+
if (this.isCardKnown(card.id) || this.reservations.has(card.id)) {
|
|
8989
|
+
log.debug(TAG31, `Card ${card.id} already queued, active, or reserved, skipping`);
|
|
8941
8990
|
return;
|
|
8942
8991
|
}
|
|
8943
|
-
|
|
8944
|
-
|
|
8945
|
-
|
|
8946
|
-
|
|
8947
|
-
|
|
8948
|
-
|
|
8949
|
-
|
|
8950
|
-
|
|
8951
|
-
|
|
8952
|
-
|
|
8953
|
-
|
|
8954
|
-
|
|
8955
|
-
|
|
8956
|
-
|
|
8957
|
-
|
|
8958
|
-
|
|
8959
|
-
|
|
8960
|
-
|
|
8961
|
-
|
|
8992
|
+
this.reservations.add(card.id);
|
|
8993
|
+
try {
|
|
8994
|
+
if (mode === "implement") {
|
|
8995
|
+
if (this.authPaused) {
|
|
8996
|
+
log.debug(TAG31, `#${card.short_id} held — agent paused (auth error)`);
|
|
8997
|
+
await this.emitWaiting(card.id, "Agent paused — Anthropic auth error, check API credentials");
|
|
8998
|
+
return;
|
|
8999
|
+
}
|
|
9000
|
+
const cooldownMs = this.apiCooldownRemainingMs();
|
|
9001
|
+
if (cooldownMs > 0) {
|
|
9002
|
+
log.debug(TAG31, `#${card.short_id} held — API cooldown ${Math.round(cooldownMs / 1000)}s remaining`);
|
|
9003
|
+
await this.emitWaiting(card.id, `Paused — Anthropic API limit, retrying in ~${Math.round(cooldownMs / 1000)}s`);
|
|
9004
|
+
return;
|
|
9005
|
+
}
|
|
9006
|
+
const decision = this.budget.check(card.id);
|
|
9007
|
+
if (!decision.allow) {
|
|
9008
|
+
if (decision.reason === "daily_budget") {
|
|
9009
|
+
log.warn(TAG31, `#${card.short_id} skipped (daily_budget): ${decision.detail}`);
|
|
9010
|
+
await this.emitWaiting(card.id, `Daily budget reached — waiting for reset (${decision.detail})`);
|
|
9011
|
+
} else {
|
|
9012
|
+
log.debug(TAG31, `#${card.short_id} gave up: ${decision.detail}`);
|
|
9013
|
+
}
|
|
9014
|
+
return;
|
|
9015
|
+
}
|
|
9016
|
+
const blockers = await getUnresolvedBlockers(this.client, card, this.projectId);
|
|
9017
|
+
if (blockers === null) {
|
|
9018
|
+
log.warn(TAG31, `#${card.short_id} blocker check failed — deferring to next tick`);
|
|
9019
|
+
return;
|
|
9020
|
+
}
|
|
9021
|
+
if (blockers.length > 0) {
|
|
9022
|
+
const list = blockers.map((b) => `#${b.shortId}`).join(", ");
|
|
9023
|
+
log.info(TAG31, `#${card.short_id} blocked by ${list} — waiting`);
|
|
9024
|
+
await this.emitWaiting(card.id, `Blocked by ${list} — waiting for chain`);
|
|
9025
|
+
return;
|
|
8962
9026
|
}
|
|
8963
|
-
return;
|
|
8964
|
-
}
|
|
8965
|
-
const blockers = await getUnresolvedBlockers(this.client, card, this.projectId);
|
|
8966
|
-
if (blockers === null) {
|
|
8967
|
-
log.warn(TAG31, `#${card.short_id} blocker check failed — deferring to next tick`);
|
|
8968
|
-
return;
|
|
8969
9027
|
}
|
|
8970
|
-
|
|
8971
|
-
|
|
8972
|
-
|
|
8973
|
-
|
|
8974
|
-
|
|
9028
|
+
const queue = mode === "review" ? this.reviewQueue : this.implQueue;
|
|
9029
|
+
queue.enqueue(card, column, labels, mode);
|
|
9030
|
+
this.cardDataCache.set(card.id, { card, column, labels, subtasks, mode });
|
|
9031
|
+
const workers = mode === "review" ? this.reviewWorkers : this.implWorkers;
|
|
9032
|
+
const dispatched = this.tryDispatchFor(workers, queue, mode);
|
|
9033
|
+
if (!dispatched) {
|
|
9034
|
+
const position = queue.cardIds().indexOf(card.id) + 1;
|
|
9035
|
+
const total = queue.length;
|
|
9036
|
+
await this.emitWaiting(card.id, position > 0 ? `Queued (${position}/${total}) — waiting for ${mode} worker` : `Queued — waiting for ${mode} worker`);
|
|
8975
9037
|
}
|
|
8976
|
-
}
|
|
8977
|
-
|
|
8978
|
-
queue.enqueue(card, column, labels, mode);
|
|
8979
|
-
this.cardDataCache.set(card.id, { card, column, labels, subtasks, mode });
|
|
8980
|
-
const workers = mode === "review" ? this.reviewWorkers : this.implWorkers;
|
|
8981
|
-
const dispatched = this.tryDispatchFor(workers, queue, mode);
|
|
8982
|
-
if (!dispatched) {
|
|
8983
|
-
const position = queue.cardIds().indexOf(card.id) + 1;
|
|
8984
|
-
const total = queue.length;
|
|
8985
|
-
await this.emitWaiting(card.id, position > 0 ? `Queued (${position}/${total}) — waiting for ${mode} worker` : `Queued — waiting for ${mode} worker`);
|
|
9038
|
+
} finally {
|
|
9039
|
+
this.reservations.delete(card.id);
|
|
8986
9040
|
}
|
|
8987
9041
|
}
|
|
8988
9042
|
lastWaitingEmit = new Map;
|
|
@@ -9024,6 +9078,7 @@ class Pool {
|
|
|
9024
9078
|
async removeCard(cardId) {
|
|
9025
9079
|
await this.stateStore.resetAttempts(cardId);
|
|
9026
9080
|
this.lastWaitingEmit.delete(cardId);
|
|
9081
|
+
this.reservations.delete(cardId);
|
|
9027
9082
|
for (const queue of [this.implQueue, this.reviewQueue]) {
|
|
9028
9083
|
const removed = queue.remove(cardId);
|
|
9029
9084
|
if (removed) {
|
|
@@ -9128,6 +9183,7 @@ class Pool {
|
|
|
9128
9183
|
this.sleepGuard.stop();
|
|
9129
9184
|
log.info(TAG31, "Pool shutdown complete");
|
|
9130
9185
|
}
|
|
9186
|
+
reservations = new Set;
|
|
9131
9187
|
cardDataCache = new Map;
|
|
9132
9188
|
tryDispatchFor(workers, queue, label) {
|
|
9133
9189
|
if (this.shuttingDown)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gethmy/agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.21.0",
|
|
4
4
|
"description": "Push-based agent daemon for Harmony — watches board assignments and spawns Claude CLI workers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@anthropic-ai/claude-agent-sdk": "^0.3.178",
|
|
48
48
|
"@supabase/supabase-js": "2.95.3",
|
|
49
|
-
"@gethmy/mcp": "^2.
|
|
49
|
+
"@gethmy/mcp": "^2.17.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@harmony/shared": "workspace:*",
|