agent-orcha 0.0.7 → 0.0.8
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/README.md +86 -28
- package/dist/lib/agents/agent-executor.d.ts.map +1 -1
- package/dist/lib/agents/agent-executor.js +23 -7
- package/dist/lib/agents/agent-executor.js.map +1 -1
- package/dist/lib/agents/react-loop.d.ts.map +1 -1
- package/dist/lib/agents/react-loop.js +27 -0
- package/dist/lib/agents/react-loop.js.map +1 -1
- package/dist/lib/functions/simple-function-wrapper.js +3 -3
- package/dist/lib/functions/simple-function-wrapper.js.map +1 -1
- package/dist/lib/knowledge/knowledge-store.d.ts +1 -1
- package/dist/lib/knowledge/knowledge-store.d.ts.map +1 -1
- package/dist/lib/knowledge/knowledge-store.js +25 -4
- package/dist/lib/knowledge/knowledge-store.js.map +1 -1
- package/dist/lib/knowledge/loaders/file-loaders.d.ts +0 -1
- package/dist/lib/knowledge/loaders/file-loaders.d.ts.map +1 -1
- package/dist/lib/knowledge/loaders/file-loaders.js +7 -15
- package/dist/lib/knowledge/loaders/file-loaders.js.map +1 -1
- package/dist/lib/knowledge/sqlite-store.d.ts.map +1 -1
- package/dist/lib/knowledge/sqlite-store.js +19 -10
- package/dist/lib/knowledge/sqlite-store.js.map +1 -1
- package/dist/lib/knowledge/types.d.ts +13 -13
- package/dist/lib/llm/index.d.ts +1 -1
- package/dist/lib/llm/index.d.ts.map +1 -1
- package/dist/lib/llm/index.js +1 -1
- package/dist/lib/llm/index.js.map +1 -1
- package/dist/lib/llm/llm-config.d.ts +51 -8
- package/dist/lib/llm/llm-config.d.ts.map +1 -1
- package/dist/lib/llm/llm-config.js +161 -17
- package/dist/lib/llm/llm-config.js.map +1 -1
- package/dist/lib/llm/llm-factory.d.ts +1 -2
- package/dist/lib/llm/llm-factory.d.ts.map +1 -1
- package/dist/lib/llm/llm-factory.js +41 -8
- package/dist/lib/llm/llm-factory.js.map +1 -1
- package/dist/lib/llm/providers/openai-chat-model.d.ts +10 -0
- package/dist/lib/llm/providers/openai-chat-model.d.ts.map +1 -1
- package/dist/lib/llm/providers/openai-chat-model.js +37 -5
- package/dist/lib/llm/providers/openai-chat-model.js.map +1 -1
- package/dist/lib/llm/providers/openai-embeddings.d.ts.map +1 -1
- package/dist/lib/llm/providers/openai-embeddings.js +41 -10
- package/dist/lib/llm/providers/openai-embeddings.js.map +1 -1
- package/dist/lib/local-llm/binary-manager.d.ts +66 -0
- package/dist/lib/local-llm/binary-manager.d.ts.map +1 -0
- package/dist/lib/local-llm/binary-manager.js +441 -0
- package/dist/lib/local-llm/binary-manager.js.map +1 -0
- package/dist/lib/local-llm/engine-interface.d.ts +47 -0
- package/dist/lib/local-llm/engine-interface.d.ts.map +1 -0
- package/dist/lib/local-llm/engine-interface.js +2 -0
- package/dist/lib/local-llm/engine-interface.js.map +1 -0
- package/dist/lib/local-llm/engine-registry.d.ts +20 -0
- package/dist/lib/local-llm/engine-registry.d.ts.map +1 -0
- package/dist/lib/local-llm/engine-registry.js +56 -0
- package/dist/lib/local-llm/engine-registry.js.map +1 -0
- package/dist/lib/local-llm/engines/llama-cpp-engine.d.ts +31 -0
- package/dist/lib/local-llm/engines/llama-cpp-engine.d.ts.map +1 -0
- package/dist/lib/local-llm/engines/llama-cpp-engine.js +164 -0
- package/dist/lib/local-llm/engines/llama-cpp-engine.js.map +1 -0
- package/dist/lib/local-llm/engines/mlx-serve-engine.d.ts +31 -0
- package/dist/lib/local-llm/engines/mlx-serve-engine.d.ts.map +1 -0
- package/dist/lib/local-llm/engines/mlx-serve-engine.js +161 -0
- package/dist/lib/local-llm/engines/mlx-serve-engine.js.map +1 -0
- package/dist/lib/local-llm/gguf-reader.d.ts +20 -0
- package/dist/lib/local-llm/gguf-reader.d.ts.map +1 -0
- package/dist/lib/local-llm/gguf-reader.js +190 -0
- package/dist/lib/local-llm/gguf-reader.js.map +1 -0
- package/dist/lib/local-llm/index.d.ts +9 -0
- package/dist/lib/local-llm/index.d.ts.map +1 -0
- package/dist/lib/local-llm/index.js +6 -0
- package/dist/lib/local-llm/index.js.map +1 -0
- package/dist/lib/local-llm/llama-server-process.d.ts +42 -0
- package/dist/lib/local-llm/llama-server-process.d.ts.map +1 -0
- package/dist/lib/local-llm/llama-server-process.js +237 -0
- package/dist/lib/local-llm/llama-server-process.js.map +1 -0
- package/dist/lib/local-llm/mlx-binary-manager.d.ts +33 -0
- package/dist/lib/local-llm/mlx-binary-manager.d.ts.map +1 -0
- package/dist/lib/local-llm/mlx-binary-manager.js +211 -0
- package/dist/lib/local-llm/mlx-binary-manager.js.map +1 -0
- package/dist/lib/local-llm/mlx-server-process.d.ts +26 -0
- package/dist/lib/local-llm/mlx-server-process.d.ts.map +1 -0
- package/dist/lib/local-llm/mlx-server-process.js +210 -0
- package/dist/lib/local-llm/mlx-server-process.js.map +1 -0
- package/dist/lib/local-llm/model-manager.d.ts +33 -0
- package/dist/lib/local-llm/model-manager.d.ts.map +1 -0
- package/dist/lib/local-llm/model-manager.js +591 -0
- package/dist/lib/local-llm/model-manager.js.map +1 -0
- package/dist/lib/local-llm/types.d.ts +51 -0
- package/dist/lib/local-llm/types.d.ts.map +1 -0
- package/dist/lib/local-llm/types.js +2 -0
- package/dist/lib/local-llm/types.js.map +1 -0
- package/dist/lib/logger.d.ts +2 -0
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/logger.js +68 -5
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/orchestrator.d.ts +9 -0
- package/dist/lib/orchestrator.d.ts.map +1 -1
- package/dist/lib/orchestrator.js +151 -3
- package/dist/lib/orchestrator.js.map +1 -1
- package/dist/lib/sandbox/cdp-client.d.ts +2 -1
- package/dist/lib/sandbox/cdp-client.d.ts.map +1 -1
- package/dist/lib/sandbox/cdp-client.js +33 -7
- package/dist/lib/sandbox/cdp-client.js.map +1 -1
- package/dist/lib/sandbox/index.d.ts +1 -0
- package/dist/lib/sandbox/index.d.ts.map +1 -1
- package/dist/lib/sandbox/index.js +1 -0
- package/dist/lib/sandbox/index.js.map +1 -1
- package/dist/lib/sandbox/page-readiness.d.ts.map +1 -1
- package/dist/lib/sandbox/page-readiness.js +33 -0
- package/dist/lib/sandbox/page-readiness.js.map +1 -1
- package/dist/lib/sandbox/sandbox-browser.d.ts.map +1 -1
- package/dist/lib/sandbox/sandbox-browser.js +14 -1
- package/dist/lib/sandbox/sandbox-browser.js.map +1 -1
- package/dist/lib/sandbox/sandbox-container.d.ts +39 -0
- package/dist/lib/sandbox/sandbox-container.d.ts.map +1 -0
- package/dist/lib/sandbox/sandbox-container.js +176 -0
- package/dist/lib/sandbox/sandbox-container.js.map +1 -0
- package/dist/lib/sandbox/sandbox-file.d.ts.map +1 -1
- package/dist/lib/sandbox/sandbox-file.js +5 -4
- package/dist/lib/sandbox/sandbox-file.js.map +1 -1
- package/dist/lib/sandbox/sandbox-shell.d.ts +2 -1
- package/dist/lib/sandbox/sandbox-shell.d.ts.map +1 -1
- package/dist/lib/sandbox/sandbox-shell.js +42 -24
- package/dist/lib/sandbox/sandbox-shell.js.map +1 -1
- package/dist/lib/sandbox/sandbox-web.d.ts.map +1 -1
- package/dist/lib/sandbox/sandbox-web.js +27 -2
- package/dist/lib/sandbox/sandbox-web.js.map +1 -1
- package/dist/lib/sandbox/vision-browser.d.ts.map +1 -1
- package/dist/lib/sandbox/vision-browser.js +9 -0
- package/dist/lib/sandbox/vision-browser.js.map +1 -1
- package/dist/lib/sea/app-window.d.ts +7 -0
- package/dist/lib/sea/app-window.d.ts.map +1 -0
- package/dist/lib/sea/app-window.js +95 -0
- package/dist/lib/sea/app-window.js.map +1 -0
- package/dist/lib/sea/bootstrap.d.ts +18 -0
- package/dist/lib/sea/bootstrap.d.ts.map +1 -0
- package/dist/lib/sea/bootstrap.js +103 -0
- package/dist/lib/sea/bootstrap.js.map +1 -0
- package/dist/lib/sea/sqlite-vec-shim.d.ts +3 -0
- package/dist/lib/sea/sqlite-vec-shim.d.ts.map +1 -0
- package/dist/lib/sea/sqlite-vec-shim.js +10 -0
- package/dist/lib/sea/sqlite-vec-shim.js.map +1 -0
- package/dist/lib/tools/built-in/knowledge-entity-lookup.tool.d.ts +1 -2
- package/dist/lib/tools/built-in/knowledge-entity-lookup.tool.d.ts.map +1 -1
- package/dist/lib/tools/built-in/knowledge-entity-lookup.tool.js +7 -13
- package/dist/lib/tools/built-in/knowledge-entity-lookup.tool.js.map +1 -1
- package/dist/lib/tools/built-in/knowledge-graph-schema.tool.d.ts.map +1 -1
- package/dist/lib/tools/built-in/knowledge-graph-schema.tool.js +2 -4
- package/dist/lib/tools/built-in/knowledge-graph-schema.tool.js.map +1 -1
- package/dist/lib/tools/built-in/knowledge-search.tool.js +4 -4
- package/dist/lib/tools/built-in/knowledge-search.tool.js.map +1 -1
- package/dist/lib/tools/built-in/knowledge-sql.tool.d.ts.map +1 -1
- package/dist/lib/tools/built-in/knowledge-sql.tool.js +70 -37
- package/dist/lib/tools/built-in/knowledge-sql.tool.js.map +1 -1
- package/dist/lib/tools/built-in/knowledge-tools-factory.js +2 -2
- package/dist/lib/tools/built-in/knowledge-tools-factory.js.map +1 -1
- package/dist/lib/tools/built-in/knowledge-traverse.tool.d.ts +1 -2
- package/dist/lib/tools/built-in/knowledge-traverse.tool.d.ts.map +1 -1
- package/dist/lib/tools/built-in/knowledge-traverse.tool.js +5 -11
- package/dist/lib/tools/built-in/knowledge-traverse.tool.js.map +1 -1
- package/dist/lib/tools/workspace/workspace-tools.d.ts.map +1 -1
- package/dist/lib/tools/workspace/workspace-tools.js +5 -4
- package/dist/lib/tools/workspace/workspace-tools.js.map +1 -1
- package/dist/lib/types/tool-factory.d.ts.map +1 -1
- package/dist/lib/types/tool-factory.js +9 -2
- package/dist/lib/types/tool-factory.js.map +1 -1
- package/dist/lib/utils/document-extract.d.ts +10 -0
- package/dist/lib/utils/document-extract.d.ts.map +1 -0
- package/dist/lib/utils/document-extract.js +149 -0
- package/dist/lib/utils/document-extract.js.map +1 -0
- package/dist/lib/workflows/react-workflow-executor.d.ts.map +1 -1
- package/dist/lib/workflows/react-workflow-executor.js +20 -14
- package/dist/lib/workflows/react-workflow-executor.js.map +1 -1
- package/dist/lib/workflows/types.d.ts +71 -45
- package/dist/lib/workflows/types.d.ts.map +1 -1
- package/dist/lib/workflows/types.js +10 -0
- package/dist/lib/workflows/types.js.map +1 -1
- package/dist/public/assets/logo.png +0 -0
- package/dist/public/chat.html +3 -78
- package/dist/public/index.html +3 -330
- package/dist/public/src/components/AgentComposer.js +132 -132
- package/dist/public/src/components/AgentsView.js +1231 -350
- package/dist/public/src/components/AppRoot.js +101 -39
- package/dist/public/src/components/GraphView.js +11 -13
- package/dist/public/src/components/IdeView.js +133 -98
- package/dist/public/src/components/KnowledgeView.js +94 -130
- package/dist/public/src/components/LlmView.js +15 -19
- package/dist/public/src/components/LocalLlmView.js +2440 -0
- package/dist/public/src/components/LogViewer.js +155 -0
- package/dist/public/src/components/McpView.js +41 -49
- package/dist/public/src/components/MonitorView.js +79 -126
- package/dist/public/src/components/NavBar.js +16 -26
- package/dist/public/src/components/StandaloneChat.js +136 -150
- package/dist/public/src/services/ApiService.js +196 -2
- package/dist/public/src/services/SessionStore.js +6 -3
- package/dist/public/src/services/StreamManager.js +183 -0
- package/dist/public/src/store.js +1 -1
- package/dist/public/src/utils/card.js +21 -0
- package/dist/public/src/utils/markdown.js +1 -7
- package/dist/public/styles.css +2777 -0
- package/dist/src/cli/commands/init.d.ts.map +1 -1
- package/dist/src/cli/commands/init.js +7 -1
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/start.d.ts.map +1 -1
- package/dist/src/cli/commands/start.js +28 -5
- package/dist/src/cli/commands/start.js.map +1 -1
- package/dist/src/cli/index.js +13 -2
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/index.js +7 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/routes/agents.route.d.ts.map +1 -1
- package/dist/src/routes/agents.route.js +2 -0
- package/dist/src/routes/agents.route.js.map +1 -1
- package/dist/src/routes/chat.route.d.ts.map +1 -1
- package/dist/src/routes/chat.route.js +3 -2
- package/dist/src/routes/chat.route.js.map +1 -1
- package/dist/src/routes/llm.route.d.ts.map +1 -1
- package/dist/src/routes/llm.route.js +227 -7
- package/dist/src/routes/llm.route.js.map +1 -1
- package/dist/src/routes/local-llm.route.d.ts +3 -0
- package/dist/src/routes/local-llm.route.d.ts.map +1 -0
- package/dist/src/routes/local-llm.route.js +688 -0
- package/dist/src/routes/local-llm.route.js.map +1 -0
- package/dist/src/routes/logs.route.d.ts +3 -0
- package/dist/src/routes/logs.route.d.ts.map +1 -0
- package/dist/src/routes/logs.route.js +24 -0
- package/dist/src/routes/logs.route.js.map +1 -0
- package/dist/src/routes/vnc.route.d.ts +10 -1
- package/dist/src/routes/vnc.route.d.ts.map +1 -1
- package/dist/src/routes/vnc.route.js +37 -12
- package/dist/src/routes/vnc.route.js.map +1 -1
- package/dist/src/routes/workflows.route.d.ts.map +1 -1
- package/dist/src/routes/workflows.route.js +24 -0
- package/dist/src/routes/workflows.route.js.map +1 -1
- package/dist/src/server.d.ts.map +1 -1
- package/dist/src/server.js +24 -2
- package/dist/src/server.js.map +1 -1
- package/dist/templates/agents/actor.agent.yaml +34 -0
- package/dist/templates/agents/architect.agent.yaml +0 -1
- package/dist/templates/agents/chatbot.agent.yaml +0 -1
- package/dist/templates/agents/corporate.agent.yaml +0 -1
- package/dist/templates/agents/functions.agent.yaml +29 -0
- package/dist/templates/agents/investment-analyst.agent.yaml +0 -1
- package/dist/templates/agents/music-librarian.agent.yaml +3 -27
- package/dist/templates/agents/network-security.agent.yaml +0 -1
- package/dist/templates/agents/transport-security.agent.yaml +0 -1
- package/dist/templates/agents/web-engineer.agent.yaml +3 -4
- package/dist/templates/agents/web-pilot.agent.yaml +0 -1
- package/dist/templates/knowledge/patient-records.knowledge.yaml +20 -0
- package/dist/templates/knowledge/pdf-patients/PDF_Deid_Deidentification_0.pdf +0 -0
- package/dist/templates/knowledge/pdf-patients/PDF_Deid_Deidentification_1.pdf +0 -0
- package/dist/templates/knowledge/pdf-patients/PDF_Deid_Deidentification_10.pdf +0 -0
- package/dist/templates/knowledge/pdf-patients/PDF_Deid_Deidentification_11.pdf +0 -0
- package/dist/templates/knowledge/web-docs.knowledge.yaml +1 -1
- package/dist/templates/llm.json +73 -10
- package/dist/templates/skills/orcha-builder/SKILL.md +56 -3
- package/dist/templates/workflows/example.workflow.yaml +27 -35
- package/dist/templates/workflows/react-example.workflow.yaml +14 -19
- package/dist/templates/workflows/team-chat.workflow.yaml +47 -0
- package/package.json +14 -6
- package/dist/public/src/components/SkillsView.js +0 -137
- package/dist/public/src/components/WorkflowsView.js +0 -568
|
@@ -3,12 +3,12 @@ import { Component } from '../utils/Component.js';
|
|
|
3
3
|
import { api } from '../services/ApiService.js';
|
|
4
4
|
|
|
5
5
|
const TOOL_PREFIXES = {
|
|
6
|
-
'mcp': '
|
|
7
|
-
'knowledge': '
|
|
8
|
-
'function': '
|
|
9
|
-
'builtin': '
|
|
10
|
-
'sandbox': '
|
|
11
|
-
'workspace': '
|
|
6
|
+
'mcp': 'tool-chip-mcp',
|
|
7
|
+
'knowledge': 'tool-chip-knowledge',
|
|
8
|
+
'function': 'tool-chip-function',
|
|
9
|
+
'builtin': 'tool-chip-builtin',
|
|
10
|
+
'sandbox': 'tool-chip-sandbox',
|
|
11
|
+
'workspace': 'tool-chip-workspace',
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
export class AgentComposer extends Component {
|
|
@@ -97,69 +97,69 @@ export class AgentComposer extends Component {
|
|
|
97
97
|
const toolChips = tools.map(t => {
|
|
98
98
|
const prefix = t.split(':')[0];
|
|
99
99
|
const cls = TOOL_PREFIXES[prefix] || TOOL_PREFIXES['workspace'];
|
|
100
|
-
return `<span class="
|
|
101
|
-
${this._esc(t)}<button class="remove-tool-btn
|
|
100
|
+
return `<span class="tool-chip ${cls}">
|
|
101
|
+
${this._esc(t)}<button class="remove-tool-btn composer-remove-btn ml-1" data-tool="${this._esc(t)}">×</button>
|
|
102
102
|
</span>`;
|
|
103
103
|
}).join('');
|
|
104
104
|
|
|
105
105
|
const varChips = vars.map(v =>
|
|
106
|
-
`<span class="
|
|
107
|
-
${this._esc(v)}<button class="remove-var-btn
|
|
106
|
+
`<span class="var-chip">
|
|
107
|
+
${this._esc(v)}<button class="remove-var-btn composer-remove-btn ml-1" data-var="${this._esc(v)}">×</button>
|
|
108
108
|
</span>`
|
|
109
109
|
).join('');
|
|
110
110
|
|
|
111
111
|
const questionRows = questions.map((q, i) =>
|
|
112
112
|
`<div class="flex gap-2">
|
|
113
113
|
<input type="text" data-field="sampleQuestions.${i}" value="${this._esc(q)}"
|
|
114
|
-
class="composer-input
|
|
115
|
-
<button class="remove-question-btn
|
|
114
|
+
class="composer-input composer-input-field flex-1" />
|
|
115
|
+
<button class="remove-question-btn composer-remove-btn px-1" data-q-idx="${i}"><i class="fas fa-trash"></i></button>
|
|
116
116
|
</div>`
|
|
117
117
|
).join('');
|
|
118
118
|
|
|
119
119
|
return `
|
|
120
120
|
<!-- Identity & LLM -->
|
|
121
|
-
<div class="grid grid-cols-
|
|
122
|
-
<div class="
|
|
123
|
-
<h3 class="
|
|
121
|
+
<div class="grid grid-cols-2 gap-4">
|
|
122
|
+
<div class="composer-section space-y-3">
|
|
123
|
+
<h3 class="section-title">Identity</h3>
|
|
124
124
|
<div>
|
|
125
|
-
<label class="
|
|
125
|
+
<label class="composer-label">Name</label>
|
|
126
126
|
<input type="text" data-field="name" value="${this._esc(d.name || '')}"
|
|
127
|
-
class="composer-input
|
|
127
|
+
class="composer-input composer-input-field" />
|
|
128
128
|
</div>
|
|
129
129
|
<div>
|
|
130
|
-
<label class="
|
|
130
|
+
<label class="composer-label">Description</label>
|
|
131
131
|
<input type="text" data-field="description" value="${this._esc(d.description || '')}"
|
|
132
|
-
class="composer-input
|
|
132
|
+
class="composer-input composer-input-field" />
|
|
133
133
|
</div>
|
|
134
134
|
<div class="grid grid-cols-2 gap-3">
|
|
135
135
|
<div>
|
|
136
|
-
<label class="
|
|
136
|
+
<label class="composer-label">Version</label>
|
|
137
137
|
<input type="text" data-field="version" value="${this._esc(d.version || '1.0.0')}"
|
|
138
|
-
class="composer-input
|
|
138
|
+
class="composer-input composer-input-field" />
|
|
139
139
|
</div>
|
|
140
140
|
<div>
|
|
141
|
-
<label class="
|
|
141
|
+
<label class="composer-label">Max Iterations</label>
|
|
142
142
|
<input type="number" data-field="maxIterations" value="${d.maxIterations || ''}" min="1" placeholder="Default"
|
|
143
|
-
class="composer-input
|
|
143
|
+
class="composer-input composer-input-field" />
|
|
144
144
|
</div>
|
|
145
145
|
</div>
|
|
146
146
|
</div>
|
|
147
147
|
|
|
148
|
-
<div class="
|
|
149
|
-
<h3 class="
|
|
148
|
+
<div class="composer-section space-y-3">
|
|
149
|
+
<h3 class="section-title">LLM</h3>
|
|
150
150
|
<div>
|
|
151
|
-
<label class="
|
|
151
|
+
<label class="composer-label">Model</label>
|
|
152
152
|
<select data-field="llm.name"
|
|
153
|
-
class="composer-input
|
|
153
|
+
class="composer-input composer-input-field">
|
|
154
154
|
<option value="default" ${llmName === 'default' ? 'selected' : ''}>default</option>
|
|
155
155
|
${llmOptions}
|
|
156
156
|
</select>
|
|
157
157
|
</div>
|
|
158
158
|
<div>
|
|
159
|
-
<label class="
|
|
159
|
+
<label class="composer-label">Temperature <span class="text-muted font-mono" data-temp-display>${temp !== undefined ? temp : '—'}</span></label>
|
|
160
160
|
<input type="range" data-field="llm.temperature" min="0" max="2" step="0.1" value="${temp !== undefined ? temp : 0.7}"
|
|
161
|
-
class="w-full
|
|
162
|
-
<div class="flex justify-between text-xs text-
|
|
161
|
+
class="w-full" />
|
|
162
|
+
<div class="flex justify-between text-xs text-muted mt-1">
|
|
163
163
|
<span>0 Precise</span>
|
|
164
164
|
<span>2 Creative</span>
|
|
165
165
|
</div>
|
|
@@ -168,146 +168,146 @@ export class AgentComposer extends Component {
|
|
|
168
168
|
</div>
|
|
169
169
|
|
|
170
170
|
<!-- Prompt -->
|
|
171
|
-
<div class="
|
|
172
|
-
<h3 class="
|
|
171
|
+
<div class="composer-section space-y-3">
|
|
172
|
+
<h3 class="section-title">System Prompt</h3>
|
|
173
173
|
<textarea data-field="prompt.system" rows="10"
|
|
174
|
-
class="composer-input
|
|
174
|
+
class="composer-input composer-input-field font-mono resize-y">${this._esc(prompt.system || '')}</textarea>
|
|
175
175
|
<div>
|
|
176
|
-
<label class="
|
|
177
|
-
<div class="flex flex-wrap gap-1
|
|
176
|
+
<label class="composer-label">Input Variables</label>
|
|
177
|
+
<div class="flex flex-wrap gap-1 mb-2">${varChips}</div>
|
|
178
178
|
<div class="flex gap-2">
|
|
179
179
|
<input type="text" id="newVarInput" placeholder="Add variable..."
|
|
180
|
-
class="
|
|
181
|
-
<button id="addVarBtn" class="
|
|
180
|
+
class="composer-input-field flex-1" />
|
|
181
|
+
<button id="addVarBtn" class="btn btn-sm bg-surface">Add</button>
|
|
182
182
|
</div>
|
|
183
183
|
</div>
|
|
184
184
|
</div>
|
|
185
185
|
|
|
186
186
|
<!-- Tools & Skills -->
|
|
187
|
-
<div class="grid grid-cols-
|
|
188
|
-
<div class="
|
|
189
|
-
<h3 class="
|
|
190
|
-
<div class="flex flex-wrap gap-1
|
|
191
|
-
<button id="addToolBtn" class="
|
|
187
|
+
<div class="grid grid-cols-2 gap-4">
|
|
188
|
+
<div class="composer-section space-y-3">
|
|
189
|
+
<h3 class="section-title">Tools</h3>
|
|
190
|
+
<div class="flex flex-wrap gap-1">${toolChips || '<span class="text-xs text-muted">No tools added</span>'}</div>
|
|
191
|
+
<button id="addToolBtn" class="composer-add-btn">
|
|
192
192
|
<i class="fas fa-plus mr-1"></i> Add tool
|
|
193
193
|
</button>
|
|
194
194
|
<div id="toolPicker" class="hidden"></div>
|
|
195
195
|
</div>
|
|
196
196
|
|
|
197
|
-
<div class="
|
|
198
|
-
<h3 class="
|
|
197
|
+
<div class="composer-section space-y-3">
|
|
198
|
+
<h3 class="section-title">Skills</h3>
|
|
199
199
|
<div class="flex gap-3">
|
|
200
|
-
<label class="inline-flex items-center gap-1
|
|
201
|
-
<input type="radio" name="skillsMode" value="none" ${!skills ? 'checked' : ''} class="
|
|
200
|
+
<label class="inline-flex items-center gap-1 text-xs text-secondary cursor-pointer">
|
|
201
|
+
<input type="radio" name="skillsMode" value="none" ${!skills ? 'checked' : ''} class="skills-mode-radio" /> None
|
|
202
202
|
</label>
|
|
203
|
-
<label class="inline-flex items-center gap-1
|
|
204
|
-
<input type="radio" name="skillsMode" value="all" ${isAllSkills ? 'checked' : ''} class="
|
|
203
|
+
<label class="inline-flex items-center gap-1 text-xs text-secondary cursor-pointer">
|
|
204
|
+
<input type="radio" name="skillsMode" value="all" ${isAllSkills ? 'checked' : ''} class="skills-mode-radio" /> All
|
|
205
205
|
</label>
|
|
206
|
-
<label class="inline-flex items-center gap-1
|
|
207
|
-
<input type="radio" name="skillsMode" value="specific" ${(Array.isArray(skills) && !isAllSkills) ? 'checked' : ''} class="
|
|
206
|
+
<label class="inline-flex items-center gap-1 text-xs text-secondary cursor-pointer">
|
|
207
|
+
<input type="radio" name="skillsMode" value="specific" ${(Array.isArray(skills) && !isAllSkills) ? 'checked' : ''} class="skills-mode-radio" /> Specific
|
|
208
208
|
</label>
|
|
209
209
|
</div>
|
|
210
210
|
<div id="skillsList" class="${(Array.isArray(skills) && !isAllSkills) ? '' : 'hidden'} space-y-1">
|
|
211
211
|
${this._skills.map(s => {
|
|
212
212
|
const name = typeof s === 'string' ? s : s.name;
|
|
213
213
|
const checked = selectedSkills.includes(name);
|
|
214
|
-
return `<label class="flex items-center gap-2 text-xs text-
|
|
215
|
-
<input type="checkbox" value="${this._esc(name)}" ${checked ? 'checked' : ''} class="
|
|
214
|
+
return `<label class="flex items-center gap-2 text-xs text-secondary cursor-pointer">
|
|
215
|
+
<input type="checkbox" value="${this._esc(name)}" ${checked ? 'checked' : ''} class="skill-checkbox" /> ${this._esc(name)}
|
|
216
216
|
</label>`;
|
|
217
217
|
}).join('')}
|
|
218
|
-
${this._skills.length === 0 ? '<span class="text-xs text-
|
|
218
|
+
${this._skills.length === 0 ? '<span class="text-xs text-muted">No skills loaded</span>' : ''}
|
|
219
219
|
</div>
|
|
220
220
|
</div>
|
|
221
221
|
</div>
|
|
222
222
|
|
|
223
223
|
<!-- Memory, Output, Publish -->
|
|
224
|
-
<div class="grid grid-cols-
|
|
225
|
-
<div class="
|
|
226
|
-
<h3 class="
|
|
227
|
-
<label class="flex items-center gap-2 text-xs text-
|
|
228
|
-
<input type="checkbox" data-field="memory.enabled" ${memEnabled ? 'checked' : ''} class="
|
|
224
|
+
<div class="grid grid-cols-3 gap-4">
|
|
225
|
+
<div class="composer-section space-y-3">
|
|
226
|
+
<h3 class="section-title">Memory</h3>
|
|
227
|
+
<label class="flex items-center gap-2 text-xs text-secondary cursor-pointer">
|
|
228
|
+
<input type="checkbox" data-field="memory.enabled" ${memEnabled ? 'checked' : ''} class="composer-input" />
|
|
229
229
|
Enable persistent memory
|
|
230
230
|
</label>
|
|
231
231
|
<div id="memoryFields" class="${memEnabled ? '' : 'hidden'}">
|
|
232
|
-
<label class="
|
|
232
|
+
<label class="composer-label">Max Lines</label>
|
|
233
233
|
<input type="number" data-field="memory.maxLines" value="${memMaxLines}" min="1" placeholder="100"
|
|
234
|
-
class="composer-input
|
|
234
|
+
class="composer-input composer-input-field" />
|
|
235
235
|
</div>
|
|
236
236
|
</div>
|
|
237
237
|
|
|
238
|
-
<div class="
|
|
239
|
-
<h3 class="
|
|
238
|
+
<div class="composer-section space-y-3">
|
|
239
|
+
<h3 class="section-title">Output</h3>
|
|
240
240
|
<div>
|
|
241
|
-
<label class="
|
|
241
|
+
<label class="composer-label">Format</label>
|
|
242
242
|
<select data-field="output.format"
|
|
243
|
-
class="composer-input
|
|
243
|
+
class="composer-input composer-input-field">
|
|
244
244
|
<option value="text" ${outFmt === 'text' ? 'selected' : ''}>text</option>
|
|
245
245
|
<option value="structured" ${outFmt === 'structured' ? 'selected' : ''}>structured</option>
|
|
246
246
|
</select>
|
|
247
247
|
</div>
|
|
248
248
|
<div id="outputSchemaField" class="${outFmt === 'structured' ? '' : 'hidden'}">
|
|
249
|
-
<label class="
|
|
249
|
+
<label class="composer-label">Schema (JSON)</label>
|
|
250
250
|
<textarea data-field="output.schema" rows="4"
|
|
251
|
-
class="composer-input
|
|
252
|
-
<div id="outputSchemaError" class="hidden text-xs text-red
|
|
251
|
+
class="composer-input composer-input-field text-xs font-mono resize-y">${this._esc(outSchema)}</textarea>
|
|
252
|
+
<div id="outputSchemaError" class="hidden text-xs text-red mt-1"></div>
|
|
253
253
|
</div>
|
|
254
254
|
</div>
|
|
255
255
|
|
|
256
|
-
<div class="
|
|
257
|
-
<h3 class="
|
|
258
|
-
<label class="flex items-center gap-2 text-xs text-
|
|
259
|
-
<input type="checkbox" data-field="publish.enabled" ${pubEnabled ? 'checked' : ''} class="
|
|
256
|
+
<div class="composer-section space-y-3">
|
|
257
|
+
<h3 class="section-title">Publish</h3>
|
|
258
|
+
<label class="flex items-center gap-2 text-xs text-secondary cursor-pointer">
|
|
259
|
+
<input type="checkbox" data-field="publish.enabled" ${pubEnabled ? 'checked' : ''} class="composer-input" />
|
|
260
260
|
Standalone chat page
|
|
261
261
|
</label>
|
|
262
262
|
<div id="publishFields" class="${pubEnabled ? '' : 'hidden'}">
|
|
263
|
-
<label class="
|
|
263
|
+
<label class="composer-label">Password</label>
|
|
264
264
|
<input type="text" data-field="publish.password" value="${this._esc(pubPassword)}" placeholder="Optional"
|
|
265
|
-
class="composer-input
|
|
265
|
+
class="composer-input composer-input-field" />
|
|
266
266
|
</div>
|
|
267
267
|
</div>
|
|
268
268
|
</div>
|
|
269
269
|
|
|
270
270
|
<!-- Integrations -->
|
|
271
|
-
<div class="
|
|
271
|
+
<div class="composer-section space-y-3">
|
|
272
272
|
<div class="flex items-center justify-between">
|
|
273
|
-
<h3 class="
|
|
273
|
+
<h3 class="section-title">Integrations</h3>
|
|
274
274
|
<div class="flex gap-1">
|
|
275
|
-
<button class="add-integration-btn
|
|
276
|
-
<button class="add-integration-btn
|
|
275
|
+
<button class="add-integration-btn composer-add-btn" data-integ-type="collabnook"><i class="fas fa-plus mr-1"></i>Collabnook</button>
|
|
276
|
+
<button class="add-integration-btn composer-add-btn ml-3" data-integ-type="email"><i class="fas fa-plus mr-1"></i>Email</button>
|
|
277
277
|
</div>
|
|
278
278
|
</div>
|
|
279
279
|
${this._renderIntegrations()}
|
|
280
280
|
</div>
|
|
281
281
|
|
|
282
282
|
<!-- Triggers -->
|
|
283
|
-
<div class="
|
|
283
|
+
<div class="composer-section space-y-3">
|
|
284
284
|
<div class="flex items-center justify-between">
|
|
285
|
-
<h3 class="
|
|
285
|
+
<h3 class="section-title">Triggers</h3>
|
|
286
286
|
<div class="flex gap-1">
|
|
287
|
-
<button class="add-trigger-btn
|
|
288
|
-
<button class="add-trigger-btn
|
|
287
|
+
<button class="add-trigger-btn composer-add-btn" data-trigger-type="cron"><i class="fas fa-plus mr-1"></i>Cron</button>
|
|
288
|
+
<button class="add-trigger-btn composer-add-btn ml-3" data-trigger-type="webhook"><i class="fas fa-plus mr-1"></i>Webhook</button>
|
|
289
289
|
</div>
|
|
290
290
|
</div>
|
|
291
291
|
${this._renderTriggers()}
|
|
292
292
|
</div>
|
|
293
293
|
|
|
294
294
|
<!-- Sample Questions & Metadata -->
|
|
295
|
-
<div class="grid grid-cols-
|
|
296
|
-
<div class="
|
|
297
|
-
<h3 class="
|
|
295
|
+
<div class="grid grid-cols-2 gap-4">
|
|
296
|
+
<div class="composer-section space-y-3">
|
|
297
|
+
<h3 class="section-title">Sample Questions</h3>
|
|
298
298
|
<div class="space-y-2">
|
|
299
|
-
${questionRows || '<span class="text-xs text-
|
|
299
|
+
${questionRows || '<span class="text-xs text-muted">No sample questions</span>'}
|
|
300
300
|
</div>
|
|
301
|
-
<button id="addQuestionBtn" class="
|
|
301
|
+
<button id="addQuestionBtn" class="composer-add-btn">
|
|
302
302
|
<i class="fas fa-plus mr-1"></i> Add question
|
|
303
303
|
</button>
|
|
304
304
|
</div>
|
|
305
305
|
|
|
306
|
-
<div class="
|
|
307
|
-
<h3 class="
|
|
306
|
+
<div class="composer-section space-y-3">
|
|
307
|
+
<h3 class="section-title">Metadata</h3>
|
|
308
308
|
<textarea data-field="metadata" rows="6"
|
|
309
|
-
class="composer-input
|
|
310
|
-
<div id="metadataError" class="hidden text-xs text-red
|
|
309
|
+
class="composer-input composer-input-field text-xs font-mono resize-y">${this._esc(meta)}</textarea>
|
|
310
|
+
<div id="metadataError" class="hidden text-xs text-red mt-1"></div>
|
|
311
311
|
</div>
|
|
312
312
|
</div>
|
|
313
313
|
`;
|
|
@@ -316,16 +316,16 @@ export class AgentComposer extends Component {
|
|
|
316
316
|
// ── Integrations sub-cards ──
|
|
317
317
|
_renderIntegrations() {
|
|
318
318
|
const integrations = this._data.integrations || [];
|
|
319
|
-
if (!integrations.length) return '<div class="text-xs text-
|
|
319
|
+
if (!integrations.length) return '<div class="text-xs text-muted">No integrations</div>';
|
|
320
320
|
return integrations.map((integ, i) => integ.type === 'email' ? this._renderEmailCard(integ, i) : this._renderCollabnookCard(integ, i)).join('');
|
|
321
321
|
}
|
|
322
322
|
|
|
323
323
|
_renderCollabnookCard(integ, idx) {
|
|
324
324
|
return `
|
|
325
|
-
<div class="
|
|
325
|
+
<div class="composer-sub-card" data-integ-idx="${idx}">
|
|
326
326
|
<div class="flex items-center justify-between mb-2">
|
|
327
|
-
<span class="text-xs font-medium text-
|
|
328
|
-
<button class="remove-integration-btn
|
|
327
|
+
<span class="text-xs font-medium text-secondary"><i class="fas fa-comments mr-1"></i>Collabnook</span>
|
|
328
|
+
<button class="remove-integration-btn composer-remove-btn" data-integ-idx="${idx}"><i class="fas fa-trash"></i></button>
|
|
329
329
|
</div>
|
|
330
330
|
<div class="grid grid-cols-2 gap-2">
|
|
331
331
|
${this._field(`integrations.${idx}.url`, 'URL', integ.url)}
|
|
@@ -339,10 +339,10 @@ export class AgentComposer extends Component {
|
|
|
339
339
|
_renderEmailCard(integ, idx) {
|
|
340
340
|
const imap = integ.imap || {}, smtp = integ.smtp || {}, auth = integ.auth || {};
|
|
341
341
|
return `
|
|
342
|
-
<div class="
|
|
342
|
+
<div class="composer-sub-card" data-integ-idx="${idx}">
|
|
343
343
|
<div class="flex items-center justify-between mb-2">
|
|
344
|
-
<span class="text-xs font-medium text-
|
|
345
|
-
<button class="remove-integration-btn
|
|
344
|
+
<span class="text-xs font-medium text-secondary"><i class="fas fa-envelope mr-1"></i>Email</span>
|
|
345
|
+
<button class="remove-integration-btn composer-remove-btn" data-integ-idx="${idx}"><i class="fas fa-trash"></i></button>
|
|
346
346
|
</div>
|
|
347
347
|
<div class="grid grid-cols-3 gap-2 mb-2">
|
|
348
348
|
${this._field(`integrations.${idx}.imap.host`, 'IMAP Host', imap.host)}
|
|
@@ -371,39 +371,39 @@ export class AgentComposer extends Component {
|
|
|
371
371
|
const inputVars = this._data.prompt?.inputVariables || [];
|
|
372
372
|
const primaryVar = inputVars[0] || 'query';
|
|
373
373
|
|
|
374
|
-
if (!triggers.length) return '<div class="text-xs text-
|
|
374
|
+
if (!triggers.length) return '<div class="text-xs text-muted">No triggers</div>';
|
|
375
375
|
return triggers.map((trig, i) => {
|
|
376
376
|
const isCron = trig.type === 'cron' || trig.schedule;
|
|
377
377
|
const inputVal = (typeof trig.input === 'object' && trig.input) ? (trig.input[primaryVar] || '') : '';
|
|
378
378
|
return `
|
|
379
|
-
<div class="
|
|
379
|
+
<div class="composer-sub-card" data-trigger-idx="${i}">
|
|
380
380
|
<div class="flex items-center justify-between mb-2">
|
|
381
|
-
<span class="text-xs font-medium text-
|
|
382
|
-
<button class="remove-trigger-btn
|
|
381
|
+
<span class="text-xs font-medium text-secondary"><i class="fas ${isCron ? 'fa-clock' : 'fa-link'} mr-1"></i>${isCron ? 'Cron' : 'Webhook'}</span>
|
|
382
|
+
<button class="remove-trigger-btn composer-remove-btn" data-trigger-idx="${i}"><i class="fas fa-trash"></i></button>
|
|
383
383
|
</div>
|
|
384
384
|
<div class="grid grid-cols-2 gap-2">
|
|
385
385
|
${isCron
|
|
386
386
|
? `<div>
|
|
387
|
-
<label class="
|
|
387
|
+
<label class="composer-label">Schedule</label>
|
|
388
388
|
<input type="text" data-field="triggers.${i}.schedule" value="${this._esc(trig.schedule || '')}" placeholder="*/5 * * * *"
|
|
389
|
-
class="composer-input
|
|
389
|
+
class="composer-input composer-input-sm" />
|
|
390
390
|
<div class="flex flex-wrap gap-1 mt-1">
|
|
391
|
-
<button class="cron-preset-btn
|
|
392
|
-
<button class="cron-preset-btn
|
|
393
|
-
<button class="cron-preset-btn
|
|
394
|
-
<button class="cron-preset-btn
|
|
395
|
-
<button class="cron-preset-btn
|
|
396
|
-
<button class="cron-preset-btn
|
|
397
|
-
<button class="cron-preset-btn
|
|
398
|
-
<button class="cron-preset-btn
|
|
391
|
+
<button class="cron-preset-btn" data-preset="* * * * *" data-trigger-idx="${i}">1min</button>
|
|
392
|
+
<button class="cron-preset-btn" data-preset="*/5 * * * *" data-trigger-idx="${i}">5min</button>
|
|
393
|
+
<button class="cron-preset-btn" data-preset="*/15 * * * *" data-trigger-idx="${i}">15min</button>
|
|
394
|
+
<button class="cron-preset-btn" data-preset="0 * * * *" data-trigger-idx="${i}">hourly</button>
|
|
395
|
+
<button class="cron-preset-btn" data-preset="0 */6 * * *" data-trigger-idx="${i}">6hr</button>
|
|
396
|
+
<button class="cron-preset-btn" data-preset="0 0 * * *" data-trigger-idx="${i}">daily</button>
|
|
397
|
+
<button class="cron-preset-btn" data-preset="0 0 * * 1" data-trigger-idx="${i}">weekly</button>
|
|
398
|
+
<button class="cron-preset-btn" data-preset="0 0 1 * *" data-trigger-idx="${i}">monthly</button>
|
|
399
399
|
</div>
|
|
400
400
|
</div>`
|
|
401
401
|
: this._field(`triggers.${i}.path`, 'Path', trig.path, '/webhook/my-hook')
|
|
402
402
|
}
|
|
403
403
|
<div>
|
|
404
|
-
<label class="
|
|
404
|
+
<label class="composer-label">Prompt <span class="text-muted font-mono">(${this._esc(primaryVar)})</span></label>
|
|
405
405
|
<input type="text" data-field="triggers.${i}.inputVar" value="${this._esc(inputVal)}" placeholder="e.g. Generate the daily report"
|
|
406
|
-
class="composer-input
|
|
406
|
+
class="composer-input composer-input-sm" />
|
|
407
407
|
</div>
|
|
408
408
|
</div>
|
|
409
409
|
</div>`;
|
|
@@ -413,23 +413,23 @@ export class AgentComposer extends Component {
|
|
|
413
413
|
// ── Shared field helpers ──
|
|
414
414
|
_field(dataField, label, value, placeholder) {
|
|
415
415
|
return `<div>
|
|
416
|
-
<label class="
|
|
416
|
+
<label class="composer-label">${label}</label>
|
|
417
417
|
<input type="text" data-field="${dataField}" value="${this._esc(value || '')}" ${placeholder ? `placeholder="${placeholder}"` : ''}
|
|
418
|
-
class="composer-input
|
|
418
|
+
class="composer-input composer-input-sm" />
|
|
419
419
|
</div>`;
|
|
420
420
|
}
|
|
421
421
|
_fieldNum(dataField, label, value) {
|
|
422
422
|
return `<div>
|
|
423
|
-
<label class="
|
|
423
|
+
<label class="composer-label">${label}</label>
|
|
424
424
|
<input type="number" data-field="${dataField}" value="${value || ''}"
|
|
425
|
-
class="composer-input
|
|
425
|
+
class="composer-input composer-input-sm" />
|
|
426
426
|
</div>`;
|
|
427
427
|
}
|
|
428
428
|
_fieldSelect(dataField, label, value) {
|
|
429
429
|
return `<div>
|
|
430
|
-
<label class="
|
|
430
|
+
<label class="composer-label">${label}</label>
|
|
431
431
|
<select data-field="${dataField}"
|
|
432
|
-
class="composer-input
|
|
432
|
+
class="composer-input composer-input-sm">
|
|
433
433
|
<option value="false" ${!value ? 'selected' : ''}>false</option>
|
|
434
434
|
<option value="true" ${value ? 'selected' : ''}>true</option>
|
|
435
435
|
</select>
|
|
@@ -451,27 +451,27 @@ export class AgentComposer extends Component {
|
|
|
451
451
|
const filtered = active.items.filter(v => !search || v.toLowerCase().includes(search));
|
|
452
452
|
|
|
453
453
|
return `
|
|
454
|
-
<div class="
|
|
455
|
-
<div class="
|
|
456
|
-
${tabs.map(t => `<button class="tool-picker-tab
|
|
454
|
+
<div class="tool-picker-inline">
|
|
455
|
+
<div class="tool-picker-inline-tabs">
|
|
456
|
+
${tabs.map(t => `<button class="tool-picker-inline-tab ${t.id === this._toolPickerTab ? 'active' : ''} tool-picker-tab" data-tab="${t.id}">${t.label}</button>`).join('')}
|
|
457
457
|
</div>
|
|
458
458
|
<div class="p-2">
|
|
459
459
|
<input type="text" id="toolPickerSearch" placeholder="Filter..." value="${this._esc(this._toolPickerSearch)}"
|
|
460
|
-
class="
|
|
461
|
-
<div class="
|
|
462
|
-
${filtered.length === 0 ? '<div class="text-xs text-
|
|
460
|
+
class="composer-input-sm mb-2" />
|
|
461
|
+
<div class="tool-picker-list">
|
|
462
|
+
${filtered.length === 0 ? '<div class="text-xs text-muted p-2 text-center">No items</div>' : ''}
|
|
463
463
|
${filtered.map(item => {
|
|
464
464
|
const added = existing.has(item);
|
|
465
|
-
return `<div class="
|
|
465
|
+
return `<div class="tool-picker-item ${added ? 'added' : 'available'}"
|
|
466
466
|
${!added ? `data-add-tool="${this._esc(item)}"` : ''}>
|
|
467
467
|
<span>${this._esc(item.split(':')[1] || item)}</span>
|
|
468
|
-
${added ? '<i class="fas fa-check text-green
|
|
468
|
+
${added ? '<i class="fas fa-check text-green text-2xs"></i>' : '<i class="fas fa-plus text-muted text-2xs"></i>'}
|
|
469
469
|
</div>`;
|
|
470
470
|
}).join('')}
|
|
471
471
|
</div>
|
|
472
472
|
</div>
|
|
473
|
-
<div class="border-t
|
|
474
|
-
<button id="closeToolPicker" class="
|
|
473
|
+
<div class="border-t px-2 py-1 flex justify-end">
|
|
474
|
+
<button id="closeToolPicker" class="composer-add-btn">Close</button>
|
|
475
475
|
</div>
|
|
476
476
|
</div>`;
|
|
477
477
|
}
|
|
@@ -529,9 +529,9 @@ export class AgentComposer extends Component {
|
|
|
529
529
|
if (!field || !error) return;
|
|
530
530
|
field.addEventListener('blur', () => {
|
|
531
531
|
const val = field.value.trim();
|
|
532
|
-
if (!val) { error.classList.add('hidden'); field.classList.remove('
|
|
533
|
-
try { JSON.parse(val); error.classList.add('hidden'); field.classList.remove('
|
|
534
|
-
catch (e) { error.textContent = e.message; error.classList.remove('hidden'); field.classList.add('
|
|
532
|
+
if (!val) { error.classList.add('hidden'); field.classList.remove('error'); return; }
|
|
533
|
+
try { JSON.parse(val); error.classList.add('hidden'); field.classList.remove('error'); }
|
|
534
|
+
catch (e) { error.textContent = e.message; error.classList.remove('hidden'); field.classList.add('error'); }
|
|
535
535
|
});
|
|
536
536
|
}
|
|
537
537
|
|