mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 19:34:01 +00:00
Merge pull request #1031 from rudycelekli/contrib/gods-010-catalog-cancellation-v2-20261011-reviewed
fix(tools): reject already-cancelled queries before execution
This commit is contained in:
4 files changed
+57
-13
No files matched your search
+1
-13
@@ -24,19 +24,7 @@
|
|||||||
the five borough cores load and `CCTV_NYC_MAX_SOURCES` changes the cap. The catalog-wide ceiling is
|
the five borough cores load and `CCTV_NYC_MAX_SOURCES` changes the cap. The catalog-wide ceiling is
|
||||||
unchanged; extra cameras share it round-robin with the other packs.
|
unchanged; extra cameras share it round-robin with the other packs.
|
||||||
|
|
||||||
- Street Level counts unique tiles before ranking so overlapping dateline halves
|
- Cancelled catalog queries refuse execution when their signal is already aborted.
|
||||||
in polar views do not waste slots in the 16-tile overview budget.
|
|
||||||
|
|
||||||
- Directions no longer shows a truncation notice for a route with exactly 200
|
|
||||||
turns, and a roundabout at the 200th turn keeps its exit distance.
|
|
||||||
|
|
||||||
- Weather records keep missing conditions unknown and refuse summaries without a measured temperature.
|
|
||||||
|
|
||||||
- Tool string length validation counts Unicode characters correctly, including characters outside the basic multilingual plane.
|
|
||||||
|
|
||||||
- Director timeline seeks cross the dateline along the short longitude arc.
|
|
||||||
|
|
||||||
- Boundary capability checks recover after unsuccessful or malformed status responses, using the existing retry backoff.
|
|
||||||
|
|
||||||
- Treat explicitly current, complete empty vessel coverage as a successful update,
|
- Treat explicitly current, complete empty vessel coverage as a successful update,
|
||||||
clearing obsolete contacts while retaining stale or incomplete snapshots.
|
clearing obsolete contacts while retaining stale or incomplete snapshots.
|
||||||
|
|||||||
@@ -101,6 +101,10 @@ lists at 25 rows by default. Voice offers the same queries next to its app
|
|||||||
actions: the session lists them, and the browser runs them through the same
|
actions: the session lists them, and the browser runs them through the same
|
||||||
catalog, loaded on first use. See [tools and the MCP server](TOOLS.md).
|
catalog, loaded on first use. See [tools and the MCP server](TOOLS.md).
|
||||||
|
|
||||||
|
Catalog calls check their cancellation signal immediately before executing a
|
||||||
|
tool. Already-cancelled queries do not start; cancellation after execution starts
|
||||||
|
continues to follow the existing tool and caller behavior.
|
||||||
|
|
||||||
## Cyber HUD — September 30, 2026
|
## Cyber HUD — September 30, 2026
|
||||||
|
|
||||||
Display > HUD > Layout includes Cyber, also available through the HUD voice
|
Display > HUD > Layout includes Cyber, also available through the HUD voice
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import test from 'node:test';
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import { composeCatalog, defineTool } from './catalog.js';
|
||||||
|
|
||||||
|
for (const intercept of [false, true]) {
|
||||||
|
test(`cancelled query refuses execution${intercept ? ' after an awaited interceptor' : ''}`, async () => {
|
||||||
|
let calls = 0;
|
||||||
|
const controller = new AbortController();
|
||||||
|
const query = defineTool({
|
||||||
|
name: 'fixture_query',
|
||||||
|
kind: 'query',
|
||||||
|
title: 'Fixture',
|
||||||
|
description: 'Offline fixture',
|
||||||
|
inputSchema: { type: 'object' },
|
||||||
|
run: async () => {
|
||||||
|
calls++;
|
||||||
|
return { summary: 'fixture', data: {} };
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const catalog = composeCatalog({
|
||||||
|
tools: [query],
|
||||||
|
interceptors: intercept
|
||||||
|
? [
|
||||||
|
async (call, next) => {
|
||||||
|
await Promise.resolve();
|
||||||
|
controller.abort();
|
||||||
|
return next(call);
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: [],
|
||||||
|
});
|
||||||
|
if (!intercept) controller.abort();
|
||||||
|
await assert.rejects(
|
||||||
|
catalog.call('fixture_query', {}, { signal: controller.signal }),
|
||||||
|
{ name: 'AbortError' },
|
||||||
|
);
|
||||||
|
assert.equal(calls, 0);
|
||||||
|
const fresh = composeCatalog({ tools: [query] });
|
||||||
|
assert.equal(
|
||||||
|
(
|
||||||
|
await fresh.call(
|
||||||
|
'fixture_query',
|
||||||
|
{},
|
||||||
|
{ signal: new AbortController().signal },
|
||||||
|
)
|
||||||
|
).summary,
|
||||||
|
'fixture',
|
||||||
|
);
|
||||||
|
assert.equal(calls, 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -178,6 +178,7 @@ export function composeCatalog({
|
|||||||
return chain({ tool, args, signal, ...(parent ? { parent } : {}) });
|
return chain({ tool, args, signal, ...(parent ? { parent } : {}) });
|
||||||
};
|
};
|
||||||
const execute = async ({ tool, args, signal }) => {
|
const execute = async ({ tool, args, signal }) => {
|
||||||
|
signal?.throwIfAborted();
|
||||||
const problems = validateValue(tool.inputSchema, args);
|
const problems = validateValue(tool.inputSchema, args);
|
||||||
if (problems.length)
|
if (problems.length)
|
||||||
throw new ToolError('invalid_arguments', problems.join('; '));
|
throw new ToolError('invalid_arguments', problems.join('; '));
|
||||||
|
|||||||
Reference in new issue
Block a user