ocuclaw 1.3.2 → 1.3.4
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 +29 -1
- package/dist/config/runtime-config-session-title-model.test.js +0 -3
- package/dist/config/runtime-config.js +22 -33
- package/dist/domain/activity-status-adapter.js +0 -7
- package/dist/domain/activity-status-arbiter.js +3 -27
- package/dist/domain/activity-status-labels.js +8 -38
- package/dist/domain/code-span-regions.js +4 -24
- package/dist/domain/constant-time-equal.js +9 -0
- package/dist/domain/constant-time-equal.test.js +28 -0
- package/dist/domain/conversation-state.js +27 -138
- package/dist/domain/debug-bundle-cache.js +52 -0
- package/dist/domain/debug-bundle-format.js +60 -0
- package/dist/domain/debug-bundle-preview.js +123 -0
- package/dist/domain/debug-bundle-redaction.js +182 -0
- package/dist/domain/debug-bundle-save.js +11 -0
- package/dist/domain/debug-bundle-zip.js +15 -0
- package/dist/domain/debug-bundle.js +97 -0
- package/dist/domain/debug-store.js +6 -17
- package/dist/domain/debug-upload-preset.js +27 -0
- package/dist/domain/glasses-display-system-prompt.js +0 -5
- package/dist/domain/glasses-display-system-prompt.test.js +1 -1
- package/dist/domain/glasses-ui-content-summary.js +0 -6
- package/dist/domain/glasses-ui-system-prompt.test.js +1 -2
- package/dist/domain/message-emoji-allowlist.js +0 -7
- package/dist/domain/message-emoji-filter.js +3 -9
- package/dist/domain/neural-emoji-reactor-tag-config.js +3 -3
- package/dist/domain/prompt-channel-fragments.js +1 -10
- package/dist/domain/tagged-span-parser.js +3 -26
- package/dist/domain/tagged-span-strip.js +0 -7
- package/dist/even-ai/even-ai-endpoint.js +77 -24
- package/dist/even-ai/even-ai-run-waiter.js +0 -1
- package/dist/even-ai/even-ai-settings-store.js +11 -0
- package/dist/gateway/gateway-bridge.js +8 -9
- package/dist/gateway/gateway-timing-ledger.js +8 -6
- package/dist/gateway/openclaw-client.js +97 -297
- package/dist/gateway/sanitize-connect-reason.js +10 -0
- package/dist/gateway/sanitize-connect-reason.test.js +34 -0
- package/dist/index.js +3 -3
- package/dist/runtime/channel-two-hook.js +1 -6
- package/dist/runtime/container-env.js +1 -5
- package/dist/runtime/debug-bundle-handler.js +159 -0
- package/dist/runtime/display-toggle-states.js +6 -17
- package/dist/runtime/downstream-handler.js +682 -508
- package/dist/runtime/glasses-backpressure-latch.js +93 -0
- package/dist/runtime/ocuclaw-settings-store.js +10 -1
- package/dist/runtime/openclaw-host-version.js +5 -0
- package/dist/runtime/plugin-version-service.js +13 -6
- package/dist/runtime/provider-usage-select.js +0 -6
- package/dist/runtime/register-session-title-distiller.js +14 -16
- package/dist/runtime/relay-core.js +657 -271
- package/dist/runtime/relay-service.js +40 -36
- package/dist/runtime/relay-worker-approval-replay-cache.js +1 -1
- package/dist/runtime/relay-worker-entry.js +1 -2
- package/dist/runtime/relay-worker-health.js +2 -10
- package/dist/runtime/relay-worker-protocol.js +6 -1
- package/dist/runtime/relay-worker-supervisor.js +109 -39
- package/dist/runtime/relay-worker-transport.js +157 -15
- package/dist/runtime/session-context-service.js +5 -45
- package/dist/runtime/session-service.js +157 -175
- package/dist/runtime/session-title-distiller-budget.js +1 -5
- package/dist/runtime/session-title-distiller-helpers.js +14 -24
- package/dist/runtime/session-title-distiller.js +109 -122
- package/dist/runtime/session-title-record.js +0 -6
- package/dist/runtime/stable-prompt-snapshot.js +3 -14
- package/dist/runtime/upstream-runtime.js +600 -103
- package/dist/tools/device-info-tool.js +4 -21
- package/dist/tools/glasses-ui-cron.js +58 -63
- package/dist/tools/glasses-ui-descriptors.js +4 -33
- package/dist/tools/glasses-ui-limits.js +0 -13
- package/dist/tools/glasses-ui-paint-floor.js +22 -34
- package/dist/tools/glasses-ui-recipes.js +92 -101
- package/dist/tools/glasses-ui-surfaces.js +295 -100
- package/dist/tools/glasses-ui-template.js +7 -22
- package/dist/tools/glasses-ui-tool-description.test.js +2 -2
- package/dist/tools/glasses-ui-tool.js +475 -331
- package/dist/tools/glasses-ui-voicemail.js +242 -0
- package/dist/tools/glasses-ui-wake.js +195 -0
- package/dist/tools/session-title-tool.js +2 -7
- package/dist/tools/session-title-tool.test.js +1 -1
- package/dist/version.js +3 -2
- package/openclaw.plugin.json +60 -13
- package/package.json +3 -2
- package/skills/glasses-ui/SKILL.md +19 -3
- package/dist/runtime/protocol-adapter.js +0 -387
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
const DEFAULT_RECOVERED_HOLD_MS = 3_000;
|
|
2
|
+
const DEFAULT_STALE_MS = 5_000;
|
|
3
|
+
|
|
4
|
+
export function createGlassesBackpressureLatch(options = {}) {
|
|
5
|
+
const now = typeof options.now === "function" ? options.now : Date.now;
|
|
6
|
+
const recoveredHoldMs = Number.isFinite(options.recoveredHoldMs)
|
|
7
|
+
? options.recoveredHoldMs
|
|
8
|
+
: DEFAULT_RECOVERED_HOLD_MS;
|
|
9
|
+
const staleMs = Number.isFinite(options.staleMs) ? options.staleMs : DEFAULT_STALE_MS;
|
|
10
|
+
const emitDebug = typeof options.emitDebug === "function" ? options.emitDebug : () => {};
|
|
11
|
+
|
|
12
|
+
let latched = false;
|
|
13
|
+
let latchedAtMs = null;
|
|
14
|
+
let lastOverAtMs = null;
|
|
15
|
+
let lastReportAtMs = null;
|
|
16
|
+
let workerEpoch = null;
|
|
17
|
+
|
|
18
|
+
function clearState() {
|
|
19
|
+
latched = false;
|
|
20
|
+
latchedAtMs = null;
|
|
21
|
+
lastOverAtMs = null;
|
|
22
|
+
lastReportAtMs = null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function emitTransition(nextLatched, reason, atMs) {
|
|
26
|
+
if (nextLatched === latched) return;
|
|
27
|
+
if (nextLatched) {
|
|
28
|
+
latchedAtMs = atMs;
|
|
29
|
+
emitDebug("glasses_backpressure_latched", "warn", { reason });
|
|
30
|
+
} else {
|
|
31
|
+
emitDebug("glasses_backpressure_cleared", "info", {
|
|
32
|
+
reason,
|
|
33
|
+
latchedForMs: latchedAtMs === null ? null : Math.max(0, atMs - latchedAtMs),
|
|
34
|
+
});
|
|
35
|
+
latchedAtMs = null;
|
|
36
|
+
}
|
|
37
|
+
latched = nextLatched;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function evaluate(atMs) {
|
|
41
|
+
if (!latched) return;
|
|
42
|
+
if (lastReportAtMs !== null && atMs - lastReportAtMs > staleMs) {
|
|
43
|
+
emitTransition(false, "stale_reports", atMs);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (
|
|
47
|
+
lastOverAtMs !== null &&
|
|
48
|
+
atMs - lastOverAtMs >= recoveredHoldMs &&
|
|
49
|
+
lastReportAtMs !== null &&
|
|
50
|
+
lastReportAtMs > lastOverAtMs
|
|
51
|
+
) {
|
|
52
|
+
|
|
53
|
+
emitTransition(false, "recovered", atMs);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function report(params) {
|
|
58
|
+
const atMs = now();
|
|
59
|
+
const count =
|
|
60
|
+
params && Number.isFinite(params.sendBufferHighWaterClients)
|
|
61
|
+
? params.sendBufferHighWaterClients
|
|
62
|
+
: null;
|
|
63
|
+
if (count === null) return;
|
|
64
|
+
const epoch = params && Number.isFinite(params.workerEpoch) ? params.workerEpoch : null;
|
|
65
|
+
if (epoch !== null && workerEpoch !== null && epoch !== workerEpoch) {
|
|
66
|
+
|
|
67
|
+
clearState();
|
|
68
|
+
}
|
|
69
|
+
if (epoch !== null) workerEpoch = epoch;
|
|
70
|
+
lastReportAtMs = atMs;
|
|
71
|
+
if (count >= 1) {
|
|
72
|
+
lastOverAtMs = atMs;
|
|
73
|
+
emitTransition(true, "over_high_water", atMs);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
evaluate(atMs);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function isOverHighWater() {
|
|
80
|
+
evaluate(now());
|
|
81
|
+
return latched;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function reset(reason) {
|
|
85
|
+
const atMs = now();
|
|
86
|
+
emitTransition(false, typeof reason === "string" ? reason : "reset", atMs);
|
|
87
|
+
clearState();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return { report, isOverHighWater, reset };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export default { createGlassesBackpressureLatch };
|
|
@@ -53,6 +53,10 @@ export function normalizeOcuClawDefaultFastMode(value) {
|
|
|
53
53
|
return value === true;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
export function normalizeOcuClawDefaultAgent(value) {
|
|
57
|
+
return normalizeTrimmedString(value);
|
|
58
|
+
}
|
|
59
|
+
|
|
56
60
|
function isStoredSnapshotCanonical(value, snapshot) {
|
|
57
61
|
if (!value || typeof value !== "object") {
|
|
58
62
|
return false;
|
|
@@ -61,7 +65,8 @@ function isStoredSnapshotCanonical(value, snapshot) {
|
|
|
61
65
|
normalizeTrimmedString(value.systemPrompt) === snapshot.systemPrompt &&
|
|
62
66
|
normalizeTrimmedString(value.defaultModel) === snapshot.defaultModel &&
|
|
63
67
|
normalizeOcuClawDefaultThinking(value.defaultThinking) === snapshot.defaultThinking &&
|
|
64
|
-
normalizeOcuClawDefaultFastMode(value.defaultFastMode) === snapshot.defaultFastMode
|
|
68
|
+
normalizeOcuClawDefaultFastMode(value.defaultFastMode) === snapshot.defaultFastMode &&
|
|
69
|
+
normalizeOcuClawDefaultAgent(value.defaultAgent) === snapshot.defaultAgent
|
|
65
70
|
);
|
|
66
71
|
}
|
|
67
72
|
|
|
@@ -71,6 +76,7 @@ export function normalizeOcuClawSettingsSnapshot(value = {}) {
|
|
|
71
76
|
defaultModel: normalizeOcuClawDefaultModel(value.defaultModel),
|
|
72
77
|
defaultThinking: normalizeOcuClawDefaultThinking(value.defaultThinking),
|
|
73
78
|
defaultFastMode: normalizeOcuClawDefaultFastMode(value.defaultFastMode),
|
|
79
|
+
defaultAgent: normalizeOcuClawDefaultAgent(value.defaultAgent),
|
|
74
80
|
};
|
|
75
81
|
}
|
|
76
82
|
|
|
@@ -266,6 +272,9 @@ export function createOcuClawSettingsStore(opts = {}) {
|
|
|
266
272
|
defaultFastMode: hasOwn(patch, "defaultFastMode")
|
|
267
273
|
? normalizeOcuClawDefaultFastMode(patch.defaultFastMode)
|
|
268
274
|
: snapshot.defaultFastMode,
|
|
275
|
+
defaultAgent: hasOwn(patch, "defaultAgent")
|
|
276
|
+
? normalizeOcuClawDefaultAgent(patch.defaultAgent)
|
|
277
|
+
: snapshot.defaultAgent,
|
|
269
278
|
};
|
|
270
279
|
snapshot = next;
|
|
271
280
|
persistSnapshot(snapshot, "set_settings");
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import { PLUGIN_VERSION, REQUIRES_CLIENT_VERSION } from "../version.js";
|
|
1
|
+
import { PLUGIN_VERSION, REQUIRES_CLIENT_VERSION, BUILD_INPUT_HASH } from "../version.js";
|
|
2
|
+
import { readOpenClawHostVersion } from "./openclaw-host-version.js";
|
|
2
3
|
|
|
3
|
-
/**
|
|
4
|
-
* Plugin version provider. Exposes the build-time version constants used by the
|
|
5
|
-
* relay handshake. No process execution.
|
|
6
|
-
*/
|
|
7
4
|
function createPluginVersionService() {
|
|
8
5
|
function getPluginVersion() {
|
|
9
6
|
return typeof PLUGIN_VERSION === "string" && PLUGIN_VERSION.length > 0
|
|
@@ -17,7 +14,17 @@ function createPluginVersionService() {
|
|
|
17
14
|
: null;
|
|
18
15
|
}
|
|
19
16
|
|
|
20
|
-
|
|
17
|
+
function getOpenClawHostVersion() {
|
|
18
|
+
return readOpenClawHostVersion();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function getDistHash() {
|
|
22
|
+
return typeof BUILD_INPUT_HASH === "string" && BUILD_INPUT_HASH.length > 0
|
|
23
|
+
? BUILD_INPUT_HASH
|
|
24
|
+
: null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return { getPluginVersion, getRequiresClientVersion, getOpenClawHostVersion, getDistHash };
|
|
21
28
|
}
|
|
22
29
|
|
|
23
30
|
export { createPluginVersionService };
|
|
@@ -85,12 +85,6 @@ export function selectProviderUsageSnapshot(summary, opts = {}) {
|
|
|
85
85
|
(entry) => entry.provider.trim().toLowerCase() === activeProvider,
|
|
86
86
|
);
|
|
87
87
|
|
|
88
|
-
// Family fallback: the session model config reports the base provider id
|
|
89
|
-
// (e.g. "openai") while the usage summary keys the same usage by its
|
|
90
|
-
// sub-provider source (e.g. "openai-codex"). When there is no exact match
|
|
91
|
-
// but exactly ONE summary entry belongs to the active provider's family
|
|
92
|
-
// ("${activeProvider}-…"), resolve it. Restricted to a single family member
|
|
93
|
-
// to avoid ambiguous attribution when multiple sub-providers exist.
|
|
94
88
|
if (!match) {
|
|
95
89
|
const familyMatches = namedEntries.filter((entry) =>
|
|
96
90
|
entry.provider.trim().toLowerCase().startsWith(`${activeProvider}-`),
|
|
@@ -10,10 +10,7 @@ function genRunId() {
|
|
|
10
10
|
|
|
11
11
|
export function registerSessionTitleDistiller(api, service) {
|
|
12
12
|
if (!api || typeof api.on !== "function") return () => {};
|
|
13
|
-
|
|
14
|
-
// title record + toggle state). Resolve it lazily per call: at registration
|
|
15
|
-
// the live relay may not exist yet, and a sibling context resolves the shared
|
|
16
|
-
// relay's budget.
|
|
13
|
+
|
|
17
14
|
const budget = {
|
|
18
15
|
canRun: (k) => {
|
|
19
16
|
const b = service.getDistillerBudget();
|
|
@@ -29,8 +26,7 @@ export function registerSessionTitleDistiller(api, service) {
|
|
|
29
26
|
},
|
|
30
27
|
};
|
|
31
28
|
const distiller = createSessionTitleDistiller({
|
|
32
|
-
|
|
33
|
-
// this distiller is constructed during registration.
|
|
29
|
+
|
|
34
30
|
getStateDir: () => (service.getStateDir ? service.getStateDir() : undefined),
|
|
35
31
|
nowMs: () => Date.now(),
|
|
36
32
|
genId: genRunId,
|
|
@@ -49,6 +45,12 @@ export function registerSessionTitleDistiller(api, service) {
|
|
|
49
45
|
typeof service.deleteDistillerSession === "function"
|
|
50
46
|
? service.deleteDistillerSession(k)
|
|
51
47
|
: Promise.resolve(null),
|
|
48
|
+
|
|
49
|
+
llmComplete: (() => {
|
|
50
|
+
const llm = api && api.runtime && api.runtime.llm;
|
|
51
|
+
if (!llm || typeof llm.complete !== "function") return undefined;
|
|
52
|
+
return (params) => llm.complete(params);
|
|
53
|
+
})(),
|
|
52
54
|
subagentRuntime: (() => {
|
|
53
55
|
const sa = api && api.runtime && api.runtime.subagent;
|
|
54
56
|
if (
|
|
@@ -76,24 +78,20 @@ export function registerSessionTitleDistiller(api, service) {
|
|
|
76
78
|
});
|
|
77
79
|
|
|
78
80
|
return api.on("agent_end", (event, ctx) => {
|
|
79
|
-
|
|
80
|
-
// keyed by the bare relay key — normalize at the boundary.
|
|
81
|
+
|
|
81
82
|
const rawSessionKey = ctx && typeof ctx.sessionKey === "string" ? ctx.sessionKey : null;
|
|
82
83
|
const sessionKey = stripAgentSessionPrefix(rawSessionKey);
|
|
83
84
|
if (!sessionKey) return;
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
// conversation state. Either way the messages are pinned here so a later
|
|
88
|
-
// session switch / clear can't make the distiller title from another
|
|
89
|
-
// session's transcript.
|
|
85
|
+
|
|
86
|
+
const agentId = ctx && typeof ctx.agentId === "string" && ctx.agentId.trim() ? ctx.agentId.trim() : undefined;
|
|
87
|
+
|
|
90
88
|
const eventMessages = event && Array.isArray(event.messages) ? event.messages : null;
|
|
91
89
|
const messages =
|
|
92
90
|
eventMessages && eventMessages.length
|
|
93
91
|
? eventMessages
|
|
94
92
|
: service.getRawMessages();
|
|
95
|
-
|
|
96
|
-
Promise.resolve(distiller.maybeRun(sessionKey, { messages })).catch(() => {});
|
|
93
|
+
|
|
94
|
+
Promise.resolve(distiller.maybeRun(sessionKey, { messages, agentId })).catch(() => {});
|
|
97
95
|
});
|
|
98
96
|
}
|
|
99
97
|
|