pi-harness-runtime 1.1.337 → 1.1.339
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/package.json +1 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/agent-policy/package.json +1 -1
- package/packages/architecture-generator/package.json +1 -1
- package/packages/auth/package.json +1 -1
- package/packages/autonomous-refactor/package.json +1 -1
- package/packages/autonomous-runtime/package.json +1 -1
- package/packages/cache-strategy/package.json +1 -1
- package/packages/capability-registry/package.json +1 -1
- package/packages/checkpoint/package.json +1 -1
- package/packages/cli-plugin-sdk/package.json +1 -1
- package/packages/clipboard/package.json +1 -1
- package/packages/clipboard-plugin/package.json +1 -1
- package/packages/code-generation/package.json +1 -1
- package/packages/code-review/package.json +1 -1
- package/packages/codex-adapter/package.json +1 -1
- package/packages/codex-watcher/package.json +1 -1
- package/packages/config-capture/package.json +1 -1
- package/packages/connection-runtime/package.json +1 -1
- package/packages/context-compiler/package.json +1 -1
- package/packages/context-discovery/package.json +1 -1
- package/packages/context-manager/package.json +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/cookie-sanitizer/package.json +1 -1
- package/packages/cost-optimizer/package.json +1 -1
- package/packages/dependency-analyzer/package.json +1 -1
- package/packages/django-plugin/package.json +1 -1
- package/packages/doc-generator/package.json +1 -1
- package/packages/durable-review/package.json +1 -1
- package/packages/e2e-tester/package.json +1 -1
- package/packages/evaluation-engine/package.json +1 -1
- package/packages/evaluation-runner/package.json +1 -1
- package/packages/event-bus/package.json +1 -1
- package/packages/event-sink/package.json +1 -1
- package/packages/event-store/package.json +1 -1
- package/packages/experience-replay/package.json +1 -1
- package/packages/feedback-collector/package.json +1 -1
- package/packages/file-copy-helper/package.json +1 -1
- package/packages/framework-detector/package.json +1 -1
- package/packages/framework-plugin-sdk/package.json +1 -1
- package/packages/frappe-plugin/package.json +1 -1
- package/packages/generic-web-plugin/package.json +1 -1
- package/packages/health-monitor/package.json +1 -1
- package/packages/intent-analyzer/package.json +1 -1
- package/packages/jev-judge/package.json +1 -1
- package/packages/knowledge-graph/package.json +1 -1
- package/packages/knowledge-retrieval/package.json +1 -1
- package/packages/laravel-plugin/package.json +1 -1
- package/packages/learning-engine/package.json +1 -1
- package/packages/mcp-adapter/package.json +1 -1
- package/packages/memory-engine/package.json +1 -1
- package/packages/milestone-manager/package.json +1 -1
- package/packages/model-registry/package.json +1 -1
- package/packages/nextjs-plugin/package.json +1 -1
- package/packages/notification/package.json +1 -1
- package/packages/observability/package.json +1 -1
- package/packages/okf-indexer/package.json +1 -1
- package/packages/paperclip-integration/package.json +1 -1
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/permission-mode/package.json +1 -1
- package/packages/privilege-broker/package.json +1 -1
- package/packages/project-analyzer/package.json +1 -1
- package/packages/project-bootstrap/package.json +1 -1
- package/packages/projection-engine/package.json +1 -1
- package/packages/prompt-compiler/package.json +1 -1
- package/packages/prompt-versioning/package.json +1 -1
- package/packages/provider-adapter-sdk/package.json +1 -1
- package/packages/provider-router/package.json +1 -1
- package/packages/provider-selector/package.json +1 -1
- package/packages/providers/package.json +1 -1
- package/packages/qdrant-skills/package.json +1 -1
- package/packages/quota-manager/package.json +1 -1
- package/packages/rate-limiter/package.json +1 -1
- package/packages/react-vite-plugin/package.json +1 -1
- package/packages/relay/package.json +1 -1
- package/packages/release-manager/package.json +1 -1
- package/packages/requirement-compiler/package.json +1 -1
- package/packages/runtime/package.json +1 -1
- package/packages/scheduler/package.json +1 -1
- package/packages/scheduler-adapter/package.json +1 -1
- package/packages/session/package.json +1 -1
- package/packages/session-api/package.json +1 -1
- package/packages/session-export/package.json +1 -1
- package/packages/shared-context/package.json +1 -1
- package/packages/skill-mcp-client/package.json +1 -1
- package/packages/skill-registry/package.json +1 -1
- package/packages/skills/package.json +1 -1
- package/packages/sprint-planner/package.json +1 -1
- package/packages/subscription-engine/package.json +1 -1
- package/packages/task-compiler/package.json +1 -1
- package/packages/telegram/package.json +1 -1
- package/packages/tencentdb-memory/package.json +1 -1
- package/packages/tencentdb-sync/package.json +1 -1
- package/packages/test-data-generator/package.json +1 -1
- package/packages/test-generator/package.json +1 -1
- package/packages/todo-bd-sync/package.json +1 -1
- package/packages/token-estimation/package.json +1 -1
- package/packages/token-optimizer/package.json +1 -1
- package/packages/trajectory/package.json +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/types/package.json +1 -1
- package/packages/voice-api/dist/index.d.ts +14 -0
- package/packages/voice-api/dist/index.js +12 -0
- package/packages/voice-api/dist/line.d.ts +100 -0
- package/packages/voice-api/dist/line.js +147 -0
- package/packages/voice-api/dist/provider.d.ts +23 -0
- package/packages/voice-api/dist/provider.js +154 -0
- package/packages/voice-api/dist/telegram.d.ts +74 -0
- package/packages/voice-api/dist/telegram.js +119 -0
- package/packages/voice-api/dist/transcriber.d.ts +48 -0
- package/packages/voice-api/dist/transcriber.js +118 -0
- package/packages/voice-api/dist/types.d.ts +75 -0
- package/packages/voice-api/dist/types.js +4 -0
- package/packages/voice-api/package.json +24 -0
- package/packages/voice-api/src/index.ts +15 -0
- package/packages/voice-api/src/line.ts +229 -0
- package/packages/voice-api/src/provider.ts +186 -0
- package/packages/voice-api/src/telegram.ts +191 -0
- package/packages/voice-api/src/transcriber.ts +136 -0
- package/packages/voice-api/src/types.ts +79 -0
- package/packages/webmcp-tester/package.json +1 -1
- package/packages/wiki/package.json +1 -1
- package/packages/workflow-events/package.json +1 -1
- package/packages/workspace-scanner/package.json +1 -1
- package/packages/worktree/package.json +1 -1
- package/packages/write-review/package.json +1 -1
- package/scripts/voice-api-example.ts +112 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Voice Transcriber - Main interface for speech-to-text
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { TranscriptionResult, TranscribeOptions, VoiceApiConfig } from './types.js';
|
|
6
|
+
import { WhisperProvider, createOpenAIProvider, createReplicateProvider } from './provider.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Voice Transcriber
|
|
10
|
+
*
|
|
11
|
+
* Main interface for transcribing voice messages to text.
|
|
12
|
+
* Supports multiple providers (OpenAI, Replicate).
|
|
13
|
+
*/
|
|
14
|
+
export class VoiceTranscriber {
|
|
15
|
+
private providers: Map<string, WhisperProvider> = new Map();
|
|
16
|
+
private defaultProvider: string = '';
|
|
17
|
+
|
|
18
|
+
constructor(config: VoiceApiConfig = {}) {
|
|
19
|
+
// Initialize OpenAI provider
|
|
20
|
+
if (config.openaiApiKey) {
|
|
21
|
+
const provider = createOpenAIProvider(config.openaiApiKey);
|
|
22
|
+
this.providers.set('openai', provider);
|
|
23
|
+
this.defaultProvider = 'openai';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Initialize Replicate provider
|
|
27
|
+
if (config.replicateApiToken) {
|
|
28
|
+
const provider = createReplicateProvider(config.replicateApiToken);
|
|
29
|
+
this.providers.set('replicate', provider);
|
|
30
|
+
if (!this.defaultProvider) {
|
|
31
|
+
this.defaultProvider = 'replicate';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Set default provider from config
|
|
36
|
+
if (config.provider && this.providers.has(config.provider)) {
|
|
37
|
+
this.defaultProvider = config.provider;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Check if transcriber is configured
|
|
43
|
+
*/
|
|
44
|
+
isConfigured(): boolean {
|
|
45
|
+
return this.providers.size > 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Get configured providers
|
|
50
|
+
*/
|
|
51
|
+
getProviders(): string[] {
|
|
52
|
+
return Array.from(this.providers.keys());
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Get default provider
|
|
57
|
+
*/
|
|
58
|
+
getDefaultProvider(): string | null {
|
|
59
|
+
return this.defaultProvider || null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Transcribe audio to text
|
|
64
|
+
*/
|
|
65
|
+
async transcribe(options: TranscribeOptions): Promise<TranscriptionResult> {
|
|
66
|
+
const providerName = options.provider || this.defaultProvider;
|
|
67
|
+
|
|
68
|
+
if (!providerName) {
|
|
69
|
+
return {
|
|
70
|
+
text: '',
|
|
71
|
+
timestamp: new Date().toISOString(),
|
|
72
|
+
provider: 'openai',
|
|
73
|
+
error: 'No provider configured',
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const provider = this.providers.get(providerName);
|
|
78
|
+
if (!provider) {
|
|
79
|
+
return {
|
|
80
|
+
text: '',
|
|
81
|
+
timestamp: new Date().toISOString(),
|
|
82
|
+
provider: providerName as 'openai' | 'replicate',
|
|
83
|
+
error: `Provider ${providerName} not configured`,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return provider.transcribe(options);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Add a provider
|
|
92
|
+
*/
|
|
93
|
+
addProvider(name: string, provider: WhisperProvider): void {
|
|
94
|
+
this.providers.set(name, provider);
|
|
95
|
+
if (!this.defaultProvider) {
|
|
96
|
+
this.defaultProvider = name;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Remove a provider
|
|
102
|
+
*/
|
|
103
|
+
removeProvider(name: string): boolean {
|
|
104
|
+
const deleted = this.providers.delete(name);
|
|
105
|
+
if (this.defaultProvider === name) {
|
|
106
|
+
this.defaultProvider = this.providers.keys().next().value || '';
|
|
107
|
+
}
|
|
108
|
+
return deleted;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Set default provider
|
|
113
|
+
*/
|
|
114
|
+
setDefaultProvider(name: string): boolean {
|
|
115
|
+
if (this.providers.has(name)) {
|
|
116
|
+
this.defaultProvider = name;
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Create a VoiceTranscriber from environment variables
|
|
125
|
+
*/
|
|
126
|
+
export function createFromEnv(): VoiceTranscriber {
|
|
127
|
+
// SAFETY: globalThis.process is always available in Node.js
|
|
128
|
+
const env = (globalThis as unknown as { process: { env: Record<string, string> } }).process;
|
|
129
|
+
const envVars = env?.env ?? {};
|
|
130
|
+
|
|
131
|
+
return new VoiceTranscriber({
|
|
132
|
+
openaiApiKey: envVars.OPENAI_API_KEY,
|
|
133
|
+
replicateApiToken: envVars.REPLICATE_API_TOKEN,
|
|
134
|
+
provider: (envVars.VOICE_PROVIDER as 'openai' | 'replicate') || 'openai',
|
|
135
|
+
});
|
|
136
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Voice API Types
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Transcription result from Whisper
|
|
7
|
+
*/
|
|
8
|
+
export interface TranscriptionResult {
|
|
9
|
+
/** The transcribed text */
|
|
10
|
+
text: string;
|
|
11
|
+
/** Language detected (ISO 639-1) */
|
|
12
|
+
language?: string;
|
|
13
|
+
/** Duration in seconds */
|
|
14
|
+
duration?: number;
|
|
15
|
+
/** Confidence score (0-1) */
|
|
16
|
+
confidence?: number;
|
|
17
|
+
/** Timestamp of transcription */
|
|
18
|
+
timestamp: string;
|
|
19
|
+
/** Provider used (openai/replicate) */
|
|
20
|
+
provider: 'openai' | 'replicate';
|
|
21
|
+
/** Error message if failed */
|
|
22
|
+
error?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Voice message from messaging platforms
|
|
27
|
+
*/
|
|
28
|
+
export interface VoiceMessage {
|
|
29
|
+
/** Unique message ID */
|
|
30
|
+
id: string;
|
|
31
|
+
/** Platform source (telegram/line) */
|
|
32
|
+
platform: 'telegram' | 'line';
|
|
33
|
+
/** Chat/user ID */
|
|
34
|
+
chatId: string;
|
|
35
|
+
/** Audio file URL or path */
|
|
36
|
+
audioUrl: string;
|
|
37
|
+
/** Duration in seconds */
|
|
38
|
+
duration?: number;
|
|
39
|
+
/** MIME type */
|
|
40
|
+
mimeType: string;
|
|
41
|
+
/** File size in bytes */
|
|
42
|
+
fileSize?: number;
|
|
43
|
+
/** Raw platform-specific data */
|
|
44
|
+
raw?: unknown;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Voice API configuration
|
|
49
|
+
*/
|
|
50
|
+
export interface VoiceApiConfig {
|
|
51
|
+
/** OpenAI API key (for Whisper) */
|
|
52
|
+
openaiApiKey?: string;
|
|
53
|
+
/** Replicate API token (alternative) */
|
|
54
|
+
replicateApiToken?: string;
|
|
55
|
+
/** Default provider */
|
|
56
|
+
provider?: 'openai' | 'replicate';
|
|
57
|
+
/** Model to use */
|
|
58
|
+
model?: string;
|
|
59
|
+
/** Language hint (ISO 639-1) */
|
|
60
|
+
language?: string;
|
|
61
|
+
/** Temperature for generation */
|
|
62
|
+
temperature?: number;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Transcribe options
|
|
67
|
+
*/
|
|
68
|
+
export interface TranscribeOptions {
|
|
69
|
+
/** Audio URL or file path (required if no audioBuffer) */
|
|
70
|
+
audioUrl?: string;
|
|
71
|
+
/** Audio as Buffer (Uint8Array for cross-platform) */
|
|
72
|
+
audioBuffer?: Uint8Array;
|
|
73
|
+
/** Language hint */
|
|
74
|
+
language?: string;
|
|
75
|
+
/** Model override */
|
|
76
|
+
model?: string;
|
|
77
|
+
/** Provider override */
|
|
78
|
+
provider?: 'openai' | 'replicate';
|
|
79
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Voice API Example - Telegram Voice to Command
|
|
3
|
+
*
|
|
4
|
+
* This script demonstrates how to:
|
|
5
|
+
* 1. Receive voice message from Telegram
|
|
6
|
+
* 2. Transcribe with Whisper API
|
|
7
|
+
* 3. Execute as pi-harness command
|
|
8
|
+
*
|
|
9
|
+
* Run:
|
|
10
|
+
* OPENAI_API_KEY=sk-xxx bun run scripts/voice-api-example.ts
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import * as fs from "node:fs";
|
|
14
|
+
import * as path from "node:path";
|
|
15
|
+
import { VoiceTranscriber } from "../packages/voice-api/dist/transcriber.js";
|
|
16
|
+
import { TelegramVoiceHandler } from "../packages/voice-api/dist/telegram.js";
|
|
17
|
+
|
|
18
|
+
// Load API keys from key files
|
|
19
|
+
function loadKey(filename: string): string | null {
|
|
20
|
+
const keysDir = path.join(process.env.HOME || "/home/frappe", ".pi-harness-runtime", "keys");
|
|
21
|
+
const filepath = path.join(keysDir, filename);
|
|
22
|
+
try {
|
|
23
|
+
return fs.readFileSync(filepath, "utf8").trim();
|
|
24
|
+
} catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function main() {
|
|
30
|
+
console.log("=".repeat(60));
|
|
31
|
+
console.log("Voice API Example - Telegram Voice to Command");
|
|
32
|
+
console.log("=".repeat(60));
|
|
33
|
+
|
|
34
|
+
// Load API keys
|
|
35
|
+
const openaiApiKey = process.env.OPENAI_API_KEY || loadKey("openai-api-key.txt");
|
|
36
|
+
const telegramBotToken = loadKey("telegram-bot-token.txt");
|
|
37
|
+
|
|
38
|
+
if (!openaiApiKey) {
|
|
39
|
+
console.log("❌ OpenAI API key not found");
|
|
40
|
+
console.log(" Set OPENAI_API_KEY or create ~/.pi-harness-runtime/keys/openai-api-key.txt");
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
console.log("✓ OpenAI API key loaded");
|
|
45
|
+
|
|
46
|
+
// Create transcriber
|
|
47
|
+
const transcriber = new VoiceTranscriber({ openaiApiKey });
|
|
48
|
+
console.log("✓ VoiceTranscriber created");
|
|
49
|
+
|
|
50
|
+
if (!transcriber.isConfigured()) {
|
|
51
|
+
console.log("❌ Transcriber not configured");
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
console.log(`✓ Providers: ${transcriber.getProviders().join(", ")}`);
|
|
56
|
+
console.log(`✓ Default: ${transcriber.getDefaultProvider()}`);
|
|
57
|
+
|
|
58
|
+
// If Telegram token provided, create handler
|
|
59
|
+
if (telegramBotToken) {
|
|
60
|
+
console.log("✓ Telegram bot token loaded");
|
|
61
|
+
|
|
62
|
+
const handler = new TelegramVoiceHandler({
|
|
63
|
+
botToken: telegramBotToken,
|
|
64
|
+
transcriber,
|
|
65
|
+
onTranscribed: async (chatId, text, result) => {
|
|
66
|
+
console.log("\n" + "=".repeat(60));
|
|
67
|
+
console.log("Voice transcribed:");
|
|
68
|
+
console.log(` Chat: ${chatId}`);
|
|
69
|
+
console.log(` Text: ${text}`);
|
|
70
|
+
console.log(` Provider: ${result.provider}`);
|
|
71
|
+
console.log(` Language: ${result.language || "auto"}`);
|
|
72
|
+
console.log("=".repeat(60));
|
|
73
|
+
|
|
74
|
+
// Here you would execute the command in pi-harness
|
|
75
|
+
console.log("\n[pi-harness] Would execute:");
|
|
76
|
+
console.log(` ${text}`);
|
|
77
|
+
},
|
|
78
|
+
onError: (chatId, error) => {
|
|
79
|
+
console.log(`❌ Error for chat ${chatId}: ${error.message}`);
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
console.log("✓ TelegramVoiceHandler created");
|
|
84
|
+
console.log("\nListening for Telegram voice messages...");
|
|
85
|
+
console.log("(This is a demo - actual webhook server not started)");
|
|
86
|
+
} else {
|
|
87
|
+
console.log("⚠ Telegram bot token not found");
|
|
88
|
+
console.log(" Create ~/.pi-harness-runtime/keys/telegram-bot-token.txt for Telegram integration");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Demo: transcribe a local audio file
|
|
92
|
+
console.log("\n" + "-".repeat(60));
|
|
93
|
+
console.log("Demo: Transcribing test audio file...");
|
|
94
|
+
|
|
95
|
+
// Note: In production, this would be triggered by actual Telegram/LINE webhooks
|
|
96
|
+
// For testing, you can manually transcribe an audio file:
|
|
97
|
+
//
|
|
98
|
+
// const result = await transcriber.transcribe({
|
|
99
|
+
// audioUrl: "https://example.com/audio.ogg",
|
|
100
|
+
// language: "en",
|
|
101
|
+
// });
|
|
102
|
+
// console.log("Transcribed:", result.text);
|
|
103
|
+
|
|
104
|
+
console.log("\n" + "=".repeat(60));
|
|
105
|
+
console.log("Ready for voice commands!");
|
|
106
|
+
console.log("=".repeat(60));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
main().catch(err => {
|
|
110
|
+
console.error("❌ Error:", err);
|
|
111
|
+
process.exit(1);
|
|
112
|
+
});
|