mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 11:24:00 +00:00
fix(tools): stop cancelled calls before execution and discard late results
This commit is contained in:
1 parent
6dd4d0156f
commit
691be39c1b
4 files changed
+50
No files matched your search
@@ -15,6 +15,8 @@
|
|||||||
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.
|
||||||
|
|
||||||
|
- Cancelled tool calls refuse actions before execution and discard results that settle after cancellation.
|
||||||
|
|
||||||
- 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.
|
||||||
|
|
||||||
|
|||||||
@@ -5310,3 +5310,8 @@ datacenters, dams and the Nepal locator retain that shared credit while displaye
|
|||||||
|
|
||||||
Military fragments stitch by source identity. Different mapped parcels merge only
|
Military fragments stitch by source identity. Different mapped parcels merge only
|
||||||
when their footprints touch or contain one another, never across a seam tolerance gap.
|
when their footprints touch or contain one another, never across a seam tolerance gap.
|
||||||
|
|
||||||
|
|
||||||
|
### fix(tools): stop cancelled calls before execution and discard late results
|
||||||
|
|
||||||
|
Check cancellation before invoking the tool and after it resolves, including nested calls that share the same signal. This does not promise rollback of an action already completed.
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import test from 'node:test';
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import { composeCatalog, defineTool } from './catalog.js';
|
||||||
|
test('cancelled catalog calls cannot execute or return late results', async () => {
|
||||||
|
let calls = 0,
|
||||||
|
release,
|
||||||
|
block = false;
|
||||||
|
const action = defineTool({
|
||||||
|
name: 'fixture_action',
|
||||||
|
kind: 'action',
|
||||||
|
title: 'Fixture',
|
||||||
|
description: 'Offline fixture',
|
||||||
|
inputSchema: { type: 'object' },
|
||||||
|
run: async () => {
|
||||||
|
calls++;
|
||||||
|
return block
|
||||||
|
? new Promise((r) => (release = r))
|
||||||
|
: { summary: 'fixture', data: {} };
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const catalog = composeCatalog({ tools: [action] });
|
||||||
|
const c = new AbortController();
|
||||||
|
c.abort();
|
||||||
|
await assert.rejects(
|
||||||
|
catalog.call('fixture_action', {}, { signal: c.signal }),
|
||||||
|
{ name: 'AbortError' },
|
||||||
|
);
|
||||||
|
assert.equal(calls, 0);
|
||||||
|
block = true;
|
||||||
|
const running = new AbortController();
|
||||||
|
const pending = catalog.call(
|
||||||
|
'fixture_action',
|
||||||
|
{},
|
||||||
|
{ signal: running.signal },
|
||||||
|
);
|
||||||
|
while (!release) await Promise.resolve();
|
||||||
|
running.abort();
|
||||||
|
release({ summary: 'late', data: {} });
|
||||||
|
await assert.rejects(pending, { name: 'AbortError' });
|
||||||
|
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('; '));
|
||||||
@@ -194,6 +195,7 @@ export function composeCatalog({
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw fromSourceError(error);
|
throw fromSourceError(error);
|
||||||
}
|
}
|
||||||
|
signal?.throwIfAborted();
|
||||||
if (!result || typeof result.summary !== 'string' || !result.data)
|
if (!result || typeof result.summary !== 'string' || !result.data)
|
||||||
throw new TypeError(`${tool.name} returned no summary or data`);
|
throw new TypeError(`${tool.name} returned no summary or data`);
|
||||||
if (
|
if (
|
||||||
|
|||||||
Reference in new issue
Block a user