@kubitnodes/stellaris 0.4.0 → 0.4.1
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/index.js +42 -19
- package/dist/server/index.js +159 -58
- package/package.json +1 -1
- package/web/dist/assets/BackLink-fxPmFUg8.js +1 -0
- package/web/dist/assets/Button-DxGzriWQ.js +1 -0
- package/web/dist/assets/ChannelForms-C3m4IPnZ.js +1 -0
- package/web/dist/assets/ChannelView-DvtoxLi5.js +2 -0
- package/web/dist/assets/CitizenView-Dq64VsZi.js +2 -0
- package/web/dist/assets/{CitizensView-DXD3qkq1.js → CitizensView-BOZHABbN.js} +1 -1
- package/web/dist/assets/{CliIcon-DL4ZwgZv.js → CliIcon-D3GddnP4.js} +1 -1
- package/web/dist/assets/CronsView-CI947lZS.js +1 -0
- package/web/dist/assets/{FileTree-BFa_KVI8.js → FileTree-DSFN4sd8.js} +1 -1
- package/web/dist/assets/{FileView-Cd9Ijarf.js → FileView-DyUYLXRC.js} +2 -2
- package/web/dist/assets/{KnowledgeView-D_a4pjGV.js → KnowledgeView-CMdXaTvS.js} +1 -1
- package/web/dist/assets/{Markdown-DPqvK--4.js → Markdown-BSeWHBBA.js} +5 -5
- package/web/dist/assets/{MessageItem-WBTzWwyj.js → MessageItem-qIxS96uJ.js} +1 -1
- package/web/dist/assets/{MetricsView-YUkYixqT.js → MetricsView-BhjdwkX1.js} +1 -1
- package/web/dist/assets/NeedsYouView-7uZW9dY8.js +1 -0
- package/web/dist/assets/Overview-D6kiK8sE.js +1 -0
- package/web/dist/assets/{Pane-C9TbEME4.js → Pane-pZUzNQIW.js} +1 -1
- package/web/dist/assets/{Picker-BK48MjLY.js → Picker-CDf6os_x.js} +1 -1
- package/web/dist/assets/{ProjectView-sL3aGAC6.js → ProjectView-B6OmxiT9.js} +1 -1
- package/web/dist/assets/ProposalView-B1X8Jlo0.js +1 -0
- package/web/dist/assets/{ProposalsView-DTGx8NDn.js → ProposalsView-DBGpcAPO.js} +1 -1
- package/web/dist/assets/{Quota-BkF7pa0u.js → Quota-Brd4ddB4.js} +1 -1
- package/web/dist/assets/RunnersView-45OXtalD.js +1 -0
- package/web/dist/assets/{SkillFileList-BUpKUkaG.js → SkillFileList-BUImALv9.js} +1 -1
- package/web/dist/assets/SkillView-B1knYZV8.js +1 -0
- package/web/dist/assets/SocietyView-F7bzrNv5.js +1 -0
- package/web/dist/assets/{StickyList-DafbJutb.js → StickyList-D_ED_-LW.js} +1 -1
- package/web/dist/assets/{SubjectThread-Jyl5YCFL.js → SubjectThread-B5zvoRSd.js} +1 -1
- package/web/dist/assets/{TaskView-Jke2pVGT.js → TaskView-B5_QTI3p.js} +2 -2
- package/web/dist/assets/{TasksView-zJTIaqEA.js → TasksView-DZLNqU2V.js} +1 -1
- package/web/dist/assets/{ThreadForms-DwUOktyP.js → ThreadForms-CbFClyd0.js} +1 -1
- package/web/dist/assets/{ThreadItem-Blx8gSvO.js → ThreadItem-kFn5M3Cx.js} +1 -1
- package/web/dist/assets/{ThreadView-CdQpBb7M.js → ThreadView-CHFs0zaS.js} +1 -1
- package/web/dist/assets/{citizen-BOn5BBRL.js → citizen-B8p56JRh.js} +1 -1
- package/web/dist/assets/{compose-D-X3BQgY.js → compose-CV4o6TMb.js} +1 -1
- package/web/dist/assets/{format-Dhd2NUB3.js → format-BYF63sQU.js} +1 -1
- package/web/dist/assets/{governance-CWzi7hzX.js → governance-BjIg0eok.js} +1 -1
- package/web/dist/assets/index-CyROMh25.js +24 -0
- package/web/dist/assets/{mentions-S-r32HKM.js → mentions-BH0RZXfc.js} +1 -1
- package/web/dist/assets/{tasks-D_Fy7dtN.js → tasks-D2Es55TQ.js} +1 -1
- package/web/dist/assets/useMatch-DeOpK57G.js +1 -0
- package/web/dist/index.html +8 -8
- package/web/dist/assets/BackLink-BLiSCuKv.js +0 -1
- package/web/dist/assets/Button-D4-iu6aX.js +0 -1
- package/web/dist/assets/ChannelForms-DjviQfVm.js +0 -1
- package/web/dist/assets/ChannelView-B-0H7Ps8.js +0 -2
- package/web/dist/assets/CitizenView-gE5GgCBa.js +0 -2
- package/web/dist/assets/CronsView-CX_G5D3h.js +0 -1
- package/web/dist/assets/NeedsYouView-CE_B9bZQ.js +0 -1
- package/web/dist/assets/Overview-BGUnf6K1.js +0 -1
- package/web/dist/assets/ProposalView-BhZR4MIR.js +0 -1
- package/web/dist/assets/RunnersView-Bl62pXNw.js +0 -1
- package/web/dist/assets/SkillView-BQJApSh7.js +0 -1
- package/web/dist/assets/SocietyView-JSdVE50m.js +0 -1
- package/web/dist/assets/index-iplooQqq.js +0 -24
- package/web/dist/assets/useMatch-DZXCHHaG.js +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -370,6 +370,18 @@ function mergeQuota(previous, next) {
|
|
|
370
370
|
windows: [...windows.values()]
|
|
371
371
|
};
|
|
372
372
|
}
|
|
373
|
+
var UNKNOWN_LIMIT_HOLD_MS = 30 * 6e4;
|
|
374
|
+
function stopsTurns(quota) {
|
|
375
|
+
return quota.status === "limited" && !(quota.source === "read" && quota.extraUsage?.enabled === true);
|
|
376
|
+
}
|
|
377
|
+
function limitHold(quota, now) {
|
|
378
|
+
if (!stopsTurns(quota)) {
|
|
379
|
+
return null;
|
|
380
|
+
}
|
|
381
|
+
const known = quota.limitedUntil !== null;
|
|
382
|
+
const until = quota.limitedUntil ?? new Date(Date.parse(quota.observedAt) + UNKNOWN_LIMIT_HOLD_MS).toISOString();
|
|
383
|
+
return Date.parse(until) > now.getTime() ? { until, known } : null;
|
|
384
|
+
}
|
|
373
385
|
function readings(quota) {
|
|
374
386
|
const windows = quota.windows.map((window) => `${window.key}=${window.usedPercent === null ? "?" : Math.round(window.usedPercent)}@${window.resetsAt === null ? "?" : Math.round(Date.parse(window.resetsAt) / 6e4)}`).toSorted();
|
|
375
387
|
return windows.join(",");
|
|
@@ -699,12 +711,16 @@ var RunnerSchema = z5.object({
|
|
|
699
711
|
function runnerPause(runner2, cli) {
|
|
700
712
|
return runner2.paused ?? runner2.pausedClis?.[cli];
|
|
701
713
|
}
|
|
702
|
-
function
|
|
714
|
+
function runnerLimitHold(runner2, cli, now) {
|
|
715
|
+
const quota = runner2.quotas?.[cli];
|
|
716
|
+
return quota === void 0 ? null : limitHold(quota, now);
|
|
717
|
+
}
|
|
718
|
+
function heldOn(runners, runner2, cli, now) {
|
|
703
719
|
if (runner2 === void 0 || cli === null) {
|
|
704
720
|
return false;
|
|
705
721
|
}
|
|
706
722
|
const record = runners.find((each) => each.name === runner2);
|
|
707
|
-
return record !== void 0 && runnerPause(record, cli) !== void 0;
|
|
723
|
+
return record !== void 0 && (runnerPause(record, cli) !== void 0 || runnerLimitHold(record, cli, now) !== null);
|
|
708
724
|
}
|
|
709
725
|
var ProposalKindSchema = z5.enum([
|
|
710
726
|
"role",
|
|
@@ -2284,7 +2300,7 @@ var RunnerConfigSchema = z13.object({
|
|
|
2284
2300
|
});
|
|
2285
2301
|
|
|
2286
2302
|
// packages/shared/dist/version.js
|
|
2287
|
-
var STELLARIS_VERSION = "0.4.
|
|
2303
|
+
var STELLARIS_VERSION = "0.4.1";
|
|
2288
2304
|
|
|
2289
2305
|
// packages/shared/dist/mentions.js
|
|
2290
2306
|
import { parse, postprocess, preprocess } from "micromark";
|
|
@@ -3900,8 +3916,10 @@ function plain(value) {
|
|
|
3900
3916
|
return "";
|
|
3901
3917
|
return JSON.stringify(value);
|
|
3902
3918
|
}
|
|
3903
|
-
|
|
3904
|
-
|
|
3919
|
+
var SENTENCE_END = /[.…?!]["'”’»)\]}*_]*$/u;
|
|
3920
|
+
function asSentence(text) {
|
|
3921
|
+
const trimmed = text.trim();
|
|
3922
|
+
return SENTENCE_END.test(trimmed) ? trimmed : `${trimmed}.`;
|
|
3905
3923
|
}
|
|
3906
3924
|
function skillSummary(data, body) {
|
|
3907
3925
|
const description = data["description"];
|
|
@@ -5485,7 +5503,7 @@ ${current.body}`);
|
|
|
5485
5503
|
name: args.name,
|
|
5486
5504
|
reason: args.reason
|
|
5487
5505
|
});
|
|
5488
|
-
await this.appendMessage(SYSTEM_ACTOR.name, "general", `Skill ${args.name} removed from the society by ${actor.name}: ${
|
|
5506
|
+
await this.appendMessage(SYSTEM_ACTOR.name, "general", `Skill ${args.name} removed from the society by ${actor.name}: ${asSentence(withoutMentions(args.reason))} Every citizen's skills index stops listing it from its next turn.`);
|
|
5489
5507
|
return removed;
|
|
5490
5508
|
});
|
|
5491
5509
|
}
|
|
@@ -6555,7 +6573,7 @@ ${args.summary}`);
|
|
|
6555
6573
|
});
|
|
6556
6574
|
const thread2 = await this.openThreadUnlocked(actor.name, this.proposalThreadOpening(proposal2));
|
|
6557
6575
|
const rationale = args.rationale.trim();
|
|
6558
|
-
await this.appendThreadMessage(actor.name, thread2.id, `Proposal ${proposal2.id}: ${describeCharter(proposal2.kind, proposal2.charter)}
|
|
6576
|
+
await this.appendThreadMessage(actor.name, thread2.id, `Proposal ${proposal2.id}: ${asSentence(describeCharter(proposal2.kind, proposal2.charter))}${rationale.length === 0 ? "" : `
|
|
6559
6577
|
|
|
6560
6578
|
${rationale}`}`);
|
|
6561
6579
|
return proposal2;
|
|
@@ -7259,7 +7277,7 @@ ${rationale}`}`);
|
|
|
7259
7277
|
const ts = this.now().toISOString();
|
|
7260
7278
|
const landed = current.onDone !== "none";
|
|
7261
7279
|
if (landed) {
|
|
7262
|
-
await this.postTaskNote(actor.name, current, input.ok ?
|
|
7280
|
+
await this.postTaskNote(actor.name, current, input.ok ? asSentence(input.detail) : `Landing failed: ${asSentence(input.detail)} The task waits at its last stage for its participants to reshape the plan.`, input.ok ? { action: "landed", stage: current.stage, to: null } : { action: "reopened", stage: current.stage, to: current.stage });
|
|
7263
7281
|
}
|
|
7264
7282
|
if (input.ok) {
|
|
7265
7283
|
const task3 = await this.writeEndedTask(actor.name, location.project, {
|
|
@@ -7279,7 +7297,7 @@ ${rationale}`}`);
|
|
|
7279
7297
|
await this.refreshMember(name);
|
|
7280
7298
|
}
|
|
7281
7299
|
if (landed) {
|
|
7282
|
-
await this.appendMessage(actor.name, channelRef(location.project, task3.channel), `Task ${task3.id} "${task3.title}" is done: ${
|
|
7300
|
+
await this.appendMessage(actor.name, channelRef(location.project, task3.channel), `Task ${task3.id} "${task3.title}" is done: ${asSentence(input.detail)}`);
|
|
7283
7301
|
}
|
|
7284
7302
|
return task3;
|
|
7285
7303
|
}
|
|
@@ -7990,7 +8008,7 @@ Short, curated, loaded on every turn. Keep entries that change future behavior a
|
|
|
7990
8008
|
files: taken.files.length,
|
|
7991
8009
|
...meta
|
|
7992
8010
|
});
|
|
7993
|
-
await this.appendMessage(SYSTEM_ACTOR.name, "general", `Skill ${skill2.name} ${replaced ? "updated in" : "promoted to"} the society: ${
|
|
8011
|
+
await this.appendMessage(SYSTEM_ACTOR.name, "general", `Skill ${skill2.name} ${replaced ? "updated in" : "promoted to"} the society: ${asSentence(skill2.summary)} Every citizen's skills index now lists it.`);
|
|
7994
8012
|
return replaced;
|
|
7995
8013
|
}
|
|
7996
8014
|
/**
|
|
@@ -8237,7 +8255,7 @@ Short, curated, loaded on every turn. Keep entries that change future behavior a
|
|
|
8237
8255
|
});
|
|
8238
8256
|
const purpose = withoutMentions(input.purpose);
|
|
8239
8257
|
await this.appendMessage(SYSTEM_ACTOR.name, ref, `Channel ${ref} opened: ${purpose}`);
|
|
8240
|
-
await this.appendMessage(SYSTEM_ACTOR.name, channelRef(input.project, "general"), `Channel ${ref} opened by ${by}: ${purpose}
|
|
8258
|
+
await this.appendMessage(SYSTEM_ACTOR.name, channelRef(input.project, "general"), `Channel ${ref} opened by ${by}: ${asSentence(purpose)} Subscribe to it to follow its posts; its tasks and mentions reach whoever they concern either way.`);
|
|
8241
8259
|
return ref;
|
|
8242
8260
|
}
|
|
8243
8261
|
/**
|
|
@@ -8660,17 +8678,18 @@ ${charter.purpose}
|
|
|
8660
8678
|
return kept > lease ? new Date(kept).toISOString() : null;
|
|
8661
8679
|
}
|
|
8662
8680
|
/**
|
|
8663
|
-
* The lease a holder keeps while the user's pause holds its turns in the
|
|
8664
|
-
* (`heldOn`), when later than the one it has, else null. It is renewed for a full
|
|
8665
|
-
* than half is left, as for a pending cron, so it never lapses while the holder
|
|
8666
|
-
* turn there, and after the resume the holder has at least half a
|
|
8681
|
+
* The lease a holder keeps while the user's pause, or its CLI's limit, holds its turns in the
|
|
8682
|
+
* task's project (`heldOn`), when later than the one it has, else null. It is renewed for a full
|
|
8683
|
+
* lease once less than half is left, as for a pending cron, so it never lapses while the holder
|
|
8684
|
+
* cannot take a turn there, and after the resume or the reset the holder has at least half a
|
|
8685
|
+
* lease to come back to it.
|
|
8667
8686
|
*/
|
|
8668
8687
|
async pausedLease(task2, runners, runner2, now) {
|
|
8669
8688
|
if (task2.claimedBy === void 0 || task2.leaseExpiresAt === void 0) {
|
|
8670
8689
|
return null;
|
|
8671
8690
|
}
|
|
8672
8691
|
const holder = await this.readAgent(task2.claimedBy).catch(() => null);
|
|
8673
|
-
if (holder === null || !heldOn(runners, runner2, holder.cli)) {
|
|
8692
|
+
if (holder === null || !heldOn(runners, runner2, holder.cli, now)) {
|
|
8674
8693
|
return null;
|
|
8675
8694
|
}
|
|
8676
8695
|
const lease = Date.parse(task2.leaseExpiresAt);
|
|
@@ -8761,9 +8780,9 @@ ${charter.purpose}
|
|
|
8761
8780
|
});
|
|
8762
8781
|
}
|
|
8763
8782
|
const verdict = outcome === "approved" ? "Approved" : "Rejected";
|
|
8764
|
-
const why = reason === void 0 ? "" : ` Reason: ${reason}
|
|
8783
|
+
const why = reason === void 0 ? "" : ` Reason: ${asSentence(reason)}`;
|
|
8765
8784
|
const result = provision === void 0 ? "" : ` Provisioned: ${Object.entries(provision).map(([key, value]) => `${key} ${plain(value)}`).join(", ")}.`;
|
|
8766
|
-
const post = `${verdict}: ${describeCharter(proposal2.kind, proposal2.charter)}
|
|
8785
|
+
const post = `${verdict}: ${asSentence(describeCharter(proposal2.kind, proposal2.charter))}${why}${result}`;
|
|
8767
8786
|
await this.appendThreadMessage(actor.name, thread2.id, actor.name === SYSTEM_ACTOR.name ? withoutMentions(post) : post, { step: { action: outcome } });
|
|
8768
8787
|
await this.endThreadOf(proposalId, actor.name, outcome);
|
|
8769
8788
|
return decision;
|
|
@@ -9040,7 +9059,11 @@ runner.command("add <name>").description("Register a runner and print its token
|
|
|
9040
9059
|
runner.command("list").description("List runners and what they offer").action(async () => {
|
|
9041
9060
|
const board = await open3();
|
|
9042
9061
|
const runners = await board.listRunners();
|
|
9043
|
-
|
|
9062
|
+
const now = /* @__PURE__ */ new Date();
|
|
9063
|
+
print(runners, () => runners.length === 0 ? "No runners yet; add one with `runner add <name>`." : runners.map((each) => `${each.name} ${each.status}${each.paused === void 0 ? "" : " paused"} ${each.os}${each.version === void 0 ? "" : ` v${each.version}`} ${each.clis.join(",") || "no CLIs yet"}${each.capabilities.length === 0 ? "" : ` ${each.capabilities.join(",")}`}${Object.keys(each.pausedClis ?? {}).map((cli) => ` ${cli} paused`).join("")}${each.clis.map((cli) => {
|
|
9064
|
+
const hold = runnerLimitHold(each, cli, now);
|
|
9065
|
+
return hold === null ? "" : ` ${cli} held until ${hold.until}`;
|
|
9066
|
+
}).join("")}`).join("\n"));
|
|
9044
9067
|
});
|
|
9045
9068
|
for (const [verb, paused] of [
|
|
9046
9069
|
["pause", true],
|
package/dist/server/index.js
CHANGED
|
@@ -398,6 +398,21 @@ function quotaLevel(quota, now) {
|
|
|
398
398
|
const high = quota.windows.some((window) => windowCurrent(window, now) && window.usedPercent !== null && window.usedPercent >= QUOTA_WARNING_PERCENT);
|
|
399
399
|
return quota.status === "warning" || high ? "warning" : "ok";
|
|
400
400
|
}
|
|
401
|
+
var UNKNOWN_LIMIT_HOLD_MS = 30 * 6e4;
|
|
402
|
+
function stopsTurns(quota) {
|
|
403
|
+
return quota.status === "limited" && !(quota.source === "read" && quota.extraUsage?.enabled === true);
|
|
404
|
+
}
|
|
405
|
+
function limitHold(quota, now) {
|
|
406
|
+
if (!stopsTurns(quota)) {
|
|
407
|
+
return null;
|
|
408
|
+
}
|
|
409
|
+
const known = quota.limitedUntil !== null;
|
|
410
|
+
const until = quota.limitedUntil ?? new Date(Date.parse(quota.observedAt) + UNKNOWN_LIMIT_HOLD_MS).toISOString();
|
|
411
|
+
return Date.parse(until) > now.getTime() ? { until, known } : null;
|
|
412
|
+
}
|
|
413
|
+
function limitLapsed(quota, now) {
|
|
414
|
+
return stopsTurns(quota) && quota.limitedUntil === null && limitHold(quota, now) === null;
|
|
415
|
+
}
|
|
401
416
|
var WINDOW_NAMES = {
|
|
402
417
|
five_hour: "5h",
|
|
403
418
|
seven_day: "7d",
|
|
@@ -751,12 +766,16 @@ var RunnerSchema = z5.object({
|
|
|
751
766
|
function runnerPause(runner, cli) {
|
|
752
767
|
return runner.paused ?? runner.pausedClis?.[cli];
|
|
753
768
|
}
|
|
754
|
-
function
|
|
769
|
+
function runnerLimitHold(runner, cli, now) {
|
|
770
|
+
const quota = runner.quotas?.[cli];
|
|
771
|
+
return quota === void 0 ? null : limitHold(quota, now);
|
|
772
|
+
}
|
|
773
|
+
function heldOn(runners2, runner, cli, now) {
|
|
755
774
|
if (runner === void 0 || cli === null) {
|
|
756
775
|
return false;
|
|
757
776
|
}
|
|
758
777
|
const record = runners2.find((each) => each.name === runner);
|
|
759
|
-
return record !== void 0 && runnerPause(record, cli) !== void 0;
|
|
778
|
+
return record !== void 0 && (runnerPause(record, cli) !== void 0 || runnerLimitHold(record, cli, now) !== null);
|
|
760
779
|
}
|
|
761
780
|
var ProposalKindSchema = z5.enum([
|
|
762
781
|
"role",
|
|
@@ -2467,7 +2486,7 @@ var RunnerConfigSchema = z13.object({
|
|
|
2467
2486
|
});
|
|
2468
2487
|
|
|
2469
2488
|
// packages/shared/dist/version.js
|
|
2470
|
-
var STELLARIS_VERSION = "0.4.
|
|
2489
|
+
var STELLARIS_VERSION = "0.4.1";
|
|
2471
2490
|
|
|
2472
2491
|
// packages/shared/dist/mentions.js
|
|
2473
2492
|
import { parse, postprocess, preprocess } from "micromark";
|
|
@@ -4086,8 +4105,10 @@ function plain(value) {
|
|
|
4086
4105
|
return "";
|
|
4087
4106
|
return JSON.stringify(value);
|
|
4088
4107
|
}
|
|
4089
|
-
|
|
4090
|
-
|
|
4108
|
+
var SENTENCE_END = /[.…?!]["'”’»)\]}*_]*$/u;
|
|
4109
|
+
function asSentence(text) {
|
|
4110
|
+
const trimmed = text.trim();
|
|
4111
|
+
return SENTENCE_END.test(trimmed) ? trimmed : `${trimmed}.`;
|
|
4091
4112
|
}
|
|
4092
4113
|
function skillSummary(data, body) {
|
|
4093
4114
|
const description = data["description"];
|
|
@@ -5671,7 +5692,7 @@ ${current.body}`);
|
|
|
5671
5692
|
name: args.name,
|
|
5672
5693
|
reason: args.reason
|
|
5673
5694
|
});
|
|
5674
|
-
await this.appendMessage(SYSTEM_ACTOR.name, "general", `Skill ${args.name} removed from the society by ${actor.name}: ${
|
|
5695
|
+
await this.appendMessage(SYSTEM_ACTOR.name, "general", `Skill ${args.name} removed from the society by ${actor.name}: ${asSentence(withoutMentions(args.reason))} Every citizen's skills index stops listing it from its next turn.`);
|
|
5675
5696
|
return removed;
|
|
5676
5697
|
});
|
|
5677
5698
|
}
|
|
@@ -6741,7 +6762,7 @@ ${args.summary}`);
|
|
|
6741
6762
|
});
|
|
6742
6763
|
const thread = await this.openThreadUnlocked(actor.name, this.proposalThreadOpening(proposal));
|
|
6743
6764
|
const rationale = args.rationale.trim();
|
|
6744
|
-
await this.appendThreadMessage(actor.name, thread.id, `Proposal ${proposal.id}: ${describeCharter(proposal.kind, proposal.charter)}
|
|
6765
|
+
await this.appendThreadMessage(actor.name, thread.id, `Proposal ${proposal.id}: ${asSentence(describeCharter(proposal.kind, proposal.charter))}${rationale.length === 0 ? "" : `
|
|
6745
6766
|
|
|
6746
6767
|
${rationale}`}`);
|
|
6747
6768
|
return proposal;
|
|
@@ -7445,7 +7466,7 @@ ${rationale}`}`);
|
|
|
7445
7466
|
const ts = this.now().toISOString();
|
|
7446
7467
|
const landed = current.onDone !== "none";
|
|
7447
7468
|
if (landed) {
|
|
7448
|
-
await this.postTaskNote(actor.name, current, input.ok ?
|
|
7469
|
+
await this.postTaskNote(actor.name, current, input.ok ? asSentence(input.detail) : `Landing failed: ${asSentence(input.detail)} The task waits at its last stage for its participants to reshape the plan.`, input.ok ? { action: "landed", stage: current.stage, to: null } : { action: "reopened", stage: current.stage, to: current.stage });
|
|
7449
7470
|
}
|
|
7450
7471
|
if (input.ok) {
|
|
7451
7472
|
const task2 = await this.writeEndedTask(actor.name, location.project, {
|
|
@@ -7465,7 +7486,7 @@ ${rationale}`}`);
|
|
|
7465
7486
|
await this.refreshMember(name);
|
|
7466
7487
|
}
|
|
7467
7488
|
if (landed) {
|
|
7468
|
-
await this.appendMessage(actor.name, channelRef(location.project, task2.channel), `Task ${task2.id} "${task2.title}" is done: ${
|
|
7489
|
+
await this.appendMessage(actor.name, channelRef(location.project, task2.channel), `Task ${task2.id} "${task2.title}" is done: ${asSentence(input.detail)}`);
|
|
7469
7490
|
}
|
|
7470
7491
|
return task2;
|
|
7471
7492
|
}
|
|
@@ -8176,7 +8197,7 @@ Short, curated, loaded on every turn. Keep entries that change future behavior a
|
|
|
8176
8197
|
files: taken.files.length,
|
|
8177
8198
|
...meta
|
|
8178
8199
|
});
|
|
8179
|
-
await this.appendMessage(SYSTEM_ACTOR.name, "general", `Skill ${skill.name} ${replaced ? "updated in" : "promoted to"} the society: ${
|
|
8200
|
+
await this.appendMessage(SYSTEM_ACTOR.name, "general", `Skill ${skill.name} ${replaced ? "updated in" : "promoted to"} the society: ${asSentence(skill.summary)} Every citizen's skills index now lists it.`);
|
|
8180
8201
|
return replaced;
|
|
8181
8202
|
}
|
|
8182
8203
|
/**
|
|
@@ -8423,7 +8444,7 @@ Short, curated, loaded on every turn. Keep entries that change future behavior a
|
|
|
8423
8444
|
});
|
|
8424
8445
|
const purpose = withoutMentions(input.purpose);
|
|
8425
8446
|
await this.appendMessage(SYSTEM_ACTOR.name, ref, `Channel ${ref} opened: ${purpose}`);
|
|
8426
|
-
await this.appendMessage(SYSTEM_ACTOR.name, channelRef(input.project, "general"), `Channel ${ref} opened by ${by}: ${purpose}
|
|
8447
|
+
await this.appendMessage(SYSTEM_ACTOR.name, channelRef(input.project, "general"), `Channel ${ref} opened by ${by}: ${asSentence(purpose)} Subscribe to it to follow its posts; its tasks and mentions reach whoever they concern either way.`);
|
|
8427
8448
|
return ref;
|
|
8428
8449
|
}
|
|
8429
8450
|
/**
|
|
@@ -8846,17 +8867,18 @@ ${charter.purpose}
|
|
|
8846
8867
|
return kept > lease ? new Date(kept).toISOString() : null;
|
|
8847
8868
|
}
|
|
8848
8869
|
/**
|
|
8849
|
-
* The lease a holder keeps while the user's pause holds its turns in the
|
|
8850
|
-
* (`heldOn`), when later than the one it has, else null. It is renewed for a full
|
|
8851
|
-
* than half is left, as for a pending cron, so it never lapses while the holder
|
|
8852
|
-
* turn there, and after the resume the holder has at least half a
|
|
8870
|
+
* The lease a holder keeps while the user's pause, or its CLI's limit, holds its turns in the
|
|
8871
|
+
* task's project (`heldOn`), when later than the one it has, else null. It is renewed for a full
|
|
8872
|
+
* lease once less than half is left, as for a pending cron, so it never lapses while the holder
|
|
8873
|
+
* cannot take a turn there, and after the resume or the reset the holder has at least half a
|
|
8874
|
+
* lease to come back to it.
|
|
8853
8875
|
*/
|
|
8854
8876
|
async pausedLease(task, runners2, runner, now) {
|
|
8855
8877
|
if (task.claimedBy === void 0 || task.leaseExpiresAt === void 0) {
|
|
8856
8878
|
return null;
|
|
8857
8879
|
}
|
|
8858
8880
|
const holder = await this.readAgent(task.claimedBy).catch(() => null);
|
|
8859
|
-
if (holder === null || !heldOn(runners2, runner, holder.cli)) {
|
|
8881
|
+
if (holder === null || !heldOn(runners2, runner, holder.cli, now)) {
|
|
8860
8882
|
return null;
|
|
8861
8883
|
}
|
|
8862
8884
|
const lease = Date.parse(task.leaseExpiresAt);
|
|
@@ -8947,9 +8969,9 @@ ${charter.purpose}
|
|
|
8947
8969
|
});
|
|
8948
8970
|
}
|
|
8949
8971
|
const verdict = outcome === "approved" ? "Approved" : "Rejected";
|
|
8950
|
-
const why = reason === void 0 ? "" : ` Reason: ${reason}
|
|
8972
|
+
const why = reason === void 0 ? "" : ` Reason: ${asSentence(reason)}`;
|
|
8951
8973
|
const result = provision === void 0 ? "" : ` Provisioned: ${Object.entries(provision).map(([key, value]) => `${key} ${plain(value)}`).join(", ")}.`;
|
|
8952
|
-
const post = `${verdict}: ${describeCharter(proposal.kind, proposal.charter)}
|
|
8974
|
+
const post = `${verdict}: ${asSentence(describeCharter(proposal.kind, proposal.charter))}${why}${result}`;
|
|
8953
8975
|
await this.appendThreadMessage(actor.name, thread.id, actor.name === SYSTEM_ACTOR.name ? withoutMentions(post) : post, { step: { action: outcome } });
|
|
8954
8976
|
await this.endThreadOf(proposalId, actor.name, outcome);
|
|
8955
8977
|
return decision;
|
|
@@ -10501,7 +10523,7 @@ var Scheduler = class {
|
|
|
10501
10523
|
}
|
|
10502
10524
|
members ??= await this.board.projectMembers(project.slug);
|
|
10503
10525
|
const takers = members.filter((member) => member.cli !== null && mayHoldStage(member, task));
|
|
10504
|
-
if (takers.length > 0 && takers.every((taker) => heldOn(runners2, project.runner, taker.cli))) {
|
|
10526
|
+
if (takers.length > 0 && takers.every((taker) => heldOn(runners2, project.runner, taker.cli, new Date(now)))) {
|
|
10505
10527
|
this.state.waitingHeld[key] = iso(now);
|
|
10506
10528
|
continue;
|
|
10507
10529
|
}
|
|
@@ -10708,7 +10730,8 @@ var Scheduler = class {
|
|
|
10708
10730
|
last = Math.max(last, Date.parse(ended));
|
|
10709
10731
|
}
|
|
10710
10732
|
}
|
|
10711
|
-
const
|
|
10733
|
+
const at = new Date(now);
|
|
10734
|
+
const held = heldOn(runners2, agent.homeRunner, agent.cli, at) || projects.some((project) => agent.memberships.includes(project.slug) && heldOn(runners2, project.runner, agent.cli, at));
|
|
10712
10735
|
if (held) {
|
|
10713
10736
|
this.state.idleHeld[agent.name] = iso(now);
|
|
10714
10737
|
}
|
|
@@ -11227,7 +11250,11 @@ function runnerLine(runner, projects, now) {
|
|
|
11227
11250
|
].join(", ");
|
|
11228
11251
|
const pauses = runner.clis.flatMap((cli) => {
|
|
11229
11252
|
const pause = runner.pausedClis?.[cli];
|
|
11230
|
-
|
|
11253
|
+
const hold = runnerLimitHold(runner, cli, now);
|
|
11254
|
+
return [
|
|
11255
|
+
...pause === void 0 ? [] : [`${cli} paused by the user since ${pause.at}`],
|
|
11256
|
+
...hold === null ? [] : [`${cli} held by its limit until ${hold.until}`]
|
|
11257
|
+
];
|
|
11231
11258
|
});
|
|
11232
11259
|
const quotas = runner.clis.flatMap((cli) => {
|
|
11233
11260
|
const quota = runner.quotas?.[cli];
|
|
@@ -11400,7 +11427,7 @@ function buildTurnPrompt(input) {
|
|
|
11400
11427
|
}
|
|
11401
11428
|
const machines = input.runners;
|
|
11402
11429
|
if (machines !== void 0 && machines !== null) {
|
|
11403
|
-
lines.push("", "## Runners", "", "The machines turns run on. A project lives on the runner that takes its first turn, one that offers every capability the project and that turn's task require, and moves only when the user moves it. A task's required_capabilities must name capabilities exactly as a runner below offers them; a task needing one its project's runner lacks waits. A runner's quota is what each CLI's login there last reported of its plan, in percent of each window
|
|
11430
|
+
lines.push("", "## Runners", "", "The machines turns run on. A project lives on the runner that takes its first turn, one that offers every capability the project and that turn's task require, and moves only when the user moves it. A task's required_capabilities must name capabilities exactly as a runner below offers them; a task needing one its project's runner lacks waits. A runner's quota is what each CLI's login there last reported of its plan, in percent of each window. A runner, or a CLI on it, paused by the user starts none of the turns it would run until the user resumes it, and a CLI held by its limit starts none of its turns there until the limit lifts, at the reset the CLI gave or, with none given, half an hour after the report: they wait, and the stages their citizens hold keep their leases.", "");
|
|
11404
11431
|
if (machines.runners.length === 0) {
|
|
11405
11432
|
lines.push("None registered yet.");
|
|
11406
11433
|
}
|
|
@@ -12297,6 +12324,9 @@ var TurnHost = class {
|
|
|
12297
12324
|
|
|
12298
12325
|
// packages/turn-host/dist/hub.js
|
|
12299
12326
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
12327
|
+
function receiptOverdue(seat) {
|
|
12328
|
+
return [...seat.unacked.values()].some((each) => each.overdue);
|
|
12329
|
+
}
|
|
12300
12330
|
var RunnerProtocolError = class extends Error {
|
|
12301
12331
|
};
|
|
12302
12332
|
var RunnerAwayError = class extends Error {
|
|
@@ -12341,6 +12371,13 @@ var RunnerHub = class {
|
|
|
12341
12371
|
starting = /* @__PURE__ */ new Map();
|
|
12342
12372
|
/** Moves started since the hub did, so a placement that a move overtook gives its turn back. */
|
|
12343
12373
|
moveStarts = 0;
|
|
12374
|
+
/** When each runner was last asked to read a CLI's quota for a limit with no reset, by `runner/cli`. */
|
|
12375
|
+
limitReads = /* @__PURE__ */ new Map();
|
|
12376
|
+
/**
|
|
12377
|
+
* The turn let through once a limit with no reset had held its half hour, by `runner/cli`: the
|
|
12378
|
+
* report it tries, which `observedAt` names, and whether the turn has ended.
|
|
12379
|
+
*/
|
|
12380
|
+
limitTries = /* @__PURE__ */ new Map();
|
|
12344
12381
|
constructor(options) {
|
|
12345
12382
|
this.board = options.board;
|
|
12346
12383
|
this.host = options.host;
|
|
@@ -12377,9 +12414,9 @@ var RunnerHub = class {
|
|
|
12377
12414
|
if (hello.protocol !== RUNNER_PROTOCOL) {
|
|
12378
12415
|
throw new RunnerProtocolError(`runner protocol ${hello.protocol} is not ${RUNNER_PROTOCOL}; upgrade the runner or the server`);
|
|
12379
12416
|
}
|
|
12380
|
-
|
|
12417
|
+
let seat = this.seats.get(name);
|
|
12381
12418
|
if (seat === void 0) {
|
|
12382
|
-
|
|
12419
|
+
seat = {
|
|
12383
12420
|
name,
|
|
12384
12421
|
hello,
|
|
12385
12422
|
send: null,
|
|
@@ -12387,19 +12424,18 @@ var RunnerHub = class {
|
|
|
12387
12424
|
warm: /* @__PURE__ */ new Set(),
|
|
12388
12425
|
disconnectedAt: null,
|
|
12389
12426
|
grace: null,
|
|
12390
|
-
unacked: /* @__PURE__ */ new Map()
|
|
12391
|
-
|
|
12392
|
-
|
|
12427
|
+
unacked: /* @__PURE__ */ new Map()
|
|
12428
|
+
};
|
|
12429
|
+
this.seats.set(name, seat);
|
|
12393
12430
|
} else {
|
|
12394
12431
|
seat.hello = hello;
|
|
12395
12432
|
seat.warm = /* @__PURE__ */ new Set();
|
|
12396
12433
|
}
|
|
12397
12434
|
const still = new Set(hello.turns);
|
|
12398
|
-
const unacked = this.seats.get(name)?.unacked ?? /* @__PURE__ */ new Map();
|
|
12399
12435
|
for (const turnId of this.host.turnsOn(name)) {
|
|
12400
12436
|
if (still.has(turnId)) {
|
|
12401
|
-
this.settle(
|
|
12402
|
-
} else if (!unacked.has(turnId)) {
|
|
12437
|
+
this.settle(seat, turnId);
|
|
12438
|
+
} else if (!seat.unacked.has(turnId)) {
|
|
12403
12439
|
await this.host.abortTurn(turnId, `runner ${name} restarted during the turn`);
|
|
12404
12440
|
}
|
|
12405
12441
|
}
|
|
@@ -12422,7 +12458,6 @@ var RunnerHub = class {
|
|
|
12422
12458
|
}
|
|
12423
12459
|
seat.send = send;
|
|
12424
12460
|
seat.disconnectedAt = null;
|
|
12425
|
-
seat.unconfirmed = false;
|
|
12426
12461
|
if (seat.grace !== null) {
|
|
12427
12462
|
clearTimeout(seat.grace);
|
|
12428
12463
|
seat.grace = null;
|
|
@@ -12463,24 +12498,23 @@ var RunnerHub = class {
|
|
|
12463
12498
|
}
|
|
12464
12499
|
await Promise.allSettled(this.detaching);
|
|
12465
12500
|
}
|
|
12501
|
+
/** A turn's steps, which show its job arrived as its receipt would. */
|
|
12466
12502
|
async turnEvents(runner, turnId, entries) {
|
|
12467
12503
|
this.assertOwns(runner, turnId);
|
|
12504
|
+
this.received(runner, turnId);
|
|
12468
12505
|
await this.host.addEvents(turnId, entries);
|
|
12469
12506
|
}
|
|
12470
12507
|
/** A runner's word that a turn's job arrived, which also shows its stream delivers again. */
|
|
12471
12508
|
received(runner, turnId) {
|
|
12472
12509
|
const seat = this.seats.get(runner);
|
|
12473
|
-
if (seat
|
|
12474
|
-
|
|
12475
|
-
}
|
|
12476
|
-
this.settle(seat.unacked, turnId);
|
|
12477
|
-
if (seat.unconfirmed) {
|
|
12478
|
-
seat.unconfirmed = false;
|
|
12479
|
-
this.log.info({ runner }, "runner is taking jobs again");
|
|
12510
|
+
if (seat !== void 0) {
|
|
12511
|
+
this.settle(seat, turnId);
|
|
12480
12512
|
}
|
|
12481
12513
|
}
|
|
12514
|
+
/** A turn's outcome, which shows its job arrived as its receipt would. */
|
|
12482
12515
|
async turnOutcome(runner, turnId, outcome) {
|
|
12483
12516
|
this.assertOwns(runner, turnId);
|
|
12517
|
+
this.received(runner, turnId);
|
|
12484
12518
|
const ack = await this.host.closeTurn(turnId, outcome);
|
|
12485
12519
|
return ack ?? { dropWorkspace: false };
|
|
12486
12520
|
}
|
|
@@ -12625,8 +12659,10 @@ var RunnerHub = class {
|
|
|
12625
12659
|
}
|
|
12626
12660
|
const cli = agent.cli;
|
|
12627
12661
|
const runners2 = await this.board.listRunners();
|
|
12628
|
-
const
|
|
12662
|
+
const now = this.now();
|
|
12663
|
+
const free = (seat) => seat.send !== null && !receiptOverdue(seat) && seat.hello.clis.includes(cli) && (seat.hello.slots === null || seat.inUse < seat.hello.slots) && !heldOn(runners2, seat.name, cli, now) && !this.tryRunning(runners2, seat.name, cli, now);
|
|
12629
12664
|
let chosen;
|
|
12665
|
+
let waitsOn = agent.homeRunner;
|
|
12630
12666
|
if (dispatch.project === SOCIETY_SCOPE) {
|
|
12631
12667
|
chosen = await this.pinnedSeat(agent.name, agent.homeRunner, cli, free);
|
|
12632
12668
|
} else {
|
|
@@ -12655,8 +12691,12 @@ var RunnerHub = class {
|
|
|
12655
12691
|
}
|
|
12656
12692
|
const seat = this.seats.get(home);
|
|
12657
12693
|
chosen = seat !== void 0 && free(seat) ? seat : void 0;
|
|
12694
|
+
waitsOn = home;
|
|
12658
12695
|
}
|
|
12659
12696
|
if (chosen === void 0) {
|
|
12697
|
+
if (waitsOn !== void 0) {
|
|
12698
|
+
this.readAfterLimit(runners2, waitsOn, cli, now);
|
|
12699
|
+
}
|
|
12660
12700
|
return null;
|
|
12661
12701
|
}
|
|
12662
12702
|
if (dispatch.project !== SOCIETY_SCOPE && (this.moving.has(dispatch.project) || this.moveStarts !== starts)) {
|
|
@@ -12666,7 +12706,17 @@ var RunnerHub = class {
|
|
|
12666
12706
|
if (dispatch.project !== SOCIETY_SCOPE) {
|
|
12667
12707
|
this.starting.set(dispatch.project, (this.starting.get(dispatch.project) ?? 0) + 1);
|
|
12668
12708
|
}
|
|
12669
|
-
|
|
12709
|
+
const runner = chosen.name;
|
|
12710
|
+
const lapsed = runners2.find((each) => each.name === runner)?.quotas?.[cli];
|
|
12711
|
+
const tried = this.limitTries.get(`${runner}/${cli}`);
|
|
12712
|
+
if (lapsed !== void 0 && limitLapsed(lapsed, now) && tried?.observedAt !== lapsed.observedAt) {
|
|
12713
|
+
this.limitTries.set(`${runner}/${cli}`, {
|
|
12714
|
+
observedAt: lapsed.observedAt,
|
|
12715
|
+
dispatch,
|
|
12716
|
+
ended: false
|
|
12717
|
+
});
|
|
12718
|
+
}
|
|
12719
|
+
return { runner };
|
|
12670
12720
|
}
|
|
12671
12721
|
async runTurn(dispatch, assignment) {
|
|
12672
12722
|
if ("refused" in assignment) {
|
|
@@ -12703,10 +12753,15 @@ var RunnerHub = class {
|
|
|
12703
12753
|
return await opened.ended;
|
|
12704
12754
|
} finally {
|
|
12705
12755
|
opening();
|
|
12756
|
+
for (const tried of this.limitTries.values()) {
|
|
12757
|
+
if (tried.dispatch === dispatch) {
|
|
12758
|
+
tried.ended = true;
|
|
12759
|
+
}
|
|
12760
|
+
}
|
|
12706
12761
|
if (seat !== void 0) {
|
|
12707
12762
|
seat.inUse = Math.max(0, seat.inUse - 1);
|
|
12708
12763
|
if (turnId !== null) {
|
|
12709
|
-
this.settle(seat
|
|
12764
|
+
this.settle(seat, turnId);
|
|
12710
12765
|
}
|
|
12711
12766
|
}
|
|
12712
12767
|
}
|
|
@@ -13096,6 +13151,40 @@ var RunnerHub = class {
|
|
|
13096
13151
|
await this.board.recordQuota(runner, cli, quota);
|
|
13097
13152
|
return quota;
|
|
13098
13153
|
}
|
|
13154
|
+
/**
|
|
13155
|
+
* Whether a turn let through to try a limit with no reset, once its hold ran out, is still running
|
|
13156
|
+
* on the runner, so the CLI's other turns there wait for what it reports: a refusal records a newer
|
|
13157
|
+
* limit, which holds them another half hour, and a turn that ends without one lets them go.
|
|
13158
|
+
*/
|
|
13159
|
+
tryRunning(runners2, name, cli, now) {
|
|
13160
|
+
const quota = runners2.find((each) => each.name === name)?.quotas?.[cli];
|
|
13161
|
+
const tried = this.limitTries.get(`${name}/${cli}`);
|
|
13162
|
+
return quota !== void 0 && tried !== void 0 && !tried.ended && tried.observedAt === quota.observedAt && limitLapsed(quota, now);
|
|
13163
|
+
}
|
|
13164
|
+
/**
|
|
13165
|
+
* Asks a runner to read a CLI's quota again while a limit it gave no reset for holds a turn
|
|
13166
|
+
* waiting for it there, at most once per `UNKNOWN_LIMIT_HOLD_MS` for each runner and CLI, so a
|
|
13167
|
+
* reset the read names becomes the hold and a clear read lifts it. Not while the user's pause
|
|
13168
|
+
* holds the CLI there too, nor on a runner from before quota reads; a read that fails changes
|
|
13169
|
+
* nothing, and the hold runs out as it would have.
|
|
13170
|
+
*/
|
|
13171
|
+
readAfterLimit(runners2, name, cli, now) {
|
|
13172
|
+
const record = runners2.find((each) => each.name === name);
|
|
13173
|
+
const seat = this.seats.get(name);
|
|
13174
|
+
if (record === void 0 || seat === void 0 || seat.send === null || !seat.hello.quotaReads || !seat.hello.clis.includes(cli) || runnerPause(record, cli) !== void 0 || runnerLimitHold(record, cli, now)?.known !== false) {
|
|
13175
|
+
return;
|
|
13176
|
+
}
|
|
13177
|
+
const key = `${name}/${cli}`;
|
|
13178
|
+
const last = this.limitReads.get(key);
|
|
13179
|
+
if (last !== void 0 && now.getTime() - last < UNKNOWN_LIMIT_HOLD_MS) {
|
|
13180
|
+
return;
|
|
13181
|
+
}
|
|
13182
|
+
this.limitReads.set(key, now.getTime());
|
|
13183
|
+
this.log.info({ runner: name, cli }, "reading a quota limited until an unknown time");
|
|
13184
|
+
this.quota(name, cli).catch((error) => {
|
|
13185
|
+
this.log.warn({ runner: name, cli, error: String(error) }, "could not read a limited quota");
|
|
13186
|
+
});
|
|
13187
|
+
}
|
|
13099
13188
|
/** Calls `listener` whenever a runner registers, connects, or goes away. */
|
|
13100
13189
|
onRunnerChange(listener) {
|
|
13101
13190
|
this.runnerListeners.add(listener);
|
|
@@ -13109,29 +13198,41 @@ var RunnerHub = class {
|
|
|
13109
13198
|
/**
|
|
13110
13199
|
* Waits for a runner to acknowledge a job. One that does not in time may be behind a stream that
|
|
13111
13200
|
* looks open but delivers nothing, as when its machine's network stops passing traffic, so no
|
|
13112
|
-
* more turns go to it until
|
|
13113
|
-
* they report by posts.
|
|
13201
|
+
* more turns go to it until the job is acknowledged, its turn ends, or the runner connects again;
|
|
13202
|
+
* the turns it has carry on, since they report by posts.
|
|
13114
13203
|
*/
|
|
13115
13204
|
expectAck(seat, job) {
|
|
13116
13205
|
const previous = seat.unacked.get(job.turnId);
|
|
13117
13206
|
if (previous !== void 0) {
|
|
13118
13207
|
clearTimeout(previous.timer);
|
|
13119
13208
|
}
|
|
13120
|
-
const
|
|
13121
|
-
|
|
13122
|
-
|
|
13123
|
-
|
|
13124
|
-
|
|
13125
|
-
|
|
13126
|
-
|
|
13127
|
-
|
|
13128
|
-
|
|
13129
|
-
|
|
13130
|
-
|
|
13131
|
-
|
|
13132
|
-
|
|
13133
|
-
|
|
13134
|
-
|
|
13209
|
+
const entry = {
|
|
13210
|
+
job,
|
|
13211
|
+
timer: setTimeout(() => {
|
|
13212
|
+
if (seat.unacked.get(job.turnId) !== entry || seat.send === null) {
|
|
13213
|
+
return;
|
|
13214
|
+
}
|
|
13215
|
+
const wasHeld = receiptOverdue(seat);
|
|
13216
|
+
entry.overdue = true;
|
|
13217
|
+
if (!wasHeld) {
|
|
13218
|
+
this.log.warn({ runner: seat.name, turnId: job.turnId, waitedMs: this.ackTimeoutMs }, "runner has not acknowledged a job; no more turns go to it until it does, the turn ends, or it reconnects");
|
|
13219
|
+
}
|
|
13220
|
+
}, this.ackTimeoutMs),
|
|
13221
|
+
overdue: false
|
|
13222
|
+
};
|
|
13223
|
+
entry.timer.unref?.();
|
|
13224
|
+
seat.unacked.set(job.turnId, entry);
|
|
13225
|
+
}
|
|
13226
|
+
/** A job acknowledged, or its turn over: the hold it put on its runner, if any, goes with it. */
|
|
13227
|
+
settle(seat, turnId) {
|
|
13228
|
+
const entry = seat.unacked.get(turnId);
|
|
13229
|
+
if (entry === void 0) {
|
|
13230
|
+
return;
|
|
13231
|
+
}
|
|
13232
|
+
clearTimeout(entry.timer);
|
|
13233
|
+
seat.unacked.delete(turnId);
|
|
13234
|
+
if (entry.overdue && !receiptOverdue(seat)) {
|
|
13235
|
+
this.log.info({ runner: seat.name }, "runner is taking jobs again");
|
|
13135
13236
|
}
|
|
13136
13237
|
}
|
|
13137
13238
|
async detach(seat) {
|
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Jn as e,S as t,tn as n}from"./format-BYF63sQU.js";import{O as r,n as i,r as a,t as o,v as s}from"./index-CyROMh25.js";var c=e(),l=`grid size-7 shrink-0 place-items-center rounded-lg text-fg-tertiary hover:bg-surface-2/70 hover:text-fg-primary`;function u({fallback:e}){let u=n(),d=r({select:e=>e.location.state.__TSR_index}),f=a(),p=s(),m=t(),h=i(f,d);if(h===null)return e;let g=o(h,{entity:e=>p.get(e)?.title,project:e=>m.data?.find(t=>t.slug===e)?.name});return(0,c.jsx)(`button`,{type:`button`,onClick:()=>u.history.back(),"aria-label":`Back to ${g}`,title:`Back to ${g}`,className:l,children:`←`})}export{u as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{An as e,Bn as t,In as n,Jn as r,Mn as i,Pn as a,Qn as o,Un as s,Wn as c,Yn as l,kn as u,qn as d}from"./format-BYF63sQU.js";var f=class extends u{#e;#t;#n;#r;constructor(e){super(),this.#e=e.client,this.mutationId=e.mutationId,this.#n=e.mutationCache,this.#t=[],this.state=e.state||p(),this.setOptions(e.options),this.scheduleGc()}setOptions(e){this.options=e,this.updateGcTime(this.options.gcTime)}get meta(){return this.options.meta}addObserver(e){this.#t.includes(e)||(this.#t.push(e),this.clearGcTimeout(),this.#n.notify({type:`observerAdded`,mutation:this,observer:e}))}removeObserver(e){this.#t=this.#t.filter(t=>t!==e),this.scheduleGc(),this.#n.notify({type:`observerRemoved`,mutation:this,observer:e})}optionalRemove(){this.#t.length||(this.state.status===`pending`?this.scheduleGc():this.#n.remove(this))}continue(){return this.#r?.continue()??(this.state.status===`pending`?this.execute(this.state.variables):Promise.resolve())}async execute(t){let n=()=>{this.#i({type:`continue`})},r={client:this.#e,meta:this.options.meta,mutationKey:this.options.mutationKey},i=this.#r=e({fn:()=>this.options.mutationFn?this.options.mutationFn(t,r):Promise.reject(Error(`No mutationFn found`)),onFail:(e,t)=>{this.#i({type:`failed`,failureCount:e,error:t})},onPause:()=>{this.#i({type:`pause`})},onContinue:n,retry:this.options.retry??0,retryDelay:this.options.retryDelay,networkMode:this.options.networkMode,canRun:()=>this.#n.canRun(this)}),a=this.state.status===`pending`,o=!i.canStart();try{if(a)n();else{this.#i({type:`pending`,variables:t,isPaused:o}),this.#n.config.onMutate&&await this.#n.config.onMutate(t,this,r);let e=await this.options.onMutate?.(t,r);e!==this.state.context&&this.#i({type:`pending`,context:e,variables:t,isPaused:o})}let e=await i.start();return await this.#n.config.onSuccess?.(e,t,this.state.context,this,r),await this.options.onSuccess?.(e,t,this.state.context,r),await this.#n.config.onSettled?.(e,null,this.state.variables,this.state.context,this,r),await this.options.onSettled?.(e,null,t,this.state.context,r),this.#i({type:`success`,data:e}),e}catch(e){try{await this.#n.config.onError?.(e,t,this.state.context,this,r)}catch(e){Promise.reject(e)}try{await this.options.onError?.(e,t,this.state.context,r)}catch(e){Promise.reject(e)}try{await this.#n.config.onSettled?.(void 0,e,this.state.variables,this.state.context,this,r)}catch(e){Promise.reject(e)}try{await this.options.onSettled?.(void 0,e,t,this.state.context,r)}catch(e){Promise.reject(e)}throw this.#i({type:`error`,error:e}),e}finally{this.#r===i&&(this.#r=void 0),this.#n.runNext(this)}}#i(e){let t=t=>{switch(e.type){case`failed`:return{...t,failureCount:e.failureCount,failureReason:e.error};case`pause`:return{...t,isPaused:!0};case`continue`:return{...t,isPaused:!1};case`pending`:return{...t,context:e.context,data:void 0,failureCount:0,failureReason:null,error:null,isPaused:e.isPaused,status:`pending`,variables:e.variables,submittedAt:Date.now()};case`success`:return{...t,data:e.data,failureCount:0,failureReason:null,error:null,status:`success`,isPaused:!1};case`error`:return{...t,data:void 0,error:e.error,failureCount:t.failureCount+1,failureReason:e.error,isPaused:!1,status:`error`}}};this.state=t(this.state),i.batch(()=>{this.#t.forEach(t=>{t.onMutationUpdate(e)}),this.#n.notify({mutation:this,type:`updated`,action:e})})}};function p(){return{context:void 0,data:void 0,error:null,failureCount:0,failureReason:null,isPaused:!1,status:`idle`,variables:void 0,submittedAt:0}}var m=class extends a{#e;#t=void 0;#n;#r;constructor(e,t){super(),this.#e=e,this.setOptions(t),this.bindMethods(),this.#i()}bindMethods(){this.mutate=this.mutate.bind(this),this.reset=this.reset.bind(this)}setOptions(e){let t=this.options;this.options=this.#e.defaultMutationOptions(e),s(this.options,t)||this.#e.getMutationCache().notify({type:`observerOptionsUpdated`,mutation:this.#n,observer:this}),t?.mutationKey&&this.options.mutationKey&&n(t.mutationKey)!==n(this.options.mutationKey)?this.reset():this.#n?.state.status===`pending`&&this.#n.setOptions(this.options)}onSubscribe(){this.listeners.size===1&&this.#n&&(this.#n.addObserver(this),this.#i())}onUnsubscribe(){this.hasListeners()||this.#n?.removeObserver(this)}onMutationUpdate(e){this.#i(),this.#a(e)}getCurrentResult(){return this.#t}reset(){this.#n?.removeObserver(this),this.#n=void 0,this.#i(),this.#a()}mutate(e,t){return this.#r=t,this.#n?.removeObserver(this),this.#n=this.#e.getMutationCache().build(this.#e,this.options),this.#n.addObserver(this),this.#n.execute(e)}#i(){let e=this.#n?.state??p();this.#t={...e,isPending:e.status===`pending`,isSuccess:e.status===`success`,isError:e.status===`error`,isIdle:e.status===`idle`,mutate:this.mutate,reset:this.reset}}#a(e){i.batch(()=>{if(this.#r&&this.hasListeners()){let t=this.#t.variables,n=this.#t.context,r={client:this.#e,meta:this.options.meta,mutationKey:this.options.mutationKey};if(e?.type===`success`){try{this.#r.onSuccess?.(e.data,t,n,r)}catch(e){Promise.reject(e)}try{this.#r.onSettled?.(e.data,null,t,n,r)}catch(e){Promise.reject(e)}}else if(e?.type===`error`){try{this.#r.onError?.(e.error,t,n,r)}catch(e){Promise.reject(e)}try{this.#r.onSettled?.(void 0,e.error,t,n,r)}catch(e){Promise.reject(e)}}}this.listeners.forEach(e=>{e(this.#t)})})}},h=o(l(),1);function g(e,n){let r=d(n),[a]=h.useState(()=>new m(r,e));h.useEffect(()=>{a.setOptions(e)},[a,e]);let o=h.useSyncExternalStore(h.useCallback(e=>a.subscribe(i.batchCalls(e)),[a]),()=>a.getCurrentResult(),()=>a.getCurrentResult()),s=h.useCallback((...e)=>{a.mutate(e[0],e[1]).catch(t)},[a]);if(o.error&&c(a.options.throwOnError,[o.error]))throw o.error;return{...o,mutate:s,mutateAsync:o.mutate}}var _=r(),v={primary:`bg-fg-primary font-medium text-surface-0 hover:bg-white`,ghost:`text-fg-tertiary hover:bg-surface-2/70 hover:text-fg-primary`};function y({variant:e=`ghost`,className:t=``,...n}){return(0,_.jsx)(`button`,{type:`button`,...n,className:`inline-flex h-7 shrink-0 items-center rounded-md px-3 text-xs transition-colors focus-visible:ring-2 focus-visible:ring-fg-primary/30 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-40 ${v[e]} ${t}`})}export{g as n,f as r,y as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{$t as e,Jn as t,Qn as n,Yn as r,j as i,qn as a,t as o}from"./format-BYF63sQU.js";import{n as s,t as c}from"./Button-DxGzriWQ.js";import{l}from"./compose-CV4o6TMb.js";import{n as u,r as d}from"./ThreadForms-CbFClyd0.js";var f=n(r(),1),p=t();function m({project:e,onDone:t}){let{api:n}=i(),r=a(),o=l(),[m,h]=(0,f.useState)(``),[g,_]=(0,f.useState)(``),v=(0,f.useRef)(null);(0,f.useEffect)(()=>v.current?.focus(),[]);let y=s({mutationFn:()=>n.createChannel({project:e,name:m.trim(),purpose:g.trim()}),onSuccess:async e=>{await r.invalidateQueries({queryKey:[`channels`]}),t(),await o({to:`/c/$`,params:{_splat:e}})}});return(0,p.jsxs)(`form`,{"aria-label":`New channel`,className:`space-y-2 border-b border-line bg-surface-2/20 p-3`,onSubmit:e=>{e.preventDefault(),y.mutate()},children:[(0,p.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,p.jsx)(`div`,{className:`w-40 shrink-0`,children:(0,p.jsx)(`input`,{ref:v,value:m,maxLength:64,spellCheck:!1,"aria-label":`Channel name`,placeholder:`release-0-4`,onChange:e=>h(e.target.value),className:`${u} font-mono`})}),(0,p.jsx)(`input`,{value:g,"aria-label":`Purpose`,placeholder:`What the channel is for`,onChange:e=>_(e.target.value),className:`${u} min-w-0 flex-1`}),(0,p.jsx)(c,{onClick:t,children:`Cancel`}),(0,p.jsx)(c,{variant:`primary`,type:`submit`,disabled:y.isPending||m.trim()===``||g.trim()===``,children:y.isPending?`Opening…`:`Open`})]}),(0,p.jsx)(d,{error:y.error})]})}function h({channel:e,onDone:t}){let{api:n}=i(),r=a(),[o,l]=(0,f.useState)(``),m=s({mutationFn:()=>n.archiveChannel({channel:e,reason:o.trim()}),onSuccess:async()=>{await r.invalidateQueries({queryKey:[`channels`]}),t()}});return(0,p.jsxs)(`form`,{"aria-label":`Archive the channel`,className:`space-y-2 border-b border-line bg-surface-2/20 p-3`,onSubmit:e=>{e.preventDefault(),m.mutate()},children:[(0,p.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,p.jsx)(`input`,{value:o,"aria-label":`Reason`,placeholder:`Why its work is done`,onChange:e=>l(e.target.value),className:`${u} min-w-0 flex-1`}),(0,p.jsx)(c,{onClick:t,children:`Cancel`}),(0,p.jsx)(c,{variant:`primary`,type:`submit`,disabled:m.isPending||o.trim()===``,children:m.isPending?`Archiving…`:`Archive channel`})]}),(0,p.jsx)(d,{error:m.error})]})}function g({channels:t,now:n}){return t.length===0?(0,p.jsx)(`p`,{className:`text-meta`,children:`No channels.`}):(0,p.jsx)(`ul`,{className:`space-y-1`,children:t.map(t=>(0,p.jsxs)(`li`,{children:[(0,p.jsxs)(e,{to:`/c/$`,params:{_splat:t.ref},className:`text-sm hover:text-fg-primary ${t.archived===void 0?`text-fg-secondary`:`text-fg-tertiary`}`,children:[`# `,t.name]}),(0,p.jsxs)(`span`,{className:`text-meta`,children:[` `,`· `,t.messages,` messages`,t.archived===void 0?``:` · archived ${o(t.archived.at,n)}`]})]},t.ref))})}export{g as n,m as r,h as t};
|