sunpeak 0.20.42 → 0.20.47
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/bin/commands/inspect.mjs +66 -30
- package/bin/commands/test-init.mjs +2 -0
- package/bin/lib/eval/eval-runner.mjs +4 -0
- package/bin/lib/eval/model-registry.mjs +3 -6
- package/dist/chatgpt/index.cjs +1 -1
- package/dist/chatgpt/index.js +1 -1
- package/dist/claude/index.cjs +1 -1
- package/dist/claude/index.js +1 -1
- package/dist/hooks/tool-data-store.d.ts +26 -0
- package/dist/hooks/use-tool-data.d.ts +3 -9
- package/dist/host/chatgpt/index.cjs +1 -1
- package/dist/host/chatgpt/index.js +1 -1
- package/dist/index.cjs +35 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +35 -21
- package/dist/index.js.map +1 -1
- package/dist/inspector/index.cjs +1 -1
- package/dist/inspector/index.js +1 -1
- package/dist/{inspector-C6n8zap3.js → inspector-BSha-CAW.js} +45 -19
- package/dist/inspector-BSha-CAW.js.map +1 -0
- package/dist/{inspector-DOmiG64-.cjs → inspector-Chhc2GNO.cjs} +45 -19
- package/dist/inspector-Chhc2GNO.cjs.map +1 -0
- package/dist/lib/utils.d.ts +8 -7
- package/dist/mcp/index.cjs +5 -3
- package/dist/mcp/index.cjs.map +1 -1
- package/dist/mcp/index.js +5 -3
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/server.d.ts +12 -1
- package/dist/{use-app-Duar2Ipu.js → use-app-CtKy52kw.js} +62 -1
- package/dist/use-app-CtKy52kw.js.map +1 -0
- package/dist/{use-app-DUdnDLP5.cjs → use-app-xaiN0HAd.cjs} +62 -1
- package/dist/use-app-xaiN0HAd.cjs.map +1 -0
- package/package.json +8 -8
- package/template/dist/albums/albums.html +2 -2
- package/template/dist/albums/albums.json +1 -1
- package/template/dist/carousel/carousel.html +2 -2
- package/template/dist/carousel/carousel.json +1 -1
- package/template/dist/map/map.html +3 -3
- package/template/dist/map/map.json +1 -1
- package/template/dist/review/review.html +2 -2
- package/template/dist/review/review.json +1 -1
- package/template/node_modules/.bin/tsc +2 -2
- package/template/node_modules/.bin/tsserver +2 -2
- package/template/node_modules/.bin/vitest +2 -2
- package/template/node_modules/.vite/deps/_metadata.json +3 -3
- package/template/node_modules/.vite-mcp/deps/_metadata.json +20 -20
- package/template/node_modules/.vite-mcp/deps/vitest.js +7 -7
- package/template/node_modules/.vite-mcp/deps/vitest.js.map +1 -1
- package/template/package.json +1 -1
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-fullscreen-chatgpt-darwin.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-fullscreen-claude-darwin.png +0 -0
- package/template/tsconfig.json +2 -0
- package/dist/inspector-C6n8zap3.js.map +0 -1
- package/dist/inspector-DOmiG64-.cjs.map +0 -1
- package/dist/use-app-DUdnDLP5.cjs.map +0 -1
- package/dist/use-app-Duar2Ipu.js.map +0 -1
package/bin/commands/inspect.mjs
CHANGED
|
@@ -308,7 +308,7 @@ async function negotiateOAuth(serverUrl) {
|
|
|
308
308
|
|
|
309
309
|
// Try the anonymous/auto-approved path first: follow the authorization URL
|
|
310
310
|
// without a browser and see if it immediately redirects with a code.
|
|
311
|
-
const code = await tryAnonymousOAuth(authUrl.toString(), callbackUrl);
|
|
311
|
+
const code = await tryAnonymousOAuth(authUrl.toString(), callbackUrl, oauthState.stateParam);
|
|
312
312
|
if (code) {
|
|
313
313
|
// Complete the flow with the authorization code.
|
|
314
314
|
const tokenResult = await auth(provider, {
|
|
@@ -347,15 +347,17 @@ async function negotiateOAuth(serverUrl) {
|
|
|
347
347
|
*
|
|
348
348
|
* @param {string} authUrl - The authorization URL
|
|
349
349
|
* @param {string} callbackUrl - The expected callback URL prefix
|
|
350
|
+
* @param {string} [expectedState] - OAuth state value that must be echoed by the callback
|
|
351
|
+
* @param {typeof fetch} [fetchFn]
|
|
350
352
|
* @returns {Promise<string | null>}
|
|
351
353
|
*/
|
|
352
|
-
async function tryAnonymousOAuth(authUrl, callbackUrl) {
|
|
354
|
+
async function tryAnonymousOAuth(authUrl, callbackUrl, expectedState, fetchFn = fetch) {
|
|
353
355
|
// Follow redirects manually to detect when the server redirects back
|
|
354
356
|
// to our callback URL with a code parameter.
|
|
355
357
|
let url = authUrl;
|
|
356
358
|
const maxRedirects = 10;
|
|
357
359
|
for (let i = 0; i < maxRedirects; i++) {
|
|
358
|
-
const response = await
|
|
360
|
+
const response = await fetchFn(url, { redirect: 'manual' });
|
|
359
361
|
const location = response.headers.get('location');
|
|
360
362
|
|
|
361
363
|
if (!location) {
|
|
@@ -366,11 +368,21 @@ async function tryAnonymousOAuth(authUrl, callbackUrl) {
|
|
|
366
368
|
}
|
|
367
369
|
|
|
368
370
|
// Resolve relative redirects.
|
|
369
|
-
const
|
|
371
|
+
const resolvedUrl = new URL(location, url);
|
|
372
|
+
if (resolvedUrl.protocol !== 'http:' && resolvedUrl.protocol !== 'https:') {
|
|
373
|
+
throw new Error(
|
|
374
|
+
`OAuth authorization redirect has unsupported scheme: ${resolvedUrl.protocol}`
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
const resolved = resolvedUrl.toString();
|
|
370
378
|
|
|
371
379
|
// Check if the redirect goes to our callback URL.
|
|
372
380
|
if (resolved.startsWith(callbackUrl)) {
|
|
373
381
|
const params = new URL(resolved).searchParams;
|
|
382
|
+
const state = params.get('state');
|
|
383
|
+
if (expectedState && state !== expectedState) {
|
|
384
|
+
throw new Error('OAuth state mismatch — callback rejected');
|
|
385
|
+
}
|
|
374
386
|
const code = params.get('code');
|
|
375
387
|
if (code) return code;
|
|
376
388
|
const error = params.get('error');
|
|
@@ -906,45 +918,68 @@ async function discoverSimulations(client) {
|
|
|
906
918
|
|
|
907
919
|
/**
|
|
908
920
|
* Load simulation JSON fixtures from a directory and merge into discovered simulations.
|
|
921
|
+
*
|
|
922
|
+
* Each fixture becomes a simulation keyed by its filename, so a tool can have
|
|
923
|
+
* multiple fixtures (e.g. `show-albums.json` and `show-albums-empty.json`
|
|
924
|
+
* both targeting tool `show-albums`). Auto-discovered slots are kept only for
|
|
925
|
+
* tools that have no fixture file.
|
|
926
|
+
*
|
|
909
927
|
* @param {string} dir - Simulation directory path
|
|
910
928
|
* @param {Record<string, object>} simulations - Discovered simulations to merge into
|
|
911
929
|
*/
|
|
912
|
-
function mergeSimulationFixtures(dir, simulations) {
|
|
930
|
+
export function mergeSimulationFixtures(dir, simulations) {
|
|
913
931
|
if (!existsSync(dir)) return;
|
|
914
932
|
|
|
915
933
|
const files = readdirSync(dir).filter((f) => f.endsWith('.json'));
|
|
934
|
+
|
|
935
|
+
// Load every fixture first so we can group by tool name. We need the grouping
|
|
936
|
+
// to decide whether to keep the auto-discovered slot (no fixtures) or replace
|
|
937
|
+
// it with one entry per fixture file (one or more fixtures).
|
|
938
|
+
const fixtures = [];
|
|
916
939
|
for (const file of files) {
|
|
917
940
|
try {
|
|
918
941
|
const fixture = JSON.parse(readFileSync(join(dir, file), 'utf-8'));
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
// Find matching simulation by tool name
|
|
923
|
-
const sim = simulations[toolName];
|
|
924
|
-
if (sim) {
|
|
925
|
-
// Merge fixture data into discovered simulation
|
|
926
|
-
if (fixture.toolInput !== undefined) sim.toolInput = fixture.toolInput;
|
|
927
|
-
if (fixture.toolResult !== undefined) sim.toolResult = fixture.toolResult;
|
|
928
|
-
if (fixture.serverTools !== undefined) sim.serverTools = fixture.serverTools;
|
|
929
|
-
if (fixture.userMessage !== undefined) sim.userMessage = fixture.userMessage;
|
|
930
|
-
if (fixture.hostContext !== undefined) sim.hostContext = fixture.hostContext;
|
|
931
|
-
} else {
|
|
932
|
-
// Create a new simulation from the fixture (tool not on server, but user wants to mock it)
|
|
933
|
-
const simName = file.replace(/\.json$/, '');
|
|
934
|
-
simulations[simName] = {
|
|
935
|
-
name: simName,
|
|
936
|
-
tool: { name: toolName, inputSchema: { type: 'object' } },
|
|
937
|
-
toolInput: fixture.toolInput,
|
|
938
|
-
toolResult: fixture.toolResult,
|
|
939
|
-
serverTools: fixture.serverTools,
|
|
940
|
-
userMessage: fixture.userMessage,
|
|
941
|
-
hostContext: fixture.hostContext,
|
|
942
|
-
};
|
|
943
|
-
}
|
|
942
|
+
if (!fixture.tool) continue;
|
|
943
|
+
fixtures.push({ file, fixture });
|
|
944
944
|
} catch (err) {
|
|
945
945
|
console.warn(`Warning: Failed to parse simulation fixture ${file}:`, err.message);
|
|
946
946
|
}
|
|
947
947
|
}
|
|
948
|
+
|
|
949
|
+
const byTool = new Map();
|
|
950
|
+
for (const item of fixtures) {
|
|
951
|
+
const tool = item.fixture.tool;
|
|
952
|
+
if (!byTool.has(tool)) byTool.set(tool, []);
|
|
953
|
+
byTool.get(tool).push(item);
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
for (const [toolName, items] of byTool) {
|
|
957
|
+
const discovered = simulations[toolName];
|
|
958
|
+
|
|
959
|
+
// Drop the auto-discovered slot if none of the fixtures will reuse its
|
|
960
|
+
// key (filename === tool name). Otherwise the named fixture overwrites
|
|
961
|
+
// it in place below.
|
|
962
|
+
const reusesSlot = items.some(({ file }) => file.replace(/\.json$/, '') === toolName);
|
|
963
|
+
if (discovered && !reusesSlot) {
|
|
964
|
+
delete simulations[toolName];
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
for (const { file, fixture } of items) {
|
|
968
|
+
const simName = file.replace(/\.json$/, '');
|
|
969
|
+
const sim = discovered
|
|
970
|
+
? { ...discovered, name: simName }
|
|
971
|
+
: {
|
|
972
|
+
name: simName,
|
|
973
|
+
tool: { name: toolName, inputSchema: { type: 'object' } },
|
|
974
|
+
};
|
|
975
|
+
if (fixture.toolInput !== undefined) sim.toolInput = fixture.toolInput;
|
|
976
|
+
if (fixture.toolResult !== undefined) sim.toolResult = fixture.toolResult;
|
|
977
|
+
if (fixture.serverTools !== undefined) sim.serverTools = fixture.serverTools;
|
|
978
|
+
if (fixture.userMessage !== undefined) sim.userMessage = fixture.userMessage;
|
|
979
|
+
if (fixture.hostContext !== undefined) sim.hostContext = fixture.hostContext;
|
|
980
|
+
simulations[simName] = sim;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
948
983
|
}
|
|
949
984
|
|
|
950
985
|
const MODEL_PROVIDERS = new Set(['openai', 'anthropic']);
|
|
@@ -2875,6 +2910,7 @@ export const _securityTestExports = {
|
|
|
2875
2910
|
readRequestBody,
|
|
2876
2911
|
resolveHttpRedirectsForMcp,
|
|
2877
2912
|
shouldAllowPrivateServerUrls,
|
|
2913
|
+
tryAnonymousOAuth,
|
|
2878
2914
|
};
|
|
2879
2915
|
|
|
2880
2916
|
/**
|
|
@@ -220,12 +220,16 @@ export async function runSingleEval({
|
|
|
220
220
|
}) {
|
|
221
221
|
const { generateText } = await import('ai');
|
|
222
222
|
const system = formatEvalAppContextForModel(appContext);
|
|
223
|
+
const providerOptions = model?.provider?.startsWith('openai.')
|
|
224
|
+
? { openai: { strictJsonSchema: false } }
|
|
225
|
+
: undefined;
|
|
223
226
|
|
|
224
227
|
const result = await generateText({
|
|
225
228
|
model,
|
|
226
229
|
tools,
|
|
227
230
|
prompt,
|
|
228
231
|
...(system ? { system } : {}),
|
|
232
|
+
...(providerOptions ? { providerOptions } : {}),
|
|
229
233
|
maxSteps,
|
|
230
234
|
temperature,
|
|
231
235
|
maxRetries: 0, // We manage runs ourselves; AI SDK retries compound rate limits
|
|
@@ -47,12 +47,9 @@ export async function resolveModel(modelId) {
|
|
|
47
47
|
// @ai-sdk/openai v3 defaults to the Responses API, which requires strict
|
|
48
48
|
// JSON Schema (additionalProperties: false at every level, all properties
|
|
49
49
|
// required) — incompatible with arbitrary MCP server schemas. Use .chat()
|
|
50
|
-
// (Chat Completions API) when available
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
return typeof openai.chat === 'function'
|
|
54
|
-
? openai.chat(modelId, settings)
|
|
55
|
-
: openai(modelId, settings);
|
|
50
|
+
// (Chat Completions API) when available. The eval runner disables strict
|
|
51
|
+
// JSON Schema through per-call provider options.
|
|
52
|
+
return typeof openai.chat === 'function' ? openai.chat(modelId) : openai(modelId);
|
|
56
53
|
}
|
|
57
54
|
if (pkg === '@ai-sdk/anthropic') {
|
|
58
55
|
const { anthropic } = provider;
|
package/dist/chatgpt/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("../chunk-Cek0wNdY.cjs");
|
|
3
|
-
const require_inspector = require("../inspector-
|
|
3
|
+
const require_inspector = require("../inspector-Chhc2GNO.cjs");
|
|
4
4
|
const require_inspector_url = require("../inspector-url-BxScdDag.cjs");
|
|
5
5
|
const require_discovery = require("../discovery-31_n0zcu.cjs");
|
|
6
6
|
//#region src/chatgpt/index.ts
|
package/dist/chatgpt/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Ct as __exportAll } from "../protocol-bhrz2H_E.js";
|
|
2
|
-
import { _ as extractResourceCSP, f as ThemeProvider, g as IframeResource, p as useThemeContext, r as resolveServerToolResult, t as Inspector, v as McpAppHost, y as SCREEN_WIDTHS } from "../inspector-
|
|
2
|
+
import { _ as extractResourceCSP, f as ThemeProvider, g as IframeResource, p as useThemeContext, r as resolveServerToolResult, t as Inspector, v as McpAppHost, y as SCREEN_WIDTHS } from "../inspector-BSha-CAW.js";
|
|
3
3
|
import { t as createInspectorUrl } from "../inspector-url-xUMGbWis.js";
|
|
4
4
|
import { c as toPascalCase, i as findResourceKey, n as extractSimulationKey, r as findResourceDirs, s as getComponentName, t as extractResourceKey } from "../discovery-DOVner--.js";
|
|
5
5
|
//#region src/chatgpt/index.ts
|
package/dist/claude/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
require("../chunk-Cek0wNdY.cjs");
|
|
3
|
-
const require_inspector = require("../inspector-
|
|
3
|
+
const require_inspector = require("../inspector-Chhc2GNO.cjs");
|
|
4
4
|
exports.Inspector = require_inspector.Inspector;
|
package/dist/claude/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as Inspector } from "../inspector-
|
|
1
|
+
import { t as Inspector } from "../inspector-BSha-CAW.js";
|
|
2
2
|
export { Inspector };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { App } from '@modelcontextprotocol/ext-apps';
|
|
2
|
+
export interface ToolData<TInput = unknown, TOutput = unknown> {
|
|
3
|
+
input: TInput | null;
|
|
4
|
+
inputPartial: TInput | null;
|
|
5
|
+
output: TOutput | null;
|
|
6
|
+
isError: boolean;
|
|
7
|
+
isLoading: boolean;
|
|
8
|
+
isCancelled: boolean;
|
|
9
|
+
cancelReason: string | null;
|
|
10
|
+
}
|
|
11
|
+
export interface ToolDataStore<TInput = unknown, TOutput = unknown> {
|
|
12
|
+
data: ToolData<TInput, TOutput>;
|
|
13
|
+
listeners: Set<() => void>;
|
|
14
|
+
}
|
|
15
|
+
declare module '@modelcontextprotocol/ext-apps' {
|
|
16
|
+
interface App {
|
|
17
|
+
/** @internal Eager store attached by AppProvider before connect(). */
|
|
18
|
+
__toolDataStore?: ToolDataStore;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Initialize the tool-data store on an App instance and wire its event
|
|
23
|
+
* listeners. Idempotent - returns the existing store if one is already
|
|
24
|
+
* attached.
|
|
25
|
+
*/
|
|
26
|
+
export declare function initToolDataStore(app: App): ToolDataStore;
|
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
output: TOutput | null;
|
|
5
|
-
isError: boolean;
|
|
6
|
-
isLoading: boolean;
|
|
7
|
-
isCancelled: boolean;
|
|
8
|
-
cancelReason: string | null;
|
|
9
|
-
}
|
|
1
|
+
import { initToolDataStore, ToolData } from './tool-data-store';
|
|
2
|
+
export type { ToolData };
|
|
3
|
+
export { initToolDataStore };
|
|
10
4
|
/**
|
|
11
5
|
* Reactive access to tool input and output data from the MCP Apps host.
|
|
12
6
|
*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
require("../../chunk-Cek0wNdY.cjs");
|
|
3
|
-
const require_use_app = require("../../use-app-
|
|
3
|
+
const require_use_app = require("../../use-app-xaiN0HAd.cjs");
|
|
4
4
|
let react = require("react");
|
|
5
5
|
//#region src/host/chatgpt/openai-types.ts
|
|
6
6
|
/**
|
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("./chunk-Cek0wNdY.cjs");
|
|
3
3
|
const require_protocol = require("./protocol-Cafvpf0x.cjs");
|
|
4
|
-
const require_use_app = require("./use-app-
|
|
5
|
-
const require_inspector = require("./inspector-
|
|
4
|
+
const require_use_app = require("./use-app-xaiN0HAd.cjs");
|
|
5
|
+
const require_inspector = require("./inspector-Chhc2GNO.cjs");
|
|
6
6
|
const require_host_index = require("./host/index.cjs");
|
|
7
7
|
const require_inspector_index = require("./inspector/index.cjs");
|
|
8
8
|
const require_chatgpt_index = require("./chatgpt/index.cjs");
|
|
@@ -455,9 +455,22 @@ function useHostContext() {
|
|
|
455
455
|
//#region src/hooks/use-tool-data.ts
|
|
456
456
|
var stores = /* @__PURE__ */ new WeakMap();
|
|
457
457
|
function getStore(app, defaultInput, defaultOutput) {
|
|
458
|
+
const eager = app.__toolDataStore;
|
|
459
|
+
if (eager) {
|
|
460
|
+
if (defaultInput !== void 0 && eager.data.input === null) eager.data = {
|
|
461
|
+
...eager.data,
|
|
462
|
+
input: defaultInput
|
|
463
|
+
};
|
|
464
|
+
if (defaultOutput !== void 0 && eager.data.output === null) eager.data = {
|
|
465
|
+
...eager.data,
|
|
466
|
+
output: defaultOutput,
|
|
467
|
+
isLoading: false
|
|
468
|
+
};
|
|
469
|
+
return eager;
|
|
470
|
+
}
|
|
458
471
|
let store = stores.get(app);
|
|
459
472
|
if (!store) {
|
|
460
|
-
|
|
473
|
+
const lazy = {
|
|
461
474
|
data: {
|
|
462
475
|
input: defaultInput ?? null,
|
|
463
476
|
inputPartial: null,
|
|
@@ -469,43 +482,44 @@ function getStore(app, defaultInput, defaultOutput) {
|
|
|
469
482
|
},
|
|
470
483
|
listeners: /* @__PURE__ */ new Set()
|
|
471
484
|
};
|
|
472
|
-
stores.set(app,
|
|
485
|
+
stores.set(app, lazy);
|
|
486
|
+
store = lazy;
|
|
473
487
|
const notify = () => {
|
|
474
|
-
for (const fn of
|
|
488
|
+
for (const fn of lazy.listeners) fn();
|
|
475
489
|
};
|
|
476
|
-
app.
|
|
477
|
-
|
|
478
|
-
...
|
|
490
|
+
app.addEventListener("toolinput", (_params) => {
|
|
491
|
+
lazy.data = {
|
|
492
|
+
...lazy.data,
|
|
479
493
|
input: _params.arguments,
|
|
480
494
|
inputPartial: null
|
|
481
495
|
};
|
|
482
496
|
notify();
|
|
483
|
-
};
|
|
484
|
-
app.
|
|
485
|
-
|
|
486
|
-
...
|
|
497
|
+
});
|
|
498
|
+
app.addEventListener("toolinputpartial", (_params) => {
|
|
499
|
+
lazy.data = {
|
|
500
|
+
...lazy.data,
|
|
487
501
|
inputPartial: _params.arguments
|
|
488
502
|
};
|
|
489
503
|
notify();
|
|
490
|
-
};
|
|
491
|
-
app.
|
|
492
|
-
|
|
493
|
-
...
|
|
504
|
+
});
|
|
505
|
+
app.addEventListener("toolresult", (_params) => {
|
|
506
|
+
lazy.data = {
|
|
507
|
+
...lazy.data,
|
|
494
508
|
output: _params.structuredContent ?? _params.content,
|
|
495
509
|
isError: _params.isError ?? false,
|
|
496
510
|
isLoading: false
|
|
497
511
|
};
|
|
498
512
|
notify();
|
|
499
|
-
};
|
|
500
|
-
app.
|
|
501
|
-
|
|
502
|
-
...
|
|
513
|
+
});
|
|
514
|
+
app.addEventListener("toolcancelled", (_params) => {
|
|
515
|
+
lazy.data = {
|
|
516
|
+
...lazy.data,
|
|
503
517
|
isCancelled: true,
|
|
504
518
|
cancelReason: _params.reason ?? null,
|
|
505
519
|
isLoading: false
|
|
506
520
|
};
|
|
507
521
|
notify();
|
|
508
|
-
};
|
|
522
|
+
});
|
|
509
523
|
}
|
|
510
524
|
return store;
|
|
511
525
|
}
|