@integrity-labs/agt-cli 0.28.421 → 0.28.423
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/bin/agt.js +4 -4
- package/dist/{chunk-EP6E6CIY.js → chunk-3HLECXMI.js} +28 -6
- package/dist/chunk-3HLECXMI.js.map +1 -0
- package/dist/{chunk-HVVEMQWZ.js → chunk-4SEBGBAO.js} +22 -6
- package/dist/chunk-4SEBGBAO.js.map +1 -0
- package/dist/{chunk-B4NX2T2H.js → chunk-XFC7YVGS.js} +20 -2
- package/dist/{chunk-B4NX2T2H.js.map → chunk-XFC7YVGS.js.map} +1 -1
- package/dist/{claude-pair-runtime-ZTZR3VCN.js → claude-pair-runtime-3JHCWZZD.js} +2 -2
- package/dist/lib/manager-worker.js +12 -12
- package/dist/mcp/direct-chat-channel.js +19 -1
- package/dist/mcp/origami.js +19 -1
- package/dist/mcp/slack-channel.js +19 -1
- package/dist/mcp/telegram-channel.js +19 -1
- package/dist/{persistent-session-2OYYXMM7.js → persistent-session-HWCKGPYF.js} +2 -2
- package/dist/{responsiveness-probe-7OOA57BP.js → responsiveness-probe-4CGMUXOH.js} +2 -2
- package/dist/{scheduler-engine-HYOOQV4A.js → scheduler-engine-NDP36U7O.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-EP6E6CIY.js.map +0 -1
- package/dist/chunk-HVVEMQWZ.js.map +0 -1
- /package/dist/{claude-pair-runtime-ZTZR3VCN.js.map → claude-pair-runtime-3JHCWZZD.js.map} +0 -0
- /package/dist/{persistent-session-2OYYXMM7.js.map → persistent-session-HWCKGPYF.js.map} +0 -0
- /package/dist/{responsiveness-probe-7OOA57BP.js.map → responsiveness-probe-4CGMUXOH.js.map} +0 -0
- /package/dist/{scheduler-engine-HYOOQV4A.js.map → scheduler-engine-NDP36U7O.js.map} +0 -0
|
@@ -100,7 +100,7 @@ async function spawnPairSession(session) {
|
|
|
100
100
|
return { ok: true };
|
|
101
101
|
} catch {
|
|
102
102
|
}
|
|
103
|
-
const { resolveClaudeBinary } = await import("./persistent-session-
|
|
103
|
+
const { resolveClaudeBinary } = await import("./persistent-session-HWCKGPYF.js");
|
|
104
104
|
const claudeBin = resolveClaudeBinary();
|
|
105
105
|
const pairEnv = {
|
|
106
106
|
...process.env,
|
|
@@ -373,4 +373,4 @@ export {
|
|
|
373
373
|
startClaudePair,
|
|
374
374
|
submitClaudePairCode
|
|
375
375
|
};
|
|
376
|
-
//# sourceMappingURL=claude-pair-runtime-
|
|
376
|
+
//# sourceMappingURL=claude-pair-runtime-3JHCWZZD.js.map
|
|
@@ -45,14 +45,14 @@ import {
|
|
|
45
45
|
resolveEffectivePinRaw,
|
|
46
46
|
safeWriteJsonAtomic,
|
|
47
47
|
setConfigHash
|
|
48
|
-
} from "../chunk-
|
|
48
|
+
} from "../chunk-4SEBGBAO.js";
|
|
49
49
|
import {
|
|
50
50
|
getProjectDir as getProjectDir2,
|
|
51
51
|
getReadyTasks,
|
|
52
52
|
loadSchedulerState,
|
|
53
53
|
markTaskFired,
|
|
54
54
|
syncTasksToScheduler
|
|
55
|
-
} from "../chunk-
|
|
55
|
+
} from "../chunk-3HLECXMI.js";
|
|
56
56
|
import {
|
|
57
57
|
AnchorSessionClient,
|
|
58
58
|
CONVERSATION_FAILURE_CATEGORIES,
|
|
@@ -150,7 +150,7 @@ import {
|
|
|
150
150
|
toOpencodeModel,
|
|
151
151
|
transcriptActivityAgeSeconds,
|
|
152
152
|
writeEgressAllowlist
|
|
153
|
-
} from "../chunk-
|
|
153
|
+
} from "../chunk-XFC7YVGS.js";
|
|
154
154
|
import {
|
|
155
155
|
reapOrphanChannelMcps
|
|
156
156
|
} from "../chunk-XWVM4KPK.js";
|
|
@@ -9458,7 +9458,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
9458
9458
|
var lastVersionCheckAt = 0;
|
|
9459
9459
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
9460
9460
|
var lastResponsivenessProbeAt = 0;
|
|
9461
|
-
var agtCliVersion = true ? "0.28.
|
|
9461
|
+
var agtCliVersion = true ? "0.28.423" : "dev";
|
|
9462
9462
|
function resolveBrewPath(execFileSync2) {
|
|
9463
9463
|
try {
|
|
9464
9464
|
const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -10606,7 +10606,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
|
|
|
10606
10606
|
if (codeNames.length === 0) return;
|
|
10607
10607
|
void (async () => {
|
|
10608
10608
|
try {
|
|
10609
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
10609
|
+
const { collectDiagnostics } = await import("../persistent-session-HWCKGPYF.js");
|
|
10610
10610
|
await api.post("/host/heartbeat", {
|
|
10611
10611
|
host_id: hostId,
|
|
10612
10612
|
agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor)
|
|
@@ -10713,7 +10713,7 @@ async function pollCycle() {
|
|
|
10713
10713
|
}
|
|
10714
10714
|
try {
|
|
10715
10715
|
const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
|
|
10716
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
10716
|
+
const { collectDiagnostics } = await import("../persistent-session-HWCKGPYF.js");
|
|
10717
10717
|
const diagCodeNames = [...agentState.persistentSessionAgents];
|
|
10718
10718
|
const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor) : void 0;
|
|
10719
10719
|
let tailscaleHostname;
|
|
@@ -10827,7 +10827,7 @@ async function pollCycle() {
|
|
|
10827
10827
|
collectResponsivenessProbes,
|
|
10828
10828
|
collectPanelessActivityProbes,
|
|
10829
10829
|
getResponsivenessIntervalMs
|
|
10830
|
-
} = await import("../responsiveness-probe-
|
|
10830
|
+
} = await import("../responsiveness-probe-4CGMUXOH.js");
|
|
10831
10831
|
const probeIntervalMs = getResponsivenessIntervalMs();
|
|
10832
10832
|
if (now - lastResponsivenessProbeAt > probeIntervalMs) {
|
|
10833
10833
|
const probeCodeNames = [...agentState.persistentSessionAgents];
|
|
@@ -10866,8 +10866,8 @@ async function pollCycle() {
|
|
|
10866
10866
|
collectResponsivenessProbes,
|
|
10867
10867
|
livePendingInboundOldestAgeSeconds,
|
|
10868
10868
|
parkPendingInbound
|
|
10869
|
-
} = await import("../responsiveness-probe-
|
|
10870
|
-
const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-
|
|
10869
|
+
} = await import("../responsiveness-probe-4CGMUXOH.js");
|
|
10870
|
+
const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-NDP36U7O.js");
|
|
10871
10871
|
const wedgeNow = /* @__PURE__ */ new Date();
|
|
10872
10872
|
const liveAgents = agentState.persistentSessionAgents;
|
|
10873
10873
|
for (const tracked of consecutiveWedgeCycles.keys()) {
|
|
@@ -14177,7 +14177,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
|
|
|
14177
14177
|
void api.post("/host/restart-ack", { host_id: hostId, agent_id: agentId, restart_requested_at: requestedAt }).catch((err) => log(`[restart-lane] ack failed for '${codeName}': ${err.message}`));
|
|
14178
14178
|
void (async () => {
|
|
14179
14179
|
try {
|
|
14180
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
14180
|
+
const { collectDiagnostics } = await import("../persistent-session-HWCKGPYF.js");
|
|
14181
14181
|
await api.post("/host/heartbeat", {
|
|
14182
14182
|
host_id: hostId,
|
|
14183
14183
|
agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor)
|
|
@@ -14227,7 +14227,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
|
|
|
14227
14227
|
}
|
|
14228
14228
|
try {
|
|
14229
14229
|
const hostId = await getHostId();
|
|
14230
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
14230
|
+
const { collectDiagnostics } = await import("../persistent-session-HWCKGPYF.js");
|
|
14231
14231
|
await api.post("/host/heartbeat", {
|
|
14232
14232
|
host_id: hostId,
|
|
14233
14233
|
agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor)
|
|
@@ -14680,7 +14680,7 @@ async function processClaudePairSessions(agents) {
|
|
|
14680
14680
|
killPairSession,
|
|
14681
14681
|
pairTmuxSession,
|
|
14682
14682
|
finalizeClaudePairOnboarding
|
|
14683
|
-
} = await import("../claude-pair-runtime-
|
|
14683
|
+
} = await import("../claude-pair-runtime-3JHCWZZD.js");
|
|
14684
14684
|
for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
|
|
14685
14685
|
log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
|
|
14686
14686
|
const killed = await killPairSession(pairTmuxSession(pairId));
|
|
@@ -34681,7 +34681,14 @@ var FLAG_REGISTRY = [
|
|
|
34681
34681
|
envVar: "AGT_SLACK_SCHEDULED_CHANNEL_GUARD_MODE",
|
|
34682
34682
|
// enforce REFUSES a send the agent asked to make - a visible availability
|
|
34683
34683
|
// change, so flipping toward it is deliberate (ADR-0022 sensitive-flag confirm).
|
|
34684
|
-
sensitive: true
|
|
34684
|
+
sensitive: true,
|
|
34685
|
+
// ENG-8149: the agt-cli that first carries resolveSlackScheduledChannelGuardMode
|
|
34686
|
+
// (published from the ENG-8137 merge c6ff71cd). Without this the flip-reach modal
|
|
34687
|
+
// reports FULL reach, because an undefined `since` means "every host can honour
|
|
34688
|
+
// it" - true for flags that predate the reach work, wrong for a NEW host-read
|
|
34689
|
+
// flag whose reader older hosts simply do not have. Excluded from
|
|
34690
|
+
// projectDefinition, so setting it does not roll FLAGS_SCHEMA_VERSION.
|
|
34691
|
+
since: "0.28.421"
|
|
34685
34692
|
},
|
|
34686
34693
|
{
|
|
34687
34694
|
key: "slack-hot-thread-guard",
|
|
@@ -35293,6 +35300,17 @@ var FLAG_REGISTRY = [
|
|
|
35293
35300
|
// direction - a flag-DB read error must not resurrect the mis-threading/noise the kill
|
|
35294
35301
|
// fixes. Net-new gate, registry-only (ADR-0022); API-evaluated, no env materialization.
|
|
35295
35302
|
defaultValue: false
|
|
35303
|
+
},
|
|
35304
|
+
{
|
|
35305
|
+
key: "onboarding-msteams-channel",
|
|
35306
|
+
description: `Offer Microsoft Teams as a selectable channel on onboarding step 3 ("which channels should your org use?", ENG-8146). OFF (default) hides the Teams option entirely: it is not rendered, not selectable, and not named in the plan-upgrade note. Turn it ON per org to restore the option for a customer who genuinely runs on Teams. Resolved SERVER-SIDE in the step-3 server component for the URL's orgId (webapp lib/feature-flags-org-server.ts), NOT via the browser public map \u2014 the client flag path evaluates at the active-org cookie, which onboarding deliberately does not pin to the org being onboarded, so a client read would resolve the wrong org for a multi-org user. Hiding the option never revokes a channel: an org that already saved msteams keeps it (step 3 carries hidden-but-saved channels through the write). Ships dark.`,
|
|
35307
|
+
flagType: "boolean",
|
|
35308
|
+
// Declared safe value is `false`: Teams hidden. `false` is also the fail-closed
|
|
35309
|
+
// direction - a flag-DB read error must show the narrower channel set, never
|
|
35310
|
+
// surface an option the operator has not deliberately turned on. Net-new gate,
|
|
35311
|
+
// registry-only (ADR-0022). NOT `public`: it is resolved server-side only, so it
|
|
35312
|
+
// must never be serialized into the browser map.
|
|
35313
|
+
defaultValue: false
|
|
35296
35314
|
}
|
|
35297
35315
|
];
|
|
35298
35316
|
var REGISTRY_BY_KEY = new Map(FLAG_REGISTRY.map((definition) => [definition.key, definition]));
|
package/dist/mcp/origami.js
CHANGED
|
@@ -40297,7 +40297,14 @@ var FLAG_REGISTRY = [
|
|
|
40297
40297
|
envVar: "AGT_SLACK_SCHEDULED_CHANNEL_GUARD_MODE",
|
|
40298
40298
|
// enforce REFUSES a send the agent asked to make - a visible availability
|
|
40299
40299
|
// change, so flipping toward it is deliberate (ADR-0022 sensitive-flag confirm).
|
|
40300
|
-
sensitive: true
|
|
40300
|
+
sensitive: true,
|
|
40301
|
+
// ENG-8149: the agt-cli that first carries resolveSlackScheduledChannelGuardMode
|
|
40302
|
+
// (published from the ENG-8137 merge c6ff71cd). Without this the flip-reach modal
|
|
40303
|
+
// reports FULL reach, because an undefined `since` means "every host can honour
|
|
40304
|
+
// it" - true for flags that predate the reach work, wrong for a NEW host-read
|
|
40305
|
+
// flag whose reader older hosts simply do not have. Excluded from
|
|
40306
|
+
// projectDefinition, so setting it does not roll FLAGS_SCHEMA_VERSION.
|
|
40307
|
+
since: "0.28.421"
|
|
40301
40308
|
},
|
|
40302
40309
|
{
|
|
40303
40310
|
key: "slack-hot-thread-guard",
|
|
@@ -40909,6 +40916,17 @@ var FLAG_REGISTRY = [
|
|
|
40909
40916
|
// direction - a flag-DB read error must not resurrect the mis-threading/noise the kill
|
|
40910
40917
|
// fixes. Net-new gate, registry-only (ADR-0022); API-evaluated, no env materialization.
|
|
40911
40918
|
defaultValue: false
|
|
40919
|
+
},
|
|
40920
|
+
{
|
|
40921
|
+
key: "onboarding-msteams-channel",
|
|
40922
|
+
description: `Offer Microsoft Teams as a selectable channel on onboarding step 3 ("which channels should your org use?", ENG-8146). OFF (default) hides the Teams option entirely: it is not rendered, not selectable, and not named in the plan-upgrade note. Turn it ON per org to restore the option for a customer who genuinely runs on Teams. Resolved SERVER-SIDE in the step-3 server component for the URL's orgId (webapp lib/feature-flags-org-server.ts), NOT via the browser public map \u2014 the client flag path evaluates at the active-org cookie, which onboarding deliberately does not pin to the org being onboarded, so a client read would resolve the wrong org for a multi-org user. Hiding the option never revokes a channel: an org that already saved msteams keeps it (step 3 carries hidden-but-saved channels through the write). Ships dark.`,
|
|
40923
|
+
flagType: "boolean",
|
|
40924
|
+
// Declared safe value is `false`: Teams hidden. `false` is also the fail-closed
|
|
40925
|
+
// direction - a flag-DB read error must show the narrower channel set, never
|
|
40926
|
+
// surface an option the operator has not deliberately turned on. Net-new gate,
|
|
40927
|
+
// registry-only (ADR-0022). NOT `public`: it is resolved server-side only, so it
|
|
40928
|
+
// must never be serialized into the browser map.
|
|
40929
|
+
defaultValue: false
|
|
40912
40930
|
}
|
|
40913
40931
|
];
|
|
40914
40932
|
var REGISTRY_BY_KEY = new Map(FLAG_REGISTRY.map((definition) => [definition.key, definition]));
|
|
@@ -34264,7 +34264,14 @@ var FLAG_REGISTRY = [
|
|
|
34264
34264
|
envVar: "AGT_SLACK_SCHEDULED_CHANNEL_GUARD_MODE",
|
|
34265
34265
|
// enforce REFUSES a send the agent asked to make - a visible availability
|
|
34266
34266
|
// change, so flipping toward it is deliberate (ADR-0022 sensitive-flag confirm).
|
|
34267
|
-
sensitive: true
|
|
34267
|
+
sensitive: true,
|
|
34268
|
+
// ENG-8149: the agt-cli that first carries resolveSlackScheduledChannelGuardMode
|
|
34269
|
+
// (published from the ENG-8137 merge c6ff71cd). Without this the flip-reach modal
|
|
34270
|
+
// reports FULL reach, because an undefined `since` means "every host can honour
|
|
34271
|
+
// it" - true for flags that predate the reach work, wrong for a NEW host-read
|
|
34272
|
+
// flag whose reader older hosts simply do not have. Excluded from
|
|
34273
|
+
// projectDefinition, so setting it does not roll FLAGS_SCHEMA_VERSION.
|
|
34274
|
+
since: "0.28.421"
|
|
34268
34275
|
},
|
|
34269
34276
|
{
|
|
34270
34277
|
key: "slack-hot-thread-guard",
|
|
@@ -34876,6 +34883,17 @@ var FLAG_REGISTRY = [
|
|
|
34876
34883
|
// direction - a flag-DB read error must not resurrect the mis-threading/noise the kill
|
|
34877
34884
|
// fixes. Net-new gate, registry-only (ADR-0022); API-evaluated, no env materialization.
|
|
34878
34885
|
defaultValue: false
|
|
34886
|
+
},
|
|
34887
|
+
{
|
|
34888
|
+
key: "onboarding-msteams-channel",
|
|
34889
|
+
description: `Offer Microsoft Teams as a selectable channel on onboarding step 3 ("which channels should your org use?", ENG-8146). OFF (default) hides the Teams option entirely: it is not rendered, not selectable, and not named in the plan-upgrade note. Turn it ON per org to restore the option for a customer who genuinely runs on Teams. Resolved SERVER-SIDE in the step-3 server component for the URL's orgId (webapp lib/feature-flags-org-server.ts), NOT via the browser public map \u2014 the client flag path evaluates at the active-org cookie, which onboarding deliberately does not pin to the org being onboarded, so a client read would resolve the wrong org for a multi-org user. Hiding the option never revokes a channel: an org that already saved msteams keeps it (step 3 carries hidden-but-saved channels through the write). Ships dark.`,
|
|
34890
|
+
flagType: "boolean",
|
|
34891
|
+
// Declared safe value is `false`: Teams hidden. `false` is also the fail-closed
|
|
34892
|
+
// direction - a flag-DB read error must show the narrower channel set, never
|
|
34893
|
+
// surface an option the operator has not deliberately turned on. Net-new gate,
|
|
34894
|
+
// registry-only (ADR-0022). NOT `public`: it is resolved server-side only, so it
|
|
34895
|
+
// must never be serialized into the browser map.
|
|
34896
|
+
defaultValue: false
|
|
34879
34897
|
}
|
|
34880
34898
|
];
|
|
34881
34899
|
var REGISTRY_BY_KEY = new Map(FLAG_REGISTRY.map((definition) => [definition.key, definition]));
|
|
@@ -34566,7 +34566,14 @@ var FLAG_REGISTRY = [
|
|
|
34566
34566
|
envVar: "AGT_SLACK_SCHEDULED_CHANNEL_GUARD_MODE",
|
|
34567
34567
|
// enforce REFUSES a send the agent asked to make - a visible availability
|
|
34568
34568
|
// change, so flipping toward it is deliberate (ADR-0022 sensitive-flag confirm).
|
|
34569
|
-
sensitive: true
|
|
34569
|
+
sensitive: true,
|
|
34570
|
+
// ENG-8149: the agt-cli that first carries resolveSlackScheduledChannelGuardMode
|
|
34571
|
+
// (published from the ENG-8137 merge c6ff71cd). Without this the flip-reach modal
|
|
34572
|
+
// reports FULL reach, because an undefined `since` means "every host can honour
|
|
34573
|
+
// it" - true for flags that predate the reach work, wrong for a NEW host-read
|
|
34574
|
+
// flag whose reader older hosts simply do not have. Excluded from
|
|
34575
|
+
// projectDefinition, so setting it does not roll FLAGS_SCHEMA_VERSION.
|
|
34576
|
+
since: "0.28.421"
|
|
34570
34577
|
},
|
|
34571
34578
|
{
|
|
34572
34579
|
key: "slack-hot-thread-guard",
|
|
@@ -35178,6 +35185,17 @@ var FLAG_REGISTRY = [
|
|
|
35178
35185
|
// direction - a flag-DB read error must not resurrect the mis-threading/noise the kill
|
|
35179
35186
|
// fixes. Net-new gate, registry-only (ADR-0022); API-evaluated, no env materialization.
|
|
35180
35187
|
defaultValue: false
|
|
35188
|
+
},
|
|
35189
|
+
{
|
|
35190
|
+
key: "onboarding-msteams-channel",
|
|
35191
|
+
description: `Offer Microsoft Teams as a selectable channel on onboarding step 3 ("which channels should your org use?", ENG-8146). OFF (default) hides the Teams option entirely: it is not rendered, not selectable, and not named in the plan-upgrade note. Turn it ON per org to restore the option for a customer who genuinely runs on Teams. Resolved SERVER-SIDE in the step-3 server component for the URL's orgId (webapp lib/feature-flags-org-server.ts), NOT via the browser public map \u2014 the client flag path evaluates at the active-org cookie, which onboarding deliberately does not pin to the org being onboarded, so a client read would resolve the wrong org for a multi-org user. Hiding the option never revokes a channel: an org that already saved msteams keeps it (step 3 carries hidden-but-saved channels through the write). Ships dark.`,
|
|
35192
|
+
flagType: "boolean",
|
|
35193
|
+
// Declared safe value is `false`: Teams hidden. `false` is also the fail-closed
|
|
35194
|
+
// direction - a flag-DB read error must show the narrower channel set, never
|
|
35195
|
+
// surface an option the operator has not deliberately turned on. Net-new gate,
|
|
35196
|
+
// registry-only (ADR-0022). NOT `public`: it is resolved server-side only, so it
|
|
35197
|
+
// must never be serialized into the browser map.
|
|
35198
|
+
defaultValue: false
|
|
35181
35199
|
}
|
|
35182
35200
|
];
|
|
35183
35201
|
var REGISTRY_BY_KEY = new Map(FLAG_REGISTRY.map((definition) => [definition.key, definition]));
|
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
writeDirectChatSessionState,
|
|
37
37
|
writeEgressAllowlist,
|
|
38
38
|
writePersistentClaudeWrapper
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-XFC7YVGS.js";
|
|
40
40
|
import "./chunk-XWVM4KPK.js";
|
|
41
41
|
export {
|
|
42
42
|
EGRESS_BASELINE_DOMAINS,
|
|
@@ -77,4 +77,4 @@ export {
|
|
|
77
77
|
writeEgressAllowlist,
|
|
78
78
|
writePersistentClaudeWrapper
|
|
79
79
|
};
|
|
80
|
-
//# sourceMappingURL=persistent-session-
|
|
80
|
+
//# sourceMappingURL=persistent-session-HWCKGPYF.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
paneLogPath
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-XFC7YVGS.js";
|
|
4
4
|
import "./chunk-XWVM4KPK.js";
|
|
5
5
|
|
|
6
6
|
// src/lib/responsiveness-probe.ts
|
|
@@ -471,4 +471,4 @@ export {
|
|
|
471
471
|
readAndResetSlackReplyBindingClassifications,
|
|
472
472
|
readAndResetSlackReplyTargetClassifications
|
|
473
473
|
};
|
|
474
|
-
//# sourceMappingURL=responsiveness-probe-
|
|
474
|
+
//# sourceMappingURL=responsiveness-probe-4CGMUXOH.js.map
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
markTaskFired,
|
|
8
8
|
saveSchedulerState,
|
|
9
9
|
syncTasksToScheduler
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-3HLECXMI.js";
|
|
11
11
|
export {
|
|
12
12
|
computeNextFire,
|
|
13
13
|
findTaskByTemplate,
|
|
@@ -18,4 +18,4 @@ export {
|
|
|
18
18
|
saveSchedulerState,
|
|
19
19
|
syncTasksToScheduler
|
|
20
20
|
};
|
|
21
|
-
//# sourceMappingURL=scheduler-engine-
|
|
21
|
+
//# sourceMappingURL=scheduler-engine-NDP36U7O.js.map
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/scheduler-engine.ts"],"sourcesContent":["/**\n * Framework-agnostic scheduled-task state machine.\n *\n * The pure scheduling engine: schedule definitions -> next-fire computation ->\n * ready-task detection -> post-fire state advance, with on-disk persistence so\n * nextFireAt/lastFireAt survive manager restarts. It owns the WHEN, not the HOW:\n * each framework supplies its own firing leaf and calls back into\n * `markTaskFired`.\n * - Claude Code fires via the in-session kanban todo-card route\n * (manager/scheduler/execution.ts + kanban-route.ts).\n * - opencode fires via an HTTP inject into `opencode serve`\n * (manager/opencode-scheduler.ts).\n * Both share this engine verbatim, so cadence, one-shot completion,\n * manual-trigger, and cross-restart recovery are identical across frameworks.\n * (Named claude-scheduler.ts historically, when the claude `-p` oneshot was the\n * only consumer.)\n */\n\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { Cron } from 'croner';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface SchedulerTaskState {\n taskId: string;\n templateId: string;\n name: string;\n agentCodeName: string;\n agentId: string;\n scheduleKind: 'cron' | 'every' | 'at';\n scheduleExpr: string | null;\n scheduleEvery: string | null;\n scheduleAt: string | null;\n timezone: string;\n prompt: string;\n sessionTarget: string;\n deliveryMode: string;\n /** ENG-6107: always | conditional | never — whether results deliver.\n * Optional: states persisted by older CLIs lack it; absent = 'always'. */\n deliveryPolicy?: string | null;\n deliveryChannel: string | null;\n /** ENG-4422 §4: JSONB DeliveryTarget (or null). Legacy string form is gone\n * after the migration; in-memory shape is the structured object. */\n deliveryTo: unknown | null;\n enabled: boolean;\n triggeredAt: number | null; // epoch ms — manual trigger from webapp\n nextFireAt: number | null; // epoch ms, null = completed one-shot\n lastFireAt: number | null;\n lastStatus: 'ok' | 'error' | null;\n firedCount: number;\n}\n\nexport interface SchedulerState {\n version: 1;\n tasks: Record<string, SchedulerTaskState>;\n updatedAt: string;\n}\n\nexport interface SchedulerTaskInput {\n id: string;\n template_id: string;\n name: string;\n schedule_kind: 'cron' | 'every' | 'at';\n schedule_expr: string | null;\n schedule_every: string | null;\n schedule_at: string | null;\n timezone: string;\n prompt: string;\n session_target: string;\n delivery_mode: string;\n /** ENG-6107: absent from older APIs — treated as 'always'. */\n delivery_policy?: string | null;\n delivery_channel: string | null;\n /** ENG-4422 §4: JSONB DeliveryTarget or null (post-migration). */\n delivery_to: unknown | null;\n enabled: boolean;\n triggered_at?: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Interval parsing (reused from Claude Code adapter)\n// ---------------------------------------------------------------------------\n\nfunction parseIntervalMs(scheduleEvery: string | null): number {\n if (!scheduleEvery) return 60 * 60_000; // 1hr default\n const match = scheduleEvery.match(/^(\\d+)\\s*(m|min|h|hr|d)$/i);\n if (!match) return 60 * 60_000;\n const value = parseInt(match[1]!, 10);\n const unit = match[2]!.toLowerCase();\n if (unit === 'h' || unit === 'hr') return value * 60 * 60_000;\n if (unit === 'd') return value * 24 * 60 * 60_000;\n return value * 60_000; // minutes\n}\n\n// ---------------------------------------------------------------------------\n// Next-fire computation\n// ---------------------------------------------------------------------------\n\nexport function computeNextFire(\n kind: 'cron' | 'every' | 'at',\n expr: string | null,\n every: string | null,\n at: string | null,\n timezone: string,\n afterMs?: number,\n): number | null {\n const now = afterMs ?? Date.now();\n\n if (kind === 'cron' && expr) {\n try {\n const cron = new Cron(expr, { timezone: timezone || undefined });\n const next = cron.nextRun(new Date(now));\n return next ? next.getTime() : null;\n } catch {\n return null;\n }\n }\n\n if (kind === 'every') {\n const intervalMs = parseIntervalMs(every);\n return now + intervalMs;\n }\n\n if (kind === 'at' && at) {\n const ts = new Date(at).getTime();\n if (isNaN(ts)) return null;\n // If the 'at' timestamp is in the past and afterMs is set (meaning we already\n // fired), return null to prevent re-firing on state rebuild.\n if (afterMs && ts <= afterMs) return null;\n return ts;\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// State persistence\n// ---------------------------------------------------------------------------\n\nfunction getStateDir(codeName: string): string {\n // ENG-4418: unified agent dir — scheduler state lives at the agent root\n // alongside other runtime state files (plugins.json, schedules.json,\n // registration.json). Legacy ~/.augmented/<codeName>/claudecode/scheduler-state.json\n // is migrated up by claudeCodeAdapter.getAgentDir on first poll.\n return join(homedir(), '.augmented', codeName);\n}\n\nfunction getStatePath(codeName: string): string {\n return join(getStateDir(codeName), 'scheduler-state.json');\n}\n\nexport function loadSchedulerState(codeName: string): SchedulerState {\n const path = getStatePath(codeName);\n if (existsSync(path)) {\n try {\n return JSON.parse(readFileSync(path, 'utf-8'));\n } catch { /* corrupted — start fresh */ }\n }\n return { version: 1, tasks: {}, updatedAt: new Date().toISOString() };\n}\n\nexport function saveSchedulerState(codeName: string, state: SchedulerState): void {\n const dir = getStateDir(codeName);\n mkdirSync(dir, { recursive: true });\n state.updatedAt = new Date().toISOString();\n const path = getStatePath(codeName);\n const tmpPath = path + '.tmp';\n writeFileSync(tmpPath, JSON.stringify(state, null, 2));\n renameSync(tmpPath, path);\n}\n\n// ---------------------------------------------------------------------------\n// Sync API tasks → scheduler state\n// ---------------------------------------------------------------------------\n\nexport function syncTasksToScheduler(\n codeName: string,\n agentId: string,\n tasks: SchedulerTaskInput[],\n): SchedulerState {\n const state = loadSchedulerState(codeName);\n const desiredIds = new Set(tasks.map((t) => t.id));\n\n // Remove tasks no longer in API\n for (const id of Object.keys(state.tasks)) {\n if (!desiredIds.has(id)) {\n delete state.tasks[id];\n }\n }\n\n // Add or update tasks\n for (const t of tasks) {\n const existing = state.tasks[t.id];\n if (existing) {\n // Only recompute nextFireAt if the schedule definition actually changed.\n // Without this guard, every sync cycle resets nextFireAt from \"now\",\n // preventing past-due tasks from ever being detected as ready.\n const scheduleChanged =\n existing.scheduleKind !== t.schedule_kind ||\n existing.scheduleExpr !== t.schedule_expr ||\n existing.scheduleEvery !== t.schedule_every ||\n existing.scheduleAt !== t.schedule_at ||\n existing.timezone !== t.timezone;\n\n // Update mutable fields, preserve fire history\n existing.name = t.name;\n existing.templateId = t.template_id;\n existing.scheduleKind = t.schedule_kind;\n existing.scheduleExpr = t.schedule_expr;\n existing.scheduleEvery = t.schedule_every;\n existing.scheduleAt = t.schedule_at;\n existing.timezone = t.timezone;\n existing.prompt = t.prompt;\n existing.sessionTarget = t.session_target;\n existing.deliveryMode = t.delivery_mode;\n existing.deliveryPolicy = t.delivery_policy ?? 'always';\n existing.deliveryChannel = t.delivery_channel;\n existing.deliveryTo = t.delivery_to;\n existing.enabled = t.enabled;\n if (t.triggered_at) existing.triggeredAt = new Date(t.triggered_at).getTime();\n if (scheduleChanged) {\n existing.nextFireAt = computeNextFire(\n t.schedule_kind, t.schedule_expr, t.schedule_every, t.schedule_at,\n t.timezone, existing.lastFireAt ?? undefined,\n );\n }\n } else {\n // New task\n state.tasks[t.id] = {\n taskId: t.id,\n templateId: t.template_id,\n name: t.name,\n agentCodeName: codeName,\n agentId,\n scheduleKind: t.schedule_kind,\n scheduleExpr: t.schedule_expr,\n scheduleEvery: t.schedule_every,\n scheduleAt: t.schedule_at,\n timezone: t.timezone,\n prompt: t.prompt,\n sessionTarget: t.session_target,\n deliveryMode: t.delivery_mode,\n deliveryPolicy: t.delivery_policy ?? 'always',\n deliveryChannel: t.delivery_channel,\n deliveryTo: t.delivery_to,\n enabled: t.enabled,\n triggeredAt: t.triggered_at ? new Date(t.triggered_at).getTime() : null,\n nextFireAt: computeNextFire(\n t.schedule_kind, t.schedule_expr, t.schedule_every, t.schedule_at, t.timezone,\n ),\n lastFireAt: null,\n lastStatus: null,\n firedCount: 0,\n };\n }\n }\n\n saveSchedulerState(codeName, state);\n return state;\n}\n\n// ---------------------------------------------------------------------------\n// Ready-task detection\n// ---------------------------------------------------------------------------\n\n// ENG-4675: pass `inFlightTaskIds` so the manager's poll loop doesn't\n// re-detect tasks that already have a `claude -p` subprocess running.\n// Without this, every supervisor tick (~17s) saw the manual trigger as\n// still ready (because lastFireAt is only set on completion, not on\n// fire start), spamming \"N ready task(s)\" + \"Firing task\" log lines that\n// looked like duplicate fires. The in-flight guard at the spawn site\n// prevented actual duplicate subprocesses, but the log was misleading.\nexport function getReadyTasks(\n state: SchedulerState,\n inFlightTaskIds?: ReadonlySet<string>,\n): SchedulerTaskState[] {\n const now = Date.now();\n const ready = Object.values(state.tasks).filter((t) => {\n if (!t.enabled) return false;\n if (inFlightTaskIds?.has(t.taskId)) return false;\n // Manual trigger: triggered_at is set and hasn't been fired yet\n if (t.triggeredAt) {\n const triggerReady = !t.lastFireAt || t.triggeredAt > t.lastFireAt;\n if (triggerReady) return true;\n }\n // Normal schedule\n return t.nextFireAt !== null && t.nextFireAt <= now;\n });\n // Deduplicate by templateId — only fire one task per template per cycle\n const seen = new Set<string>();\n return ready.filter((t) => {\n if (seen.has(t.templateId)) return false;\n seen.add(t.templateId);\n return true;\n });\n}\n\n// ---------------------------------------------------------------------------\n// Post-execution state update\n// ---------------------------------------------------------------------------\n\nexport function markTaskFired(\n codeName: string,\n taskId: string,\n status: 'ok' | 'error',\n): SchedulerState {\n const state = loadSchedulerState(codeName);\n const task = state.tasks[taskId];\n if (!task) return state;\n\n task.lastFireAt = Date.now();\n task.lastStatus = status;\n task.firedCount++;\n\n // Compute next fire\n if (task.scheduleKind === 'at') {\n // One-shot — mark as completed\n task.nextFireAt = null;\n } else {\n task.nextFireAt = computeNextFire(\n task.scheduleKind, task.scheduleExpr, task.scheduleEvery, task.scheduleAt,\n task.timezone, task.lastFireAt,\n );\n }\n\n // Persisting is best-effort: the SchedulerState the caller stores in memory\n // (claudeSchedulerStates) is the running source of truth — getReadyTasks\n // reads it, not the disk file. A disk-write failure (ENOSPC/EACCES) must NOT\n // throw, or the caller's in-memory state would never advance and the task\n // would be treated as ready again next poll (ENG-5599: a duplicate\n // scheduled-task card materialised every tick). The mutated `state` is\n // returned regardless; cross-restart recovery is a separate concern.\n try {\n saveSchedulerState(codeName, state);\n } catch (err) {\n console.error(\n `[scheduler-engine] markTaskFired: failed to persist state for '${codeName}': ${(err as Error).message}`,\n );\n }\n return state;\n}\n\n// ---------------------------------------------------------------------------\n// Find a task by template ID (for work triggers)\n// ---------------------------------------------------------------------------\n\nexport function findTaskByTemplate(state: SchedulerState, templateId: string): SchedulerTaskState | undefined {\n return Object.values(state.tasks).find(\n (t) => t.templateId === templateId && t.enabled,\n );\n}\n\nexport function getProjectDir(codeName: string): string {\n return join(homedir(), '.augmented', codeName, 'project');\n}\n"],"mappings":"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","names":[]}
|