zerochat 7.3.0__py3-none-any.whl
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.
- zerochat-7.3.0.dist-info/METADATA +70 -0
- zerochat-7.3.0.dist-info/RECORD +130 -0
- zerochat-7.3.0.dist-info/WHEEL +5 -0
- zerochat-7.3.0.dist-info/entry_points.txt +2 -0
- zerochat-7.3.0.dist-info/licenses/LICENSE +34 -0
- zerochat-7.3.0.dist-info/top_level.txt +2 -0
- zerochat.py +2004 -0
- zerochat_runtime/__init__.py +1 -0
- zerochat_runtime/assets/css/base.css +199 -0
- zerochat_runtime/assets/css/components/composer.css +1258 -0
- zerochat_runtime/assets/css/components/debug.css +777 -0
- zerochat_runtime/assets/css/components/header.css +97 -0
- zerochat_runtime/assets/css/components/icons.css +39 -0
- zerochat_runtime/assets/css/components/markdown.css +685 -0
- zerochat_runtime/assets/css/components/messages.css +473 -0
- zerochat_runtime/assets/css/components/modals.css +1319 -0
- zerochat_runtime/assets/css/components/sidebar.css +622 -0
- zerochat_runtime/assets/css/components/tools.css +1223 -0
- zerochat_runtime/assets/css/layout.css +171 -0
- zerochat_runtime/assets/css/print.css +120 -0
- zerochat_runtime/assets/css/styles.css +18 -0
- zerochat_runtime/assets/css/theme-overrides.css +555 -0
- zerochat_runtime/assets/css/tokens.css +165 -0
- zerochat_runtime/assets/help/architecture.html +247 -0
- zerochat_runtime/assets/help/composer.html +134 -0
- zerochat_runtime/assets/help/conversations.html +105 -0
- zerochat_runtime/assets/help/debug.html +108 -0
- zerochat_runtime/assets/help/en/architecture.html +247 -0
- zerochat_runtime/assets/help/en/composer.html +134 -0
- zerochat_runtime/assets/help/en/conversations.html +104 -0
- zerochat_runtime/assets/help/en/debug.html +105 -0
- zerochat_runtime/assets/help/en/gemini-free.html +39 -0
- zerochat_runtime/assets/help/en/index.html +191 -0
- zerochat_runtime/assets/help/en/learning.html +71 -0
- zerochat_runtime/assets/help/en/mcp.html +143 -0
- zerochat_runtime/assets/help/en/openrouter-free.html +39 -0
- zerochat_runtime/assets/help/en/profiles.html +173 -0
- zerochat_runtime/assets/help/en/rag.html +130 -0
- zerochat_runtime/assets/help/en/reasoning-telemetry.html +108 -0
- zerochat_runtime/assets/help/en/tools-agent.html +133 -0
- zerochat_runtime/assets/help/en/webllm.html +355 -0
- zerochat_runtime/assets/help/gemini-free.html +39 -0
- zerochat_runtime/assets/help/help.css +604 -0
- zerochat_runtime/assets/help/help.js +51 -0
- zerochat_runtime/assets/help/index.html +194 -0
- zerochat_runtime/assets/help/learning.html +71 -0
- zerochat_runtime/assets/help/mcp.html +143 -0
- zerochat_runtime/assets/help/openrouter-free.html +39 -0
- zerochat_runtime/assets/help/profiles.html +174 -0
- zerochat_runtime/assets/help/rag.html +130 -0
- zerochat_runtime/assets/help/reasoning-telemetry.html +111 -0
- zerochat_runtime/assets/help/tools-agent.html +133 -0
- zerochat_runtime/assets/help/webllm.html +359 -0
- zerochat_runtime/assets/js/agent-core.js +1553 -0
- zerochat_runtime/assets/js/api.js +844 -0
- zerochat_runtime/assets/js/app.js +2558 -0
- zerochat_runtime/assets/js/attachments.js +220 -0
- zerochat_runtime/assets/js/charts.js +338 -0
- zerochat_runtime/assets/js/chat-engine.js +566 -0
- zerochat_runtime/assets/js/config-store.js +207 -0
- zerochat_runtime/assets/js/context-manager.js +584 -0
- zerochat_runtime/assets/js/conversation-service.js +484 -0
- zerochat_runtime/assets/js/cookies.js +688 -0
- zerochat_runtime/assets/js/data-reset-service.js +136 -0
- zerochat_runtime/assets/js/debug.js +508 -0
- zerochat_runtime/assets/js/defaults.js +16 -0
- zerochat_runtime/assets/js/export.js +179 -0
- zerochat_runtime/assets/js/file-parser.js +2088 -0
- zerochat_runtime/assets/js/generation-controller.js +417 -0
- zerochat_runtime/assets/js/i18n.js +1483 -0
- zerochat_runtime/assets/js/icons.js +156 -0
- zerochat_runtime/assets/js/ingestionEngine.js +436 -0
- zerochat_runtime/assets/js/markdown.js +588 -0
- zerochat_runtime/assets/js/mcp.js +1271 -0
- zerochat_runtime/assets/js/message-turns.js +62 -0
- zerochat_runtime/assets/js/profile-backup.js +118 -0
- zerochat_runtime/assets/js/profile-export-bundle.js +481 -0
- zerochat_runtime/assets/js/profile-repository.js +213 -0
- zerochat_runtime/assets/js/providers-webllm.js +486 -0
- zerochat_runtime/assets/js/providers.js +1560 -0
- zerochat_runtime/assets/js/rag-index.js +295 -0
- zerochat_runtime/assets/js/rag-service.js +530 -0
- zerochat_runtime/assets/js/rag-ui.js +997 -0
- zerochat_runtime/assets/js/ragStorage.js +676 -0
- zerochat_runtime/assets/js/sandbox.js +449 -0
- zerochat_runtime/assets/js/state.js +704 -0
- zerochat_runtime/assets/js/storage-db.js +144 -0
- zerochat_runtime/assets/js/tool-cards.js +330 -0
- zerochat_runtime/assets/js/tool-security.js +653 -0
- zerochat_runtime/assets/js/tools/README.md +50 -0
- zerochat_runtime/assets/js/tools/builtin/agent-checkpoint.tool.js +212 -0
- zerochat_runtime/assets/js/tools/builtin/download-pdf.tool.js +111 -0
- zerochat_runtime/assets/js/tools/builtin/execute-javascript.tool.js +219 -0
- zerochat_runtime/assets/js/tools/builtin/fetch-web-page.tool.js +112 -0
- zerochat_runtime/assets/js/tools/builtin/list-documents.tool.js +117 -0
- zerochat_runtime/assets/js/tools/builtin/read-knowledge-chunk.tool.js +129 -0
- zerochat_runtime/assets/js/tools/builtin/read-knowledge-image.tool.js +95 -0
- zerochat_runtime/assets/js/tools/builtin/render-chart.tool.js +90 -0
- zerochat_runtime/assets/js/tools/builtin/search-knowledge-base.tool.js +124 -0
- zerochat_runtime/assets/js/tools/builtin/search-web.tool.js +125 -0
- zerochat_runtime/assets/js/tools/tool-manifest.js +53 -0
- zerochat_runtime/assets/js/tools/tool-runtime.js +77 -0
- zerochat_runtime/assets/js/ui-composer.js +319 -0
- zerochat_runtime/assets/js/ui-conversation.js +655 -0
- zerochat_runtime/assets/js/ui-dialogs.js +132 -0
- zerochat_runtime/assets/js/ui-generation-status.js +119 -0
- zerochat_runtime/assets/js/ui-inspector.js +804 -0
- zerochat_runtime/assets/js/ui-mcp.js +604 -0
- zerochat_runtime/assets/js/ui-profiles.js +824 -0
- zerochat_runtime/assets/js/ui-reasoning.js +146 -0
- zerochat_runtime/assets/js/ui-settings.js +825 -0
- zerochat_runtime/assets/js/ui-shell.js +215 -0
- zerochat_runtime/assets/js/ui-sidebar.js +429 -0
- zerochat_runtime/assets/js/ui-telemetry.js +404 -0
- zerochat_runtime/assets/js/ui-transfer.js +262 -0
- zerochat_runtime/assets/js/utils.js +216 -0
- zerochat_runtime/assets/js/vendor/orama.browser.js +11 -0
- zerochat_runtime/assets/js/web-browser.js +569 -0
- zerochat_runtime/assets/js/web-search.js +519 -0
- zerochat_runtime/assets/manifest.webmanifest +20 -0
- zerochat_runtime/assets/services/dummy_mcp/dummy_mcp_server.py +47 -0
- zerochat_runtime/assets/services/dummy_mcp/service.json +22 -0
- zerochat_runtime/assets/services/lsp/installer.json +9 -0
- zerochat_runtime/assets/services/lsp/service.json +22 -0
- zerochat_runtime/assets/services/memory/installer.json +9 -0
- zerochat_runtime/assets/services/memory/service.json +24 -0
- zerochat_runtime/assets/services/playwright/installer.json +10 -0
- zerochat_runtime/assets/services/playwright/service.json +39 -0
- zerochat_runtime/assets/sw.js +164 -0
- zerochat_runtime/assets/zerochat.html +671 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/** Tool autocontenida: agent_checkpoint. */
|
|
2
|
+
(function (root, factory) {
|
|
3
|
+
if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = factory();
|
|
4
|
+
else root.ChatBuiltinAgentCheckpointTool = factory();
|
|
5
|
+
})(typeof self !== 'undefined' ? self : this, function () {
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const definition = {
|
|
9
|
+
name: 'agent_checkpoint',
|
|
10
|
+
description: 'Agentic checkpoint for consolidating findings and recording the next step: invoke it after querying sources, verifying whether information is sufficient, or validating the final answer.',
|
|
11
|
+
parameters: {
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
findings: {
|
|
15
|
+
type: 'string',
|
|
16
|
+
description: 'Structured, concise summary of the data, figures, or confirmed facts gathered so far (working memory).'
|
|
17
|
+
},
|
|
18
|
+
ready_to_respond: {
|
|
19
|
+
type: 'boolean',
|
|
20
|
+
description: 'Whether enough information is available to formulate the final answer to the user (true) or more queries are still needed (false).'
|
|
21
|
+
},
|
|
22
|
+
missing_info: {
|
|
23
|
+
type: 'string',
|
|
24
|
+
description: 'Specific data or contrasts that still need to be investigated (only when ready_to_respond is false).'
|
|
25
|
+
},
|
|
26
|
+
next_action: {
|
|
27
|
+
type: 'string',
|
|
28
|
+
description: 'Next hypothesis, tool, or specific query planned (only when ready_to_respond is false).'
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
required: ['findings', 'ready_to_respond']
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const CHECKPOINT_ICON_SVG = '<svg class="ui-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 6H5a2 2 0 0 0-2 2v3a2 2 0 0 0 2 2h13l4-3.5L18 6Z"></path><line x1="12" y1="13" x2="12" y2="21"></line></svg>';
|
|
36
|
+
|
|
37
|
+
function createCardWrapper(ui) {
|
|
38
|
+
if (ui?.createCardWrapper) return ui.createCardWrapper();
|
|
39
|
+
const doc = ui?.document || (typeof document !== 'undefined' ? document : null);
|
|
40
|
+
if (!doc) return null;
|
|
41
|
+
const cardDiv = doc.createElement('div');
|
|
42
|
+
cardDiv.className = 'tool-card-wrapper';
|
|
43
|
+
return cardDiv;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const safeEscapeHtml = (value) => String(value || '').replace(/[&<>"']/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]));
|
|
47
|
+
|
|
48
|
+
function createLiveCard(args, ui) {
|
|
49
|
+
const cardDiv = createCardWrapper(ui);
|
|
50
|
+
if (!cardDiv) return null;
|
|
51
|
+
const Markdown = ui?.markdown || (typeof window !== 'undefined' && window.ChatMarkdown) || (typeof window !== 'undefined' && window.ChatUtils) || { escapeHtml: safeEscapeHtml };
|
|
52
|
+
const t = ui?.t || ((key) => key);
|
|
53
|
+
const spinner = ui?.SPINNER_SVG || '';
|
|
54
|
+
const chevron = ui?.CHEVRON_SVG || '';
|
|
55
|
+
const title = t('tool_agent_checkpoint_title') || 'Punto de control agéntico';
|
|
56
|
+
const statusText = t('tool_agent_checkpoint_loading') || 'Consolidando hallazgos...';
|
|
57
|
+
|
|
58
|
+
cardDiv.innerHTML = `<div class="tool-execution-card agent-checkpoint-card"><div class="tool-card-header"><div class="tool-card-title"><span>${CHECKPOINT_ICON_SVG}</span><span>${title}</span></div><div class="tool-card-header-actions"><span class="tool-card-badge status-loading">${spinner} <span>${statusText}</span></span><button type="button" class="btn-tool-collapse" title="${t('tool_btn_collapse') || 'Minimizar'}">${chevron}</button></div></div><div class="tool-card-collapsible-body"><div class="tool-card-result"><div class="checkpoint-findings"><strong>${t('tool_agent_checkpoint_findings') || 'Hallazgos clave:'}</strong><div class="checkpoint-findings-text">${Markdown.escapeHtml(args?.findings || '')}</div></div></div></div></div>`;
|
|
59
|
+
return cardDiv;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function updateLiveCard(cardDiv, args, result = {}, elapsedMs = 0, ui) {
|
|
63
|
+
if (!cardDiv) return;
|
|
64
|
+
const Markdown = ui?.markdown || (typeof window !== 'undefined' && window.ChatMarkdown) || (typeof window !== 'undefined' && window.ChatUtils) || { escapeHtml: safeEscapeHtml };
|
|
65
|
+
const t = ui?.t || ((key) => key);
|
|
66
|
+
const checkSvg = ui?.CHECK_SVG || '';
|
|
67
|
+
const errorSvg = ui?.ERROR_SVG || '';
|
|
68
|
+
const isReady = result?.action === 'conclude' || args?.ready_to_respond === true || args?.ready_to_respond === 'true';
|
|
69
|
+
const success = result?.success !== false && !result?.error;
|
|
70
|
+
|
|
71
|
+
const badge = cardDiv.querySelector('.tool-card-badge');
|
|
72
|
+
if (badge) {
|
|
73
|
+
badge.className = `tool-card-badge ${success ? 'status-success' : 'status-error'}`;
|
|
74
|
+
const label = isReady
|
|
75
|
+
? (t('tool_agent_checkpoint_ready') || 'Listo para responder')
|
|
76
|
+
: (t('tool_agent_checkpoint_continue') || 'Continuando análisis');
|
|
77
|
+
badge.innerHTML = success
|
|
78
|
+
? `${checkSvg} <span>${label} (${elapsedMs || 0}ms)</span>`
|
|
79
|
+
: `${errorSvg} <span>${result?.error || 'Error'}</span>`;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const body = cardDiv.querySelector('.tool-card-result');
|
|
83
|
+
if (body) {
|
|
84
|
+
const findings = result?.findings || args?.findings || '';
|
|
85
|
+
const missing = result?.missing_info || args?.missing_info || '';
|
|
86
|
+
const nextAction = result?.next_action || args?.next_action || '';
|
|
87
|
+
const guidance = result?.guidance || '';
|
|
88
|
+
|
|
89
|
+
let contentHtml = `<div class="checkpoint-findings" style="margin-bottom: 6px;"><div class="checkpoint-label" style="font-weight: 600; opacity: 0.85; margin-bottom: 2px;">${t('tool_agent_checkpoint_findings') || 'Hallazgos clave:'}</div><div class="checkpoint-text" style="white-space: pre-wrap; font-size: 0.9em;">${Markdown.escapeHtml(findings)}</div></div>`;
|
|
90
|
+
|
|
91
|
+
if (missing) {
|
|
92
|
+
contentHtml += `<div class="checkpoint-missing" style="margin-bottom: 6px; font-size: 0.88em;"><span style="font-weight: 600; opacity: 0.85;">${t('tool_agent_checkpoint_missing') || 'Información faltante:'} </span><span>${Markdown.escapeHtml(missing)}</span></div>`;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (nextAction) {
|
|
96
|
+
contentHtml += `<div class="checkpoint-next" style="margin-bottom: 6px; font-size: 0.88em;"><span style="font-weight: 600; opacity: 0.85;">${t('tool_agent_checkpoint_next') || 'Siguiente hipótesis / paso:'} </span><span>${Markdown.escapeHtml(nextAction)}</span></div>`;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (guidance) {
|
|
100
|
+
contentHtml += `<div class="checkpoint-guidance" style="padding-top: 4px; border-top: 1px dashed var(--border-color, #444); font-size: 0.85em; opacity: 0.9;"><em>${Markdown.escapeHtml(guidance)}</em></div>`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
body.innerHTML = contentHtml;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function renderHistoricalCard(args, toolMessage, ui) {
|
|
108
|
+
const cardDiv = createLiveCard(args, ui);
|
|
109
|
+
if (!cardDiv) return null;
|
|
110
|
+
let result = {};
|
|
111
|
+
if (toolMessage?.content) {
|
|
112
|
+
try {
|
|
113
|
+
result = JSON.parse(toolMessage.content);
|
|
114
|
+
} catch (e) {
|
|
115
|
+
result = { findings: toolMessage.content };
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
updateLiveCard(cardDiv, args, result, 0, ui);
|
|
119
|
+
return cardDiv;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function createTool(Tool) {
|
|
123
|
+
if (typeof Tool !== 'function') throw new Error('La clase Tool es necesaria para crear agent_checkpoint.');
|
|
124
|
+
return new Tool({
|
|
125
|
+
id: definition.name,
|
|
126
|
+
definition,
|
|
127
|
+
aliases: ['checkpoint', 'agentcheckpoint', 'checkpoint_agent', 'punto_control'],
|
|
128
|
+
category: 'agent',
|
|
129
|
+
metadata: { icon: 'milestone', label: definition.name },
|
|
130
|
+
settings: {
|
|
131
|
+
titleKey: 'agent_checkpoint_title',
|
|
132
|
+
titleFallback: 'Punto de Control Agéntico',
|
|
133
|
+
descKey: 'agent_checkpoint_desc',
|
|
134
|
+
descFallback: 'Permite al modelo consolidar hallazgos, solicitar asistencia y registrar el siguiente paso para razonar sin pérdida de foco.',
|
|
135
|
+
icon: 'milestone',
|
|
136
|
+
defaultEnabled: false,
|
|
137
|
+
showInSettings: true
|
|
138
|
+
},
|
|
139
|
+
promptGuide: () => '- `agent_checkpoint(findings="...", ready_to_respond=true|false, missing_info="...", next_action="...")`: Consolidates multi-step findings, records the current plan, and verifies whether to conclude or continue searching.',
|
|
140
|
+
execute: async (args = {}, context = {}) => {
|
|
141
|
+
const isReady = args.ready_to_respond === true || args.ready_to_respond === 'true';
|
|
142
|
+
const findings = String(args.findings || args.summary || args.state || '').trim();
|
|
143
|
+
const missingInfo = String(args.missing_info || args.missing || '').trim();
|
|
144
|
+
const nextAction = String(args.next_action || args.hypothesis || args.next || '').trim();
|
|
145
|
+
|
|
146
|
+
if (isReady) {
|
|
147
|
+
return {
|
|
148
|
+
success: true,
|
|
149
|
+
status: 'acknowledged',
|
|
150
|
+
action: 'conclude',
|
|
151
|
+
findings,
|
|
152
|
+
guidance: 'Findings consolidated and verified. Proceed immediately to formulate your complete, structured, and detailed final answer to the user.'
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
success: true,
|
|
158
|
+
status: 'acknowledged',
|
|
159
|
+
action: 'continue',
|
|
160
|
+
findings,
|
|
161
|
+
missing_info: missingInfo,
|
|
162
|
+
next_action: nextAction,
|
|
163
|
+
guidance: `Checkpoint recorded. Proceed with your planned next action: ${nextAction || 'perform the pending query.'}`
|
|
164
|
+
};
|
|
165
|
+
},
|
|
166
|
+
result: {
|
|
167
|
+
toModel: (_args, result) => typeof result === 'string' ? result : JSON.stringify(result || {}),
|
|
168
|
+
toMarkdown: (args, result) => {
|
|
169
|
+
const status = result?.action === 'conclude' ? 'Listo para responder' : 'Continuar análisis';
|
|
170
|
+
return `> **agent_checkpoint** [${status}]\n> *Hallazgos:* ${args.findings || ''}\n\n`;
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
displayMode: 'collapsed',
|
|
174
|
+
view: {
|
|
175
|
+
id: definition.name,
|
|
176
|
+
displayMode: 'collapsed',
|
|
177
|
+
createLiveCard,
|
|
178
|
+
updateLiveCard,
|
|
179
|
+
renderHistoricalCard
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const toolModule = {
|
|
185
|
+
id: definition.name,
|
|
186
|
+
definition,
|
|
187
|
+
displayMode: 'collapsed',
|
|
188
|
+
createTool,
|
|
189
|
+
view: {
|
|
190
|
+
id: definition.name,
|
|
191
|
+
displayMode: 'collapsed',
|
|
192
|
+
createLiveCard,
|
|
193
|
+
updateLiveCard,
|
|
194
|
+
renderHistoricalCard
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
let manifestApi = null;
|
|
199
|
+
if (typeof window !== 'undefined' && window.ChatToolManifest) {
|
|
200
|
+
manifestApi = window.ChatToolManifest;
|
|
201
|
+
} else if (typeof require !== 'undefined') {
|
|
202
|
+
try {
|
|
203
|
+
manifestApi = require('../tool-manifest.js');
|
|
204
|
+
} catch (e) {}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (manifestApi?.builtin && !manifestApi.builtin.has(toolModule.id)) {
|
|
208
|
+
manifestApi.builtin.register(toolModule);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return toolModule;
|
|
212
|
+
});
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/** Tool autocontenida: download_pdf. */
|
|
2
|
+
(function (root, factory) {
|
|
3
|
+
if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = factory();
|
|
4
|
+
else root.ChatBuiltinDownloadPdfTool = factory();
|
|
5
|
+
})(typeof self !== 'undefined' ? self : this, function () {
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const definition = {
|
|
9
|
+
name: 'download_pdf',
|
|
10
|
+
description: 'Downloads a PDF file or document from a web URL and extracts all its readable text to analyze and include in the context (e.g. "https://arxiv.org/pdf/2310.06825.pdf").',
|
|
11
|
+
parameters: { type: 'object', properties: { url: { type: 'string', description: 'Direct URL of the PDF document to download and extract.' } }, required: ['url'] }
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
function getUrl(args) {
|
|
15
|
+
return args?.url || args?.URL || args?.uri || args?.link || args?.href || args?.path || args?.input || (typeof args === 'string' ? args : '');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function createCardWrapper(ui) {
|
|
19
|
+
if (ui?.createCardWrapper) return ui.createCardWrapper();
|
|
20
|
+
const doc = ui?.document || (typeof document !== 'undefined' ? document : null);
|
|
21
|
+
if (!doc) return null;
|
|
22
|
+
const cardDiv = doc.createElement('div');
|
|
23
|
+
cardDiv.className = 'tool-card-wrapper';
|
|
24
|
+
return cardDiv;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const PDF_ICON_SVG = '<svg class="ui-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>';
|
|
28
|
+
|
|
29
|
+
function getHtmlSafety() {
|
|
30
|
+
if (typeof window !== 'undefined' && window.ChatUtils) return window.ChatUtils;
|
|
31
|
+
if (typeof require !== 'undefined') { try { return require('../../utils.js'); } catch (_) {} }
|
|
32
|
+
return { escapeHtml: () => '', sanitizeUrl: () => '#' };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function createLiveCard(args, ui) {
|
|
36
|
+
const cardDiv = createCardWrapper(ui);
|
|
37
|
+
if (!cardDiv) return null;
|
|
38
|
+
const Markdown = ui?.markdown || (typeof window !== 'undefined' && window.ChatMarkdown) || getHtmlSafety();
|
|
39
|
+
const t = ui?.t || ((key) => key);
|
|
40
|
+
const spinner = ui?.SPINNER_SVG || '';
|
|
41
|
+
const chevron = ui?.CHEVRON_SVG || '';
|
|
42
|
+
const url = getUrl(args);
|
|
43
|
+
cardDiv.innerHTML = `<div class="web-request-card pdf-request-card"><div class="web-card-header"><div class="web-card-title"><span>${PDF_ICON_SVG}</span><span>${t('tool_pdf_title')}</span></div><div class="tool-card-header-actions"><span class="web-card-badge status-loading">${spinner} <span>${t('tool_badge_downloading') || 'Descargando...'}</span></span><button type="button" class="btn-tool-collapse" title="${t('tool_btn_collapse') || 'Minimizar'}">${chevron}</button></div></div><div class="tool-card-collapsible-body"><div class="web-card-section web-request-section"><div class="section-label">${t('tool_web_requested_url')}</div><div class="url-badge"><a href="${Markdown.sanitizeUrl(url)}" target="_blank" rel="noopener noreferrer">${Markdown.escapeHtml(url)}</a></div></div><div class="web-card-section web-response-section"><div class="section-label section-response-label">${t('tool_web_receiving') || 'Recibiendo contenido...'}</div><div class="web-response-body tool-loading-placeholder">${spinner} <span>${t('tool_loading_pdf')}</span></div></div></div></div>`;
|
|
44
|
+
return cardDiv;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function updateLiveCard(cardDiv, _args, result = {}, elapsedMs = 0, ui) {
|
|
48
|
+
if (!cardDiv) return;
|
|
49
|
+
const Markdown = ui?.markdown || (typeof window !== 'undefined' && window.ChatMarkdown) || getHtmlSafety();
|
|
50
|
+
const t = ui?.t || ((key) => key);
|
|
51
|
+
const checkSvg = ui?.CHECK_SVG || '';
|
|
52
|
+
const errorSvg = ui?.ERROR_SVG || '';
|
|
53
|
+
const success = result?.success !== false && !result?.error;
|
|
54
|
+
const content = result?.content || result?.error || '';
|
|
55
|
+
const badge = cardDiv.querySelector('.web-card-badge');
|
|
56
|
+
if (badge) {
|
|
57
|
+
badge.className = `web-card-badge ${success ? 'status-success' : 'status-error'}`;
|
|
58
|
+
badge.innerHTML = success
|
|
59
|
+
? `${checkSvg} <span>PDF OK (${elapsedMs || 0}ms)</span>`
|
|
60
|
+
: `${errorSvg} <span>Error PDF (${elapsedMs || 0}ms)</span>`;
|
|
61
|
+
}
|
|
62
|
+
const label = cardDiv.querySelector('.section-response-label');
|
|
63
|
+
if (label) label.textContent = t('tool_web_content_received', { size: `${content.length} chars` }) || `Contenido recibido (${content.length} caracteres):`;
|
|
64
|
+
const body = cardDiv.querySelector('.web-response-body');
|
|
65
|
+
if (body) { body.className = 'web-response-body'; body.innerHTML = `<code>${Markdown.escapeHtml(content.slice(0, 1500))}${content.length > 1500 ? '...' : ''}</code>`; }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function renderHistoricalCard(args, toolMessage, ui) {
|
|
69
|
+
const cardDiv = createLiveCard(args, ui);
|
|
70
|
+
if (!cardDiv) return null;
|
|
71
|
+
let result = {};
|
|
72
|
+
if (toolMessage?.content) { try { result = JSON.parse(toolMessage.content); } catch (e) { result = { content: toolMessage.content }; } }
|
|
73
|
+
updateLiveCard(cardDiv, args, result, 0, ui);
|
|
74
|
+
return cardDiv;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function createTool(Tool) {
|
|
78
|
+
if (typeof Tool !== 'function') throw new Error('La clase Tool es necesaria para crear download_pdf.');
|
|
79
|
+
return new Tool({
|
|
80
|
+
id: definition.name,
|
|
81
|
+
definition,
|
|
82
|
+
aliases: ['downloadpdf', 'fetch_pdf', 'download_pdf_document', 'fetch_pdf_document', 'download_file', 'getpdf', 'readpdf'],
|
|
83
|
+
category: 'web',
|
|
84
|
+
metadata: { icon: 'file-text', label: definition.name },
|
|
85
|
+
settings: {
|
|
86
|
+
titleKey: 'agent_pdf_title', titleFallback: 'Descarga y Lectura de Documentos PDF',
|
|
87
|
+
descKey: 'agent_pdf_desc', descFallback: 'Permite al modelo descargar documentos PDF desde la web y extraer todo su texto al contexto en tiempo real.',
|
|
88
|
+
icon: 'file-text', defaultEnabled: true, showInSettings: true
|
|
89
|
+
},
|
|
90
|
+
promptGuide: () => '- `download_pdf(url="...")`: Downloads a PDF file from a URL and extracts its readable text into the prompt context.',
|
|
91
|
+
execute: async (args, context = {}) => {
|
|
92
|
+
const WebBrowser = context.services?.webBrowser;
|
|
93
|
+
if (!WebBrowser || !WebBrowser.downloadPdf) return { success: false, error: 'Módulo WebBrowser no disponible.' };
|
|
94
|
+
return WebBrowser.downloadPdf(getUrl(args), context.options || {});
|
|
95
|
+
},
|
|
96
|
+
result: {
|
|
97
|
+
toModel: (_args, result) => JSON.stringify(result || {}),
|
|
98
|
+
toMarkdown: (args) => `> **download_pdf**\n> URL: "${args.url || ''}"\n\n`
|
|
99
|
+
},
|
|
100
|
+
displayMode: 'collapsed',
|
|
101
|
+
view: { id: definition.name, displayMode: 'collapsed', createLiveCard, updateLiveCard, renderHistoricalCard }
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const toolModule = { id: definition.name, definition, displayMode: 'collapsed', createTool, getUrl, view: { id: definition.name, displayMode: 'collapsed', createLiveCard, updateLiveCard, renderHistoricalCard } };
|
|
106
|
+
let manifestApi = null;
|
|
107
|
+
if (typeof window !== 'undefined' && window.ChatToolManifest) manifestApi = window.ChatToolManifest;
|
|
108
|
+
else if (typeof require !== 'undefined') { try { manifestApi = require('../tool-manifest.js'); } catch (e) {} }
|
|
109
|
+
if (manifestApi?.builtin && !manifestApi.builtin.has(toolModule.id)) manifestApi.builtin.register(toolModule);
|
|
110
|
+
return toolModule;
|
|
111
|
+
});
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool autocontenida: execute_javascript.
|
|
3
|
+
*
|
|
4
|
+
* La dependencia del ejecutor de JavaScript se recibe desde ToolExecutionContext.services;
|
|
5
|
+
* este módulo no depende de globals ni de resolutores del núcleo agéntico.
|
|
6
|
+
*/
|
|
7
|
+
(function (root, factory) {
|
|
8
|
+
if (typeof exports === 'object' && typeof module !== 'undefined') {
|
|
9
|
+
module.exports = factory();
|
|
10
|
+
} else {
|
|
11
|
+
root.ChatBuiltinExecuteJavascriptTool = factory();
|
|
12
|
+
}
|
|
13
|
+
})(typeof self !== 'undefined' ? self : this, function () {
|
|
14
|
+
'use strict';
|
|
15
|
+
|
|
16
|
+
const definition = {
|
|
17
|
+
name: 'execute_javascript',
|
|
18
|
+
description: 'Executes JavaScript code in an isolated local worker to assist with calculations and data processing under technical user supervision. Always use return <value> or console.log() to emit the result.',
|
|
19
|
+
parameters: {
|
|
20
|
+
type: 'object',
|
|
21
|
+
properties: {
|
|
22
|
+
code: { type: 'string', description: 'Executable JS code. Always use return <value> or console.log() to emit output.' }
|
|
23
|
+
},
|
|
24
|
+
required: ['code']
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
function getCode(args) {
|
|
29
|
+
const raw = args?.code || args?.javascript || args?.js || args?.script || args?.input || (typeof args === 'string' ? args : '');
|
|
30
|
+
if (typeof raw !== 'string') return '';
|
|
31
|
+
let code = raw.trim();
|
|
32
|
+
if (code.startsWith('```')) {
|
|
33
|
+
code = code.replace(/^```(?:javascript|js)?\s*\n?/, '').replace(/\n?```\s*$/, '');
|
|
34
|
+
}
|
|
35
|
+
return code;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function toModel(_args, result, outcome) {
|
|
39
|
+
return result?.success
|
|
40
|
+
? (result.result || (result.logs && result.logs.length > 0 ? result.logs.join('\n') : 'undefined'))
|
|
41
|
+
: `Error: ${result?.error || outcome?.error || 'Error de ejecución'}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function toMarkdown(args, result, outcome) {
|
|
45
|
+
const code = getCode(args);
|
|
46
|
+
const output = toModel(args, result, outcome);
|
|
47
|
+
return `> ⚡ **execute_javascript**\n> \`\`\`javascript\n> ${code.split('\n').join('\n> ')}\n> \`\`\`\n> \`\`\`\n> ${String(output).split('\n').join('\n> ')}\n> \`\`\``;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function createCardWrapper(ui) {
|
|
51
|
+
if (ui?.createCardWrapper) return ui.createCardWrapper();
|
|
52
|
+
const doc = ui?.document || (typeof document !== 'undefined' ? document : null);
|
|
53
|
+
if (!doc) return null;
|
|
54
|
+
const cardDiv = doc.createElement('div');
|
|
55
|
+
cardDiv.className = 'tool-card-wrapper';
|
|
56
|
+
return cardDiv;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const safeEscapeHtml = (value) => String(value || '').replace(/[&<>"']/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]));
|
|
60
|
+
|
|
61
|
+
function getUiHelpers(ui) {
|
|
62
|
+
return {
|
|
63
|
+
Markdown: ui?.markdown || (typeof window !== 'undefined' && window.ChatMarkdown) || (typeof window !== 'undefined' && window.ChatUtils) || { escapeHtml: safeEscapeHtml },
|
|
64
|
+
t: ui?.t || ((key) => key),
|
|
65
|
+
spinner: ui?.SPINNER_SVG || '',
|
|
66
|
+
checkSvg: ui?.CHECK_SVG || '',
|
|
67
|
+
errorSvg: ui?.ERROR_SVG || '',
|
|
68
|
+
chevron: ui?.CHEVRON_SVG || ''
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const JS_ICON_SVG = '<svg class="ui-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="4 17 10 11 4 5"></polyline><line x1="12" y1="19" x2="20" y2="19"></line></svg>';
|
|
73
|
+
|
|
74
|
+
function createLiveCard(args, ui) {
|
|
75
|
+
const cardDiv = createCardWrapper(ui);
|
|
76
|
+
if (!cardDiv) return null;
|
|
77
|
+
const { Markdown, t, spinner, chevron } = getUiHelpers(ui);
|
|
78
|
+
const code = getCode(args);
|
|
79
|
+
cardDiv.innerHTML = `
|
|
80
|
+
<div class="tool-execution-card">
|
|
81
|
+
<div class="tool-card-header">
|
|
82
|
+
<div class="tool-card-title">
|
|
83
|
+
<span>${JS_ICON_SVG}</span>
|
|
84
|
+
<span>${t('tool_js_title_running') || 'execute_javascript'}</span>
|
|
85
|
+
</div>
|
|
86
|
+
<div class="tool-card-header-actions">
|
|
87
|
+
<span class="tool-card-badge status-loading">${spinner} <span>${t('tool_badge_executing') || 'Ejecutando...'}</span></span>
|
|
88
|
+
<button type="button" class="btn-tool-collapse" title="${t('tool_btn_collapse') || 'Minimizar'}">${chevron}</button>
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
<div class="tool-card-collapsible-body">
|
|
92
|
+
<pre class="tool-card-code"><code>${Markdown.escapeHtml(code)}</code></pre>
|
|
93
|
+
<div class="tool-card-result">
|
|
94
|
+
<div class="tool-loading-placeholder">${spinner} <span>${t('tool_loading_js') || 'Ejecutando código JavaScript...'}</span></div>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
`;
|
|
99
|
+
return cardDiv;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function updateLiveCard(cardDiv, _args, result = {}, elapsedMs = 0, ui) {
|
|
103
|
+
if (!cardDiv) return;
|
|
104
|
+
const { Markdown, t, checkSvg, errorSvg } = getUiHelpers(ui);
|
|
105
|
+
const isSuccess = result?.success !== false && !result?.error;
|
|
106
|
+
const badgeEl = cardDiv.querySelector('.tool-card-badge');
|
|
107
|
+
if (badgeEl) {
|
|
108
|
+
badgeEl.className = `tool-card-badge ${isSuccess ? 'status-success' : 'status-error'}`;
|
|
109
|
+
badgeEl.innerHTML = isSuccess
|
|
110
|
+
? `${checkSvg} <span>${t('tool_status_success') || 'Completado'} (${elapsedMs || 0}ms)</span>`
|
|
111
|
+
: `${errorSvg} <span>Error (${elapsedMs || 0}ms)</span>`;
|
|
112
|
+
}
|
|
113
|
+
const resContainer = cardDiv.querySelector('.tool-card-result');
|
|
114
|
+
if (resContainer) {
|
|
115
|
+
const output = isSuccess
|
|
116
|
+
? (result.result || (result.logs && result.logs.length > 0 ? result.logs.join('\n') : 'undefined'))
|
|
117
|
+
: `Error: ${result.error || 'Error de ejecución'}`;
|
|
118
|
+
const cleanOutput = String(output ?? '').trim();
|
|
119
|
+
resContainer.innerHTML = `<div class="tool-result-label">${t('tool_sandbox_output') || 'Resultado:'}</div><pre class="tool-result-pre"><code>${Markdown.escapeHtml(cleanOutput)}</code></pre>`;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function renderHistoricalCard(args, toolMessage, ui) {
|
|
124
|
+
const cardDiv = createCardWrapper(ui);
|
|
125
|
+
if (!cardDiv) return null;
|
|
126
|
+
const { Markdown, t, checkSvg, chevron } = getUiHelpers(ui);
|
|
127
|
+
let output = '';
|
|
128
|
+
if (toolMessage?.content) {
|
|
129
|
+
try {
|
|
130
|
+
const parsed = JSON.parse(toolMessage.content);
|
|
131
|
+
output = parsed.result || (parsed.logs && parsed.logs.length > 0
|
|
132
|
+
? parsed.logs.join('\n')
|
|
133
|
+
: (parsed.error ? `Error: ${parsed.error}` : toolMessage.content));
|
|
134
|
+
} catch (e) {
|
|
135
|
+
output = toolMessage.content;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const cleanOutput = String(output ?? '').trim();
|
|
139
|
+
cardDiv.innerHTML = `
|
|
140
|
+
<div class="tool-execution-card">
|
|
141
|
+
<div class="tool-card-header">
|
|
142
|
+
<div class="tool-card-title"><span>${JS_ICON_SVG}</span><span>${t('tool_js_title_running') || 'execute_javascript'}</span></div>
|
|
143
|
+
<div class="tool-card-header-actions">
|
|
144
|
+
<span class="tool-card-badge status-success">${checkSvg} <span>${t('tool_status_success') || 'Completado'}</span></span>
|
|
145
|
+
<button type="button" class="btn-tool-collapse" title="${t('tool_btn_collapse') || 'Minimizar'}">${chevron}</button>
|
|
146
|
+
</div>
|
|
147
|
+
</div>
|
|
148
|
+
<div class="tool-card-collapsible-body">
|
|
149
|
+
<pre class="tool-card-code"><code>${Markdown.escapeHtml(getCode(args).trim())}</code></pre>
|
|
150
|
+
<div class="tool-card-result"><div class="tool-result-label">${t('tool_sandbox_output') || 'Resultado:'}</div><pre class="tool-result-pre"><code>${Markdown.escapeHtml(cleanOutput)}</code></pre></div>
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
`;
|
|
154
|
+
return cardDiv;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function createTool(Tool) {
|
|
158
|
+
if (typeof Tool !== 'function') {
|
|
159
|
+
throw new Error('La clase Tool es necesaria para crear execute_javascript.');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return new Tool({
|
|
163
|
+
id: definition.name,
|
|
164
|
+
definition,
|
|
165
|
+
aliases: ['executejs', 'execute_js', 'run_javascript', 'run_js', 'javascript', 'evaljs'],
|
|
166
|
+
category: 'computation',
|
|
167
|
+
metadata: { icon: 'zap', label: definition.name },
|
|
168
|
+
settings: {
|
|
169
|
+
titleKey: 'agent_js_title',
|
|
170
|
+
titleFallback: 'Ejecución de JavaScript (Cálculos locales)',
|
|
171
|
+
descKey: 'agent_js_desc',
|
|
172
|
+
descFallback: 'Permite al modelo invocar execute_javascript para calcular, procesar datos o validar algoritmos directamente en el navegador bajo supervisión técnica.',
|
|
173
|
+
icon: 'zap',
|
|
174
|
+
defaultEnabled: true,
|
|
175
|
+
showInSettings: true
|
|
176
|
+
},
|
|
177
|
+
promptGuide: () => '- `execute_javascript(code="...")`: Runs JavaScript locally in an isolated worker to assist with calculations and logic. Always use `return <value>` or `console.log(...)` to output results.',
|
|
178
|
+
execute: async (args, context = {}) => {
|
|
179
|
+
const Sandbox = context.services?.sandbox;
|
|
180
|
+
if (!Sandbox || !Sandbox.execute) {
|
|
181
|
+
return { success: false, error: 'Módulo de ejecución de JavaScript no disponible.' };
|
|
182
|
+
}
|
|
183
|
+
const timeoutMs = typeof context.timeoutMs === 'number'
|
|
184
|
+
? context.timeoutMs
|
|
185
|
+
: (typeof context.options?.timeoutMs === 'number' ? context.options.timeoutMs : undefined);
|
|
186
|
+
return Sandbox.execute(getCode(args), timeoutMs);
|
|
187
|
+
},
|
|
188
|
+
result: { toModel, toMarkdown },
|
|
189
|
+
displayMode: 'collapsed',
|
|
190
|
+
view: { id: 'execute_javascript', displayMode: 'collapsed', createLiveCard, updateLiveCard, renderHistoricalCard }
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const toolModule = {
|
|
195
|
+
id: definition.name,
|
|
196
|
+
definition,
|
|
197
|
+
displayMode: 'collapsed',
|
|
198
|
+
createTool,
|
|
199
|
+
getCode,
|
|
200
|
+
toModel,
|
|
201
|
+
toMarkdown,
|
|
202
|
+
view: { id: 'execute_javascript', displayMode: 'collapsed', createLiveCard, updateLiveCard, renderHistoricalCard }
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
function registerWithBuiltinManifest() {
|
|
206
|
+
let manifestApi = null;
|
|
207
|
+
if (typeof window !== 'undefined' && window.ChatToolManifest) {
|
|
208
|
+
manifestApi = window.ChatToolManifest;
|
|
209
|
+
} else if (typeof require !== 'undefined') {
|
|
210
|
+
try { manifestApi = require('../tool-manifest.js'); } catch (e) {}
|
|
211
|
+
}
|
|
212
|
+
if (manifestApi?.builtin && !manifestApi.builtin.has(toolModule.id)) {
|
|
213
|
+
manifestApi.builtin.register(toolModule);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
registerWithBuiltinManifest();
|
|
218
|
+
return toolModule;
|
|
219
|
+
});
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/** Tool autocontenida: fetch_web_page. */
|
|
2
|
+
(function (root, factory) {
|
|
3
|
+
if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = factory();
|
|
4
|
+
else root.ChatBuiltinFetchWebPageTool = factory();
|
|
5
|
+
})(typeof self !== 'undefined' ? self : this, function () {
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const definition = {
|
|
9
|
+
name: 'fetch_web_page',
|
|
10
|
+
description: 'Downloads and reads the text and content of a public web page or HTML article from its URL (e.g. "https://en.wikipedia.org/wiki/Sun").',
|
|
11
|
+
parameters: { type: 'object', properties: { url: { type: 'string', description: 'URL of the web page to read.' } }, required: ['url'] }
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
function getUrl(args) {
|
|
15
|
+
return args?.url || args?.URL || args?.uri || args?.link || args?.href || args?.path || args?.input || (typeof args === 'string' ? args : '');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function createCardWrapper(ui) {
|
|
19
|
+
if (ui?.createCardWrapper) return ui.createCardWrapper();
|
|
20
|
+
const doc = ui?.document || (typeof document !== 'undefined' ? document : null);
|
|
21
|
+
if (!doc) return null;
|
|
22
|
+
const cardDiv = doc.createElement('div');
|
|
23
|
+
cardDiv.className = 'tool-card-wrapper';
|
|
24
|
+
return cardDiv;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const GLOBE_ICON_SVG = '<svg class="ui-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"></circle><line x1="2" y1="12" x2="22" y2="12"></line><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path></svg>';
|
|
28
|
+
|
|
29
|
+
function getHtmlSafety() {
|
|
30
|
+
if (typeof window !== 'undefined' && window.ChatUtils) return window.ChatUtils;
|
|
31
|
+
if (typeof require !== 'undefined') { try { return require('../../utils.js'); } catch (_) {} }
|
|
32
|
+
return { escapeHtml: () => '', sanitizeUrl: () => '#' };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function createLiveCard(args, ui) {
|
|
36
|
+
const cardDiv = createCardWrapper(ui);
|
|
37
|
+
if (!cardDiv) return null;
|
|
38
|
+
const Markdown = ui?.markdown || (typeof window !== 'undefined' && window.ChatMarkdown) || getHtmlSafety();
|
|
39
|
+
const t = ui?.t || ((key) => key);
|
|
40
|
+
const spinner = ui?.SPINNER_SVG || '';
|
|
41
|
+
const chevron = ui?.CHEVRON_SVG || '';
|
|
42
|
+
const url = getUrl(args);
|
|
43
|
+
cardDiv.innerHTML = `<div class="web-request-card"><div class="web-card-header"><div class="web-card-title"><span>${GLOBE_ICON_SVG}</span><span>${t('tool_web_title')}</span></div><div class="tool-card-header-actions"><span class="web-card-badge status-loading">${spinner} <span>${t('tool_badge_fetching') || 'Consultando...'}</span></span><button type="button" class="btn-tool-collapse" title="${t('tool_btn_collapse') || 'Minimizar'}">${chevron}</button></div></div><div class="tool-card-collapsible-body"><div class="web-card-section web-request-section"><div class="section-label">${t('tool_web_requested_url')}</div><div class="url-badge"><a href="${Markdown.sanitizeUrl(url)}" target="_blank" rel="noopener noreferrer">${Markdown.escapeHtml(url)}</a></div></div><div class="web-card-section web-response-section"><div class="section-label section-response-label">${t('tool_web_receiving') || 'Recibiendo contenido...'}</div><div class="web-response-body tool-loading-placeholder">${spinner} <span>${t('tool_loading_web')}</span></div></div></div></div>`;
|
|
44
|
+
return cardDiv;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function updateLiveCard(cardDiv, _args, result = {}, elapsedMs = 0, ui) {
|
|
48
|
+
if (!cardDiv) return;
|
|
49
|
+
const Markdown = ui?.markdown || (typeof window !== 'undefined' && window.ChatMarkdown) || getHtmlSafety();
|
|
50
|
+
const t = ui?.t || ((key) => key);
|
|
51
|
+
const checkSvg = ui?.CHECK_SVG || '';
|
|
52
|
+
const errorSvg = ui?.ERROR_SVG || '';
|
|
53
|
+
const success = result?.success !== false && !result?.error;
|
|
54
|
+
const status = result?.status || (success ? 200 : 500);
|
|
55
|
+
const content = result?.content || result?.error || '';
|
|
56
|
+
const badge = cardDiv.querySelector('.web-card-badge');
|
|
57
|
+
if (badge) {
|
|
58
|
+
badge.className = `web-card-badge ${success ? 'status-success' : 'status-error'}`;
|
|
59
|
+
badge.innerHTML = success
|
|
60
|
+
? `${checkSvg} <span>HTTP ${status} OK (${elapsedMs || 0}ms)</span>`
|
|
61
|
+
: `${errorSvg} <span>HTTP ${status} Error (${elapsedMs || 0}ms)</span>`;
|
|
62
|
+
}
|
|
63
|
+
const label = cardDiv.querySelector('.section-response-label');
|
|
64
|
+
if (label) label.textContent = t('tool_web_content_received', { size: `${content.length} chars` }) || `Contenido recibido (${content.length} caracteres):`;
|
|
65
|
+
const body = cardDiv.querySelector('.web-response-body');
|
|
66
|
+
if (body) { body.className = 'web-response-body'; body.innerHTML = `<code>${Markdown.escapeHtml(content.slice(0, 1500))}${content.length > 1500 ? '...' : ''}</code>`; }
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function renderHistoricalCard(args, toolMessage, ui) {
|
|
70
|
+
const cardDiv = createLiveCard(args, ui);
|
|
71
|
+
if (!cardDiv) return null;
|
|
72
|
+
let result = {};
|
|
73
|
+
if (toolMessage?.content) { try { result = JSON.parse(toolMessage.content); } catch (e) { result = { content: toolMessage.content }; } }
|
|
74
|
+
updateLiveCard(cardDiv, args, result, 0, ui);
|
|
75
|
+
return cardDiv;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function createTool(Tool) {
|
|
79
|
+
if (typeof Tool !== 'function') throw new Error('La clase Tool es necesaria para crear fetch_web_page.');
|
|
80
|
+
return new Tool({
|
|
81
|
+
id: definition.name,
|
|
82
|
+
definition,
|
|
83
|
+
aliases: ['fetchwebpage', 'fetch_web', 'fetch_url', 'get_web_page', 'read_web_page', 'web_fetch', 'browse_web', 'webpage'],
|
|
84
|
+
category: 'web',
|
|
85
|
+
metadata: { icon: 'globe', label: definition.name },
|
|
86
|
+
settings: {
|
|
87
|
+
titleKey: 'agent_web_title', titleFallback: 'Navegación Web en Tiempo Real',
|
|
88
|
+
descKey: 'agent_web_desc', descFallback: 'Permite al modelo invocar fetch_web_page para consultar páginas web públicas y extraer su contenido textual en tiempo real.',
|
|
89
|
+
icon: 'globe', defaultEnabled: true, showInSettings: true
|
|
90
|
+
},
|
|
91
|
+
promptGuide: () => '- `fetch_web_page(url="...")`: Downloads and extracts clean text content from public web pages or HTML articles.',
|
|
92
|
+
execute: async (args, context = {}) => {
|
|
93
|
+
const WebBrowser = context.services?.webBrowser;
|
|
94
|
+
if (!WebBrowser || !WebBrowser.fetchPage) return { success: false, error: 'Módulo WebBrowser no disponible.' };
|
|
95
|
+
return WebBrowser.fetchPage(getUrl(args), context.options || {});
|
|
96
|
+
},
|
|
97
|
+
result: {
|
|
98
|
+
toModel: (_args, result) => JSON.stringify(result || {}),
|
|
99
|
+
toMarkdown: (args) => `> **fetch_web_page**\n> URL: "${args.url || ''}"\n\n`
|
|
100
|
+
},
|
|
101
|
+
displayMode: 'collapsed',
|
|
102
|
+
view: { id: definition.name, displayMode: 'collapsed', createLiveCard, updateLiveCard, renderHistoricalCard }
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const toolModule = { id: definition.name, definition, displayMode: 'collapsed', createTool, getUrl, view: { id: definition.name, displayMode: 'collapsed', createLiveCard, updateLiveCard, renderHistoricalCard } };
|
|
107
|
+
let manifestApi = null;
|
|
108
|
+
if (typeof window !== 'undefined' && window.ChatToolManifest) manifestApi = window.ChatToolManifest;
|
|
109
|
+
else if (typeof require !== 'undefined') { try { manifestApi = require('../tool-manifest.js'); } catch (e) {} }
|
|
110
|
+
if (manifestApi?.builtin && !manifestApi.builtin.has(toolModule.id)) manifestApi.builtin.register(toolModule);
|
|
111
|
+
return toolModule;
|
|
112
|
+
});
|