@astra-code/astra-ai 0.1.3 → 0.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/README.md +8 -0
- package/dist/app/App.js +256 -37
- package/dist/app/App.js.map +1 -1
- package/dist/lib/backendClient.js +5 -1
- package/dist/lib/backendClient.js.map +1 -1
- package/dist/lib/voice.js +19 -2
- package/dist/lib/voice.js.map +1 -1
- package/package.json +1 -1
- package/src/app/App.tsx +338 -111
- package/src/lib/backendClient.ts +5 -1
- package/src/lib/voice.ts +19 -2
- package/src/types/events.ts +11 -0
package/src/lib/backendClient.ts
CHANGED
|
@@ -281,7 +281,11 @@ export class BackendClient {
|
|
|
281
281
|
return;
|
|
282
282
|
}
|
|
283
283
|
try {
|
|
284
|
-
|
|
284
|
+
const parsed = JSON.parse(data) as AgentEvent;
|
|
285
|
+
if (parsed.type === "done") {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
yield parsed;
|
|
285
289
|
} catch {
|
|
286
290
|
// Ignore malformed chunks and keep stream alive.
|
|
287
291
|
}
|
package/src/lib/voice.ts
CHANGED
|
@@ -39,7 +39,8 @@ const captureAudioChunk = async (seconds: number): Promise<string> => {
|
|
|
39
39
|
if (process.platform === "darwin") {
|
|
40
40
|
// Prefer ffmpeg on macOS (works on Apple Silicon/Homebrew setups).
|
|
41
41
|
if (commandExists("ffmpeg")) {
|
|
42
|
-
|
|
42
|
+
const micDevice = process.env.ASTRA_STT_DEVICE?.trim() || ":0";
|
|
43
|
+
cmd = `ffmpeg -hide_banner -loglevel error -f avfoundation -i "${micDevice}" -ar 16000 -ac 1 -t ${seconds} "${outPath}"`;
|
|
43
44
|
} else if (commandExists("rec")) {
|
|
44
45
|
cmd = `rec -q -r 16000 -c 1 "${outPath}" trim 0 ${seconds}`;
|
|
45
46
|
} else {
|
|
@@ -62,12 +63,21 @@ const captureAudioChunk = async (seconds: number): Promise<string> => {
|
|
|
62
63
|
cmd = cmd.replaceAll("{output}", outPath).replaceAll("{seconds}", String(seconds));
|
|
63
64
|
}
|
|
64
65
|
|
|
66
|
+
// #region agent log
|
|
67
|
+
fetch('http://127.0.0.1:7573/ingest/fdd4f018-1ba3-4303-b1bb-375443267476',{method:'POST',headers:{'Content-Type':'application/json','X-Debug-Session-Id':'17f1ea'},body:JSON.stringify({sessionId:'17f1ea',runId:'voice_run_2',hypothesisId:'H6',location:'voice.ts:captureAudioChunk',message:'capture command selected',data:{platform:process.platform,seconds,usesCustom:Boolean(custom),cmdPreview:cmd.slice(0,180)},timestamp:Date.now()})}).catch(()=>{});
|
|
68
|
+
// #endregion
|
|
65
69
|
await runShell(cmd);
|
|
70
|
+
// #region agent log
|
|
71
|
+
fetch('http://127.0.0.1:7573/ingest/fdd4f018-1ba3-4303-b1bb-375443267476',{method:'POST',headers:{'Content-Type':'application/json','X-Debug-Session-Id':'17f1ea'},body:JSON.stringify({sessionId:'17f1ea',runId:'voice_run_2',hypothesisId:'H6',location:'voice.ts:captureAudioChunk',message:'capture command completed',data:{outputPath:outPath},timestamp:Date.now()})}).catch(()=>{});
|
|
72
|
+
// #endregion
|
|
66
73
|
return outPath;
|
|
67
74
|
};
|
|
68
75
|
|
|
69
76
|
const transcribeAudioFile = async (filePath: string): Promise<string> => {
|
|
70
77
|
const bytes = await readFile(filePath);
|
|
78
|
+
// #region agent log
|
|
79
|
+
fetch('http://127.0.0.1:7573/ingest/fdd4f018-1ba3-4303-b1bb-375443267476',{method:'POST',headers:{'Content-Type':'application/json','X-Debug-Session-Id':'17f1ea'},body:JSON.stringify({sessionId:'17f1ea',runId:'voice_run_2',hypothesisId:'H7',location:'voice.ts:transcribeAudioFile',message:'audio chunk loaded',data:{filePath,byteLength:bytes.length},timestamp:Date.now()})}).catch(()=>{});
|
|
80
|
+
// #endregion
|
|
71
81
|
const file = new File([bytes], basename(filePath), {type: "audio/wav"});
|
|
72
82
|
|
|
73
83
|
// Backend proxy only: backend holds provider secrets.
|
|
@@ -83,12 +93,19 @@ const transcribeAudioFile = async (filePath: string): Promise<string> => {
|
|
|
83
93
|
headers: {Authorization: `Bearer ${token}`},
|
|
84
94
|
body: form
|
|
85
95
|
});
|
|
96
|
+
// #region agent log
|
|
97
|
+
fetch('http://127.0.0.1:7573/ingest/fdd4f018-1ba3-4303-b1bb-375443267476',{method:'POST',headers:{'Content-Type':'application/json','X-Debug-Session-Id':'17f1ea'},body:JSON.stringify({sessionId:'17f1ea',runId:'voice_run_2',hypothesisId:'H7',location:'voice.ts:transcribeAudioFile',message:'backend transcribe response',data:{status:response.status,ok:response.ok},timestamp:Date.now()})}).catch(()=>{});
|
|
98
|
+
// #endregion
|
|
86
99
|
if (!response.ok) {
|
|
87
100
|
const detail = (await response.text()).slice(0, 400);
|
|
88
101
|
throw new Error(`Backend transcription failed ${response.status}: ${detail}`);
|
|
89
102
|
}
|
|
90
103
|
const data = (await response.json()) as {text?: string};
|
|
91
|
-
|
|
104
|
+
const out = String(data.text ?? "").trim();
|
|
105
|
+
// #region agent log
|
|
106
|
+
fetch('http://127.0.0.1:7573/ingest/fdd4f018-1ba3-4303-b1bb-375443267476',{method:'POST',headers:{'Content-Type':'application/json','X-Debug-Session-Id':'17f1ea'},body:JSON.stringify({sessionId:'17f1ea',runId:'voice_run_2',hypothesisId:'H8',location:'voice.ts:transcribeAudioFile',message:'transcribe text received',data:{textLen:out.length,textPreview:out.slice(0,80)},timestamp:Date.now()})}).catch(()=>{});
|
|
107
|
+
// #endregion
|
|
108
|
+
return out;
|
|
92
109
|
};
|
|
93
110
|
|
|
94
111
|
/**
|
package/src/types/events.ts
CHANGED
|
@@ -38,5 +38,16 @@ export type AgentEvent =
|
|
|
38
38
|
}
|
|
39
39
|
| {type: "credits_update"; remaining?: number; cost?: number}
|
|
40
40
|
| {type: "credits_exhausted"; message?: string}
|
|
41
|
+
| {
|
|
42
|
+
type: "continuation_check";
|
|
43
|
+
allow_continue?: boolean;
|
|
44
|
+
reason?: string;
|
|
45
|
+
recommendation?: string;
|
|
46
|
+
iteration?: number;
|
|
47
|
+
consecutive_read_only_iterations?: number;
|
|
48
|
+
threshold?: number;
|
|
49
|
+
analysis_intent?: boolean;
|
|
50
|
+
tool_names_used?: string[];
|
|
51
|
+
}
|
|
41
52
|
| {type: "error"; error?: string; content?: string}
|
|
42
53
|
| {type: string; [key: string]: unknown};
|