@hasna/recordings 0.1.32 → 0.1.34

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/cli/index.js CHANGED
@@ -5003,7 +5003,7 @@ var init_pg_migrations = __esm(() => {
5003
5003
  raw_text TEXT NOT NULL,
5004
5004
  processed_text TEXT,
5005
5005
  processing_mode TEXT NOT NULL DEFAULT 'raw' CHECK(processing_mode IN ('raw', 'enhanced')),
5006
- model_used TEXT NOT NULL DEFAULT 'gpt-4o-mini-transcribe',
5006
+ model_used TEXT NOT NULL DEFAULT 'gpt-4o-transcribe',
5007
5007
  enhancement_model TEXT,
5008
5008
  duration_ms INTEGER DEFAULT 0,
5009
5009
  language TEXT,
@@ -5098,7 +5098,7 @@ var init_pg_migrate = __esm(() => {
5098
5098
  var require_package = __commonJS((exports, module) => {
5099
5099
  module.exports = {
5100
5100
  name: "@hasna/recordings",
5101
- version: "0.1.32",
5101
+ version: "0.1.34",
5102
5102
  type: "module",
5103
5103
  description: "Speech-to-text recording tool with MCP and CLI \u2014 records, transcribes, and optionally enhances text using AI",
5104
5104
  repository: {
@@ -5148,7 +5148,7 @@ var require_package = __commonJS((exports, module) => {
5148
5148
  "LICENSE"
5149
5149
  ],
5150
5150
  dependencies: {
5151
- "@hasna/events": "^0.1.3",
5151
+ "@hasna/events": "^0.1.7",
5152
5152
  "@modelcontextprotocol/sdk": "^1.12.1",
5153
5153
  chalk: "^5.4.1",
5154
5154
  commander: "^13.1.0",
@@ -5736,9 +5736,15 @@ function print(value, json, text) {
5736
5736
  else
5737
5737
  console.log(text);
5738
5738
  }
5739
+ function hasJsonOption(options) {
5740
+ return Boolean(options?.json || options?.opts?.().json || options?.optsWithGlobals?.().json || options?.parent?.opts?.().json || options?.parent?.optsWithGlobals?.().json);
5741
+ }
5742
+ function wantsJson(actionOptions, command) {
5743
+ return hasJsonOption(actionOptions) || hasJsonOption(command);
5744
+ }
5739
5745
  function registerWebhookCommands(program, options) {
5740
5746
  const webhooks = program.command(options.webhooksCommandName ?? "webhooks").description("Manage Hasna event webhook subscriptions");
5741
- webhooks.command("add").description("Add or replace a webhook or command subscription").argument("<target>", "Webhook URL or command binary").requiredOption("--id <id>", "Subscription/channel identifier").option("--transport <kind>", "Transport kind: webhook or command", "webhook").option("--name <name>", "Display name").option("--type <pattern>", "Event type filter, e.g. todos.task.*").option("--source <pattern>", "Event source filter").option("--subject <pattern>", "Event subject filter").option("--severity <pattern>", "Event severity filter").option("--secret <secret>", "Webhook HMAC secret").option("--header <name=value...>", "Webhook header", collectValues, []).option("--arg <arg...>", "Command argument", collectValues, []).option("--timeout-ms <ms>", "Transport timeout in milliseconds", parseNumber).option("--retry-attempts <n>", "Maximum delivery attempts", parseNumber).option("--retry-backoff-ms <ms>", "Initial retry backoff in milliseconds", parseNumber).option("--redact <path...>", "Event field path to redact before delivery", collectValues, []).option("--disabled", "Create channel disabled", false).option("-j, --json", "Print JSON output", false).action(async (target, actionOptions) => {
5747
+ webhooks.command("add").description("Add or replace a webhook or command subscription").argument("<target>", "Webhook URL or command binary").requiredOption("--id <id>", "Subscription/channel identifier").option("--transport <kind>", "Transport kind: webhook or command", "webhook").option("--name <name>", "Display name").option("--type <pattern>", "Event type filter, e.g. todos.task.*").option("--source <pattern>", "Event source filter").option("--subject <pattern>", "Event subject filter").option("--severity <pattern>", "Event severity filter").option("--secret <secret>", "Webhook HMAC secret").option("--header <name=value...>", "Webhook header", collectValues, []).option("--arg <arg...>", "Command argument", collectValues, []).option("--timeout-ms <ms>", "Transport timeout in milliseconds", parseNumber).option("--retry-attempts <n>", "Maximum delivery attempts", parseNumber).option("--retry-backoff-ms <ms>", "Initial retry backoff in milliseconds", parseNumber).option("--redact <path...>", "Event field path to redact before delivery", collectValues, []).option("--disabled", "Create channel disabled", false).option("-j, --json", "Print JSON output", false).action(async (target, actionOptions, command) => {
5742
5748
  const timestamp = new Date().toISOString();
5743
5749
  const channel = {
5744
5750
  id: actionOptions.id,
@@ -5759,11 +5765,11 @@ function registerWebhookCommands(program, options) {
5759
5765
  throw new Error(`Transport ${actionOptions.transport} is reserved for future use and cannot be added yet`);
5760
5766
  }
5761
5767
  const saved = await createClient(options).addChannel(channel);
5762
- print(sanitizeChannelForOutput(saved), Boolean(actionOptions.json), `Added ${saved.transport} channel ${saved.id}`);
5768
+ print(sanitizeChannelForOutput(saved), wantsJson(actionOptions, command), `Added ${saved.transport} channel ${saved.id}`);
5763
5769
  });
5764
- webhooks.command("list").description("List configured subscriptions").option("-j, --json", "Print JSON output", false).action(async (actionOptions) => {
5770
+ webhooks.command("list").description("List configured subscriptions").option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
5765
5771
  const channels = await createClient(options).listChannels();
5766
- if (actionOptions.json) {
5772
+ if (wantsJson(actionOptions, command)) {
5767
5773
  console.log(JSON.stringify(sanitizeChannelsForOutput(channels), null, 2));
5768
5774
  return;
5769
5775
  }
@@ -5775,11 +5781,11 @@ function registerWebhookCommands(program, options) {
5775
5781
  console.log(`${channel.id} ${channel.enabled ? "enabled" : "disabled"} ${channel.transport} ${channel.webhook?.url ?? channel.command?.command ?? channel.transport}`);
5776
5782
  }
5777
5783
  });
5778
- webhooks.command("remove").description("Remove a subscription").argument("<id>", "Subscription/channel identifier").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions) => {
5784
+ webhooks.command("remove").description("Remove a subscription").argument("<id>", "Subscription/channel identifier").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
5779
5785
  const removed = await createClient(options).removeChannel(id);
5780
- print({ removed }, Boolean(actionOptions.json), removed ? `Removed ${id}` : `Channel not found: ${id}`);
5786
+ print({ removed }, wantsJson(actionOptions, command), removed ? `Removed ${id}` : `Channel not found: ${id}`);
5781
5787
  });
5782
- webhooks.command("test").description("Send a test event to one subscription").argument("<id>", "Subscription/channel identifier").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events test delivery").option("--data <json>", "Event data JSON object").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions) => {
5788
+ webhooks.command("test").description("Send a test event to one subscription").argument("<id>", "Subscription/channel identifier").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events test delivery").option("--data <json>", "Event data JSON object").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
5783
5789
  const result = await createClient(options).testChannel(id, {
5784
5790
  source: options.source,
5785
5791
  type: actionOptions.type,
@@ -5787,13 +5793,13 @@ function registerWebhookCommands(program, options) {
5787
5793
  message: actionOptions.message,
5788
5794
  data: parseJsonObject(actionOptions.data, { test: true })
5789
5795
  });
5790
- print(result, Boolean(actionOptions.json), `${result.status}: ${result.channelId}`);
5796
+ print(result, wantsJson(actionOptions, command), `${result.status}: ${result.channelId}`);
5791
5797
  });
5792
5798
  return webhooks;
5793
5799
  }
5794
5800
  function registerEventCommands(program, options) {
5795
5801
  const events = program.command(options.eventsCommandName ?? "events").description("Emit, list, and replay Hasna events");
5796
- events.command("emit").description("Emit an event from this app").argument("<type>", "Event type").option("--source <source>", "Event source override").option("--subject <subject>", "Event subject").option("--severity <severity>", "Event severity", "info").option("--message <message>", "Event message").option("--dedupe-key <key>", "Dedupe key").option("--data <json>", "Event data JSON object").option("--metadata <json>", "Event metadata JSON object").option("--no-deliver", "Record without delivering").option("--no-dedupe", "Allow duplicate id/dedupeKey events").option("-j, --json", "Print JSON output", false).action(async (type, actionOptions) => {
5802
+ events.command("emit").description("Emit an event from this app").argument("<type>", "Event type").option("--source <source>", "Event source override").option("--subject <subject>", "Event subject").option("--severity <severity>", "Event severity", "info").option("--message <message>", "Event message").option("--dedupe-key <key>", "Dedupe key").option("--data <json>", "Event data JSON object").option("--metadata <json>", "Event metadata JSON object").option("--no-deliver", "Record without delivering").option("--no-dedupe", "Allow duplicate id/dedupeKey events").option("-j, --json", "Print JSON output", false).action(async (type, actionOptions, command) => {
5797
5803
  const result = await createClient(options).emit({
5798
5804
  source: actionOptions.source ?? options.source,
5799
5805
  type,
@@ -5804,9 +5810,9 @@ function registerEventCommands(program, options) {
5804
5810
  data: parseJsonObject(actionOptions.data, {}),
5805
5811
  metadata: parseJsonObject(actionOptions.metadata, {})
5806
5812
  }, { deliver: actionOptions.deliver, dedupe: actionOptions.dedupe });
5807
- print(result, Boolean(actionOptions.json), `${result.deduped ? "Deduped" : "Emitted"} ${result.event.id} to ${result.deliveries.length} channel(s)`);
5813
+ print(result, wantsJson(actionOptions, command), `${result.deduped ? "Deduped" : "Emitted"} ${result.event.id} to ${result.deliveries.length} channel(s)`);
5808
5814
  });
5809
- events.command("list").description("List recorded events").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--limit <n>", "Limit results", parseNumber).option("-j, --json", "Print JSON output", false).action(async (actionOptions) => {
5815
+ events.command("list").description("List recorded events").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--limit <n>", "Limit results", parseNumber).option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
5810
5816
  let rows = await createClient(options).listEvents();
5811
5817
  if (actionOptions.source)
5812
5818
  rows = rows.filter((event) => event.source === actionOptions.source);
@@ -5814,7 +5820,7 @@ function registerEventCommands(program, options) {
5814
5820
  rows = rows.filter((event) => event.type === actionOptions.type);
5815
5821
  if (actionOptions.limit)
5816
5822
  rows = rows.slice(-actionOptions.limit);
5817
- if (actionOptions.json) {
5823
+ if (wantsJson(actionOptions, command)) {
5818
5824
  console.log(JSON.stringify(rows, null, 2));
5819
5825
  return;
5820
5826
  }
@@ -5825,14 +5831,14 @@ function registerEventCommands(program, options) {
5825
5831
  for (const event of rows)
5826
5832
  console.log(`${event.time} ${event.id} ${event.source} ${event.type} ${event.severity}`);
5827
5833
  });
5828
- events.command("replay").description("Replay recorded events").option("--id <id>", "Replay one event id").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--dry-run", "Preview without delivery", false).option("-j, --json", "Print JSON output", false).action(async (actionOptions) => {
5834
+ events.command("replay").description("Replay recorded events").option("--id <id>", "Replay one event id").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--dry-run", "Preview without delivery", false).option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
5829
5835
  const result = await createClient(options).replay({
5830
5836
  eventId: actionOptions.id,
5831
5837
  source: actionOptions.source,
5832
5838
  type: actionOptions.type,
5833
5839
  dryRun: actionOptions.dryRun
5834
5840
  });
5835
- print(result, Boolean(actionOptions.json), `Replayed ${result.events.length} event(s), ${result.deliveries.length} delivery result(s)`);
5841
+ print(result, wantsJson(actionOptions, command), `Replayed ${result.events.length} event(s), ${result.deliveries.length} delivery result(s)`);
5836
5842
  });
5837
5843
  return events;
5838
5844
  }
@@ -5865,7 +5871,7 @@ import { homedir as homedir2 } from "os";
5865
5871
  var DEFAULT_CONFIG = {
5866
5872
  openai_api_key: "",
5867
5873
  enhancement_api_key: "",
5868
- transcription_model: "gpt-4o-mini-transcribe",
5874
+ transcription_model: "gpt-4o-transcribe",
5869
5875
  enhancement_model: "gpt-4o",
5870
5876
  language: "en",
5871
5877
  audio_format: "wav",
@@ -6103,7 +6109,7 @@ var MIGRATIONS = [
6103
6109
  raw_text TEXT NOT NULL,
6104
6110
  processed_text TEXT,
6105
6111
  processing_mode TEXT NOT NULL DEFAULT 'raw' CHECK(processing_mode IN ('raw', 'enhanced')),
6106
- model_used TEXT NOT NULL DEFAULT 'gpt-4o-mini-transcribe',
6112
+ model_used TEXT NOT NULL DEFAULT 'gpt-4o-transcribe',
6107
6113
  enhancement_model TEXT,
6108
6114
  duration_ms INTEGER DEFAULT 0,
6109
6115
  language TEXT,
@@ -6233,7 +6239,7 @@ function parseRow(row) {
6233
6239
  raw_text: row["raw_text"],
6234
6240
  processed_text: row["processed_text"] || null,
6235
6241
  processing_mode: row["processing_mode"] || "raw",
6236
- model_used: row["model_used"] || "gpt-4o-mini-transcribe",
6242
+ model_used: row["model_used"] || "gpt-4o-transcribe",
6237
6243
  enhancement_model: row["enhancement_model"] || null,
6238
6244
  duration_ms: row["duration_ms"] || 0,
6239
6245
  language: row["language"] || null,
@@ -6255,7 +6261,7 @@ function createRecording(input, db) {
6255
6261
  const tagsJson = JSON.stringify(input.tags || []);
6256
6262
  const metadataJson = JSON.stringify(input.metadata || {});
6257
6263
  d.query(`INSERT INTO recordings (id, audio_path, raw_text, processed_text, processing_mode, model_used, enhancement_model, duration_ms, language, tags, agent_id, project_id, session_id, goal, role, task_list_id, machine_id, metadata)
6258
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, input.audio_path || null, input.raw_text, input.processed_text || null, input.processing_mode || "raw", input.model_used || "gpt-4o-mini-transcribe", input.enhancement_model || null, input.duration_ms || 0, input.language || null, tagsJson, input.agent_id || null, input.project_id || null, input.session_id || null, input.goal || null, input.role || null, input.task_list_id || null, input.machine_id || null, metadataJson);
6264
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, input.audio_path || null, input.raw_text, input.processed_text || null, input.processing_mode || "raw", input.model_used || "gpt-4o-transcribe", input.enhancement_model || null, input.duration_ms || 0, input.language || null, tagsJson, input.agent_id || null, input.project_id || null, input.session_id || null, input.goal || null, input.role || null, input.task_list_id || null, input.machine_id || null, metadataJson);
6259
6265
  if (input.tags && input.tags.length > 0) {
6260
6266
  const insertTag = d.query("INSERT OR IGNORE INTO recording_tags (recording_id, tag) VALUES (?, ?)");
6261
6267
  for (const tag of input.tags) {
@@ -6762,7 +6768,7 @@ async function processText(rawText, config, systemPrompt) {
6762
6768
  }
6763
6769
 
6764
6770
  // src/version.ts
6765
- var VERSION = "0.1.32";
6771
+ var VERSION = "0.1.33";
6766
6772
 
6767
6773
  // src/cli/storage.ts
6768
6774
  import chalk from "chalk";
@@ -7415,7 +7421,7 @@ program.command("init").description("Initialize .recordings/ in current director
7415
7421
  mkdirSync3(audioDir, { recursive: true });
7416
7422
  if (!existsSync6(configFile)) {
7417
7423
  const defaultConf = {
7418
- transcription_model: "gpt-4o-mini-transcribe",
7424
+ transcription_model: "gpt-4o-transcribe",
7419
7425
  enhancement_model: "gpt-4o",
7420
7426
  language: "en",
7421
7427
  auto_enhance: true
package/dist/index.js CHANGED
@@ -4972,7 +4972,7 @@ import { homedir } from "os";
4972
4972
  var DEFAULT_CONFIG = {
4973
4973
  openai_api_key: "",
4974
4974
  enhancement_api_key: "",
4975
- transcription_model: "gpt-4o-mini-transcribe",
4975
+ transcription_model: "gpt-4o-transcribe",
4976
4976
  enhancement_model: "gpt-4o",
4977
4977
  language: "en",
4978
4978
  audio_format: "wav",
@@ -5177,7 +5177,7 @@ var MIGRATIONS = [
5177
5177
  raw_text TEXT NOT NULL,
5178
5178
  processed_text TEXT,
5179
5179
  processing_mode TEXT NOT NULL DEFAULT 'raw' CHECK(processing_mode IN ('raw', 'enhanced')),
5180
- model_used TEXT NOT NULL DEFAULT 'gpt-4o-mini-transcribe',
5180
+ model_used TEXT NOT NULL DEFAULT 'gpt-4o-transcribe',
5181
5181
  enhancement_model TEXT,
5182
5182
  duration_ms INTEGER DEFAULT 0,
5183
5183
  language TEXT,
@@ -5460,7 +5460,7 @@ var PG_MIGRATIONS = [
5460
5460
  raw_text TEXT NOT NULL,
5461
5461
  processed_text TEXT,
5462
5462
  processing_mode TEXT NOT NULL DEFAULT 'raw' CHECK(processing_mode IN ('raw', 'enhanced')),
5463
- model_used TEXT NOT NULL DEFAULT 'gpt-4o-mini-transcribe',
5463
+ model_used TEXT NOT NULL DEFAULT 'gpt-4o-transcribe',
5464
5464
  enhancement_model TEXT,
5465
5465
  duration_ms INTEGER DEFAULT 0,
5466
5466
  language TEXT,
@@ -5701,7 +5701,7 @@ function parseRow(row) {
5701
5701
  raw_text: row["raw_text"],
5702
5702
  processed_text: row["processed_text"] || null,
5703
5703
  processing_mode: row["processing_mode"] || "raw",
5704
- model_used: row["model_used"] || "gpt-4o-mini-transcribe",
5704
+ model_used: row["model_used"] || "gpt-4o-transcribe",
5705
5705
  enhancement_model: row["enhancement_model"] || null,
5706
5706
  duration_ms: row["duration_ms"] || 0,
5707
5707
  language: row["language"] || null,
@@ -5723,7 +5723,7 @@ function createRecording(input, db) {
5723
5723
  const tagsJson = JSON.stringify(input.tags || []);
5724
5724
  const metadataJson = JSON.stringify(input.metadata || {});
5725
5725
  d.query(`INSERT INTO recordings (id, audio_path, raw_text, processed_text, processing_mode, model_used, enhancement_model, duration_ms, language, tags, agent_id, project_id, session_id, goal, role, task_list_id, machine_id, metadata)
5726
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, input.audio_path || null, input.raw_text, input.processed_text || null, input.processing_mode || "raw", input.model_used || "gpt-4o-mini-transcribe", input.enhancement_model || null, input.duration_ms || 0, input.language || null, tagsJson, input.agent_id || null, input.project_id || null, input.session_id || null, input.goal || null, input.role || null, input.task_list_id || null, input.machine_id || null, metadataJson);
5726
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, input.audio_path || null, input.raw_text, input.processed_text || null, input.processing_mode || "raw", input.model_used || "gpt-4o-transcribe", input.enhancement_model || null, input.duration_ms || 0, input.language || null, tagsJson, input.agent_id || null, input.project_id || null, input.session_id || null, input.goal || null, input.role || null, input.task_list_id || null, input.machine_id || null, metadataJson);
5727
5727
  if (input.tags && input.tags.length > 0) {
5728
5728
  const insertTag = d.query("INSERT OR IGNORE INTO recording_tags (recording_id, tag) VALUES (?, ?)");
5729
5729
  for (const tag of input.tags) {
package/dist/mcp/index.js CHANGED
@@ -4920,7 +4920,7 @@ var require_lib2 = __commonJS((exports, module) => {
4920
4920
  var require_package = __commonJS((exports, module) => {
4921
4921
  module.exports = {
4922
4922
  name: "@hasna/recordings",
4923
- version: "0.1.32",
4923
+ version: "0.1.34",
4924
4924
  type: "module",
4925
4925
  description: "Speech-to-text recording tool with MCP and CLI \u2014 records, transcribes, and optionally enhances text using AI",
4926
4926
  repository: {
@@ -4970,7 +4970,7 @@ var require_package = __commonJS((exports, module) => {
4970
4970
  "LICENSE"
4971
4971
  ],
4972
4972
  dependencies: {
4973
- "@hasna/events": "^0.1.3",
4973
+ "@hasna/events": "^0.1.7",
4974
4974
  "@modelcontextprotocol/sdk": "^1.12.1",
4975
4975
  chalk: "^5.4.1",
4976
4976
  commander: "^13.1.0",
@@ -9021,7 +9021,7 @@ import { homedir } from "os";
9021
9021
  var DEFAULT_CONFIG = {
9022
9022
  openai_api_key: "",
9023
9023
  enhancement_api_key: "",
9024
- transcription_model: "gpt-4o-mini-transcribe",
9024
+ transcription_model: "gpt-4o-transcribe",
9025
9025
  enhancement_model: "gpt-4o",
9026
9026
  language: "en",
9027
9027
  audio_format: "wav",
@@ -9259,7 +9259,7 @@ var MIGRATIONS = [
9259
9259
  raw_text TEXT NOT NULL,
9260
9260
  processed_text TEXT,
9261
9261
  processing_mode TEXT NOT NULL DEFAULT 'raw' CHECK(processing_mode IN ('raw', 'enhanced')),
9262
- model_used TEXT NOT NULL DEFAULT 'gpt-4o-mini-transcribe',
9262
+ model_used TEXT NOT NULL DEFAULT 'gpt-4o-transcribe',
9263
9263
  enhancement_model TEXT,
9264
9264
  duration_ms INTEGER DEFAULT 0,
9265
9265
  language TEXT,
@@ -9389,7 +9389,7 @@ function parseRow(row) {
9389
9389
  raw_text: row["raw_text"],
9390
9390
  processed_text: row["processed_text"] || null,
9391
9391
  processing_mode: row["processing_mode"] || "raw",
9392
- model_used: row["model_used"] || "gpt-4o-mini-transcribe",
9392
+ model_used: row["model_used"] || "gpt-4o-transcribe",
9393
9393
  enhancement_model: row["enhancement_model"] || null,
9394
9394
  duration_ms: row["duration_ms"] || 0,
9395
9395
  language: row["language"] || null,
@@ -9411,7 +9411,7 @@ function createRecording(input, db) {
9411
9411
  const tagsJson = JSON.stringify(input.tags || []);
9412
9412
  const metadataJson = JSON.stringify(input.metadata || {});
9413
9413
  d.query(`INSERT INTO recordings (id, audio_path, raw_text, processed_text, processing_mode, model_used, enhancement_model, duration_ms, language, tags, agent_id, project_id, session_id, goal, role, task_list_id, machine_id, metadata)
9414
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, input.audio_path || null, input.raw_text, input.processed_text || null, input.processing_mode || "raw", input.model_used || "gpt-4o-mini-transcribe", input.enhancement_model || null, input.duration_ms || 0, input.language || null, tagsJson, input.agent_id || null, input.project_id || null, input.session_id || null, input.goal || null, input.role || null, input.task_list_id || null, input.machine_id || null, metadataJson);
9414
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, input.audio_path || null, input.raw_text, input.processed_text || null, input.processing_mode || "raw", input.model_used || "gpt-4o-transcribe", input.enhancement_model || null, input.duration_ms || 0, input.language || null, tagsJson, input.agent_id || null, input.project_id || null, input.session_id || null, input.goal || null, input.role || null, input.task_list_id || null, input.machine_id || null, metadataJson);
9415
9415
  if (input.tags && input.tags.length > 0) {
9416
9416
  const insertTag = d.query("INSERT OR IGNORE INTO recording_tags (recording_id, tag) VALUES (?, ?)");
9417
9417
  for (const tag of input.tags) {
@@ -9798,7 +9798,7 @@ async function processText(rawText, config, systemPrompt) {
9798
9798
  }
9799
9799
 
9800
9800
  // src/version.ts
9801
- var VERSION = "0.1.32";
9801
+ var VERSION = "0.1.33";
9802
9802
 
9803
9803
  // src/db/storage-config.ts
9804
9804
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
@@ -9957,7 +9957,7 @@ var PG_MIGRATIONS = [
9957
9957
  raw_text TEXT NOT NULL,
9958
9958
  processed_text TEXT,
9959
9959
  processing_mode TEXT NOT NULL DEFAULT 'raw' CHECK(processing_mode IN ('raw', 'enhanced')),
9960
- model_used TEXT NOT NULL DEFAULT 'gpt-4o-mini-transcribe',
9960
+ model_used TEXT NOT NULL DEFAULT 'gpt-4o-transcribe',
9961
9961
  enhancement_model TEXT,
9962
9962
  duration_ms INTEGER DEFAULT 0,
9963
9963
  language TEXT,
package/dist/storage.js CHANGED
@@ -5024,7 +5024,7 @@ import { homedir as homedir2 } from "os";
5024
5024
  var DEFAULT_CONFIG = {
5025
5025
  openai_api_key: "",
5026
5026
  enhancement_api_key: "",
5027
- transcription_model: "gpt-4o-mini-transcribe",
5027
+ transcription_model: "gpt-4o-transcribe",
5028
5028
  enhancement_model: "gpt-4o",
5029
5029
  language: "en",
5030
5030
  audio_format: "wav",
@@ -5229,7 +5229,7 @@ var MIGRATIONS = [
5229
5229
  raw_text TEXT NOT NULL,
5230
5230
  processed_text TEXT,
5231
5231
  processing_mode TEXT NOT NULL DEFAULT 'raw' CHECK(processing_mode IN ('raw', 'enhanced')),
5232
- model_used TEXT NOT NULL DEFAULT 'gpt-4o-mini-transcribe',
5232
+ model_used TEXT NOT NULL DEFAULT 'gpt-4o-transcribe',
5233
5233
  enhancement_model TEXT,
5234
5234
  duration_ms INTEGER DEFAULT 0,
5235
5235
  language TEXT,
@@ -5434,7 +5434,7 @@ var PG_MIGRATIONS = [
5434
5434
  raw_text TEXT NOT NULL,
5435
5435
  processed_text TEXT,
5436
5436
  processing_mode TEXT NOT NULL DEFAULT 'raw' CHECK(processing_mode IN ('raw', 'enhanced')),
5437
- model_used TEXT NOT NULL DEFAULT 'gpt-4o-mini-transcribe',
5437
+ model_used TEXT NOT NULL DEFAULT 'gpt-4o-transcribe',
5438
5438
  enhancement_model TEXT,
5439
5439
  duration_ms INTEGER DEFAULT 0,
5440
5440
  language TEXT,
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.1.32";
1
+ export declare const VERSION = "0.1.33";
2
2
  //# sourceMappingURL=version.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/recordings",
3
- "version": "0.1.32",
3
+ "version": "0.1.34",
4
4
  "type": "module",
5
5
  "description": "Speech-to-text recording tool with MCP and CLI — records, transcribes, and optionally enhances text using AI",
6
6
  "repository": {
@@ -50,7 +50,7 @@
50
50
  "LICENSE"
51
51
  ],
52
52
  "dependencies": {
53
- "@hasna/events": "^0.1.3",
53
+ "@hasna/events": "^0.1.7",
54
54
  "@modelcontextprotocol/sdk": "^1.12.1",
55
55
  "chalk": "^5.4.1",
56
56
  "commander": "^13.1.0",
@@ -520,7 +520,6 @@ public final class RecordingEngine: ObservableObject {
520
520
 
521
521
  public func stopAndTranscribe() {
522
522
  guard isRecording else { return }
523
- let stopStartedAt = Date()
524
523
  log("stopAndTranscribe")
525
524
 
526
525
  recordingTimer?.invalidate()
@@ -541,7 +540,6 @@ public final class RecordingEngine: ObservableObject {
541
540
  let audioPath = activeAudioPath
542
541
  let pcmStreamPipe = pcmStreamPipe
543
542
  let client = realtimeClient
544
- let transcriptionLanguage = transcriptionLanguage
545
543
  resetRecordingIntent()
546
544
  self.pcmStreamPipe = nil
547
545
 
@@ -558,37 +556,11 @@ public final class RecordingEngine: ObservableObject {
558
556
  self.streamingTask = nil
559
557
 
560
558
  let realtimeText = Self.normalizedRealtimeTranscript(streamingResult)
561
- let fastPathText = Self.realtimeFastPathTranscript(
562
- realtimeText: streamingResult,
563
- pcmByteCount: self.recordedPCM.count,
564
- language: transcriptionLanguage
565
- )
566
559
 
567
560
  self.liveTranscriptionText = ""
568
561
 
569
- if let fastPathText {
570
- let releaseToTextMS = Int(Date().timeIntervalSince(stopStartedAt) * 1_000)
571
- let repaired = Self.wasRealtimeTranscriptRepaired(rawText: streamingResult, cleanedText: fastPathText)
572
- self.log("using realtime fast path chars=\(fastPathText.count) repaired=\(repaired) releaseToTextMs=\(releaseToTextMS)")
573
- self.isTranscribing = false
574
- self.finishWithText(
575
- fastPathText,
576
- curMode: curMode,
577
- targetAppBundleIdentifier: targetAppBundleIdentifier,
578
- targetAppPid: targetAppPid,
579
- activeProjectId: activeProjectId,
580
- activeProjectName: activeProjectName
581
- )
582
- if let audioPath, !self.recordedPCM.isEmpty {
583
- Self.saveCapturedWAVInBackground(pcmData: self.recordedPCM, audioPath: audioPath, homePath: self.home)
584
- }
585
- self.activeAudioPath = nil
586
- self.recordedPCM.removeAll(keepingCapacity: true)
587
- return
588
- }
589
-
590
562
  if let audioPath, self.writeCapturedWAV(to: audioPath) {
591
- self.log("transcribing captured full audio audioPath=\(audioPath) realtimePreviewChars=\(realtimeText?.count ?? 0)")
563
+ self.log("transcribing captured full audio with quality model audioPath=\(audioPath) realtimePreviewChars=\(realtimeText?.count ?? 0)")
592
564
  self.fallbackTranscribe(
593
565
  audioPath: audioPath,
594
566
  curMode: curMode,
@@ -119,7 +119,7 @@ struct OpenAIAPIKeyStoreTests {
119
119
  let home = try makeHome()
120
120
  try writeConfig(home: home, [
121
121
  "openai_api_key": "old-key",
122
- "transcription_model": "gpt-4o-mini-transcribe",
122
+ "transcription_model": "gpt-4o-transcribe",
123
123
  ])
124
124
 
125
125
  try OpenAIAPIKeyStore.save(key: "sk-rotated", homePath: home.path)
@@ -131,7 +131,7 @@ struct OpenAIAPIKeyStoreTests {
131
131
  let data = try Data(contentsOf: configURL)
132
132
  let json = try #require(JSONSerialization.jsonObject(with: data) as? [String: Any])
133
133
  #expect(json["openai_api_key"] as? String == "sk-rotated")
134
- #expect(json["transcription_model"] as? String == "gpt-4o-mini-transcribe")
134
+ #expect(json["transcription_model"] as? String == "gpt-4o-transcribe")
135
135
  }
136
136
 
137
137
  @Test("Saving an empty key removes it from config.json")