sensorium-mcp 3.1.3 → 3.1.5
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 +251 -39
- package/dist/config/agent-settings.d.ts +11 -0
- package/dist/config/agent-settings.d.ts.map +1 -1
- package/dist/config/agent-settings.js +79 -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 +7 -0
- package/dist/config/misc-settings.d.ts.map +1 -1
- package/dist/config/misc-settings.js +38 -1
- package/dist/config/misc-settings.js.map +1 -1
- package/dist/dashboard/routes/codex.d.ts +14 -0
- package/dist/dashboard/routes/codex.d.ts.map +1 -0
- package/dist/dashboard/routes/codex.js +92 -0
- package/dist/dashboard/routes/codex.js.map +1 -0
- package/dist/dashboard/routes/prompts.d.ts +2 -2
- package/dist/dashboard/routes/prompts.d.ts.map +1 -1
- package/dist/dashboard/routes/prompts.js +2 -2
- package/dist/dashboard/routes/prompts.js.map +1 -1
- package/dist/dashboard/routes/threads-read.d.ts +10 -7
- package/dist/dashboard/routes/threads-read.d.ts.map +1 -1
- package/dist/dashboard/routes/threads-read.js +21 -16
- package/dist/dashboard/routes/threads-read.js.map +1 -1
- package/dist/dashboard/routes.d.ts.map +1 -1
- package/dist/dashboard/routes.js +3 -0
- package/dist/dashboard/routes.js.map +1 -1
- package/dist/dashboard/spa.html +11 -11
- package/dist/data/memory/bootstrap.d.ts +1 -8
- package/dist/data/memory/bootstrap.d.ts.map +1 -1
- package/dist/data/memory/bootstrap.js +27 -37
- package/dist/data/memory/bootstrap.js.map +1 -1
- package/dist/data/memory/consolidation.d.ts +20 -1
- package/dist/data/memory/consolidation.d.ts.map +1 -1
- package/dist/data/memory/consolidation.js +53 -3
- package/dist/data/memory/consolidation.js.map +1 -1
- package/dist/data/memory/index.d.ts +0 -4
- package/dist/data/memory/index.d.ts.map +1 -1
- package/dist/data/memory/index.js +0 -4
- package/dist/data/memory/index.js.map +1 -1
- package/dist/data/memory/key-knowledge.d.ts +51 -0
- package/dist/data/memory/key-knowledge.d.ts.map +1 -0
- package/dist/data/memory/key-knowledge.js +128 -0
- package/dist/data/memory/key-knowledge.js.map +1 -0
- package/dist/data/memory/migration-runner.d.ts +1 -1
- package/dist/data/memory/migration-runner.d.ts.map +1 -1
- package/dist/data/memory/migration-runner.js +23 -1
- package/dist/data/memory/migration-runner.js.map +1 -1
- package/dist/data/memory/narrative-lint.d.ts +2 -2
- package/dist/data/memory/narrative-lint.d.ts.map +1 -1
- package/dist/data/memory/narrative-lint.js +23 -13
- package/dist/data/memory/narrative-lint.js.map +1 -1
- package/dist/data/memory/narrative-resolutions.d.ts +7 -2
- package/dist/data/memory/narrative-resolutions.d.ts.map +1 -1
- package/dist/data/memory/narrative-resolutions.js +7 -8
- package/dist/data/memory/narrative-resolutions.js.map +1 -1
- package/dist/data/memory/narrative-sources.d.ts +1 -1
- package/dist/data/memory/narrative-sources.d.ts.map +1 -1
- package/dist/data/memory/narrative-sources.js +8 -3
- package/dist/data/memory/narrative-sources.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 +47 -29
- package/dist/data/memory/narrative.js.map +1 -1
- package/dist/data/memory/note-archival.d.ts +1 -1
- package/dist/data/memory/note-archival.d.ts.map +1 -1
- package/dist/data/memory/note-archival.js +7 -3
- package/dist/data/memory/note-archival.js.map +1 -1
- package/dist/data/memory/note-embeddings.d.ts +7 -0
- package/dist/data/memory/note-embeddings.d.ts.map +1 -1
- package/dist/data/memory/note-embeddings.js +6 -2
- package/dist/data/memory/note-embeddings.js.map +1 -1
- package/dist/data/memory/schema-ddl.d.ts +1 -1
- package/dist/data/memory/schema-ddl.d.ts.map +1 -1
- package/dist/data/memory/schema-ddl.js +3 -1
- package/dist/data/memory/schema-ddl.js.map +1 -1
- package/dist/data/memory/semantic-notes.d.ts +13 -8
- package/dist/data/memory/semantic-notes.d.ts.map +1 -1
- package/dist/data/memory/semantic-notes.js +12 -17
- package/dist/data/memory/semantic-notes.js.map +1 -1
- package/dist/data/memory/thread-registry.d.ts +7 -1
- package/dist/data/memory/thread-registry.d.ts.map +1 -1
- package/dist/data/memory/thread-registry.js +14 -5
- package/dist/data/memory/thread-registry.js.map +1 -1
- package/dist/data/memory/utils.d.ts +6 -0
- package/dist/data/memory/utils.d.ts.map +1 -1
- package/dist/data/memory/utils.js +13 -0
- package/dist/data/memory/utils.js.map +1 -1
- package/dist/integrations/openai/speech.js +4 -4
- 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/llm/prompts/narrative.d.ts.map +1 -1
- package/dist/llm/prompts/narrative.js +27 -86
- package/dist/llm/prompts/narrative.js.map +1 -1
- package/dist/services/claude-spawn.service.d.ts.map +1 -1
- package/dist/services/claude-spawn.service.js +6 -1
- package/dist/services/claude-spawn.service.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 +64 -58
- package/dist/services/codex-spawn.service.js.map +1 -1
- package/dist/services/consolidation.service.d.ts.map +1 -1
- package/dist/services/consolidation.service.js +10 -43
- package/dist/services/consolidation.service.js.map +1 -1
- package/dist/services/copilot-spawn.service.d.ts.map +1 -1
- package/dist/services/copilot-spawn.service.js +6 -1
- package/dist/services/copilot-spawn.service.js.map +1 -1
- package/dist/services/daily-session.d.ts +22 -11
- package/dist/services/daily-session.d.ts.map +1 -1
- package/dist/services/daily-session.js +69 -24
- package/dist/services/daily-session.js.map +1 -1
- package/dist/services/dispatcher/poller.d.ts.map +1 -1
- package/dist/services/dispatcher/poller.js +8 -15
- package/dist/services/dispatcher/poller.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 +14 -1
- package/dist/services/mcp-config.service.js.map +1 -1
- package/dist/services/memory-briefing.service.d.ts +1 -1
- package/dist/services/memory-briefing.service.d.ts.map +1 -1
- package/dist/services/memory-briefing.service.js +27 -73
- package/dist/services/memory-briefing.service.js.map +1 -1
- package/dist/services/memory-pruning.service.d.ts.map +1 -1
- package/dist/services/memory-pruning.service.js +22 -4
- package/dist/services/memory-pruning.service.js.map +1 -1
- package/dist/services/predefined-prompts.d.ts +11 -0
- package/dist/services/predefined-prompts.d.ts.map +1 -0
- package/dist/services/predefined-prompts.js +25 -0
- package/dist/services/predefined-prompts.js.map +1 -0
- package/dist/services/spawn-common.d.ts +10 -2
- package/dist/services/spawn-common.d.ts.map +1 -1
- package/dist/services/spawn-common.js +25 -4
- 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/sessions/mcp-registry.d.ts +7 -2
- package/dist/sessions/mcp-registry.d.ts.map +1 -1
- package/dist/sessions/mcp-registry.js +52 -30
- package/dist/sessions/mcp-registry.js.map +1 -1
- package/dist/tools/defs/memory-defs.d.ts.map +1 -1
- package/dist/tools/defs/memory-defs.js +4 -0
- package/dist/tools/defs/memory-defs.js.map +1 -1
- package/dist/tools/delegate-tool.js +2 -2
- package/dist/tools/delegate-tool.js.map +1 -1
- package/dist/tools/memory-tools.d.ts.map +1 -1
- package/dist/tools/memory-tools.js +9 -1
- package/dist/tools/memory-tools.js.map +1 -1
- package/dist/tools/start-session-tool.d.ts.map +1 -1
- package/dist/tools/start-session-tool.js +13 -1
- package/dist/tools/start-session-tool.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 +45 -59
- 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 +4 -21
- package/dist/tools/wait/message-delivery.js.map +1 -1
- package/dist/tools/wait/message-processing.d.ts.map +1 -1
- package/dist/tools/wait/message-processing.js +2 -1
- package/dist/tools/wait/message-processing.js.map +1 -1
- package/dist/tools/wait/poll-loop.d.ts.map +1 -1
- package/dist/tools/wait/poll-loop.js +8 -8
- package/dist/tools/wait/poll-loop.js.map +1 -1
- package/package.json +1 -1
- package/templates/increment-pr-pipeline.default.md +79 -0
- package/dist/data/memory/reflection-dedup.d.ts +0 -17
- package/dist/data/memory/reflection-dedup.d.ts.map +0 -1
- package/dist/data/memory/reflection-dedup.js +0 -55
- package/dist/data/memory/reflection-dedup.js.map +0 -1
- package/dist/data/memory/reflection-gates.d.ts +0 -40
- package/dist/data/memory/reflection-gates.d.ts.map +0 -1
- package/dist/data/memory/reflection-gates.js +0 -220
- package/dist/data/memory/reflection-gates.js.map +0 -1
- package/dist/data/memory/reflection-sources.d.ts +0 -13
- package/dist/data/memory/reflection-sources.d.ts.map +0 -1
- package/dist/data/memory/reflection-sources.js +0 -115
- package/dist/data/memory/reflection-sources.js.map +0 -1
- package/dist/data/memory/reflection.d.ts +0 -43
- package/dist/data/memory/reflection.d.ts.map +0 -1
- package/dist/data/memory/reflection.js +0 -329
- package/dist/data/memory/reflection.js.map +0 -1
- package/dist/llm/prompts/reflection.d.ts +0 -6
- package/dist/llm/prompts/reflection.d.ts.map +0 -1
- package/dist/llm/prompts/reflection.js +0 -77
- package/dist/llm/prompts/reflection.js.map +0 -1
|
@@ -96,4 +96,17 @@ export function parseJsonObject(val) {
|
|
|
96
96
|
return {};
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Resolve an optional `validUntil` argument into a strictly-future ISO timestamp,
|
|
101
|
+
* or null. Garbage (unparseable) and past/now instants both yield null so the
|
|
102
|
+
* note is saved permanent rather than born already-due. Exported for tests.
|
|
103
|
+
*/
|
|
104
|
+
export function resolveFutureExpiry(validUntil) {
|
|
105
|
+
if (typeof validUntil !== "string")
|
|
106
|
+
return null;
|
|
107
|
+
const parsed = parseRelativeTime(validUntil);
|
|
108
|
+
if (!parsed)
|
|
109
|
+
return null;
|
|
110
|
+
return new Date(parsed).getTime() > Date.now() ? parsed : null;
|
|
111
|
+
}
|
|
99
112
|
//# sourceMappingURL=utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/data/memory/utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,sEAAsE;AACtE,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,OAAO,GAAG,MAAM,IAAI,UAAU,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;AACpE,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,MAAM;IACpB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,UAAU,CAAC,GAAY;IACrC,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACnD,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;AAC7B,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,cAAc,CAAC,GAA8B;IAC3D,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,gFAAgF;AAEhF;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC1D,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAE3C,qDAAqD;IACrD,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;IACjC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5D,OAAO,MAAM,CAAC,WAAW,EAAE,CAAC;IAC9B,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAEpC,iCAAiC;IACjC,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,EAAE,GAAG,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;QACxF,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;IACzB,CAAC;IAED,yCAAyC;IACzC,IAAI,KAAK,KAAK,WAAW,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,EAAE,GAAG,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QAC5F,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;IACzB,CAAC;IAED,2BAA2B;IAC3B,IAAI,KAAK,KAAK,WAAW,EAAE,CAAC;QAC1B,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IACzE,CAAC;IAED,2BAA2B;IAC3B,IAAI,KAAK,KAAK,WAAW,EAAE,CAAC;QAC1B,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IAChE,CAAC;IAED,sDAAsD;IACtD,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC9D,IAAI,CAAC,EAAE,CAAC;QACN,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC/B,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QAC9C,MAAM,EAAE,GAAG,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QAC3E,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACpD,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,eAAe,CAAC,GAA8B;IAC5D,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/data/memory/utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { recordUsage } from "../../lib/usage-metering/index.js";
|
|
7
7
|
import { errorMessage } from "../../lib/utils.js";
|
|
8
|
-
import { abortableDelay, computeBackoffMs, DEFAULT_RETRY_POLICY } from "../../
|
|
8
|
+
import { abortableDelay, computeBackoffMs, DEFAULT_RETRY_POLICY } from "../../lib/http-retry.js";
|
|
9
9
|
// ─── TTS ──────────────────────────────────────────────────────────────────
|
|
10
10
|
/** Valid TTS voice names. */
|
|
11
11
|
export const TTS_VOICES = ["alloy", "echo", "fable", "onyx", "nova", "shimmer"];
|
|
@@ -45,10 +45,10 @@ export async function textToSpeech(text, apiKey, voice = "nova") {
|
|
|
45
45
|
if (!(err instanceof TypeError))
|
|
46
46
|
throw err;
|
|
47
47
|
if (!attemptsRemaining) {
|
|
48
|
-
// Tag the leg and preserve the
|
|
49
|
-
// can surface the real reason (ENOTFOUND/ECONNRESET/…).
|
|
48
|
+
// Tag the leg and preserve the original transport error so the caller's
|
|
49
|
+
// error log can surface the real reason (ENOTFOUND/ECONNRESET/…).
|
|
50
50
|
throw new Error(`OpenAI TTS request failed: ${errorMessage(err)}`, {
|
|
51
|
-
cause: err
|
|
51
|
+
cause: err,
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
54
|
await abortableDelay(computeBackoffMs(attempt, policy));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"speech.js","sourceRoot":"","sources":["../../../src/integrations/openai/speech.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"speech.js","sourceRoot":"","sources":["../../../src/integrations/openai/speech.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,91 @@
|
|
|
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 declare const TRANSIENT_STATUS: ReadonlySet<number>;
|
|
27
|
+
/** True when `status` is in the transient (retryable) set. */
|
|
28
|
+
export declare function isTransientStatus(status: number): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Parse the `Retry-After` response header into milliseconds.
|
|
31
|
+
*
|
|
32
|
+
* Per RFC 9110 the value is either a number of seconds (`Retry-After: 120`) or
|
|
33
|
+
* an HTTP-date (`Retry-After: Wed, 21 Oct 2026 07:28:00 GMT`). Returns
|
|
34
|
+
* `undefined` when the header is absent or unparseable, and clamps any positive
|
|
35
|
+
* result to {@link RETRY_AFTER_MAX_MS}. A date in the past yields `0`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function parseRetryAfterMs(response: Response): number | undefined;
|
|
38
|
+
/** Tunables for {@link computeBackoffMs} / {@link fetchWithRetry}. */
|
|
39
|
+
export interface RetryPolicy {
|
|
40
|
+
/** Total number of attempts (1 = no retry). */
|
|
41
|
+
maxAttempts: number;
|
|
42
|
+
/** Base delay for the first backoff step, in ms. */
|
|
43
|
+
baseMs: number;
|
|
44
|
+
/** Hard ceiling for any single backoff wait, in ms. */
|
|
45
|
+
capMs: number;
|
|
46
|
+
}
|
|
47
|
+
/** Sensible default: 3 attempts, 500ms base, 8s cap. */
|
|
48
|
+
export declare const DEFAULT_RETRY_POLICY: RetryPolicy;
|
|
49
|
+
/**
|
|
50
|
+
* Exponential backoff with FULL jitter.
|
|
51
|
+
*
|
|
52
|
+
* The deterministic component is `baseMs * 2^attempt`, capped at `capMs`. We
|
|
53
|
+
* then draw a uniformly random value in `[0, capped]` (the "full jitter"
|
|
54
|
+
* strategy from the AWS Architecture Blog). Full jitter — rather than
|
|
55
|
+
* equal-jitter or none — is chosen because it maximizes spread across many
|
|
56
|
+
* concurrent clients hammering the same recovering proxy, which minimizes
|
|
57
|
+
* retry-storm synchronization.
|
|
58
|
+
*
|
|
59
|
+
* @param attempt Zero-based retry index (0 for the first backoff).
|
|
60
|
+
*/
|
|
61
|
+
export declare function computeBackoffMs(attempt: number, policy?: Pick<RetryPolicy, "baseMs" | "capMs">): number;
|
|
62
|
+
/**
|
|
63
|
+
* Sleep for `ms`, rejecting immediately if `signal` aborts mid-wait.
|
|
64
|
+
*
|
|
65
|
+
* Retries must not swallow an intentional shutdown: if the caller's signal
|
|
66
|
+
* fires while we are backing off, propagate the abort at once rather than
|
|
67
|
+
* finishing the sleep.
|
|
68
|
+
*/
|
|
69
|
+
export declare function abortableDelay(ms: number, signal?: AbortSignal): Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* `fetch` with bounded, jittered retry on transient failures.
|
|
72
|
+
*
|
|
73
|
+
* Behavior:
|
|
74
|
+
* - Performs the fetch. If the response status is transient AND attempts
|
|
75
|
+
* remain, waits (honoring `Retry-After` when present, otherwise
|
|
76
|
+
* {@link computeBackoffMs}) and retries. Otherwise returns the response — the
|
|
77
|
+
* caller still inspects `.ok` to handle permanent (4xx) errors itself.
|
|
78
|
+
* - Only a thrown `TypeError` — how native `fetch` reports a genuine transport
|
|
79
|
+
* failure (DNS, ECONNREFUSED, socket reset) — is retried (if attempts
|
|
80
|
+
* remain, else the last error is rethrown). Every other throw propagates
|
|
81
|
+
* IMMEDIATELY with no wasted backoff: an AbortError / TimeoutError from
|
|
82
|
+
* `init.signal` (or `AbortSignal.timeout`) is intentional and must not be
|
|
83
|
+
* retried, and a programmer error (e.g. a bad argument) is not transient.
|
|
84
|
+
* - The backoff sleep is abort-aware: aborting `init.signal` mid-wait rejects
|
|
85
|
+
* at once.
|
|
86
|
+
*
|
|
87
|
+
* Kept PURE — no knowledge of any caller secret. Token redaction is layered on
|
|
88
|
+
* top by the caller's own try/catch.
|
|
89
|
+
*/
|
|
90
|
+
export declare function fetchWithRetry(input: string | URL | Request, init?: RequestInit, policy?: RetryPolicy): Promise<Response>;
|
|
91
|
+
//# sourceMappingURL=http-retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-retry.d.ts","sourceRoot":"","sources":["../../src/lib/http-retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAA2C,CAAC;AAE7F,8DAA8D;AAC9D,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEzD;AASD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CAmBxE;AAED,sEAAsE;AACtE,MAAM,WAAW,WAAW;IAC1B,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wDAAwD;AACxD,eAAO,MAAM,oBAAoB,EAAE,WAIlC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAwB,GACnE,MAAM,CAIR;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAmB9E;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAC7B,IAAI,CAAC,EAAE,WAAW,EAClB,MAAM,GAAE,WAAkC,GACzC,OAAO,CAAC,QAAQ,CAAC,CAyCnB"}
|
|
@@ -0,0 +1,177 @@
|
|
|
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
|
+
}
|
|
177
|
+
//# sourceMappingURL=http-retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-retry.js","sourceRoot":"","sources":["../../src/lib/http-retry.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,7 +23,7 @@ export const MODEL_PRICES = {
|
|
|
23
23
|
// OpenAI transcription — $0.006/min
|
|
24
24
|
"whisper-1": { audioPerMinute: 0.006 },
|
|
25
25
|
// Groq transcription — $0.111/hr → per minute
|
|
26
|
-
"whisper-large-v3": { audioPerMinute: 0.
|
|
26
|
+
"whisper-large-v3": { audioPerMinute: 0.0018498 },
|
|
27
27
|
};
|
|
28
28
|
/**
|
|
29
29
|
* Pure cost in USD for one usage event. Unknown models (absent from the table)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pricing.js","sourceRoot":"","sources":["../../../src/lib/usage-metering/pricing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAWH;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAA+B;IACtD,cAAc;IACd,QAAQ,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,aAAa,EAAE,EAAE,EAAE;IAClD,aAAa,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE;IACzD,iCAAiC;IACjC,wBAAwB,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;IAChD,oCAAoC;IACpC,WAAW,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE;IACtC,8CAA8C;IAC9C,kBAAkB,EAAE,EAAE,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"pricing.js","sourceRoot":"","sources":["../../../src/lib/usage-metering/pricing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAWH;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAA+B;IACtD,cAAc;IACd,QAAQ,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,aAAa,EAAE,EAAE,EAAE;IAClD,aAAa,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE;IACzD,iCAAiC;IACjC,wBAAwB,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;IAChD,oCAAoC;IACpC,WAAW,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE;IACtC,8CAA8C;IAC9C,kBAAkB,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE;CAClD,CAAC;AAUF;;;;GAIG;AACH,MAAM,UAAU,MAAM,CAAC,KAAgB;IACrC,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACxC,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,CAAC;IACrB,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QAC7C,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,SAAS,CAAC,GAAG,KAAK,CAAC,YAAY,CAAC;IAC/D,CAAC;IACD,IAAI,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,gBAAgB,EAAE,CAAC;QAClD,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,GAAG,SAAS,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC;IACpE,CAAC;IACD,IAAI,KAAK,CAAC,cAAc,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QAC/C,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC,cAAc,CAAC;IAC1D,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"narrative.d.ts","sourceRoot":"","sources":["../../../src/llm/prompts/narrative.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"narrative.d.ts","sourceRoot":"","sources":["../../../src/llm/prompts/narrative.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAgBhF,wBAAgB,WAAW,CACzB,UAAU,EAAE,mBAAmB,EAC/B,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,MAAM,CA2BR;AAED,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,mBAAmB,EAC/B,mBAAmB,EAAE,MAAM,EAC3B,eAAe,EAAE,mBAAmB,EACpC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,MAAM,CAqBR"}
|
|
@@ -1,67 +1,35 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Prompt builders for the temporal narrative pipeline.
|
|
3
3
|
*/
|
|
4
|
+
/**
|
|
5
|
+
* Shared house style for every resolution: a dated event log (what + when),
|
|
6
|
+
* never flattering prose or thematic essays. Keeping one constant avoids the
|
|
7
|
+
* near-identical per-resolution style blocks drifting apart.
|
|
8
|
+
*/
|
|
9
|
+
const LOG_STYLE = `STYLE:
|
|
10
|
+
- A dated log: one event per line, each line self-contained. NOT prose paragraphs, NOT thematic arcs.
|
|
11
|
+
- First person for yourself ("I ..."), third person for the operator ("The operator ...").
|
|
12
|
+
- Every line names an exact system/thread/feature/version/ID and carries at least one concrete identifier.
|
|
13
|
+
- Keep cause->effect in each line: what triggered it, what was decided, what resulted.
|
|
14
|
+
- Date each entry with a single point date. A "YYYY-MM-DD to YYYY-MM-DD" range is allowed ONLY where the instructions above permit it, and a ranged line must still name the concrete systems/versions/counts — never collapse it into vague wording like "various improvements".
|
|
15
|
+
- FORBIDDEN — do not write summaries, commentary, opinions, assessments, or your own conclusions of any kind (e.g. "what works", "what's fragile", "overall", "this shows", "the project is healthy", "current state"). No praise or filler ("significant progress", "notable", "pivotal", "crucial", "the period was marked by"); no marketing tone.
|
|
16
|
+
- Output ONLY dated event lines: no title, no intro, no closing or summary section whatsoever. Start directly with the first dated entry and stop after the last one.`;
|
|
4
17
|
export function buildPrompt(resolution, episodesText, notesText, episodeCount, periodLabel, periodStart) {
|
|
5
18
|
const startYear = new Date(periodStart).getFullYear();
|
|
6
19
|
const endYear = new Date().getFullYear();
|
|
7
20
|
const instructions = {
|
|
8
|
-
day: `Write a
|
|
9
|
-
week: `Write a
|
|
10
|
-
month: `Write a chronological decision log for this month (${periodLabel}). Format: "Date — decision/event. Reason. Result." One entry per line
|
|
11
|
-
quarter: `Write a
|
|
12
|
-
half_year: `Write a
|
|
21
|
+
day: `Write a dated event log of what happened today (${periodLabel}). One event per line, format: "HH:MM — what happened. Why / what was decided. Result." Chronological. Only real events (decisions, bugs, fixes/features shipped, operator requests) — skip filler and status noise. Name systems, threads, versions, IDs. Target ~400 tokens.`,
|
|
22
|
+
week: `Write a dated event log of the key developments this week (${periodLabel}). One event per line, format: "YYYY-MM-DD — what happened. Why / what was decided. Result." Chronological by day. Only what mattered — decisions that changed direction, bugs that broke something, features shipped; skip routine fixes and status checks. Name systems, threads, versions, IDs. Target ~500 tokens.`,
|
|
23
|
+
month: `Write a chronological decision log for this month (${periodLabel}). Format: "Date — decision/event. Reason. Result." One entry per line, day-level dates, no hours. An important event — a decision that changed direction, a bug that broke something, a feature shipped — gets its OWN single date, with enough context to stand alone. Several less-important events that don't each warrant a line — group them into ONE "YYYY-MM-DD to YYYY-MM-DD" line that still names the concrete systems/versions/counts (never vague wording). Target ~500 tokens.`,
|
|
24
|
+
quarter: `Write a dated decision log for this quarter (${periodLabel}). Format: "Date — decision/event. Reason. Result." One entry per line, day-level dates. A strategic item — direction change, major bug, feature/system shipped, architecture shift — gets its OWN single date; episodes marked [imp: 0.6+] are operator-priority, include them. Several less-important events that don't each warrant a line — group them into ONE "YYYY-MM-DD to YYYY-MM-DD" line that still names the concrete systems/versions/counts (never vague wording). Target ~450 tokens.`,
|
|
25
|
+
half_year: `Write a dated milestone log for this half-year (${periodLabel}). Format: "Date — milestone/decision. Reason. Result." One entry per line, day- or month-level dates. A major turning point — direction change, system shipped, architecture shift — gets its OWN single date. Several less-important events that don't each warrant a line — group them into ONE "YYYY-MM-DD to YYYY-MM-DD" line that still names the concrete systems/versions/counts (never vague wording). Target ~400 tokens.`,
|
|
13
26
|
};
|
|
14
|
-
|
|
15
|
-
day: `STYLE:
|
|
16
|
-
- Write flowing prose, not bullet points or numbered lists. Connect events into a story.
|
|
17
|
-
- First person for yourself ("I did..."), third person for the operator ("The operator...").
|
|
18
|
-
- Name every system, thread, feature by exact name with IDs where available.
|
|
19
|
-
- Be concrete — every sentence needs at least one identifier (name, version, date, ID, number).
|
|
20
|
-
- Preserve cause-and-effect chains: "X happened because Y, which led to Z."
|
|
21
|
-
- No filler phrases: "significant progress", "notable improvement", "pivotal moment", "crucial step".
|
|
22
|
-
- NEVER open with "In [Month]..." or "During [Month]..." — start with what happened.
|
|
23
|
-
- NEVER write introductory or concluding paragraphs that summarize.`,
|
|
24
|
-
week: `STYLE:
|
|
25
|
-
- Write flowing prose, not bullet points or numbered lists. Connect events into a weekly story.
|
|
26
|
-
- First person for yourself ("I did..."), third person for the operator ("The operator...").
|
|
27
|
-
- Name every system, thread, feature by exact name with IDs where available.
|
|
28
|
-
- Be concrete — every sentence needs at least one identifier (name, version, date, ID, number).
|
|
29
|
-
- Preserve cause-and-effect chains across days.
|
|
30
|
-
- No filler phrases: "significant progress", "notable improvement", "pivotal moment", "crucial step".
|
|
31
|
-
- NEVER open with "In [Month]..." or "During [Month]..." — start with what happened.
|
|
32
|
-
- NEVER write introductory or concluding paragraphs that summarize.`,
|
|
33
|
-
month: `STYLE:
|
|
34
|
-
- Each log entry: 1-2 sentences with full context. A reader should understand the entry without reading others.
|
|
35
|
-
- First person for yourself ("I did..."), third person for the operator ("The operator...").
|
|
36
|
-
- Name every system, thread, feature by exact name with IDs where available.
|
|
37
|
-
- No filler phrases: "significant progress", "notable improvement", "pivotal moment", "crucial step".
|
|
38
|
-
- NEVER open with "In [Month]..." or "During [Month]..." or "The period was marked by...".
|
|
39
|
-
- NEVER write introductory or concluding paragraphs.`,
|
|
40
|
-
quarter: `STYLE:
|
|
41
|
-
- Start each initiative with its name on its own line, then write 1-2 prose paragraphs. NO dated entries, NO log format.
|
|
42
|
-
- Write flowing connected narrative — "The memory system entered the quarter with X problem. In April, Y happened because Z, which led to W by May."
|
|
43
|
-
- First person for yourself ("I did..."), third person for the operator ("The operator...").
|
|
44
|
-
- Name every system, thread, feature by exact name with IDs where available.
|
|
45
|
-
- Reference dates and versions naturally within prose, not as entry prefixes.
|
|
46
|
-
- Show cross-month cause-effect — how one month's decisions shaped the next.
|
|
47
|
-
- No filler phrases: "significant progress", "notable improvement", "pivotal moment", "crucial step".
|
|
48
|
-
- NEVER open with "In [Month]..." or "During [Month]..." or "The period was marked by...".
|
|
49
|
-
- NEVER write introductory or concluding paragraphs.`,
|
|
50
|
-
half_year: `STYLE:
|
|
51
|
-
- Write in thematic arc paragraphs, not a chronological list. Each arc = 1-2 paragraphs.
|
|
52
|
-
- First person for yourself ("I did..."), third person for the operator ("The operator...").
|
|
53
|
-
- Name every system, thread, feature by exact name with IDs where available.
|
|
54
|
-
- Within each arc, reference specific dates and versions as evidence of the trajectory.
|
|
55
|
-
- No filler phrases: "significant progress", "notable improvement", "pivotal moment", "crucial step".
|
|
56
|
-
- NEVER open with "In [Month]..." or "During [Month]..." or "The period was marked by...".
|
|
57
|
-
- NEVER write an introductory paragraph. Start directly with the first arc.`,
|
|
58
|
-
};
|
|
59
|
-
return `You are a temporal memory narrator. You create concise records from raw interaction data.
|
|
27
|
+
return `You are a temporal memory narrator. You create concise, dated event logs from raw interaction data.
|
|
60
28
|
|
|
61
29
|
${instructions[resolution]}
|
|
62
30
|
|
|
63
|
-
${
|
|
64
|
-
- Only use years in the range ${startYear}${startYear !== endYear ?
|
|
31
|
+
${LOG_STYLE}
|
|
32
|
+
- Only use years in the range ${startYear}${startYear !== endYear ? `-${endYear}` : ""}.
|
|
65
33
|
|
|
66
34
|
SOURCE DATA (${episodeCount} episodes):
|
|
67
35
|
|
|
@@ -77,43 +45,16 @@ export function buildHierarchicalPrompt(resolution, childNarrativesText, childRe
|
|
|
77
45
|
const startYear = new Date(periodStart).getFullYear();
|
|
78
46
|
const endYear = new Date().getFullYear();
|
|
79
47
|
const instructions = {
|
|
80
|
-
month: `Write a chronological decision log for this month (${periodLabel}). You have ${childCount} weekly narratives below. Format: "Date — decision/event. Reason. Result." One entry per line.
|
|
81
|
-
quarter: `Write a
|
|
82
|
-
half_year: `Write a
|
|
83
|
-
};
|
|
84
|
-
const styleByResolution = {
|
|
85
|
-
month: `STYLE:
|
|
86
|
-
- Each log entry: 1-3 sentences with full context. Explain the situation, not just the fact.
|
|
87
|
-
- First person for yourself ("I did..."), third person for the operator ("The operator...").
|
|
88
|
-
- Name every system, thread, feature by exact name with IDs where available.
|
|
89
|
-
- Every sentence must have at least one identifier (name, version, date, ID, number).
|
|
90
|
-
- No filler phrases: "significant progress", "notable improvement", "pivotal moment", "crucial step", "driven by", "shaped the direction", "the focus remains on".
|
|
91
|
-
- NEVER open with "In [Month]..." or "During [Month]..." or "The period was marked by...".
|
|
92
|
-
- NEVER write introductory or concluding paragraphs.`,
|
|
93
|
-
quarter: `STYLE:
|
|
94
|
-
- Start each initiative with its name on its own line, then write 1-2 prose paragraphs. NO dated entries, NO log format.
|
|
95
|
-
- Write flowing connected narrative that tells the story of each initiative's evolution.
|
|
96
|
-
- First person for yourself ("I did..."), third person for the operator ("The operator...").
|
|
97
|
-
- Name every system, thread, feature by exact name with IDs where available.
|
|
98
|
-
- Reference dates and versions naturally within prose, not as entry prefixes.
|
|
99
|
-
- No filler phrases: "significant progress", "notable improvement", "pivotal moment", "crucial step", "driven by", "shaped the direction", "the focus remains on".
|
|
100
|
-
- NEVER open with "In [Month]..." or "During [Month]..." or "The period was marked by...".
|
|
101
|
-
- NEVER write introductory or concluding paragraphs.`,
|
|
102
|
-
half_year: `STYLE:
|
|
103
|
-
- Write in thematic arc paragraphs. Each arc = 1-2 paragraphs showing system evolution.
|
|
104
|
-
- First person for yourself ("I did..."), third person for the operator ("The operator...").
|
|
105
|
-
- Name every system, thread, feature by exact name with IDs where available.
|
|
106
|
-
- Reference dates and versions as evidence of the trajectory within prose.
|
|
107
|
-
- No filler phrases: "significant progress", "notable improvement", "pivotal moment", "crucial step", "driven by", "shaped the direction", "the focus remains on".
|
|
108
|
-
- NEVER open with "In [Month]..." or "During [Month]..." or "The period was marked by...".
|
|
109
|
-
- NEVER write introductory or concluding paragraphs.`,
|
|
48
|
+
month: `Write a chronological decision log for this month (${periodLabel}). You have ${childCount} weekly narratives below. Format: "Date — decision/event. Reason. Result." One entry per line, day-level dates, no hours. Preserve the reasons and consequences from the weekly narratives — don't compress them away. An important event — a decision that changed direction, a bug that broke something, a feature shipped — gets its OWN single date. Several less-important events that don't each warrant a line — group them into ONE "YYYY-MM-DD to YYYY-MM-DD" line that still names the concrete systems/versions/counts (never vague wording). Target ~500 tokens.`,
|
|
49
|
+
quarter: `Write a dated decision log for this quarter (${periodLabel}). You have ${childCount} monthly logs and possibly top-importance raw episodes below. Format: "Date — decision/event. Reason. Result." One entry per line, day-level dates. Synthesize the monthly logs. A strategic item — direction change, major bug, feature/system shipped, architecture shift — gets its OWN single date; raw episodes marked [imp: 0.6+] are operator-priority, include them. Several less-important events that don't each warrant a line — group them into ONE "YYYY-MM-DD to YYYY-MM-DD" line that still names the concrete systems/versions/counts (never vague wording). Target ~450 tokens.`,
|
|
50
|
+
half_year: `Write a dated milestone log for this half-year (${periodLabel}). You have ${childCount} quarterly logs and possibly top-importance raw episodes below. Format: "Date — milestone/decision. Reason. Result." One entry per line, day- or month-level dates. A major turning point — direction change, system shipped, architecture shift — gets its OWN single date. Several less-important events that don't each warrant a line — group them into ONE "YYYY-MM-DD to YYYY-MM-DD" line that still names the concrete systems/versions/counts (never vague wording). Target ~400 tokens.`,
|
|
110
51
|
};
|
|
111
|
-
return `You are a temporal memory narrator. You synthesize lower-resolution
|
|
52
|
+
return `You are a temporal memory narrator. You synthesize lower-resolution logs into higher-level dated logs.
|
|
112
53
|
|
|
113
54
|
${instructions[resolution]}
|
|
114
55
|
|
|
115
|
-
${
|
|
116
|
-
- Only use years in the range ${startYear}${startYear !== endYear ?
|
|
56
|
+
${LOG_STYLE}
|
|
57
|
+
- Only use years in the range ${startYear}${startYear !== endYear ? `-${endYear}` : ""}.
|
|
117
58
|
|
|
118
59
|
SOURCE: ${childCount} ${childResolution} narratives
|
|
119
60
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"narrative.js","sourceRoot":"","sources":["../../../src/llm/prompts/narrative.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,UAAU,WAAW,CACzB,UAA+B,EAC/B,YAAoB,EACpB,SAAiB,EACjB,YAAoB,EACpB,WAAmB,EACnB,WAAmB;IAEnB,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC;IACtD,MAAM,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACzC,MAAM,YAAY,GAAwC;QACxD,GAAG,EAAE,
|
|
1
|
+
{"version":3,"file":"narrative.js","sourceRoot":"","sources":["../../../src/llm/prompts/narrative.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;;GAIG;AACH,MAAM,SAAS,GAAG;;;;;;;sKAOoJ,CAAC;AAEvK,MAAM,UAAU,WAAW,CACzB,UAA+B,EAC/B,YAAoB,EACpB,SAAiB,EACjB,YAAoB,EACpB,WAAmB,EACnB,WAAmB;IAEnB,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC;IACtD,MAAM,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACzC,MAAM,YAAY,GAAwC;QACxD,GAAG,EAAE,mDAAmD,WAAW,gRAAgR;QACnV,IAAI,EAAE,8DAA8D,WAAW,wTAAwT;QACvY,KAAK,EAAE,sDAAsD,WAAW,8dAA8d;QACtiB,OAAO,EAAE,gDAAgD,WAAW,seAAse;QAC1iB,SAAS,EAAE,mDAAmD,WAAW,qaAAqa;KAC/e,CAAC;IAEF,OAAO;;EAEP,YAAY,CAAC,UAAU,CAAC;;EAExB,SAAS;gCACqB,SAAS,GAAG,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE;;eAEvE,YAAY;;;EAGzB,YAAY,IAAI,8BAA8B;;;EAG9C,SAAS,IAAI,YAAY;;oCAES,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,UAA+B,EAC/B,mBAA2B,EAC3B,eAAoC,EACpC,UAAkB,EAClB,WAAmB,EACnB,WAAmB;IAEnB,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC;IACtD,MAAM,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACzC,MAAM,YAAY,GAAiD;QACjE,KAAK,EAAE,sDAAsD,WAAW,eAAe,UAAU,8iBAA8iB;QAC/oB,OAAO,EAAE,gDAAgD,WAAW,eAAe,UAAU,kkBAAkkB;QAC/pB,SAAS,EAAE,mDAAmD,WAAW,eAAe,UAAU,keAAke;KACrkB,CAAC;IAEF,OAAO;;EAEP,YAAY,CAAC,UAAU,CAAC;;EAExB,SAAS;gCACqB,SAAS,GAAG,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE;;UAE5E,UAAU,IAAI,eAAe;;EAErC,mBAAmB;;oCAEe,CAAC;AACrC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-spawn.service.d.ts","sourceRoot":"","sources":["../../src/services/claude-spawn.service.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA0BH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAE5E,OAAO,EAWL,KAAK,WAAW,EACjB,MAAM,mBAAmB,CAAC;AAE3B,eAAO,MAAM,iBAAiB,QAAO,MAAM,GAAG,IAQ7C,CAAC;AAqDF,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,sBAAsB,EACvC,gBAAgB,CAAC,EAAE,MAAM,EACzB,oBAAoB,CAAC,EAAE,MAAM,EAC7B,UAAU,CAAC,EAAE,QAAQ,GAAG,QAAQ,EAChC,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,WAAW,CAAC,
|
|
1
|
+
{"version":3,"file":"claude-spawn.service.d.ts","sourceRoot":"","sources":["../../src/services/claude-spawn.service.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA0BH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAE5E,OAAO,EAWL,KAAK,WAAW,EACjB,MAAM,mBAAmB,CAAC;AAE3B,eAAO,MAAM,iBAAiB,QAAO,MAAM,GAAG,IAQ7C,CAAC;AAqDF,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,sBAAsB,EACvC,gBAAgB,CAAC,EAAE,MAAM,EACzB,oBAAoB,CAAC,EAAE,MAAM,EAC7B,UAAU,CAAC,EAAE,QAAQ,GAAG,QAAQ,EAChC,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,WAAW,CAAC,CAiItB"}
|
|
@@ -79,7 +79,7 @@ export async function spawnAgentProcess(claudePath, name, threadId, threadLifecy
|
|
|
79
79
|
if ("error" in pre)
|
|
80
80
|
return pre;
|
|
81
81
|
workingDirectory = normalizeWorkingDirectory(workingDirectory);
|
|
82
|
-
const logFilePath = buildThreadLogPath(name, threadId, "json");
|
|
82
|
+
const logFilePath = buildThreadLogPath(name, "claude", threadId, "json");
|
|
83
83
|
const effectiveConfigPath = buildClaudeMcpConfig(pre.transport, threadId);
|
|
84
84
|
const claudeConfigDir = join(PROCESS_BASE_DIR, "claude-configs", String(threadId));
|
|
85
85
|
mkdirSync(claudeConfigDir, { recursive: true });
|
|
@@ -148,6 +148,11 @@ export async function spawnAgentProcess(claudePath, name, threadId, threadLifecy
|
|
|
148
148
|
// read was already destructive, so the message is simply gone. 0 disables
|
|
149
149
|
// the timer; the long-poll has its own ceiling and keepalives when awake.
|
|
150
150
|
CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT: "0",
|
|
151
|
+
// The CLI caps MCP tool output at ~25k tokens by default and spills anything
|
|
152
|
+
// larger to a file with only a ~2KB inline preview. A large bootstrap briefing
|
|
153
|
+
// exceeds that cap, so the agent sees the preview instead of the full briefing.
|
|
154
|
+
// Raise the cap so the whole briefing arrives inline. Claude-only knob.
|
|
155
|
+
MAX_MCP_OUTPUT_TOKENS: "50000",
|
|
151
156
|
ENABLE_TOOL_SEARCH: "false",
|
|
152
157
|
...(oauthToken ? { CLAUDE_CODE_OAUTH_TOKEN: oauthToken } : {}),
|
|
153
158
|
...(memorySourceThreadId !== undefined
|