@bolloon/bolloon-agent 0.6.4 → 0.6.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/chain/chain-settlement.js +0 -1
- package/dist/agents/chat-segmenter.js +4 -16
- package/dist/agents/contacts/human-directory.js +155 -0
- package/dist/agents/contacts/tools.js +79 -0
- package/dist/agents/experience-review.js +0 -3
- package/dist/agents/goal-flywheel/goal-change.js +3 -4
- package/dist/agents/goal-resume.js +0 -4
- package/dist/agents/intent-classifier.js +1 -1
- package/dist/agents/iteration-budget.js +12 -0
- package/dist/agents/knowledge-organizer.js +0 -2
- package/dist/agents/lesson-to-skill.js +0 -1
- package/dist/agents/loop-review.js +2 -2
- package/dist/agents/memory-store.js +359 -0
- package/dist/agents/opportunity-inbox.js +147 -0
- package/dist/agents/opportunity-match.js +48 -7
- package/dist/agents/opportunity-web-search.js +222 -0
- package/dist/agents/p2p-chat-tools.js +1 -2
- package/dist/agents/parse-tool-call.js +9 -22
- package/dist/agents/pi-harness.js +1 -2
- package/dist/agents/pi-sdk-tools.js +180 -5
- package/dist/agents/pi-sdk.js +143 -9
- package/dist/agents/process-runner.js +28 -9
- package/dist/agents/react-loop.js +9 -17
- package/dist/agents/runner-resolver.js +4 -3
- package/dist/agents/skill-loader.js +22 -15
- package/dist/agents/skills-manager.js +1 -25
- package/dist/agents/workflow-pivot-loop.js +152 -61
- package/dist/agents/world-watcher.js +30 -1
- package/dist/bootstrap/context-collector.js +2 -4
- package/dist/bootstrap/context-hierarchy.js +13 -1
- package/dist/cli/ink-app.js +44 -17
- package/dist/cli/intent-command.js +22 -12
- package/dist/cli/loading-tui.js +8 -2
- package/dist/cli/log-gate.js +40 -8
- package/dist/cli/mention-data.js +1 -0
- package/dist/cli/reply-hygiene.js +22 -0
- package/dist/cli/trace-line.js +61 -2
- package/dist/electron-build/agents/agent-gateway.js.map +1 -1
- package/dist/electron-build/agents/chain/chain-indexer.js.map +1 -1
- package/dist/electron-build/agents/chain/chain-settlement.js +0 -1
- package/dist/electron-build/agents/chain/chain-settlement.js.map +1 -1
- package/dist/electron-build/agents/contacts/chain.js.map +1 -1
- package/dist/electron-build/agents/contacts/human-directory.js +204 -0
- package/dist/electron-build/agents/contacts/human-directory.js.map +1 -0
- package/dist/electron-build/agents/contacts/policy.js.map +1 -1
- package/dist/electron-build/agents/contacts/tools.js +112 -0
- package/dist/electron-build/agents/contacts/tools.js.map +1 -1
- package/dist/electron-build/agents/experience-review.js +0 -3
- package/dist/electron-build/agents/experience-review.js.map +1 -1
- package/dist/electron-build/agents/external-events.js.map +1 -1
- package/dist/electron-build/agents/goal-flywheel/goal-change.js +3 -4
- package/dist/electron-build/agents/goal-flywheel/goal-change.js.map +1 -1
- package/dist/electron-build/agents/goal-flywheel-wiring.js.map +1 -1
- package/dist/electron-build/agents/goal-resume.js +0 -4
- package/dist/electron-build/agents/goal-resume.js.map +1 -1
- package/dist/electron-build/agents/intent-classifier.js +1 -1
- package/dist/electron-build/agents/lesson-to-skill.js +0 -1
- package/dist/electron-build/agents/lesson-to-skill.js.map +1 -1
- package/dist/electron-build/agents/loop-review.js +2 -2
- package/dist/electron-build/agents/loop-review.js.map +1 -1
- package/dist/electron-build/agents/memory-recall.js.map +1 -1
- package/dist/electron-build/agents/memory-store.js +404 -0
- package/dist/electron-build/agents/memory-store.js.map +1 -0
- package/dist/electron-build/agents/parse-tool-call.js +9 -22
- package/dist/electron-build/agents/parse-tool-call.js.map +1 -1
- package/dist/electron-build/agents/pi-harness.js +1 -2
- package/dist/electron-build/agents/pi-harness.js.map +1 -1
- package/dist/electron-build/agents/pi-sdk-tools.js +180 -5
- package/dist/electron-build/agents/pi-sdk-tools.js.map +1 -1
- package/dist/electron-build/agents/pi-sdk.js +143 -9
- package/dist/electron-build/agents/pi-sdk.js.map +1 -1
- package/dist/electron-build/agents/pre-tool-validator.js.map +1 -1
- package/dist/electron-build/agents/process-runner.js +28 -9
- package/dist/electron-build/agents/process-runner.js.map +1 -1
- package/dist/electron-build/agents/runner-resolver.js +4 -3
- package/dist/electron-build/agents/runner-resolver.js.map +1 -1
- package/dist/electron-build/agents/skill-loader.js +22 -16
- package/dist/electron-build/agents/skill-loader.js.map +1 -1
- package/dist/electron-build/agents/skill-supervisor-link.js.map +1 -1
- package/dist/electron-build/agents/skills-manager.js +0 -24
- package/dist/electron-build/agents/skills-manager.js.map +1 -1
- package/dist/electron-build/agents/task/task-runner.js.map +1 -1
- package/dist/electron-build/agents/workflow-engine.js.map +1 -1
- package/dist/electron-build/agents/workflow-pivot-loop.js +155 -62
- package/dist/electron-build/agents/workflow-pivot-loop.js.map +1 -1
- package/dist/electron-build/agents/x402/goal-run-bridge.js.map +1 -1
- package/dist/electron-build/bollharness-integration/gate-state-machine.js.map +1 -1
- package/dist/electron-build/bootstrap/context-collector.js +2 -4
- package/dist/electron-build/bootstrap/context-collector.js.map +1 -1
- package/dist/electron-build/bootstrap/context-hierarchy.js +13 -1
- package/dist/electron-build/bootstrap/context-hierarchy.js.map +1 -1
- package/dist/electron-build/electron-preload.js.map +1 -1
- package/dist/electron-build/external-engines/delegate.js.map +1 -1
- package/dist/electron-build/kernel/channel-actor.js +31 -2
- package/dist/electron-build/kernel/channel-actor.js.map +1 -1
- package/dist/electron-build/kernel/model-runtime.js +8 -1
- package/dist/electron-build/kernel/model-runtime.js.map +1 -1
- package/dist/electron-build/llm/config-store.js +20 -0
- package/dist/electron-build/llm/config-store.js.map +1 -1
- package/dist/electron-build/llm/embedding-adapter.js +75 -0
- package/dist/electron-build/llm/embedding-adapter.js.map +1 -0
- package/dist/electron-build/llm/pi-ai.js +96 -35
- package/dist/electron-build/llm/pi-ai.js.map +1 -1
- package/dist/electron-build/network/agent-network.js.map +1 -1
- package/dist/electron-build/orbitdb/memory-sync.js +76 -0
- package/dist/electron-build/orbitdb/memory-sync.js.map +1 -0
- package/dist/electron-build/pi-ecosystem-judgment/adaptive-scan.js.map +1 -1
- package/dist/electron-build/security/tool-gate.js +2 -0
- package/dist/electron-build/security/tool-gate.js.map +1 -1
- package/dist/electron-build/setup/setup-store.js +34 -6
- package/dist/electron-build/setup/setup-store.js.map +1 -1
- package/dist/electron-build/social/heartbeat.js +18 -5
- package/dist/electron-build/social/heartbeat.js.map +1 -1
- package/dist/electron-build/utils/update-manager.js.map +1 -1
- package/dist/index.js +250 -12
- package/dist/ios/bolloon-web.json +3 -3
- package/dist/ios/client.js +150 -113
- package/dist/ios/icons/icon-1400x1400.png +0 -0
- package/dist/ios/icons/icon-1400x1400.webp +0 -0
- package/dist/ios/index.html +106 -107
- package/dist/ios/mobile-agent.js +346 -45
- package/dist/ios/mobile-core.js +7303 -4590
- package/dist/ios/mobile-harness.js +1004 -0
- package/dist/ios/mobile-orbitdb.js +194 -0
- package/dist/ios/mobile-persona.js +80 -0
- package/dist/ios/mobile-privacy.js +2 -3
- package/dist/ios/mobile.css +286 -21
- package/dist/ios/mobile.html +106 -107
- package/dist/ios/mobile.js +300 -132
- package/dist/ios/routes-world.js +58 -1
- package/dist/ios/server.js +3 -1
- package/dist/ios/style.css +49 -2
- package/dist/ios/sw.js +1 -1
- package/dist/ios/ui/message-renderer.js +4 -18
- package/dist/ios/ui/step-timeline.js +14 -1
- package/dist/kernel/channel-actor.js +30 -2
- package/dist/kernel/gate-scan.js +1 -1
- package/dist/kernel/index.js +33 -0
- package/dist/kernel/model-runtime.js +8 -1
- package/dist/kernel/plan.js +3 -3
- package/dist/kernel/roster.js +3 -3
- package/dist/llm/config-store.js +20 -0
- package/dist/llm/embedding-adapter.js +69 -0
- package/dist/llm/pi-ai.js +94 -34
- package/dist/orbitdb/memory-sync.js +70 -0
- package/dist/pi-ecosystem-judgment/adaptive-scan.js +1 -1
- package/dist/security/tool-gate.js +2 -0
- package/dist/setup/setup-store.js +34 -6
- package/dist/social/heartbeat.js +18 -5
- package/dist/web/bolloon-web.json +3 -3
- package/dist/web/client.js +150 -113
- package/dist/web/icons/icon-1400x1400.png +0 -0
- package/dist/web/icons/icon-1400x1400.webp +0 -0
- package/dist/web/index.html +52 -59
- package/dist/web/mobile-agent.js +351 -45
- package/dist/web/mobile-contacts.js +0 -4
- package/dist/web/mobile-core.js +7430 -4590
- package/dist/web/mobile-harness.js +1004 -0
- package/dist/web/mobile-orbitdb.js +194 -0
- package/dist/web/mobile-persona.js +80 -0
- package/dist/web/mobile-privacy.js +2 -3
- package/dist/web/mobile.css +286 -21
- package/dist/web/mobile.html +121 -107
- package/dist/web/mobile.js +409 -136
- package/dist/web/routes-contacts.js +94 -1
- package/dist/web/routes-world.js +58 -1
- package/dist/web/server.js +4 -2
- package/dist/web/style.css +49 -2
- package/dist/web/sw.js +1 -1
- package/dist/web/ui/message-renderer.js +4 -18
- package/dist/web/ui/step-timeline.js +14 -1
- package/package.json +3 -2
- package/scripts/build-web.ts +16 -1
package/dist/web/client.js
CHANGED
|
@@ -33,6 +33,15 @@
|
|
|
33
33
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
34
34
|
|
|
35
35
|
// src/web/ui/step-timeline.ts
|
|
36
|
+
function formatDuration(ms) {
|
|
37
|
+
if (!Number.isFinite(ms) || ms < 0) return "(\u8017\u65F6\u672A\u77E5)";
|
|
38
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
39
|
+
const s = ms / 1e3;
|
|
40
|
+
if (s < 60) return `${s.toFixed(1)}s`;
|
|
41
|
+
const m = Math.floor(s / 60);
|
|
42
|
+
const rem = Math.round(s % 60);
|
|
43
|
+
return `${m}m${rem}s`;
|
|
44
|
+
}
|
|
36
45
|
function readExpanded(channelId) {
|
|
37
46
|
if (!channelId) return false;
|
|
38
47
|
try {
|
|
@@ -152,7 +161,10 @@
|
|
|
152
161
|
}
|
|
153
162
|
node.setAttribute("data-status", step.status);
|
|
154
163
|
const label = node.querySelector(".step-timeline-label");
|
|
155
|
-
if (label)
|
|
164
|
+
if (label) {
|
|
165
|
+
const dur = step.durationMs !== void 0 && step.status !== "active" ? ` \xB7 ${formatDuration(step.durationMs)}` : "";
|
|
166
|
+
label.textContent = step.name + dur;
|
|
167
|
+
}
|
|
156
168
|
const argsEl = node.querySelector(".step-timeline-args");
|
|
157
169
|
if (argsEl) {
|
|
158
170
|
const argStr = step.args && Object.keys(step.args).length > 0 ? JSON.stringify(step.args).slice(0, 60) : "";
|
|
@@ -296,6 +308,7 @@
|
|
|
296
308
|
steps[targetIdx].status = data.success === false ? "error" : "done";
|
|
297
309
|
if (data.output) steps[targetIdx].output = data.output;
|
|
298
310
|
if (data.error) steps[targetIdx].error = data.error;
|
|
311
|
+
if (data.durationMs !== void 0) steps[targetIdx].durationMs = data.durationMs;
|
|
299
312
|
} else {
|
|
300
313
|
steps[targetIdx].status = "error";
|
|
301
314
|
if (data.error) steps[targetIdx].error = data.error;
|
|
@@ -595,21 +608,10 @@
|
|
|
595
608
|
if (remaining.trim()) {
|
|
596
609
|
remaining = filterFillerText(remaining);
|
|
597
610
|
}
|
|
598
|
-
const
|
|
599
|
-
let beforeFinalText = remaining;
|
|
600
|
-
if (finalIdx >= 0) {
|
|
601
|
-
beforeFinalText = remaining.substring(0, finalIdx);
|
|
602
|
-
}
|
|
603
|
-
const textContent = beforeFinalText.trim();
|
|
611
|
+
const textContent = remaining.trim();
|
|
604
612
|
if (textContent) {
|
|
605
613
|
segments.push({ type: "text", content: textContent });
|
|
606
614
|
}
|
|
607
|
-
if (finalIdx >= 0) {
|
|
608
|
-
const afterFinal = remaining.substring(finalIdx + "<final gen>".length).trim();
|
|
609
|
-
if (afterFinal) {
|
|
610
|
-
segments.push({ type: "final", content: afterFinal });
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
615
|
return segments;
|
|
614
616
|
}
|
|
615
617
|
function extractAndPush(type, text, out, re) {
|
|
@@ -879,11 +881,7 @@
|
|
|
879
881
|
div.className = `message message-${type}`;
|
|
880
882
|
let cleanContent = content;
|
|
881
883
|
if (type === "ai") {
|
|
882
|
-
cleanContent = cleanContent.replace(
|
|
883
|
-
const finalGenIdx = cleanContent.indexOf("<final gen>");
|
|
884
|
-
if (finalGenIdx >= 0) {
|
|
885
|
-
cleanContent = cleanContent.substring(0, finalGenIdx).trim();
|
|
886
|
-
}
|
|
884
|
+
cleanContent = cleanContent.replace(/ thinking[\s\S]*?<\/think>/g, "");
|
|
887
885
|
}
|
|
888
886
|
const knownToolNames2 = ctx && ctx.knownToolNames || /* @__PURE__ */ new Set();
|
|
889
887
|
const segments = segmentChatReply(cleanContent, { knownToolNames: knownToolNames2 });
|
|
@@ -1207,7 +1205,8 @@
|
|
|
1207
1205
|
args: data.args,
|
|
1208
1206
|
success: data.success,
|
|
1209
1207
|
output: data.output,
|
|
1210
|
-
error: data.error
|
|
1208
|
+
error: data.error,
|
|
1209
|
+
durationMs: data.durationMs
|
|
1211
1210
|
});
|
|
1212
1211
|
}
|
|
1213
1212
|
function flushStepEventBuffer(channelId, ctx) {
|
|
@@ -1547,6 +1546,8 @@
|
|
|
1547
1546
|
var renderLoopStatusBar2 = (...args) => _getLS().renderLoopStatusBar?.(...args);
|
|
1548
1547
|
var hideLoopStatusBar2 = (...args) => _getLS().hideLoopStatusBar?.(...args);
|
|
1549
1548
|
var sidebarToggle = document.getElementById("sidebar-toggle");
|
|
1549
|
+
var sidebarCollapsedBar = document.getElementById("sidebar-collapsed-bar");
|
|
1550
|
+
var sidebarExpandBtn = document.getElementById("sidebar-expand-btn");
|
|
1550
1551
|
var themeToggle = document.getElementById("theme-toggle");
|
|
1551
1552
|
var channelList = document.getElementById("channel-list");
|
|
1552
1553
|
var newChannelBtn = document.getElementById("new-channel-btn");
|
|
@@ -1720,13 +1721,16 @@
|
|
|
1720
1721
|
isSidebarCollapsed = !isSidebarCollapsed;
|
|
1721
1722
|
if (isSidebarCollapsed) {
|
|
1722
1723
|
sidebar.classList.add("collapsed");
|
|
1724
|
+
if (sidebarCollapsedBar) sidebarCollapsedBar.classList.remove("hidden");
|
|
1723
1725
|
} else {
|
|
1724
1726
|
sidebar.classList.remove("collapsed");
|
|
1727
|
+
if (sidebarCollapsedBar) sidebarCollapsedBar.classList.add("hidden");
|
|
1725
1728
|
}
|
|
1726
1729
|
}
|
|
1727
1730
|
function expandSidebar() {
|
|
1728
1731
|
isSidebarCollapsed = false;
|
|
1729
1732
|
sidebar.classList.remove("collapsed");
|
|
1733
|
+
if (sidebarCollapsedBar) sidebarCollapsedBar.classList.add("hidden");
|
|
1730
1734
|
}
|
|
1731
1735
|
async function loadChannels() {
|
|
1732
1736
|
try {
|
|
@@ -1736,7 +1740,6 @@
|
|
|
1736
1740
|
const text = await res.text().catch(() => "");
|
|
1737
1741
|
if (!text.trim().startsWith("[") && !text.trim().startsWith("{")) {
|
|
1738
1742
|
console.warn("[\u52A0\u8F7D\u9891\u9053] \u68C0\u6D4B\u5230 IPFS \u9759\u6001\u6A21\u5F0F (\u65E0\u540E\u7AEF server), \u529F\u80FD\u53D7\u9650");
|
|
1739
|
-
showStaticModeNotice();
|
|
1740
1743
|
return;
|
|
1741
1744
|
}
|
|
1742
1745
|
}
|
|
@@ -1762,17 +1765,6 @@
|
|
|
1762
1765
|
console.error("[\u52A0\u8F7D\u9891\u9053] \u5931\u8D25:", err);
|
|
1763
1766
|
}
|
|
1764
1767
|
}
|
|
1765
|
-
function showStaticModeNotice() {
|
|
1766
|
-
if (document.getElementById("ipfs-static-notice")) return;
|
|
1767
|
-
const notice = document.createElement("div");
|
|
1768
|
-
notice.id = "ipfs-static-notice";
|
|
1769
|
-
notice.style.cssText = "position:fixed;bottom:60px;left:50%;transform:translateX(-50%);z-index:9999;background:#1a1a18;border:1px solid #c4d640;color:#d8d8c8;padding:10px 16px;border-radius:8px;font-size:12px;box-shadow:0 4px 20px rgba(0,0,0,.5);max-width:560px;text-align:center;";
|
|
1770
|
-
notice.innerHTML = `\u{1F4E1} <b style="color:#c4d640">IPFS \u9759\u6001\u6A21\u5F0F</b> \u2014 \u6B64\u9875\u9762\u901A\u8FC7 IPNS \u4ECE\u53BB\u4E2D\u5FC3\u5316\u7F51\u7EDC\u52A0\u8F7D.<br>\u5B8C\u6574\u529F\u80FD (\u5BF9\u8BDD/\u5DE5\u5177/\u5224\u65AD\u529B) \u9700\u8FDE\u63A5\u672C\u5730 Bolloon server: <code style="color:#c4d640">bolloon --web</code>`;
|
|
1771
|
-
document.body.appendChild(notice);
|
|
1772
|
-
setTimeout(() => {
|
|
1773
|
-
notice.remove();
|
|
1774
|
-
}, 15e3);
|
|
1775
|
-
}
|
|
1776
1768
|
var gwGroups = [];
|
|
1777
1769
|
var gwNetworks = [];
|
|
1778
1770
|
var gwActiveChat = null;
|
|
@@ -3111,6 +3103,8 @@ ${data.error || "channel not found"}`, "error");
|
|
|
3111
3103
|
}, 1e4);
|
|
3112
3104
|
eventSource.onerror = () => {
|
|
3113
3105
|
console.warn("[SSE] \u9519\u8BEF, \u6D4F\u89C8\u5668\u81EA\u52A8\u91CD\u8FDE\u4E2D:", targetChannelId, "readyState=", eventSource.readyState);
|
|
3106
|
+
hideLoopStatusBar2();
|
|
3107
|
+
setSendMode("idle");
|
|
3114
3108
|
if (eventSource.readyState === EventSource.CLOSED) {
|
|
3115
3109
|
clearInterval(heartbeatTimer);
|
|
3116
3110
|
eventSources.delete(targetChannelId);
|
|
@@ -3230,6 +3224,13 @@ ${data.error || "channel not found"}`, "error");
|
|
|
3230
3224
|
async function sendMessage() {
|
|
3231
3225
|
const text = input.value.trim();
|
|
3232
3226
|
if (!text) return;
|
|
3227
|
+
if (text === "/world" || text === "/chat") {
|
|
3228
|
+
const panel = text === "/world" ? "world" : "chat";
|
|
3229
|
+
if (typeof switchPanel === "function") switchPanel(panel);
|
|
3230
|
+
input.value = "";
|
|
3231
|
+
if (typeof showSimpleToast === "function") showSimpleToast(panel === "world" ? "\u{1F30D} \u5DF2\u5207\u6362\u5230\u4E16\u754C\u6A21\u5F0F" : "\u{1F4AC} \u5DF2\u5207\u6362\u5230\u804A\u5929\u6A21\u5F0F");
|
|
3232
|
+
return;
|
|
3233
|
+
}
|
|
3233
3234
|
setSendMode("abort");
|
|
3234
3235
|
const container = messagesContainers.get(currentChannelId) || messagesEl;
|
|
3235
3236
|
addMessage2(text, "user", true, container);
|
|
@@ -3263,10 +3264,16 @@ ${data.error || "channel not found"}`, "error");
|
|
|
3263
3264
|
})
|
|
3264
3265
|
});
|
|
3265
3266
|
if (!res.ok) {
|
|
3266
|
-
|
|
3267
|
+
hideLoopStatusBar2();
|
|
3268
|
+
const errBody = await res.json().catch(() => ({}));
|
|
3269
|
+
const reason = errBody?.error || errBody?.message || `HTTP ${res.status}`;
|
|
3270
|
+
addMessage2(`\u26A0\uFE0F \u53D1\u9001\u5931\u8D25: ${reason}`, "ai");
|
|
3267
3271
|
setSendMode("idle");
|
|
3272
|
+
if (typeof showSimpleToast === "function") showSimpleToast("\u26A0\uFE0F " + String(reason).slice(0, 200));
|
|
3273
|
+
return;
|
|
3268
3274
|
}
|
|
3269
3275
|
} catch (err) {
|
|
3276
|
+
hideLoopStatusBar2();
|
|
3270
3277
|
addMessage2("\u8FDE\u63A5\u9519\u8BEF", "ai");
|
|
3271
3278
|
console.error("Send error", err);
|
|
3272
3279
|
setSendMode("idle");
|
|
@@ -3520,6 +3527,8 @@ ${data.error || "channel not found"}`, "error");
|
|
|
3520
3527
|
{ cmd: "goal", desc: "\u6682\u505C\u76EE\u6807 (park_goal)", args: "\u76EE\u6807ID; \u539F\u56E0" },
|
|
3521
3528
|
{ cmd: "skill", desc: "\u6C89\u6DC0\u6280\u80FD (create_skill)", args: "\u6280\u80FD\u540D; \u63CF\u8FF0; \u6B65\u9AA4" },
|
|
3522
3529
|
{ cmd: "add-friend", desc: "\u6DFB\u52A0 P2P \u597D\u53CB", args: "\u516C\u94A5; \u5907\u6CE8" },
|
|
3530
|
+
{ cmd: "world", desc: "\u5207\u6362\u5230\u4E16\u754C\u6A21\u5F0F (\u673A\u4F1A\u6D41)", args: "" },
|
|
3531
|
+
{ cmd: "chat", desc: "\u5207\u6362\u5230\u804A\u5929\u6A21\u5F0F (\u5BF9\u8BDD)", args: "" },
|
|
3523
3532
|
{ cmd: "help", desc: "\u663E\u793A\u53EF\u7528\u547D\u4EE4", args: "" }
|
|
3524
3533
|
];
|
|
3525
3534
|
var slashDropdownEl = null;
|
|
@@ -3542,6 +3551,14 @@ ${data.error || "channel not found"}`, "error");
|
|
|
3542
3551
|
slashBlockEnd = -1;
|
|
3543
3552
|
}
|
|
3544
3553
|
function applySlashCommand(cmdObj) {
|
|
3554
|
+
if (cmdObj.cmd === "world" || cmdObj.cmd === "chat") {
|
|
3555
|
+
const panel = cmdObj.cmd === "world" ? "world" : "chat";
|
|
3556
|
+
if (typeof switchPanel === "function") switchPanel(panel);
|
|
3557
|
+
input.value = "";
|
|
3558
|
+
closeSlashDropdown();
|
|
3559
|
+
if (typeof showSimpleToast === "function") showSimpleToast(panel === "world" ? "\u{1F30D} \u5DF2\u5207\u6362\u5230\u4E16\u754C\u6A21\u5F0F" : "\u{1F4AC} \u5DF2\u5207\u6362\u5230\u804A\u5929\u6A21\u5F0F");
|
|
3560
|
+
return;
|
|
3561
|
+
}
|
|
3545
3562
|
const anchor = slashAnchor;
|
|
3546
3563
|
const blockEnd = slashBlockEnd >= 0 ? slashBlockEnd : anchor + 1 + (getCurrentSlashQuery()?.query || "").length;
|
|
3547
3564
|
if (anchor < 0 || anchor > input.value.length || input.value[anchor] !== "/") {
|
|
@@ -4076,6 +4093,9 @@ ${data.error || "channel not found"}`, "error");
|
|
|
4076
4093
|
if (sidebarToggle) {
|
|
4077
4094
|
sidebarToggle.addEventListener("click", toggleSidebar);
|
|
4078
4095
|
}
|
|
4096
|
+
if (sidebarExpandBtn) {
|
|
4097
|
+
sidebarExpandBtn.addEventListener("click", expandSidebar);
|
|
4098
|
+
}
|
|
4079
4099
|
if (newChannelBtn) {
|
|
4080
4100
|
newChannelBtn.addEventListener("click", () => {
|
|
4081
4101
|
createChannel("\u667A\u80FD\u4F53");
|
|
@@ -4994,27 +5014,18 @@ ${data.error || "channel not found"}`, "error");
|
|
|
4994
5014
|
}
|
|
4995
5015
|
var worldView = document.getElementById("world-view");
|
|
4996
5016
|
var worldBtn = document.getElementById("world-btn");
|
|
4997
|
-
var
|
|
4998
|
-
var
|
|
4999
|
-
var
|
|
5000
|
-
var worldIntentPriority = document.getElementById("world-intent-priority");
|
|
5001
|
-
var worldIntentBudget = document.getElementById("world-intent-budget");
|
|
5002
|
-
var worldIntentSet = document.getElementById("world-intent-set");
|
|
5003
|
-
var worldError = document.getElementById("world-intent-error");
|
|
5017
|
+
var worldIntentCol = document.getElementById("world-intent-col");
|
|
5018
|
+
var worldColToggle = document.getElementById("world-col-toggle");
|
|
5019
|
+
var worldColClose = document.getElementById("world-col-close");
|
|
5004
5020
|
var worldIntentsList = document.getElementById("world-intents-list");
|
|
5005
5021
|
var worldOpportunities = document.getElementById("world-opportunities");
|
|
5006
5022
|
var worldStats = document.getElementById("world-stats");
|
|
5007
5023
|
var worldBadge = document.getElementById("world-badge");
|
|
5008
|
-
var worldProfileInput = document.getElementById("world-profile-input");
|
|
5009
|
-
var worldProfileSet = document.getElementById("world-profile-set");
|
|
5010
5024
|
var worldLoaded = false;
|
|
5011
5025
|
var worldPollTimer = null;
|
|
5012
5026
|
var WORLD_POLL_MS = 3e4;
|
|
5013
5027
|
function worldStatus(msg) {
|
|
5014
|
-
if (
|
|
5015
|
-
worldError.textContent = msg || "";
|
|
5016
|
-
worldError.style.display = msg ? "" : "none";
|
|
5017
|
-
}
|
|
5028
|
+
if (msg) console.info("[world]", msg);
|
|
5018
5029
|
}
|
|
5019
5030
|
async function fetchWorldIntents() {
|
|
5020
5031
|
try {
|
|
@@ -5035,7 +5046,7 @@ ${data.error || "channel not found"}`, "error");
|
|
|
5035
5046
|
function renderWorldIntents(intents) {
|
|
5036
5047
|
if (!worldIntentsList) return;
|
|
5037
5048
|
if (!intents.length) {
|
|
5038
|
-
worldIntentsList.innerHTML = '<div class="form-hint" style="font-size:11px;">(\u8FD8\u6CA1\u6709\u610F\u56FE \u2014 \
|
|
5049
|
+
worldIntentsList.innerHTML = '<div class="form-hint" style="font-size:11px;">(\u8FD8\u6CA1\u6709\u610F\u56FE \u2014 \u5728\u5E95\u90E8\u8F93\u5165\u6846\u544A\u8BC9\u4E16\u754C\u4F60\u5728\u505A\u4EC0\u4E48)</div>';
|
|
5039
5050
|
return;
|
|
5040
5051
|
}
|
|
5041
5052
|
const active = intents.filter((i) => i.status === "active");
|
|
@@ -5082,12 +5093,30 @@ ${data.error || "channel not found"}`, "error");
|
|
|
5082
5093
|
}
|
|
5083
5094
|
const cards = opps.map((o) => {
|
|
5084
5095
|
const pct = Math.round(o.score * 100);
|
|
5085
|
-
|
|
5096
|
+
const inboxLine = o.inbox ? `<div style="font-size:11px;color:#8a8a80;margin-top:6px;border-top:1px dashed var(--border,#3a3a36);padding-top:6px;">
|
|
5097
|
+
\u2709 \u5916\u90E8\u6295\u9012 \xB7 \u6765\u81EA <span style="color:#c4d640;">${String(o.inbox.providerName || o.inbox.providerDid || "").slice(0, 40)}</span>
|
|
5098
|
+
\xB7 <span style="color:#6aaa6a;">\u2713 \u9A8C\u7B7E\u901A\u8FC7</span>
|
|
5099
|
+
${(o.inbox.refs || []).length ? "\xB7 " + o.inbox.refs.map((r) => `<a href="${String(r).replace(/</g, "<")}" target="_blank" rel="noopener" style="color:#7a9ad4;">[\u5F15\u7528]</a>`).join(" ") : ""}
|
|
5100
|
+
</div>` : "";
|
|
5101
|
+
const searchLine = o.search ? `<div style="font-size:11px;color:#8a8a80;margin-top:6px;border-top:1px dashed var(--border,#3a3a36);padding-top:6px;">
|
|
5102
|
+
\u{1F50E} AI \u4E3B\u52A8\u641C\u7D22 \xB7 <a href="${String(o.search.url || "").replace(/</g, "<")}" target="_blank" rel="noopener" style="color:#7a9ad4;">\u6253\u5F00\u539F\u6587 \u2197</a>
|
|
5103
|
+
\xB7 <span style="color:#6aaa6a;">\u6765\u6E90 ${o.search.source}</span>
|
|
5104
|
+
</div>` : "";
|
|
5105
|
+
const detailLine = `<div class="world-opp-detail" style="display:none;margin-top:8px;padding-top:8px;border-top:1px solid var(--border,#3a3a36);font-size:12px;color:#b8b8b0;line-height:1.6;">
|
|
5106
|
+
<div style="font-weight:600;color:#f0f0ea;margin-bottom:4px;">\u5B8C\u6574\u5185\u5BB9</div>
|
|
5107
|
+
<div>${String(o.summary || "(\u65E0\u66F4\u591A\u5185\u5BB9)").replace(/</g, "<")}</div>
|
|
5108
|
+
${o.search?.url ? `<div style="margin-top:6px;">\u{1F517} <a href="${String(o.search.url).replace(/</g, "<")}" target="_blank" rel="noopener" style="color:#7a9ad4;">${String(o.search.url).slice(0, 80)}</a></div>` : ""}
|
|
5109
|
+
<div style="margin-top:6px;color:#606058;">\u5339\u914D ${pct}% \xB7 \u6765\u6E90 ${o.source} \xB7 id ${o.id}</div>
|
|
5110
|
+
</div>`;
|
|
5111
|
+
return `<div class="world-opp-card" data-opp-card="${o.id}" style="border:1px solid var(--border,#3a3a36);border-radius:12px;padding:12px 14px;margin-bottom:10px;background:var(--bg-card,#222220);cursor:pointer;transition:border-color 0.2s;">
|
|
5086
5112
|
<div style="display:flex;justify-content:space-between;align-items:center;">
|
|
5087
5113
|
<b style="font-size:14px;">${String(o.title || "").slice(0, 60).replace(/</g, "<")}</b>
|
|
5088
5114
|
<span style="color:#c4d640;font-weight:700;font-size:14px;">${pct}%</span>
|
|
5089
5115
|
</div>
|
|
5090
5116
|
<div style="font-size:12px;color:#909088;margin-top:4px;">${String(o.summary || "").slice(0, 90).replace(/</g, "<")}</div>
|
|
5117
|
+
${inboxLine}
|
|
5118
|
+
${searchLine}
|
|
5119
|
+
${detailLine}
|
|
5091
5120
|
<div style="margin-top:8px;display:flex;gap:8px;">
|
|
5092
5121
|
<button class="btn-primary btn-sm" data-opp-action="accept" data-opp-id="${o.id}" style="font-size:11px;padding:3px 12px;">\u770B\u770B</button>
|
|
5093
5122
|
<button class="btn-secondary btn-sm" data-opp-action="ignore" data-opp-id="${o.id}" style="font-size:11px;padding:3px 12px;">\u5FFD\u7565</button>
|
|
@@ -5096,26 +5125,39 @@ ${data.error || "channel not found"}`, "error");
|
|
|
5096
5125
|
}).join("");
|
|
5097
5126
|
worldOpportunities.innerHTML = cards;
|
|
5098
5127
|
worldOpportunities.querySelectorAll("[data-opp-action]").forEach((btn) => {
|
|
5099
|
-
btn.addEventListener("click", async () => {
|
|
5128
|
+
btn.addEventListener("click", async (ev) => {
|
|
5129
|
+
ev.stopPropagation();
|
|
5100
5130
|
const id = btn.dataset.oppId;
|
|
5101
5131
|
if (btn.dataset.oppAction === "ignore") {
|
|
5102
5132
|
try {
|
|
5103
5133
|
await fetch("/api/opportunities/" + id + "/ignore", { method: "POST" });
|
|
5104
5134
|
} catch (e) {
|
|
5105
5135
|
}
|
|
5106
|
-
btn.closest(".world-opp-card")
|
|
5107
|
-
|
|
5136
|
+
const card = btn.closest(".world-opp-card");
|
|
5137
|
+
if (card) {
|
|
5138
|
+
card.style.opacity = "0.3";
|
|
5139
|
+
card.style.filter = "grayscale(1)";
|
|
5140
|
+
}
|
|
5108
5141
|
} else {
|
|
5109
5142
|
try {
|
|
5110
5143
|
await fetch("/api/opportunities/" + id + "/accept", { method: "POST" });
|
|
5111
5144
|
} catch (e) {
|
|
5112
5145
|
}
|
|
5113
|
-
|
|
5114
|
-
worldStatus("\u5DF2\u8BB0\u4E0B: " + srcId);
|
|
5115
|
-
btn.closest(".world-opp-card").style.borderColor = "#c4d640";
|
|
5146
|
+
toggleOppDetail(btn.closest(".world-opp-card"));
|
|
5116
5147
|
}
|
|
5117
5148
|
});
|
|
5118
5149
|
});
|
|
5150
|
+
worldOpportunities.querySelectorAll("[data-opp-card]").forEach((card) => {
|
|
5151
|
+
card.addEventListener("click", () => toggleOppDetail(card));
|
|
5152
|
+
});
|
|
5153
|
+
}
|
|
5154
|
+
function toggleOppDetail(card) {
|
|
5155
|
+
if (!card) return;
|
|
5156
|
+
const detail = card.querySelector(".world-opp-detail");
|
|
5157
|
+
if (!detail) return;
|
|
5158
|
+
const shown = detail.style.display !== "none";
|
|
5159
|
+
detail.style.display = shown ? "none" : "block";
|
|
5160
|
+
card.style.borderColor = shown ? "var(--border,#3a3a36)" : "#c4d640";
|
|
5119
5161
|
}
|
|
5120
5162
|
async function loadWorld() {
|
|
5121
5163
|
worldLoaded = true;
|
|
@@ -5136,88 +5178,83 @@ ${data.error || "channel not found"}`, "error");
|
|
|
5136
5178
|
worldPollTimer = null;
|
|
5137
5179
|
}
|
|
5138
5180
|
}
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5181
|
+
var tabWorld = document.getElementById("tab-world");
|
|
5182
|
+
var tabChat = document.getElementById("tab-chat");
|
|
5183
|
+
var loopStatusBar2 = document.getElementById("loop-status-bar");
|
|
5184
|
+
function switchPanel(panel) {
|
|
5185
|
+
if (!worldView || !messagesEl) return;
|
|
5186
|
+
const isWorld = panel === "world";
|
|
5187
|
+
worldView.style.display = isWorld ? "flex" : "none";
|
|
5188
|
+
if (messagesEl) messagesEl.hidden = isWorld;
|
|
5189
|
+
if (loopStatusBar2) loopStatusBar2.hidden = isWorld;
|
|
5190
|
+
if (inputArea) inputArea.hidden = isWorld;
|
|
5191
|
+
if (tabWorld) tabWorld.classList.toggle("active", isWorld);
|
|
5192
|
+
if (tabChat) tabChat.classList.toggle("active", !isWorld);
|
|
5193
|
+
if (isWorld) {
|
|
5142
5194
|
if (!worldLoaded) loadWorld();
|
|
5143
5195
|
else {
|
|
5144
5196
|
fetchWorldIntents();
|
|
5145
5197
|
refreshWorldOpportunities();
|
|
5146
5198
|
}
|
|
5147
5199
|
startWorldPoll();
|
|
5200
|
+
} else {
|
|
5201
|
+
stopWorldPoll();
|
|
5148
5202
|
}
|
|
5149
5203
|
}
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5204
|
+
if (tabWorld) tabWorld.addEventListener("click", () => switchPanel("world"));
|
|
5205
|
+
if (tabChat) tabChat.addEventListener("click", () => switchPanel("chat"));
|
|
5206
|
+
if (worldBtn) worldBtn.addEventListener("click", () => switchPanel("world"));
|
|
5207
|
+
function toggleWorldIntentCol(show) {
|
|
5208
|
+
if (!worldIntentCol) return;
|
|
5209
|
+
worldIntentCol.style.display = show ? "" : "none";
|
|
5210
|
+
if (worldColToggle) worldColToggle.textContent = show ? "\u25BE \u6211\u7684\u610F\u56FE" : "\u25B8 \u6211\u7684\u610F\u56FE";
|
|
5153
5211
|
}
|
|
5154
|
-
if (
|
|
5155
|
-
|
|
5156
|
-
if (worldRefreshBtn) worldRefreshBtn.addEventListener("click", () => {
|
|
5157
|
-
fetchWorldIntents();
|
|
5158
|
-
refreshWorldOpportunities();
|
|
5212
|
+
if (worldColToggle) worldColToggle.addEventListener("click", () => {
|
|
5213
|
+
toggleWorldIntentCol(worldIntentCol ? worldIntentCol.style.display === "none" : false);
|
|
5159
5214
|
});
|
|
5160
|
-
if (
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5215
|
+
if (worldColClose) worldColClose.addEventListener("click", () => toggleWorldIntentCol(false));
|
|
5216
|
+
var worldInput = document.getElementById("world-input");
|
|
5217
|
+
var worldInputSend = document.getElementById("world-input-send");
|
|
5218
|
+
async function tellWorld() {
|
|
5219
|
+
const text = (worldInput && worldInput.value || "").trim();
|
|
5220
|
+
if (!text) return;
|
|
5221
|
+
if (text === "/chat" || text === "/world") {
|
|
5222
|
+
const panel = text === "/chat" ? "chat" : "world";
|
|
5223
|
+
if (typeof switchPanel === "function") switchPanel(panel);
|
|
5224
|
+
worldInput.value = "";
|
|
5225
|
+
if (typeof showSimpleToast === "function") showSimpleToast(panel === "world" ? "\u{1F30D} \u5DF2\u5207\u6362\u5230\u4E16\u754C\u6A21\u5F0F" : "\u{1F4AC} \u5DF2\u5207\u6362\u5230\u804A\u5929\u6A21\u5F0F");
|
|
5164
5226
|
return;
|
|
5165
5227
|
}
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
const
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
if (!res.ok) {
|
|
5174
|
-
const err = await res.json().catch(() => ({}));
|
|
5175
|
-
worldStatus("\u753B\u50CF\u4FDD\u5B58\u5931\u8D25: " + (err.error || "HTTP " + res.status));
|
|
5176
|
-
return;
|
|
5177
|
-
}
|
|
5178
|
-
worldStatus("\u753B\u50CF\u5DF2\u4FDD\u5B58 \u2014 \u4E16\u754C\u5F00\u59CB\u6309\u5B83\u63A8\u9001");
|
|
5179
|
-
await refreshWorldOpportunities();
|
|
5180
|
-
} catch (e) {
|
|
5181
|
-
worldStatus("\u753B\u50CF\u4FDD\u5B58\u5931\u8D25: " + (e && e.message ? e.message : e));
|
|
5182
|
-
} finally {
|
|
5183
|
-
if (worldProfileSet) worldProfileSet.disabled = false;
|
|
5228
|
+
worldInput.value = "";
|
|
5229
|
+
if (worldOpportunities) {
|
|
5230
|
+
const echo = document.createElement("div");
|
|
5231
|
+
echo.className = "world-opp-card";
|
|
5232
|
+
echo.style.cssText = "border:1px dashed var(--accent,#c4d640);border-radius:12px;padding:10px 14px;margin-bottom:10px;background:var(--bg-card,#222220);font-size:13px;color:var(--text,#f0f0ea);";
|
|
5233
|
+
echo.innerHTML = `<div style="font-weight:700;margin-bottom:4px;">\u270D \u4F60\u544A\u8BC9\u4E16\u754C</div><div>${String(text).replace(/</g, "<")}</div><div style="color:#909088;font-size:11px;margin-top:6px;">\u5DF2\u58F0\u660E\u610F\u56FE \xB7 \u6B63\u5728\u4E3A\u4F60\u5339\u914D\u673A\u4F1A\u2026</div>`;
|
|
5234
|
+
worldOpportunities.prepend(echo);
|
|
5184
5235
|
}
|
|
5185
|
-
|
|
5186
|
-
if (worldIntentSet) worldIntentSet.addEventListener("click", async () => {
|
|
5187
|
-
const text = (worldIntentInput && worldIntentInput.value || "").trim();
|
|
5188
|
-
if (!text) {
|
|
5189
|
-
worldStatus("\u5148\u5199\u4E00\u53E5\u4F60\u73B0\u5728\u5728\u505A\u4EC0\u4E48");
|
|
5190
|
-
return;
|
|
5191
|
-
}
|
|
5192
|
-
if (worldIntentSet) worldIntentSet.disabled = true;
|
|
5236
|
+
if (typeof showSimpleToast === "function") showSimpleToast("\u{1F30D} \u5DF2\u544A\u8BC9\u4E16\u754C\uFF1A" + text, "success");
|
|
5193
5237
|
try {
|
|
5194
|
-
const
|
|
5195
|
-
if (worldIntentBudget && worldIntentBudget.value.trim()) body.budget = worldIntentBudget.value.trim();
|
|
5196
|
-
const res = await fetch("/api/intents", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) });
|
|
5238
|
+
const res = await fetch("/api/intents", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ text, priority: 3 }) });
|
|
5197
5239
|
if (!res.ok) {
|
|
5198
|
-
|
|
5199
|
-
worldStatus("\u58F0\u660E\u5931\u8D25: " + (err.error || "HTTP " + res.status));
|
|
5240
|
+
console.info("[world] \u58F0\u660E\u5931\u8D25 HTTP", res.status);
|
|
5200
5241
|
return;
|
|
5201
5242
|
}
|
|
5202
|
-
if (worldIntentInput) worldIntentInput.value = "";
|
|
5203
|
-
if (worldIntentBudget) worldIntentBudget.value = "";
|
|
5204
5243
|
await fetchWorldIntents();
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5244
|
+
try {
|
|
5245
|
+
await fetch("/api/world/search", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ topic: text }) });
|
|
5246
|
+
} catch (e) {
|
|
5247
|
+
console.info("[world] \u4E3B\u52A8\u641C\u7D22\u5931\u8D25", e);
|
|
5209
5248
|
}
|
|
5249
|
+
await refreshWorldOpportunities();
|
|
5210
5250
|
} catch (e) {
|
|
5211
|
-
|
|
5212
|
-
} finally {
|
|
5213
|
-
if (worldIntentSet) worldIntentSet.disabled = false;
|
|
5251
|
+
console.info("[world] \u58F0\u660E\u5931\u8D25", e);
|
|
5214
5252
|
}
|
|
5215
|
-
});
|
|
5216
|
-
if (worldIntentInput) {
|
|
5217
|
-
worldIntentInput.addEventListener("keydown", (e) => {
|
|
5218
|
-
if (e.key === "Enter" && worldIntentSet) worldIntentSet.click();
|
|
5219
|
-
});
|
|
5220
5253
|
}
|
|
5254
|
+
if (worldInputSend) worldInputSend.addEventListener("click", tellWorld);
|
|
5255
|
+
if (worldInput) worldInput.addEventListener("keydown", (e) => {
|
|
5256
|
+
if (e.key === "Enter") tellWorld();
|
|
5257
|
+
});
|
|
5221
5258
|
(async function autoWorldBadge() {
|
|
5222
5259
|
try {
|
|
5223
5260
|
await refreshWorldOpportunities();
|
|
Binary file
|
|
Binary file
|
package/dist/web/index.html
CHANGED
|
@@ -125,14 +125,28 @@
|
|
|
125
125
|
<span class="status-text">已连接</span>
|
|
126
126
|
</div>
|
|
127
127
|
</div>
|
|
128
|
-
|
|
128
|
+
</aside>
|
|
129
|
+
|
|
130
|
+
<!-- 2026-10-06 (用户): 左侧导航收起的恢复条 — 收起后滑出的方式不留下展开按钮就打不开, 补窄条 + 展开按钮 -->
|
|
131
|
+
<div class="sidebar-collapsed hidden" id="sidebar-collapsed-bar">
|
|
132
|
+
<button class="expand-btn" id="sidebar-expand-btn" title="展开侧边栏">
|
|
133
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
134
|
+
<polyline points="9 18 15 12 9 6"></polyline>
|
|
135
|
+
</svg>
|
|
136
|
+
</button>
|
|
137
|
+
</div>
|
|
129
138
|
|
|
130
|
-
|
|
131
|
-
|
|
139
|
+
<main class="main">
|
|
140
|
+
<header class="header">
|
|
132
141
|
<div class="header-left">
|
|
133
142
|
<span class="channel-indicator" id="channel-indicator"></span>
|
|
134
143
|
<h1 id="channel-name">Bolloon Agent</h1>
|
|
135
144
|
</div>
|
|
145
|
+
<!-- 2026-10-05 (leo): 世界/聊天切换放进原导航栏 (header) 中间 — 与钱包/配置同栏, 不再另起一行 -->
|
|
146
|
+
<div class="header-tabs">
|
|
147
|
+
<button id="tab-world" class="header-tab active" data-panel="world">🌍 世界 <span id="world-badge" class="task-badge" style="display:none;">0</span></button>
|
|
148
|
+
<button id="tab-chat" class="header-tab" data-panel="chat">💬 聊天</button>
|
|
149
|
+
</div>
|
|
136
150
|
<div class="header-right">
|
|
137
151
|
<button id="theme-toggle" class="theme-toggle" title="切换主题">
|
|
138
152
|
<svg class="sun-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
@@ -165,15 +179,6 @@
|
|
|
165
179
|
</svg>
|
|
166
180
|
<span id="wallet-badge" class="task-badge" style="display:none;">0</span>
|
|
167
181
|
</button>
|
|
168
|
-
<!-- 2026-10-05: World (Intent Console + Opportunity) — PC=Create 工作台入口 -->
|
|
169
|
-
<button id="world-btn" class="header-action" title="World — 我的意图与世界机会">
|
|
170
|
-
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
171
|
-
<circle cx="12" cy="12" r="9"></circle>
|
|
172
|
-
<path d="M3 12h18"></path>
|
|
173
|
-
<path d="M12 3a14 14 0 0 1 0 18 14 14 0 0 1 0-18z"></path>
|
|
174
|
-
</svg>
|
|
175
|
-
<span id="world-badge" class="task-badge" style="display:none;">0</span>
|
|
176
|
-
</button>
|
|
177
182
|
<button id="judgments-btn" class="header-action" title="我的判断">
|
|
178
183
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
179
184
|
<path d="M12 2L4 6v6c0 5 3.5 9.5 8 10 4.5-.5 8-5 8-10V6l-8-4z"></path>
|
|
@@ -422,55 +427,43 @@
|
|
|
422
427
|
</div>
|
|
423
428
|
</div>
|
|
424
429
|
|
|
425
|
-
<!-- World View (2026-10-05, leo Intent Network) —
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
<div style="display:flex;gap:8px;margin:8px 0;">
|
|
459
|
-
<select id="world-intent-priority" style="font-size:12px;padding:6px;background:var(--bg-card,#222220);color:var(--text);border:1px solid var(--border,#3a3a36);border-radius:6px;">
|
|
460
|
-
<option value="3">★★★</option><option value="5">★★★★★</option><option value="4">★★★★</option><option value="2">★★</option><option value="1">★</option>
|
|
461
|
-
</select>
|
|
462
|
-
<input type="text" id="world-intent-budget" placeholder="预算 ¥" style="font-size:12px;padding:6px;width:80px;background:var(--bg-card,#222220);color:var(--text);border:1px solid var(--border,#3a3a36);border-radius:6px;">
|
|
463
|
-
</div>
|
|
464
|
-
<button id="world-intent-set" class="btn-primary btn-sm" style="width:100%;padding:8px;font-size:13px;">声明 → 世界开始找</button>
|
|
465
|
-
<div id="world-intent-error" style="font-size:12px;color:#f59e0b;margin-top:8px;min-height:16px;"></div>
|
|
466
|
-
<div style="font-size:11px;color:#606058;margin-top:12px;line-height:1.6;">
|
|
467
|
-
世界会自己校准 —— 你「看看 / 忽略」的每个动作, 都让接下来的推送更准。
|
|
468
|
-
</div>
|
|
469
|
-
</aside>
|
|
430
|
+
<!-- World View (2026-10-05, leo Intent Network) — 主页内嵌面板 (不再全屏跳转):
|
|
431
|
+
顶部 tab 切换 世界/聊天, 默认世界; 无嵌套无跳转 -->
|
|
432
|
+
<div id="world-view" style="position:relative;background:var(--bg,#1a1a18);display:flex;flex-direction:column;flex:1;min-height:0;">
|
|
433
|
+
<!-- 面板头 (刷新按钮已按用户要求去掉; 内容自动流入) -->
|
|
434
|
+
<div style="display:flex;align-items:center;justify-content:space-between;padding:8px 18px;border-bottom:1px solid var(--border,#3a3a36);flex-shrink:0;">
|
|
435
|
+
<div style="font-weight:700;font-size:14px;">🌍 World <span style="color:#606058;font-weight:400;font-size:11px;">世界在给你送东西 · 自动流入</span></div>
|
|
436
|
+
<button id="world-col-toggle" class="btn-secondary btn-sm" style="font-size:11px;padding:3px 12px;" title="展开/折叠我的意图栏">▸ 我的意图</button>
|
|
437
|
+
</div>
|
|
438
|
+
<!-- Twitter 式两栏: 左 = 机会时间线, 右 = 我的意图 (可折叠, 2026-10-06 用户要求右置 + 折叠) -->
|
|
439
|
+
<div style="display:flex;flex:1;overflow:hidden;">
|
|
440
|
+
<!-- 左栏: 机会时间线 (Twitter feed 自动流入, 全宽) -->
|
|
441
|
+
<main style="flex:1;overflow-y:auto;padding:16px 24px;max-width:760px;margin:0 auto;width:100%;">
|
|
442
|
+
<div style="font-size:12px;color:#909088;margin-bottom:12px;">✦ 世界在给你送东西 (自动匹配, 持续流入)</div>
|
|
443
|
+
<div id="world-opportunities" style="min-height:120px;">
|
|
444
|
+
<div class="form-hint">世界正在观察…</div>
|
|
445
|
+
</div>
|
|
446
|
+
</main>
|
|
447
|
+
<!-- 右栏: 我的意图 (nav 风格, 可折叠隐藏) -->
|
|
448
|
+
<aside style="width:240px;border-left:1px solid var(--border,#3a3a36);overflow-y:auto;padding:12px;flex-shrink:0;transition:width .2s;" id="world-intent-col">
|
|
449
|
+
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:8px;">
|
|
450
|
+
<div style="font-size:12px;color:#909088;font-weight:600;">我的意图 (Intent)</div>
|
|
451
|
+
<button id="world-col-close" class="btn-secondary btn-sm" style="font-size:10px;padding:1px 7px;" title="折叠意图栏">✕</button>
|
|
452
|
+
</div>
|
|
453
|
+
<div id="world-intents-list" style="margin-bottom:12px;"><div class="form-hint">(还没有意图)</div></div>
|
|
454
|
+
<div style="font-size:12px;color:#909088;font-weight:600;margin-bottom:8px;">世界变化</div>
|
|
455
|
+
<div id="world-stats" style="font-size:12px;color:#606058;"></div>
|
|
456
|
+
</aside>
|
|
457
|
+
</div>
|
|
458
|
+
<!-- 2026-10-05 (leo): 世界底部输入框 — 想做什么直接说, 自动触发匹配 (不是聊天输入框) -->
|
|
459
|
+
<div class="world-input-bar" style="display:flex;gap:8px;align-items:center;padding:10px 18px;border-top:1px solid var(--border,#3a3a36);flex-shrink:0;background:var(--bg-sidebar,#222220);">
|
|
460
|
+
<input type="text" id="world-input" placeholder="告诉世界你在做什么 / 需要什么… (Enter 自动匹配)" autocomplete="off"
|
|
461
|
+
style="flex:1;padding:8px 12px;border-radius:8px;border:1px solid var(--border,#3a3a36);background:var(--bg-card,#222220);color:var(--text,#f0f0ea);font-size:13px;">
|
|
462
|
+
<button id="world-input-send" class="btn-primary btn-sm" style="padding:7px 16px;font-size:12px;">→ 世界</button>
|
|
470
463
|
</div>
|
|
471
464
|
</div>
|
|
472
465
|
|
|
473
|
-
<div class="messages" id="messages"></div>
|
|
466
|
+
<div class="messages" id="messages" hidden></div>
|
|
474
467
|
|
|
475
468
|
<!-- 2026-06-15: 旧 loop-timeline-panel 删除 — 步骤状态条改在每条 AI 消息气泡内挂 step-timeline 组件 -->
|
|
476
469
|
<!-- 2026-06-16: 循环 status bar — 渲染 tool='loop' | 'compactor' | 'recovery' 的 status 事件
|
|
@@ -484,7 +477,7 @@
|
|
|
484
477
|
<button id="loop-status-check" class="loop-status-action" hidden type="button">✓ 检查</button>
|
|
485
478
|
</div>
|
|
486
479
|
|
|
487
|
-
<div class="input-area">
|
|
480
|
+
<div class="input-area" hidden>
|
|
488
481
|
<div class="input-wrapper">
|
|
489
482
|
<button id="send-tools-toggle" class="send-tools-toggle" title="本次发送是否允许工具调用 (点击切换)"
|
|
490
483
|
style="display:none;align-items:center;gap:4px;background:transparent;border:1px solid var(--border);color:var(--text-muted);border-radius:6px;padding:4px 8px;font-size:11px;cursor:pointer;white-space:nowrap;flex-shrink:0;">
|