@useorgx/openclaw-plugin 0.7.8 → 0.7.15
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 +94 -122
- package/dashboard/dist/assets/0RUEVzJa.js +1 -0
- package/dashboard/dist/assets/0RUEVzJa.js.br +0 -0
- package/dashboard/dist/assets/0RUEVzJa.js.gz +0 -0
- package/dashboard/dist/assets/3TtV4moZ.js +1 -0
- package/dashboard/dist/assets/3TtV4moZ.js.br +0 -0
- package/dashboard/dist/assets/3TtV4moZ.js.gz +0 -0
- package/dashboard/dist/assets/3VwNyxUf.js +1 -0
- package/dashboard/dist/assets/3VwNyxUf.js.br +0 -0
- package/dashboard/dist/assets/3VwNyxUf.js.gz +0 -0
- package/dashboard/dist/assets/{DpuQm1oF.js → 7DhYqBrM.js} +2 -2
- package/dashboard/dist/assets/7DhYqBrM.js.br +0 -0
- package/dashboard/dist/assets/7DhYqBrM.js.gz +0 -0
- package/dashboard/dist/assets/{tcEHYcbW.js → BCudUvwg.js} +1 -1
- package/dashboard/dist/assets/BCudUvwg.js.br +0 -0
- package/dashboard/dist/assets/BCudUvwg.js.gz +0 -0
- package/dashboard/dist/assets/BV0BcV1u.js +53 -0
- package/dashboard/dist/assets/BV0BcV1u.js.br +0 -0
- package/dashboard/dist/assets/BV0BcV1u.js.gz +0 -0
- package/dashboard/dist/assets/BVvffj0x.js +1 -0
- package/dashboard/dist/assets/BVvffj0x.js.br +0 -0
- package/dashboard/dist/assets/BVvffj0x.js.gz +0 -0
- package/dashboard/dist/assets/BiOgVMED.js +1 -0
- package/dashboard/dist/assets/BiOgVMED.js.br +0 -0
- package/dashboard/dist/assets/BiOgVMED.js.gz +0 -0
- package/dashboard/dist/assets/BjK42gtU.js +1 -0
- package/dashboard/dist/assets/BjK42gtU.js.br +0 -0
- package/dashboard/dist/assets/BjK42gtU.js.gz +0 -0
- package/dashboard/dist/assets/C-MOJWHs.js +1 -0
- package/dashboard/dist/assets/C-MOJWHs.js.br +0 -0
- package/dashboard/dist/assets/C-MOJWHs.js.gz +0 -0
- package/dashboard/dist/assets/C91KLKit.js +1 -0
- package/dashboard/dist/assets/C91KLKit.js.br +0 -0
- package/dashboard/dist/assets/C91KLKit.js.gz +0 -0
- package/dashboard/dist/assets/{CnitK1MX.js → C9fvfXmS.js} +1 -1
- package/dashboard/dist/assets/C9fvfXmS.js.br +0 -0
- package/dashboard/dist/assets/C9fvfXmS.js.gz +0 -0
- package/dashboard/dist/assets/CFZ4Swr5.js +1 -0
- package/dashboard/dist/assets/CFZ4Swr5.js.br +0 -0
- package/dashboard/dist/assets/CFZ4Swr5.js.gz +0 -0
- package/dashboard/dist/assets/{77gGFBt6.js → CGj8kRhg.js} +1 -1
- package/dashboard/dist/assets/CGj8kRhg.js.br +0 -0
- package/dashboard/dist/assets/CGj8kRhg.js.gz +0 -0
- package/dashboard/dist/assets/CJjEAGFN.js +1 -0
- package/dashboard/dist/assets/CJjEAGFN.js.br +0 -0
- package/dashboard/dist/assets/CJjEAGFN.js.gz +0 -0
- package/dashboard/dist/assets/CKrH5fYO.js +1 -0
- package/dashboard/dist/assets/CKrH5fYO.js.br +0 -0
- package/dashboard/dist/assets/CKrH5fYO.js.gz +0 -0
- package/dashboard/dist/assets/CMTTPXch.js +1 -0
- package/dashboard/dist/assets/CMTTPXch.js.br +0 -0
- package/dashboard/dist/assets/CMTTPXch.js.gz +0 -0
- package/dashboard/dist/assets/CSlBSRyv.js +1 -0
- package/dashboard/dist/assets/CSlBSRyv.js.br +0 -0
- package/dashboard/dist/assets/CSlBSRyv.js.gz +0 -0
- package/dashboard/dist/assets/CnPC783_.js +1 -0
- package/dashboard/dist/assets/CnPC783_.js.br +0 -0
- package/dashboard/dist/assets/CnPC783_.js.gz +0 -0
- package/dashboard/dist/assets/Ctw95IkC.js +1 -0
- package/dashboard/dist/assets/Ctw95IkC.js.br +0 -0
- package/dashboard/dist/assets/Ctw95IkC.js.gz +0 -0
- package/dashboard/dist/assets/DHz-aQPw.js +1 -0
- package/dashboard/dist/assets/DHz-aQPw.js.br +0 -0
- package/dashboard/dist/assets/DHz-aQPw.js.gz +0 -0
- package/dashboard/dist/assets/DNX2foSJ.css +1 -0
- package/dashboard/dist/assets/DNX2foSJ.css.br +0 -0
- package/dashboard/dist/assets/DNX2foSJ.css.gz +0 -0
- package/dashboard/dist/assets/Dj2k1r16.js +8 -0
- package/dashboard/dist/assets/Dj2k1r16.js.br +0 -0
- package/dashboard/dist/assets/Dj2k1r16.js.gz +0 -0
- package/dashboard/dist/assets/DxUw4FMR.js +212 -0
- package/dashboard/dist/assets/DxUw4FMR.js.br +0 -0
- package/dashboard/dist/assets/DxUw4FMR.js.gz +0 -0
- package/dashboard/dist/assets/T2NFtzAv.js +1 -0
- package/dashboard/dist/assets/T2NFtzAv.js.br +0 -0
- package/dashboard/dist/assets/T2NFtzAv.js.gz +0 -0
- package/dashboard/dist/assets/cX2e-TLi.js +1 -0
- package/dashboard/dist/assets/cX2e-TLi.js.br +0 -0
- package/dashboard/dist/assets/cX2e-TLi.js.gz +0 -0
- package/dashboard/dist/assets/eeHXe_OQ.js +9 -0
- package/dashboard/dist/assets/eeHXe_OQ.js.br +0 -0
- package/dashboard/dist/assets/eeHXe_OQ.js.gz +0 -0
- package/dashboard/dist/assets/{DxKG5zy8.js → gZr_xKlA.js} +2 -2
- package/dashboard/dist/assets/gZr_xKlA.js.br +0 -0
- package/dashboard/dist/assets/gZr_xKlA.js.gz +0 -0
- package/dashboard/dist/brand/control-tower.png +0 -0
- package/dashboard/dist/brand/design-codex.png +0 -0
- package/dashboard/dist/brand/engineering-autopilot.png +0 -0
- package/dashboard/dist/brand/launch-captain.png +0 -0
- package/dashboard/dist/brand/orgx-logo.png +0 -0
- package/dashboard/dist/brand/pipeline-intelligence.png +0 -0
- package/dashboard/dist/brand/product-orchestrator.png +0 -0
- package/dashboard/dist/brand/xandy-orchestrator.png +0 -0
- package/dashboard/dist/index.html +8 -6
- package/dashboard/dist/index.html.br +0 -0
- package/dashboard/dist/index.html.gz +0 -0
- package/dist/hash-utils.d.ts +1 -0
- package/dist/hash-utils.js +4 -0
- package/dist/http/helpers/auto-continue-engine.d.ts +36 -0
- package/dist/http/helpers/auto-continue-engine.js +198 -75
- package/dist/http/helpers/autopilot-runtime.d.ts +1 -0
- package/dist/http/helpers/autopilot-runtime.js +31 -3
- package/dist/http/helpers/autopilot-slice-utils.d.ts +10 -0
- package/dist/http/helpers/autopilot-slice-utils.js +158 -54
- package/dist/http/helpers/hash-utils.d.ts +1 -1
- package/dist/http/helpers/hash-utils.js +1 -1
- package/dist/http/helpers/humanize-slice-failure.d.ts +35 -0
- package/dist/http/helpers/humanize-slice-failure.js +137 -0
- package/dist/http/helpers/mission-control.d.ts +1 -0
- package/dist/http/helpers/mission-control.js +73 -7
- package/dist/http/helpers/queue-constants.d.ts +37 -0
- package/dist/http/helpers/queue-constants.js +34 -0
- package/dist/http/helpers/slice-experience-v2.js +2 -5
- package/dist/http/helpers/slice-run-projections.js +2 -5
- package/dist/http/helpers/workspace-scope.js +4 -3
- package/dist/http/index.js +166 -63
- package/dist/http/routes/chat.js +1 -21
- package/dist/http/routes/live-misc.js +9 -2
- package/dist/http/routes/live-snapshot.js +14 -27
- package/dist/http/routes/mission-control-actions.js +7 -18
- package/dist/http/routes/mission-control-read.d.ts +1 -0
- package/dist/http/routes/mission-control-read.js +14 -56
- package/dist/index.d.ts +8 -1
- package/dist/index.js +21 -1
- package/dist/lib/type-coercion.d.ts +10 -0
- package/dist/lib/type-coercion.js +82 -0
- package/dist/mcp-http-handler.js +14 -2
- package/dist/openclaw.plugin.json +1 -1
- package/dist/services/experiment-randomization.js +9 -2
- package/dist/tools/core-tools.d.ts +27 -0
- package/dist/tools/core-tools.js +89 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +3 -2
- package/dashboard/dist/assets/77gGFBt6.js.br +0 -0
- package/dashboard/dist/assets/77gGFBt6.js.gz +0 -0
- package/dashboard/dist/assets/BBpTN_SR.js +0 -1
- package/dashboard/dist/assets/BBpTN_SR.js.br +0 -0
- package/dashboard/dist/assets/BBpTN_SR.js.gz +0 -0
- package/dashboard/dist/assets/BJgZIVUQ.js +0 -53
- package/dashboard/dist/assets/BJgZIVUQ.js.br +0 -0
- package/dashboard/dist/assets/BJgZIVUQ.js.gz +0 -0
- package/dashboard/dist/assets/BTAEErUY.js +0 -1
- package/dashboard/dist/assets/BTAEErUY.js.br +0 -0
- package/dashboard/dist/assets/BTAEErUY.js.gz +0 -0
- package/dashboard/dist/assets/BVShoyjA.js +0 -1
- package/dashboard/dist/assets/BVShoyjA.js.br +0 -0
- package/dashboard/dist/assets/BVShoyjA.js.gz +0 -0
- package/dashboard/dist/assets/BgcAY5rE.js +0 -1
- package/dashboard/dist/assets/BgcAY5rE.js.br +0 -0
- package/dashboard/dist/assets/BgcAY5rE.js.gz +0 -0
- package/dashboard/dist/assets/C-KIc3Wc.js +0 -1
- package/dashboard/dist/assets/C-KIc3Wc.js.br +0 -0
- package/dashboard/dist/assets/C-KIc3Wc.js.gz +0 -0
- package/dashboard/dist/assets/C-PAoJF-.js +0 -1
- package/dashboard/dist/assets/C-PAoJF-.js.br +0 -0
- package/dashboard/dist/assets/C-PAoJF-.js.gz +0 -0
- package/dashboard/dist/assets/C0nA-iUG.js +0 -1
- package/dashboard/dist/assets/C0nA-iUG.js.br +0 -0
- package/dashboard/dist/assets/C0nA-iUG.js.gz +0 -0
- package/dashboard/dist/assets/C6GO-FKy.js +0 -1
- package/dashboard/dist/assets/C6GO-FKy.js.br +0 -0
- package/dashboard/dist/assets/C6GO-FKy.js.gz +0 -0
- package/dashboard/dist/assets/CFwPph5U.js +0 -1
- package/dashboard/dist/assets/CFwPph5U.js.br +0 -0
- package/dashboard/dist/assets/CFwPph5U.js.gz +0 -0
- package/dashboard/dist/assets/CL_wXqR7.js +0 -1
- package/dashboard/dist/assets/CL_wXqR7.js.br +0 -0
- package/dashboard/dist/assets/CL_wXqR7.js.gz +0 -0
- package/dashboard/dist/assets/CPjsbbgZ.js +0 -212
- package/dashboard/dist/assets/CPjsbbgZ.js.br +0 -0
- package/dashboard/dist/assets/CPjsbbgZ.js.gz +0 -0
- package/dashboard/dist/assets/CSr2ZnTV.js +0 -1
- package/dashboard/dist/assets/CSr2ZnTV.js.br +0 -0
- package/dashboard/dist/assets/CSr2ZnTV.js.gz +0 -0
- package/dashboard/dist/assets/CgQDT6yL.js +0 -1
- package/dashboard/dist/assets/CgQDT6yL.js.br +0 -0
- package/dashboard/dist/assets/CgQDT6yL.js.gz +0 -0
- package/dashboard/dist/assets/CnitK1MX.js.br +0 -0
- package/dashboard/dist/assets/CnitK1MX.js.gz +0 -0
- package/dashboard/dist/assets/CxQ08qFN.js +0 -9
- package/dashboard/dist/assets/CxQ08qFN.js.br +0 -0
- package/dashboard/dist/assets/CxQ08qFN.js.gz +0 -0
- package/dashboard/dist/assets/D7DHFX0D.js +0 -1
- package/dashboard/dist/assets/D7DHFX0D.js.br +0 -0
- package/dashboard/dist/assets/D7DHFX0D.js.gz +0 -0
- package/dashboard/dist/assets/DEip7uko.js +0 -1
- package/dashboard/dist/assets/DEip7uko.js.br +0 -0
- package/dashboard/dist/assets/DEip7uko.js.gz +0 -0
- package/dashboard/dist/assets/DHUSLc01.css +0 -1
- package/dashboard/dist/assets/DHUSLc01.css.br +0 -0
- package/dashboard/dist/assets/DHUSLc01.css.gz +0 -0
- package/dashboard/dist/assets/DOFL9l8s.js +0 -1
- package/dashboard/dist/assets/DOFL9l8s.js.br +0 -0
- package/dashboard/dist/assets/DOFL9l8s.js.gz +0 -0
- package/dashboard/dist/assets/DpuQm1oF.js.br +0 -0
- package/dashboard/dist/assets/DpuQm1oF.js.gz +0 -0
- package/dashboard/dist/assets/DxKG5zy8.js.br +0 -0
- package/dashboard/dist/assets/DxKG5zy8.js.gz +0 -0
- package/dashboard/dist/assets/cNrhgGc1.js +0 -8
- package/dashboard/dist/assets/cNrhgGc1.js.br +0 -0
- package/dashboard/dist/assets/cNrhgGc1.js.gz +0 -0
- package/dashboard/dist/assets/tcEHYcbW.js.br +0 -0
- package/dashboard/dist/assets/tcEHYcbW.js.gz +0 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Canonical state constants for queue, lane, and related enumerations.
|
|
3
|
+
// Use these instead of raw string literals throughout the codebase.
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
/** Queue state for next-up items (workstream-level). */
|
|
6
|
+
export const QueueState = {
|
|
7
|
+
QUEUED: "queued",
|
|
8
|
+
RUNNING: "running",
|
|
9
|
+
BLOCKED: "blocked",
|
|
10
|
+
IDLE: "idle",
|
|
11
|
+
/** Used only in the API normalization layer (mission-control-read.ts). */
|
|
12
|
+
COMPLETED: "completed",
|
|
13
|
+
};
|
|
14
|
+
/** Auto-continue lane state (per-workstream within a run). */
|
|
15
|
+
export const LaneState = {
|
|
16
|
+
IDLE: "idle",
|
|
17
|
+
RUNNING: "running",
|
|
18
|
+
BLOCKED: "blocked",
|
|
19
|
+
WAITING_DEPENDENCY: "waiting_dependency",
|
|
20
|
+
RATE_LIMITED: "rate_limited",
|
|
21
|
+
COMPLETED: "completed",
|
|
22
|
+
};
|
|
23
|
+
/** Auto-continue run status. */
|
|
24
|
+
export const RunStatus = {
|
|
25
|
+
RUNNING: "running",
|
|
26
|
+
STOPPING: "stopping",
|
|
27
|
+
STOPPED: "stopped",
|
|
28
|
+
};
|
|
29
|
+
/** Runner source — how the agent was assigned. */
|
|
30
|
+
export const RunnerSource = {
|
|
31
|
+
ASSIGNED: "assigned",
|
|
32
|
+
INFERRED: "inferred",
|
|
33
|
+
FALLBACK: "fallback",
|
|
34
|
+
};
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
+
import { asRecord } from "../../lib/type-coercion.js";
|
|
1
2
|
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
2
3
|
const GENERIC_ACTOR_IDS = new Set(["main", "unknown", "system", "openclaw", "orgx"]);
|
|
3
|
-
|
|
4
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
5
|
-
return null;
|
|
6
|
-
return value;
|
|
7
|
-
}
|
|
4
|
+
// asRecord imported from ../../lib/type-coercion.js
|
|
8
5
|
function normalizeText(value) {
|
|
9
6
|
if (typeof value !== "string")
|
|
10
7
|
return null;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { asRecord } from "../../lib/type-coercion.js";
|
|
1
2
|
const TERMINAL_STATES = new Set([
|
|
2
3
|
"completed",
|
|
3
4
|
"needs_review",
|
|
@@ -5,11 +6,7 @@ const TERMINAL_STATES = new Set([
|
|
|
5
6
|
"archived",
|
|
6
7
|
]);
|
|
7
8
|
const RUN_LIKE_STATUS = new Set(["dispatching", "running"]);
|
|
8
|
-
|
|
9
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
10
|
-
return null;
|
|
11
|
-
return value;
|
|
12
|
-
}
|
|
9
|
+
// asRecord imported from ../../lib/type-coercion.js
|
|
13
10
|
function normalizeText(value) {
|
|
14
11
|
if (typeof value !== "string")
|
|
15
12
|
return null;
|
|
@@ -70,20 +70,21 @@ export function workspaceScopeFromHeaders(headers) {
|
|
|
70
70
|
"x-orgx-command-center-id",
|
|
71
71
|
"x_orgx_command_center_id",
|
|
72
72
|
]);
|
|
73
|
+
const centerId = readScopeValue(headers, ["center"]);
|
|
73
74
|
if (workspaceId && commandCenterId && workspaceId !== commandCenterId) {
|
|
74
75
|
return {
|
|
75
76
|
workspace_id: workspaceId,
|
|
76
77
|
command_center_id: commandCenterId,
|
|
77
|
-
center: workspaceId,
|
|
78
|
+
center: centerId ?? workspaceId,
|
|
78
79
|
};
|
|
79
80
|
}
|
|
80
|
-
const canonical = workspaceId ?? commandCenterId;
|
|
81
|
+
const canonical = workspaceId ?? commandCenterId ?? centerId;
|
|
81
82
|
if (!canonical)
|
|
82
83
|
return null;
|
|
83
84
|
return {
|
|
84
85
|
workspace_id: canonical,
|
|
85
86
|
command_center_id: canonical,
|
|
86
|
-
center: canonical,
|
|
87
|
+
center: centerId ?? canonical,
|
|
87
88
|
};
|
|
88
89
|
}
|
|
89
90
|
function mergeCandidates(payloadCandidates, queryCandidates) {
|
package/dist/http/index.js
CHANGED
|
@@ -46,10 +46,11 @@ import { summarizeActivityHeadline } from "./helpers/activity-headline.js";
|
|
|
46
46
|
import { createAutoContinueEngine, } from "./helpers/auto-continue-engine.js";
|
|
47
47
|
import { createAutopilotOperations, } from "./helpers/autopilot-operations.js";
|
|
48
48
|
import { mapDecisionEntity } from "./helpers/decision-mapper.js";
|
|
49
|
-
import { idempotencyKey, stableHash } from "./helpers/hash-utils.js";
|
|
49
|
+
import { deterministicActivityId, idempotencyKey, stableHash } from "./helpers/hash-utils.js";
|
|
50
50
|
import { createCodexBinResolver, } from "./helpers/autopilot-slice-utils.js";
|
|
51
51
|
import { createLocalArtifactDetailFallbackBuilder } from "./helpers/artifact-fallback.js";
|
|
52
52
|
import { buildMissionControlGraph, deriveExecutionPolicy, dedupeStrings, isDispatchableWorkstreamStatus, isDoneStatus, isInProgressStatus, isTodoStatus, listEntitiesSafe, normalizeEntityMutationPayload, pickStringArray, resolveAutoAssignments, selectSliceTasksByScope, } from "./helpers/mission-control.js";
|
|
53
|
+
import { QueueState, LaneState, RunStatus, RunnerSource, } from "./helpers/queue-constants.js";
|
|
53
54
|
import { configureOpenClawProviderRouting, fetchBillingStatusSafe, isPidAlive, listOpenClawAgents, listOpenClawProviderModels, modelImpliesByok, normalizeOpenClawProvider, resolveAutoOpenClawProvider, resolveByokEnvOverrides, spawnOpenClawAgentTurn, stopDetachedProcess, } from "./helpers/openclaw-cli.js";
|
|
54
55
|
import { fetchKickoffContextSafe, renderKickoffMessage } from "./helpers/kickoff-context.js";
|
|
55
56
|
import { createDispatchLifecycle } from "./helpers/dispatch-lifecycle.js";
|
|
@@ -106,8 +107,64 @@ async function resolveSkillPackOverrides(input) {
|
|
|
106
107
|
}
|
|
107
108
|
}
|
|
108
109
|
function safeErrorMessage(err) {
|
|
109
|
-
const raw = err instanceof Error
|
|
110
|
-
|
|
110
|
+
const raw = err instanceof Error
|
|
111
|
+
? err.message
|
|
112
|
+
: typeof err === "string"
|
|
113
|
+
? err
|
|
114
|
+
: err && typeof err === "object" && "message" in err && typeof err.message === "string"
|
|
115
|
+
? (err.message ?? "")
|
|
116
|
+
: "";
|
|
117
|
+
const parseStructuredMessage = (value) => {
|
|
118
|
+
const trimmed = value.trim();
|
|
119
|
+
if (!trimmed)
|
|
120
|
+
return null;
|
|
121
|
+
const parseObjectMessage = (parsed) => {
|
|
122
|
+
if (!parsed || typeof parsed !== "object")
|
|
123
|
+
return null;
|
|
124
|
+
const root = parsed;
|
|
125
|
+
const nested = root.error && typeof root.error === "object" ? root.error : null;
|
|
126
|
+
const envelope = nested ?? root;
|
|
127
|
+
return ((typeof envelope.message === "string" && envelope.message.trim()) ||
|
|
128
|
+
(typeof envelope.detail === "string" && envelope.detail.trim()) ||
|
|
129
|
+
(!nested && typeof root.error === "string" && root.error.trim()) ||
|
|
130
|
+
null);
|
|
131
|
+
};
|
|
132
|
+
try {
|
|
133
|
+
const parsed = JSON.parse(trimmed);
|
|
134
|
+
const direct = parseObjectMessage(parsed);
|
|
135
|
+
if (direct)
|
|
136
|
+
return direct;
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// Continue and try extracting embedded JSON payloads.
|
|
140
|
+
}
|
|
141
|
+
const firstBrace = trimmed.indexOf("{");
|
|
142
|
+
const lastBrace = trimmed.lastIndexOf("}");
|
|
143
|
+
if (firstBrace >= 0 && lastBrace > firstBrace) {
|
|
144
|
+
const candidate = trimmed.slice(firstBrace, lastBrace + 1);
|
|
145
|
+
try {
|
|
146
|
+
const parsed = JSON.parse(candidate);
|
|
147
|
+
return parseObjectMessage(parsed);
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return null;
|
|
154
|
+
};
|
|
155
|
+
const stripStructuredNoise = (value) => value
|
|
156
|
+
.replace(/"requestId"\s*:\s*"[^"]*"/gi, "")
|
|
157
|
+
.replace(/"timestamp"\s*:\s*"[^"]*"/gi, "")
|
|
158
|
+
.replace(/"docsUrl"\s*:\s*"[^"]*"/gi, "")
|
|
159
|
+
.replace(/\brequest[_\s-]?id[:=]\s*[\w-]+/gi, "")
|
|
160
|
+
.replace(/\btimestamp[:=]\s*\S+/gi, "")
|
|
161
|
+
.replace(/\bdocsUrl[:=]\s*\S+/gi, "")
|
|
162
|
+
.replace(/[{}]/g, " ")
|
|
163
|
+
.replace(/\s{2,}/g, " ")
|
|
164
|
+
.trim();
|
|
165
|
+
const normalizedMessage = parseStructuredMessage(raw) ?? raw;
|
|
166
|
+
const sanitized = stripStructuredNoise(normalizedMessage);
|
|
167
|
+
const normalized = sanitized.toLowerCase();
|
|
111
168
|
if (normalized.length > 0) {
|
|
112
169
|
if (normalized.includes("signal is aborted") ||
|
|
113
170
|
normalized.includes("aborterror") ||
|
|
@@ -121,7 +178,16 @@ function safeErrorMessage(err) {
|
|
|
121
178
|
if (normalized.includes("failed to fetch") || normalized.includes("network")) {
|
|
122
179
|
return "network request failed";
|
|
123
180
|
}
|
|
124
|
-
|
|
181
|
+
if (normalized.includes("relation does not exist")) {
|
|
182
|
+
return sanitized;
|
|
183
|
+
}
|
|
184
|
+
if (normalized.includes("internal_error") || normalized.includes("internal server error")) {
|
|
185
|
+
return "temporary server issue";
|
|
186
|
+
}
|
|
187
|
+
if (normalized.includes("failed to list decision") || normalized.includes("failed to load decision")) {
|
|
188
|
+
return "decision data temporarily unavailable";
|
|
189
|
+
}
|
|
190
|
+
return sanitized;
|
|
125
191
|
}
|
|
126
192
|
return "Unexpected error";
|
|
127
193
|
}
|
|
@@ -318,6 +384,16 @@ function deriveStructuredActivityBucket(input) {
|
|
|
318
384
|
"nonBlockingDecisionCount",
|
|
319
385
|
]) ?? 0;
|
|
320
386
|
if (event === "autopilot_slice_result") {
|
|
387
|
+
const parsedStatus = typeof metadata?.parsed_status === "string"
|
|
388
|
+
? metadata.parsed_status.trim().toLowerCase()
|
|
389
|
+
: typeof metadata?.parsedStatus === "string"
|
|
390
|
+
? metadata.parsedStatus.trim().toLowerCase()
|
|
391
|
+
: "";
|
|
392
|
+
if (parsedStatus === "completed" && decisionRequired === false) {
|
|
393
|
+
if (artifacts > 0)
|
|
394
|
+
return "artifact";
|
|
395
|
+
return "message";
|
|
396
|
+
}
|
|
321
397
|
// Any blocked slice result needs decision-first surfacing in the Activity UX.
|
|
322
398
|
if (input.phase === "blocked")
|
|
323
399
|
return "decision";
|
|
@@ -650,26 +726,10 @@ function activityMetadataStr(metadata, keys) {
|
|
|
650
726
|
}
|
|
651
727
|
return null;
|
|
652
728
|
}
|
|
653
|
-
const SEMANTIC_ACTIVITY_EVENTS = new Set([
|
|
654
|
-
"autopilot_slice_result",
|
|
655
|
-
"auto_continue_started",
|
|
656
|
-
"auto_continue_stopped",
|
|
657
|
-
"next_up_manual_dispatch_started",
|
|
658
|
-
"autopilot_slice_mcp_handshake_failed",
|
|
659
|
-
"autopilot_slice_timeout",
|
|
660
|
-
"autopilot_slice_log_stall",
|
|
661
|
-
"auto_continue_spawn_guard_blocked",
|
|
662
|
-
"auto_continue_spawn_guard_rate_limited",
|
|
663
|
-
"autopilot_autofix_scheduled",
|
|
664
|
-
"autopilot_autofix_executed",
|
|
665
|
-
"autopilot_autofix_skipped",
|
|
666
|
-
]);
|
|
667
729
|
function semanticActivityKey(item) {
|
|
668
730
|
const metadata = asActivityMetadataRecord(item.metadata);
|
|
669
731
|
const eventRaw = metadata?.event;
|
|
670
732
|
const event = typeof eventRaw === "string" ? eventRaw.trim().toLowerCase() : "";
|
|
671
|
-
if (!event || !SEMANTIC_ACTIVITY_EVENTS.has(event))
|
|
672
|
-
return null;
|
|
673
733
|
const runLike = (typeof item.runId === "string" && item.runId.trim().length > 0
|
|
674
734
|
? item.runId.trim()
|
|
675
735
|
: null) ??
|
|
@@ -693,6 +753,8 @@ function semanticActivityKey(item) {
|
|
|
693
753
|
const stopReason = activityMetadataStr(metadata, ["stop_reason", "stopReason"]);
|
|
694
754
|
const parsedStatus = activityMetadataStr(metadata, ["parsed_status", "parsedStatus"]);
|
|
695
755
|
const title = (item.title ?? "").trim().toLowerCase();
|
|
756
|
+
if (!event && !runLike && !correlationId)
|
|
757
|
+
return null;
|
|
696
758
|
if (!runLike && !correlationId && !workstreamId && !taskId)
|
|
697
759
|
return null;
|
|
698
760
|
return [
|
|
@@ -707,6 +769,27 @@ function semanticActivityKey(item) {
|
|
|
707
769
|
title,
|
|
708
770
|
].join("|");
|
|
709
771
|
}
|
|
772
|
+
function activityRichness(item) {
|
|
773
|
+
let score = 0;
|
|
774
|
+
const meta = item.metadata;
|
|
775
|
+
if (meta)
|
|
776
|
+
score += Object.keys(meta).length;
|
|
777
|
+
if (item.summary)
|
|
778
|
+
score += 2;
|
|
779
|
+
if (item.description)
|
|
780
|
+
score += 2;
|
|
781
|
+
if (item.agentName)
|
|
782
|
+
score += 1;
|
|
783
|
+
if (item.runtimeLabel)
|
|
784
|
+
score += 1;
|
|
785
|
+
if (item.runtimeProvider)
|
|
786
|
+
score += 1;
|
|
787
|
+
if (item.phase)
|
|
788
|
+
score += 1;
|
|
789
|
+
if (item.state)
|
|
790
|
+
score += 1;
|
|
791
|
+
return score;
|
|
792
|
+
}
|
|
710
793
|
function mergeActivities(base, extra, limit) {
|
|
711
794
|
const merged = [...(base ?? []), ...(extra ?? [])].sort((a, b) => {
|
|
712
795
|
const timestampDelta = Date.parse(b.timestamp) - Date.parse(a.timestamp);
|
|
@@ -717,15 +800,28 @@ function mergeActivities(base, extra, limit) {
|
|
|
717
800
|
const deduped = [];
|
|
718
801
|
const seenIds = new Set();
|
|
719
802
|
const seenSemantic = new Set();
|
|
803
|
+
const semanticIdx = new Map();
|
|
720
804
|
for (const item of merged) {
|
|
721
|
-
if (seenIds.has(item.id))
|
|
805
|
+
if (seenIds.has(item.id)) {
|
|
806
|
+
const existingIdx = deduped.findIndex(d => d.id === item.id);
|
|
807
|
+
if (existingIdx >= 0 && activityRichness(item) > activityRichness(deduped[existingIdx])) {
|
|
808
|
+
deduped[existingIdx] = item;
|
|
809
|
+
}
|
|
722
810
|
continue;
|
|
811
|
+
}
|
|
723
812
|
seenIds.add(item.id);
|
|
724
813
|
const sk = semanticActivityKey(item);
|
|
725
|
-
if (sk && seenSemantic.has(sk))
|
|
814
|
+
if (sk && seenSemantic.has(sk)) {
|
|
815
|
+
const existingIdx = semanticIdx.get(sk);
|
|
816
|
+
if (activityRichness(item) > activityRichness(deduped[existingIdx])) {
|
|
817
|
+
deduped[existingIdx] = item;
|
|
818
|
+
}
|
|
726
819
|
continue;
|
|
727
|
-
|
|
820
|
+
}
|
|
821
|
+
if (sk) {
|
|
728
822
|
seenSemantic.add(sk);
|
|
823
|
+
semanticIdx.set(sk, deduped.length);
|
|
824
|
+
}
|
|
729
825
|
deduped.push(item);
|
|
730
826
|
if (deduped.length >= limit)
|
|
731
827
|
break;
|
|
@@ -2111,11 +2207,11 @@ export function createHttpHandler(config, client, getSnapshot, onboarding, diagn
|
|
|
2111
2207
|
initiativeStatusById.set(initiativeId, override.status);
|
|
2112
2208
|
}
|
|
2113
2209
|
const queueRank = (state) => {
|
|
2114
|
-
if (state ===
|
|
2210
|
+
if (state === QueueState.RUNNING)
|
|
2115
2211
|
return 0;
|
|
2116
|
-
if (state ===
|
|
2212
|
+
if (state === QueueState.QUEUED)
|
|
2117
2213
|
return 1;
|
|
2118
|
-
if (state ===
|
|
2214
|
+
if (state === QueueState.BLOCKED)
|
|
2119
2215
|
return 2;
|
|
2120
2216
|
return 3;
|
|
2121
2217
|
};
|
|
@@ -2260,12 +2356,12 @@ export function createHttpHandler(config, client, getSnapshot, onboarding, diagn
|
|
|
2260
2356
|
const hasRunning = statusValues.some((status) => isInProgressStatus(status));
|
|
2261
2357
|
const hasQueued = statusValues.some((status) => status === "queued" || status === "pending");
|
|
2262
2358
|
const queueState = hasRunning
|
|
2263
|
-
?
|
|
2359
|
+
? QueueState.RUNNING
|
|
2264
2360
|
: hasBlocked
|
|
2265
|
-
?
|
|
2361
|
+
? QueueState.BLOCKED
|
|
2266
2362
|
: hasQueued
|
|
2267
|
-
?
|
|
2268
|
-
:
|
|
2363
|
+
? QueueState.QUEUED
|
|
2364
|
+
: QueueState.IDLE;
|
|
2269
2365
|
const latestRunner = [];
|
|
2270
2366
|
const latestRunnerSeen = new Set();
|
|
2271
2367
|
pushRunnerAgent(latestRunner, latestRunnerSeen, {
|
|
@@ -2279,7 +2375,7 @@ export function createHttpHandler(config, client, getSnapshot, onboarding, diagn
|
|
|
2279
2375
|
const runnerAgentId = primaryRunner?.id ?? "unassigned";
|
|
2280
2376
|
const runnerAgentName = primaryRunner?.name ?? "Unassigned";
|
|
2281
2377
|
const pinKey = `${entry.initiativeId}:${entry.workstreamId}`;
|
|
2282
|
-
if (isSuppressed(entry.initiativeId, entry.workstreamId) && queueState !==
|
|
2378
|
+
if (isSuppressed(entry.initiativeId, entry.workstreamId) && queueState !== QueueState.RUNNING) {
|
|
2283
2379
|
continue;
|
|
2284
2380
|
}
|
|
2285
2381
|
fallbackItems.push({
|
|
@@ -2298,7 +2394,7 @@ export function createHttpHandler(config, client, getSnapshot, onboarding, diagn
|
|
|
2298
2394
|
runnerAgentId,
|
|
2299
2395
|
runnerAgentName,
|
|
2300
2396
|
runnerAgents,
|
|
2301
|
-
runnerSource:
|
|
2397
|
+
runnerSource: RunnerSource.FALLBACK,
|
|
2302
2398
|
queueState,
|
|
2303
2399
|
blockReason: hasBlocked
|
|
2304
2400
|
? entry.blockers[0] ??
|
|
@@ -2483,7 +2579,7 @@ export function createHttpHandler(config, client, getSnapshot, onboarding, diagn
|
|
|
2483
2579
|
: [];
|
|
2484
2580
|
const runScopedToCurrentWorkstream = scopedAllowedWorkstreams.length === 1 &&
|
|
2485
2581
|
scopedAllowedWorkstreams[0] === workstream.id &&
|
|
2486
|
-
autoContinueRun?.status ===
|
|
2582
|
+
autoContinueRun?.status === RunStatus.RUNNING;
|
|
2487
2583
|
const activeRunIds = Array.isArray(autoContinueRun?.activeSliceRunIds)
|
|
2488
2584
|
? autoContinueRun.activeSliceRunIds
|
|
2489
2585
|
.filter((id) => typeof id === "string" && id.trim().length > 0)
|
|
@@ -2533,20 +2629,26 @@ export function createHttpHandler(config, client, getSnapshot, onboarding, diagn
|
|
|
2533
2629
|
const sliceMilestoneId = defaultScope === "milestone"
|
|
2534
2630
|
? scopeSelection.milestoneIds[0] ?? pin?.preferredMilestoneId ?? null
|
|
2535
2631
|
: null;
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2632
|
+
// Only mark as "running" when the lane is actively executing a slice.
|
|
2633
|
+
// runScopedToCurrentWorkstream means the initiative run targets this
|
|
2634
|
+
// workstream, but the lane may be idle between slices — don't conflate
|
|
2635
|
+
// "scoped to a running initiative" with "actively executing".
|
|
2636
|
+
const laneIsActivelyRunning = laneState === LaneState.RUNNING ||
|
|
2637
|
+
(runScopedToCurrentWorkstream && activeRunIds.length > 0);
|
|
2638
|
+
let queueState = laneIsActivelyRunning
|
|
2639
|
+
? QueueState.RUNNING
|
|
2640
|
+
: candidateTask
|
|
2641
|
+
? QueueState.QUEUED
|
|
2642
|
+
: runScopedToCurrentWorkstream
|
|
2643
|
+
? QueueState.QUEUED
|
|
2644
|
+
: QueueState.IDLE;
|
|
2543
2645
|
let blockReason = null;
|
|
2544
|
-
if (laneState ===
|
|
2545
|
-
queueState =
|
|
2646
|
+
if (laneState === LaneState.BLOCKED) {
|
|
2647
|
+
queueState = QueueState.BLOCKED;
|
|
2546
2648
|
blockReason = autoContinueLane?.blockedReason ?? "Blocked";
|
|
2547
2649
|
}
|
|
2548
|
-
else if (laneState ===
|
|
2549
|
-
queueState =
|
|
2650
|
+
else if (laneState === LaneState.WAITING_DEPENDENCY) {
|
|
2651
|
+
queueState = QueueState.BLOCKED;
|
|
2550
2652
|
if (Array.isArray(autoContinueLane?.waitingOnWorkstreamIds) &&
|
|
2551
2653
|
autoContinueLane.waitingOnWorkstreamIds.length > 0) {
|
|
2552
2654
|
const waitingTitles = autoContinueLane.waitingOnWorkstreamIds
|
|
@@ -2564,12 +2666,12 @@ export function createHttpHandler(config, client, getSnapshot, onboarding, diagn
|
|
|
2564
2666
|
blockReason = "Waiting on dependency workstreams";
|
|
2565
2667
|
}
|
|
2566
2668
|
}
|
|
2567
|
-
else if (laneState ===
|
|
2568
|
-
queueState =
|
|
2669
|
+
else if (laneState === LaneState.RATE_LIMITED) {
|
|
2670
|
+
queueState = QueueState.BLOCKED;
|
|
2569
2671
|
blockReason = autoContinueLane?.blockedReason ?? "Rate-limited";
|
|
2570
2672
|
}
|
|
2571
2673
|
if (!autoContinueRun && !readyTask && candidateTask) {
|
|
2572
|
-
queueState =
|
|
2674
|
+
queueState = QueueState.BLOCKED;
|
|
2573
2675
|
const blockedDeps = candidateTask.dependencyIds
|
|
2574
2676
|
.map((depId) => nodeById.get(depId))
|
|
2575
2677
|
.filter((dependency) => Boolean(dependency && !isDoneStatus(dependency.status)))
|
|
@@ -2587,7 +2689,7 @@ export function createHttpHandler(config, client, getSnapshot, onboarding, diagn
|
|
|
2587
2689
|
if (!candidateTask && !autoContinueRun && !pin) {
|
|
2588
2690
|
continue;
|
|
2589
2691
|
}
|
|
2590
|
-
if (isSuppressed(initiativeId, workstream.id) && queueState !==
|
|
2692
|
+
if (isSuppressed(initiativeId, workstream.id) && queueState !== QueueState.RUNNING) {
|
|
2591
2693
|
continue;
|
|
2592
2694
|
}
|
|
2593
2695
|
runningWorkstreams.add(workstream.id);
|
|
@@ -2622,10 +2724,10 @@ export function createHttpHandler(config, client, getSnapshot, onboarding, diagn
|
|
|
2622
2724
|
}
|
|
2623
2725
|
const runnerAgents = assignedRunnerAgents.length > 0 ? assignedRunnerAgents : inferredRunnerAgents;
|
|
2624
2726
|
const runnerSource = assignedRunnerAgents.length > 0
|
|
2625
|
-
?
|
|
2727
|
+
? RunnerSource.ASSIGNED
|
|
2626
2728
|
: runnerAgents.length > 0
|
|
2627
|
-
?
|
|
2628
|
-
:
|
|
2729
|
+
? RunnerSource.INFERRED
|
|
2730
|
+
: RunnerSource.FALLBACK;
|
|
2629
2731
|
const primaryRunner = runnerAgents[0] ?? null;
|
|
2630
2732
|
const runnerAgentId = primaryRunner?.id ?? "unassigned";
|
|
2631
2733
|
const runnerAgentName = primaryRunner?.name ?? "Unassigned";
|
|
@@ -2719,14 +2821,14 @@ export function createHttpHandler(config, client, getSnapshot, onboarding, diagn
|
|
|
2719
2821
|
: activeTaskId
|
|
2720
2822
|
? [activeTaskId]
|
|
2721
2823
|
: [];
|
|
2722
|
-
const queueState = laneState ===
|
|
2723
|
-
?
|
|
2724
|
-
: laneState ===
|
|
2725
|
-
laneState ===
|
|
2726
|
-
laneState ===
|
|
2727
|
-
?
|
|
2728
|
-
:
|
|
2729
|
-
if (isSuppressed(initiativeId, workstream.id) && queueState !==
|
|
2824
|
+
const queueState = laneState === LaneState.RUNNING
|
|
2825
|
+
? QueueState.RUNNING
|
|
2826
|
+
: laneState === LaneState.BLOCKED ||
|
|
2827
|
+
laneState === LaneState.WAITING_DEPENDENCY ||
|
|
2828
|
+
laneState === LaneState.RATE_LIMITED
|
|
2829
|
+
? QueueState.BLOCKED
|
|
2830
|
+
: QueueState.QUEUED;
|
|
2831
|
+
if (isSuppressed(initiativeId, workstream.id) && queueState !== QueueState.RUNNING) {
|
|
2730
2832
|
continue;
|
|
2731
2833
|
}
|
|
2732
2834
|
const runRunnerAgents = [];
|
|
@@ -2752,9 +2854,9 @@ export function createHttpHandler(config, client, getSnapshot, onboarding, diagn
|
|
|
2752
2854
|
runnerAgentId: runPrimaryRunner?.id ?? "unassigned",
|
|
2753
2855
|
runnerAgentName: runPrimaryRunner?.name ?? "Unassigned",
|
|
2754
2856
|
runnerAgents: runRunnerAgents,
|
|
2755
|
-
runnerSource: runPrimaryRunner ?
|
|
2857
|
+
runnerSource: runPrimaryRunner ? RunnerSource.INFERRED : RunnerSource.FALLBACK,
|
|
2756
2858
|
queueState,
|
|
2757
|
-
blockReason: queueState ===
|
|
2859
|
+
blockReason: queueState === QueueState.BLOCKED
|
|
2758
2860
|
? lane?.blockedReason ?? "Blocked"
|
|
2759
2861
|
: null,
|
|
2760
2862
|
isPinned: Boolean(pinnedByKey.get(`${initiativeId}:${workstream.id}`)),
|
|
@@ -3178,10 +3280,11 @@ export function createHttpHandler(config, client, getSnapshot, onboarding, diagn
|
|
|
3178
3280
|
broadcastRuntimeSse("runtime.updated", runtimeRecord);
|
|
3179
3281
|
}
|
|
3180
3282
|
clearSnapshotResponseCache();
|
|
3283
|
+
const activityId = deterministicActivityId("run_completed", normalizedRunId, nowIso, runtimeRecord?.agentId ?? existingRun?.agentId ?? null, "dashboard_run_mark_completed");
|
|
3181
3284
|
try {
|
|
3182
3285
|
appendActivityItems([
|
|
3183
3286
|
{
|
|
3184
|
-
id:
|
|
3287
|
+
id: activityId,
|
|
3185
3288
|
type: "run_completed",
|
|
3186
3289
|
title: message,
|
|
3187
3290
|
description: reason,
|
|
@@ -3213,7 +3316,7 @@ export function createHttpHandler(config, client, getSnapshot, onboarding, diagn
|
|
|
3213
3316
|
try {
|
|
3214
3317
|
const outboxSessionId = runtimeRecord?.initiativeId ?? existingRun?.initiativeId ?? normalizedRunId;
|
|
3215
3318
|
const outboxActivityItem = {
|
|
3216
|
-
id:
|
|
3319
|
+
id: activityId,
|
|
3217
3320
|
type: "run_completed",
|
|
3218
3321
|
title: message,
|
|
3219
3322
|
description: reason,
|
package/dist/http/routes/chat.js
CHANGED
|
@@ -1,25 +1,5 @@
|
|
|
1
1
|
import { getChatThread, linkChatThreadScope, listChatThreads, recordChatLaunch, sendChatMessage, updateChatLaunchStatus, } from "../../chat-store.js";
|
|
2
|
-
|
|
3
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
4
|
-
return null;
|
|
5
|
-
return value;
|
|
6
|
-
}
|
|
7
|
-
function asStringArray(value) {
|
|
8
|
-
if (!Array.isArray(value))
|
|
9
|
-
return [];
|
|
10
|
-
const out = [];
|
|
11
|
-
const seen = new Set();
|
|
12
|
-
for (const entry of value) {
|
|
13
|
-
if (typeof entry !== "string")
|
|
14
|
-
continue;
|
|
15
|
-
const trimmed = entry.trim();
|
|
16
|
-
if (!trimmed || seen.has(trimmed))
|
|
17
|
-
continue;
|
|
18
|
-
seen.add(trimmed);
|
|
19
|
-
out.push(trimmed);
|
|
20
|
-
}
|
|
21
|
-
return out;
|
|
22
|
-
}
|
|
2
|
+
import { asRecord, asStringArray } from "../../lib/type-coercion.js";
|
|
23
3
|
function normalizeStatus(value) {
|
|
24
4
|
const normalized = (value ?? "").trim().toLowerCase();
|
|
25
5
|
if (normalized === "requested" ||
|
|
@@ -31,8 +31,15 @@ export function registerLiveMiscRoutes(router, deps) {
|
|
|
31
31
|
const projectId = projectIdRaw?.trim() ?? "";
|
|
32
32
|
if (!projectId)
|
|
33
33
|
return null;
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
try {
|
|
35
|
+
const ids = await deps.listInitiativeIdsForProject({ projectId });
|
|
36
|
+
return new Set(ids);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// Scope discovery is best-effort. Continue with unscoped fallback data
|
|
40
|
+
// instead of hard-failing live surfaces.
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
36
43
|
}
|
|
37
44
|
router.add("POST", "live/activity/headline", async ({ req, res }) => {
|
|
38
45
|
try {
|
|
@@ -13,7 +13,7 @@ const LIVE_SNAPSHOT_UPSTREAM_TIMEOUT_MS = (() => {
|
|
|
13
13
|
const LIVE_SNAPSHOT_NEXT_UP_TIMEOUT_MS = (() => {
|
|
14
14
|
const raw = Number(process.env.ORGX_LIVE_SNAPSHOT_NEXT_UP_TIMEOUT_MS ?? "");
|
|
15
15
|
if (!Number.isFinite(raw))
|
|
16
|
-
return
|
|
16
|
+
return 350;
|
|
17
17
|
return Math.max(250, Math.min(15_000, Math.floor(raw)));
|
|
18
18
|
})();
|
|
19
19
|
async function withSoftTimeout(work, timeoutMs, label) {
|
|
@@ -280,9 +280,15 @@ export function registerLiveSnapshotRoutes(router, deps) {
|
|
|
280
280
|
const agentContexts = contextStore.agents;
|
|
281
281
|
const runContexts = contextStore.runs ?? {};
|
|
282
282
|
const scopedAgentIds = deps.getScopedAgentIds(agentContexts);
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
283
|
+
let scopedProjectInitiativeIds = null;
|
|
284
|
+
if (projectId && projectId.trim().length > 0) {
|
|
285
|
+
try {
|
|
286
|
+
scopedProjectInitiativeIds = new Set(await deps.listInitiativeIdsForProject({ projectId: projectId.trim() }));
|
|
287
|
+
}
|
|
288
|
+
catch (err) {
|
|
289
|
+
degraded.push(`workspace initiative scope unavailable (${deps.safeErrorMessage(err)})`);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
286
292
|
let outboxStatus;
|
|
287
293
|
try {
|
|
288
294
|
const diagnosticsOutbox = await deps.readDiagnosticsOutboxStatus();
|
|
@@ -444,29 +450,7 @@ export function registerLiveSnapshotRoutes(router, deps) {
|
|
|
444
450
|
try {
|
|
445
451
|
const buffered = await deps.readOutboxItems();
|
|
446
452
|
if (buffered.length > 0) {
|
|
447
|
-
|
|
448
|
-
.sort((a, b) => {
|
|
449
|
-
const d = Date.parse(b.timestamp) - Date.parse(a.timestamp);
|
|
450
|
-
if (d !== 0)
|
|
451
|
-
return d;
|
|
452
|
-
return b.id.localeCompare(a.id);
|
|
453
|
-
})
|
|
454
|
-
.slice(0, activityLimit);
|
|
455
|
-
const deduped = [];
|
|
456
|
-
const seenIds = new Set();
|
|
457
|
-
const seenSemantic = new Set();
|
|
458
|
-
for (const item of merged) {
|
|
459
|
-
if (seenIds.has(item.id))
|
|
460
|
-
continue;
|
|
461
|
-
seenIds.add(item.id);
|
|
462
|
-
const sk = deps.semanticActivityKey(item);
|
|
463
|
-
if (sk && seenSemantic.has(sk))
|
|
464
|
-
continue;
|
|
465
|
-
if (sk)
|
|
466
|
-
seenSemantic.add(sk);
|
|
467
|
-
deduped.push(item);
|
|
468
|
-
}
|
|
469
|
-
activity = deduped;
|
|
453
|
+
activity = deps.mergeActivities(activity, buffered, activityLimit);
|
|
470
454
|
}
|
|
471
455
|
}
|
|
472
456
|
catch (err) {
|
|
@@ -494,6 +478,9 @@ export function registerLiveSnapshotRoutes(router, deps) {
|
|
|
494
478
|
agents: agentContexts,
|
|
495
479
|
runs: runContexts,
|
|
496
480
|
});
|
|
481
|
+
// Final dedup pass after enrichment — catches items that became
|
|
482
|
+
// semantically identical after runtime/agent context decoration.
|
|
483
|
+
activity = deps.mergeActivities(activity, [], activityLimit);
|
|
497
484
|
activity = activity.filter((item) => !shouldHideActivityItem(item));
|
|
498
485
|
sessions = normalizeReportingBlockedSessions({
|
|
499
486
|
sessions,
|