@useorgx/openclaw-plugin 0.4.9 → 0.7.0

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.
Files changed (222) hide show
  1. package/README.md +35 -0
  2. package/dashboard/dist/assets/BJgZIVUQ.js +53 -0
  3. package/dashboard/dist/assets/BJgZIVUQ.js.br +0 -0
  4. package/dashboard/dist/assets/BJgZIVUQ.js.gz +0 -0
  5. package/dashboard/dist/assets/BXWDRGm-.js +1 -0
  6. package/dashboard/dist/assets/BXWDRGm-.js.br +0 -0
  7. package/dashboard/dist/assets/BXWDRGm-.js.gz +0 -0
  8. package/dashboard/dist/assets/BgOYB78t.js +4 -0
  9. package/dashboard/dist/assets/BgOYB78t.js.br +0 -0
  10. package/dashboard/dist/assets/BgOYB78t.js.gz +0 -0
  11. package/dashboard/dist/assets/C-KIc3Wc.js.br +0 -0
  12. package/dashboard/dist/assets/C-KIc3Wc.js.gz +0 -0
  13. package/dashboard/dist/assets/CE38zU4U.js +1 -0
  14. package/dashboard/dist/assets/CE38zU4U.js.br +0 -0
  15. package/dashboard/dist/assets/CE38zU4U.js.gz +0 -0
  16. package/dashboard/dist/assets/CFGKRAzG.js +1 -0
  17. package/dashboard/dist/assets/CFGKRAzG.js.br +0 -0
  18. package/dashboard/dist/assets/CFGKRAzG.js.gz +0 -0
  19. package/dashboard/dist/assets/CGGR2GZh.js +1 -0
  20. package/dashboard/dist/assets/CGGR2GZh.js.br +0 -0
  21. package/dashboard/dist/assets/CGGR2GZh.js.gz +0 -0
  22. package/dashboard/dist/assets/CL_wXqR7.js +1 -0
  23. package/dashboard/dist/assets/CL_wXqR7.js.br +0 -0
  24. package/dashboard/dist/assets/CL_wXqR7.js.gz +0 -0
  25. package/dashboard/dist/assets/CPFiTmlw.js +8 -0
  26. package/dashboard/dist/assets/CPFiTmlw.js.br +0 -0
  27. package/dashboard/dist/assets/CPFiTmlw.js.gz +0 -0
  28. package/dashboard/dist/assets/CZZTvkQZ.js +1 -0
  29. package/dashboard/dist/assets/CZZTvkQZ.js.br +0 -0
  30. package/dashboard/dist/assets/CZZTvkQZ.js.gz +0 -0
  31. package/dashboard/dist/assets/{CpJsfbXo.js → CxQ08qFN.js} +2 -2
  32. package/dashboard/dist/assets/CxQ08qFN.js.br +0 -0
  33. package/dashboard/dist/assets/CxQ08qFN.js.gz +0 -0
  34. package/dashboard/dist/assets/D-bf6hEI.js +213 -0
  35. package/dashboard/dist/assets/D-bf6hEI.js.br +0 -0
  36. package/dashboard/dist/assets/D-bf6hEI.js.gz +0 -0
  37. package/dashboard/dist/assets/DG6y9wJI.js +2 -0
  38. package/dashboard/dist/assets/DG6y9wJI.js.br +0 -0
  39. package/dashboard/dist/assets/DG6y9wJI.js.gz +0 -0
  40. package/dashboard/dist/assets/DNxKz-GV.js +1 -0
  41. package/dashboard/dist/assets/DNxKz-GV.js.br +0 -0
  42. package/dashboard/dist/assets/DNxKz-GV.js.gz +0 -0
  43. package/dashboard/dist/assets/DW_rKUic.js +11 -0
  44. package/dashboard/dist/assets/DW_rKUic.js.br +0 -0
  45. package/dashboard/dist/assets/DW_rKUic.js.gz +0 -0
  46. package/dashboard/dist/assets/DbNoijHm.js +1 -0
  47. package/dashboard/dist/assets/DbNoijHm.js.br +0 -0
  48. package/dashboard/dist/assets/DbNoijHm.js.gz +0 -0
  49. package/dashboard/dist/assets/DjcdE6jC.js +2 -0
  50. package/dashboard/dist/assets/DjcdE6jC.js.br +0 -0
  51. package/dashboard/dist/assets/DjcdE6jC.js.gz +0 -0
  52. package/dashboard/dist/assets/FZYuCDnt.js +1 -0
  53. package/dashboard/dist/assets/FZYuCDnt.js.br +0 -0
  54. package/dashboard/dist/assets/FZYuCDnt.js.gz +0 -0
  55. package/dashboard/dist/assets/PAUiij_z.js +1 -0
  56. package/dashboard/dist/assets/PAUiij_z.js.br +0 -0
  57. package/dashboard/dist/assets/PAUiij_z.js.gz +0 -0
  58. package/dashboard/dist/assets/cNrhgGc1.js +8 -0
  59. package/dashboard/dist/assets/cNrhgGc1.js.br +0 -0
  60. package/dashboard/dist/assets/cNrhgGc1.js.gz +0 -0
  61. package/dashboard/dist/assets/h5biQs2I.css +1 -0
  62. package/dashboard/dist/assets/h5biQs2I.css.br +0 -0
  63. package/dashboard/dist/assets/h5biQs2I.css.gz +0 -0
  64. package/dashboard/dist/assets/ic2FaMnh.js +1 -0
  65. package/dashboard/dist/assets/ic2FaMnh.js.br +0 -0
  66. package/dashboard/dist/assets/ic2FaMnh.js.gz +0 -0
  67. package/dashboard/dist/assets/nByHNHoW.js +1 -0
  68. package/dashboard/dist/assets/nByHNHoW.js.br +0 -0
  69. package/dashboard/dist/assets/nByHNHoW.js.gz +0 -0
  70. package/dashboard/dist/assets/qm8xLgv-.css +1 -0
  71. package/dashboard/dist/assets/qm8xLgv-.css.br +0 -0
  72. package/dashboard/dist/assets/qm8xLgv-.css.gz +0 -0
  73. package/dashboard/dist/assets/tS9mbYZi.js +1 -0
  74. package/dashboard/dist/assets/tS9mbYZi.js.br +0 -0
  75. package/dashboard/dist/assets/tS9mbYZi.js.gz +0 -0
  76. package/dashboard/dist/brand/anthropic-mark.svg.br +0 -0
  77. package/dashboard/dist/brand/anthropic-mark.svg.gz +0 -0
  78. package/dashboard/dist/brand/openai-mark.svg.br +0 -0
  79. package/dashboard/dist/brand/openai-mark.svg.gz +0 -0
  80. package/dashboard/dist/brand/openclaw-mark.svg.br +0 -0
  81. package/dashboard/dist/brand/openclaw-mark.svg.gz +0 -0
  82. package/dashboard/dist/brand/xandy-orchestrator.png +0 -0
  83. package/dashboard/dist/index.html +7 -5
  84. package/dashboard/dist/index.html.br +0 -0
  85. package/dashboard/dist/index.html.gz +0 -0
  86. package/dist/activity-actor-fields.js +26 -4
  87. package/dist/activity-store.js +34 -8
  88. package/dist/agent-context-store.js +79 -17
  89. package/dist/agent-run-store.js +44 -3
  90. package/dist/agent-suite.d.ts +9 -0
  91. package/dist/agent-suite.js +149 -9
  92. package/dist/artifacts/artifact-domain-schemas.d.ts +66 -0
  93. package/dist/artifacts/artifact-domain-schemas.js +357 -0
  94. package/dist/artifacts/register-artifact.d.ts +4 -3
  95. package/dist/artifacts/register-artifact.js +170 -57
  96. package/dist/chat-store.d.ts +157 -0
  97. package/dist/chat-store.js +586 -0
  98. package/dist/cli/orgx.js +11 -0
  99. package/dist/contracts/client.d.ts +43 -3
  100. package/dist/contracts/client.js +159 -30
  101. package/dist/contracts/retro-schema.d.ts +81 -0
  102. package/dist/contracts/retro-schema.js +80 -0
  103. package/dist/contracts/shared-types.d.ts +159 -0
  104. package/dist/contracts/shared-types.js +177 -1
  105. package/dist/contracts/skill-pack-schema.d.ts +192 -0
  106. package/dist/contracts/skill-pack-schema.js +180 -0
  107. package/dist/contracts/types.d.ts +227 -2
  108. package/dist/entities/auto-assignment.js +43 -17
  109. package/dist/event-sanitization.d.ts +11 -0
  110. package/dist/event-sanitization.js +113 -0
  111. package/dist/fs-utils.js +13 -1
  112. package/dist/gateway-watchdog.d.ts +5 -0
  113. package/dist/gateway-watchdog.js +50 -0
  114. package/dist/hooks/post-reporting-event.mjs +1 -5
  115. package/dist/http/helpers/activity-headline.js +13 -132
  116. package/dist/http/helpers/auto-continue-engine.d.ts +198 -10
  117. package/dist/http/helpers/auto-continue-engine.js +2531 -186
  118. package/dist/http/helpers/autopilot-operations.d.ts +19 -0
  119. package/dist/http/helpers/autopilot-operations.js +182 -31
  120. package/dist/http/helpers/autopilot-runtime.d.ts +1 -0
  121. package/dist/http/helpers/autopilot-runtime.js +308 -20
  122. package/dist/http/helpers/autopilot-slice-utils.d.ts +18 -0
  123. package/dist/http/helpers/autopilot-slice-utils.js +516 -93
  124. package/dist/http/helpers/decision-mapper.d.ts +40 -0
  125. package/dist/http/helpers/decision-mapper.js +223 -7
  126. package/dist/http/helpers/dispatch-lifecycle.d.ts +19 -2
  127. package/dist/http/helpers/dispatch-lifecycle.js +242 -37
  128. package/dist/http/helpers/kickoff-context.js +74 -0
  129. package/dist/http/helpers/llm-client.d.ts +47 -0
  130. package/dist/http/helpers/llm-client.js +256 -0
  131. package/dist/http/helpers/mission-control.d.ts +102 -3
  132. package/dist/http/helpers/mission-control.js +498 -9
  133. package/dist/http/helpers/sentinel-catalog.d.ts +23 -0
  134. package/dist/http/helpers/sentinel-catalog.js +193 -0
  135. package/dist/http/helpers/session-classification.d.ts +9 -0
  136. package/dist/http/helpers/session-classification.js +564 -0
  137. package/dist/http/helpers/slice-experience-v2.d.ts +137 -0
  138. package/dist/http/helpers/slice-experience-v2.js +677 -0
  139. package/dist/http/helpers/slice-run-projections.d.ts +72 -0
  140. package/dist/http/helpers/slice-run-projections.js +860 -0
  141. package/dist/http/helpers/triage-mapper.d.ts +43 -0
  142. package/dist/http/helpers/triage-mapper.js +549 -0
  143. package/dist/http/helpers/value-utils.js +7 -2
  144. package/dist/http/helpers/workspace-scope.d.ts +15 -0
  145. package/dist/http/helpers/workspace-scope.js +170 -0
  146. package/dist/http/index.js +1354 -97
  147. package/dist/http/routes/agent-suite.d.ts +9 -0
  148. package/dist/http/routes/agent-suite.js +207 -8
  149. package/dist/http/routes/agents-catalog.js +64 -19
  150. package/dist/http/routes/chat.d.ts +19 -0
  151. package/dist/http/routes/chat.js +522 -0
  152. package/dist/http/routes/decision-actions.d.ts +8 -1
  153. package/dist/http/routes/decision-actions.js +42 -5
  154. package/dist/http/routes/dispatch-gateway-envelope.d.ts +25 -0
  155. package/dist/http/routes/dispatch-gateway-envelope.js +26 -0
  156. package/dist/http/routes/entities.d.ts +16 -0
  157. package/dist/http/routes/entities.js +294 -6
  158. package/dist/http/routes/live-legacy.d.ts +5 -0
  159. package/dist/http/routes/live-legacy.js +23 -509
  160. package/dist/http/routes/live-misc.d.ts +12 -0
  161. package/dist/http/routes/live-misc.js +251 -31
  162. package/dist/http/routes/live-snapshot.d.ts +48 -2
  163. package/dist/http/routes/live-snapshot.js +638 -19
  164. package/dist/http/routes/live-terminal.d.ts +11 -0
  165. package/dist/http/routes/live-terminal.js +261 -0
  166. package/dist/http/routes/live-triage.d.ts +61 -0
  167. package/dist/http/routes/live-triage.js +248 -0
  168. package/dist/http/routes/mission-control-actions.d.ts +49 -1
  169. package/dist/http/routes/mission-control-actions.js +1334 -84
  170. package/dist/http/routes/mission-control-read.d.ts +48 -3
  171. package/dist/http/routes/mission-control-read.js +1593 -20
  172. package/dist/http/routes/realtime-orchestrator.d.ts +10 -0
  173. package/dist/http/routes/realtime-orchestrator.js +74 -0
  174. package/dist/http/routes/run-control.d.ts +5 -2
  175. package/dist/http/routes/run-control.js +10 -0
  176. package/dist/http/routes/sentinels-catalog.d.ts +7 -0
  177. package/dist/http/routes/sentinels-catalog.js +24 -0
  178. package/dist/http/routes/summary.js +10 -3
  179. package/dist/http/routes/usage.d.ts +24 -0
  180. package/dist/http/routes/usage.js +362 -0
  181. package/dist/http/routes/work-artifacts.js +28 -9
  182. package/dist/index.js +165 -27
  183. package/dist/local-openclaw.js +29 -6
  184. package/dist/mcp-client-setup.js +3 -3
  185. package/dist/mcp-http-handler.js +33 -59
  186. package/dist/next-up-queue-store.d.ts +16 -1
  187. package/dist/next-up-queue-store.js +89 -7
  188. package/dist/outbox.d.ts +5 -0
  189. package/dist/outbox.js +113 -9
  190. package/dist/paths.js +24 -5
  191. package/dist/reporting/rollups.d.ts +53 -0
  192. package/dist/reporting/rollups.js +148 -0
  193. package/dist/retro/domain-templates.d.ts +45 -0
  194. package/dist/retro/domain-templates.js +297 -0
  195. package/dist/retro/quality-rubric.d.ts +33 -0
  196. package/dist/retro/quality-rubric.js +213 -0
  197. package/dist/runtime-cleanup.d.ts +18 -0
  198. package/dist/runtime-cleanup.js +87 -0
  199. package/dist/services/background.d.ts +11 -0
  200. package/dist/services/background.js +22 -0
  201. package/dist/services/experiment-randomization.d.ts +21 -0
  202. package/dist/services/experiment-randomization.js +63 -0
  203. package/dist/skill-pack-state.d.ts +36 -5
  204. package/dist/skill-pack-state.js +273 -29
  205. package/dist/sync/local-agent-telemetry.d.ts +13 -0
  206. package/dist/sync/local-agent-telemetry.js +128 -0
  207. package/dist/sync/outbox-replay.js +131 -24
  208. package/dist/team-context-store.d.ts +23 -0
  209. package/dist/team-context-store.js +116 -0
  210. package/dist/telemetry/posthog.js +4 -2
  211. package/dist/tools/core-tools.d.ts +10 -14
  212. package/dist/tools/core-tools.js +1289 -24
  213. package/dist/types.d.ts +2 -0
  214. package/dist/types.js +2 -0
  215. package/dist/worker-supervisor.js +23 -0
  216. package/package.json +14 -4
  217. package/dashboard/dist/assets/B3ziCA02.js +0 -8
  218. package/dashboard/dist/assets/B5NEElEI.css +0 -1
  219. package/dashboard/dist/assets/BhapSNAs.js +0 -215
  220. package/dashboard/dist/assets/iFdvE7lx.js +0 -1
  221. package/dashboard/dist/assets/jRJsmpYM.js +0 -1
  222. package/dashboard/dist/assets/sAhvFnpk.js +0 -4
