@jay-framework/aiditor 0.20.0 → 0.22.0
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/dist/actions/cancel-agent-task.jay-action +1 -0
- package/dist/actions/cancel-agent-task.jay-action.d.ts +1 -0
- package/dist/agent-kit-template/plugin/aiditor-add-menu.md +470 -63
- package/dist/index.client.d.ts +254 -16
- package/dist/index.client.js +3323 -1359
- package/dist/index.d.ts +29 -29
- package/dist/index.js +180 -162
- package/dist/pages/aiditor/page.css +127 -22
- package/dist/pages/aiditor/page.jay-html +853 -171
- package/dist/pages/aiditor/page.jay-html.d.ts +254 -16
- package/package.json +11 -10
- package/plugin.yaml +2 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as _jay_framework_dev_server from '@jay-framework/dev-server';
|
|
2
2
|
import * as _jay_framework_fullstack_component from '@jay-framework/fullstack-component';
|
|
3
3
|
import { JayFile } from '@jay-framework/fullstack-component';
|
|
4
|
+
import { AddMenuCatalogLintWarning, AddMenuItem, AddMenuPresentation, AddMenuBrowseSize } from '@jay-framework/plugin-validator';
|
|
5
|
+
export { AddMenuItem, AddMenuPresentation } from '@jay-framework/plugin-validator';
|
|
4
6
|
import { PluginSetupContext, PluginSetupResult } from '@jay-framework/stack-server-runtime';
|
|
5
7
|
export { aiditorPage, aiditorShell } from './index.client.js';
|
|
6
8
|
import '@jay-framework/component';
|
|
@@ -110,35 +112,24 @@ declare const submitTaskAction: _jay_framework_fullstack_component.JayStreamActi
|
|
|
110
112
|
declare const cancelAgentTaskAction: _jay_framework_fullstack_component.JayAction<{
|
|
111
113
|
pageRoute?: string;
|
|
112
114
|
renderedUrl?: string;
|
|
115
|
+
cancelKey?: string;
|
|
113
116
|
}, {
|
|
114
117
|
cancelled: boolean;
|
|
115
118
|
}> & _jay_framework_fullstack_component.JayActionDefinition<{
|
|
116
119
|
pageRoute?: string;
|
|
117
120
|
renderedUrl?: string;
|
|
121
|
+
cancelKey?: string;
|
|
118
122
|
}, {
|
|
119
123
|
cancelled: boolean;
|
|
120
124
|
}, []>;
|
|
121
125
|
|
|
122
|
-
/**
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
type
|
|
129
|
-
/** Stable unique id, convention: `<pluginName>:<slug>` */
|
|
130
|
-
id: string;
|
|
131
|
-
title: string;
|
|
132
|
-
/** Menu navigation label — not a type system */
|
|
133
|
-
category: string;
|
|
134
|
-
/** Injected verbatim into agent prompt when attached */
|
|
135
|
-
prompt: string;
|
|
136
|
-
pluginName?: string;
|
|
137
|
-
packageName?: string;
|
|
138
|
-
subCategory?: string;
|
|
139
|
-
thumbnail?: string;
|
|
140
|
-
interaction?: AddMenuInteraction;
|
|
141
|
-
};
|
|
126
|
+
/**
|
|
127
|
+
* AIditor Add Menu runtime types.
|
|
128
|
+
* Catalog item schema types come from @jay-framework/plugin-validator (source of truth).
|
|
129
|
+
*/
|
|
130
|
+
|
|
131
|
+
/** Runtime catalog warning — same shape as plugin-validator lint findings. */
|
|
132
|
+
type AddMenuCatalogWarning = AddMenuCatalogLintWarning;
|
|
142
133
|
type AddMenuAttachment = {
|
|
143
134
|
itemId: string;
|
|
144
135
|
/** Change Request: set when chip is on a marker; omit = request-level */
|
|
@@ -161,7 +152,7 @@ type AddMenuSubCategoryGroup = {
|
|
|
161
152
|
type ListAddMenuItemsResult = {
|
|
162
153
|
items: AddMenuItem[];
|
|
163
154
|
categories: AddMenuCategoryGroup[];
|
|
164
|
-
warnings:
|
|
155
|
+
warnings: AddMenuCatalogWarning[];
|
|
165
156
|
};
|
|
166
157
|
|
|
167
158
|
type PageBriefAttachment = {
|
|
@@ -384,9 +375,9 @@ declare const generateAddPageBriefFromImageAction: _jay_framework_fullstack_comp
|
|
|
384
375
|
referenceAttachments?: undefined;
|
|
385
376
|
} | {
|
|
386
377
|
ok: boolean;
|
|
387
|
-
markdown:
|
|
388
|
-
suggestedRoute:
|
|
389
|
-
suggestedRouteKind:
|
|
378
|
+
markdown: any;
|
|
379
|
+
suggestedRoute: any;
|
|
380
|
+
suggestedRouteKind: any;
|
|
390
381
|
referenceAttachments: {
|
|
391
382
|
id: string;
|
|
392
383
|
path: string;
|
|
@@ -408,9 +399,9 @@ declare const generateAddPageBriefFromImageAction: _jay_framework_fullstack_comp
|
|
|
408
399
|
referenceAttachments?: undefined;
|
|
409
400
|
} | {
|
|
410
401
|
ok: boolean;
|
|
411
|
-
markdown:
|
|
412
|
-
suggestedRoute:
|
|
413
|
-
suggestedRouteKind:
|
|
402
|
+
markdown: any;
|
|
403
|
+
suggestedRoute: any;
|
|
404
|
+
suggestedRouteKind: any;
|
|
414
405
|
referenceAttachments: {
|
|
415
406
|
id: string;
|
|
416
407
|
path: string;
|
|
@@ -763,7 +754,6 @@ type PageAssetEntry = {
|
|
|
763
754
|
source: PageAssetSource;
|
|
764
755
|
itemId?: string;
|
|
765
756
|
thumbnail?: string;
|
|
766
|
-
persistOnPage: boolean;
|
|
767
757
|
addedAt: string;
|
|
768
758
|
/** Stable key for detected entries — used for sync + suppression */
|
|
769
759
|
detectedKey?: string;
|
|
@@ -861,4 +851,14 @@ declare const runAiditorPublishAction: _jay_framework_fullstack_component.JayStr
|
|
|
861
851
|
|
|
862
852
|
declare function setupAiditor(ctx: PluginSetupContext): Promise<PluginSetupResult>;
|
|
863
853
|
|
|
864
|
-
|
|
854
|
+
declare function listAddMenuItems(projectRoot: string): Promise<ListAddMenuItemsResult>;
|
|
855
|
+
|
|
856
|
+
declare function sanitizeAddMenuHtmlFragment(html: string): string;
|
|
857
|
+
|
|
858
|
+
/** Normalize legacy `thumbnail` and explicit `presentation` to one shape (Design Log #30). */
|
|
859
|
+
declare function normalizeAddMenuPresentation(item: Pick<AddMenuItem, "thumbnail" | "presentation">): AddMenuPresentation | undefined;
|
|
860
|
+
|
|
861
|
+
/** Default browse footprint — Design Log #32. */
|
|
862
|
+
declare function normalizeAddMenuBrowseSize(item: Pick<AddMenuItem, "browse">): AddMenuBrowseSize;
|
|
863
|
+
|
|
864
|
+
export { type AddMenuCatalogWarning, type ListAddMenuItemsResult, cancelAgentTaskAction, checkAddPageRouteAction, checkAiditorPublishAction, checkPageAddPageBriefAction, checkPluginUpdateAction, ensureProjectPluginAction, generateAddPageBriefFromImageAction, getAiditorBootstrap, getContractInspectorTagsAction, getPageAssetsAction, getPageMetaAction, getPageParamsAction, getPluginSetupStatusAction, getProjectInfoAction, listAddMenuItems, listAddMenuItemsAction, listFreezesAction, listJayPluginsAction, listPluginContractsAction, normalizeAddMenuBrowseSize, normalizeAddMenuPresentation, openAddPageFromBriefAction, readFileAction, reclassifyAddPageAssetAction, rerunPluginSetupAction, resolveAddMenuContractParamsAction, runAiditorPublishAction, sanitizeAddMenuHtmlFragment, saveAddPageDraftAction, savePageAssetsAction, savePageMetaAction, setupAiditor, startAddPageRequestAction, submitAddPageAction, submitTaskAction, syncAddMenuAttachmentsAction, syncAddPagePluginManifestAction, syncDetectedPageAssetsAction, uploadAddPageAssetAction, writePluginSourceAction };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1
4
|
import { makeJayQuery, makeJayStream, makeJayStackComponent, phaseOutput, RenderPipeline } from "@jay-framework/fullstack-component";
|
|
2
5
|
import { DEV_SERVER_SERVICE } from "@jay-framework/dev-server";
|
|
3
6
|
import fs, { readFile, readdir } from "fs/promises";
|
|
@@ -6,6 +9,7 @@ import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
|
6
9
|
import fs$1 from "fs";
|
|
7
10
|
import crypto from "crypto";
|
|
8
11
|
import yaml, { load } from "js-yaml";
|
|
12
|
+
import { validateAddMenuCatalogFile, lintAddMenuCatalog } from "@jay-framework/plugin-validator";
|
|
9
13
|
import { getLogger } from "@jay-framework/logger";
|
|
10
14
|
import { fileURLToPath } from "url";
|
|
11
15
|
import { spawn } from "child_process";
|
|
@@ -338,131 +342,10 @@ function groupAddMenuItems(items) {
|
|
|
338
342
|
return sa.localeCompare(sb);
|
|
339
343
|
}).map(([subCategory, subItems]) => ({
|
|
340
344
|
subCategory,
|
|
341
|
-
items: subItems
|
|
345
|
+
items: subItems
|
|
342
346
|
}))
|
|
343
347
|
}));
|
|
344
348
|
}
|
|
345
|
-
const REJECTED_ITEM_FIELDS = [
|
|
346
|
-
"kind",
|
|
347
|
-
"parameters",
|
|
348
|
-
"component",
|
|
349
|
-
"allowedScopes"
|
|
350
|
-
];
|
|
351
|
-
function isRecord(value) {
|
|
352
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
353
|
-
}
|
|
354
|
-
function requiredString(obj, field, path2, errors) {
|
|
355
|
-
const value = obj[field];
|
|
356
|
-
if (typeof value !== "string" || value.trim().length === 0) {
|
|
357
|
-
errors.push({
|
|
358
|
-
path: `${path2}.${field}`,
|
|
359
|
-
message: "required non-empty string"
|
|
360
|
-
});
|
|
361
|
-
return null;
|
|
362
|
-
}
|
|
363
|
-
return value.trim();
|
|
364
|
-
}
|
|
365
|
-
function optionalString(obj, field) {
|
|
366
|
-
const value = obj[field];
|
|
367
|
-
if (value === void 0) return void 0;
|
|
368
|
-
if (typeof value !== "string") return void 0;
|
|
369
|
-
const trimmed = value.trim();
|
|
370
|
-
return trimmed.length > 0 ? trimmed : void 0;
|
|
371
|
-
}
|
|
372
|
-
function optionalBoolean(obj, field) {
|
|
373
|
-
const value = obj[field];
|
|
374
|
-
return typeof value === "boolean" ? value : void 0;
|
|
375
|
-
}
|
|
376
|
-
function validateInteraction(raw, path2, errors) {
|
|
377
|
-
if (raw === void 0) return void 0;
|
|
378
|
-
if (!isRecord(raw)) {
|
|
379
|
-
errors.push({ path: path2, message: "interaction must be an object" });
|
|
380
|
-
return void 0;
|
|
381
|
-
}
|
|
382
|
-
const mode = raw.mode;
|
|
383
|
-
if (mode !== "reference" && mode !== "stage-place") {
|
|
384
|
-
errors.push({
|
|
385
|
-
path: `${path2}.mode`,
|
|
386
|
-
message: 'mode must be "reference" or "stage-place"'
|
|
387
|
-
});
|
|
388
|
-
return void 0;
|
|
389
|
-
}
|
|
390
|
-
return {
|
|
391
|
-
mode,
|
|
392
|
-
persistOnPage: optionalBoolean(raw, "persistOnPage"),
|
|
393
|
-
stagePromptTemplate: optionalString(raw, "stagePromptTemplate")
|
|
394
|
-
};
|
|
395
|
-
}
|
|
396
|
-
function validateAddMenuItem(raw, path2) {
|
|
397
|
-
const errors = [];
|
|
398
|
-
if (!isRecord(raw)) {
|
|
399
|
-
return {
|
|
400
|
-
item: null,
|
|
401
|
-
errors: [{ path: path2, message: "item must be an object" }]
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
for (const field of REJECTED_ITEM_FIELDS) {
|
|
405
|
-
if (field in raw) {
|
|
406
|
-
errors.push({
|
|
407
|
-
path: `${path2}.${field}`,
|
|
408
|
-
message: `field "${field}" is not allowed in Add Menu catalog items`
|
|
409
|
-
});
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
const id = requiredString(raw, "id", path2, errors);
|
|
413
|
-
const title = requiredString(raw, "title", path2, errors);
|
|
414
|
-
const category = requiredString(raw, "category", path2, errors);
|
|
415
|
-
const prompt = requiredString(raw, "prompt", path2, errors);
|
|
416
|
-
if (errors.length > 0 || !id || !title || !category || !prompt) {
|
|
417
|
-
return { item: null, errors };
|
|
418
|
-
}
|
|
419
|
-
const interaction = validateInteraction(
|
|
420
|
-
raw.interaction,
|
|
421
|
-
`${path2}.interaction`,
|
|
422
|
-
errors
|
|
423
|
-
);
|
|
424
|
-
return {
|
|
425
|
-
item: {
|
|
426
|
-
id,
|
|
427
|
-
title,
|
|
428
|
-
category,
|
|
429
|
-
prompt,
|
|
430
|
-
pluginName: optionalString(raw, "pluginName"),
|
|
431
|
-
packageName: optionalString(raw, "packageName"),
|
|
432
|
-
subCategory: optionalString(raw, "subCategory"),
|
|
433
|
-
thumbnail: optionalString(raw, "thumbnail"),
|
|
434
|
-
...interaction ? { interaction } : {}
|
|
435
|
-
},
|
|
436
|
-
errors
|
|
437
|
-
};
|
|
438
|
-
}
|
|
439
|
-
function validateAddMenuCatalogFile(raw, sourcePath) {
|
|
440
|
-
const errors = [];
|
|
441
|
-
if (!isRecord(raw)) {
|
|
442
|
-
return {
|
|
443
|
-
file: null,
|
|
444
|
-
errors: [{ path: sourcePath, message: "catalog file must be an object" }]
|
|
445
|
-
};
|
|
446
|
-
}
|
|
447
|
-
if (!Array.isArray(raw.items)) {
|
|
448
|
-
return {
|
|
449
|
-
file: null,
|
|
450
|
-
errors: [
|
|
451
|
-
{ path: `${sourcePath}.items`, message: "items must be an array" }
|
|
452
|
-
]
|
|
453
|
-
};
|
|
454
|
-
}
|
|
455
|
-
const items = [];
|
|
456
|
-
raw.items.forEach((entry, index) => {
|
|
457
|
-
const result = validateAddMenuItem(entry, `${sourcePath}.items[${index}]`);
|
|
458
|
-
errors.push(...result.errors);
|
|
459
|
-
if (result.item) items.push(result.item);
|
|
460
|
-
});
|
|
461
|
-
if (items.length === 0 && errors.length > 0) {
|
|
462
|
-
return { file: null, errors };
|
|
463
|
-
}
|
|
464
|
-
return { file: { items }, errors };
|
|
465
|
-
}
|
|
466
349
|
function parsePluginsIndexYaml(yaml2) {
|
|
467
350
|
const entries = [];
|
|
468
351
|
let currentPlugin = null;
|
|
@@ -588,6 +471,7 @@ async function parsePluginYamlContracts(projectRoot, pluginName) {
|
|
|
588
471
|
}
|
|
589
472
|
}
|
|
590
473
|
const ADD_MENU_DIR = path.join("agent-kit", "aiditor", "add-menu");
|
|
474
|
+
const LOCAL_PLUGINS_DIR = path.join("src", "plugins");
|
|
591
475
|
function packageNameFromItem(item) {
|
|
592
476
|
if (item.packageName) return item.packageName;
|
|
593
477
|
if (item.pluginName) return `@jay-framework/${item.pluginName}`;
|
|
@@ -603,6 +487,39 @@ function pluginNameFromItem(item) {
|
|
|
603
487
|
if (colon > 0) return item.id.slice(0, colon);
|
|
604
488
|
return null;
|
|
605
489
|
}
|
|
490
|
+
async function getLocalPluginNames(projectRoot) {
|
|
491
|
+
const names = /* @__PURE__ */ new Set();
|
|
492
|
+
const pluginsDir = path.join(projectRoot, LOCAL_PLUGINS_DIR);
|
|
493
|
+
let entries;
|
|
494
|
+
try {
|
|
495
|
+
entries = await fs.readdir(pluginsDir);
|
|
496
|
+
} catch (e) {
|
|
497
|
+
const code = e && typeof e === "object" && "code" in e ? e.code : void 0;
|
|
498
|
+
if (code === "ENOENT") return names;
|
|
499
|
+
throw e;
|
|
500
|
+
}
|
|
501
|
+
for (const entry of entries) {
|
|
502
|
+
const pluginYaml = path.join(pluginsDir, entry, "plugin.yaml");
|
|
503
|
+
try {
|
|
504
|
+
const yaml2 = await fs.readFile(pluginYaml, "utf-8");
|
|
505
|
+
const nameMatch = yaml2.match(/^name:\s*(.+)\s*$/m);
|
|
506
|
+
if (nameMatch?.[1]) {
|
|
507
|
+
names.add(nameMatch[1].trim());
|
|
508
|
+
continue;
|
|
509
|
+
}
|
|
510
|
+
} catch {
|
|
511
|
+
}
|
|
512
|
+
names.add(entry);
|
|
513
|
+
}
|
|
514
|
+
return names;
|
|
515
|
+
}
|
|
516
|
+
function validationErrorToWarning(err) {
|
|
517
|
+
return {
|
|
518
|
+
code: err.code ?? "catalog-validation-error",
|
|
519
|
+
message: `${err.path}: ${err.message}`,
|
|
520
|
+
sourcePath: err.path
|
|
521
|
+
};
|
|
522
|
+
}
|
|
606
523
|
async function listAddMenuItems(projectRoot) {
|
|
607
524
|
const addMenuDir = path.join(projectRoot, ADD_MENU_DIR);
|
|
608
525
|
const warnings = [];
|
|
@@ -620,43 +537,67 @@ async function listAddMenuItems(projectRoot) {
|
|
|
620
537
|
const installed = await getInstalledPlugins(projectRoot);
|
|
621
538
|
const installedPackages = new Set(installed.map((p) => p.packageName));
|
|
622
539
|
const installedPlugins = new Set(installed.map((p) => p.pluginName));
|
|
540
|
+
for (const localName of await getLocalPluginNames(projectRoot)) {
|
|
541
|
+
installedPlugins.add(localName);
|
|
542
|
+
}
|
|
623
543
|
const byId = /* @__PURE__ */ new Map();
|
|
544
|
+
const orderedIds = [];
|
|
545
|
+
const lintBlockedIds = /* @__PURE__ */ new Set();
|
|
624
546
|
for (const filePath of yamlFiles) {
|
|
625
547
|
const relPath = path.relative(projectRoot, filePath);
|
|
626
548
|
let rawContent;
|
|
627
549
|
try {
|
|
628
550
|
rawContent = await fs.readFile(filePath, "utf-8");
|
|
629
551
|
} catch {
|
|
630
|
-
warnings.push(
|
|
552
|
+
warnings.push({
|
|
553
|
+
code: "catalog-read-error",
|
|
554
|
+
message: `Could not read Add Menu catalog file: ${relPath}`,
|
|
555
|
+
sourcePath: relPath
|
|
556
|
+
});
|
|
631
557
|
continue;
|
|
632
558
|
}
|
|
633
559
|
let parsed;
|
|
634
560
|
try {
|
|
635
561
|
parsed = load(rawContent);
|
|
636
562
|
} catch (err) {
|
|
637
|
-
warnings.push(
|
|
638
|
-
|
|
639
|
-
|
|
563
|
+
warnings.push({
|
|
564
|
+
code: "catalog-parse-error",
|
|
565
|
+
message: `Invalid YAML in ${relPath}: ${err instanceof Error ? err.message : String(err)}`,
|
|
566
|
+
sourcePath: relPath
|
|
567
|
+
});
|
|
640
568
|
continue;
|
|
641
569
|
}
|
|
642
570
|
const validated = validateAddMenuCatalogFile(parsed, relPath);
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
571
|
+
for (const err of validated.errors) {
|
|
572
|
+
warnings.push(validationErrorToWarning(err));
|
|
573
|
+
}
|
|
574
|
+
if (!validated.file) {
|
|
647
575
|
continue;
|
|
648
576
|
}
|
|
577
|
+
const linted = lintAddMenuCatalog(validated.file.items, relPath);
|
|
578
|
+
for (const err of linted.errors) {
|
|
579
|
+
warnings.push(err);
|
|
580
|
+
if (err.itemId) lintBlockedIds.add(err.itemId);
|
|
581
|
+
}
|
|
582
|
+
warnings.push(...linted.warnings);
|
|
649
583
|
for (const item of validated.file.items) {
|
|
584
|
+
if (lintBlockedIds.has(item.id)) continue;
|
|
650
585
|
const prev = byId.get(item.id);
|
|
651
586
|
if (prev) {
|
|
652
|
-
warnings.push(
|
|
653
|
-
|
|
654
|
-
|
|
587
|
+
warnings.push({
|
|
588
|
+
code: "catalog-duplicate-id",
|
|
589
|
+
message: `Duplicate Add Menu item id "${item.id}": "${prev.sourcePath}" overwritten by "${relPath}"`,
|
|
590
|
+
itemId: item.id,
|
|
591
|
+
sourcePath: relPath
|
|
592
|
+
});
|
|
593
|
+
byId.set(item.id, { item, sourcePath: relPath });
|
|
594
|
+
continue;
|
|
655
595
|
}
|
|
656
596
|
byId.set(item.id, { item, sourcePath: relPath });
|
|
597
|
+
orderedIds.push(item.id);
|
|
657
598
|
}
|
|
658
599
|
}
|
|
659
|
-
const merged =
|
|
600
|
+
const merged = orderedIds.map((id) => byId.get(id)?.item).filter((item) => item !== void 0);
|
|
660
601
|
const filtered = merged.filter((item) => {
|
|
661
602
|
const pkg = packageNameFromItem(item);
|
|
662
603
|
const plugin = pluginNameFromItem(item);
|
|
@@ -665,7 +606,7 @@ async function listAddMenuItems(projectRoot) {
|
|
|
665
606
|
return false;
|
|
666
607
|
});
|
|
667
608
|
return {
|
|
668
|
-
items: filtered
|
|
609
|
+
items: filtered,
|
|
669
610
|
categories: groupAddMenuItems(filtered),
|
|
670
611
|
warnings
|
|
671
612
|
};
|
|
@@ -938,7 +879,7 @@ function buildRouteMigrationPromptSection(routeMigration) {
|
|
|
938
879
|
].join("\n");
|
|
939
880
|
}
|
|
940
881
|
function buildPageAssetsPromptSection(assets) {
|
|
941
|
-
const active = assets.filter((a) =>
|
|
882
|
+
const active = assets.filter((a) => !a.userRemoved);
|
|
942
883
|
if (active.length === 0) return "";
|
|
943
884
|
const lines = [
|
|
944
885
|
"Page assets (in scope for this page — use when referenced in marker instructions or @mentions):"
|
|
@@ -1086,11 +1027,12 @@ function appendVisualAttachmentLines(body, attachments, indent = "") {
|
|
|
1086
1027
|
return;
|
|
1087
1028
|
}
|
|
1088
1029
|
body.push(
|
|
1089
|
-
`${indent}Attachments (read from disk; belong to this annotation only):`
|
|
1030
|
+
`${indent}Attachments (read from disk; belong to this annotation only; match "image #N" in the instruction):`
|
|
1090
1031
|
);
|
|
1091
|
-
for (
|
|
1032
|
+
for (let i = 0; i < attachments.length; i++) {
|
|
1033
|
+
const att = attachments[i];
|
|
1092
1034
|
body.push(
|
|
1093
|
-
`${indent}- ${att.taskCopyPath} (filename: ${att.originalFileName})`
|
|
1035
|
+
`${indent}- Image #${i + 1}: ${att.taskCopyPath} (filename: ${att.originalFileName})`
|
|
1094
1036
|
);
|
|
1095
1037
|
}
|
|
1096
1038
|
}
|
|
@@ -1265,6 +1207,13 @@ function buildVisualPromptVideo(config, pageRoute, renderedUrl, videoPath, frame
|
|
|
1265
1207
|
}
|
|
1266
1208
|
return [...preamble, ...body].join("\n");
|
|
1267
1209
|
}
|
|
1210
|
+
function distinctTimeSecsAscending(annotations) {
|
|
1211
|
+
const s = /* @__PURE__ */ new Set();
|
|
1212
|
+
for (const a of annotations) {
|
|
1213
|
+
s.add(a.timeSec);
|
|
1214
|
+
}
|
|
1215
|
+
return [...s].sort((a, b) => a - b);
|
|
1216
|
+
}
|
|
1268
1217
|
function persistFile(file, destDir, fileName) {
|
|
1269
1218
|
fs$1.mkdirSync(destDir, { recursive: true });
|
|
1270
1219
|
const dest = path.join(destDir, fileName ?? file.name);
|
|
@@ -1309,14 +1258,13 @@ const submitTaskAction = makeJayStream("aiditor.submitTask").withFiles().withHan
|
|
|
1309
1258
|
}
|
|
1310
1259
|
const extra = input.extraFiles ?? {};
|
|
1311
1260
|
const frames = [];
|
|
1261
|
+
const momentTimes = parsed.structuredVideo ? distinctTimeSecsAscending(parsed.structuredVideo.annotations) : [];
|
|
1312
1262
|
for (let i = 0; ; i++) {
|
|
1313
1263
|
const markers = extra[`frame_${i}_markers_only`];
|
|
1314
1264
|
const clean = extra[`frame_${i}_clean`];
|
|
1315
1265
|
if (!markers && !clean) break;
|
|
1316
1266
|
const frameDir = path.join(taskDir, "frames", String(i));
|
|
1317
|
-
const timeSec =
|
|
1318
|
-
(a, idx) => idx === i || a.timeSec !== void 0
|
|
1319
|
-
)?.timeSec ?? i;
|
|
1267
|
+
const timeSec = momentTimes[i] ?? i;
|
|
1320
1268
|
frames.push({
|
|
1321
1269
|
timeSec,
|
|
1322
1270
|
frameIndex: i,
|
|
@@ -1456,17 +1404,19 @@ const submitTaskAction = makeJayStream("aiditor.submitTask").withFiles().withHan
|
|
|
1456
1404
|
});
|
|
1457
1405
|
const cancelAgentTaskAction = makeJayQuery(
|
|
1458
1406
|
"aiditor.cancelAgentTask"
|
|
1459
|
-
).withHandler(
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1407
|
+
).withHandler(
|
|
1408
|
+
async (input) => {
|
|
1409
|
+
const routeKey = input.cancelKey?.trim() || resolveAgentContextKey({
|
|
1410
|
+
pageRoute: input.pageRoute ?? "/",
|
|
1411
|
+
renderedUrl: input.renderedUrl
|
|
1412
|
+
});
|
|
1413
|
+
const cancelled = cancelAgentTask(routeKey);
|
|
1414
|
+
if (!cancelled) {
|
|
1415
|
+
forceReleaseAgentRoute(routeKey);
|
|
1416
|
+
}
|
|
1417
|
+
return { cancelled: true };
|
|
1467
1418
|
}
|
|
1468
|
-
|
|
1469
|
-
});
|
|
1419
|
+
);
|
|
1470
1420
|
class AddPagePromptLoadError extends Error {
|
|
1471
1421
|
constructor(message) {
|
|
1472
1422
|
super(message);
|
|
@@ -2292,6 +2242,12 @@ When the image is a formal Figma **design definitions** board, apply these rules
|
|
|
2292
2242
|
${designDefinitionsBody}`;
|
|
2293
2243
|
});
|
|
2294
2244
|
}
|
|
2245
|
+
class BriefFillCancelledError extends Error {
|
|
2246
|
+
constructor() {
|
|
2247
|
+
super("Stopped by user.");
|
|
2248
|
+
__publicField(this, "name", "BriefFillCancelledError");
|
|
2249
|
+
}
|
|
2250
|
+
}
|
|
2295
2251
|
const briefFillModelOverride = process.env.AIDITOR_BRIEF_FILL_MODEL?.trim();
|
|
2296
2252
|
const ALLOWED_IMAGE_MIMES = /* @__PURE__ */ new Set([
|
|
2297
2253
|
"image/png",
|
|
@@ -2459,6 +2415,9 @@ async function runBriefFillAgentQuery(input) {
|
|
|
2459
2415
|
thinking: { type: "disabled" }
|
|
2460
2416
|
}
|
|
2461
2417
|
})) {
|
|
2418
|
+
if (input.cancelKey && isAgentTaskCancelled(input.cancelKey)) {
|
|
2419
|
+
throw new BriefFillCancelledError();
|
|
2420
|
+
}
|
|
2462
2421
|
collected.push(message);
|
|
2463
2422
|
}
|
|
2464
2423
|
const rawText = extractBriefFillRawText(collected);
|
|
@@ -2487,6 +2446,19 @@ async function generateBriefFromImages(input, options) {
|
|
|
2487
2446
|
}
|
|
2488
2447
|
return { markdown };
|
|
2489
2448
|
}
|
|
2449
|
+
const BRIEF_FILL_CANCEL_PREFIX = "brief-fill:";
|
|
2450
|
+
function resolveBriefFillCancelKey(input) {
|
|
2451
|
+
const targetSuffix = input.target ? `:${input.target}` : "";
|
|
2452
|
+
const requestId = input.requestId?.trim();
|
|
2453
|
+
if (requestId) {
|
|
2454
|
+
return `${BRIEF_FILL_CANCEL_PREFIX}request:${requestId}${targetSuffix}`;
|
|
2455
|
+
}
|
|
2456
|
+
const route = input.pageRoute?.trim();
|
|
2457
|
+
if (route) {
|
|
2458
|
+
return `${BRIEF_FILL_CANCEL_PREFIX}route:${normalizePageRoute(route)}${targetSuffix}`;
|
|
2459
|
+
}
|
|
2460
|
+
return `${BRIEF_FILL_CANCEL_PREFIX}draft${targetSuffix}`;
|
|
2461
|
+
}
|
|
2490
2462
|
function persistUpload(file, destPath) {
|
|
2491
2463
|
fs$1.mkdirSync(path.dirname(destPath), { recursive: true });
|
|
2492
2464
|
fs$1.copyFileSync(file.path, destPath);
|
|
@@ -2826,15 +2798,27 @@ const generateAddPageBriefFromImageAction = makeJayQuery(
|
|
|
2826
2798
|
}
|
|
2827
2799
|
try {
|
|
2828
2800
|
const images = imageFiles.map(readImageAsBase64);
|
|
2829
|
-
const
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2801
|
+
const cancelKey = resolveBriefFillCancelKey({
|
|
2802
|
+
requestId: input.requestId,
|
|
2803
|
+
pageRoute: input.pageRoute,
|
|
2804
|
+
target: input.target
|
|
2805
|
+
});
|
|
2806
|
+
const cancelToken = beginCancellableAgentTask(cancelKey);
|
|
2807
|
+
let result;
|
|
2808
|
+
try {
|
|
2809
|
+
result = await generateBriefFromImages(
|
|
2810
|
+
{
|
|
2811
|
+
target: input.target,
|
|
2812
|
+
images,
|
|
2813
|
+
contextNotes: input.contextNotes,
|
|
2814
|
+
pageRoute: input.pageRoute,
|
|
2815
|
+
cancelKey
|
|
2816
|
+
},
|
|
2817
|
+
{ projectDir }
|
|
2818
|
+
);
|
|
2819
|
+
} finally {
|
|
2820
|
+
endCancellableAgentTask(cancelKey, cancelToken);
|
|
2821
|
+
}
|
|
2838
2822
|
const referenceAttachments = [];
|
|
2839
2823
|
if (input.requestId) {
|
|
2840
2824
|
for (const file of imageFiles) {
|
|
@@ -2863,6 +2847,9 @@ const generateAddPageBriefFromImageAction = makeJayQuery(
|
|
|
2863
2847
|
referenceAttachments
|
|
2864
2848
|
};
|
|
2865
2849
|
} catch (err) {
|
|
2850
|
+
if (err instanceof BriefFillCancelledError) {
|
|
2851
|
+
return { ok: false, error: err.message };
|
|
2852
|
+
}
|
|
2866
2853
|
return {
|
|
2867
2854
|
ok: false,
|
|
2868
2855
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -4374,7 +4361,6 @@ function detectedToPageAssetEntry(detected) {
|
|
|
4374
4361
|
prompt: detected.prompt,
|
|
4375
4362
|
source: "detected",
|
|
4376
4363
|
itemId: detected.pluginName ? `${detected.pluginName}:${detected.contractName ?? ""}` : void 0,
|
|
4377
|
-
persistOnPage: true,
|
|
4378
4364
|
addedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4379
4365
|
detectedKey: detected.detectedKey,
|
|
4380
4366
|
detectedMeta: {
|
|
@@ -4596,6 +4582,34 @@ async function setupAiditor(ctx) {
|
|
|
4596
4582
|
...filesUpdated.length > 0 ? { filesUpdated } : {}
|
|
4597
4583
|
};
|
|
4598
4584
|
}
|
|
4585
|
+
const BLOCKED_TAGS = /<\s*(script|iframe|object|embed)\b[^>]*>[\s\S]*?<\/\s*\1\s*>|<\s*(script|iframe|object|embed)\b[^>]*\/?>/gi;
|
|
4586
|
+
const EVENT_HANDLER_ATTR = /\s+on[a-z]+\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/gi;
|
|
4587
|
+
const JAVASCRIPT_URL = /\b(href|src|xlink:href)\s*=\s*("|')\s*javascript:/gi;
|
|
4588
|
+
function sanitizeAddMenuHtmlFragment(html) {
|
|
4589
|
+
let result = html;
|
|
4590
|
+
result = result.replace(BLOCKED_TAGS, "");
|
|
4591
|
+
BLOCKED_TAGS.lastIndex = 0;
|
|
4592
|
+
result = result.replace(EVENT_HANDLER_ATTR, "");
|
|
4593
|
+
EVENT_HANDLER_ATTR.lastIndex = 0;
|
|
4594
|
+
result = result.replace(JAVASCRIPT_URL, "");
|
|
4595
|
+
JAVASCRIPT_URL.lastIndex = 0;
|
|
4596
|
+
return result.trim();
|
|
4597
|
+
}
|
|
4598
|
+
function isGifPath(src) {
|
|
4599
|
+
return /\.gif($|\?)/i.test(src.trim());
|
|
4600
|
+
}
|
|
4601
|
+
function normalizeAddMenuPresentation(item) {
|
|
4602
|
+
if (item.presentation) return item.presentation;
|
|
4603
|
+
const thumbnail = item.thumbnail?.trim();
|
|
4604
|
+
if (!thumbnail) return void 0;
|
|
4605
|
+
if (isGifPath(thumbnail)) {
|
|
4606
|
+
return { type: "gif", src: thumbnail };
|
|
4607
|
+
}
|
|
4608
|
+
return { type: "image", src: thumbnail };
|
|
4609
|
+
}
|
|
4610
|
+
function normalizeAddMenuBrowseSize(item) {
|
|
4611
|
+
return item.browse?.size ?? "medium";
|
|
4612
|
+
}
|
|
4599
4613
|
const aiditorShell = makeJayStackComponent().withProps().withSlowlyRender(async () => {
|
|
4600
4614
|
return phaseOutput({}, { headline: "AIditor" });
|
|
4601
4615
|
}).withFastRender(async (_props, carryForward) => {
|
|
@@ -4626,16 +4640,20 @@ export {
|
|
|
4626
4640
|
getPageParamsAction,
|
|
4627
4641
|
getPluginSetupStatusAction,
|
|
4628
4642
|
getProjectInfoAction,
|
|
4643
|
+
listAddMenuItems,
|
|
4629
4644
|
listAddMenuItemsAction,
|
|
4630
4645
|
listFreezesAction,
|
|
4631
4646
|
listJayPluginsAction,
|
|
4632
4647
|
listPluginContractsAction,
|
|
4648
|
+
normalizeAddMenuBrowseSize,
|
|
4649
|
+
normalizeAddMenuPresentation,
|
|
4633
4650
|
openAddPageFromBriefAction,
|
|
4634
4651
|
readFileAction,
|
|
4635
4652
|
reclassifyAddPageAssetAction,
|
|
4636
4653
|
rerunPluginSetupAction,
|
|
4637
4654
|
resolveAddMenuContractParamsAction,
|
|
4638
4655
|
runAiditorPublishAction,
|
|
4656
|
+
sanitizeAddMenuHtmlFragment,
|
|
4639
4657
|
saveAddPageDraftAction,
|
|
4640
4658
|
savePageAssetsAction,
|
|
4641
4659
|
savePageMetaAction,
|