@veolab/discoverylab 1.4.4 → 1.6.5
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +70 -211
- package/assets/applab-bundle-icon.png +0 -0
- package/assets/icons/icons8-claude-150.png +0 -0
- package/assets/icons/icons8-claude-500.png +0 -0
- package/dist/{chunk-CUBQRT5L.js → chunk-JAA53ES7.js} +111 -2
- package/dist/{chunk-HB3YPWF3.js → chunk-Q7Q3A2ZI.js} +301 -10
- package/dist/{chunk-XKX6NBHF.js → chunk-TWRWARU4.js} +52 -2
- package/dist/{chunk-2UUMLAVR.js → chunk-V6RREMYD.js} +332 -38
- package/dist/cli.js +164 -28
- package/dist/export/infographic-template.html +254 -0
- package/dist/import-W2JEW254.js +180 -0
- package/dist/index.d.ts +30 -6
- package/dist/index.html +473 -11
- package/dist/index.js +5 -5
- package/dist/infographic-GQAHEOAA.js +183 -0
- package/dist/mcpb/node_modules/@anthropic-ai/sdk/src/lib/.keep +4 -0
- package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/Release/better_sqlite3.node.d +1 -0
- package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/Release/obj.target/better_sqlite3/src/better_sqlite3.o.d +133 -0
- package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/Release/obj.target/deps/locate_sqlite3.stamp.d +1 -0
- package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/Release/obj.target/sqlite3/gen/sqlite3/sqlite3.o.d +4 -0
- package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/Release/obj.target/test_extension/deps/test_extension.o.d +7 -0
- package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/Release/sqlite3.a.d +1 -0
- package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/Release/test_extension.node.d +1 -0
- package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/ba23eeee118cd63e16015df367567cb043fed872.intermediate.d +1 -0
- package/dist/{server-QFNKZCOJ.js → server-C2NZM2RV.js} +1 -1
- package/dist/{server-OVOACIOJ.js → server-WN6DCCUA.js} +1 -1
- package/dist/{setup-6JJYKKBS.js → setup-SMN7FJNZ.js} +5 -2
- package/dist/{tools-Q7OZO732.js → tools-VXU3JEQP.js} +6 -4
- package/doc/esvp-protocol.md +116 -0
- package/package.json +9 -3
- package/skills/knowledge-brain/SKILL.md +44 -43
package/dist/index.d.ts
CHANGED
|
@@ -13,16 +13,35 @@ interface MCPTool {
|
|
|
13
13
|
name: string;
|
|
14
14
|
description: string;
|
|
15
15
|
inputSchema: z.ZodType<any>;
|
|
16
|
+
_meta?: Record<string, any>;
|
|
16
17
|
handler: (params: any) => Promise<MCPToolResult>;
|
|
17
18
|
}
|
|
19
|
+
interface MCPToolContent {
|
|
20
|
+
type: 'text' | 'image';
|
|
21
|
+
text?: string;
|
|
22
|
+
data?: string;
|
|
23
|
+
mimeType?: string;
|
|
24
|
+
}
|
|
18
25
|
interface MCPToolResult {
|
|
19
|
-
content:
|
|
20
|
-
type: 'text' | 'image';
|
|
21
|
-
text?: string;
|
|
22
|
-
data?: string;
|
|
23
|
-
mimeType?: string;
|
|
24
|
-
}>;
|
|
26
|
+
content: MCPToolContent[];
|
|
25
27
|
isError?: boolean;
|
|
28
|
+
structuredContent?: Record<string, any>;
|
|
29
|
+
_meta?: Record<string, any>;
|
|
30
|
+
}
|
|
31
|
+
interface MCPResourceContents {
|
|
32
|
+
uri: string;
|
|
33
|
+
mimeType: string;
|
|
34
|
+
text?: string;
|
|
35
|
+
blob?: string;
|
|
36
|
+
_meta?: Record<string, any>;
|
|
37
|
+
}
|
|
38
|
+
interface MCPResource {
|
|
39
|
+
uri: string;
|
|
40
|
+
name: string;
|
|
41
|
+
title?: string;
|
|
42
|
+
description?: string;
|
|
43
|
+
mimeType: string;
|
|
44
|
+
contents?: MCPResourceContents[];
|
|
26
45
|
}
|
|
27
46
|
interface MCPRequest {
|
|
28
47
|
jsonrpc: '2.0';
|
|
@@ -42,12 +61,17 @@ interface MCPResponse {
|
|
|
42
61
|
}
|
|
43
62
|
declare class MCPServer {
|
|
44
63
|
private tools;
|
|
64
|
+
private resources;
|
|
45
65
|
private serverInfo;
|
|
46
66
|
registerTool(tool: MCPTool): void;
|
|
47
67
|
registerTools(tools: MCPTool[]): void;
|
|
68
|
+
registerResource(resource: MCPResource): void;
|
|
69
|
+
upsertResourceContents(uri: string, resource: Omit<MCPResource, 'uri'>): void;
|
|
48
70
|
handleRequest(request: MCPRequest): Promise<MCPResponse>;
|
|
49
71
|
private handleInitialize;
|
|
50
72
|
private handleToolsList;
|
|
73
|
+
private handleResourcesList;
|
|
74
|
+
private handleResourcesRead;
|
|
51
75
|
private handleToolCall;
|
|
52
76
|
private zodToJsonSchema;
|
|
53
77
|
runStdio(): Promise<void>;
|
package/dist/index.html
CHANGED
|
@@ -806,6 +806,10 @@
|
|
|
806
806
|
opacity: 1;
|
|
807
807
|
}
|
|
808
808
|
|
|
809
|
+
.project-card.select-mode .project-claude-action {
|
|
810
|
+
display: none;
|
|
811
|
+
}
|
|
812
|
+
|
|
809
813
|
.project-card.select-mode.checked .checkbox-circle {
|
|
810
814
|
opacity: 0;
|
|
811
815
|
}
|
|
@@ -920,6 +924,44 @@
|
|
|
920
924
|
object-fit: cover;
|
|
921
925
|
}
|
|
922
926
|
|
|
927
|
+
.project-claude-action {
|
|
928
|
+
position: absolute;
|
|
929
|
+
top: 8px;
|
|
930
|
+
right: 8px;
|
|
931
|
+
display: inline-flex;
|
|
932
|
+
align-items: center;
|
|
933
|
+
justify-content: center;
|
|
934
|
+
width: 32px;
|
|
935
|
+
height: 32px;
|
|
936
|
+
border-radius: 999px;
|
|
937
|
+
border: 1px solid rgba(255, 255, 255, 0.18);
|
|
938
|
+
background: rgba(11, 16, 24, 0.78);
|
|
939
|
+
color: #f5f0e6;
|
|
940
|
+
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.22);
|
|
941
|
+
z-index: 2;
|
|
942
|
+
cursor: pointer;
|
|
943
|
+
transition: transform 0.15s ease, border-color 0.15s ease, background 0.15s ease;
|
|
944
|
+
backdrop-filter: blur(10px);
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
.project-claude-action.secondary {
|
|
948
|
+
background: rgba(18, 24, 34, 0.6);
|
|
949
|
+
border-color: rgba(255, 255, 255, 0.1);
|
|
950
|
+
color: var(--text-secondary);
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
.project-claude-action:hover {
|
|
954
|
+
transform: translateY(-1px);
|
|
955
|
+
border-color: rgba(245, 240, 230, 0.5);
|
|
956
|
+
background: rgba(17, 24, 32, 0.92);
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
.project-claude-action svg,
|
|
960
|
+
.project-claude-action img {
|
|
961
|
+
width: 16px;
|
|
962
|
+
height: 16px;
|
|
963
|
+
}
|
|
964
|
+
|
|
923
965
|
.project-info {
|
|
924
966
|
padding: 12px;
|
|
925
967
|
}
|
|
@@ -987,6 +1029,84 @@
|
|
|
987
1029
|
font-weight: 700;
|
|
988
1030
|
}
|
|
989
1031
|
|
|
1032
|
+
.claude-integration-row {
|
|
1033
|
+
display: flex;
|
|
1034
|
+
align-items: center;
|
|
1035
|
+
justify-content: space-between;
|
|
1036
|
+
gap: 12px;
|
|
1037
|
+
margin-top: 10px;
|
|
1038
|
+
padding-top: 10px;
|
|
1039
|
+
border-top: 1px solid var(--border);
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
.claude-integration-meta {
|
|
1043
|
+
min-width: 0;
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
.claude-integration-title {
|
|
1047
|
+
font-size: 11px;
|
|
1048
|
+
color: var(--text-muted);
|
|
1049
|
+
font-weight: 600;
|
|
1050
|
+
text-transform: uppercase;
|
|
1051
|
+
letter-spacing: 0.4px;
|
|
1052
|
+
margin-bottom: 4px;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
.claude-integration-copy {
|
|
1056
|
+
font-size: 12px;
|
|
1057
|
+
color: var(--text-secondary);
|
|
1058
|
+
line-height: 1.45;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
.claude-integration-actions {
|
|
1062
|
+
display: flex;
|
|
1063
|
+
align-items: center;
|
|
1064
|
+
gap: 8px;
|
|
1065
|
+
flex-shrink: 0;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
.claude-action-btn {
|
|
1069
|
+
display: inline-flex;
|
|
1070
|
+
align-items: center;
|
|
1071
|
+
gap: 8px;
|
|
1072
|
+
border: 1px solid rgba(236, 229, 215, 0.18);
|
|
1073
|
+
background: linear-gradient(135deg, rgba(34, 25, 18, 0.96), rgba(17, 12, 9, 0.96));
|
|
1074
|
+
color: #f5f0e6;
|
|
1075
|
+
padding: 9px 12px;
|
|
1076
|
+
border-radius: 10px;
|
|
1077
|
+
cursor: pointer;
|
|
1078
|
+
transition: transform 0.15s ease, border-color 0.15s ease, opacity 0.15s ease;
|
|
1079
|
+
font-size: 12px;
|
|
1080
|
+
font-weight: 600;
|
|
1081
|
+
box-shadow: 0 14px 28px rgba(0, 0, 0, 0.18);
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
.claude-action-btn:hover {
|
|
1085
|
+
transform: translateY(-1px);
|
|
1086
|
+
border-color: rgba(245, 240, 230, 0.34);
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
.claude-action-btn.secondary {
|
|
1090
|
+
background: var(--bg-tertiary);
|
|
1091
|
+
color: var(--text-secondary);
|
|
1092
|
+
box-shadow: none;
|
|
1093
|
+
border-color: var(--border);
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
.claude-action-btn:disabled {
|
|
1097
|
+
opacity: 0.56;
|
|
1098
|
+
cursor: default;
|
|
1099
|
+
transform: none;
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
.claude-action-btn svg,
|
|
1103
|
+
.claude-action-btn img {
|
|
1104
|
+
width: 14px;
|
|
1105
|
+
height: 14px;
|
|
1106
|
+
flex-shrink: 0;
|
|
1107
|
+
object-fit: contain;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
990
1110
|
.project-meta {
|
|
991
1111
|
font-size: 11px;
|
|
992
1112
|
color: var(--text-muted);
|
|
@@ -6795,7 +6915,7 @@
|
|
|
6795
6915
|
<span>App Intelligence</span>
|
|
6796
6916
|
</div>
|
|
6797
6917
|
<div class="welcome-footnote">
|
|
6798
|
-
Built with the open
|
|
6918
|
+
Built with the open ESVP protocol by Entropy Lab for reproducible mobile sessions, replay, and network-aware validation.
|
|
6799
6919
|
</div>
|
|
6800
6920
|
</div>
|
|
6801
6921
|
</div>
|
|
@@ -8109,6 +8229,265 @@
|
|
|
8109
8229
|
}
|
|
8110
8230
|
}
|
|
8111
8231
|
|
|
8232
|
+
let claudeDesktopStatus = {
|
|
8233
|
+
ready: false,
|
|
8234
|
+
appDetected: false,
|
|
8235
|
+
launcherSupported: false,
|
|
8236
|
+
mcpConfigured: false,
|
|
8237
|
+
serverName: null,
|
|
8238
|
+
installCommand: 'npx -y @veolab/discoverylab@latest install --target desktop',
|
|
8239
|
+
message: 'Checking Claude Desktop...',
|
|
8240
|
+
checking: false,
|
|
8241
|
+
error: null,
|
|
8242
|
+
lastCheckedAt: null
|
|
8243
|
+
};
|
|
8244
|
+
|
|
8245
|
+
function getClaudeIconSvg() {
|
|
8246
|
+
return `
|
|
8247
|
+
<img src="/assets/icons/icons8-claude-150.png" alt="" aria-hidden="true" />
|
|
8248
|
+
`;
|
|
8249
|
+
}
|
|
8250
|
+
|
|
8251
|
+
function projectHasRenderableThumb(project) {
|
|
8252
|
+
if (!project) return false;
|
|
8253
|
+
if (project.thumbnailPath) return true;
|
|
8254
|
+
if (!project.videoPath) return false;
|
|
8255
|
+
|
|
8256
|
+
const ext = String(project.videoPath).toLowerCase().split('.').pop();
|
|
8257
|
+
return ['png', 'jpg', 'jpeg', 'gif', 'webp', 'mp4', 'mov', 'webm'].includes(ext);
|
|
8258
|
+
}
|
|
8259
|
+
|
|
8260
|
+
function isProjectReadyForClaude(project) {
|
|
8261
|
+
if (!project) return false;
|
|
8262
|
+
if (isProjectAnalyzing(project.status || '')) return false;
|
|
8263
|
+
return Boolean(
|
|
8264
|
+
(project.aiSummary && project.aiSummary.trim()) ||
|
|
8265
|
+
(project.ocrText && project.ocrText.trim()) ||
|
|
8266
|
+
(Array.isArray(project.frames) && project.frames.length > 0) ||
|
|
8267
|
+
project.frameCount > 0
|
|
8268
|
+
);
|
|
8269
|
+
}
|
|
8270
|
+
|
|
8271
|
+
function buildClaudeDesktopPrompt(project) {
|
|
8272
|
+
const projectId = project?.id || '';
|
|
8273
|
+
const projectName = project?.name || 'this DiscoveryLab project';
|
|
8274
|
+
return [
|
|
8275
|
+
`Use DiscoveryLab local tools to open project "${projectName}" (projectId: "${projectId}") in an interactive flow canvas.`,
|
|
8276
|
+
`Call dlab.knowledge.open with projectId "${projectId}".`,
|
|
8277
|
+
'After opening the canvas, explain the flow, key screens, and important risks or opportunities.',
|
|
8278
|
+
].join(' ');
|
|
8279
|
+
}
|
|
8280
|
+
|
|
8281
|
+
function renderClaudeProjectQuickAction(project) {
|
|
8282
|
+
if (!isProjectReadyForClaude(project) || !claudeDesktopStatus.launcherSupported || !projectHasRenderableThumb(project)) {
|
|
8283
|
+
return '';
|
|
8284
|
+
}
|
|
8285
|
+
|
|
8286
|
+
const setupNeeded = claudeDesktopStatus.appDetected && !claudeDesktopStatus.mcpConfigured;
|
|
8287
|
+
const ready = claudeDesktopStatus.ready;
|
|
8288
|
+
const promptTitle = ready
|
|
8289
|
+
? `Copy prompt and open ${project.name} in Claude Desktop`
|
|
8290
|
+
: setupNeeded
|
|
8291
|
+
? `Copy the ${project.name} prompt and open Claude Desktop`
|
|
8292
|
+
: `Copy the ${project.name} prompt and check Claude Desktop`;
|
|
8293
|
+
const buttonClass = ready ? 'project-claude-action' : 'project-claude-action secondary';
|
|
8294
|
+
|
|
8295
|
+
return `
|
|
8296
|
+
<button
|
|
8297
|
+
class="${buttonClass}"
|
|
8298
|
+
type="button"
|
|
8299
|
+
data-project-id="${escapeAttr(project.id)}"
|
|
8300
|
+
title="${escapeAttr(promptTitle)}"
|
|
8301
|
+
aria-label="${escapeAttr(promptTitle)}"
|
|
8302
|
+
onclick="event.stopPropagation(); openProjectInClaudeById(this.dataset.projectId);"
|
|
8303
|
+
>
|
|
8304
|
+
${getClaudeIconSvg()}
|
|
8305
|
+
</button>
|
|
8306
|
+
`;
|
|
8307
|
+
}
|
|
8308
|
+
|
|
8309
|
+
function renderClaudeProjectLaunchRow(project) {
|
|
8310
|
+
const projectReady = isProjectReadyForClaude(project);
|
|
8311
|
+
const statusCopy = !projectReady
|
|
8312
|
+
? 'Finish analysis or capture enough frames before opening this project in Claude Desktop.'
|
|
8313
|
+
: claudeDesktopStatus.error
|
|
8314
|
+
? claudeDesktopStatus.error
|
|
8315
|
+
: claudeDesktopStatus.message || 'Claude Desktop status unavailable.';
|
|
8316
|
+
const ready = claudeDesktopStatus.ready && projectReady;
|
|
8317
|
+
const setupNeeded = claudeDesktopStatus.appDetected && !claudeDesktopStatus.mcpConfigured;
|
|
8318
|
+
const buttonLabel = ready
|
|
8319
|
+
? 'Open in Claude Desktop'
|
|
8320
|
+
: !projectReady
|
|
8321
|
+
? 'Analyze first'
|
|
8322
|
+
: setupNeeded
|
|
8323
|
+
? 'Copy prompt'
|
|
8324
|
+
: 'Reload';
|
|
8325
|
+
const buttonClass = ready ? 'claude-action-btn' : 'claude-action-btn secondary';
|
|
8326
|
+
const action = ready
|
|
8327
|
+
? 'openCurrentProjectInClaude()'
|
|
8328
|
+
: !projectReady
|
|
8329
|
+
? ''
|
|
8330
|
+
: setupNeeded
|
|
8331
|
+
? 'copyCurrentProjectClaudePrompt()'
|
|
8332
|
+
: 'refreshClaudeDesktopStatus()';
|
|
8333
|
+
|
|
8334
|
+
return `
|
|
8335
|
+
<div class="claude-integration-row">
|
|
8336
|
+
<div class="claude-integration-meta">
|
|
8337
|
+
<div class="claude-integration-title">Claude Desktop</div>
|
|
8338
|
+
<div class="claude-integration-copy">${escapeHtml(statusCopy)}</div>
|
|
8339
|
+
</div>
|
|
8340
|
+
<div class="claude-integration-actions">
|
|
8341
|
+
<button class="${buttonClass}" type="button" ${action ? `onclick="${action}"` : 'disabled'}>
|
|
8342
|
+
${getClaudeIconSvg()}
|
|
8343
|
+
<span>${escapeHtml(buttonLabel)}</span>
|
|
8344
|
+
</button>
|
|
8345
|
+
</div>
|
|
8346
|
+
</div>
|
|
8347
|
+
`;
|
|
8348
|
+
}
|
|
8349
|
+
|
|
8350
|
+
function rerenderClaudeDesktopAffordances() {
|
|
8351
|
+
if (currentView === 'projects') {
|
|
8352
|
+
renderProjects();
|
|
8353
|
+
} else if (currentView === 'analysis' && currentProject) {
|
|
8354
|
+
updateAnalysisTab();
|
|
8355
|
+
} else if (currentView === 'export' && currentProject) {
|
|
8356
|
+
updateExportTab();
|
|
8357
|
+
}
|
|
8358
|
+
}
|
|
8359
|
+
|
|
8360
|
+
async function refreshClaudeDesktopStatus(options = {}) {
|
|
8361
|
+
const { silent = false } = options;
|
|
8362
|
+
claudeDesktopStatus.checking = true;
|
|
8363
|
+
|
|
8364
|
+
try {
|
|
8365
|
+
const response = await fetch('/api/integrations/claude-desktop/status');
|
|
8366
|
+
const data = await response.json();
|
|
8367
|
+
if (data?.error) {
|
|
8368
|
+
throw new Error(data.error);
|
|
8369
|
+
}
|
|
8370
|
+
|
|
8371
|
+
claudeDesktopStatus = {
|
|
8372
|
+
...claudeDesktopStatus,
|
|
8373
|
+
ready: !!data.ready,
|
|
8374
|
+
appDetected: !!data.appDetected,
|
|
8375
|
+
launcherSupported: !!data.launcherSupported,
|
|
8376
|
+
mcpConfigured: !!data.mcpConfigured,
|
|
8377
|
+
serverName: data.serverName || null,
|
|
8378
|
+
installCommand: data.installCommand || claudeDesktopStatus.installCommand,
|
|
8379
|
+
message: data.message || 'Claude Desktop status loaded.',
|
|
8380
|
+
checking: false,
|
|
8381
|
+
error: null,
|
|
8382
|
+
lastCheckedAt: new Date().toISOString()
|
|
8383
|
+
};
|
|
8384
|
+
} catch (error) {
|
|
8385
|
+
claudeDesktopStatus = {
|
|
8386
|
+
...claudeDesktopStatus,
|
|
8387
|
+
checking: false,
|
|
8388
|
+
error: error instanceof Error ? error.message : 'Failed to check Claude Desktop status',
|
|
8389
|
+
message: 'Could not check Claude Desktop status.'
|
|
8390
|
+
};
|
|
8391
|
+
if (!silent) {
|
|
8392
|
+
showToast('Failed to check Claude Desktop status', 'error');
|
|
8393
|
+
}
|
|
8394
|
+
}
|
|
8395
|
+
|
|
8396
|
+
rerenderClaudeDesktopAffordances();
|
|
8397
|
+
}
|
|
8398
|
+
|
|
8399
|
+
function copyClaudeDesktopInstallCommand() {
|
|
8400
|
+
void copyToClipboard(
|
|
8401
|
+
claudeDesktopStatus.installCommand || 'npx -y @veolab/discoverylab@latest install --target desktop',
|
|
8402
|
+
{ silent: true }
|
|
8403
|
+
).then((copied) => {
|
|
8404
|
+
showToast(copied ? 'Claude Desktop install command copied' : 'Failed to copy install command', copied ? 'success' : 'error');
|
|
8405
|
+
});
|
|
8406
|
+
}
|
|
8407
|
+
|
|
8408
|
+
async function copyClaudeProjectPrompt(project) {
|
|
8409
|
+
if (!project) return false;
|
|
8410
|
+
|
|
8411
|
+
const copied = await copyToClipboard(buildClaudeDesktopPrompt(project), { silent: true });
|
|
8412
|
+
if (!copied) {
|
|
8413
|
+
showToast('Failed to copy Claude Desktop prompt', 'error');
|
|
8414
|
+
return false;
|
|
8415
|
+
}
|
|
8416
|
+
|
|
8417
|
+
return true;
|
|
8418
|
+
}
|
|
8419
|
+
|
|
8420
|
+
async function copyCurrentProjectClaudePrompt() {
|
|
8421
|
+
if (!currentProject?.id) {
|
|
8422
|
+
showToast('Select a project first', 'warning');
|
|
8423
|
+
return;
|
|
8424
|
+
}
|
|
8425
|
+
|
|
8426
|
+
const copied = await copyClaudeProjectPrompt(currentProject);
|
|
8427
|
+
if (!copied) return;
|
|
8428
|
+
|
|
8429
|
+
showToast('Claude Desktop prompt copied', 'success');
|
|
8430
|
+
}
|
|
8431
|
+
|
|
8432
|
+
async function launchClaudeDesktop() {
|
|
8433
|
+
const response = await fetch('/api/integrations/claude-desktop/launch', { method: 'POST' });
|
|
8434
|
+
const data = await response.json();
|
|
8435
|
+
if (!response.ok || data?.success === false) {
|
|
8436
|
+
throw new Error(data?.error || 'Failed to open Claude Desktop');
|
|
8437
|
+
}
|
|
8438
|
+
}
|
|
8439
|
+
|
|
8440
|
+
async function copyPromptAndLaunchClaude(project) {
|
|
8441
|
+
if (!project) return;
|
|
8442
|
+
|
|
8443
|
+
const copied = await copyClaudeProjectPrompt(project);
|
|
8444
|
+
if (!copied) {
|
|
8445
|
+
return;
|
|
8446
|
+
}
|
|
8447
|
+
|
|
8448
|
+
try {
|
|
8449
|
+
await launchClaudeDesktop();
|
|
8450
|
+
showToast('Prompt copied and Claude Desktop opened', 'success');
|
|
8451
|
+
} catch (error) {
|
|
8452
|
+
showToast(error instanceof Error ? error.message : 'Prompt copied, but Claude Desktop could not be opened', 'warning');
|
|
8453
|
+
}
|
|
8454
|
+
}
|
|
8455
|
+
|
|
8456
|
+
async function openProjectInClaudeById(projectId) {
|
|
8457
|
+
const project = projects.find((item) => item.id === projectId) || (currentProject?.id === projectId ? currentProject : null);
|
|
8458
|
+
if (!project) {
|
|
8459
|
+
showToast('Project not found', 'error');
|
|
8460
|
+
return;
|
|
8461
|
+
}
|
|
8462
|
+
|
|
8463
|
+
if (!claudeDesktopStatus.ready) {
|
|
8464
|
+
if (claudeDesktopStatus.appDetected && !claudeDesktopStatus.mcpConfigured) {
|
|
8465
|
+
const copied = await copyClaudeProjectPrompt(project);
|
|
8466
|
+
if (copied) {
|
|
8467
|
+
showToast('Project prompt copied. Enable the DiscoveryLab extension in Claude Desktop to open it there.', 'warning');
|
|
8468
|
+
}
|
|
8469
|
+
return;
|
|
8470
|
+
}
|
|
8471
|
+
|
|
8472
|
+
const copied = await copyClaudeProjectPrompt(project);
|
|
8473
|
+
if (copied) {
|
|
8474
|
+
showToast(claudeDesktopStatus.message || 'Project prompt copied. Claude Desktop is not ready yet.', 'warning');
|
|
8475
|
+
}
|
|
8476
|
+
return;
|
|
8477
|
+
}
|
|
8478
|
+
|
|
8479
|
+
await copyPromptAndLaunchClaude(project);
|
|
8480
|
+
}
|
|
8481
|
+
|
|
8482
|
+
async function openCurrentProjectInClaude() {
|
|
8483
|
+
if (!currentProject?.id) {
|
|
8484
|
+
showToast('Select a project first', 'warning');
|
|
8485
|
+
return;
|
|
8486
|
+
}
|
|
8487
|
+
|
|
8488
|
+
await openProjectInClaudeById(currentProject.id);
|
|
8489
|
+
}
|
|
8490
|
+
|
|
8112
8491
|
let jiraMcpStatus = {
|
|
8113
8492
|
available: false,
|
|
8114
8493
|
configured: false,
|
|
@@ -11288,6 +11667,7 @@
|
|
|
11288
11667
|
<div class="processing-text">${processingText}</div>
|
|
11289
11668
|
</div>
|
|
11290
11669
|
<div class="project-thumb">
|
|
11670
|
+
${renderClaudeProjectQuickAction(p)}
|
|
11291
11671
|
${getProjectThumb(p)}
|
|
11292
11672
|
</div>
|
|
11293
11673
|
<div class="project-info">
|
|
@@ -12418,6 +12798,7 @@
|
|
|
12418
12798
|
<button class="btn btn-primary btn-small" onclick="retryProjectAnalysis()" id="retryProjectAnalysisBtn">Retry Analysis</button>
|
|
12419
12799
|
</div>
|
|
12420
12800
|
` : ''}
|
|
12801
|
+
${renderClaudeProjectLaunchRow(currentProject)}
|
|
12421
12802
|
<div class="project-integration-row">
|
|
12422
12803
|
<div class="project-integration-label">Jira MCP</div>
|
|
12423
12804
|
<div class="project-integration-status">
|
|
@@ -12864,6 +13245,23 @@
|
|
|
12864
13245
|
|
|
12865
13246
|
if (favoriteTemplate && currentTemplateProps?.templatesAllowed !== false) {
|
|
12866
13247
|
switchTemplate(favoriteTemplate);
|
|
13248
|
+
} else if (currentTemplateProps?.templatesAllowed !== false) {
|
|
13249
|
+
// Auto-select cached template if available (no re-render needed)
|
|
13250
|
+
const templates = templateStatus.templates || [];
|
|
13251
|
+
for (const t of templates) {
|
|
13252
|
+
try {
|
|
13253
|
+
const checkRes = await fetch('/api/templates/render', {
|
|
13254
|
+
method: 'POST',
|
|
13255
|
+
headers: { 'Content-Type': 'application/json' },
|
|
13256
|
+
body: JSON.stringify({ projectId: currentProject?.id, templateId: t.id }),
|
|
13257
|
+
});
|
|
13258
|
+
const checkData = await checkRes.json();
|
|
13259
|
+
if (checkData.cached) {
|
|
13260
|
+
switchTemplate(t.id);
|
|
13261
|
+
break;
|
|
13262
|
+
}
|
|
13263
|
+
} catch { /* skip */ }
|
|
13264
|
+
}
|
|
12867
13265
|
}
|
|
12868
13266
|
} catch (e) {
|
|
12869
13267
|
console.log('[Templates] Init error:', e);
|
|
@@ -12983,7 +13381,7 @@
|
|
|
12983
13381
|
}
|
|
12984
13382
|
}
|
|
12985
13383
|
|
|
12986
|
-
async function switchTemplate(templateId) {
|
|
13384
|
+
async function switchTemplate(templateId, force = false) {
|
|
12987
13385
|
// Skip if already on this template
|
|
12988
13386
|
if (templateId === activeTemplate) return;
|
|
12989
13387
|
if (templateId !== 'raw' && currentTemplateProps?.templatesAllowed === false) {
|
|
@@ -13028,7 +13426,7 @@
|
|
|
13028
13426
|
const res = await fetch('/api/templates/render', {
|
|
13029
13427
|
method: 'POST',
|
|
13030
13428
|
headers: { 'Content-Type': 'application/json' },
|
|
13031
|
-
body: JSON.stringify({ projectId: currentProject.id, templateId }),
|
|
13429
|
+
body: JSON.stringify({ projectId: currentProject.id, templateId, force }),
|
|
13032
13430
|
});
|
|
13033
13431
|
const data = await res.json();
|
|
13034
13432
|
|
|
@@ -13038,6 +13436,20 @@
|
|
|
13038
13436
|
return;
|
|
13039
13437
|
}
|
|
13040
13438
|
|
|
13439
|
+
// Cached render - show immediately without polling
|
|
13440
|
+
if (data.cached && data.previewUrl) {
|
|
13441
|
+
const skeleton = document.getElementById('templateSkeleton');
|
|
13442
|
+
const templateContainer = document.getElementById('templatePreviewContainer');
|
|
13443
|
+
const templateVideo = document.getElementById('templateVideo');
|
|
13444
|
+
if (skeleton) skeleton.style.display = 'none';
|
|
13445
|
+
if (templateVideo) {
|
|
13446
|
+
templateVideo.src = data.previewUrl + '&t=' + Date.now();
|
|
13447
|
+
templateVideo.load();
|
|
13448
|
+
}
|
|
13449
|
+
if (templateContainer) templateContainer.style.display = '';
|
|
13450
|
+
return;
|
|
13451
|
+
}
|
|
13452
|
+
|
|
13041
13453
|
if (data.jobId) {
|
|
13042
13454
|
pollRenderJob(data.jobId, templateId);
|
|
13043
13455
|
}
|
|
@@ -13490,11 +13902,11 @@
|
|
|
13490
13902
|
deviceMockup: data.content?.deviceMockup || deviceMockup,
|
|
13491
13903
|
};
|
|
13492
13904
|
|
|
13493
|
-
// Force re-render
|
|
13905
|
+
// Force re-render after content edit
|
|
13494
13906
|
if (activeTemplate !== 'raw') {
|
|
13495
13907
|
const prevTemplate = activeTemplate;
|
|
13496
13908
|
activeTemplate = '__force_rerender__';
|
|
13497
|
-
switchTemplate(prevTemplate);
|
|
13909
|
+
switchTemplate(prevTemplate, true);
|
|
13498
13910
|
}
|
|
13499
13911
|
} catch {
|
|
13500
13912
|
showToast('Failed to save content', 'error');
|
|
@@ -15571,9 +15983,34 @@
|
|
|
15571
15983
|
showToast(`Copied "${command}" - paste in Claude Code`, 'success', 5000);
|
|
15572
15984
|
}
|
|
15573
15985
|
|
|
15574
|
-
function copyToClipboard(text) {
|
|
15575
|
-
|
|
15576
|
-
|
|
15986
|
+
async function copyToClipboard(text, options = {}) {
|
|
15987
|
+
const { silent = false } = options;
|
|
15988
|
+
|
|
15989
|
+
try {
|
|
15990
|
+
if (navigator.clipboard?.writeText) {
|
|
15991
|
+
await navigator.clipboard.writeText(text);
|
|
15992
|
+
} else {
|
|
15993
|
+
const textarea = document.createElement('textarea');
|
|
15994
|
+
textarea.value = text;
|
|
15995
|
+
textarea.setAttribute('readonly', 'true');
|
|
15996
|
+
textarea.style.position = 'absolute';
|
|
15997
|
+
textarea.style.left = '-9999px';
|
|
15998
|
+
document.body.appendChild(textarea);
|
|
15999
|
+
textarea.select();
|
|
16000
|
+
document.execCommand('copy');
|
|
16001
|
+
textarea.remove();
|
|
16002
|
+
}
|
|
16003
|
+
|
|
16004
|
+
if (!silent) {
|
|
16005
|
+
showToast('Copied to clipboard', 'success');
|
|
16006
|
+
}
|
|
16007
|
+
return true;
|
|
16008
|
+
} catch (error) {
|
|
16009
|
+
if (!silent) {
|
|
16010
|
+
showToast('Failed to copy to clipboard', 'error');
|
|
16011
|
+
}
|
|
16012
|
+
return false;
|
|
16013
|
+
}
|
|
15577
16014
|
}
|
|
15578
16015
|
|
|
15579
16016
|
async function openMaestroStudio() {
|
|
@@ -15868,6 +16305,7 @@
|
|
|
15868
16305
|
if (el && data.version) el.textContent = 'v' + data.version;
|
|
15869
16306
|
}).catch(() => {});
|
|
15870
16307
|
void loadProxySafetySettings().catch(() => null);
|
|
16308
|
+
void refreshClaudeDesktopStatus({ silent: true });
|
|
15871
16309
|
|
|
15872
16310
|
// Auto-check dependencies on first load — open Settings if critical deps missing
|
|
15873
16311
|
fetch('/api/setup/status').then(r => r.json()).then(data => {
|
|
@@ -21984,8 +22422,8 @@ appId: ${platform === 'ios' ? 'com.apple.Preferences' : 'com.android.settings'}
|
|
|
21984
22422
|
jpg: 'Exports the current capture as JPEG images.',
|
|
21985
22423
|
mp4: 'Exports the current capture as an MP4 video.',
|
|
21986
22424
|
gif: 'Exports the current capture as an animated GIF.',
|
|
21987
|
-
applab: 'Packages
|
|
21988
|
-
esvp: 'Packages
|
|
22425
|
+
applab: 'Packages a Claude-friendly App Lab bundle: analyzed frames, thumbnail, OCR, app intelligence, network trace, ESVP snapshot, and Task Hub metadata without heavy renders or long recordings.',
|
|
22426
|
+
esvp: 'Packages a lightweight ESVP-ready bundle with analyzed frames, OCR, app intelligence, network trace, and the attached ESVP snapshot when available.',
|
|
21989
22427
|
};
|
|
21990
22428
|
|
|
21991
22429
|
help.textContent = descriptions[select.value] || '';
|
|
@@ -22043,13 +22481,37 @@ appId: ${platform === 'ios' ? 'com.apple.Preferences' : 'com.android.settings'}
|
|
|
22043
22481
|
<div id="exportFormatHelp" style="margin-top: 8px; font-size: 12px; color: var(--text-muted); line-height: 1.5;"></div>
|
|
22044
22482
|
</div>
|
|
22045
22483
|
|
|
22046
|
-
<
|
|
22484
|
+
<div style="display: flex; gap: 8px;">
|
|
22485
|
+
<button class="btn btn-primary" onclick="exportProject()">Export</button>
|
|
22486
|
+
<button class="btn btn-secondary" onclick="exportInfographicHtml()" style="font-size: 11px;">Infographic HTML</button>
|
|
22487
|
+
</div>
|
|
22047
22488
|
</div>
|
|
22048
22489
|
`;
|
|
22049
22490
|
|
|
22050
22491
|
updateExportFormatHelp();
|
|
22051
22492
|
}
|
|
22052
22493
|
|
|
22494
|
+
async function exportInfographicHtml() {
|
|
22495
|
+
if (!currentProject) return;
|
|
22496
|
+
showToast('Generating infographic...', 'info');
|
|
22497
|
+
try {
|
|
22498
|
+
const resp = await fetch('/api/export/infographic', {
|
|
22499
|
+
method: 'POST',
|
|
22500
|
+
headers: { 'Content-Type': 'application/json' },
|
|
22501
|
+
body: JSON.stringify({ projectId: currentProject.id, open: true }),
|
|
22502
|
+
});
|
|
22503
|
+
const data = await resp.json();
|
|
22504
|
+
if (data.success) {
|
|
22505
|
+
const sizeKb = ((data.size || 0) / 1024).toFixed(1);
|
|
22506
|
+
showToast(`Infographic exported (${sizeKb}KB, ${data.frameCount} frames)`, 'success');
|
|
22507
|
+
} else {
|
|
22508
|
+
showToast(data.error || 'Export failed', 'error');
|
|
22509
|
+
}
|
|
22510
|
+
} catch (err) {
|
|
22511
|
+
showToast('Export failed', 'error');
|
|
22512
|
+
}
|
|
22513
|
+
}
|
|
22514
|
+
|
|
22053
22515
|
async function exportProject() {
|
|
22054
22516
|
if (!currentProject) return;
|
|
22055
22517
|
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
startServer,
|
|
4
4
|
stopServer
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-V6RREMYD.js";
|
|
6
6
|
import {
|
|
7
7
|
analyzeTools,
|
|
8
8
|
canvasTools,
|
|
@@ -16,15 +16,15 @@ import {
|
|
|
16
16
|
templateTools,
|
|
17
17
|
testingTools,
|
|
18
18
|
uiTools
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-Q7Q3A2ZI.js";
|
|
20
|
+
import "./chunk-34GGYFXX.js";
|
|
20
21
|
import "./chunk-PMCXEA7J.js";
|
|
21
22
|
import {
|
|
22
23
|
setupTools
|
|
23
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-JAA53ES7.js";
|
|
24
25
|
import {
|
|
25
26
|
mcpServer
|
|
26
|
-
} from "./chunk-
|
|
27
|
-
import "./chunk-34GGYFXX.js";
|
|
27
|
+
} from "./chunk-TWRWARU4.js";
|
|
28
28
|
import "./chunk-6GK5K6CS.js";
|
|
29
29
|
import "./chunk-7R5YNOXE.js";
|
|
30
30
|
import "./chunk-3ERJNXYM.js";
|