opencode and native tasks
This commit is contained in:
@@ -26,7 +26,7 @@ Transcribe an audio file to text using whisper.cpp.
|
|||||||
|
|
||||||
## Steps
|
## Steps
|
||||||
|
|
||||||
1. Determine the user's root directory by navigating one level up from the current working directory. Read `settings.json` from the root directory and extract the `languages` section.
|
1. Starting from the directory containing the audio file, walk up parent by parent until you find a directory whose name is an email address. This is the user's root directory. Read `settings.json` from it and extract the `languages` section.
|
||||||
2. Detect the language of the audio file using the whisper.cpp skill with `detect_language=true` and `response_format=verbose_json`.
|
2. Detect the language of the audio file using the whisper.cpp skill with `detect_language=true` and `response_format=verbose_json`.
|
||||||
3. Compare the detected language against the user's `languages.spoken` list. If the detected language is in the list, skip translation. Otherwise, set `translate=true`.
|
3. Compare the detected language against the user's `languages.spoken` list. If the detected language is in the list, skip translation. Otherwise, set `translate=true`.
|
||||||
4. Use the whisper.cpp skill to transcribe the audio file at `file_path`, passing the detected language as the `language` parameter and the `translate` flag from the previous step.
|
4. Use the whisper.cpp skill to transcribe the audio file at `file_path`, passing the detected language as the `language` parameter and the `translate` flag from the previous step.
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -2,7 +2,8 @@ import type { ServerWebSocket } from 'bun';
|
|||||||
import { mkdir, rename } from 'node:fs/promises';
|
import { mkdir, rename } from 'node:fs/promises';
|
||||||
import { join } from 'node:path';
|
import { join } from 'node:path';
|
||||||
import type { ClientMessage, ServerMessage, ImageData, TaskInfo } from '@@/api/chat-types';
|
import type { ClientMessage, ServerMessage, ImageData, TaskInfo } from '@@/api/chat-types';
|
||||||
import { getTmpAttachmentsDir, getAttachmentsDir } from '@@/data-path';
|
import { getTmpAttachmentsDir, getAttachmentsDir, getNativeSkillsDir, getGlobalSkillsDir, getUserSkillsDir } from '@@/data-path';
|
||||||
|
import { readSkillDirs, parseFrontmatter } from '@@/api/skills/skills';
|
||||||
import { createTaskLog, appendToLog, finalizeLog } from '@@/api/task-logger';
|
import { createTaskLog, appendToLog, finalizeLog } from '@@/api/task-logger';
|
||||||
|
|
||||||
const OPENCODE_PORT = process.env.OPENCODE_PORT ?? '10006';
|
const OPENCODE_PORT = process.env.OPENCODE_PORT ?? '10006';
|
||||||
@@ -303,6 +304,29 @@ function handleSSEEvent(ws: ServerWebSocket<WSData>, event: string, data: any) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function buildSkillsPrompt(email: string): Promise<string> {
|
||||||
|
const nativeSkills = await readSkillDirs(getNativeSkillsDir());
|
||||||
|
const globalSkills = await readSkillDirs(getGlobalSkillsDir());
|
||||||
|
const userSkills = await readSkillDirs(getUserSkillsDir(email));
|
||||||
|
|
||||||
|
const merged = new Map(nativeSkills);
|
||||||
|
for (const [name, path] of globalSkills) merged.set(name, path);
|
||||||
|
for (const [name, path] of userSkills) merged.set(name, path);
|
||||||
|
|
||||||
|
if (merged.size === 0) return '';
|
||||||
|
|
||||||
|
const lines = await Promise.all(
|
||||||
|
Array.from(merged.entries()).map(async ([dirName, filePath]) => {
|
||||||
|
const raw = await Bun.file(filePath).text();
|
||||||
|
const { frontmatter } = parseFrontmatter(raw);
|
||||||
|
const name = frontmatter.name || dirName;
|
||||||
|
return `- ${name}: ${frontmatter.description} (read ${filePath} for full instructions)`;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return `\n\nYou have access to the following skills. When a user's request matches a skill, read its SKILL.md file for detailed instructions before proceeding.\n\nAvailable skills:\n${lines.join('\n')}`;
|
||||||
|
}
|
||||||
|
|
||||||
type HandleChatParams = {
|
type HandleChatParams = {
|
||||||
ws: ServerWebSocket<WSData>;
|
ws: ServerWebSocket<WSData>;
|
||||||
prompt: string;
|
prompt: string;
|
||||||
@@ -368,6 +392,9 @@ async function handleChat({ ws, prompt, sessionId, model, attachmentIds, images,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const skillsAppend = await buildSkillsPrompt(ws.data.email);
|
||||||
|
const fullPrompt = skillsAppend ? `${skillsAppend}\n\n${prompt}` : prompt;
|
||||||
|
|
||||||
const parts: Record<string, unknown>[] = [];
|
const parts: Record<string, unknown>[] = [];
|
||||||
if (images?.length) {
|
if (images?.length) {
|
||||||
for (const img of images) {
|
for (const img of images) {
|
||||||
@@ -378,7 +405,7 @@ async function handleChat({ ws, prompt, sessionId, model, attachmentIds, images,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parts.push({ type: 'text', text: prompt });
|
parts.push({ type: 'text', text: fullPrompt });
|
||||||
|
|
||||||
const promptBody: Record<string, unknown> = { parts };
|
const promptBody: Record<string, unknown> = { parts };
|
||||||
if (modelSelection.modelId) {
|
if (modelSelection.modelId) {
|
||||||
|
|||||||
Reference in New Issue
Block a user