@theronap/agnoclast-mcp 0.9.164 → 0.9.166
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/lib/server.mjs +61 -4
- package/package.json +1 -1
package/lib/server.mjs
CHANGED
|
@@ -285,6 +285,48 @@ function renderArrival(payload) {
|
|
|
285
285
|
` — \`staged_records\` lists them. Not offered to you, just counted; \`ignore_arrivals\` if this is noise right now.`
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
+
function renderSettling(payload) {
|
|
289
|
+
const feed = payload?.settling
|
|
290
|
+
const offers = Array.isArray(feed?.offers) ? feed.offers : []
|
|
291
|
+
if (!offers.length) return ''
|
|
292
|
+
const total = Number(feed?.total ?? offers.length)
|
|
293
|
+
|
|
294
|
+
const lines = offers.map((x) => {
|
|
295
|
+
const why = x.via?.length ? ` — matches ${x.via.map((v) => `\`${v}\``).join(', ')}` : ''
|
|
296
|
+
// Looks without claims is evidence about the UNIT, not about the sessions that walked away.
|
|
297
|
+
const looked = x.looks > 0 ? ` [looked at ${x.looks}x, still unclaimed]` : ''
|
|
298
|
+
return ` - ${x.source} · ${x.hoursAgo}h ago · ${x.intakeItemId}${why}${looked}`
|
|
299
|
+
})
|
|
300
|
+
|
|
301
|
+
// ⚠ SAY THE TRUE TOTAL, NOT THE PAGE SIZE. Measured 2026-09-22: one identifier matched 113 settling
|
|
302
|
+
// units against a cap of 12. A block that says "here are 12" when there are 113 is claiming
|
|
303
|
+
// certainty it does not have — and renders identically every turn, which teaches the reader that
|
|
304
|
+
// it never changes and can be skipped.
|
|
305
|
+
const more = total > offers.length
|
|
306
|
+
? `\n— Showing ${offers.length} of ${total}. \`intake_changes\` lists the rest; this is a sample, not the queue.`
|
|
307
|
+
: ''
|
|
308
|
+
|
|
309
|
+
// ⚠ CONTENTION IS STATED, exactly as the record nudge states `k`. Measured the same day: THREE live
|
|
310
|
+
// sessions each matched the SAME 113 units on one identifier. Silent about that, each would claim
|
|
311
|
+
// the same units and learn about the race from a failed lease.
|
|
312
|
+
const maxHolders = offers.reduce((m, x) => Math.max(m, Number(x.holders ?? 1)), 1)
|
|
313
|
+
const who = maxHolders > 1
|
|
314
|
+
? `\n— ⚠ ${maxHolders} live sessions of yours hold a matching identifier, so these are offered to all of them. \`intake_claim\` takes a lease — claim before you work, not after, or two sessions judge the same arrival.`
|
|
315
|
+
: `\n— No other live session of yours holds a matching identifier, so nobody else is looking at these.`
|
|
316
|
+
|
|
317
|
+
return `\n\n⚡ ARRIVALS SETTLING — yours alone, and no one else can see these yet:\n${lines.join('\n')}\n` +
|
|
318
|
+
`— These are unjudged ARRIVALS, not records. Since automatic materialization was deleted, nothing files them for you.\n` +
|
|
319
|
+
`— \`intake_look <id>\` reads the full body without claiming it — looking is free, non-exclusive and logged, so look rather than guess from the headline.\n` +
|
|
320
|
+
// ⚠ NAME THE EXACT CALL, INCLUDING THE ARRAY. This line used to read "Then `intake_claim` and
|
|
321
|
+
// `intake_materialize`" straight after a list of ids, which reads as `intake_claim <id>`. It is not:
|
|
322
|
+
// the parameter is `intakeItemIds`, an ARRAY, and on 2026-09-22 following this very sentence took a
|
|
323
|
+
// lease on ten unrelated units. The singular is accepted now, but an offer must still state the call
|
|
324
|
+
// that acts on the thing being offered — a reader should not have to consult a schema to use a nudge.
|
|
325
|
+
`— Then \`intake_claim {intakeItemIds: ["<id>"]}\` to take a lease on THAT unit (the array is required; without an id you claim the head of the queue instead), then \`intake_materialize\` into the brain and pages it belongs to — or \`intake_discard\`, or \`intake_defer\` with a question when only the owner can decide.` +
|
|
326
|
+
more + who +
|
|
327
|
+
`\n— If none are yours, leave them: they stay settling for your other sessions, and become everyone's business once the window closes.`
|
|
328
|
+
}
|
|
329
|
+
|
|
288
330
|
function renderNudge(payload) {
|
|
289
331
|
const n = Array.isArray(payload?.nudge) ? payload.nudge : []
|
|
290
332
|
if (!n.length) return ''
|
|
@@ -945,6 +987,17 @@ function renderNudge(payload) {
|
|
|
945
987
|
claimKind: z.enum(['relevance', 'cleanup']).optional().describe('default relevance'),
|
|
946
988
|
limit: z.number().optional().describe('max items (default 10). Ignored when intakeItemIds is given.'),
|
|
947
989
|
leaseMinutes: z.number().optional().describe('lease length in minutes, 5-60 (default 30). Prefer intake_look for read-only inspection — a short lease is only for briefly exclusive work.'),
|
|
990
|
+
// 🔴 SINGULAR ACCEPTED, AND NOT AS A CONVENIENCE. Every sibling verb takes `intakeItemId`:
|
|
991
|
+
// intake_look, intake_materialize, intake_release, intake_defer, intake_discard. This one
|
|
992
|
+
// alone was plural, so the natural singular was NOT IN THE SCHEMA and was silently dropped
|
|
993
|
+
// — and the fallback is not an error, it is claiming the head of the queue. On 2026-09-22 a
|
|
994
|
+
// session offered one unit by the settling block called `intake_claim {intakeItemId}` and
|
|
995
|
+
// took a 30-minute lease on TEN unrelated units belonging to other sessions' work. A typo
|
|
996
|
+
// that becomes a side effect is worse than a typo that fails.
|
|
997
|
+
intakeItemId: z.string().optional().describe(
|
|
998
|
+
'a single unit to claim — the same thing as intakeItemIds with one element. Accepted because ' +
|
|
999
|
+
'every other intake verb spells it this way.',
|
|
1000
|
+
),
|
|
948
1001
|
intakeItemIds: z.array(z.string()).optional().describe(
|
|
949
1002
|
'claim these specific units instead of the head of the queue (max 50). Without it you get FIFO, ' +
|
|
950
1003
|
'so reaching one known unit means claiming everything ahead of it. Ids come from intake_changes ' +
|
|
@@ -956,7 +1009,11 @@ function renderNudge(payload) {
|
|
|
956
1009
|
),
|
|
957
1010
|
},
|
|
958
1011
|
},
|
|
959
|
-
async ({ claimKind, limit, intakeItemIds, leaseMinutes }) => {
|
|
1012
|
+
async ({ claimKind, limit, intakeItemId, intakeItemIds, leaseMinutes }) => {
|
|
1013
|
+
// Merge the two spellings before anything else looks at them. Passing both is not an error —
|
|
1014
|
+
// the union is what the caller plainly meant.
|
|
1015
|
+
const ids = [...new Set([...(intakeItemIds ?? []), ...(intakeItemId ? [intakeItemId] : [])])]
|
|
1016
|
+
intakeItemIds = ids.length ? ids : undefined
|
|
960
1017
|
const res = await fetchCortex(`${BASE}/api/intake/claim`, {
|
|
961
1018
|
method: 'POST',
|
|
962
1019
|
headers: { Authorization: `Bearer ${TOKEN}`, 'Content-Type': 'application/json' },
|
|
@@ -1389,7 +1446,7 @@ function renderNudge(payload) {
|
|
|
1389
1446
|
throw new Error(classify(res.status, res.headers.get('content-type'), body, res.headers.get('x-vercel-id')).message)
|
|
1390
1447
|
}
|
|
1391
1448
|
const payload = await res.json()
|
|
1392
|
-
return { content: [{ type: 'text', text: formatGrepHits(payload, query) + renderArrival(payload) + renderNudge(payload) }] }
|
|
1449
|
+
return { content: [{ type: 'text', text: formatGrepHits(payload, query) + renderArrival(payload) + renderNudge(payload) + renderSettling(payload) }] }
|
|
1393
1450
|
},
|
|
1394
1451
|
)
|
|
1395
1452
|
|
|
@@ -1698,7 +1755,7 @@ function renderNudge(payload) {
|
|
|
1698
1755
|
// `k` is stated rather than hidden. "Only you" and "you and two others" call for different
|
|
1699
1756
|
// behaviour, and a nudge that claimed certainty it did not have is how an agent learns to stop
|
|
1700
1757
|
// reading them.
|
|
1701
|
-
const nudgeBlock = renderArrival(page) + renderNudge(page)
|
|
1758
|
+
const nudgeBlock = renderArrival(page) + renderNudge(page) + renderSettling(page)
|
|
1702
1759
|
|
|
1703
1760
|
if (matches.length === 1) {
|
|
1704
1761
|
return { content: [{ type: 'text', text: renderMatch(matches[0], false) + nudgeBlock }] }
|
|
@@ -3449,7 +3506,7 @@ function renderNudge(payload) {
|
|
|
3449
3506
|
return toolError(`Could not list records: ${d.message}`)
|
|
3450
3507
|
}
|
|
3451
3508
|
const payload = await res.json()
|
|
3452
|
-
return { content: [{ type: 'text', text: (payload?.text ?? '') + renderArrival(payload) + renderNudge(payload) }] }
|
|
3509
|
+
return { content: [{ type: 'text', text: (payload?.text ?? '') + renderArrival(payload) + renderNudge(payload) + renderSettling(payload) }] }
|
|
3453
3510
|
},
|
|
3454
3511
|
)
|
|
3455
3512
|
|
package/package.json
CHANGED