ai-browser 0.2.4 → 0.2.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/README.md +30 -0
- package/dist/agent/agent-loop.d.ts +8 -2
- package/dist/agent/agent-loop.d.ts.map +1 -1
- package/dist/agent/agent-loop.js +138 -86
- package/dist/agent/agent-loop.js.map +1 -1
- package/dist/agent/config.d.ts +5 -0
- package/dist/agent/config.d.ts.map +1 -1
- package/dist/agent/config.js +5 -0
- package/dist/agent/config.js.map +1 -1
- package/dist/agent/content-budget.d.ts +11 -0
- package/dist/agent/content-budget.d.ts.map +1 -0
- package/dist/agent/content-budget.js +129 -0
- package/dist/agent/content-budget.js.map +1 -0
- package/dist/agent/conversation-manager.d.ts +48 -0
- package/dist/agent/conversation-manager.d.ts.map +1 -0
- package/dist/agent/conversation-manager.js +157 -0
- package/dist/agent/conversation-manager.js.map +1 -0
- package/dist/agent/error-recovery.d.ts +29 -0
- package/dist/agent/error-recovery.d.ts.map +1 -0
- package/dist/agent/error-recovery.js +72 -0
- package/dist/agent/error-recovery.js.map +1 -0
- package/dist/agent/page-state-cache.d.ts +22 -0
- package/dist/agent/page-state-cache.d.ts.map +1 -0
- package/dist/agent/page-state-cache.js +71 -0
- package/dist/agent/page-state-cache.js.map +1 -0
- package/dist/agent/progress-estimator.d.ts +17 -0
- package/dist/agent/progress-estimator.d.ts.map +1 -0
- package/dist/agent/progress-estimator.js +67 -0
- package/dist/agent/progress-estimator.js.map +1 -0
- package/dist/agent/prompt.d.ts +1 -1
- package/dist/agent/prompt.d.ts.map +1 -1
- package/dist/agent/prompt.js +83 -48
- package/dist/agent/prompt.js.map +1 -1
- package/dist/agent/token-tracker.d.ts +22 -0
- package/dist/agent/token-tracker.d.ts.map +1 -0
- package/dist/agent/token-tracker.js +29 -0
- package/dist/agent/token-tracker.js.map +1 -0
- package/dist/agent/tool-usage-tracker.d.ts +45 -0
- package/dist/agent/tool-usage-tracker.d.ts.map +1 -0
- package/dist/agent/tool-usage-tracker.js +145 -0
- package/dist/agent/tool-usage-tracker.js.map +1 -0
- package/dist/agent/types.d.ts +24 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/api/routes.d.ts.map +1 -1
- package/dist/api/routes.js +75 -1
- package/dist/api/routes.js.map +1 -1
- package/dist/mcp/ai-markdown.d.ts +2 -0
- package/dist/mcp/ai-markdown.d.ts.map +1 -0
- package/dist/mcp/ai-markdown.js +1739 -0
- package/dist/mcp/ai-markdown.js.map +1 -0
- package/dist/mcp/browser-mcp-server.d.ts.map +1 -1
- package/dist/mcp/browser-mcp-server.js +279 -49
- package/dist/mcp/browser-mcp-server.js.map +1 -1
- package/dist/mcp/task-tools.d.ts.map +1 -1
- package/dist/mcp/task-tools.js +107 -13
- package/dist/mcp/task-tools.js.map +1 -1
- package/dist/task/tool-actions.d.ts +4 -0
- package/dist/task/tool-actions.d.ts.map +1 -1
- package/dist/task/tool-actions.js +72 -0
- package/dist/task/tool-actions.js.map +1 -1
- package/package.json +3 -2
- package/public/index.html +593 -41
package/public/index.html
CHANGED
|
@@ -565,7 +565,27 @@ body {
|
|
|
565
565
|
justify-content: center;
|
|
566
566
|
background: #010409;
|
|
567
567
|
padding: 12px;
|
|
568
|
+
position: relative;
|
|
569
|
+
}
|
|
570
|
+
.screenshot-loading::before {
|
|
571
|
+
content: '';
|
|
572
|
+
position: absolute;
|
|
573
|
+
inset: 0;
|
|
574
|
+
background: rgba(0,0,0,0.4);
|
|
575
|
+
z-index: 1;
|
|
576
|
+
}
|
|
577
|
+
.screenshot-loading::after {
|
|
578
|
+
content: '';
|
|
579
|
+
position: absolute;
|
|
580
|
+
width: 24px; height: 24px;
|
|
581
|
+
border: 2px solid var(--border);
|
|
582
|
+
border-top-color: var(--accent);
|
|
583
|
+
border-radius: 50%;
|
|
584
|
+
animation: spin 0.8s linear infinite;
|
|
585
|
+
z-index: 2;
|
|
568
586
|
}
|
|
587
|
+
@keyframes spin { to { transform: rotate(360deg); } }
|
|
588
|
+
.screenshot-updated { box-shadow: inset 0 0 0 2px var(--accent); transition: box-shadow 0.3s ease; }
|
|
569
589
|
.preview-body img {
|
|
570
590
|
max-width: 100%;
|
|
571
591
|
max-height: 100%;
|
|
@@ -660,6 +680,26 @@ body {
|
|
|
660
680
|
color: var(--accent);
|
|
661
681
|
}
|
|
662
682
|
.msg-tool-call .label { color: var(--accent); font-weight: 600; }
|
|
683
|
+
.msg-tool-call .tool-desc { color: var(--text-primary); font-size: 13px; }
|
|
684
|
+
.msg-tool-call details.tool-raw {
|
|
685
|
+
margin-top: 4px;
|
|
686
|
+
border: 1px solid var(--border);
|
|
687
|
+
border-radius: var(--radius-sm);
|
|
688
|
+
overflow: hidden;
|
|
689
|
+
}
|
|
690
|
+
.msg-tool-call details.tool-raw summary {
|
|
691
|
+
padding: 3px 8px;
|
|
692
|
+
font-size: 11px;
|
|
693
|
+
color: var(--text-muted);
|
|
694
|
+
cursor: pointer;
|
|
695
|
+
background: var(--bg-surface);
|
|
696
|
+
}
|
|
697
|
+
.msg-tool-call details.tool-raw summary:hover { color: var(--text-secondary); }
|
|
698
|
+
.msg-tool-call details.tool-raw pre {
|
|
699
|
+
margin: 0;
|
|
700
|
+
padding: 6px 8px;
|
|
701
|
+
font-size: 11px;
|
|
702
|
+
}
|
|
663
703
|
.msg-tool-call pre {
|
|
664
704
|
margin: 4px 0 0;
|
|
665
705
|
color: var(--text-primary);
|
|
@@ -746,6 +786,35 @@ body {
|
|
|
746
786
|
font-style: normal;
|
|
747
787
|
}
|
|
748
788
|
|
|
789
|
+
/* Progress bar */
|
|
790
|
+
.progress-bar-wrap {
|
|
791
|
+
height: 3px;
|
|
792
|
+
background: var(--bg-overlay);
|
|
793
|
+
border-radius: 2px;
|
|
794
|
+
overflow: hidden;
|
|
795
|
+
margin: 0;
|
|
796
|
+
display: none;
|
|
797
|
+
}
|
|
798
|
+
.progress-bar-wrap.active { display: block; }
|
|
799
|
+
.progress-bar-fill {
|
|
800
|
+
height: 100%;
|
|
801
|
+
background: var(--accent);
|
|
802
|
+
border-radius: 2px;
|
|
803
|
+
transition: width 0.4s ease;
|
|
804
|
+
width: 0%;
|
|
805
|
+
}
|
|
806
|
+
.progress-info {
|
|
807
|
+
display: none;
|
|
808
|
+
font-size: 11px;
|
|
809
|
+
color: var(--text-muted);
|
|
810
|
+
padding: 4px 16px;
|
|
811
|
+
gap: 12px;
|
|
812
|
+
background: var(--bg-surface);
|
|
813
|
+
}
|
|
814
|
+
.progress-info.active { display: flex; align-items: center; }
|
|
815
|
+
.progress-phase { text-transform: capitalize; color: var(--text-secondary); }
|
|
816
|
+
.progress-percent { color: var(--accent); font-weight: 600; }
|
|
817
|
+
|
|
749
818
|
/* Typing indicator */
|
|
750
819
|
.typing-indicator {
|
|
751
820
|
display: none;
|
|
@@ -812,6 +881,141 @@ body {
|
|
|
812
881
|
justify-content: flex-end;
|
|
813
882
|
}
|
|
814
883
|
|
|
884
|
+
/* ===== Tasks View Styles ===== */
|
|
885
|
+
.tasks-toolbar {
|
|
886
|
+
background: var(--bg-surface);
|
|
887
|
+
border-bottom: 1px solid var(--border);
|
|
888
|
+
padding: 10px 20px;
|
|
889
|
+
display: flex;
|
|
890
|
+
gap: 8px;
|
|
891
|
+
align-items: center;
|
|
892
|
+
flex-shrink: 0;
|
|
893
|
+
}
|
|
894
|
+
.tasks-list {
|
|
895
|
+
flex: 1;
|
|
896
|
+
overflow-y: auto;
|
|
897
|
+
padding: 16px;
|
|
898
|
+
display: grid;
|
|
899
|
+
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
|
900
|
+
gap: 12px;
|
|
901
|
+
align-content: start;
|
|
902
|
+
}
|
|
903
|
+
.task-card {
|
|
904
|
+
background: var(--bg-surface);
|
|
905
|
+
border: 1px solid var(--border);
|
|
906
|
+
border-radius: var(--radius-lg);
|
|
907
|
+
padding: 14px;
|
|
908
|
+
cursor: pointer;
|
|
909
|
+
transition: all var(--transition);
|
|
910
|
+
}
|
|
911
|
+
.task-card:hover { border-color: var(--accent); }
|
|
912
|
+
.task-card .task-header {
|
|
913
|
+
display: flex;
|
|
914
|
+
justify-content: space-between;
|
|
915
|
+
align-items: center;
|
|
916
|
+
margin-bottom: 8px;
|
|
917
|
+
}
|
|
918
|
+
.task-card .task-id {
|
|
919
|
+
font-size: 11px;
|
|
920
|
+
color: var(--text-muted);
|
|
921
|
+
font-family: monospace;
|
|
922
|
+
}
|
|
923
|
+
.task-status {
|
|
924
|
+
display: inline-block;
|
|
925
|
+
padding: 2px 8px;
|
|
926
|
+
border-radius: var(--radius-sm);
|
|
927
|
+
font-size: 11px;
|
|
928
|
+
font-weight: 600;
|
|
929
|
+
}
|
|
930
|
+
.task-status.running { background: rgba(88,166,255,0.15); color: var(--accent); }
|
|
931
|
+
.task-status.done { background: rgba(35,134,54,0.15); color: #3fb950; }
|
|
932
|
+
.task-status.failed { background: rgba(218,54,51,0.15); color: #f85149; }
|
|
933
|
+
.task-status.pending { background: var(--bg-overlay); color: var(--text-muted); }
|
|
934
|
+
.task-card .task-goal {
|
|
935
|
+
font-size: 14px;
|
|
936
|
+
color: var(--text-primary);
|
|
937
|
+
margin-bottom: 6px;
|
|
938
|
+
overflow: hidden;
|
|
939
|
+
text-overflow: ellipsis;
|
|
940
|
+
white-space: nowrap;
|
|
941
|
+
}
|
|
942
|
+
.task-card .task-meta {
|
|
943
|
+
font-size: 12px;
|
|
944
|
+
color: var(--text-muted);
|
|
945
|
+
}
|
|
946
|
+
.task-detail {
|
|
947
|
+
flex: 1;
|
|
948
|
+
overflow-y: auto;
|
|
949
|
+
padding: 16px;
|
|
950
|
+
}
|
|
951
|
+
.task-detail-header {
|
|
952
|
+
display: flex;
|
|
953
|
+
align-items: center;
|
|
954
|
+
gap: 12px;
|
|
955
|
+
margin-bottom: 16px;
|
|
956
|
+
}
|
|
957
|
+
.task-detail-back {
|
|
958
|
+
background: none;
|
|
959
|
+
border: none;
|
|
960
|
+
color: var(--accent);
|
|
961
|
+
cursor: pointer;
|
|
962
|
+
font-size: 14px;
|
|
963
|
+
padding: 4px 8px;
|
|
964
|
+
}
|
|
965
|
+
.task-detail-back:hover { text-decoration: underline; }
|
|
966
|
+
.task-detail .meta-grid {
|
|
967
|
+
display: grid;
|
|
968
|
+
grid-template-columns: 120px 1fr;
|
|
969
|
+
row-gap: 8px;
|
|
970
|
+
font-size: 14px;
|
|
971
|
+
margin-bottom: 16px;
|
|
972
|
+
}
|
|
973
|
+
.task-detail .meta-key { color: var(--text-muted); }
|
|
974
|
+
.task-detail pre {
|
|
975
|
+
background: var(--bg-canvas);
|
|
976
|
+
border: 1px solid var(--border);
|
|
977
|
+
border-radius: var(--radius-md);
|
|
978
|
+
padding: 12px;
|
|
979
|
+
overflow: auto;
|
|
980
|
+
max-height: 400px;
|
|
981
|
+
font-size: 13px;
|
|
982
|
+
white-space: pre-wrap;
|
|
983
|
+
word-break: break-all;
|
|
984
|
+
}
|
|
985
|
+
.task-create-form {
|
|
986
|
+
max-width: 600px;
|
|
987
|
+
}
|
|
988
|
+
.task-create-form label {
|
|
989
|
+
display: block;
|
|
990
|
+
font-size: 13px;
|
|
991
|
+
color: var(--text-secondary);
|
|
992
|
+
margin: 12px 0 4px;
|
|
993
|
+
}
|
|
994
|
+
.task-create-form input,
|
|
995
|
+
.task-create-form textarea {
|
|
996
|
+
width: 100%;
|
|
997
|
+
padding: 8px 12px;
|
|
998
|
+
font-size: 14px;
|
|
999
|
+
border: 1px solid var(--border);
|
|
1000
|
+
border-radius: var(--radius-md);
|
|
1001
|
+
background: var(--bg-canvas);
|
|
1002
|
+
color: var(--text-primary);
|
|
1003
|
+
outline: none;
|
|
1004
|
+
}
|
|
1005
|
+
.task-create-form input:focus,
|
|
1006
|
+
.task-create-form textarea:focus { border-color: var(--accent); }
|
|
1007
|
+
.task-create-form textarea { min-height: 80px; resize: vertical; }
|
|
1008
|
+
.task-create-form .form-row {
|
|
1009
|
+
display: grid;
|
|
1010
|
+
grid-template-columns: 1fr 1fr;
|
|
1011
|
+
gap: 12px;
|
|
1012
|
+
}
|
|
1013
|
+
.task-create-form .form-actions {
|
|
1014
|
+
margin-top: 16px;
|
|
1015
|
+
display: flex;
|
|
1016
|
+
gap: 8px;
|
|
1017
|
+
}
|
|
1018
|
+
|
|
815
1019
|
/* ===== Responsive ===== */
|
|
816
1020
|
@media (max-width: 900px) {
|
|
817
1021
|
.sem-body { flex-direction: column; padding-bottom: 28px; }
|
|
@@ -820,6 +1024,23 @@ body {
|
|
|
820
1024
|
#view-agent .agent-main { flex-direction: column; }
|
|
821
1025
|
.chat-panel, .preview-panel { width: 100%; border-right: none; }
|
|
822
1026
|
.preview-panel { border-top: 1px solid var(--border); }
|
|
1027
|
+
.tasks-list { grid-template-columns: 1fr; }
|
|
1028
|
+
}
|
|
1029
|
+
@media (max-width: 768px) {
|
|
1030
|
+
.app-logo { font-size: 13px; }
|
|
1031
|
+
.nav-tab { padding: 5px 10px; font-size: 12px; }
|
|
1032
|
+
.preview-panel { max-height: 40vh; }
|
|
1033
|
+
.progress-info { padding: 3px 12px; font-size: 10px; }
|
|
1034
|
+
.modal { width: 95vw; padding: 16px; }
|
|
1035
|
+
.task-create-form .form-row { grid-template-columns: 1fr; }
|
|
1036
|
+
}
|
|
1037
|
+
@media (max-width: 480px) {
|
|
1038
|
+
.preview-panel { display: none; }
|
|
1039
|
+
.chat-panel { width: 100%; border-right: none; }
|
|
1040
|
+
.chat-input-bar input { font-size: 16px; padding: 12px 14px; }
|
|
1041
|
+
.msg-tool-result .result-content { max-height: 80px; }
|
|
1042
|
+
.header-right { gap: 4px; }
|
|
1043
|
+
.btn { padding: 5px 8px; font-size: 12px; }
|
|
823
1044
|
}
|
|
824
1045
|
</style>
|
|
825
1046
|
</head>
|
|
@@ -830,6 +1051,7 @@ body {
|
|
|
830
1051
|
<div class="nav-tabs">
|
|
831
1052
|
<button class="nav-tab active" onclick="switchView('semantic')">Semantic</button>
|
|
832
1053
|
<button class="nav-tab" onclick="switchView('agent')">Agent</button>
|
|
1054
|
+
<button class="nav-tab" onclick="switchView('tasks')">Tasks</button>
|
|
833
1055
|
</div>
|
|
834
1056
|
<div class="header-right" id="headerRight">
|
|
835
1057
|
<button class="btn" id="btnCloseSession" style="display:none" onclick="Sem.closeSession()">Close Session</button>
|
|
@@ -912,6 +1134,14 @@ body {
|
|
|
912
1134
|
<div class="typing-dot"></div>
|
|
913
1135
|
<div class="typing-dot"></div>
|
|
914
1136
|
</div>
|
|
1137
|
+
<div class="progress-bar-wrap" id="progressBar">
|
|
1138
|
+
<div class="progress-bar-fill" id="progressFill"></div>
|
|
1139
|
+
</div>
|
|
1140
|
+
<div class="progress-info" id="progressInfo">
|
|
1141
|
+
<span class="progress-phase" id="progressPhase"></span>
|
|
1142
|
+
<span class="progress-percent" id="progressPercent"></span>
|
|
1143
|
+
<span id="progressSteps"></span>
|
|
1144
|
+
</div>
|
|
915
1145
|
<div class="chat-input-bar">
|
|
916
1146
|
<input type="text" id="taskInput" placeholder="Enter a task, e.g.: Open Baidu and search for weather">
|
|
917
1147
|
<button class="btn-send" id="sendBtn" onclick="Agent.start()">Send</button>
|
|
@@ -934,9 +1164,20 @@ body {
|
|
|
934
1164
|
</div>
|
|
935
1165
|
</div>
|
|
936
1166
|
</div>
|
|
937
|
-
</main>
|
|
938
1167
|
|
|
939
|
-
<!--
|
|
1168
|
+
<!-- Tasks View -->
|
|
1169
|
+
<div id="view-tasks" class="view">
|
|
1170
|
+
<div class="tasks-toolbar">
|
|
1171
|
+
<button class="btn btn-primary" id="btnNewTask" onclick="Tasks.showCreate()">+ New Task</button>
|
|
1172
|
+
<button class="btn" onclick="Tasks.refreshList()">Refresh</button>
|
|
1173
|
+
</div>
|
|
1174
|
+
<div id="tasksList" class="tasks-list">
|
|
1175
|
+
<div class="placeholder-text">Loading tasks...</div>
|
|
1176
|
+
</div>
|
|
1177
|
+
<div id="taskDetail" class="task-detail" style="display:none"></div>
|
|
1178
|
+
<div id="taskCreate" class="task-detail" style="display:none"></div>
|
|
1179
|
+
</div>
|
|
1180
|
+
</main>
|
|
940
1181
|
<div class="modal-overlay hidden" id="settingsModal">
|
|
941
1182
|
<div class="modal">
|
|
942
1183
|
<h2>Model Settings</h2>
|
|
@@ -955,8 +1196,10 @@ body {
|
|
|
955
1196
|
</label>
|
|
956
1197
|
<div class="modal-btns">
|
|
957
1198
|
<button class="btn" onclick="closeSettings()">Cancel</button>
|
|
1199
|
+
<button class="btn" id="btnTestConn" onclick="testConnection()">Test Connection</button>
|
|
958
1200
|
<button class="btn btn-save" onclick="saveSettings()">Save</button>
|
|
959
1201
|
</div>
|
|
1202
|
+
<div id="connTestResult" style="margin-top:8px;font-size:12px;display:none;"></div>
|
|
960
1203
|
</div>
|
|
961
1204
|
</div>
|
|
962
1205
|
|
|
@@ -1024,16 +1267,60 @@ function saveSettings() {
|
|
|
1024
1267
|
closeSettings();
|
|
1025
1268
|
}
|
|
1026
1269
|
|
|
1270
|
+
function testConnection() {
|
|
1271
|
+
var btn = document.getElementById('btnTestConn');
|
|
1272
|
+
var result = document.getElementById('connTestResult');
|
|
1273
|
+
btn.disabled = true;
|
|
1274
|
+
btn.textContent = 'Testing...';
|
|
1275
|
+
result.style.display = 'block';
|
|
1276
|
+
result.style.color = 'var(--text-muted)';
|
|
1277
|
+
result.textContent = 'Connecting...';
|
|
1278
|
+
|
|
1279
|
+
var body = {
|
|
1280
|
+
baseURL: document.getElementById('cfgBaseURL').value.trim(),
|
|
1281
|
+
model: document.getElementById('cfgModel').value.trim(),
|
|
1282
|
+
apiKey: document.getElementById('cfgApiKey').value.trim(),
|
|
1283
|
+
};
|
|
1284
|
+
|
|
1285
|
+
fetch('/v1/llm/test', {
|
|
1286
|
+
method: 'POST',
|
|
1287
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1288
|
+
body: JSON.stringify(body),
|
|
1289
|
+
}).then(function(r) { return r.json(); })
|
|
1290
|
+
.then(function(data) {
|
|
1291
|
+
if (data.ok) {
|
|
1292
|
+
result.style.color = '#3fb950';
|
|
1293
|
+
result.textContent = '\u2713 Connected — ' + (data.model || 'OK') + ' (' + (data.latencyMs || '?') + 'ms)';
|
|
1294
|
+
} else {
|
|
1295
|
+
result.style.color = '#f85149';
|
|
1296
|
+
result.textContent = '\u2717 Failed: ' + (data.error || 'Unknown error');
|
|
1297
|
+
}
|
|
1298
|
+
}).catch(function(err) {
|
|
1299
|
+
result.style.color = '#f85149';
|
|
1300
|
+
result.textContent = '\u2717 ' + err.message;
|
|
1301
|
+
}).finally(function() {
|
|
1302
|
+
btn.disabled = false;
|
|
1303
|
+
btn.textContent = 'Test Connection';
|
|
1304
|
+
});
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1027
1307
|
// ========== Navigation ==========
|
|
1028
1308
|
function switchView(view) {
|
|
1029
1309
|
App.currentView = view;
|
|
1030
1310
|
location.hash = view;
|
|
1311
|
+
// Clean up Tasks polling when leaving
|
|
1312
|
+
if (view !== 'tasks' && Tasks.pollTimer) {
|
|
1313
|
+
clearInterval(Tasks.pollTimer);
|
|
1314
|
+
Tasks.pollTimer = null;
|
|
1315
|
+
}
|
|
1031
1316
|
document.getElementById('view-semantic').classList.toggle('active', view === 'semantic');
|
|
1032
1317
|
document.getElementById('view-agent').classList.toggle('active', view === 'agent');
|
|
1318
|
+
document.getElementById('view-tasks').classList.toggle('active', view === 'tasks');
|
|
1033
1319
|
// Update nav tabs
|
|
1034
1320
|
document.querySelectorAll('.nav-tab').forEach(function(tab) {
|
|
1035
1321
|
tab.classList.toggle('active', tab.textContent.toLowerCase() === view);
|
|
1036
1322
|
});
|
|
1323
|
+
if (view === 'tasks') Tasks.refreshList();
|
|
1037
1324
|
updateHeaderButtons();
|
|
1038
1325
|
}
|
|
1039
1326
|
|
|
@@ -1053,7 +1340,7 @@ function updateHeaderButtons() {
|
|
|
1053
1340
|
// Hash routing
|
|
1054
1341
|
window.addEventListener('hashchange', function() {
|
|
1055
1342
|
var hash = location.hash.replace('#', '');
|
|
1056
|
-
var view = (hash === 'agent') ? 'agent' : 'semantic';
|
|
1343
|
+
var view = (hash === 'agent') ? 'agent' : (hash === 'tasks') ? 'tasks' : 'semantic';
|
|
1057
1344
|
if (view !== App.currentView) switchView(view);
|
|
1058
1345
|
});
|
|
1059
1346
|
|
|
@@ -1251,7 +1538,10 @@ var Sem = {
|
|
|
1251
1538
|
.then(function(data) {
|
|
1252
1539
|
if (data.image) {
|
|
1253
1540
|
if (data.image && data.image.indexOf('data:image/') === 0) {
|
|
1254
|
-
|
|
1541
|
+
var _simg = document.createElement('img');
|
|
1542
|
+
_simg.src = data.image;
|
|
1543
|
+
_simg.alt = 'screenshot';
|
|
1544
|
+
self.screenshotHtml = _simg.outerHTML;
|
|
1255
1545
|
}
|
|
1256
1546
|
if (self.rightTab === 'screenshot') self.renderRightContent();
|
|
1257
1547
|
}
|
|
@@ -1616,6 +1906,9 @@ var Agent = {
|
|
|
1616
1906
|
document.getElementById('btnStop').style.display = 'none';
|
|
1617
1907
|
this.agentId = null;
|
|
1618
1908
|
this.showTyping(false);
|
|
1909
|
+
document.getElementById('progressBar').classList.remove('active');
|
|
1910
|
+
document.getElementById('progressInfo').classList.remove('active');
|
|
1911
|
+
document.getElementById('progressFill').style.width = '0%';
|
|
1619
1912
|
updateHeaderButtons();
|
|
1620
1913
|
},
|
|
1621
1914
|
|
|
@@ -1632,6 +1925,7 @@ var Agent = {
|
|
|
1632
1925
|
document.getElementById('agentViewElements').style.display = 'none';
|
|
1633
1926
|
this.renderPreview();
|
|
1634
1927
|
this.resetUI();
|
|
1928
|
+
ChatStore.clear();
|
|
1635
1929
|
},
|
|
1636
1930
|
|
|
1637
1931
|
showTyping: function(show) {
|
|
@@ -1691,9 +1985,26 @@ Agent.handleEvent = function(ev) {
|
|
|
1691
1985
|
self.addMsg('system', 'Agent is waiting for your input...');
|
|
1692
1986
|
self.showInputDialog(ev.requestId, ev.question, ev.fields);
|
|
1693
1987
|
break;
|
|
1988
|
+
case 'progress':
|
|
1989
|
+
if (ev.progress) {
|
|
1990
|
+
var p = ev.progress;
|
|
1991
|
+
document.getElementById('progressFill').style.width = p.percent + '%';
|
|
1992
|
+
document.getElementById('progressPhase').textContent = p.phase || '';
|
|
1993
|
+
document.getElementById('progressPercent').textContent = p.percent + '%';
|
|
1994
|
+
document.getElementById('progressSteps').textContent =
|
|
1995
|
+
(p.stepsRemaining != null && p.stepsRemaining > 0) ? '~' + p.stepsRemaining + ' steps left' : '';
|
|
1996
|
+
document.getElementById('progressBar').classList.add('active');
|
|
1997
|
+
document.getElementById('progressInfo').classList.add('active');
|
|
1998
|
+
}
|
|
1999
|
+
break;
|
|
1694
2000
|
case 'done':
|
|
1695
2001
|
self.addMsg('done', ev.success ? (ev.result || 'Done') : (ev.error || 'Failed'), null, ev.success);
|
|
1696
|
-
|
|
2002
|
+
var summary = 'Total steps: ' + ev.iterations;
|
|
2003
|
+
if (ev.tokenUsage && ev.tokenUsage.total) {
|
|
2004
|
+
var tu = ev.tokenUsage;
|
|
2005
|
+
summary += ' | Tokens: ' + tu.total.toLocaleString() + ' (in: ' + tu.input.toLocaleString() + ' / out: ' + tu.output.toLocaleString() + ')';
|
|
2006
|
+
}
|
|
2007
|
+
self.addMsg('system', summary);
|
|
1697
2008
|
if (self.currentTask) {
|
|
1698
2009
|
self.conversationHistory.push({ role: 'user', content: self.currentTask });
|
|
1699
2010
|
self.conversationHistory.push({ role: 'assistant', content: ev.result || ev.error || 'Done' });
|
|
@@ -1719,6 +2030,7 @@ Agent.addMsg = function(type, content, iteration, extra, extra2) {
|
|
|
1719
2030
|
|
|
1720
2031
|
var el = document.createElement('div');
|
|
1721
2032
|
el.className = 'msg';
|
|
2033
|
+
var self = this;
|
|
1722
2034
|
|
|
1723
2035
|
switch (type) {
|
|
1724
2036
|
case 'user':
|
|
@@ -1735,9 +2047,10 @@ Agent.addMsg = function(type, content, iteration, extra, extra2) {
|
|
|
1735
2047
|
break;
|
|
1736
2048
|
case 'tool_call':
|
|
1737
2049
|
el.className = 'msg msg-tool-call';
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
'<
|
|
2050
|
+
var desc = self.humanizeToolCall(content, extra);
|
|
2051
|
+
el.innerHTML = self.stepTag(iteration) +
|
|
2052
|
+
'<div class="tool-header"><span class="tool-icon">\u25B6</span> <span class="tool-desc">' + esc(desc) + '</span></div>' +
|
|
2053
|
+
'<details class="tool-raw"><summary>Raw params</summary><pre>' + esc(JSON.stringify(extra, null, 2)) + '</pre></details>';
|
|
1741
2054
|
break;
|
|
1742
2055
|
case 'tool_result':
|
|
1743
2056
|
el.className = 'msg msg-tool-result ' + (extra ? 'success' : 'fail');
|
|
@@ -1772,6 +2085,7 @@ Agent.addMsg = function(type, content, iteration, extra, extra2) {
|
|
|
1772
2085
|
|
|
1773
2086
|
container.appendChild(el);
|
|
1774
2087
|
container.scrollTop = container.scrollHeight;
|
|
2088
|
+
ChatStore.save();
|
|
1775
2089
|
};
|
|
1776
2090
|
|
|
1777
2091
|
Agent.toggleExpand = function(id, btn) {
|
|
@@ -1784,6 +2098,39 @@ Agent.stepTag = function(n) {
|
|
|
1784
2098
|
if (n == null) return '';
|
|
1785
2099
|
return '<span class="step-tag">Step ' + n + '</span>';
|
|
1786
2100
|
};
|
|
2101
|
+
|
|
2102
|
+
Agent.humanizeToolCall = function(name, args) {
|
|
2103
|
+
args = args || {};
|
|
2104
|
+
var map = {
|
|
2105
|
+
navigate: function(a) { return 'Navigate: ' + (a.url || ''); },
|
|
2106
|
+
click: function(a) { return 'Click: ' + (a.elementId || a.element_id || ''); },
|
|
2107
|
+
type_text: function(a) { return 'Type: "' + (a.text || '').slice(0, 40) + '"'; },
|
|
2108
|
+
get_page_info: function() { return 'Get page elements'; },
|
|
2109
|
+
get_page_content: function() { return 'Extract page content'; },
|
|
2110
|
+
find_element: function(a) { return 'Search: "' + (a.query || '') + '"'; },
|
|
2111
|
+
screenshot: function() { return 'Take screenshot'; },
|
|
2112
|
+
scroll: function(a) { return 'Scroll ' + (a.direction || 'down'); },
|
|
2113
|
+
press_key: function(a) { return 'Press key: ' + (a.key || ''); },
|
|
2114
|
+
select_option: function(a) { return 'Select: ' + (a.value || a.text || ''); },
|
|
2115
|
+
fill_form: function(a) { return 'Fill form (' + (a.fields ? a.fields.length : 0) + ' fields)'; },
|
|
2116
|
+
click_and_wait: function(a) { return 'Click & wait: ' + (a.element_id || ''); },
|
|
2117
|
+
navigate_and_extract: function(a) { return 'Navigate & extract: ' + (a.url || ''); },
|
|
2118
|
+
hover: function(a) { return 'Hover: ' + (a.elementId || a.element_id || ''); },
|
|
2119
|
+
go_back: function() { return 'Go back'; },
|
|
2120
|
+
wait: function(a) { return 'Wait: ' + (a.condition || (a.ms + 'ms')); },
|
|
2121
|
+
wait_for_stable: function() { return 'Wait for page stable'; },
|
|
2122
|
+
done: function(a) { return 'Done: ' + (a.result || '').slice(0, 50); },
|
|
2123
|
+
set_value: function(a) { return 'Set value: ' + (a.elementId || a.element_id || ''); },
|
|
2124
|
+
upload_file: function() { return 'Upload file'; },
|
|
2125
|
+
execute_javascript: function() { return 'Execute JavaScript'; },
|
|
2126
|
+
create_tab: function() { return 'Create new tab'; },
|
|
2127
|
+
list_tabs: function() { return 'List tabs'; },
|
|
2128
|
+
switch_tab: function(a) { return 'Switch to tab ' + (a.tabId || ''); },
|
|
2129
|
+
close_tab: function() { return 'Close tab'; },
|
|
2130
|
+
};
|
|
2131
|
+
var fn = map[name];
|
|
2132
|
+
return fn ? fn(args) : name;
|
|
2133
|
+
};
|
|
1787
2134
|
</script>
|
|
1788
2135
|
|
|
1789
2136
|
<script>
|
|
@@ -1791,6 +2138,15 @@ Agent.stepTag = function(n) {
|
|
|
1791
2138
|
Agent.formatMdResult = function(toolName, summary) {
|
|
1792
2139
|
try {
|
|
1793
2140
|
var obj = JSON.parse(summary);
|
|
2141
|
+
// Priority 1: use aiMarkdown from backend MCP enrichment layer
|
|
2142
|
+
if (typeof obj.aiMarkdown === 'string' && obj.aiMarkdown.length > 0) {
|
|
2143
|
+
return '## ' + toolName + '\n\n' + obj.aiMarkdown;
|
|
2144
|
+
}
|
|
2145
|
+
// Priority 2: use aiSummary as fallback
|
|
2146
|
+
if (typeof obj.aiSummary === 'string' && obj.aiSummary.length > 0) {
|
|
2147
|
+
return '## ' + toolName + '\n\n' + obj.aiSummary;
|
|
2148
|
+
}
|
|
2149
|
+
// Priority 3: manual formatting for tools without aiMarkdown
|
|
1794
2150
|
if (toolName === 'get_page_info' && obj.elements) {
|
|
1795
2151
|
var md = '## Page: ' + (obj.page?.title || '') + '\n\n';
|
|
1796
2152
|
md += '**URL:** ' + (obj.page?.url || '') + '\n\n';
|
|
@@ -1801,33 +2157,10 @@ Agent.formatMdResult = function(toolName, summary) {
|
|
|
1801
2157
|
});
|
|
1802
2158
|
return md;
|
|
1803
2159
|
}
|
|
1804
|
-
if (toolName === '
|
|
1805
|
-
var md = '## ' + (obj.title || 'Page Content') + '\n\n';
|
|
1806
|
-
if (obj.sections && obj.sections.length > 0) {
|
|
1807
|
-
obj.sections.forEach(function(s) {
|
|
1808
|
-
var stars = s.attention >= 0.7 ? '\u2605\u2605\u2605' : s.attention >= 0.4 ? '\u2605\u2605' : '\u2605';
|
|
1809
|
-
md += '**[' + stars + ']** ' + s.text + '\n\n';
|
|
1810
|
-
});
|
|
1811
|
-
} else {
|
|
1812
|
-
md += '_No content sections extracted._\n';
|
|
1813
|
-
}
|
|
1814
|
-
return md;
|
|
1815
|
-
}
|
|
1816
|
-
if (toolName === 'navigate') {
|
|
2160
|
+
if (toolName === 'navigate' && obj.page) {
|
|
1817
2161
|
return '## Navigate\n\n**URL:** ' + (obj.page?.url || '') + '\n\n**Title:** ' + (obj.page?.title || '');
|
|
1818
2162
|
}
|
|
1819
|
-
|
|
1820
|
-
var md = '## Find Element: ' + (obj.query || '') + '\n\n';
|
|
1821
|
-
if (obj.candidates && obj.candidates.length > 0) {
|
|
1822
|
-
md += '| ID | Label | Score |\n|---|---|---|\n';
|
|
1823
|
-
obj.candidates.forEach(function(c) {
|
|
1824
|
-
md += '| `' + c.id + '` | ' + (c.label || '-') + ' | ' + c.score + ' |\n';
|
|
1825
|
-
});
|
|
1826
|
-
} else {
|
|
1827
|
-
md += 'No matches found.';
|
|
1828
|
-
}
|
|
1829
|
-
return md;
|
|
1830
|
-
}
|
|
2163
|
+
// Fallback: compact JSON
|
|
1831
2164
|
return '## ' + toolName + '\n\n```json\n' + JSON.stringify(obj, null, 2) + '\n```';
|
|
1832
2165
|
} catch (e) {
|
|
1833
2166
|
return '## ' + toolName + '\n\n```\n' + summary + '\n```';
|
|
@@ -1837,11 +2170,16 @@ Agent.formatMdResult = function(toolName, summary) {
|
|
|
1837
2170
|
Agent.refreshScreenshot = function() {
|
|
1838
2171
|
var self = this;
|
|
1839
2172
|
if (!self.sessionId) return;
|
|
2173
|
+
var body = document.getElementById('previewBody');
|
|
2174
|
+
if (self.previewMode === 'screenshot') body.classList.add('screenshot-loading');
|
|
1840
2175
|
fetch('/v1/sessions/' + self.sessionId + '/screenshot')
|
|
1841
2176
|
.then(function(r) { return r.json(); })
|
|
1842
2177
|
.then(function(data) {
|
|
1843
2178
|
if (data.image && data.image.indexOf('data:image/') === 0) {
|
|
1844
|
-
|
|
2179
|
+
var _img = document.createElement('img');
|
|
2180
|
+
_img.src = data.image;
|
|
2181
|
+
_img.alt = 'screenshot';
|
|
2182
|
+
self.latestScreenshotHtml = _img.outerHTML;
|
|
1845
2183
|
}
|
|
1846
2184
|
return fetch('/v1/sessions/' + self.sessionId);
|
|
1847
2185
|
}).then(function(r) { return r.json(); })
|
|
@@ -1850,8 +2188,13 @@ Agent.refreshScreenshot = function() {
|
|
|
1850
2188
|
var tab = info.tabs.find(function(t) { return t.id === info.activeTabId; }) || info.tabs[0];
|
|
1851
2189
|
document.getElementById('previewUrl').textContent = tab.url || '';
|
|
1852
2190
|
}
|
|
1853
|
-
|
|
1854
|
-
|
|
2191
|
+
body.classList.remove('screenshot-loading');
|
|
2192
|
+
if (self.previewMode === 'screenshot') {
|
|
2193
|
+
self.renderPreview();
|
|
2194
|
+
body.classList.add('screenshot-updated');
|
|
2195
|
+
setTimeout(function() { body.classList.remove('screenshot-updated'); }, 400);
|
|
2196
|
+
}
|
|
2197
|
+
}).catch(function() { body.classList.remove('screenshot-loading'); });
|
|
1855
2198
|
};
|
|
1856
2199
|
</script>
|
|
1857
2200
|
|
|
@@ -1950,6 +2293,217 @@ Agent.cancelInput = function(requestId) {
|
|
|
1950
2293
|
};
|
|
1951
2294
|
</script>
|
|
1952
2295
|
|
|
2296
|
+
<script>
|
|
2297
|
+
// ===== ChatStore: localStorage persistence =====
|
|
2298
|
+
var CHAT_STORE_KEY = 'ai_browser_chat_history';
|
|
2299
|
+
var ChatStore = {
|
|
2300
|
+
_saveTimer: null,
|
|
2301
|
+
save: function() {
|
|
2302
|
+
if (ChatStore._saveTimer) clearTimeout(ChatStore._saveTimer);
|
|
2303
|
+
ChatStore._saveTimer = setTimeout(ChatStore._doSave, 500);
|
|
2304
|
+
},
|
|
2305
|
+
_doSave: function() {
|
|
2306
|
+
ChatStore._saveTimer = null;
|
|
2307
|
+
try {
|
|
2308
|
+
var msgs = [];
|
|
2309
|
+
var container = document.getElementById('chatMessages');
|
|
2310
|
+
container.querySelectorAll('.msg').forEach(function(el) {
|
|
2311
|
+
var type = '';
|
|
2312
|
+
if (el.classList.contains('msg-user')) type = 'user';
|
|
2313
|
+
else if (el.classList.contains('msg-system')) type = 'system';
|
|
2314
|
+
else if (el.classList.contains('msg-thinking')) type = 'thinking';
|
|
2315
|
+
else if (el.classList.contains('msg-tool-call')) type = 'tool_call';
|
|
2316
|
+
else if (el.classList.contains('msg-tool-result')) type = 'tool_result';
|
|
2317
|
+
else if (el.classList.contains('msg-error')) type = 'error';
|
|
2318
|
+
else if (el.classList.contains('msg-done')) type = 'done';
|
|
2319
|
+
if (type) msgs.push({ type: type, html: el.outerHTML });
|
|
2320
|
+
});
|
|
2321
|
+
if (msgs.length === 0) return;
|
|
2322
|
+
if (msgs.length > 50) msgs = msgs.slice(-50);
|
|
2323
|
+
var data = {
|
|
2324
|
+
messages: msgs,
|
|
2325
|
+
conversationHistory: Agent.conversationHistory,
|
|
2326
|
+
savedAt: Date.now()
|
|
2327
|
+
};
|
|
2328
|
+
localStorage.setItem(CHAT_STORE_KEY, JSON.stringify(data));
|
|
2329
|
+
} catch(e) { /* quota exceeded or other error */ }
|
|
2330
|
+
},
|
|
2331
|
+
load: function() {
|
|
2332
|
+
try {
|
|
2333
|
+
var raw = localStorage.getItem(CHAT_STORE_KEY);
|
|
2334
|
+
if (!raw) return;
|
|
2335
|
+
var data = JSON.parse(raw);
|
|
2336
|
+
if (!data.messages || data.messages.length === 0) return;
|
|
2337
|
+
var container = document.getElementById('chatMessages');
|
|
2338
|
+
var ph = container.querySelector('.placeholder-text');
|
|
2339
|
+
if (ph) ph.remove();
|
|
2340
|
+
data.messages.forEach(function(m) {
|
|
2341
|
+
var wrapper = document.createElement('div');
|
|
2342
|
+
wrapper.innerHTML = DOMPurify.sanitize(m.html);
|
|
2343
|
+
if (wrapper.firstChild) container.appendChild(wrapper.firstChild);
|
|
2344
|
+
});
|
|
2345
|
+
if (data.conversationHistory) {
|
|
2346
|
+
Agent.conversationHistory = data.conversationHistory;
|
|
2347
|
+
}
|
|
2348
|
+
} catch(e) { /* parse error */ }
|
|
2349
|
+
},
|
|
2350
|
+
clear: function() {
|
|
2351
|
+
localStorage.removeItem(CHAT_STORE_KEY);
|
|
2352
|
+
}
|
|
2353
|
+
};
|
|
2354
|
+
</script>
|
|
2355
|
+
|
|
2356
|
+
<script>
|
|
2357
|
+
// ===== Tasks: SPA integration =====
|
|
2358
|
+
var Tasks = {
|
|
2359
|
+
pollTimer: null,
|
|
2360
|
+
currentTaskId: null,
|
|
2361
|
+
|
|
2362
|
+
refreshList: function() {
|
|
2363
|
+
var list = document.getElementById('tasksList');
|
|
2364
|
+
list.innerHTML = '<div class="placeholder-text">Loading...</div>';
|
|
2365
|
+
document.getElementById('taskDetail').style.display = 'none';
|
|
2366
|
+
document.getElementById('taskCreate').style.display = 'none';
|
|
2367
|
+
fetch('/v1/tasks').then(function(r) { return r.json(); }).then(function(data) {
|
|
2368
|
+
var tasks = data.tasks || [];
|
|
2369
|
+
if (tasks.length === 0) {
|
|
2370
|
+
list.innerHTML = '<div class="placeholder-text">No tasks yet. Click "+ New Task" to create one.</div>';
|
|
2371
|
+
return;
|
|
2372
|
+
}
|
|
2373
|
+
list.innerHTML = '';
|
|
2374
|
+
tasks.forEach(function(t) {
|
|
2375
|
+
var card = document.createElement('div');
|
|
2376
|
+
card.className = 'task-card';
|
|
2377
|
+
card.onclick = function() { Tasks.showResult(t.taskId); };
|
|
2378
|
+
var safeStatus = ['running','done','pending','failed'].indexOf(t.status) >= 0 ? t.status : 'pending';
|
|
2379
|
+
var statusCls = 'task-status ' + safeStatus;
|
|
2380
|
+
card.innerHTML = '<div class="' + statusCls + '">' + esc(t.status || 'unknown') + '</div>' +
|
|
2381
|
+
'<div style="font-weight:500;margin:6px 0">' + esc((t.goal || '').slice(0, 80)) + '</div>' +
|
|
2382
|
+
'<div style="font-size:12px;color:var(--text-muted)">' + new Date(t.createdAt).toLocaleString() + '</div>';
|
|
2383
|
+
list.appendChild(card);
|
|
2384
|
+
});
|
|
2385
|
+
}).catch(function() {
|
|
2386
|
+
list.innerHTML = '<div class="placeholder-text">Failed to load tasks.</div>';
|
|
2387
|
+
});
|
|
2388
|
+
},
|
|
2389
|
+
|
|
2390
|
+
showCreate: function() {
|
|
2391
|
+
document.getElementById('tasksList').style.display = 'none';
|
|
2392
|
+
document.getElementById('taskDetail').style.display = 'none';
|
|
2393
|
+
var panel = document.getElementById('taskCreate');
|
|
2394
|
+
panel.style.display = 'block';
|
|
2395
|
+
panel.innerHTML =
|
|
2396
|
+
'<h3 style="margin:0 0 16px">New Task</h3>' +
|
|
2397
|
+
'<div class="task-create-form">' +
|
|
2398
|
+
'<label>Goal</label>' +
|
|
2399
|
+
'<textarea id="tcGoal" rows="3" placeholder="Describe what you want the agent to do..."></textarea>' +
|
|
2400
|
+
'<label>Start URL (optional)</label>' +
|
|
2401
|
+
'<input type="text" id="tcUrl" placeholder="https://...">' +
|
|
2402
|
+
'<label>Max Steps</label>' +
|
|
2403
|
+
'<input type="number" id="tcMaxSteps" value="20" min="1" max="200">' +
|
|
2404
|
+
'<div style="display:flex;gap:8px;margin-top:12px">' +
|
|
2405
|
+
'<button class="btn btn-primary" onclick="Tasks.submitTask()">Run Task</button>' +
|
|
2406
|
+
'<button class="btn" onclick="Tasks.backToList()">Cancel</button>' +
|
|
2407
|
+
'</div>' +
|
|
2408
|
+
'</div>';
|
|
2409
|
+
},
|
|
2410
|
+
|
|
2411
|
+
backToList: function() {
|
|
2412
|
+
document.getElementById('taskCreate').style.display = 'none';
|
|
2413
|
+
document.getElementById('taskDetail').style.display = 'none';
|
|
2414
|
+
document.getElementById('tasksList').style.display = '';
|
|
2415
|
+
Tasks.refreshList();
|
|
2416
|
+
},
|
|
2417
|
+
|
|
2418
|
+
submitTask: function() {
|
|
2419
|
+
var goal = document.getElementById('tcGoal').value.trim();
|
|
2420
|
+
if (!goal) return;
|
|
2421
|
+
var url = document.getElementById('tcUrl').value.trim();
|
|
2422
|
+
var maxSteps = parseInt(document.getElementById('tcMaxSteps').value) || 20;
|
|
2423
|
+
if (url) goal = goal + '\nStart URL: ' + url;
|
|
2424
|
+
|
|
2425
|
+
var cfg = JSON.parse(localStorage.getItem(SETTINGS_KEY) || '{}');
|
|
2426
|
+
var body = {
|
|
2427
|
+
goal: goal,
|
|
2428
|
+
maxIterations: maxSteps,
|
|
2429
|
+
apiKey: cfg.apiKey || undefined,
|
|
2430
|
+
baseURL: cfg.baseURL || undefined,
|
|
2431
|
+
model: cfg.model || undefined,
|
|
2432
|
+
headless: cfg.headless !== undefined ? cfg.headless : true,
|
|
2433
|
+
};
|
|
2434
|
+
|
|
2435
|
+
fetch('/v1/tasks', {
|
|
2436
|
+
method: 'POST',
|
|
2437
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2438
|
+
body: JSON.stringify(body),
|
|
2439
|
+
}).then(function(r) { return r.json(); }).then(function(data) {
|
|
2440
|
+
if (data.taskId) {
|
|
2441
|
+
Tasks.showResult(data.taskId);
|
|
2442
|
+
} else {
|
|
2443
|
+
alert('Failed to create task: ' + JSON.stringify(data));
|
|
2444
|
+
}
|
|
2445
|
+
}).catch(function(err) {
|
|
2446
|
+
alert('Error: ' + err.message);
|
|
2447
|
+
});
|
|
2448
|
+
},
|
|
2449
|
+
|
|
2450
|
+
showResult: function(taskId) {
|
|
2451
|
+
Tasks.currentTaskId = taskId;
|
|
2452
|
+
document.getElementById('tasksList').style.display = 'none';
|
|
2453
|
+
document.getElementById('taskCreate').style.display = 'none';
|
|
2454
|
+
var panel = document.getElementById('taskDetail');
|
|
2455
|
+
panel.style.display = 'block';
|
|
2456
|
+
panel.innerHTML = '<div class="placeholder-text">Loading task...</div>';
|
|
2457
|
+
|
|
2458
|
+
fetch('/v1/tasks/' + taskId).then(function(r) { return r.json(); }).then(function(data) {
|
|
2459
|
+
var safeStatus = ['running','done','pending','failed'].indexOf(data.status) >= 0 ? data.status : 'pending';
|
|
2460
|
+
var statusCls = 'task-status ' + safeStatus;
|
|
2461
|
+
var html = '<div style="display:flex;align-items:center;gap:12px;margin-bottom:16px">' +
|
|
2462
|
+
'<button class="btn" onclick="Tasks.backToList()">← Back</button>' +
|
|
2463
|
+
'<span class="' + statusCls + '">' + esc(data.status || '') + '</span>' +
|
|
2464
|
+
'<span style="font-size:12px;color:var(--text-muted)">' + esc(taskId.slice(0, 8)) + '</span>' +
|
|
2465
|
+
'</div>';
|
|
2466
|
+
html += '<div style="margin-bottom:12px"><strong>Goal:</strong> ' + esc(data.goal || '(unknown)') + '</div>';
|
|
2467
|
+
if (data.result) {
|
|
2468
|
+
html += '<div style="margin-bottom:12px"><strong>Result:</strong></div>' +
|
|
2469
|
+
'<pre style="background:var(--bg-secondary);padding:12px;border-radius:6px;overflow:auto;max-height:300px">' +
|
|
2470
|
+
esc(typeof data.result === 'string' ? data.result : JSON.stringify(data.result, null, 2)) + '</pre>';
|
|
2471
|
+
}
|
|
2472
|
+
if (data.error) {
|
|
2473
|
+
html += '<div style="color:var(--danger)"><strong>Error:</strong> ' + esc(data.error) + '</div>';
|
|
2474
|
+
}
|
|
2475
|
+
html += '<div id="taskEvents" style="margin-top:16px"></div>';
|
|
2476
|
+
panel.innerHTML = html;
|
|
2477
|
+
|
|
2478
|
+
if (data.status === 'running') {
|
|
2479
|
+
Tasks.pollStatus(taskId);
|
|
2480
|
+
}
|
|
2481
|
+
}).catch(function() {
|
|
2482
|
+
panel.innerHTML = '<div class="placeholder-text">Failed to load task.</div>' +
|
|
2483
|
+
'<button class="btn" onclick="Tasks.backToList()" style="margin-top:12px">← Back</button>';
|
|
2484
|
+
});
|
|
2485
|
+
},
|
|
2486
|
+
|
|
2487
|
+
pollStatus: function(taskId) {
|
|
2488
|
+
if (Tasks.pollTimer) clearInterval(Tasks.pollTimer);
|
|
2489
|
+
Tasks.pollTimer = setInterval(function() {
|
|
2490
|
+
if (Tasks.currentTaskId !== taskId) {
|
|
2491
|
+
clearInterval(Tasks.pollTimer);
|
|
2492
|
+
Tasks.pollTimer = null;
|
|
2493
|
+
return;
|
|
2494
|
+
}
|
|
2495
|
+
fetch('/v1/tasks/' + taskId).then(function(r) { return r.json(); }).then(function(data) {
|
|
2496
|
+
if (data.status !== 'running') {
|
|
2497
|
+
clearInterval(Tasks.pollTimer);
|
|
2498
|
+
Tasks.pollTimer = null;
|
|
2499
|
+
Tasks.showResult(taskId);
|
|
2500
|
+
}
|
|
2501
|
+
}).catch(function() {});
|
|
2502
|
+
}, 3000);
|
|
2503
|
+
}
|
|
2504
|
+
};
|
|
2505
|
+
</script>
|
|
2506
|
+
|
|
1953
2507
|
<script>
|
|
1954
2508
|
// ===== Keyboard shortcuts =====
|
|
1955
2509
|
document.getElementById('taskInput').addEventListener('keypress', function(e) {
|
|
@@ -1987,11 +2541,9 @@ document.getElementById('typeValue').addEventListener('keypress', function(e) {
|
|
|
1987
2541
|
// ========== Init ==========
|
|
1988
2542
|
(function() {
|
|
1989
2543
|
var hash = location.hash.replace('#', '');
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
switchView('semantic');
|
|
1994
|
-
}
|
|
2544
|
+
var view = (hash === 'agent') ? 'agent' : (hash === 'tasks') ? 'tasks' : 'semantic';
|
|
2545
|
+
switchView(view);
|
|
2546
|
+
ChatStore.load();
|
|
1995
2547
|
})();
|
|
1996
2548
|
</script>
|
|
1997
2549
|
</body>
|