@@ -0,0 +1,256 @@
1
+ /**
2
+ * Shared LLM client for classification, summarization, and generation tasks.
3
+ *
4
+ * Generalizes the pattern from activity-headline.ts into a reusable client
5
+ * with in-memory caching, timeout, and heuristic fallback.
6
+ */
7
+ import { createHash } from "node:crypto";
8
+ import { pickString } from "./value-utils.js";
9
+ // ---------------------------------------------------------------------------
10
+ // Configuration
11
+ // ---------------------------------------------------------------------------
12
+ const DEFAULT_MODEL = "openai/gpt-4.1-nano";
13
+ const DEFAULT_GENERATION_MODEL = "openai/gpt-4.1-mini";
14
+ const DEFAULT_TIMEOUT_MS = 4_000;
15
+ const DEFAULT_CACHE_TTL_MS = 12 * 60 * 60_000; // 12 hours
16
+ const CACHE_MAX_ENTRIES = 2_000;
17
+ const OPENROUTER_URL = "https://openrouter.ai/api/v1/chat/completions";
18
+ const cache = new Map();
19
+ function cacheKey(taskId, content) {
20
+ return `${taskId}:${createHash("sha256").update(content).digest("hex")}`;
21
+ }
22
+ function trimCache() {
23
+ while (cache.size > CACHE_MAX_ENTRIES) {
24
+ const firstKey = cache.keys().next().value;
25
+ if (!firstKey)
26
+ break;
27
+ cache.delete(firstKey);
28
+ }
29
+ }
30
+ function getCached(key) {
31
+ const entry = cache.get(key);
32
+ if (entry && entry.expiresAt > Date.now())
33
+ return entry;
34
+ if (entry)
35
+ cache.delete(key);
36
+ return null;
37
+ }
38
+ function setCached(key, value, source, ttlMs) {
39
+ if (ttlMs <= 0)
40
+ return;
41
+ cache.set(key, { value, source, expiresAt: Date.now() + ttlMs });
42
+ trimCache();
43
+ }
44
+ // ---------------------------------------------------------------------------
45
+ // API key resolution
46
+ // ---------------------------------------------------------------------------
47
+ let resolvedApiKey;
48
+ export function resolveApiKey() {
49
+ if (resolvedApiKey !== undefined)
50
+ return resolvedApiKey;
51
+ const candidates = [
52
+ process.env.ORGX_LLM_API_KEY ?? "",
53
+ process.env.ORGX_ACTIVITY_SUMMARY_API_KEY ?? "",
54
+ process.env.OPENROUTER_API_KEY ?? "",
55
+ ];
56
+ const key = candidates.find((c) => c.trim().length > 0)?.trim() ?? "";
57
+ resolvedApiKey = key || null;
58
+ return resolvedApiKey;
59
+ }
60
+ /** Reset cached key (for testing or key rotation). */
61
+ export function resetApiKeyCache() {
62
+ resolvedApiKey = undefined;
63
+ }
64
+ // ---------------------------------------------------------------------------
65
+ // OpenRouter completion
66
+ // ---------------------------------------------------------------------------
67
+ function extractCompletionText(payload) {
68
+ const choices = payload.choices;
69
+ if (!Array.isArray(choices) || choices.length === 0)
70
+ return null;
71
+ const first = choices[0];
72
+ if (!first || typeof first !== "object")
73
+ return null;
74
+ const firstRecord = first;
75
+ const message = firstRecord.message;
76
+ if (message && typeof message === "object") {
77
+ const content = message.content;
78
+ if (typeof content === "string")
79
+ return content;
80
+ if (Array.isArray(content)) {
81
+ const textParts = content
82
+ .map((part) => {
83
+ if (typeof part === "string")
84
+ return part;
85
+ if (!part || typeof part !== "object")
86
+ return "";
87
+ const record = part;
88
+ return typeof record.text === "string" ? record.text : "";
89
+ })
90
+ .filter((part) => part.length > 0);
91
+ if (textParts.length > 0)
92
+ return textParts.join(" ");
93
+ }
94
+ }
95
+ return pickString(firstRecord, ["text", "content"]);
96
+ }
97
+ // ---------------------------------------------------------------------------
98
+ // Public API: text completion
99
+ // ---------------------------------------------------------------------------
100
+ /**
101
+ * Call LLM for a text completion with automatic caching and heuristic fallback.
102
+ *
103
+ * @param request - The LLM request configuration
104
+ * @param fallback - Heuristic fallback that produces a result when LLM is unavailable
105
+ * @param parse - Optional transform on the raw LLM text (default: identity)
106
+ */
107
+ export async function callLlm(request, fallback, parse) {
108
+ const ttl = request.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;
109
+ const key = cacheKey(request.taskId, `${request.systemPrompt}\n${request.userPrompt}`);
110
+ const cached = getCached(key);
111
+ if (cached) {
112
+ return { result: cached.value, source: cached.source, model: null };
113
+ }
114
+ const apiKey = resolveApiKey();
115
+ if (!apiKey) {
116
+ const heuristic = fallback();
117
+ setCached(key, heuristic, "heuristic", ttl);
118
+ return { result: heuristic, source: "heuristic", model: null };
119
+ }
120
+ const model = process.env.ORGX_LLM_MODEL?.trim() || request.model || DEFAULT_MODEL;
121
+ const controller = new AbortController();
122
+ const timeout = setTimeout(() => controller.abort(), request.timeoutMs ?? DEFAULT_TIMEOUT_MS);
123
+ try {
124
+ const response = await fetch(OPENROUTER_URL, {
125
+ method: "POST",
126
+ headers: {
127
+ "Content-Type": "application/json",
128
+ Authorization: `Bearer ${apiKey}`,
129
+ },
130
+ body: JSON.stringify({
131
+ model,
132
+ temperature: request.temperature ?? 0.1,
133
+ max_tokens: request.maxTokens ?? 128,
134
+ messages: [
135
+ { role: "system", content: request.systemPrompt },
136
+ { role: "user", content: request.userPrompt },
137
+ ],
138
+ }),
139
+ signal: controller.signal,
140
+ });
141
+ if (!response.ok) {
142
+ throw new Error(`LLM request failed (${response.status})`);
143
+ }
144
+ const payload = (await response.json());
145
+ const raw = extractCompletionText(payload) ?? "";
146
+ const parsed = parse ? parse(raw) : raw.trim();
147
+ if (parsed && parsed.length > 0) {
148
+ setCached(key, parsed, "llm", ttl);
149
+ return { result: parsed, source: "llm", model };
150
+ }
151
+ const heuristic = fallback();
152
+ setCached(key, heuristic, "heuristic", ttl);
153
+ return { result: heuristic, source: "heuristic", model };
154
+ }
155
+ catch {
156
+ const heuristic = fallback();
157
+ setCached(key, heuristic, "heuristic", ttl);
158
+ return { result: heuristic, source: "heuristic", model: null };
159
+ }
160
+ finally {
161
+ clearTimeout(timeout);
162
+ }
163
+ }
164
+ // ---------------------------------------------------------------------------
165
+ // Public API: JSON-structured completion
166
+ // ---------------------------------------------------------------------------
167
+ /**
168
+ * Call LLM expecting a JSON response. Parses and validates via the provided parser.
169
+ *
170
+ * @param request - The LLM request (systemPrompt should instruct JSON output)
171
+ * @param parse - Parse raw JSON string into typed result, return null on failure
172
+ * @param fallback - Heuristic fallback
173
+ */
174
+ export async function callLlmJson(request, parse, fallback) {
175
+ const ttl = request.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;
176
+ const key = cacheKey(request.taskId, `${request.systemPrompt}\n${request.userPrompt}`);
177
+ const cached = getCached(key);
178
+ if (cached) {
179
+ const parsed = parse(cached.value);
180
+ if (parsed !== null) {
181
+ return { result: parsed, source: cached.source, model: null };
182
+ }
183
+ }
184
+ const apiKey = resolveApiKey();
185
+ if (!apiKey) {
186
+ const heuristic = fallback();
187
+ return { result: heuristic, source: "heuristic", model: null };
188
+ }
189
+ const model = process.env.ORGX_LLM_MODEL?.trim() || request.model || DEFAULT_GENERATION_MODEL;
190
+ const controller = new AbortController();
191
+ const timeout = setTimeout(() => controller.abort(), request.timeoutMs ?? DEFAULT_TIMEOUT_MS);
192
+ try {
193
+ const response = await fetch(OPENROUTER_URL, {
194
+ method: "POST",
195
+ headers: {
196
+ "Content-Type": "application/json",
197
+ Authorization: `Bearer ${apiKey}`,
198
+ },
199
+ body: JSON.stringify({
200
+ model,
201
+ temperature: request.temperature ?? 0.1,
202
+ max_tokens: request.maxTokens ?? 512,
203
+ messages: [
204
+ { role: "system", content: request.systemPrompt },
205
+ { role: "user", content: request.userPrompt },
206
+ ],
207
+ }),
208
+ signal: controller.signal,
209
+ });
210
+ if (!response.ok) {
211
+ throw new Error(`LLM request failed (${response.status})`);
212
+ }
213
+ const payload = (await response.json());
214
+ const raw = extractCompletionText(payload) ?? "";
215
+ // Try to extract JSON from markdown fences or raw text
216
+ const jsonStr = extractJsonFromText(raw);
217
+ const parsed = parse(jsonStr);
218
+ if (parsed !== null) {
219
+ setCached(key, jsonStr, "llm", ttl);
220
+ return { result: parsed, source: "llm", model };
221
+ }
222
+ return { result: fallback(), source: "heuristic", model };
223
+ }
224
+ catch {
225
+ return { result: fallback(), source: "heuristic", model: null };
226
+ }
227
+ finally {
228
+ clearTimeout(timeout);
229
+ }
230
+ }
231
+ // ---------------------------------------------------------------------------
232
+ // Helpers
233
+ // ---------------------------------------------------------------------------
234
+ function extractJsonFromText(text) {
235
+ const trimmed = text.trim();
236
+ // Try markdown JSON fence
237
+ const fenceMatch = trimmed.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
238
+ if (fenceMatch?.[1])
239
+ return fenceMatch[1].trim();
240
+ // Try raw JSON (starts with { or [)
241
+ if (trimmed.startsWith("{") || trimmed.startsWith("["))
242
+ return trimmed;
243
+ // Try to find JSON embedded in text
244
+ const jsonStart = trimmed.indexOf("{");
245
+ if (jsonStart >= 0) {
246
+ const candidate = trimmed.slice(jsonStart);
247
+ try {
248
+ JSON.parse(candidate);
249
+ return candidate;
250
+ }
251
+ catch {
252
+ // fall through
253
+ }
254
+ }
255
+ return trimmed;
256
+ }
@@ -23,6 +23,19 @@ export interface MissionControlNode {
23
23
  expectedDurationHours: number;
24
24
  expectedBudgetUsd: number;
25
25
  assignedAgents: MissionControlAssignedAgent[];
26
+ behaviorConfigId?: string | null;
27
+ behaviorConfigVersion?: string | null;
28
+ behaviorConfigHash?: string | null;
29
+ behaviorPolicySource?: string | null;
30
+ behaviorContext?: string | null;
31
+ behaviorRequiresApproval?: boolean | null;
32
+ behaviorApprovalStatus?: string | null;
33
+ behaviorApprovalDecisionId?: string | null;
34
+ behaviorAutomationLevel?: "auto" | "supervised" | "manual" | null;
35
+ sliceScopePreference?: "adaptive" | "task" | "milestone" | "workstream" | null;
36
+ maxSliceTasks?: number | null;
37
+ maxParallelAgents?: number | null;
38
+ dependencyMode?: "strict" | "relaxed" | null;
26
39
  updatedAt: string | null;
27
40
  }
