osborn 0.9.153 → 0.9.154
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/Dockerfile.sandbox +21 -1
- package/dist/index.js +10 -3
- package/dist/pipeline-direct-llm.d.ts +2 -0
- package/dist/pipeline-direct-llm.js +4 -1
- package/package.json +1 -1
package/Dockerfile.sandbox
CHANGED
|
@@ -45,7 +45,8 @@ RUN apt-get update -qq && \
|
|
|
45
45
|
git \
|
|
46
46
|
make \
|
|
47
47
|
g++ \
|
|
48
|
-
python-is-python3
|
|
48
|
+
python-is-python3 \
|
|
49
|
+
util-linux && \
|
|
49
50
|
rm -rf /var/lib/apt/lists/*
|
|
50
51
|
|
|
51
52
|
ARG OSBORN_VERSION=latest
|
|
@@ -122,6 +123,25 @@ fi
|
|
|
122
123
|
echo "[sandbox-d] === boot at $(date -Iseconds) ===" >> "$LOGFILE"
|
|
123
124
|
exec > >(tee -a "$LOGFILE") 2>&1
|
|
124
125
|
|
|
126
|
+
# === Swap on volume ===
|
|
127
|
+
# 8GB swapfile on /workspace (persistent volume). Created once on first boot,
|
|
128
|
+
# reactivated on every subsequent boot (swapon state is lost across cold starts).
|
|
129
|
+
# Gives 8GB RAM + 8GB swap = 16GB addressable — pressure relief when the dev
|
|
130
|
+
# server or concurrent sub-agents spike memory without killing the voice loop.
|
|
131
|
+
SWAPFILE=/workspace/swapfile
|
|
132
|
+
if [ ! -f "$SWAPFILE" ]; then
|
|
133
|
+
echo "[sandbox-d] Creating 8GB swapfile at $SWAPFILE..."
|
|
134
|
+
fallocate -l 8G "$SWAPFILE" 2>/dev/null || dd if=/dev/zero of="$SWAPFILE" bs=1M count=8192 status=none
|
|
135
|
+
chmod 600 "$SWAPFILE"
|
|
136
|
+
mkswap "$SWAPFILE"
|
|
137
|
+
echo "[sandbox-d] Swapfile created"
|
|
138
|
+
fi
|
|
139
|
+
if swapon "$SWAPFILE" 2>/dev/null; then
|
|
140
|
+
echo "[sandbox-d] Swap active: $(free -h | grep Swap)"
|
|
141
|
+
else
|
|
142
|
+
echo "[sandbox-d] swapon skipped (already active or kernel restriction)"
|
|
143
|
+
fi
|
|
144
|
+
|
|
125
145
|
# Onboarding-suppression JSON
|
|
126
146
|
ONBOARDING_JSON='{"numStartups":10,"installMethod":"npm","autoUpdates":false,"hasCompletedOnboarding":true,"hasTrustDialogAccepted":true,"hasTrustDialogHooksAccepted":true,"hasCompletedProjectOnboarding":true,"hasAcknowledgedCostThreshold":true,"effortCalloutV2Dismissed":true,"theme":"dark","projects":{"/workspace":{"hasTrustDialogAccepted":true,"hasTrustDialogHooksAccepted":true,"hasCompletedProjectOnboarding":true}}}'
|
|
127
147
|
|
package/dist/index.js
CHANGED
|
@@ -2709,7 +2709,7 @@ async function main() {
|
|
|
2709
2709
|
const { readSessionHistory } = await import('./session-access.js');
|
|
2710
2710
|
const history = readSessionHistory(sessionId, workingDir, {
|
|
2711
2711
|
lastN: 10,
|
|
2712
|
-
types: ['assistant'],
|
|
2712
|
+
types: ['assistant', 'tool_use'], // tool_use entries also carry Claude's spoken text
|
|
2713
2713
|
});
|
|
2714
2714
|
recentMessages = history
|
|
2715
2715
|
.filter((m) => m.text)
|
|
@@ -2725,8 +2725,14 @@ async function main() {
|
|
|
2725
2725
|
// BEFORE the previous TTS completed, and we may have already suppressed in-flight
|
|
2726
2726
|
// tts_say events that arrived during that overlap).
|
|
2727
2727
|
const carriedSuppressed = lastInterruption?.suppressedText ?? '';
|
|
2728
|
-
lastInterruption = {
|
|
2729
|
-
|
|
2728
|
+
lastInterruption = {
|
|
2729
|
+
spokenText: fullText,
|
|
2730
|
+
recentMessages,
|
|
2731
|
+
suppressedText: carriedSuppressed,
|
|
2732
|
+
fullBlockText: fullBlockText && fullBlockText !== fullText ? fullBlockText : undefined,
|
|
2733
|
+
timestamp: Date.now(),
|
|
2734
|
+
};
|
|
2735
|
+
console.log(`📋 Interruption context stored (text: ${fullText.length} chars, JSONL: ${recentMessages.length} chars, block: ${fullBlockText?.length ?? 0} chars, suppressed carried: ${carriedSuppressed.length} chars)`);
|
|
2730
2736
|
}
|
|
2731
2737
|
/**
|
|
2732
2738
|
* Append text the agent tried to say while the user was speaking, but which we
|
|
@@ -2766,6 +2772,7 @@ async function main() {
|
|
|
2766
2772
|
spokenText: lastInterruption.spokenText,
|
|
2767
2773
|
recentMessages: lastInterruption.recentMessages,
|
|
2768
2774
|
suppressedText: lastInterruption.suppressedText,
|
|
2775
|
+
fullBlockText: lastInterruption.fullBlockText,
|
|
2769
2776
|
};
|
|
2770
2777
|
lastInterruption = null;
|
|
2771
2778
|
return ctx;
|
|
@@ -21,6 +21,8 @@ export interface InterruptionContext {
|
|
|
21
21
|
* and can re-articulate the relevant bits in its next response.
|
|
22
22
|
*/
|
|
23
23
|
suppressedText: string;
|
|
24
|
+
/** Full text of the interrupted TTS block — fallback when JSONL read returns empty */
|
|
25
|
+
fullBlockText?: string;
|
|
24
26
|
}
|
|
25
27
|
export interface PipelineDirectOptions extends ClaudeLLMOptions {
|
|
26
28
|
onFastBrainResult?: (result: FastBrainPanelResult) => void;
|
|
@@ -204,7 +204,10 @@ export class PipelineDirectLLM extends llm.LLM {
|
|
|
204
204
|
`Anything in "Your recent messages" below that appears AFTER the quoted heard text is content the user did not hear. The user has no memory of it.`,
|
|
205
205
|
``,
|
|
206
206
|
`Your recent messages (full untruncated — you wrote these):`,
|
|
207
|
-
interruptCtx.recentMessages
|
|
207
|
+
interruptCtx.recentMessages
|
|
208
|
+
|| (interruptCtx.fullBlockText
|
|
209
|
+
? `(JSONL unavailable — full TTS block text follows)\n"${interruptCtx.fullBlockText}"`
|
|
210
|
+
: '(no recent messages found)'),
|
|
208
211
|
suppressedBlock,
|
|
209
212
|
``,
|
|
210
213
|
`User's message: "${userText}"`,
|