sensorium-mcp 3.1.2 → 3.1.3-board.2
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/Install-Sensorium.ps1 +61 -0
- package/dist/board/api/api.js +61 -0
- package/dist/board/api/client.js +96 -0
- package/dist/board/components/BottomNav.js +32 -0
- package/dist/board/components/Card.js +44 -0
- package/dist/board/components/CommentComposer.js +26 -0
- package/dist/board/components/CommentList.js +39 -0
- package/dist/board/components/Dropdown.js +66 -0
- package/dist/board/components/Lane.js +40 -0
- package/dist/board/components/PriorityChip.js +17 -0
- package/dist/board/components/ProfileSummary.js +39 -0
- package/dist/board/components/StateBanner.js +22 -0
- package/dist/board/components/StatusChip.js +21 -0
- package/dist/board/components/TokenEntry.js +42 -0
- package/dist/board/config.js +56 -0
- package/dist/board/index.html +18 -0
- package/dist/board/main.js +37 -0
- package/dist/board/mock/api.mock.js +193 -0
- package/dist/board/mock/fixtures.js +164 -0
- package/dist/board/schema/policy.js +192 -0
- package/dist/board/state/auth.js +55 -0
- package/dist/board/state/useBoard.js +149 -0
- package/dist/board/state/useBuilder.js +98 -0
- package/dist/board/state/useCard.js +67 -0
- package/dist/board/styles/board.css +1760 -0
- package/dist/board/styles/tokens.css +71 -0
- package/dist/board/vendor/vue.esm-browser.js +9 -0
- package/dist/board/views/App.js +65 -0
- package/dist/board/views/BoardView.js +84 -0
- package/dist/board/views/BuilderView.js +303 -0
- package/dist/board/views/CardView.js +245 -0
- package/dist/board/views/SettingsView.js +145 -0
- package/dist/config/agent-settings.d.ts +2 -0
- package/dist/config/agent-settings.d.ts.map +1 -1
- package/dist/config/agent-settings.js +23 -0
- package/dist/config/agent-settings.js.map +1 -1
- package/dist/config/index.d.ts +1 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +12 -0
- package/dist/config/index.js.map +1 -1
- package/dist/config/misc-settings.d.ts +14 -0
- package/dist/config/misc-settings.d.ts.map +1 -1
- package/dist/config/misc-settings.js +53 -0
- package/dist/config/misc-settings.js.map +1 -1
- package/dist/dashboard/board-static.d.ts +23 -0
- package/dist/dashboard/board-static.d.ts.map +1 -0
- package/dist/dashboard/board-static.js +131 -0
- package/dist/dashboard/board-static.js.map +1 -0
- package/dist/dashboard/routes/board.d.ts +73 -0
- package/dist/dashboard/routes/board.d.ts.map +1 -0
- package/dist/dashboard/routes/board.js +623 -0
- package/dist/dashboard/routes/board.js.map +1 -0
- package/dist/dashboard/routes/claude.d.ts.map +1 -1
- package/dist/dashboard/routes/claude.js +10 -1
- package/dist/dashboard/routes/claude.js.map +1 -1
- package/dist/dashboard/routes/settings.d.ts +2 -0
- package/dist/dashboard/routes/settings.d.ts.map +1 -1
- package/dist/dashboard/routes/settings.js +24 -1
- package/dist/dashboard/routes/settings.js.map +1 -1
- package/dist/dashboard/routes/threads-read.d.ts +7 -3
- package/dist/dashboard/routes/threads-read.d.ts.map +1 -1
- package/dist/dashboard/routes/threads-read.js +19 -4
- package/dist/dashboard/routes/threads-read.js.map +1 -1
- package/dist/dashboard/routes/types.d.ts +6 -0
- package/dist/dashboard/routes/types.d.ts.map +1 -1
- package/dist/dashboard/routes/types.js.map +1 -1
- package/dist/dashboard/routes.d.ts.map +1 -1
- package/dist/dashboard/routes.js +42 -1
- package/dist/dashboard/routes.js.map +1 -1
- package/dist/dashboard/spa.html +12 -12
- package/dist/data/board/board-schema.d.ts +22 -0
- package/dist/data/board/board-schema.d.ts.map +1 -0
- package/dist/data/board/board-schema.js +103 -0
- package/dist/data/board/board-schema.js.map +1 -0
- package/dist/data/board/board-types.d.ts +117 -0
- package/dist/data/board/board-types.d.ts.map +1 -0
- package/dist/data/board/board-types.js +9 -0
- package/dist/data/board/board-types.js.map +1 -0
- package/dist/data/board/card.repository.d.ts +64 -0
- package/dist/data/board/card.repository.d.ts.map +1 -0
- package/dist/data/board/card.repository.js +272 -0
- package/dist/data/board/card.repository.js.map +1 -0
- package/dist/data/board/comment.repository.d.ts +12 -0
- package/dist/data/board/comment.repository.d.ts.map +1 -0
- package/dist/data/board/comment.repository.js +31 -0
- package/dist/data/board/comment.repository.js.map +1 -0
- package/dist/data/board/lane.repository.d.ts +18 -0
- package/dist/data/board/lane.repository.d.ts.map +1 -0
- package/dist/data/board/lane.repository.js +44 -0
- package/dist/data/board/lane.repository.js.map +1 -0
- package/dist/data/board/profile-defaults.d.ts +19 -0
- package/dist/data/board/profile-defaults.d.ts.map +1 -0
- package/dist/data/board/profile-defaults.js +118 -0
- package/dist/data/board/profile-defaults.js.map +1 -0
- package/dist/data/memory/migration-runner.d.ts.map +1 -1
- package/dist/data/memory/migration-runner.js +4 -0
- package/dist/data/memory/migration-runner.js.map +1 -1
- package/dist/data/memory/narrative-store.d.ts +14 -0
- package/dist/data/memory/narrative-store.d.ts.map +1 -1
- package/dist/data/memory/narrative-store.js +36 -0
- package/dist/data/memory/narrative-store.js.map +1 -1
- package/dist/data/memory/narrative.d.ts.map +1 -1
- package/dist/data/memory/narrative.js +13 -1
- package/dist/data/memory/narrative.js.map +1 -1
- package/dist/data/memory/schema.d.ts.map +1 -1
- package/dist/data/memory/schema.js +4 -0
- package/dist/data/memory/schema.js.map +1 -1
- package/dist/index.js +84 -2
- package/dist/index.js.map +1 -1
- package/dist/integrations/openai/speech.d.ts.map +1 -1
- package/dist/integrations/openai/speech.js +52 -19
- package/dist/integrations/openai/speech.js.map +1 -1
- package/dist/lib/http-retry.d.ts +91 -0
- package/dist/lib/http-retry.d.ts.map +1 -0
- package/dist/lib/http-retry.js +177 -0
- package/dist/lib/http-retry.js.map +1 -0
- package/dist/lib/usage-metering/pricing.js +1 -1
- package/dist/lib/usage-metering/pricing.js.map +1 -1
- package/dist/lib/utils.d.ts +10 -0
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +22 -0
- package/dist/lib/utils.js.map +1 -1
- package/dist/server/http-server.d.ts +3 -1
- package/dist/server/http-server.d.ts.map +1 -1
- package/dist/server/http-server.js +6 -2
- package/dist/server/http-server.js.map +1 -1
- package/dist/services/board/board-signals.d.ts +25 -0
- package/dist/services/board/board-signals.d.ts.map +1 -0
- package/dist/services/board/board-signals.js +83 -0
- package/dist/services/board/board-signals.js.map +1 -0
- package/dist/services/board/card-briefing.d.ts +17 -0
- package/dist/services/board/card-briefing.d.ts.map +1 -0
- package/dist/services/board/card-briefing.js +86 -0
- package/dist/services/board/card-briefing.js.map +1 -0
- package/dist/services/board/orchestrator.service.d.ts +55 -0
- package/dist/services/board/orchestrator.service.d.ts.map +1 -0
- package/dist/services/board/orchestrator.service.js +198 -0
- package/dist/services/board/orchestrator.service.js.map +1 -0
- package/dist/services/board/release-worker.d.ts +32 -0
- package/dist/services/board/release-worker.d.ts.map +1 -0
- package/dist/services/board/release-worker.js +49 -0
- package/dist/services/board/release-worker.js.map +1 -0
- package/dist/services/board/report-capture.d.ts +48 -0
- package/dist/services/board/report-capture.d.ts.map +1 -0
- package/dist/services/board/report-capture.js +172 -0
- package/dist/services/board/report-capture.js.map +1 -0
- package/dist/services/board/worker-spawn.d.ts +30 -0
- package/dist/services/board/worker-spawn.d.ts.map +1 -0
- package/dist/services/board/worker-spawn.js +90 -0
- package/dist/services/board/worker-spawn.js.map +1 -0
- package/dist/services/broker-client.d.ts +30 -0
- package/dist/services/broker-client.d.ts.map +1 -1
- package/dist/services/broker-client.js +23 -0
- package/dist/services/broker-client.js.map +1 -1
- package/dist/services/codex-spawn.service.d.ts +2 -2
- package/dist/services/codex-spawn.service.d.ts.map +1 -1
- package/dist/services/codex-spawn.service.js +54 -54
- package/dist/services/codex-spawn.service.js.map +1 -1
- package/dist/services/http-retry.d.ts +1 -90
- package/dist/services/http-retry.d.ts.map +1 -1
- package/dist/services/http-retry.js +1 -176
- package/dist/services/http-retry.js.map +1 -1
- package/dist/services/mcp-config.service.d.ts.map +1 -1
- package/dist/services/mcp-config.service.js +5 -1
- package/dist/services/mcp-config.service.js.map +1 -1
- package/dist/services/passive-notice.service.d.ts +39 -0
- package/dist/services/passive-notice.service.d.ts.map +1 -0
- package/dist/services/passive-notice.service.js +274 -0
- package/dist/services/passive-notice.service.js.map +1 -0
- package/dist/services/spawn-common.d.ts.map +1 -1
- package/dist/services/spawn-common.js +14 -1
- package/dist/services/spawn-common.js.map +1 -1
- package/dist/services/telegram.d.ts +7 -5
- package/dist/services/telegram.d.ts.map +1 -1
- package/dist/services/telegram.js +18 -13
- package/dist/services/telegram.js.map +1 -1
- package/dist/services/usage/usage-inbox-notifier.d.ts +50 -0
- package/dist/services/usage/usage-inbox-notifier.d.ts.map +1 -0
- package/dist/services/usage/usage-inbox-notifier.js +118 -0
- package/dist/services/usage/usage-inbox-notifier.js.map +1 -0
- package/dist/services/usage/usage-poller.service.d.ts +41 -0
- package/dist/services/usage/usage-poller.service.d.ts.map +1 -0
- package/dist/services/usage/usage-poller.service.js +66 -0
- package/dist/services/usage/usage-poller.service.js.map +1 -0
- package/dist/services/usage/usage-snapshot-provider.d.ts +29 -0
- package/dist/services/usage/usage-snapshot-provider.d.ts.map +1 -0
- package/dist/services/usage/usage-snapshot-provider.js +59 -0
- package/dist/services/usage/usage-snapshot-provider.js.map +1 -0
- package/dist/services/usage/usage-types.d.ts +23 -0
- package/dist/services/usage/usage-types.d.ts.map +1 -0
- package/dist/services/usage/usage-types.js +14 -0
- package/dist/services/usage/usage-types.js.map +1 -0
- package/dist/services/worker-cleanup.service.d.ts +6 -1
- package/dist/services/worker-cleanup.service.d.ts.map +1 -1
- package/dist/services/worker-cleanup.service.js +123 -10
- package/dist/services/worker-cleanup.service.js.map +1 -1
- package/dist/tools/delegate-tool.d.ts.map +1 -1
- package/dist/tools/delegate-tool.js +34 -2
- package/dist/tools/delegate-tool.js.map +1 -1
- package/dist/tools/utility-tools.d.ts.map +1 -1
- package/dist/tools/utility-tools.js +7 -3
- package/dist/tools/utility-tools.js.map +1 -1
- package/dist/tools/wait/consolidation-strategy.d.ts +42 -0
- package/dist/tools/wait/consolidation-strategy.d.ts.map +1 -0
- package/dist/tools/wait/consolidation-strategy.js +50 -0
- package/dist/tools/wait/consolidation-strategy.js.map +1 -0
- package/dist/tools/wait/drive-handler.d.ts +5 -7
- package/dist/tools/wait/drive-handler.d.ts.map +1 -1
- package/dist/tools/wait/drive-handler.js +30 -48
- package/dist/tools/wait/drive-handler.js.map +1 -1
- package/dist/tools/wait/message-delivery.d.ts.map +1 -1
- package/dist/tools/wait/message-delivery.js +13 -0
- package/dist/tools/wait/message-delivery.js.map +1 -1
- package/package.json +2 -2
- package/templates/atomic-build-spec.default.md +57 -0
- package/templates/buildless-vue-preview.default.md +47 -0
- package/templates/phased-build.default.md +59 -0
|
@@ -1,177 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
* Transient HTTP retry policy.
|
|
3
|
-
*
|
|
4
|
-
* Centralizes the "retry on transient failure" behavior so it can be applied at
|
|
5
|
-
* a single choke point per call site rather than scattered across every request
|
|
6
|
-
* method. It is deliberately PURE: it knows nothing about the Telegram bot token
|
|
7
|
-
* or any other caller secret, so it never risks leaking one. Token redaction and
|
|
8
|
-
* response-body interpretation stay the caller's responsibility.
|
|
9
|
-
*
|
|
10
|
-
* WHY this exists: operators may point TELEGRAM_API_BASE_URL at an nginx reverse
|
|
11
|
-
* proxy or Azure gateway. Those proxies answer with 504 Gateway Timeout (or
|
|
12
|
-
* 502/503) instead of a normal Telegram JSON payload. Without retries a single
|
|
13
|
-
* proxy hiccup drops an operator notification or spins the long-poll loop; a
|
|
14
|
-
* bounded, jittered retry smooths over the transient blips.
|
|
15
|
-
*/
|
|
16
|
-
/**
|
|
17
|
-
* HTTP status codes that indicate a TRANSIENT failure — the request may well
|
|
18
|
-
* succeed if retried after a short pause:
|
|
19
|
-
* 408 Request Timeout, 429 Too Many Requests,
|
|
20
|
-
* 500 Internal Server Error, 502 Bad Gateway,
|
|
21
|
-
* 503 Service Unavailable, 504 Gateway Timeout.
|
|
22
|
-
*
|
|
23
|
-
* Every other 4xx is PERMANENT (bad request, unauthorized, not found, …) and is
|
|
24
|
-
* never retried — retrying it only wastes time and risks duplicate side effects.
|
|
25
|
-
*/
|
|
26
|
-
export const TRANSIENT_STATUS = new Set([408, 429, 500, 502, 503, 504]);
|
|
27
|
-
/** True when `status` is in the transient (retryable) set. */
|
|
28
|
-
export function isTransientStatus(status) {
|
|
29
|
-
return TRANSIENT_STATUS.has(status);
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Upper bound (ms) we are ever willing to wait for a single `Retry-After`
|
|
33
|
-
* hint. A hostile or misconfigured proxy could send an absurd value; clamp it
|
|
34
|
-
* so we never sleep for minutes on end.
|
|
35
|
-
*/
|
|
36
|
-
const RETRY_AFTER_MAX_MS = 60_000;
|
|
37
|
-
/**
|
|
38
|
-
* Parse the `Retry-After` response header into milliseconds.
|
|
39
|
-
*
|
|
40
|
-
* Per RFC 9110 the value is either a number of seconds (`Retry-After: 120`) or
|
|
41
|
-
* an HTTP-date (`Retry-After: Wed, 21 Oct 2026 07:28:00 GMT`). Returns
|
|
42
|
-
* `undefined` when the header is absent or unparseable, and clamps any positive
|
|
43
|
-
* result to {@link RETRY_AFTER_MAX_MS}. A date in the past yields `0`.
|
|
44
|
-
*/
|
|
45
|
-
export function parseRetryAfterMs(response) {
|
|
46
|
-
const raw = response.headers.get("retry-after");
|
|
47
|
-
if (raw === null)
|
|
48
|
-
return undefined;
|
|
49
|
-
const trimmed = raw.trim();
|
|
50
|
-
if (trimmed === "")
|
|
51
|
-
return undefined;
|
|
52
|
-
// Numeric form: delay in seconds.
|
|
53
|
-
if (/^\d+$/.test(trimmed)) {
|
|
54
|
-
const seconds = Number(trimmed);
|
|
55
|
-
return Math.min(seconds * 1000, RETRY_AFTER_MAX_MS);
|
|
56
|
-
}
|
|
57
|
-
// HTTP-date form: absolute time to retry at.
|
|
58
|
-
const dateMs = Date.parse(trimmed);
|
|
59
|
-
if (Number.isNaN(dateMs))
|
|
60
|
-
return undefined;
|
|
61
|
-
const deltaMs = dateMs - Date.now();
|
|
62
|
-
if (deltaMs <= 0)
|
|
63
|
-
return 0;
|
|
64
|
-
return Math.min(deltaMs, RETRY_AFTER_MAX_MS);
|
|
65
|
-
}
|
|
66
|
-
/** Sensible default: 3 attempts, 500ms base, 8s cap. */
|
|
67
|
-
export const DEFAULT_RETRY_POLICY = {
|
|
68
|
-
maxAttempts: 3,
|
|
69
|
-
baseMs: 500,
|
|
70
|
-
capMs: 8_000,
|
|
71
|
-
};
|
|
72
|
-
/**
|
|
73
|
-
* Exponential backoff with FULL jitter.
|
|
74
|
-
*
|
|
75
|
-
* The deterministic component is `baseMs * 2^attempt`, capped at `capMs`. We
|
|
76
|
-
* then draw a uniformly random value in `[0, capped]` (the "full jitter"
|
|
77
|
-
* strategy from the AWS Architecture Blog). Full jitter — rather than
|
|
78
|
-
* equal-jitter or none — is chosen because it maximizes spread across many
|
|
79
|
-
* concurrent clients hammering the same recovering proxy, which minimizes
|
|
80
|
-
* retry-storm synchronization.
|
|
81
|
-
*
|
|
82
|
-
* @param attempt Zero-based retry index (0 for the first backoff).
|
|
83
|
-
*/
|
|
84
|
-
export function computeBackoffMs(attempt, policy = DEFAULT_RETRY_POLICY) {
|
|
85
|
-
const exponential = policy.baseMs * 2 ** attempt;
|
|
86
|
-
const capped = Math.min(exponential, policy.capMs);
|
|
87
|
-
return Math.random() * capped;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Sleep for `ms`, rejecting immediately if `signal` aborts mid-wait.
|
|
91
|
-
*
|
|
92
|
-
* Retries must not swallow an intentional shutdown: if the caller's signal
|
|
93
|
-
* fires while we are backing off, propagate the abort at once rather than
|
|
94
|
-
* finishing the sleep.
|
|
95
|
-
*/
|
|
96
|
-
export function abortableDelay(ms, signal) {
|
|
97
|
-
return new Promise((resolve, reject) => {
|
|
98
|
-
if (signal?.aborted) {
|
|
99
|
-
reject(signal.reason ?? new DOMException("Aborted", "AbortError"));
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
let onAbort;
|
|
103
|
-
const timer = setTimeout(() => {
|
|
104
|
-
if (signal && onAbort)
|
|
105
|
-
signal.removeEventListener("abort", onAbort);
|
|
106
|
-
resolve();
|
|
107
|
-
}, ms);
|
|
108
|
-
if (signal) {
|
|
109
|
-
onAbort = () => {
|
|
110
|
-
clearTimeout(timer);
|
|
111
|
-
reject(signal.reason ?? new DOMException("Aborted", "AbortError"));
|
|
112
|
-
};
|
|
113
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* `fetch` with bounded, jittered retry on transient failures.
|
|
119
|
-
*
|
|
120
|
-
* Behavior:
|
|
121
|
-
* - Performs the fetch. If the response status is transient AND attempts
|
|
122
|
-
* remain, waits (honoring `Retry-After` when present, otherwise
|
|
123
|
-
* {@link computeBackoffMs}) and retries. Otherwise returns the response — the
|
|
124
|
-
* caller still inspects `.ok` to handle permanent (4xx) errors itself.
|
|
125
|
-
* - Only a thrown `TypeError` — how native `fetch` reports a genuine transport
|
|
126
|
-
* failure (DNS, ECONNREFUSED, socket reset) — is retried (if attempts
|
|
127
|
-
* remain, else the last error is rethrown). Every other throw propagates
|
|
128
|
-
* IMMEDIATELY with no wasted backoff: an AbortError / TimeoutError from
|
|
129
|
-
* `init.signal` (or `AbortSignal.timeout`) is intentional and must not be
|
|
130
|
-
* retried, and a programmer error (e.g. a bad argument) is not transient.
|
|
131
|
-
* - The backoff sleep is abort-aware: aborting `init.signal` mid-wait rejects
|
|
132
|
-
* at once.
|
|
133
|
-
*
|
|
134
|
-
* Kept PURE — no knowledge of any caller secret. Token redaction is layered on
|
|
135
|
-
* top by the caller's own try/catch.
|
|
136
|
-
*/
|
|
137
|
-
export async function fetchWithRetry(input, init, policy = DEFAULT_RETRY_POLICY) {
|
|
138
|
-
const signal = init?.signal ?? undefined;
|
|
139
|
-
let lastError;
|
|
140
|
-
for (let attempt = 0; attempt < policy.maxAttempts; attempt++) {
|
|
141
|
-
const attemptsRemaining = attempt < policy.maxAttempts - 1;
|
|
142
|
-
let response;
|
|
143
|
-
try {
|
|
144
|
-
response = await fetch(input, init);
|
|
145
|
-
}
|
|
146
|
-
catch (err) {
|
|
147
|
-
// Only a genuine transport failure is retryable. Native `fetch` throws a
|
|
148
|
-
// TypeError for network-level faults (DNS, ECONNREFUSED, socket reset);
|
|
149
|
-
// anything else — AbortError/TimeoutError from a signal, or a programmer
|
|
150
|
-
// error — is intentional or permanent and must propagate at once.
|
|
151
|
-
if (!(err instanceof TypeError))
|
|
152
|
-
throw err;
|
|
153
|
-
lastError = err;
|
|
154
|
-
if (!attemptsRemaining)
|
|
155
|
-
throw err;
|
|
156
|
-
await abortableDelay(computeBackoffMs(attempt, policy), signal);
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
// Transient HTTP status with attempts left → back off and retry. Otherwise
|
|
160
|
-
// (success, or permanent error, or out of attempts) hand the response back.
|
|
161
|
-
if (isTransientStatus(response.status) && attemptsRemaining) {
|
|
162
|
-
const retryAfter = parseRetryAfterMs(response);
|
|
163
|
-
const waitMs = retryAfter ?? computeBackoffMs(attempt, policy);
|
|
164
|
-
// Release the socket before retrying: an unconsumed undici `Response`
|
|
165
|
-
// body keeps its connection pinned until GC, so a sustained proxy outage
|
|
166
|
-
// would leak one connection per retried 504. Draining first avoids it.
|
|
167
|
-
await response.body?.cancel().catch(() => { });
|
|
168
|
-
await abortableDelay(waitMs, signal);
|
|
169
|
-
continue;
|
|
170
|
-
}
|
|
171
|
-
return response;
|
|
172
|
-
}
|
|
173
|
-
// Unreachable when maxAttempts >= 1, but keeps the type checker happy and
|
|
174
|
-
// guards against a misconfigured policy (maxAttempts <= 0).
|
|
175
|
-
throw lastError ?? new Error("fetchWithRetry: exhausted attempts with no response");
|
|
176
|
-
}
|
|
1
|
+
export * from "../lib/http-retry.js";
|
|
177
2
|
//# sourceMappingURL=http-retry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-retry.js","sourceRoot":"","sources":["../../src/services/http-retry.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"http-retry.js","sourceRoot":"","sources":["../../src/services/http-retry.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-config.service.d.ts","sourceRoot":"","sources":["../../src/services/mcp-config.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"mcp-config.service.d.ts","sourceRoot":"","sources":["../../src/services/mcp-config.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAgBH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AA+BD;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,4BAA4B,CAAC;AAoB5D;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAoB5F;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,kBAAkB,EAC7B,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,MAAM,GACf,IAAI,CAkBN;AAcD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,kBAAkB,EAC7B,QAAQ,EAAE,MAAM,GACf;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAqBjD"}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import { chmodSync, mkdirSync, writeFileSync } from "node:fs";
|
|
11
11
|
import { join } from "node:path";
|
|
12
12
|
import { randomUUID } from "node:crypto";
|
|
13
|
-
import { getMcpServers, getThreadMcpServers, } from "../config/index.js";
|
|
13
|
+
import { getMcpServers, getThreadMcpServers, getCodexToolTimeoutSec, } from "../config/index.js";
|
|
14
14
|
import { PROCESS_PIDS_DIR } from "./process.service.js";
|
|
15
15
|
// ── Shared JSON formatter (Claude & Copilot use the same schema) ────────────
|
|
16
16
|
function formatJsonMcpEntry(cfg) {
|
|
@@ -137,6 +137,10 @@ export function buildCodexMcpArgs(transport, threadId) {
|
|
|
137
137
|
args.push("-c", `mcp_servers.sensorium-mcp.url="http://127.0.0.1:${transport.httpPort}/mcp"`);
|
|
138
138
|
if (transport.secret)
|
|
139
139
|
args.push("-c", `mcp_servers.sensorium-mcp.bearer_token_env_var="SENSORIUM_MCP_SECRET"`);
|
|
140
|
+
// Codex cancels an MCP tool call after `tool_timeout_sec` (default 300s), which
|
|
141
|
+
// would sever our long-polling wait_for_instructions. Raise it to the
|
|
142
|
+
// dashboard-configured budget so a thread can park for the full wait.
|
|
143
|
+
args.push("-c", `mcp_servers.sensorium-mcp.tool_timeout_sec=${getCodexToolTimeoutSec()}`);
|
|
140
144
|
for (const [name, cfg] of Object.entries(getMcpServers())) {
|
|
141
145
|
args.push(...formatCodexEntry(name, cfg));
|
|
142
146
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-config.service.js","sourceRoot":"","sources":["../../src/services/mcp-config.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACL,aAAa,EACb,mBAAmB,
|
|
1
|
+
{"version":3,"file":"mcp-config.service.js","sourceRoot":"","sources":["../../src/services/mcp-config.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Passive-notice channel — "context, not command" (design §5).
|
|
3
|
+
*
|
|
4
|
+
* A general capability, independent of the board: notices pushed here are
|
|
5
|
+
* DRAINED into the next delivered turn of the target thread as an FYI block
|
|
6
|
+
* (message-delivery renders them next to the Persistent Context block). They
|
|
7
|
+
* never wake the agent and are never framed as tasks — the agent is aware,
|
|
8
|
+
* not commanded. This fixes the notification/command conflation of the
|
|
9
|
+
* pending-task inbox for updates that carry no instruction.
|
|
10
|
+
*
|
|
11
|
+
* Storage: per-thread JSON queue under ~/.remote-copilot-mcp/passive-notices/,
|
|
12
|
+
* write-then-rename (same durability pattern as schedules). Bounded to the
|
|
13
|
+
* most recent MAX_NOTICES entries.
|
|
14
|
+
*/
|
|
15
|
+
export interface PassiveNotice {
|
|
16
|
+
text: string;
|
|
17
|
+
createdAt: string;
|
|
18
|
+
}
|
|
19
|
+
/** Queue an FYI notice for a thread's next delivered turn. Never wakes the agent. */
|
|
20
|
+
export declare function pushPassiveNotice(threadId: number, text: string): void;
|
|
21
|
+
/**
|
|
22
|
+
* Read-and-clear (delivered-once semantics). Returns oldest→newest.
|
|
23
|
+
*
|
|
24
|
+
* Drain claims the queue file via atomic rename (under the same lock pushes
|
|
25
|
+
* take), so a push landing mid-drain writes a FRESH queue file and survives.
|
|
26
|
+
* Claims are per-pid; claims left by a crashed process are swept in too
|
|
27
|
+
* (redelivery of an FYI beats losing it).
|
|
28
|
+
*/
|
|
29
|
+
export declare function drainPassiveNotices(threadId: number): PassiveNotice[];
|
|
30
|
+
/** Non-destructive peek (dashboard/diagnostics). */
|
|
31
|
+
export declare function peekPassiveNotices(threadId: number): PassiveNotice[];
|
|
32
|
+
/**
|
|
33
|
+
* Drain and render the FYI block appended to a delivered turn (next to the
|
|
34
|
+
* Persistent Context block in message-delivery). Empty string when quiet.
|
|
35
|
+
* The framing does the "aware, not commanded" work: explicit no-action wording
|
|
36
|
+
* so a later operator voice about these makes sense without triggering work.
|
|
37
|
+
*/
|
|
38
|
+
export declare function renderPassiveNoticeBlock(threadId: number): string;
|
|
39
|
+
//# sourceMappingURL=passive-notice.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passive-notice.service.d.ts","sourceRoot":"","sources":["../../src/services/passive-notice.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAmBH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AA4FD,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAmBtE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,EAAE,CAgFrE;AAED,oDAAoD;AACpD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,EAAE,CAEpE;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA6BjE"}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Passive-notice channel — "context, not command" (design §5).
|
|
3
|
+
*
|
|
4
|
+
* A general capability, independent of the board: notices pushed here are
|
|
5
|
+
* DRAINED into the next delivered turn of the target thread as an FYI block
|
|
6
|
+
* (message-delivery renders them next to the Persistent Context block). They
|
|
7
|
+
* never wake the agent and are never framed as tasks — the agent is aware,
|
|
8
|
+
* not commanded. This fixes the notification/command conflation of the
|
|
9
|
+
* pending-task inbox for updates that carry no instruction.
|
|
10
|
+
*
|
|
11
|
+
* Storage: per-thread JSON queue under ~/.remote-copilot-mcp/passive-notices/,
|
|
12
|
+
* write-then-rename (same durability pattern as schedules). Bounded to the
|
|
13
|
+
* most recent MAX_NOTICES entries.
|
|
14
|
+
*/
|
|
15
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
16
|
+
import { homedir } from "node:os";
|
|
17
|
+
import { join } from "node:path";
|
|
18
|
+
import { log } from "../lib/logger.js";
|
|
19
|
+
import { errorMessage } from "../lib/utils.js";
|
|
20
|
+
const NOTICES_DIR = join(homedir(), ".remote-copilot-mcp", "passive-notices");
|
|
21
|
+
const MAX_NOTICES = 10;
|
|
22
|
+
function noticesFilePath(threadId) {
|
|
23
|
+
return join(NOTICES_DIR, `${threadId}.json`);
|
|
24
|
+
}
|
|
25
|
+
// ── Cross-process safety (H4 of the board kernel review) ───────────────────
|
|
26
|
+
// Writers live in DIFFERENT OS processes (a worker's own MCP tool call vs the
|
|
27
|
+
// server's orchestrator/cleanup loops). The bare read→modify→write→rename pair
|
|
28
|
+
// is atomic only in the rename, so concurrent pushes were last-writer-wins and
|
|
29
|
+
// a push landing inside drain's read→unlink window was destroyed. Same lock
|
|
30
|
+
// pattern as dispatcher/lock.ts (wx-create + dead-pid/stale takeover), scoped
|
|
31
|
+
// per thread; drain claims the file by atomic rename so a concurrent push
|
|
32
|
+
// simply starts a fresh queue file and survives.
|
|
33
|
+
const LOCK_STALE_MS = 10_000;
|
|
34
|
+
const LOCK_RETRY_MS = 5;
|
|
35
|
+
const LOCK_MAX_ATTEMPTS = 60;
|
|
36
|
+
function isPidAlive(pid) {
|
|
37
|
+
try {
|
|
38
|
+
process.kill(pid, 0);
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
return err.code === "EPERM";
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function sleepSync(ms) {
|
|
46
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
47
|
+
}
|
|
48
|
+
/** Acquire the per-thread mutation lock. Hold time is sub-millisecond (tiny
|
|
49
|
+
* file ops), so bounded spinning is fine. Returns false only under pathological
|
|
50
|
+
* contention — callers then proceed unlocked (a rare racy write beats losing
|
|
51
|
+
* the notice outright). */
|
|
52
|
+
function acquireNoticeLock(threadId) {
|
|
53
|
+
const lockPath = join(NOTICES_DIR, `${threadId}.lock`);
|
|
54
|
+
for (let attempt = 0; attempt < LOCK_MAX_ATTEMPTS; attempt++) {
|
|
55
|
+
try {
|
|
56
|
+
writeFileSync(lockPath, JSON.stringify({ pid: process.pid, ts: Date.now() }), {
|
|
57
|
+
encoding: "utf8",
|
|
58
|
+
flag: "wx",
|
|
59
|
+
});
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
try {
|
|
64
|
+
const holder = JSON.parse(readFileSync(lockPath, "utf8"));
|
|
65
|
+
if (!isPidAlive(holder.pid) || Date.now() - holder.ts > LOCK_STALE_MS) {
|
|
66
|
+
unlinkSync(lockPath); // dead or stale holder — take over next attempt
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Corrupt/vanished lock — remove and retry.
|
|
72
|
+
try {
|
|
73
|
+
unlinkSync(lockPath);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
/* already gone */
|
|
77
|
+
}
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
sleepSync(LOCK_RETRY_MS);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
log.warn(`[passive-notice] lock contention for thread ${threadId} — proceeding unlocked`);
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
function releaseNoticeLock(threadId) {
|
|
87
|
+
const lockPath = join(NOTICES_DIR, `${threadId}.lock`);
|
|
88
|
+
try {
|
|
89
|
+
const holder = JSON.parse(readFileSync(lockPath, "utf8"));
|
|
90
|
+
if (holder.pid === process.pid)
|
|
91
|
+
unlinkSync(lockPath);
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
/* already gone or not ours */
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function readNotices(threadId) {
|
|
98
|
+
const file = noticesFilePath(threadId);
|
|
99
|
+
try {
|
|
100
|
+
if (!existsSync(file))
|
|
101
|
+
return [];
|
|
102
|
+
const parsed = JSON.parse(readFileSync(file, "utf8"));
|
|
103
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
log.warn(`[passive-notice] Failed to read notices for thread ${threadId}: ${errorMessage(err)}`);
|
|
107
|
+
return [];
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/** Queue an FYI notice for a thread's next delivered turn. Never wakes the agent. */
|
|
111
|
+
export function pushPassiveNotice(threadId, text) {
|
|
112
|
+
try {
|
|
113
|
+
mkdirSync(NOTICES_DIR, { recursive: true });
|
|
114
|
+
const locked = acquireNoticeLock(threadId);
|
|
115
|
+
try {
|
|
116
|
+
const notices = readNotices(threadId);
|
|
117
|
+
notices.push({ text, createdAt: new Date().toISOString() });
|
|
118
|
+
// Bounded: keep only the freshest MAX_NOTICES — stale FYIs have no value.
|
|
119
|
+
const bounded = notices.slice(-MAX_NOTICES);
|
|
120
|
+
const file = noticesFilePath(threadId);
|
|
121
|
+
const tmp = `${file}.tmp.${process.pid}`;
|
|
122
|
+
writeFileSync(tmp, JSON.stringify(bounded, null, 2), "utf8");
|
|
123
|
+
renameSync(tmp, file);
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
if (locked)
|
|
127
|
+
releaseNoticeLock(threadId);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
log.warn(`[passive-notice] Failed to push notice for thread ${threadId}: ${errorMessage(err)}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Read-and-clear (delivered-once semantics). Returns oldest→newest.
|
|
136
|
+
*
|
|
137
|
+
* Drain claims the queue file via atomic rename (under the same lock pushes
|
|
138
|
+
* take), so a push landing mid-drain writes a FRESH queue file and survives.
|
|
139
|
+
* Claims are per-pid; claims left by a crashed process are swept in too
|
|
140
|
+
* (redelivery of an FYI beats losing it).
|
|
141
|
+
*/
|
|
142
|
+
export function drainPassiveNotices(threadId) {
|
|
143
|
+
const file = noticesFilePath(threadId);
|
|
144
|
+
const claimPath = `${file}.claim.${process.pid}`;
|
|
145
|
+
const drained = [];
|
|
146
|
+
// Sweep litter left by crashed peers: claims orphaned by a dead drainer AND
|
|
147
|
+
// `.tmp.<pid>` half-writes left by a push that died between write and rename.
|
|
148
|
+
// Both are keyed by the writer's pid; anything owned by a gone pid is dead.
|
|
149
|
+
try {
|
|
150
|
+
const claimPrefix = `${threadId}.json.claim.`;
|
|
151
|
+
const tmpPrefix = `${threadId}.json.tmp.`;
|
|
152
|
+
for (const entry of readdirSync(NOTICES_DIR)) {
|
|
153
|
+
if (entry.startsWith(claimPrefix)) {
|
|
154
|
+
const pid = Number(entry.slice(claimPrefix.length));
|
|
155
|
+
if (!Number.isInteger(pid) || pid === process.pid || isPidAlive(pid))
|
|
156
|
+
continue;
|
|
157
|
+
const orphanPath = join(NOTICES_DIR, entry);
|
|
158
|
+
try {
|
|
159
|
+
const parsed = JSON.parse(readFileSync(orphanPath, "utf8"));
|
|
160
|
+
if (Array.isArray(parsed))
|
|
161
|
+
drained.push(...parsed);
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
/* corrupt orphan — drop it */
|
|
165
|
+
}
|
|
166
|
+
try {
|
|
167
|
+
unlinkSync(orphanPath);
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
/* already gone */
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
else if (entry.startsWith(tmpPrefix)) {
|
|
174
|
+
// A crashed push's temp file: its contents never became the live queue
|
|
175
|
+
// (the rename never ran), so it may be a partial write — discard rather
|
|
176
|
+
// than risk resurrecting corrupt/duplicate notices. Only reap dead pids
|
|
177
|
+
// so a concurrent live push's in-flight temp is never deleted.
|
|
178
|
+
const pid = Number(entry.slice(tmpPrefix.length));
|
|
179
|
+
if (!Number.isInteger(pid) || pid === process.pid || isPidAlive(pid))
|
|
180
|
+
continue;
|
|
181
|
+
try {
|
|
182
|
+
unlinkSync(join(NOTICES_DIR, entry));
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
/* already gone */
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
/* dir missing — nothing queued yet */
|
|
192
|
+
}
|
|
193
|
+
// A same-pid claim left by THIS process's earlier crashed drain (renamed but
|
|
194
|
+
// never consumed) would be silently clobbered by the rename below, losing its
|
|
195
|
+
// notices. Consume it first so the notices survive.
|
|
196
|
+
if (existsSync(claimPath)) {
|
|
197
|
+
try {
|
|
198
|
+
const parsed = JSON.parse(readFileSync(claimPath, "utf8"));
|
|
199
|
+
if (Array.isArray(parsed))
|
|
200
|
+
drained.push(...parsed);
|
|
201
|
+
unlinkSync(claimPath);
|
|
202
|
+
}
|
|
203
|
+
catch (err) {
|
|
204
|
+
if (err.code !== "ENOENT")
|
|
205
|
+
log.warn(`[passive-notice] stale claim recovery failed for thread ${threadId}: ${errorMessage(err)}`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (existsSync(file)) {
|
|
209
|
+
const locked = acquireNoticeLock(threadId);
|
|
210
|
+
try {
|
|
211
|
+
renameSync(file, claimPath);
|
|
212
|
+
}
|
|
213
|
+
catch (err) {
|
|
214
|
+
log.debug(`[passive-notice] drain claim failed for thread ${threadId}: ${errorMessage(err)}`);
|
|
215
|
+
}
|
|
216
|
+
finally {
|
|
217
|
+
if (locked)
|
|
218
|
+
releaseNoticeLock(threadId);
|
|
219
|
+
}
|
|
220
|
+
try {
|
|
221
|
+
const parsed = JSON.parse(readFileSync(claimPath, "utf8"));
|
|
222
|
+
if (Array.isArray(parsed))
|
|
223
|
+
drained.push(...parsed);
|
|
224
|
+
unlinkSync(claimPath);
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
if (err.code !== "ENOENT")
|
|
228
|
+
log.warn(`[passive-notice] drain read failed for thread ${threadId}: ${errorMessage(err)}`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return drained;
|
|
232
|
+
}
|
|
233
|
+
/** Non-destructive peek (dashboard/diagnostics). */
|
|
234
|
+
export function peekPassiveNotices(threadId) {
|
|
235
|
+
return readNotices(threadId);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Drain and render the FYI block appended to a delivered turn (next to the
|
|
239
|
+
* Persistent Context block in message-delivery). Empty string when quiet.
|
|
240
|
+
* The framing does the "aware, not commanded" work: explicit no-action wording
|
|
241
|
+
* so a later operator voice about these makes sense without triggering work.
|
|
242
|
+
*/
|
|
243
|
+
export function renderPassiveNoticeBlock(threadId) {
|
|
244
|
+
const notices = drainPassiveNotices(threadId);
|
|
245
|
+
if (notices.length === 0)
|
|
246
|
+
return "";
|
|
247
|
+
// Per-item fault isolation: one malformed record (bad createdAt, non-string
|
|
248
|
+
// text) must not throw AFTER the drain already consumed the batch — that
|
|
249
|
+
// would lose every notice in the turn. Bad records are skipped, not fatal.
|
|
250
|
+
const lines = [];
|
|
251
|
+
for (const n of notices) {
|
|
252
|
+
try {
|
|
253
|
+
const stamp = typeof n.createdAt === "string" ? n.createdAt.slice(0, 16).replace("T", " ") : "?";
|
|
254
|
+
if (typeof n.text !== "string" || n.text.length === 0)
|
|
255
|
+
continue;
|
|
256
|
+
lines.push(`- [${stamp}] ${n.text}`);
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
/* skip malformed record */
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (lines.length === 0)
|
|
263
|
+
return "";
|
|
264
|
+
// Delivery-loss note: drain happens at render time, inside the poll loop's
|
|
265
|
+
// transport-liveness guards — the same consumption bar the system applies to
|
|
266
|
+
// operator messages themselves. A deeper delivered-ack protocol was reviewed
|
|
267
|
+
// and deliberately not built (FYI notices must not carry more delivery
|
|
268
|
+
// guarantees than operator messages do).
|
|
269
|
+
return (`\n\n## Situational Notices (FYI — context, not command)\n` +
|
|
270
|
+
`These are awareness-only updates. Do NOT act on them, reply to them, or treat them as tasks; ` +
|
|
271
|
+
`they exist so later operator messages about them make sense.\n` +
|
|
272
|
+
lines.join("\n"));
|
|
273
|
+
}
|
|
274
|
+
//# sourceMappingURL=passive-notice.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passive-notice.service.js","sourceRoot":"","sources":["../../src/services/passive-notice.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spawn-common.d.ts","sourceRoot":"","sources":["../../src/services/spawn-common.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAgCH,OAAO,EAAe,KAAK,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AA+BlE,mDAAmD;AACnD,MAAM,MAAM,WAAW,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"spawn-common.d.ts","sourceRoot":"","sources":["../../src/services/spawn-common.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAgCH,OAAO,EAAe,KAAK,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AA+BlE,mDAAmD;AACnD,MAAM,MAAM,WAAW,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAmC/E,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,KAAG,MAAM,CAAC,UAKpF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,GAAI,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAI1F,CAAC;AAWF,iDAAiD;AACjD,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C;AAED,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,EAAE,SAAS,MAAM,KAAG,MAAM,GAAG,IA2BvE,CAAC;AAEF,2FAA2F;AAC3F,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA8BjE;AASD,eAAO,MAAM,yBAAyB,GAAI,mBAAmB,MAAM,KAAG,MAAM,GAAG,SAK9E,CAAC;AAOF,eAAO,MAAM,0BAA0B,QAAO,OAAmC,CAAC;AAClF,eAAO,MAAM,2BAA2B,GAAI,GAAG,OAAO,KAAG,IAExD,CAAC;AASF;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,GACjB;IAAE,SAAS,EAAE,kBAAkB,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAYvD;AAED,mFAAmF;AACnF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAMhG;AAED;kEACkE;AAClE,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,EAAE,UAAU,MAAM,KAAG,MACkD,CAAC;AA6RvH;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,UAAU,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;yCACqC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,KAAK,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,eAAe,IAAI,eAAe,CAKjD;AAiDD,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAElE;AA4ED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,eAAe,EACrB,eAAe,EAAE,sBAAsB,GACtC,OAAO,CAAC,WAAW,CAAC,CAkDtB"}
|
|
@@ -63,6 +63,17 @@ const ENV_DENYLIST = new Set([
|
|
|
63
63
|
"DASHBOARD_TOKEN",
|
|
64
64
|
"MCP_START_COMMAND",
|
|
65
65
|
"WATCHER_START_COMMAND",
|
|
66
|
+
// Isolated-runtime plumbing that must stay MCP-private. When IsolateMcpRuntime is
|
|
67
|
+
// on, the supervisor exports NPM_CONFIG_CACHE (a dedicated npm/npx cache) so the
|
|
68
|
+
// MCP's own `npx …@latest` restart resolves/stages under a private cache the dev
|
|
69
|
+
// repo never touches. That var is inherited all the way down to here — if it leaked
|
|
70
|
+
// into agent workers, a worker's `npm`/`npx` in the dev checkout would use the SAME
|
|
71
|
+
// private cache the MCP restarts from, re-introducing the exact shared-cache coupling
|
|
72
|
+
// the feature exists to sever. Deny it so workers fall back to the default cache.
|
|
73
|
+
// (No-op when the knob is off: the var is simply unset.) MCP_WORKING_DIR is the
|
|
74
|
+
// MCP's private cwd hint — meaningless to children, dropped for the same hygiene.
|
|
75
|
+
"NPM_CONFIG_CACHE",
|
|
76
|
+
"MCP_WORKING_DIR",
|
|
66
77
|
"CLAUDE_CODE_OAUTH_TOKEN",
|
|
67
78
|
"COPILOT_PROVIDER_BASE_URL",
|
|
68
79
|
"COPILOT_PROVIDER_TYPE",
|
|
@@ -334,7 +345,9 @@ async function handleProcessExit(code, threadId, pid, pidFilePath, entry, proces
|
|
|
334
345
|
await deleteTelegramTopicByBotApi(token, cId, topicId);
|
|
335
346
|
},
|
|
336
347
|
};
|
|
337
|
-
|
|
348
|
+
// Pass the REAL exit code through — the board's exit safety net records
|
|
349
|
+
// it on the card, distinguishing a crash from a clean-exit-without-report.
|
|
350
|
+
await decommissionWorker(entry, { db, telegram: telegramAdapter, chatId, threadLifecycle }, code);
|
|
338
351
|
}
|
|
339
352
|
else {
|
|
340
353
|
// Non-worker (e.g., keepAlive thread): mark exited so KeeperService can restart.
|