@rubytech/create-sitedesk-code 0.1.550 → 0.1.552
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/payload/platform/lib/agent-dispatch-rule/dist/index.d.ts +22 -8
- package/payload/platform/lib/agent-dispatch-rule/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/agent-dispatch-rule/dist/index.js +47 -13
- package/payload/platform/lib/agent-dispatch-rule/dist/index.js.map +1 -1
- package/payload/platform/lib/agent-dispatch-rule/src/__tests__/rule.test.ts +68 -9
- package/payload/platform/lib/agent-dispatch-rule/src/index.ts +60 -16
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +3 -3
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +9 -0
- package/payload/platform/plugins/docs/references/admin-ui.md +2 -2
- package/payload/platform/plugins/scheduling/PLUGIN.md +22 -0
- package/payload/platform/plugins/scheduling/mcp/dist/index.js +107 -6
- package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/agent-dispatch.test.js +2 -2
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/agent-dispatch.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/connector-freebusy.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/connector-freebusy.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/connector-freebusy.test.js +216 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/connector-freebusy.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/connector-sync-provision.test.js +2 -2
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/connector-sync-provision.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-audits.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-audits.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-audits.test.js +128 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-audits.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate.test.js +135 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/schedule-audit.test.js +132 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/schedule-audit.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/connector-freebusy.d.ts +86 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/connector-freebusy.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/connector-freebusy.js +240 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/connector-freebusy.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/connector-sync-provision.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/connector-sync-provision.js +21 -8
- package/payload/platform/plugins/scheduling/mcp/dist/lib/connector-sync-provision.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.d.ts +92 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.js +193 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-run.d.ts +8 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-run.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-run.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-audit.d.ts +94 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-audit.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-audit.js +299 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-audit.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/gate-dispatch-wiring.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/gate-dispatch-wiring.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/gate-dispatch-wiring.test.js +146 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/gate-dispatch-wiring.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts +27 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js +18 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +119 -64
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-connector-busy-sync.test.js +84 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-connector-busy-sync.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-gate-write.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-gate-write.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-gate-write.test.js +218 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-gate-write.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/scheduling-gate.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/scheduling-gate.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/scheduling-gate.test.js +291 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/scheduling-gate.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-connector-busy-sync.d.ts +26 -2
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-connector-busy-sync.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-connector-busy-sync.js +51 -2
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-connector-busy-sync.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts +31 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js +44 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.d.ts +3 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js +57 -3
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.d.ts +148 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.js +410 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/package.json +1 -0
- package/payload/platform/plugins/telegram/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/telegram/PLUGIN.md +6 -4
- package/payload/platform/plugins/telegram/mcp/dist/index.js +62 -38
- package/payload/platform/plugins/telegram/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.d.ts +18 -5
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.js +34 -6
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.d.ts +25 -8
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.js +28 -16
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/agent-active.d.ts +12 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/agent-active.d.ts.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/agent-active.js +26 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/agent-active.js.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/secret-path.d.ts +16 -13
- package/payload/platform/plugins/telegram/mcp/dist/lib/secret-path.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/secret-path.js +19 -23
- package/payload/platform/plugins/telegram/mcp/dist/lib/secret-path.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/webhook-url.d.ts +9 -7
- package/payload/platform/plugins/telegram/mcp/dist/lib/webhook-url.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/webhook-url.js +11 -8
- package/payload/platform/plugins/telegram/mcp/dist/lib/webhook-url.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/message.d.ts +4 -0
- package/payload/platform/plugins/telegram/mcp/dist/tools/message.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/message.js +13 -3
- package/payload/platform/plugins/telegram/mcp/dist/tools/message.js.map +1 -1
- package/payload/platform/plugins/telegram/references/setup-guide.md +16 -8
- package/payload/platform/plugins/telegram/skills/configure/SKILL.md +30 -32
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-census.d.ts +51 -4
- package/payload/platform/services/claude-session-manager/dist/pty-census.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-census.js +60 -10
- package/payload/platform/services/claude-session-manager/dist/pty-census.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.d.ts +64 -1
- package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.js +189 -6
- package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.js.map +1 -1
- package/payload/server/server.js +510 -240
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
import { readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
1
3
|
import { scheduleList } from "../tools/schedule-list.js";
|
|
4
|
+
import { readWatermarks } from "../tools/scheduling-gate.js";
|
|
5
|
+
import { resolveConnector } from "./connector-freebusy.js";
|
|
2
6
|
/**
|
|
3
7
|
* Task 2100 — the standing check for meeting visibility.
|
|
4
8
|
*
|
|
@@ -30,4 +34,299 @@ export async function auditScheduleVisibility(session, accountId, list = schedul
|
|
|
30
34
|
console.error(`[schedule-audit] account=${accountId} meetings=${meetings} listable=${listable} invisible=${invisible}`);
|
|
31
35
|
return { meetings, listable, invisible };
|
|
32
36
|
}
|
|
37
|
+
/** Neo4j integers arrive as `{low, high}` objects; normalise to a JS number. */
|
|
38
|
+
function num(raw) {
|
|
39
|
+
if (typeof raw === "number")
|
|
40
|
+
return raw;
|
|
41
|
+
if (raw && typeof raw.toNumber === "function") {
|
|
42
|
+
return raw.toNumber();
|
|
43
|
+
}
|
|
44
|
+
return Number(raw ?? 0);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Task 2378 — the gate stuck on false.
|
|
48
|
+
*
|
|
49
|
+
* This is the gate's no-event blind spot, and it is invisible by construction. A
|
|
50
|
+
* gate that answers `false` on every fire emits a skip every fire and looks
|
|
51
|
+
* healthy on every surface: the routine is `scheduled`, `nextRun` keeps
|
|
52
|
+
* advancing, the run records close clean, and no error is written anywhere. The
|
|
53
|
+
* only symptom is silence from a routine that was DESIGNED to be silent, which
|
|
54
|
+
* is why no fire-site line can report it and why it needs a standing check.
|
|
55
|
+
*
|
|
56
|
+
* Always-skipping means every trailing-24h `:RoutineRun` for that event closed
|
|
57
|
+
* `gated`, and there are at least 24 of them. Twenty-four is one day at hourly,
|
|
58
|
+
* the cadence the routine that produced this task held for 15 consecutive days.
|
|
59
|
+
* A genuinely quiet 24 hours does trip it: it WARNs, nothing acts on it, and
|
|
60
|
+
* that is the safe direction — the alternative never sees a permanently muted
|
|
61
|
+
* routine at all.
|
|
62
|
+
*
|
|
63
|
+
* `checked=0` is emitted every tick, including on an install with no gated
|
|
64
|
+
* routines. A check that goes quiet when healthy cannot be distinguished from
|
|
65
|
+
* one that has stopped running.
|
|
66
|
+
*
|
|
67
|
+
* Never throws (honours the sweep's contract).
|
|
68
|
+
*/
|
|
69
|
+
export async function auditGateAlwaysSkipping(driver, localAccountIds, nowMs = Date.now()) {
|
|
70
|
+
if (localAccountIds.length === 0)
|
|
71
|
+
return;
|
|
72
|
+
const windowStart = new Date(nowMs - 24 * 60 * 60 * 1000).toISOString();
|
|
73
|
+
const session = driver.session();
|
|
74
|
+
try {
|
|
75
|
+
const res = await session.run(
|
|
76
|
+
// Scoped to `scheduled` gated events, the same predicate every sibling
|
|
77
|
+
// "this row is broken" audit uses: a suspended or cancelled routine is
|
|
78
|
+
// silent because someone asked it to be, and counting it would park this
|
|
79
|
+
// number above zero for ever and kill the alarm.
|
|
80
|
+
`MATCH (e:Event)
|
|
81
|
+
WHERE e.accountId IN $localAccountIds
|
|
82
|
+
AND e.eventStatus = 'scheduled'
|
|
83
|
+
AND e.gatePlugin IS NOT NULL
|
|
84
|
+
AND e.gateTool IS NOT NULL
|
|
85
|
+
OPTIONAL MATCH (r:RoutineRun)-[:RUN_OF]->(e)
|
|
86
|
+
WHERE r.startedAt >= $windowStart
|
|
87
|
+
RETURN e.eventId AS eventId, e.accountId AS accountId,
|
|
88
|
+
count(r) AS runs,
|
|
89
|
+
sum(CASE WHEN r.status = 'gated' THEN 1 ELSE 0 END) AS gatedRuns`, { localAccountIds, windowStart });
|
|
90
|
+
let checked = 0;
|
|
91
|
+
const offenders = [];
|
|
92
|
+
for (const rec of res.records) {
|
|
93
|
+
checked++;
|
|
94
|
+
const runs = num(rec.get("runs"));
|
|
95
|
+
const gatedRuns = num(rec.get("gatedRuns"));
|
|
96
|
+
if (runs >= 24 && gatedRuns === runs) {
|
|
97
|
+
offenders.push({
|
|
98
|
+
eventId: rec.get("eventId"),
|
|
99
|
+
accountId: rec.get("accountId"),
|
|
100
|
+
gatedRuns,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
console.error(`[schedule-audit] op=gate-census checked=${checked} alwaysSkipping=${offenders.length} ` +
|
|
105
|
+
`ok=${offenders.length === 0}`);
|
|
106
|
+
for (const o of offenders) {
|
|
107
|
+
console.error(`[schedule-audit] op=gate-always-skipping eventId=${o.eventId.slice(0, 8)} ` +
|
|
108
|
+
`acct=${o.accountId.slice(0, 8)} gatedRuns=${o.gatedRuns} sinceHours=24`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
console.error(`[schedule-audit] op=gate-census-error detail=${err instanceof Error ? err.message : String(err)}`);
|
|
113
|
+
}
|
|
114
|
+
finally {
|
|
115
|
+
try {
|
|
116
|
+
await session.close();
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// ignore
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Task 2378 — the watermark that stopped advancing.
|
|
125
|
+
*
|
|
126
|
+
* The opposite failure to the one above, and just as quiet. Only the agent turn
|
|
127
|
+
* commits a watermark, at the end of a successful run. If those commits stop —
|
|
128
|
+
* a prompt edited back to its pre-gate wording, a turn that always dies before
|
|
129
|
+
* its last step — the gate keeps comparing against a frozen position, reports
|
|
130
|
+
* work on every fire, and the routine runs every time. There is no error, no
|
|
131
|
+
* missing line and no failed call; it simply reads as a busy week while the
|
|
132
|
+
* whole saving is gone.
|
|
133
|
+
*
|
|
134
|
+
* `op=commit` is emitted only on a successful commit, so its ABSENCE is the
|
|
135
|
+
* signal, and an absence is not greppable on its own. This is the greppable
|
|
136
|
+
* form of it. Together with the always-skipping check it bounds the same 24-hour
|
|
137
|
+
* window from opposite ends: one catches a gate that never passes, this one a
|
|
138
|
+
* gate that never stops passing.
|
|
139
|
+
*
|
|
140
|
+
* Only a routine that has actually fired is judged. A gate bound minutes ago has
|
|
141
|
+
* no commit yet and is not late.
|
|
142
|
+
*
|
|
143
|
+
* `acct=` lines are emitted every tick including when nothing is late. Never
|
|
144
|
+
* throws (honours the sweep's contract).
|
|
145
|
+
*/
|
|
146
|
+
export async function auditGateWatermarkAge(driver, localAccountIds, platformRoot, nowMs = Date.now()) {
|
|
147
|
+
if (localAccountIds.length === 0)
|
|
148
|
+
return;
|
|
149
|
+
const session = driver.session();
|
|
150
|
+
try {
|
|
151
|
+
const res = await session.run(`MATCH (e:Event)
|
|
152
|
+
WHERE e.accountId IN $localAccountIds
|
|
153
|
+
AND e.eventStatus = 'scheduled'
|
|
154
|
+
AND e.gatePlugin IS NOT NULL
|
|
155
|
+
AND e.gateTool IS NOT NULL
|
|
156
|
+
AND e.lastTriggered IS NOT NULL
|
|
157
|
+
RETURN e.eventId AS eventId, e.accountId AS accountId`, { localAccountIds });
|
|
158
|
+
// Worst age per account, so one line per account answers "is any gate on
|
|
159
|
+
// this account running blind". Driven by localAccountIds below, not by the
|
|
160
|
+
// result rows: an account with no gated routines emits `-`, and skipping it
|
|
161
|
+
// would make "nothing to check" and "not looked at" the same silence.
|
|
162
|
+
const worst = new Map();
|
|
163
|
+
for (const rec of res.records) {
|
|
164
|
+
const eventId = rec.get("eventId");
|
|
165
|
+
const accountId = rec.get("accountId");
|
|
166
|
+
const marks = readWatermarks(eventId, platformRoot);
|
|
167
|
+
// A routine that has fired and never committed is maximally late, not
|
|
168
|
+
// exempt: never having committed is the state this check exists to find.
|
|
169
|
+
const ageHours = marks.lastCommitAt && !Number.isNaN(Date.parse(marks.lastCommitAt))
|
|
170
|
+
? (nowMs - Date.parse(marks.lastCommitAt)) / 3_600_000
|
|
171
|
+
: Number.POSITIVE_INFINITY;
|
|
172
|
+
const current = worst.get(accountId);
|
|
173
|
+
if (current === undefined || ageHours > current) {
|
|
174
|
+
worst.set(accountId, ageHours);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
for (const accountId of localAccountIds) {
|
|
178
|
+
const age = worst.get(accountId);
|
|
179
|
+
if (age === undefined) {
|
|
180
|
+
console.error(`[schedule-audit] op=gate-watermark-age acct=${accountId.slice(0, 8)} ` +
|
|
181
|
+
`lastCommitAgeHours=- ok=true`);
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
const ok = age <= 24;
|
|
185
|
+
console.error(`[schedule-audit] op=gate-watermark-age acct=${accountId.slice(0, 8)} ` +
|
|
186
|
+
`lastCommitAgeHours=${age === Number.POSITIVE_INFINITY ? "never" : Math.round(age)} ok=${ok}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
catch (err) {
|
|
190
|
+
console.error(`[schedule-audit] op=gate-watermark-age-error detail=${err instanceof Error ? err.message : String(err)}`);
|
|
191
|
+
}
|
|
192
|
+
finally {
|
|
193
|
+
try {
|
|
194
|
+
await session.close();
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
// ignore
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* The next state for one account.
|
|
203
|
+
*
|
|
204
|
+
* The `none` instant survives consecutive `none` observations and is discarded
|
|
205
|
+
* the moment a connector returns, which is what makes `noneForHours` the length
|
|
206
|
+
* of the CURRENT run rather than a cumulative total. A recovery followed by a
|
|
207
|
+
* fresh revocation therefore starts counting again from zero, which is correct:
|
|
208
|
+
* the operator's exposure began when the calendar went away this time.
|
|
209
|
+
*/
|
|
210
|
+
export function nextConnectorState(prev, connector, nowMs) {
|
|
211
|
+
if (connector !== "none")
|
|
212
|
+
return { connector, noneSinceMs: null };
|
|
213
|
+
return { connector: "none", noneSinceMs: prev?.noneSinceMs ?? nowMs };
|
|
214
|
+
}
|
|
215
|
+
/** Whole hours the account has resolved `none` without interruption. */
|
|
216
|
+
export function noneForHours(entry, nowMs) {
|
|
217
|
+
if (entry.noneSinceMs === null)
|
|
218
|
+
return 0;
|
|
219
|
+
return Math.max(0, Math.floor((nowMs - entry.noneSinceMs) / 3_600_000));
|
|
220
|
+
}
|
|
221
|
+
/** Read the persisted run lengths. An absent or corrupt file reads as empty,
|
|
222
|
+
* which restarts every account's clock — it can delay an alarm by 24 hours but
|
|
223
|
+
* never raises a false one. A corrupt file is reported, because it is the cause
|
|
224
|
+
* of a fleet-wide clock reset and that reset must carry its own explanation. */
|
|
225
|
+
function readConnectorState(path) {
|
|
226
|
+
let raw;
|
|
227
|
+
try {
|
|
228
|
+
raw = readFileSync(path, "utf-8");
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
return {}; // absent — the normal first-run case
|
|
232
|
+
}
|
|
233
|
+
try {
|
|
234
|
+
const parsed = JSON.parse(raw);
|
|
235
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
236
|
+
}
|
|
237
|
+
catch (err) {
|
|
238
|
+
console.error(`[schedule-audit] op=connector-state result=unreadable path=${path} ` +
|
|
239
|
+
`reason=${JSON.stringify(err.message)} impact=every-account-clock-reset`);
|
|
240
|
+
return {};
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/** Written to a temp path and renamed, so a kill mid-write cannot leave
|
|
244
|
+
* truncated JSON that reads back as empty and resets every clock. */
|
|
245
|
+
function writeConnectorState(path, state) {
|
|
246
|
+
const tmp = `${path}.tmp`;
|
|
247
|
+
try {
|
|
248
|
+
writeFileSync(tmp, JSON.stringify(state));
|
|
249
|
+
renameSync(tmp, path);
|
|
250
|
+
}
|
|
251
|
+
catch (err) {
|
|
252
|
+
console.error(`[schedule-audit] op=connector-state result=write-failed path=${path} ` +
|
|
253
|
+
`reason=${JSON.stringify(err.message)} impact=none-run-length-never-grows`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Task 2381 — the standing half of the connector-resolution signal.
|
|
258
|
+
*
|
|
259
|
+
* A revoked or expired authorisation makes every fire of the busy sync write an
|
|
260
|
+
* empty busy list. The action succeeds, the `:RoutineRun` closes clean, nothing
|
|
261
|
+
* errors, and the visible result is a booking page offering slots the operator is
|
|
262
|
+
* not free for. The per-fire `[connector-busy-sync] op=resolved connector=none`
|
|
263
|
+
* line IS emitted every fire, but one healthy-looking line among thousands is not
|
|
264
|
+
* a signal — this is what turns a persistent `none` into one.
|
|
265
|
+
*
|
|
266
|
+
* `ok=false` when an account has resolved `none` for more than 24 consecutive
|
|
267
|
+
* hours WHILE holding a scheduled busy-sync routine. An account with genuinely no
|
|
268
|
+
* calendar and no such routine reports a growing `noneForHours` and `ok=true`:
|
|
269
|
+
* nothing is scheduled to use a connector it does not have, so there is no
|
|
270
|
+
* exposure to report.
|
|
271
|
+
*
|
|
272
|
+
* The routine predicate matches the converted `action` form and the agent form
|
|
273
|
+
* that precedes it, so the audit is live from the day it ships rather than from
|
|
274
|
+
* the day the conversion lands.
|
|
275
|
+
*
|
|
276
|
+
* One line per local account per tick, including every healthy one. A check that
|
|
277
|
+
* goes quiet when healthy cannot be distinguished from one that has stopped
|
|
278
|
+
* running. Never throws (honours the sweep's contract).
|
|
279
|
+
*/
|
|
280
|
+
export async function auditConnectorResolution(driver, localAccountIds, accountsDir, statePath, nowMs) {
|
|
281
|
+
if (localAccountIds.length === 0)
|
|
282
|
+
return;
|
|
283
|
+
const session = driver.session();
|
|
284
|
+
let withSyncRoutine;
|
|
285
|
+
try {
|
|
286
|
+
const res = await session.run(`MATCH (e:Event)
|
|
287
|
+
WHERE e.accountId IN $localAccountIds
|
|
288
|
+
AND e.eventStatus = 'scheduled'
|
|
289
|
+
AND ( e.actionTool = 'schedule-connector-busy-sync'
|
|
290
|
+
OR e.agentPrompt CONTAINS 'schedule-connector-busy-sync' )
|
|
291
|
+
RETURN DISTINCT e.accountId AS accountId`, { localAccountIds });
|
|
292
|
+
withSyncRoutine = new Set(res.records.map((r) => r.get("accountId")));
|
|
293
|
+
}
|
|
294
|
+
catch (err) {
|
|
295
|
+
console.error(`[schedule-audit] op=connector-resolution-error detail=${err instanceof Error ? err.message : String(err)}`);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
finally {
|
|
299
|
+
try {
|
|
300
|
+
await session.close();
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
// ignore
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
const state = readConnectorState(statePath);
|
|
307
|
+
// Driven by localAccountIds, not by the query result: an account resolving
|
|
308
|
+
// nothing returns no row, and skipping it would make "healthy" and "not looked
|
|
309
|
+
// at" the same silence on a multi-account box.
|
|
310
|
+
for (const accountId of localAccountIds) {
|
|
311
|
+
let connector;
|
|
312
|
+
try {
|
|
313
|
+
connector = resolveConnector(join(accountsDir, accountId)).connector;
|
|
314
|
+
}
|
|
315
|
+
catch (err) {
|
|
316
|
+
// detectCalendarConnectors throws when a connector directory exists but is
|
|
317
|
+
// unreadable. That is "the input is unknown", not "there is no connector",
|
|
318
|
+
// and reporting it as `none` would dress a real fault as the boring case.
|
|
319
|
+
console.error(`[schedule-audit] op=connector-resolution-error acct=${accountId.slice(0, 8)} ` +
|
|
320
|
+
`detail=${err instanceof Error ? err.message : String(err)}`);
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
const entry = nextConnectorState(state[accountId], connector, nowMs);
|
|
324
|
+
state[accountId] = entry;
|
|
325
|
+
const hours = noneForHours(entry, nowMs);
|
|
326
|
+
const ok = !(hours > 24 && withSyncRoutine.has(accountId));
|
|
327
|
+
console.error(`[schedule-audit] op=connector-resolution acct=${accountId.slice(0, 8)} ` +
|
|
328
|
+
`connector=${connector} noneForHours=${hours} ok=${ok}`);
|
|
329
|
+
}
|
|
330
|
+
writeConnectorState(statePath, state);
|
|
331
|
+
}
|
|
33
332
|
//# sourceMappingURL=schedule-audit.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schedule-audit.js","sourceRoot":"","sources":["../../src/lib/schedule-audit.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"schedule-audit.js","sourceRoot":"","sources":["../../src/lib/schedule-audit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate-dispatch-wiring.test.d.ts","sourceRoot":"","sources":["../../../src/scripts/__tests__/gate-dispatch-wiring.test.ts"],"names":[],"mappings":""}
|
package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/gate-dispatch-wiring.test.js
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// @vitest-environment node
|
|
2
|
+
// Task 2378 — the dispatcher wiring.
|
|
3
|
+
//
|
|
4
|
+
// `dispatchDue` and the two dispatch queries live inside a module that calls
|
|
5
|
+
// `main()` at import time, so they cannot be imported by a test. The
|
|
6
|
+
// established answer here is to pin the source, the same way
|
|
7
|
+
// `sweep-excludes-suspended.test.ts` pins the WHERE clauses it models: the
|
|
8
|
+
// decision logic is unit-tested in `lib/__tests__/gate.test.ts`, and this file
|
|
9
|
+
// asserts the facts about the wiring that no unit test can reach.
|
|
10
|
+
//
|
|
11
|
+
// Each assertion below is a claim the task makes about ORDER or ABSENCE, and
|
|
12
|
+
// order and absence are exactly what a later edit breaks silently.
|
|
13
|
+
import { describe, it, expect } from "vitest";
|
|
14
|
+
import { readFileSync } from "node:fs";
|
|
15
|
+
import { dirname, resolve } from "node:path";
|
|
16
|
+
import { fileURLToPath } from "node:url";
|
|
17
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
18
|
+
const SOURCE = readFileSync(resolve(HERE, "../check-due-events.ts"), "utf-8");
|
|
19
|
+
const at = (needle) => {
|
|
20
|
+
const i = SOURCE.indexOf(needle);
|
|
21
|
+
expect(i, `not found in check-due-events.ts: ${needle}`).toBeGreaterThan(-1);
|
|
22
|
+
return i;
|
|
23
|
+
};
|
|
24
|
+
describe("the gate props reach the dispatcher", () => {
|
|
25
|
+
it("both dispatch queries return all three", () => {
|
|
26
|
+
// Two queries: one-time and recurring. A prop selected by one and not the
|
|
27
|
+
// other would gate one path and silently not the other.
|
|
28
|
+
for (const prop of ["e.gatePlugin AS gatePlugin", "e.gateTool AS gateTool", "e.gateArgs AS gateArgs"]) {
|
|
29
|
+
expect(SOURCE.split(prop).length - 1).toBe(2);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
it("only the recurring loop resolves a gate", () => {
|
|
33
|
+
// A one-time row is already `eventStatus = 'due'` by the time dispatchDue
|
|
34
|
+
// runs, so it will never be selected again and a skip there is permanent.
|
|
35
|
+
// Dropping a routine for good is the opposite of what the gate is for.
|
|
36
|
+
expect(SOURCE.split("const gate = chooseGate({").length - 1).toBe(1);
|
|
37
|
+
});
|
|
38
|
+
it("the recurring call site passes the gate and the one-time call site passes null", () => {
|
|
39
|
+
expect(SOURCE.split("driver, fields, runId, gate)").length - 1).toBe(1);
|
|
40
|
+
expect(SOURCE.split("driver, fields, runId, null)").length - 1).toBe(1);
|
|
41
|
+
});
|
|
42
|
+
it("the one-time loop's null is explained, so a later edit does not read it as an oversight", () => {
|
|
43
|
+
const loop = SOURCE.slice(at("--- One-time events:"), at("--- Recurring events:"));
|
|
44
|
+
expect(loop).toContain("a one-time event is NEVER gated");
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
describe("ordering", () => {
|
|
48
|
+
it("the recurring loop advances nextRun BEFORE it calls dispatchDue", () => {
|
|
49
|
+
// The advance is the anti-double-fire guard, and the gate runs inside
|
|
50
|
+
// dispatchDue. Gating first would let a gated fire be re-selected on the
|
|
51
|
+
// next tick, replaying the check until it happened to pass.
|
|
52
|
+
//
|
|
53
|
+
// Sliced to the recurring loop rather than compared across the whole file:
|
|
54
|
+
// `dispatchDue` is DEFINED near the top and CALLED near the bottom, so a
|
|
55
|
+
// whole-file index comparison measures declaration order, not the order
|
|
56
|
+
// anything runs in.
|
|
57
|
+
const loop = SOURCE.slice(at("--- Recurring events:"), at("--- Suspended routines skipped"));
|
|
58
|
+
expect(loop.indexOf("SET e.lastTriggered = $now")).toBeGreaterThan(-1);
|
|
59
|
+
expect(loop.indexOf("SET e.lastTriggered = $now")).toBeLessThan(loop.indexOf("await dispatchDue("));
|
|
60
|
+
});
|
|
61
|
+
it("the one-time loop marks the row due before it calls dispatchDue", () => {
|
|
62
|
+
const loop = SOURCE.slice(at("--- One-time events:"), at("--- Recurring events:"));
|
|
63
|
+
expect(loop.indexOf("SET e.eventStatus = 'due'")).toBeGreaterThan(-1);
|
|
64
|
+
expect(loop.indexOf("SET e.eventStatus = 'due'")).toBeLessThan(loop.indexOf("await dispatchDue("));
|
|
65
|
+
});
|
|
66
|
+
it("the gate is evaluated BEFORE the inject", () => {
|
|
67
|
+
expect(at("await evaluateGate(")).toBeLessThan(at("await dispatchAgentTurn("));
|
|
68
|
+
});
|
|
69
|
+
it("the gate is inside the agent branch, not before the mode is known", () => {
|
|
70
|
+
// The action rail already runs headlessly with no model, so a gate there
|
|
71
|
+
// would save nothing and would need its own outcome vocabulary.
|
|
72
|
+
expect(at('if (mode.kind === "agent")')).toBeLessThan(at("await evaluateGate("));
|
|
73
|
+
expect(at("await evaluateGate(")).toBeLessThan(at('if (mode.kind === "action")'));
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
describe("the no-work branch", () => {
|
|
77
|
+
const branch = SOURCE.slice(at('if (verdict.kind === "no-work")'), at("const accountsDir"));
|
|
78
|
+
it("returns before reaching the inject", () => {
|
|
79
|
+
expect(branch).toContain("return false;");
|
|
80
|
+
expect(branch).not.toContain("dispatchAgentTurn");
|
|
81
|
+
});
|
|
82
|
+
it("writes lastDispatchResult = 'gated' and the timestamp", () => {
|
|
83
|
+
expect(branch).toContain("e.lastDispatchResult = 'gated'");
|
|
84
|
+
expect(branch).toContain("e.lastDispatchAt = $now");
|
|
85
|
+
});
|
|
86
|
+
it("closes the run record as gated, so the fires-without-records audit stays reconciled", () => {
|
|
87
|
+
expect(branch).toContain('outcome: "gated"');
|
|
88
|
+
});
|
|
89
|
+
it("emits op=skipped reason=no-work", () => {
|
|
90
|
+
expect(branch).toContain("op=skipped");
|
|
91
|
+
expect(branch).toContain("reason=no-work");
|
|
92
|
+
});
|
|
93
|
+
it("does not advance nextRun itself — the caller already did", () => {
|
|
94
|
+
expect(branch).not.toContain("e.nextRun");
|
|
95
|
+
});
|
|
96
|
+
it("swallows a Neo4j failure rather than aborting the sweep", () => {
|
|
97
|
+
expect(branch).toContain("} catch {");
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
describe("fail-open reaches the dispatch", () => {
|
|
101
|
+
it("only the no-work verdict returns early", () => {
|
|
102
|
+
// If a later edit widened this comparison — to `!== "has-work"`, say — every
|
|
103
|
+
// unreadable gate would silently mute its routine, which is the inversion
|
|
104
|
+
// this whole design guards against.
|
|
105
|
+
expect(SOURCE).toContain('if (verdict.kind === "no-work")');
|
|
106
|
+
expect(SOURCE).not.toContain('verdict.kind !== "has-work"');
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
describe("the ungated path is unchanged", () => {
|
|
110
|
+
it("the gate block is entered only when a gate is present", () => {
|
|
111
|
+
expect(at("if (gate) {")).toBeLessThan(at("await evaluateGate("));
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
describe("standing audits are called every tick", () => {
|
|
115
|
+
it("both gate audits are invoked from the audit block", () => {
|
|
116
|
+
expect(SOURCE).toContain("await auditGateAlwaysSkipping(driver, localAccountIds)");
|
|
117
|
+
expect(SOURCE).toContain("await auditGateWatermarkAge(driver, localAccountIds");
|
|
118
|
+
});
|
|
119
|
+
it("each is wrapped so a failure costs the tick nothing but an error line", () => {
|
|
120
|
+
expect(SOURCE).toContain("op=gate-census-error");
|
|
121
|
+
expect(SOURCE).toContain("op=gate-watermark-age-error");
|
|
122
|
+
});
|
|
123
|
+
it("they sit outside the dispatch loops, so they run on a tick with nothing due", () => {
|
|
124
|
+
expect(at("await auditFailingDispatch(")).toBeLessThan(at("await auditGateAlwaysSkipping("));
|
|
125
|
+
expect(at("await auditGateWatermarkAge(")).toBeLessThan(at("await reconcilePluginLifecycles("));
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
describe("the extracted transport", () => {
|
|
129
|
+
it("dispatchAction calls the shared callPluginTool rather than its own client", () => {
|
|
130
|
+
expect(SOURCE).toContain("await callPluginTool(actionPlugin, actionTool, actionArgs, eventAccountId)");
|
|
131
|
+
// The inline client is gone: two transports would be two places for the
|
|
132
|
+
// timeout, the ACCOUNT_ID scoping and the stderr capture to drift.
|
|
133
|
+
expect(SOURCE).not.toContain("new StdioClientTransport(");
|
|
134
|
+
expect(SOURCE).not.toContain('new Client({ name: "event-dispatcher"');
|
|
135
|
+
});
|
|
136
|
+
it("a timeout is still recorded as timeout, not as a generic error", () => {
|
|
137
|
+
expect(SOURCE).toContain("err instanceof PluginToolError");
|
|
138
|
+
expect(SOURCE).toContain('timedOut = err.kind === "timeout"');
|
|
139
|
+
expect(SOURCE).toContain('const outcome = timedOut ? "timeout" : "error"');
|
|
140
|
+
});
|
|
141
|
+
it("child stderr is still attached to the failure record", () => {
|
|
142
|
+
expect(SOURCE).toContain("childStderr = err.childStderr");
|
|
143
|
+
expect(SOURCE).toContain("Child stderr:");
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
//# sourceMappingURL=gate-dispatch-wiring.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate-dispatch-wiring.test.js","sourceRoot":"","sources":["../../../src/scripts/__tests__/gate-dispatch-wiring.test.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,qCAAqC;AACrC,EAAE;AACF,6EAA6E;AAC7E,qEAAqE;AACrE,6DAA6D;AAC7D,2EAA2E;AAC3E,+EAA+E;AAC/E,kEAAkE;AAClE,EAAE;AACF,6EAA6E;AAC7E,mEAAmE;AACnE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACrD,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,wBAAwB,CAAC,EAAE,OAAO,CAAC,CAAC;AAE9E,MAAM,EAAE,GAAG,CAAC,MAAc,EAAU,EAAE;IACpC,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACjC,MAAM,CAAC,CAAC,EAAE,qCAAqC,MAAM,EAAE,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7E,OAAO,CAAC,CAAC;AACX,CAAC,CAAC;AAEF,QAAQ,CAAC,qCAAqC,EAAE,GAAG,EAAE;IACnD,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,0EAA0E;QAC1E,wDAAwD;QACxD,KAAK,MAAM,IAAI,IAAI,CAAC,4BAA4B,EAAE,wBAAwB,EAAE,wBAAwB,CAAC,EAAE,CAAC;YACtG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,0EAA0E;QAC1E,0EAA0E;QAC1E,uEAAuE;QACvE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gFAAgF,EAAE,GAAG,EAAE;QACxF,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yFAAyF,EAAE,GAAG,EAAE;QACjG,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAAC,EAAE,EAAE,CAAC,uBAAuB,CAAC,CAAC,CAAC;QACnF,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,iCAAiC,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;IACxB,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,sEAAsE;QACtE,yEAAyE;QACzE,4DAA4D;QAC5D,EAAE;QACF,2EAA2E;QAC3E,yEAAyE;QACzE,wEAAwE;QACxE,oBAAoB;QACpB,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAAC,EAAE,EAAE,CAAC,gCAAgC,CAAC,CAAC,CAAC;QAC7F,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QACvE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAC,CAAC,YAAY,CAC7D,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,CACnC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAAC,EAAE,EAAE,CAAC,uBAAuB,CAAC,CAAC,CAAC;QACnF,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QACtE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC;IACrG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,EAAE,CAAC,qBAAqB,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,0BAA0B,CAAC,CAAC,CAAC;IACjF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAC3E,yEAAyE;QACzE,gEAAgE;QAChE,MAAM,CAAC,EAAE,CAAC,4BAA4B,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,qBAAqB,CAAC,CAAC,CAAC;QACjF,MAAM,CAAC,EAAE,CAAC,qBAAqB,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,6BAA6B,CAAC,CAAC,CAAC;IACpF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,iCAAiC,CAAC,EAAE,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAE5F,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAC;QAC3D,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,yBAAyB,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qFAAqF,EAAE,GAAG,EAAE;QAC7F,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QACvC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC9C,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,6EAA6E;QAC7E,0EAA0E;QAC1E,oCAAoC;QACpC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,iCAAiC,CAAC,CAAC;QAC5D,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;IAC7C,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,qBAAqB,CAAC,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,uCAAuC,EAAE,GAAG,EAAE;IACrD,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,wDAAwD,CAAC,CAAC;QACnF,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,qDAAqD,CAAC,CAAC;IAClF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uEAAuE,EAAE,GAAG,EAAE;QAC/E,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;QACjD,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,GAAG,EAAE;QACrF,MAAM,CAAC,EAAE,CAAC,6BAA6B,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,gCAAgC,CAAC,CAAC,CAAC;QAC7F,MAAM,CAAC,EAAE,CAAC,8BAA8B,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,kCAAkC,CAAC,CAAC,CAAC;IAClG,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,2EAA2E,EAAE,GAAG,EAAE;QACnF,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,4EAA4E,CAAC,CAAC;QACvG,wEAAwE;QACxE,mEAAmE;QACnE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,2BAA2B,CAAC,CAAC;QAC1D,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,uCAAuC,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAC;QAC3D,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,mCAAmC,CAAC,CAAC;QAC9D,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,gDAAgD,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,+BAA+B,CAAC,CAAC;QAC1D,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -36,6 +36,33 @@ export declare function chooseDispatchMode(fields: {
|
|
|
36
36
|
actionTool: string | null;
|
|
37
37
|
actionArgs: string | null;
|
|
38
38
|
}): DispatchMode;
|
|
39
|
+
/**
|
|
40
|
+
* Task 2378 — the precondition a gated routine must satisfy before the model is
|
|
41
|
+
* invoked. Three optional `:Event` props, handled exactly as `actionArgs` is: a
|
|
42
|
+
* JSON string passed to the tool verbatim, never interpreted here.
|
|
43
|
+
*/
|
|
44
|
+
export interface EventGate {
|
|
45
|
+
plugin: string;
|
|
46
|
+
tool: string;
|
|
47
|
+
args: string | null;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Task 2378 — resolve the gate from its selected node fields.
|
|
51
|
+
*
|
|
52
|
+
* Plugin AND tool, mirroring the `action` branch of `chooseDispatchMode`: a row
|
|
53
|
+
* carrying one without the other names nothing callable, and treating it as a
|
|
54
|
+
* gate would fail open on every fire while reading as configured. `args` is
|
|
55
|
+
* optional for the same reason `actionArgs` is — a check taking no arguments is
|
|
56
|
+
* legitimate.
|
|
57
|
+
*
|
|
58
|
+
* A gate is evaluated only for an agent-mode dispatch. Write-time validation
|
|
59
|
+
* refuses one on an action-mode event, so nothing here has to re-decide that.
|
|
60
|
+
*/
|
|
61
|
+
export declare function chooseGate(fields: {
|
|
62
|
+
gatePlugin: string | null;
|
|
63
|
+
gateTool: string | null;
|
|
64
|
+
gateArgs: string | null;
|
|
65
|
+
}): EventGate | null;
|
|
39
66
|
/**
|
|
40
67
|
* Task 2130 — which missing field made `chooseDispatchMode` resolve to
|
|
41
68
|
* `{kind:'none'}`, for the `[check-due] op=dispatch-skipped` line.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-turn-dispatch.d.ts","sourceRoot":"","sources":["../../src/scripts/agent-turn-dispatch.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"agent-turn-dispatch.d.ts","sourceRoot":"","sources":["../../src/scripts/agent-turn-dispatch.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,6 +28,24 @@ export function chooseDispatchMode(fields) {
|
|
|
28
28
|
}
|
|
29
29
|
return { kind: "none" };
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Task 2378 — resolve the gate from its selected node fields.
|
|
33
|
+
*
|
|
34
|
+
* Plugin AND tool, mirroring the `action` branch of `chooseDispatchMode`: a row
|
|
35
|
+
* carrying one without the other names nothing callable, and treating it as a
|
|
36
|
+
* gate would fail open on every fire while reading as configured. `args` is
|
|
37
|
+
* optional for the same reason `actionArgs` is — a check taking no arguments is
|
|
38
|
+
* legitimate.
|
|
39
|
+
*
|
|
40
|
+
* A gate is evaluated only for an agent-mode dispatch. Write-time validation
|
|
41
|
+
* refuses one on an action-mode event, so nothing here has to re-decide that.
|
|
42
|
+
*/
|
|
43
|
+
export function chooseGate(fields) {
|
|
44
|
+
if (fields.gatePlugin && fields.gateTool) {
|
|
45
|
+
return { plugin: fields.gatePlugin, tool: fields.gateTool, args: fields.gateArgs };
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
31
49
|
/**
|
|
32
50
|
* Task 2130 — which missing field made `chooseDispatchMode` resolve to
|
|
33
51
|
* `{kind:'none'}`, for the `[check-due] op=dispatch-skipped` line.
|