@hasna/recordings 0.1.19 → 0.1.21

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/dist/mcp/index.js CHANGED
@@ -21,7 +21,7 @@ var __require = import.meta.require;
21
21
  var require_package = __commonJS((exports, module) => {
22
22
  module.exports = {
23
23
  name: "@hasna/recordings",
24
- version: "0.1.19",
24
+ version: "0.1.21",
25
25
  type: "module",
26
26
  description: "Speech-to-text recording tool with MCP and CLI \u2014 records, transcribes, and optionally enhances text using AI",
27
27
  repository: {
@@ -90,6 +90,51 @@ var require_package = __commonJS((exports, module) => {
90
90
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
91
91
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
92
92
 
93
+ // src/mcp/http.ts
94
+ import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
95
+ var DEFAULT_MCP_HTTP_PORT = 8829;
96
+ var MCP_HTTP_HOST = "127.0.0.1";
97
+ function isHttpMode(args) {
98
+ return args.includes("--http") || process.env.MCP_HTTP === "1";
99
+ }
100
+ function resolveMcpHttpPort(args) {
101
+ const portIdx = args.indexOf("--port");
102
+ if (portIdx >= 0 && args[portIdx + 1]) {
103
+ return Number(args[portIdx + 1]);
104
+ }
105
+ const envPort = process.env.MCP_HTTP_PORT;
106
+ if (envPort)
107
+ return Number(envPort);
108
+ return DEFAULT_MCP_HTTP_PORT;
109
+ }
110
+ async function handleMcpRequest(req, buildServer) {
111
+ const transport = new WebStandardStreamableHTTPServerTransport({
112
+ sessionIdGenerator: undefined
113
+ });
114
+ const server = buildServer();
115
+ await server.connect(transport);
116
+ return transport.handleRequest(req);
117
+ }
118
+ function startMcpHttpServer(options) {
119
+ const { name, port, buildServer } = options;
120
+ const server = Bun.serve({
121
+ hostname: MCP_HTTP_HOST,
122
+ port,
123
+ async fetch(req) {
124
+ const url = new URL(req.url);
125
+ if (url.pathname === "/health" && req.method === "GET") {
126
+ return Response.json({ status: "ok", name });
127
+ }
128
+ if (url.pathname === "/mcp") {
129
+ return handleMcpRequest(req, buildServer);
130
+ }
131
+ return new Response("Not Found", { status: 404 });
132
+ }
133
+ });
134
+ console.error(`${name}-mcp HTTP listening on http://${MCP_HTTP_HOST}:${port}/mcp`);
135
+ return server;
136
+ }
137
+
93
138
  // node_modules/@hasna/cloud/dist/index.js
94
139
  import { createRequire } from "module";
95
140
  import { Database } from "bun:sqlite";
@@ -14983,388 +15028,404 @@ async function processText(rawText, config, systemPrompt) {
14983
15028
  }
14984
15029
 
14985
15030
  // src/version.ts
14986
- var VERSION = "0.1.19";
15031
+ var VERSION = "0.1.21";
14987
15032
 
14988
15033
  // src/mcp/index.ts
14989
15034
  var config = loadConfig();
14990
15035
  ensureDataDir(config);
14991
15036
  getDatabase(config.db_path);
14992
- var server = new McpServer({
14993
- name: "recordings",
14994
- version: VERSION
14995
- });
14996
- var registerTool = server.tool.bind(server);
14997
- function text(content) {
14998
- return { content: [{ type: "text", text: content }] };
14999
- }
15000
- function errorResult(e) {
15001
- const msg = e instanceof Error ? e.message : String(e);
15002
- return { content: [{ type: "text", text: `Error: ${msg}` }], isError: true };
15003
- }
15004
- function compact(r) {
15005
- const t = (r.processed_text || r.raw_text).slice(0, 80);
15006
- return `${r.id.slice(0, 8)} | ${r.processing_mode} | ${r.created_at.slice(0, 16)} | ${t}${t.length >= 80 ? "..." : ""}`;
15007
- }
15008
- function full(r) {
15009
- const lines = [`ID: ${r.id}`, `Mode: ${r.processing_mode}`, `Model: ${r.model_used}`];
15010
- if (r.enhancement_model)
15011
- lines.push(`Enhanced by: ${r.enhancement_model}`);
15012
- if (r.duration_ms)
15013
- lines.push(`Duration: ${(r.duration_ms / 1000).toFixed(1)}s`);
15014
- if (r.language)
15015
- lines.push(`Language: ${r.language}`);
15016
- if (r.tags.length > 0)
15017
- lines.push(`Tags: ${r.tags.join(", ")}`);
15018
- if (r.agent_id)
15019
- lines.push(`Agent: ${r.agent_id}`);
15020
- if (r.project_id)
15021
- lines.push(`Project: ${r.project_id}`);
15022
- if (r.session_id)
15023
- lines.push(`Session: ${r.session_id}`);
15024
- lines.push(`Created: ${r.created_at}`);
15025
- lines.push(`Text: ${r.raw_text}`);
15026
- if (r.processed_text && r.processed_text !== r.raw_text) {
15027
- lines.push(`Enhanced: ${r.processed_text}`);
15028
- }
15029
- return lines.join(`
15037
+ function buildServer() {
15038
+ const server = new McpServer({
15039
+ name: "recordings",
15040
+ version: VERSION
15041
+ });
15042
+ const registerTool = server.tool.bind(server);
15043
+ function text(content) {
15044
+ return { content: [{ type: "text", text: content }] };
15045
+ }
15046
+ function errorResult(e) {
15047
+ const msg = e instanceof Error ? e.message : String(e);
15048
+ return { content: [{ type: "text", text: `Error: ${msg}` }], isError: true };
15049
+ }
15050
+ function compact(r) {
15051
+ const t = (r.processed_text || r.raw_text).slice(0, 80);
15052
+ return `${r.id.slice(0, 8)} | ${r.processing_mode} | ${r.created_at.slice(0, 16)} | ${t}${t.length >= 80 ? "..." : ""}`;
15053
+ }
15054
+ function full(r) {
15055
+ const lines = [`ID: ${r.id}`, `Mode: ${r.processing_mode}`, `Model: ${r.model_used}`];
15056
+ if (r.enhancement_model)
15057
+ lines.push(`Enhanced by: ${r.enhancement_model}`);
15058
+ if (r.duration_ms)
15059
+ lines.push(`Duration: ${(r.duration_ms / 1000).toFixed(1)}s`);
15060
+ if (r.language)
15061
+ lines.push(`Language: ${r.language}`);
15062
+ if (r.tags.length > 0)
15063
+ lines.push(`Tags: ${r.tags.join(", ")}`);
15064
+ if (r.agent_id)
15065
+ lines.push(`Agent: ${r.agent_id}`);
15066
+ if (r.project_id)
15067
+ lines.push(`Project: ${r.project_id}`);
15068
+ if (r.session_id)
15069
+ lines.push(`Session: ${r.session_id}`);
15070
+ lines.push(`Created: ${r.created_at}`);
15071
+ lines.push(`Text: ${r.raw_text}`);
15072
+ if (r.processed_text && r.processed_text !== r.raw_text) {
15073
+ lines.push(`Enhanced: ${r.processed_text}`);
15074
+ }
15075
+ return lines.join(`
15030
15076
  `);
15031
- }
15032
- async function saveRecordingMemento(args) {
15033
- try {
15034
- const proc = Bun.spawn([
15035
- "mementos",
15036
- "save",
15037
- "--scope",
15038
- "shared",
15039
- "--category",
15040
- "history",
15041
- "--importance",
15042
- "5",
15043
- "--tags",
15044
- "recording,transcription",
15045
- "--summary",
15046
- args.summary,
15047
- args.key,
15048
- args.value
15049
- ], {
15050
- stdout: "ignore",
15051
- stderr: "ignore"
15052
- });
15053
- await proc.exited;
15054
- } catch {}
15055
- }
15056
- var toolDocs = {
15057
- transcribe_audio: `Transcribe audio file. Auto-enhances if needed.
15077
+ }
15078
+ async function saveRecordingMemento(args) {
15079
+ try {
15080
+ const proc = Bun.spawn([
15081
+ "mementos",
15082
+ "save",
15083
+ "--scope",
15084
+ "shared",
15085
+ "--category",
15086
+ "history",
15087
+ "--importance",
15088
+ "5",
15089
+ "--tags",
15090
+ "recording,transcription",
15091
+ "--summary",
15092
+ args.summary,
15093
+ args.key,
15094
+ args.value
15095
+ ], {
15096
+ stdout: "ignore",
15097
+ stderr: "ignore"
15098
+ });
15099
+ await proc.exited;
15100
+ } catch {}
15101
+ }
15102
+ const toolDocs = {
15103
+ transcribe_audio: `Transcribe audio file. Auto-enhances if needed.
15058
15104
  Params: audio_path (string, required): path to wav/mp3/m4a/webm | language (string): ISO code e.g. en/es/fr | no_enhance (bool): skip AI enhancement | tags (string[]): tags | agent_id (string) | project_id (string) | session_id (string)`,
15059
- save_recording: `Save text as recording. Auto-enhances if needed.
15105
+ save_recording: `Save text as recording. Auto-enhances if needed.
15060
15106
  Params: text (string, required): text to save | enhance (bool): force enhancement | tags (string[]) | agent_id (string) | project_id (string) | session_id (string) | metadata (object)`,
15061
- get_recording: `Get recording by ID or prefix.
15107
+ get_recording: `Get recording by ID or prefix.
15062
15108
  Params: id (string, required): recording ID or prefix`,
15063
- list_recordings: `List recordings, compact by default, most recent first.
15109
+ list_recordings: `List recordings, compact by default, most recent first.
15064
15110
  Params: limit (number, default 10) | offset (number) | processing_mode ('raw'|'enhanced') | tags (string[]) | search (string): text search | since/until (ISO date) | agent_id | project_id | session_id | full (bool): verbose output`,
15065
- search_recordings: `Search recordings by text content.
15111
+ search_recordings: `Search recordings by text content.
15066
15112
  Params: query (string, required) | limit (number, default 10) | agent_id | project_id | full (bool): verbose output`,
15067
- delete_recording: `Delete recording by ID.
15113
+ delete_recording: `Delete recording by ID.
15068
15114
  Params: id (string, required)`,
15069
- recording_stats: `Recording count, mode breakdown, duration.
15115
+ recording_stats: `Recording count, mode breakdown, duration.
15070
15116
  Params: none`,
15071
- detect_enhancement: `Check if text needs AI enhancement.
15117
+ detect_enhancement: `Check if text needs AI enhancement.
15072
15118
  Params: text (string, required)`,
15073
- register_agent: `Register agent (idempotent). Auto-updates last_seen_at on re-register.
15119
+ register_agent: `Register agent (idempotent). Auto-updates last_seen_at on re-register.
15074
15120
  Params: name (string, required) | description (string) | role (string)`,
15075
- list_agents: `List registered agents.
15121
+ list_agents: `List registered agents.
15076
15122
  Params: none`,
15077
- get_agent: `Get agent by ID or name.
15123
+ get_agent: `Get agent by ID or name.
15078
15124
  Params: id (string, required)`,
15079
- heartbeat: `Update last_seen_at to signal agent is active.
15125
+ heartbeat: `Update last_seen_at to signal agent is active.
15080
15126
  Params: agent_id (string, required): agent ID or name`,
15081
- set_focus: `Set active project context for this agent session.
15127
+ set_focus: `Set active project context for this agent session.
15082
15128
  Params: agent_id (string, required) | project_id (string, nullable): project ID or null to clear`,
15083
- register_project: `Register project (idempotent).
15129
+ register_project: `Register project (idempotent).
15084
15130
  Params: name (string, required) | path (string, required): absolute path | description (string)`,
15085
- list_projects: `List registered projects.
15131
+ list_projects: `List registered projects.
15086
15132
  Params: none`
15087
- };
15088
- registerTool("describe_tool", "Get full param docs for any tool.", { name: exports_external2.string() }, async (args) => {
15089
- const doc = toolDocs[args.name];
15090
- return doc ? text(doc) : text(`Unknown tool: ${args.name}. Available: ${Object.keys(toolDocs).join(", ")}`);
15091
- });
15092
- registerTool("transcribe_audio", "Transcribe audio file. Auto-enhances if needed.", {
15093
- audio_path: exports_external2.string(),
15094
- language: exports_external2.string().optional(),
15095
- no_enhance: exports_external2.boolean().optional(),
15096
- tags: exports_external2.array(exports_external2.string()).optional(),
15097
- agent_id: exports_external2.string().optional(),
15098
- project_id: exports_external2.string().optional(),
15099
- session_id: exports_external2.string().optional()
15100
- }, async (args) => {
15101
- try {
15102
- const cfg = { ...config };
15103
- if (args.language)
15104
- cfg.language = args.language;
15105
- if (args.no_enhance)
15106
- cfg.auto_enhance = false;
15107
- const transcription = await transcribeAudio(args.audio_path, cfg);
15108
- const processed = await processText(transcription.text, cfg);
15109
- const recording = createRecording({
15110
- audio_path: args.audio_path,
15111
- raw_text: transcription.text,
15112
- processed_text: processed.mode === "enhanced" ? processed.text : undefined,
15113
- processing_mode: processed.mode,
15114
- model_used: transcription.model,
15115
- enhancement_model: processed.enhancement_model || undefined,
15116
- duration_ms: transcription.duration_ms,
15117
- language: transcription.language || undefined,
15118
- tags: args.tags,
15119
- agent_id: args.agent_id,
15120
- project_id: args.project_id,
15121
- session_id: args.session_id
15122
- });
15123
- if (args.agent_id) {
15124
- await saveRecordingMemento({
15125
- key: `recording-${recording.id}`,
15126
- value: JSON.stringify({
15127
- recording_id: recording.id,
15128
- text: processed.mode === "enhanced" ? processed.text : transcription.text,
15129
- agent_id: args.agent_id,
15130
- project_id: args.project_id,
15131
- session_id: args.session_id,
15132
- created_at: recording.created_at
15133
- }),
15134
- summary: `Recording ${recording.id.slice(0, 8)} for ${args.agent_id}`
15135
- });
15133
+ };
15134
+ registerTool("describe_tool", "Get full param docs for any tool.", { name: exports_external2.string() }, async (args) => {
15135
+ const doc = toolDocs[args.name];
15136
+ return doc ? text(doc) : text(`Unknown tool: ${args.name}. Available: ${Object.keys(toolDocs).join(", ")}`);
15137
+ });
15138
+ registerTool("transcribe_audio", "Transcribe audio file. Auto-enhances if needed.", {
15139
+ audio_path: exports_external2.string(),
15140
+ language: exports_external2.string().optional(),
15141
+ no_enhance: exports_external2.boolean().optional(),
15142
+ tags: exports_external2.array(exports_external2.string()).optional(),
15143
+ agent_id: exports_external2.string().optional(),
15144
+ project_id: exports_external2.string().optional(),
15145
+ session_id: exports_external2.string().optional()
15146
+ }, async (args) => {
15147
+ try {
15148
+ const cfg = { ...config };
15149
+ if (args.language)
15150
+ cfg.language = args.language;
15151
+ if (args.no_enhance)
15152
+ cfg.auto_enhance = false;
15153
+ const transcription = await transcribeAudio(args.audio_path, cfg);
15154
+ const processed = await processText(transcription.text, cfg);
15155
+ const recording = createRecording({
15156
+ audio_path: args.audio_path,
15157
+ raw_text: transcription.text,
15158
+ processed_text: processed.mode === "enhanced" ? processed.text : undefined,
15159
+ processing_mode: processed.mode,
15160
+ model_used: transcription.model,
15161
+ enhancement_model: processed.enhancement_model || undefined,
15162
+ duration_ms: transcription.duration_ms,
15163
+ language: transcription.language || undefined,
15164
+ tags: args.tags,
15165
+ agent_id: args.agent_id,
15166
+ project_id: args.project_id,
15167
+ session_id: args.session_id
15168
+ });
15169
+ if (args.agent_id) {
15170
+ await saveRecordingMemento({
15171
+ key: `recording-${recording.id}`,
15172
+ value: JSON.stringify({
15173
+ recording_id: recording.id,
15174
+ text: processed.mode === "enhanced" ? processed.text : transcription.text,
15175
+ agent_id: args.agent_id,
15176
+ project_id: args.project_id,
15177
+ session_id: args.session_id,
15178
+ created_at: recording.created_at
15179
+ }),
15180
+ summary: `Recording ${recording.id.slice(0, 8)} for ${args.agent_id}`
15181
+ });
15182
+ }
15183
+ const output = processed.mode === "enhanced" ? processed.text : transcription.text;
15184
+ return text(`${recording.id.slice(0, 8)} | ${processed.mode} | ${output}`);
15185
+ } catch (e) {
15186
+ return errorResult(e);
15136
15187
  }
15137
- const output = processed.mode === "enhanced" ? processed.text : transcription.text;
15138
- return text(`${recording.id.slice(0, 8)} | ${processed.mode} | ${output}`);
15139
- } catch (e) {
15140
- return errorResult(e);
15141
- }
15142
- });
15143
- registerTool("save_recording", "Save text as recording. Auto-enhances if needed.", {
15144
- text: exports_external2.string(),
15145
- enhance: exports_external2.boolean().optional(),
15146
- tags: exports_external2.array(exports_external2.string()).optional(),
15147
- agent_id: exports_external2.string().optional(),
15148
- project_id: exports_external2.string().optional(),
15149
- session_id: exports_external2.string().optional(),
15150
- goal: exports_external2.string().optional().describe("Goal or purpose of this recording session (e.g. 'code review for PR #123')"),
15151
- role: exports_external2.string().optional().describe("Agent role for this session (e.g. 'dev agent for connectdev')"),
15152
- task_list_id: exports_external2.string().optional().describe("Task list ID to bind this recording to"),
15153
- metadata: exports_external2.record(exports_external2.unknown()).optional()
15154
- }, async (args) => {
15155
- try {
15156
- let processedText;
15157
- let mode = "raw";
15158
- let enhModel;
15159
- if (args.enhance !== false) {
15160
- const processed = await processText(args.text, config);
15161
- if (processed.mode === "enhanced") {
15162
- processedText = processed.text;
15163
- mode = "enhanced";
15164
- enhModel = processed.enhancement_model || undefined;
15165
- }
15166
- }
15167
- const recording = createRecording({
15168
- raw_text: args.text,
15169
- processed_text: processedText,
15170
- processing_mode: mode,
15171
- model_used: "direct-input",
15172
- enhancement_model: enhModel,
15173
- tags: args.tags,
15174
- agent_id: args.agent_id,
15175
- project_id: args.project_id,
15176
- session_id: args.session_id,
15177
- goal: args.goal,
15178
- role: args.role,
15179
- task_list_id: args.task_list_id,
15180
- metadata: args.metadata
15181
- });
15182
- const output = processedText || args.text;
15183
- return text(`${recording.id.slice(0, 8)} | ${mode} | ${output}`);
15184
- } catch (e) {
15185
- return errorResult(e);
15186
- }
15187
- });
15188
- registerTool("get_recording", "Get recording by ID or prefix.", { id: exports_external2.string() }, async (args) => {
15189
- try {
15190
- const r = getRecording(args.id);
15191
- if (!r)
15192
- return text(`Not found: ${args.id}`);
15193
- return text(full(r));
15194
- } catch (e) {
15195
- return errorResult(e);
15196
- }
15197
- });
15198
- registerTool("list_recordings", "List recordings. Compact default, recent first.", {
15199
- limit: exports_external2.number().optional(),
15200
- offset: exports_external2.number().optional(),
15201
- processing_mode: exports_external2.enum(["raw", "enhanced"]).optional(),
15202
- tags: exports_external2.array(exports_external2.string()).optional(),
15203
- search: exports_external2.string().optional(),
15204
- since: exports_external2.string().optional(),
15205
- until: exports_external2.string().optional(),
15206
- agent_id: exports_external2.string().optional(),
15207
- project_id: exports_external2.string().optional(),
15208
- session_id: exports_external2.string().optional(),
15209
- full: exports_external2.boolean().optional()
15210
- }, async (args) => {
15211
- try {
15212
- const filter = {
15213
- limit: args.limit || 10,
15214
- offset: args.offset,
15215
- processing_mode: args.processing_mode,
15216
- tags: args.tags,
15217
- search: args.search,
15218
- since: args.since,
15219
- until: args.until,
15220
- agent_id: args.agent_id,
15221
- project_id: args.project_id,
15222
- session_id: args.session_id
15223
- };
15224
- const recordings = listRecordings(filter);
15225
- if (recordings.length === 0)
15226
- return text("No recordings found.");
15227
- const fmt = args.full ? full : compact;
15228
- const sep = args.full ? `
15188
+ });
15189
+ registerTool("save_recording", "Save text as recording. Auto-enhances if needed.", {
15190
+ text: exports_external2.string(),
15191
+ enhance: exports_external2.boolean().optional(),
15192
+ tags: exports_external2.array(exports_external2.string()).optional(),
15193
+ agent_id: exports_external2.string().optional(),
15194
+ project_id: exports_external2.string().optional(),
15195
+ session_id: exports_external2.string().optional(),
15196
+ goal: exports_external2.string().optional().describe("Goal or purpose of this recording session (e.g. 'code review for PR #123')"),
15197
+ role: exports_external2.string().optional().describe("Agent role for this session (e.g. 'dev agent for connectdev')"),
15198
+ task_list_id: exports_external2.string().optional().describe("Task list ID to bind this recording to"),
15199
+ metadata: exports_external2.record(exports_external2.unknown()).optional()
15200
+ }, async (args) => {
15201
+ try {
15202
+ let processedText;
15203
+ let mode = "raw";
15204
+ let enhModel;
15205
+ if (args.enhance !== false) {
15206
+ const processed = await processText(args.text, config);
15207
+ if (processed.mode === "enhanced") {
15208
+ processedText = processed.text;
15209
+ mode = "enhanced";
15210
+ enhModel = processed.enhancement_model || undefined;
15211
+ }
15212
+ }
15213
+ const recording = createRecording({
15214
+ raw_text: args.text,
15215
+ processed_text: processedText,
15216
+ processing_mode: mode,
15217
+ model_used: "direct-input",
15218
+ enhancement_model: enhModel,
15219
+ tags: args.tags,
15220
+ agent_id: args.agent_id,
15221
+ project_id: args.project_id,
15222
+ session_id: args.session_id,
15223
+ goal: args.goal,
15224
+ role: args.role,
15225
+ task_list_id: args.task_list_id,
15226
+ metadata: args.metadata
15227
+ });
15228
+ const output = processedText || args.text;
15229
+ return text(`${recording.id.slice(0, 8)} | ${mode} | ${output}`);
15230
+ } catch (e) {
15231
+ return errorResult(e);
15232
+ }
15233
+ });
15234
+ registerTool("get_recording", "Get recording by ID or prefix.", { id: exports_external2.string() }, async (args) => {
15235
+ try {
15236
+ const r = getRecording(args.id);
15237
+ if (!r)
15238
+ return text(`Not found: ${args.id}`);
15239
+ return text(full(r));
15240
+ } catch (e) {
15241
+ return errorResult(e);
15242
+ }
15243
+ });
15244
+ registerTool("list_recordings", "List recordings. Compact default, recent first.", {
15245
+ limit: exports_external2.number().optional(),
15246
+ offset: exports_external2.number().optional(),
15247
+ processing_mode: exports_external2.enum(["raw", "enhanced"]).optional(),
15248
+ tags: exports_external2.array(exports_external2.string()).optional(),
15249
+ search: exports_external2.string().optional(),
15250
+ since: exports_external2.string().optional(),
15251
+ until: exports_external2.string().optional(),
15252
+ agent_id: exports_external2.string().optional(),
15253
+ project_id: exports_external2.string().optional(),
15254
+ session_id: exports_external2.string().optional(),
15255
+ full: exports_external2.boolean().optional()
15256
+ }, async (args) => {
15257
+ try {
15258
+ const filter = {
15259
+ limit: args.limit || 10,
15260
+ offset: args.offset,
15261
+ processing_mode: args.processing_mode,
15262
+ tags: args.tags,
15263
+ search: args.search,
15264
+ since: args.since,
15265
+ until: args.until,
15266
+ agent_id: args.agent_id,
15267
+ project_id: args.project_id,
15268
+ session_id: args.session_id
15269
+ };
15270
+ const recordings = listRecordings(filter);
15271
+ if (recordings.length === 0)
15272
+ return text("No recordings found.");
15273
+ const fmt = args.full ? full : compact;
15274
+ const sep = args.full ? `
15229
15275
  ---
15230
15276
  ` : `
15231
15277
  `;
15232
- return text(`${recordings.length} recording(s):${sep}${recordings.map(fmt).join(sep)}`);
15233
- } catch (e) {
15234
- return errorResult(e);
15235
- }
15236
- });
15237
- registerTool("search_recordings", "Search recordings by text.", {
15238
- query: exports_external2.string(),
15239
- limit: exports_external2.number().optional(),
15240
- agent_id: exports_external2.string().optional(),
15241
- project_id: exports_external2.string().optional(),
15242
- full: exports_external2.boolean().optional()
15243
- }, async (args) => {
15244
- try {
15245
- const results = searchRecordings(args.query, {
15246
- limit: args.limit || 10,
15247
- agent_id: args.agent_id,
15248
- project_id: args.project_id
15249
- });
15250
- if (results.length === 0)
15251
- return text("No results.");
15252
- const fmt = args.full ? full : compact;
15253
- const sep = args.full ? `
15278
+ return text(`${recordings.length} recording(s):${sep}${recordings.map(fmt).join(sep)}`);
15279
+ } catch (e) {
15280
+ return errorResult(e);
15281
+ }
15282
+ });
15283
+ registerTool("search_recordings", "Search recordings by text.", {
15284
+ query: exports_external2.string(),
15285
+ limit: exports_external2.number().optional(),
15286
+ agent_id: exports_external2.string().optional(),
15287
+ project_id: exports_external2.string().optional(),
15288
+ full: exports_external2.boolean().optional()
15289
+ }, async (args) => {
15290
+ try {
15291
+ const results = searchRecordings(args.query, {
15292
+ limit: args.limit || 10,
15293
+ agent_id: args.agent_id,
15294
+ project_id: args.project_id
15295
+ });
15296
+ if (results.length === 0)
15297
+ return text("No results.");
15298
+ const fmt = args.full ? full : compact;
15299
+ const sep = args.full ? `
15254
15300
  ---
15255
15301
  ` : `
15256
15302
  `;
15257
- return text(`${results.length} result(s):${sep}${results.map(fmt).join(sep)}`);
15258
- } catch (e) {
15259
- return errorResult(e);
15260
- }
15261
- });
15262
- registerTool("delete_recording", "Delete recording by ID.", { id: exports_external2.string() }, async (args) => {
15263
- try {
15264
- return text(deleteRecording(args.id) ? `Deleted ${args.id}` : `Not found: ${args.id}`);
15265
- } catch (e) {
15266
- return errorResult(e);
15267
- }
15268
- });
15269
- registerTool("recording_stats", "Recording stats: count, modes, duration.", {}, async () => {
15270
- try {
15271
- const s = getRecordingStats();
15272
- let out = `Total: ${s.total} | Raw: ${s.raw} | Enhanced: ${s.enhanced} | Duration: ${(s.total_duration_ms / 1000).toFixed(1)}s`;
15273
- if (Object.keys(s.by_model).length > 0) {
15274
- out += `
15303
+ return text(`${results.length} result(s):${sep}${results.map(fmt).join(sep)}`);
15304
+ } catch (e) {
15305
+ return errorResult(e);
15306
+ }
15307
+ });
15308
+ registerTool("delete_recording", "Delete recording by ID.", { id: exports_external2.string() }, async (args) => {
15309
+ try {
15310
+ return text(deleteRecording(args.id) ? `Deleted ${args.id}` : `Not found: ${args.id}`);
15311
+ } catch (e) {
15312
+ return errorResult(e);
15313
+ }
15314
+ });
15315
+ registerTool("recording_stats", "Recording stats: count, modes, duration.", {}, async () => {
15316
+ try {
15317
+ const s = getRecordingStats();
15318
+ let out = `Total: ${s.total} | Raw: ${s.raw} | Enhanced: ${s.enhanced} | Duration: ${(s.total_duration_ms / 1000).toFixed(1)}s`;
15319
+ if (Object.keys(s.by_model).length > 0) {
15320
+ out += `
15275
15321
  ` + Object.entries(s.by_model).map(([m, c]) => `${m}: ${c}`).join(", ");
15322
+ }
15323
+ return text(out);
15324
+ } catch (e) {
15325
+ return errorResult(e);
15276
15326
  }
15277
- return text(out);
15278
- } catch (e) {
15279
- return errorResult(e);
15280
- }
15281
- });
15282
- registerTool("detect_enhancement", "Check if text needs AI enhancement.", { text: exports_external2.string() }, async (args) => {
15283
- try {
15284
- const r = needsEnhancement(args.text, config);
15285
- return text(`${r.needs ? "Yes" : "No"}: ${r.reason}`);
15286
- } catch (e) {
15287
- return errorResult(e);
15288
- }
15289
- });
15290
- registerTool("register_agent", "Register agent (idempotent).", { name: exports_external2.string(), description: exports_external2.string().optional(), role: exports_external2.string().optional() }, async (args) => {
15291
- try {
15292
- const a = registerAgent(args.name, args.description, args.role);
15293
- return text(`${a.id} | ${a.name} | ${a.role}`);
15294
- } catch (e) {
15295
- return errorResult(e);
15296
- }
15297
- });
15298
- registerTool("list_agents", "List registered agents.", {}, async () => {
15299
- try {
15300
- const agents = listAgents();
15301
- if (agents.length === 0)
15302
- return text("None.");
15303
- return text(agents.map((a) => `${a.id} | ${a.name} | ${a.role}`).join(`
15327
+ });
15328
+ registerTool("detect_enhancement", "Check if text needs AI enhancement.", { text: exports_external2.string() }, async (args) => {
15329
+ try {
15330
+ const r = needsEnhancement(args.text, config);
15331
+ return text(`${r.needs ? "Yes" : "No"}: ${r.reason}`);
15332
+ } catch (e) {
15333
+ return errorResult(e);
15334
+ }
15335
+ });
15336
+ registerTool("register_agent", "Register agent (idempotent).", { name: exports_external2.string(), description: exports_external2.string().optional(), role: exports_external2.string().optional() }, async (args) => {
15337
+ try {
15338
+ const a = registerAgent(args.name, args.description, args.role);
15339
+ return text(`${a.id} | ${a.name} | ${a.role}`);
15340
+ } catch (e) {
15341
+ return errorResult(e);
15342
+ }
15343
+ });
15344
+ registerTool("list_agents", "List registered agents.", {}, async () => {
15345
+ try {
15346
+ const agents = listAgents();
15347
+ if (agents.length === 0)
15348
+ return text("None.");
15349
+ return text(agents.map((a) => `${a.id} | ${a.name} | ${a.role}`).join(`
15304
15350
  `));
15305
- } catch (e) {
15306
- return errorResult(e);
15307
- }
15308
- });
15309
- registerTool("get_agent", "Get agent by ID or name.", { id: exports_external2.string() }, async (args) => {
15310
- try {
15311
- const a = getAgent(args.id);
15312
- if (!a)
15313
- return text(`Not found: ${args.id}`);
15314
- return text(`${a.id} | ${a.name} | ${a.role} | ${a.last_seen_at}`);
15315
- } catch (e) {
15316
- return errorResult(e);
15317
- }
15318
- });
15319
- registerTool("register_project", "Register project (idempotent).", { name: exports_external2.string(), path: exports_external2.string(), description: exports_external2.string().optional() }, async (args) => {
15320
- try {
15321
- const p = registerProject(args.name, args.path, args.description);
15322
- return text(`${p.id.slice(0, 8)} | ${p.name} | ${p.path}`);
15323
- } catch (e) {
15324
- return errorResult(e);
15325
- }
15326
- });
15327
- registerTool("list_projects", "List registered projects.", {}, async () => {
15328
- try {
15329
- const projects = listProjects();
15330
- if (projects.length === 0)
15331
- return text("None.");
15332
- return text(projects.map((p) => `${p.id.slice(0, 8)} | ${p.name} | ${p.path}`).join(`
15351
+ } catch (e) {
15352
+ return errorResult(e);
15353
+ }
15354
+ });
15355
+ registerTool("get_agent", "Get agent by ID or name.", { id: exports_external2.string() }, async (args) => {
15356
+ try {
15357
+ const a = getAgent(args.id);
15358
+ if (!a)
15359
+ return text(`Not found: ${args.id}`);
15360
+ return text(`${a.id} | ${a.name} | ${a.role} | ${a.last_seen_at}`);
15361
+ } catch (e) {
15362
+ return errorResult(e);
15363
+ }
15364
+ });
15365
+ registerTool("register_project", "Register project (idempotent).", { name: exports_external2.string(), path: exports_external2.string(), description: exports_external2.string().optional() }, async (args) => {
15366
+ try {
15367
+ const p = registerProject(args.name, args.path, args.description);
15368
+ return text(`${p.id.slice(0, 8)} | ${p.name} | ${p.path}`);
15369
+ } catch (e) {
15370
+ return errorResult(e);
15371
+ }
15372
+ });
15373
+ registerTool("list_projects", "List registered projects.", {}, async () => {
15374
+ try {
15375
+ const projects = listProjects();
15376
+ if (projects.length === 0)
15377
+ return text("None.");
15378
+ return text(projects.map((p) => `${p.id.slice(0, 8)} | ${p.name} | ${p.path}`).join(`
15333
15379
  `));
15334
- } catch (e) {
15335
- return errorResult(e);
15336
- }
15337
- });
15338
- registerTool("heartbeat", "Update last_seen_at to signal agent is active. Call periodically during long tasks.", { agent_id: exports_external2.string().describe("Agent ID or name") }, async (args) => {
15339
- try {
15340
- const agent = heartbeatAgent(args.agent_id);
15341
- if (!agent)
15342
- return text(`Agent not found: ${args.agent_id}`);
15343
- return text(`${agent.id} | ${agent.name} | last_seen: ${agent.last_seen_at}`);
15344
- } catch (e) {
15345
- return errorResult(e);
15346
- }
15347
- });
15348
- registerTool("set_focus", "Set active project context for this agent session.", { agent_id: exports_external2.string().describe("Agent ID or name"), project_id: exports_external2.string().nullable().optional().describe("Project ID to focus on, or null to clear") }, async (args) => {
15349
- try {
15350
- const agent = setAgentFocus(args.agent_id, args.project_id ?? null);
15351
- if (!agent)
15352
- return text(`Agent not found: ${args.agent_id}`);
15353
- return text(args.project_id ? `Focus set: ${args.project_id}` : "Focus cleared");
15354
- } catch (e) {
15355
- return errorResult(e);
15380
+ } catch (e) {
15381
+ return errorResult(e);
15382
+ }
15383
+ });
15384
+ registerTool("heartbeat", "Update last_seen_at to signal agent is active. Call periodically during long tasks.", { agent_id: exports_external2.string().describe("Agent ID or name") }, async (args) => {
15385
+ try {
15386
+ const agent = heartbeatAgent(args.agent_id);
15387
+ if (!agent)
15388
+ return text(`Agent not found: ${args.agent_id}`);
15389
+ return text(`${agent.id} | ${agent.name} | last_seen: ${agent.last_seen_at}`);
15390
+ } catch (e) {
15391
+ return errorResult(e);
15392
+ }
15393
+ });
15394
+ registerTool("set_focus", "Set active project context for this agent session.", { agent_id: exports_external2.string().describe("Agent ID or name"), project_id: exports_external2.string().nullable().optional().describe("Project ID to focus on, or null to clear") }, async (args) => {
15395
+ try {
15396
+ const agent = setAgentFocus(args.agent_id, args.project_id ?? null);
15397
+ if (!agent)
15398
+ return text(`Agent not found: ${args.agent_id}`);
15399
+ return text(args.project_id ? `Focus set: ${args.project_id}` : "Focus cleared");
15400
+ } catch (e) {
15401
+ return errorResult(e);
15402
+ }
15403
+ });
15404
+ registerTool("send_feedback", "Send feedback about this service", {
15405
+ message: exports_external2.string().describe("Feedback message"),
15406
+ email: exports_external2.string().optional().describe("Contact email (optional)"),
15407
+ category: exports_external2.enum(["bug", "feature", "general"]).optional().describe("Feedback category")
15408
+ }, async (params) => {
15409
+ const adapter = getAdapter();
15410
+ const pkg = require_package();
15411
+ adapter.run("INSERT INTO feedback (message, email, category, version) VALUES (?, ?, ?, ?)", params.message, params.email || null, params.category || "general", pkg.version);
15412
+ return text("Feedback saved. Thank you!");
15413
+ });
15414
+ registerCloudTools(server, "recordings");
15415
+ return server;
15416
+ }
15417
+ async function main() {
15418
+ const args = process.argv.slice(2);
15419
+ if (isHttpMode(args)) {
15420
+ startMcpHttpServer({ name: "recordings", port: resolveMcpHttpPort(args), buildServer });
15421
+ return;
15356
15422
  }
15357
- });
15358
- registerTool("send_feedback", "Send feedback about this service", {
15359
- message: exports_external2.string().describe("Feedback message"),
15360
- email: exports_external2.string().optional().describe("Contact email (optional)"),
15361
- category: exports_external2.enum(["bug", "feature", "general"]).optional().describe("Feedback category")
15362
- }, async (params) => {
15363
- const adapter = getAdapter();
15364
- const pkg = require_package();
15365
- adapter.run("INSERT INTO feedback (message, email, category, version) VALUES (?, ?, ?, ?)", params.message, params.email || null, params.category || "general", pkg.version);
15366
- return text("Feedback saved. Thank you!");
15367
- });
15368
- var transport = new StdioServerTransport;
15369
- registerCloudTools(server, "recordings");
15370
- await server.connect(transport);
15423
+ const transport = new StdioServerTransport;
15424
+ await buildServer().connect(transport);
15425
+ }
15426
+ if (import.meta.main) {
15427
+ await main();
15428
+ }
15429
+ export {
15430
+ buildServer
15431
+ };