psyclaw 0.29.17 → 0.29.19
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 +7 -4
- package/dist/apps/panel/index.html +441 -154
- package/dist/apps/panel/observability.js +87 -0
- package/dist/src/adapters/pi/extension.js +40 -2
- package/dist/src/adapters/pi/extension.js.map +1 -1
- package/dist/src/chat.js +2 -0
- package/dist/src/chat.js.map +1 -1
- package/dist/src/cli.js +63 -0
- package/dist/src/cli.js.map +1 -1
- package/dist/src/observability/config.d.ts +47 -0
- package/dist/src/observability/config.js +125 -0
- package/dist/src/observability/config.js.map +1 -0
- package/dist/src/observability/index.d.ts +29 -0
- package/dist/src/observability/index.js +75 -0
- package/dist/src/observability/index.js.map +1 -0
- package/dist/src/observability/node-sdks.d.ts +11 -0
- package/dist/src/observability/node-sdks.js +92 -0
- package/dist/src/observability/node-sdks.js.map +1 -0
- package/dist/src/observability/notice.d.ts +9 -0
- package/dist/src/observability/notice.js +43 -0
- package/dist/src/observability/notice.js.map +1 -0
- package/dist/src/observability/preference.d.ts +23 -0
- package/dist/src/observability/preference.js +102 -0
- package/dist/src/observability/preference.js.map +1 -0
- package/dist/src/observability/public-keys.d.ts +10 -0
- package/dist/src/observability/public-keys.js +11 -0
- package/dist/src/observability/public-keys.js.map +1 -0
- package/dist/src/orchestration/runner.js +21 -2
- package/dist/src/orchestration/runner.js.map +1 -1
- package/dist/src/panel/extension.js +5 -1
- package/dist/src/panel/extension.js.map +1 -1
- package/dist/src/panel/hub.d.ts +2 -0
- package/dist/src/panel/hub.js +12 -0
- package/dist/src/panel/hub.js.map +1 -1
- package/dist/src/panel/server.d.ts +4 -0
- package/dist/src/panel/server.js +188 -75
- package/dist/src/panel/server.js.map +1 -1
- package/dist/src/panel/workbench.js +15 -1
- package/dist/src/panel/workbench.js.map +1 -1
- package/dist/src/session/modes.d.ts +13 -0
- package/dist/src/session/modes.js +39 -3
- package/dist/src/session/modes.js.map +1 -1
- package/dist/src/style/cli-ui.js +2 -0
- package/dist/src/style/cli-ui.js.map +1 -1
- package/docs/PsyClaw/344/275/277/347/224/250/347/231/275/347/232/256/344/271/246_v0.29.15.md +907 -0
- package/docs//344/275/277/347/224/250/347/231/275/347/232/256/344/271/246.md +3 -0
- package/package.json +7 -2
- package/scripts/rebrand-pi.mjs +74 -1
- package/skills/recommended/catalog.json +4 -2
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opt-in browser observability for PsyClaw panel + website.
|
|
3
|
+
*
|
|
4
|
+
* Loads Sentry / PostHog from a CDN only when a DSN or project key is present
|
|
5
|
+
* on window.__PSYCLAW_OBS__, a meta tag, or (local debug) a query param.
|
|
6
|
+
* With those empty, this file is a no-op: no network calls, no SDK init.
|
|
7
|
+
*/
|
|
8
|
+
(function psyclawObservability() {
|
|
9
|
+
if (window.__PSYCLAW_OBS_BOOTED__) return;
|
|
10
|
+
window.__PSYCLAW_OBS_BOOTED__ = true;
|
|
11
|
+
|
|
12
|
+
function meta(name) {
|
|
13
|
+
const node = document.querySelector('meta[name="' + name + '"]');
|
|
14
|
+
const value = node && node.getAttribute("content");
|
|
15
|
+
return value ? String(value).trim() : "";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function param(name) {
|
|
19
|
+
try {
|
|
20
|
+
return new URLSearchParams(location.search).get(name) || "";
|
|
21
|
+
} catch {
|
|
22
|
+
return "";
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function readConfig() {
|
|
27
|
+
const fromWindow = window.__PSYCLAW_OBS__ || {};
|
|
28
|
+
const sentryDsn = String(fromWindow.sentryDsn || meta("psyclaw-sentry-dsn") || param("sentryDsn") || "").trim();
|
|
29
|
+
const posthogKey = String(fromWindow.posthogKey || meta("psyclaw-posthog-key") || param("posthogKey") || "").trim();
|
|
30
|
+
const posthogHost = String(
|
|
31
|
+
fromWindow.posthogHost || meta("psyclaw-posthog-host") || param("posthogHost") || "https://us.posthog.com",
|
|
32
|
+
).trim();
|
|
33
|
+
const surface = fromWindow.surface === "panel" || fromWindow.surface === "website" ? fromWindow.surface : "web";
|
|
34
|
+
const release = String(fromWindow.release || "").trim();
|
|
35
|
+
return { sentryDsn, posthogKey, posthogHost, surface, release };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function loadEsm(url) {
|
|
39
|
+
return import(url);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function bootSentry(config) {
|
|
43
|
+
const Sentry = await loadEsm("https://cdn.jsdelivr.net/npm/@sentry/browser@10/+esm");
|
|
44
|
+
Sentry.init({
|
|
45
|
+
dsn: config.sentryDsn,
|
|
46
|
+
release: config.release || undefined,
|
|
47
|
+
environment: "local",
|
|
48
|
+
tracesSampleRate: 1.0,
|
|
49
|
+
sendDefaultPii: false,
|
|
50
|
+
integrations: typeof Sentry.browserTracingIntegration === "function" ? [Sentry.browserTracingIntegration()] : [],
|
|
51
|
+
});
|
|
52
|
+
window.Sentry = Sentry;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function bootPostHog(config) {
|
|
56
|
+
const mod = await loadEsm("https://cdn.jsdelivr.net/npm/posthog-js@1/+esm");
|
|
57
|
+
const posthog = mod.default || mod.posthog || mod;
|
|
58
|
+
const panel = config.surface === "panel";
|
|
59
|
+
posthog.init(config.posthogKey, {
|
|
60
|
+
api_host: config.posthogHost,
|
|
61
|
+
person_profiles: "identified_only",
|
|
62
|
+
autocapture: true,
|
|
63
|
+
capture_pageview: true,
|
|
64
|
+
capture_pageleave: true,
|
|
65
|
+
persistence: "memory",
|
|
66
|
+
mask_all_text: panel,
|
|
67
|
+
mask_all_element_attributes: panel,
|
|
68
|
+
session_recording: {
|
|
69
|
+
maskAllInputs: true,
|
|
70
|
+
maskTextSelector: panel
|
|
71
|
+
? ".markdown, .raw, .viewer-body, .event-detail, pre, code, textarea, [data-file]"
|
|
72
|
+
: undefined,
|
|
73
|
+
},
|
|
74
|
+
loaded: function (client) {
|
|
75
|
+
client.register({ surface: config.surface, app: "psyclaw" });
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
window.posthog = posthog;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const config = readConfig();
|
|
82
|
+
const jobs = [];
|
|
83
|
+
if (config.sentryDsn) jobs.push(bootSentry(config).catch(function () {}));
|
|
84
|
+
if (config.posthogKey) jobs.push(bootPostHog(config).catch(function () {}));
|
|
85
|
+
if (jobs.length === 0) return;
|
|
86
|
+
Promise.all(jobs).catch(function () {});
|
|
87
|
+
})();
|
|
@@ -30,11 +30,12 @@ import { advanceAnalysisPlan, createAnalysisPlan, formatAnalysisPlanStatus, read
|
|
|
30
30
|
import { formatAnalysisPlanTakeover, resolveStatsIntent, } from "../../analysis/stats-router.js";
|
|
31
31
|
import { arsRoot } from "../../ars/pi-panel-executor.js";
|
|
32
32
|
import { ArsModeEditor, isArsModeEditorText } from "../../ars/mode-editor.js";
|
|
33
|
-
import { MODE_STATUS, nextSessionMode, parseSessionMode, sessionModePrompt, } from "../../session/modes.js";
|
|
33
|
+
import { MODE_STATUS, detectChatModeMismatch, formatChatModeMismatchNotice, nextSessionMode, parseSessionMode, sessionModePrompt, } from "../../session/modes.js";
|
|
34
34
|
import { continuouslyWorkWarningText, isContinuouslyWorkEnabled, } from "../../session/continuously-work.js";
|
|
35
35
|
import { assertHumanVerifyGate, formatVerifyChecklist, isNaturalPlanConfirm, ensureDefaultVerifyChecklist, loadVerifyChecklist } from "../../verify/checklist.js";
|
|
36
36
|
import { formatSessionHelp, formatSessionHelpBrief } from "../../session/help.js";
|
|
37
37
|
import { openResearchWorkbench } from "../../panel/workbench.js";
|
|
38
|
+
import { captureAgentError, initNodeObservability, readTelemetryPreference, shutdownObservability, trackGateWaiting, writeTelemetryPreference, } from "../../observability/index.js";
|
|
38
39
|
/** Codex-style slash surface: bare command, or command + trailing free text. No subcommand trees. */
|
|
39
40
|
function parseInitArgs(args) {
|
|
40
41
|
const goal = args.trim();
|
|
@@ -43,6 +44,7 @@ function parseInitArgs(args) {
|
|
|
43
44
|
return { paradigm: "survey-observational", goal };
|
|
44
45
|
}
|
|
45
46
|
async function notifyError(ctx, error) {
|
|
47
|
+
await captureAgentError(error, { phase: "extension" });
|
|
46
48
|
ctx.ui.notify(error instanceof Error ? error.message : String(error), "error");
|
|
47
49
|
}
|
|
48
50
|
const activeAgentRuns = new Set();
|
|
@@ -887,6 +889,7 @@ const WORKFLOW_RUNNERS = {
|
|
|
887
889
|
"expert-review": runExpertReview,
|
|
888
890
|
};
|
|
889
891
|
export default function psyclawExtension(pi) {
|
|
892
|
+
void initNodeObservability();
|
|
890
893
|
const developerCommands = process.env.PSYCLAW_DEVELOPER_COMMANDS === "1";
|
|
891
894
|
const legacyTestApi = typeof pi.registerTool !== "function";
|
|
892
895
|
const runtimeMcps = new RuntimeMcpRegistry();
|
|
@@ -936,7 +939,10 @@ export default function psyclawExtension(pi) {
|
|
|
936
939
|
};
|
|
937
940
|
});
|
|
938
941
|
if (!legacyTestApi && typeof pi.on === "function")
|
|
939
|
-
pi.on("session_shutdown", () =>
|
|
942
|
+
pi.on("session_shutdown", () => {
|
|
943
|
+
runtimeMcps.close();
|
|
944
|
+
void shutdownObservability();
|
|
945
|
+
});
|
|
940
946
|
if (!legacyTestApi && typeof pi.on === "function")
|
|
941
947
|
pi.on("before_agent_start", async (event, ctx) => {
|
|
942
948
|
if (!(await readActiveProject(ctx?.cwd ?? process.cwd())))
|
|
@@ -1017,6 +1023,17 @@ export default function psyclawExtension(pi) {
|
|
|
1017
1023
|
}
|
|
1018
1024
|
const mode = arsModeEditor?.getMode() ?? sessionMode;
|
|
1019
1025
|
const trimmed = event.text.trim();
|
|
1026
|
+
// Chat must not soft-takeover; when intent fits analysis/academic, remind only.
|
|
1027
|
+
if (mode === "chat") {
|
|
1028
|
+
const mismatch = detectChatModeMismatch(trimmed);
|
|
1029
|
+
if (mismatch) {
|
|
1030
|
+
ctx.ui.notify(mismatch.notify, "warning");
|
|
1031
|
+
return {
|
|
1032
|
+
action: "transform",
|
|
1033
|
+
text: formatChatModeMismatchNotice(mismatch, trimmed),
|
|
1034
|
+
};
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1020
1037
|
// Natural-language plan confirm: reply「可以」instead of forcing /plan confirm.
|
|
1021
1038
|
if (mode === "analysis" && isNaturalPlanConfirm(trimmed)) {
|
|
1022
1039
|
const plan = await readActiveAnalysisPlan(ctx.cwd);
|
|
@@ -1094,6 +1111,7 @@ export default function psyclawExtension(pi) {
|
|
|
1094
1111
|
if (requiresSeparateOperationConfirmation(event.toolName, event.input)) {
|
|
1095
1112
|
if (!ctx.hasUI)
|
|
1096
1113
|
return { block: true, terminate: true, reason: "外部发布需要用户在交互界面中明确确认" };
|
|
1114
|
+
void trackGateWaiting("tool_approval");
|
|
1097
1115
|
const choice = await ctx.ui.select(`确认外部操作\n${summary}`, ["确认执行", "取消"], { timeout: 120_000 });
|
|
1098
1116
|
const approved = choice === "确认执行";
|
|
1099
1117
|
await appendApproval(ctx.cwd, {
|
|
@@ -1607,6 +1625,26 @@ export default function psyclawExtension(pi) {
|
|
|
1607
1625
|
ctx.ui.notify(`启动横幅宠物已${action === "on" ? "开启" : "关闭"},下次启动生效`, "info");
|
|
1608
1626
|
},
|
|
1609
1627
|
});
|
|
1628
|
+
if (!legacyTestApi)
|
|
1629
|
+
pi.registerCommand("telemetry", {
|
|
1630
|
+
description: "查看或关闭匿名产品遥测",
|
|
1631
|
+
handler: async (args, ctx) => {
|
|
1632
|
+
const action = args.trim().toLowerCase() || "status";
|
|
1633
|
+
if (action === "status") {
|
|
1634
|
+
const preference = await readTelemetryPreference();
|
|
1635
|
+
ctx.ui.notify(preference.enabled
|
|
1636
|
+
? "匿名产品遥测:开启(默认)。采集粗粒度使用与错误,不含研究正文。关闭:/telemetry off"
|
|
1637
|
+
: "匿名产品遥测:已关闭。重新开启:/telemetry on", "info");
|
|
1638
|
+
return;
|
|
1639
|
+
}
|
|
1640
|
+
if (action !== "on" && action !== "off") {
|
|
1641
|
+
ctx.ui.notify("Usage: /telemetry on|off|status", "error");
|
|
1642
|
+
return;
|
|
1643
|
+
}
|
|
1644
|
+
await writeTelemetryPreference({ enabled: action === "on", noticeAcknowledged: true });
|
|
1645
|
+
ctx.ui.notify(action === "on" ? "已开启匿名产品遥测。下次启动生效。" : "已关闭匿名产品遥测。下次启动不再发送。", "info");
|
|
1646
|
+
},
|
|
1647
|
+
});
|
|
1610
1648
|
if (typeof pi.registerTool === "function") {
|
|
1611
1649
|
pi.registerTool({
|
|
1612
1650
|
name: "psyclaw_research_decision",
|