28
41
  export interface MissionControlEdge {
@@ -30,6 +43,33 @@ export interface MissionControlEdge {
30
43
  to: string;
31
44
  kind: "depends_on";
32
45
  }
46
+ export interface MissionControlCycleDiagnostics {
47
+ detected: boolean;
48
+ cycleEdgeCount: number;
49
+ removedEdges: Array<{
50
+ from: string;
51
+ to: string;
52
+ }>;
53
+ affectedNodes: Array<{
54
+ nodeId: string;
55
+ nodeType: MissionControlNodeType;
56
+ removedDependencyIds: string[];
57
+ remainingDependencyIds: string[];
58
+ }>;
59
+ }
60
+ export type SliceScope = "task" | "milestone" | "workstream";
61
+ export type SliceScopePreference = "adaptive" | SliceScope;
62
+ export interface MissionControlExecutionPolicy {
63
+ domain: string;
64
+ requiredSkills: string[];
65
+ profile?: string | null;
66
+ sliceScopePreference?: SliceScopePreference | null;
67
+ maxSliceTasks?: number | null;
68
+ maxParallelAgents?: number | null;
69
+ dependencyMode?: "strict" | "relaxed" | null;
70
+ }
71
+ export declare const SLICE_SCOPE_MAX_TASKS: Record<SliceScope, number>;
72
+ export declare const SLICE_SCOPE_TIMEOUT_MULTIPLIER: Record<SliceScope, number>;
33
73
  export declare const ORGX_SKILL_BY_DOMAIN: Record<string, string>;
34
74
  interface BudgetEnvBounds {
35
75
  min?: number;
@@ -67,6 +107,7 @@ export declare function buildMissionControlGraph(client: OrgXClient, initiativeI
67
107
  edges: MissionControlEdge[];
68
108
  recentTodos: string[];
69
109
  degraded: string[];
110
+ cycleDiagnostics?: MissionControlCycleDiagnostics;
70
111
  }>;
71
112
  export declare function normalizeEntityMutationPayload(payload: Record<string, unknown>): Record<string, unknown>;
72
113
  export declare function resolveAutoAssignments(input: {
@@ -85,10 +126,68 @@ export declare function resolveAutoAssignments(input: {
85
126
  }>;
86
127
  export declare function normalizeExecutionDomain(value: string | null | undefined): string | null;
87
128
  export declare function inferExecutionDomainFromText(...values: Array<string | null | undefined>): string;
88
- export declare function deriveExecutionPolicy(taskNode: MissionControlNode, workstreamNode: MissionControlNode | null): {
89
- domain: string;
90
- requiredSkills: string[];
129
+ export declare function selectSliceTasksByScope(input: {
130
+ scope: SliceScope;
131
+ workstreamId: string;
132
+ milestoneId?: string | null;
133
+ recentTodos: string[];
134
+ nodeById: Map<string, MissionControlNode>;
135
+ includeVerification: boolean;
136
+ }): {
137
+ tasks: MissionControlNode[];
138
+ milestoneIds: string[];
139
+ };
140
+ export declare function evaluateScopeCompletion(input: {
141
+ scope: SliceScope;
142
+ milestoneIds: string[];
143
+ workstreamId: string;
144
+ nodeById: Map<string, MissionControlNode>;
145
+ }): {
146
+ scopeComplete: boolean;
147
+ remainingTasks: number;
148
+ };
149
+ export declare function deriveExecutionPolicy(taskNode: MissionControlNode, workstreamNode: MissionControlNode | null): MissionControlExecutionPolicy;
150
+ export declare function deriveBehaviorConfigContext(taskNode: MissionControlNode, workstreamNode: MissionControlNode | null): {
151
+ configId: string | null;
152
+ version: string | null;
153
+ hash: string | null;
154
+ policySource: string | null;
155
+ context: string | null;
156
+ requiresApproval: boolean;
157
+ approvalStatus: string | null;
158
+ approvalDecisionId: string | null;
91
159
  };
160
+ export declare function deriveBehaviorAutomationLevel(taskNode: MissionControlNode, workstreamNode: MissionControlNode | null): "auto" | "supervised" | "manual";
161
+ export declare function detectBehaviorConfigDrift(input: {
162
+ taskNode: MissionControlNode;
163
+ workstreamNode: MissionControlNode | null;
164
+ behaviorConfig: {
165
+ configId: string | null;
166
+ version: string | null;
167
+ hash: string | null;
168
+ policySource: string | null;
169
+ context: string | null;
170
+ };
171
+ behaviorAutomationLevel: "auto" | "supervised" | "manual";
172
+ }): {
173
+ fields: Array<"config_id" | "version" | "hash" | "policy_source" | "context" | "automation_level">;
174
+ declared: {
175
+ configId: string | null;
176
+ version: string | null;
177
+ hash: string | null;
178
+ policySource: string | null;
179
+ context: string | null;
180
+ automationLevel: "auto" | "supervised" | "manual" | null;
181
+ };
182
+ runtime: {
183
+ configId: string | null;
184
+ version: string | null;
185
+ hash: string | null;
186
+ policySource: string | null;
187
+ context: string | null;
188
+ automationLevel: "auto" | "supervised" | "manual";
189
+ };
190
+ } | null;
92
191
  export declare function spawnGuardIsRateLimited(result: unknown): boolean;
93
192
  export declare function summarizeSpawnGuardBlockReason(result: unknown): string;
94
193
  export {};