negotium 0.4.9 → 0.5.1

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/main.js CHANGED
@@ -270,10 +270,13 @@ function resolveModelEnv(envKey, agentConst) {
270
270
  function resolveDefaultModel(agent, registryDefaultModel) {
271
271
  return agent === SESSION_AGENT && SESSION_MODEL ? SESSION_MODEL : registryDefaultModel;
272
272
  }
273
+ function resolveWhisperBackend() {
274
+ return envText("WHISPER_BACKEND") === "mlx-whisper" ? "mlx-whisper" : "faster-whisper";
275
+ }
273
276
  function codexAuthFilePath() {
274
277
  return process.env.NEGOTIUM_CODEX_AUTH_FILE || join(process.env.CODEX_HOME || join(homedir(), ".codex"), "auth.json");
275
278
  }
276
- var HOME, PROJECT_ROOT, STATE_DIR_ENV, STATE_DIR, WORKSPACE_DIR, TOPIC_WORKSPACE_DIR, SHARED_WIKI_DIR, CRON_WORKSPACE_DIR, BROWSER_DIR, BROWSER_PROFILES_DIR, BINARIES_DIR, SECRETS_DIR, DM_WORKSPACE_DIR, SESSION_WORKSPACE_DIR, CLAUDE_EXECUTABLE_ENV, CLAUDE_EXECUTABLE, DEFAULT_OUTPUT_LANGUAGE = "English", BROWSER_RS_VERSION = "v0.1.22", BROWSER_RS_MIN_SECURE_VERSION = "0.1.15", BROWSER_RS_VERSION_PROBE_TIMEOUT_MS = 15000, SNIPPETS_API_URL, BROWSER_RS_BIN, BASH_RS_VERSION = "v0.1.7", BASH_RS_BIN, PLAYWRIGHT_MCP_BIN, TSX_BIN, TSX_LOADER, TSCONFIG_PATH, SESSION_COMM_SERVER, TASK_SERVER, DECISION_SERVER, CANONICAL_MCP_PROXY_SERVER, WIKI_SERVER, TOKEN_STATS_SERVER, COMPACTION_LOG_SERVER, SYSTEM_HEALTH_SERVER, AGENT_HEALTH_SERVER, VAULT_SERVER, BG_BASH_BASE_PORT, BG_BASH_MAX_PORT, RUNTIME_MCP_SECRET, NODE_CONTROL_TOKEN, NODE_ID, VAULT_MASTER_KEY, NEGOTIUM_PORT, hostname, DATA_DIR, LOG_DIR, UPLOADS_DIR, VAULT_DIR, SESSIONS_DB, DEBUG_FILE, USERS_LOG_DIR, RUN_DIR, PROGRESS_DIR, DM_CMD_DIR, DM_RESP_DIR, SESSION_INBOX_DIR, SESSION_ASKS_DIR, BASHRS_SPILL_ROOT, PLAYWRIGHT_BASE_PORT, PLAYWRIGHT_MAX_PORT, PLAYWRIGHT_PORTS_DIR, ACTIVE_QUERY_STALE_MS, AGENTS_PROMPTS_DIR, RESOURCES_DIR, FILE_TAG_REGEX, MODEL_SONNET = "claude-sonnet-5", MODEL_OPUS = "claude-opus-5", MODEL_FABLE = "claude-fable-5", FALLBACK_AGENT, SESSION_AGENT, GATEWAY_AGENT, FALLBACK_MODEL, SESSION_MODEL, GATEWAY_MODEL, FFMPEG_BIN, FFPROBE_BIN, PYTHON_BIN, FASTER_WHISPER_WRAPPER, WHISPER_MODEL, TESSERACT_BIN, PDFTOTEXT_BIN, _envMaxTellDepth, MAX_TELL_DEPTH;
279
+ var HOME, PROJECT_ROOT, STATE_DIR_ENV, STATE_DIR, WORKSPACE_DIR, TOPIC_WORKSPACE_DIR, SHARED_WIKI_DIR, CRON_WORKSPACE_DIR, BROWSER_DIR, BROWSER_PROFILES_DIR, BINARIES_DIR, SECRETS_DIR, DM_WORKSPACE_DIR, SESSION_WORKSPACE_DIR, CLAUDE_EXECUTABLE_ENV, CLAUDE_EXECUTABLE, DEFAULT_OUTPUT_LANGUAGE = "English", BROWSER_RS_VERSION = "v0.1.23", BROWSER_RS_MIN_SECURE_VERSION = "0.1.15", BROWSER_RS_VERSION_PROBE_TIMEOUT_MS = 15000, SNIPPETS_API_URL, BROWSER_RS_BIN, BASH_RS_VERSION = "v0.1.7", BASH_RS_BIN, PLAYWRIGHT_MCP_BIN, TSX_BIN, TSX_LOADER, TSCONFIG_PATH, SESSION_COMM_SERVER, TASK_SERVER, DECISION_SERVER, CANONICAL_MCP_PROXY_SERVER, WIKI_SERVER, TOKEN_STATS_SERVER, COMPACTION_LOG_SERVER, SYSTEM_HEALTH_SERVER, AGENT_HEALTH_SERVER, VAULT_SERVER, BG_BASH_BASE_PORT, BG_BASH_MAX_PORT, RUNTIME_MCP_SECRET, NODE_CONTROL_TOKEN, NODE_ID, VAULT_MASTER_KEY, NEGOTIUM_PORT, hostname, DATA_DIR, LOG_DIR, UPLOADS_DIR, VAULT_DIR, SESSIONS_DB, DEBUG_FILE, USERS_LOG_DIR, RUN_DIR, PROGRESS_DIR, DM_CMD_DIR, DM_RESP_DIR, SESSION_INBOX_DIR, SESSION_ASKS_DIR, BASHRS_SPILL_ROOT, PLAYWRIGHT_BASE_PORT, PLAYWRIGHT_MAX_PORT, PLAYWRIGHT_PORTS_DIR, ACTIVE_QUERY_STALE_MS, AGENTS_PROMPTS_DIR, RESOURCES_DIR, FILE_TAG_REGEX, MODEL_SONNET = "claude-sonnet-5", MODEL_OPUS = "claude-opus-5", MODEL_FABLE = "claude-fable-5", FALLBACK_AGENT, SESSION_AGENT, GATEWAY_AGENT, FALLBACK_MODEL, SESSION_MODEL, GATEWAY_MODEL, FFMPEG_BIN, FFPROBE_BIN, PYTHON_BIN, FASTER_WHISPER_WRAPPER, WHISPER_MODEL, TESSERACT_BIN, PDFTOTEXT_BIN, WHISPER_BACKEND, MLX_WHISPER_BIN, WHISPER_MODEL_MLX, _envMaxTellDepth, MAX_TELL_DEPTH;
277
280
  var init_config = __esm(() => {
278
281
  init_config_helpers();
279
282
  init_logger();
@@ -375,6 +378,9 @@ var init_config = __esm(() => {
375
378
  WHISPER_MODEL = envText("WHISPER_MODEL_FILE") ?? "turbo";
376
379
  TESSERACT_BIN = envText("TESSERACT_BIN") ?? "tesseract";
377
380
  PDFTOTEXT_BIN = envText("PDFTOTEXT_BIN") ?? "pdftotext";
381
+ WHISPER_BACKEND = resolveWhisperBackend();
382
+ MLX_WHISPER_BIN = envText("MLX_WHISPER_BIN");
383
+ WHISPER_MODEL_MLX = envText("WHISPER_MODEL_MLX") ?? WHISPER_MODEL;
378
384
  _envMaxTellDepth = Number.parseInt(process.env.MAX_TELL_DEPTH ?? "", 10);
379
385
  MAX_TELL_DEPTH = Number.isInteger(_envMaxTellDepth) && _envMaxTellDepth > 0 ? _envMaxTellDepth : 20;
380
386
  });
@@ -1868,7 +1874,7 @@ var exports_version = {};
1868
1874
  __export(exports_version, {
1869
1875
  NEGOTIUM_VERSION: () => NEGOTIUM_VERSION
1870
1876
  });
1871
- var NEGOTIUM_VERSION = "0.4.9";
1877
+ var NEGOTIUM_VERSION = "0.5.1";
1872
1878
 
1873
1879
  // ../../packages/core/src/agents/codex-native-multi-agent.ts
1874
1880
  import { spawn } from "child_process";
@@ -21383,8 +21389,14 @@ async function extractFromImage(filePath) {
21383
21389
  }
21384
21390
  function isTranscriptionConfigured(opts = {}) {
21385
21391
  const ffmpeg = opts.ffmpegBin ?? FFMPEG_BIN;
21392
+ if (!ffmpeg)
21393
+ return false;
21394
+ const backend = opts.backend ?? WHISPER_BACKEND;
21395
+ if (backend === "mlx-whisper") {
21396
+ return Boolean(opts.mlxWhisperBin ?? MLX_WHISPER_BIN);
21397
+ }
21386
21398
  const wrapper = opts.wrapperPath ?? FASTER_WHISPER_WRAPPER;
21387
- return Boolean(ffmpeg) && existsSync21(wrapper);
21399
+ return existsSync21(wrapper);
21388
21400
  }
21389
21401
  async function transcribeAudio(filePath, opts = {}) {
21390
21402
  if (!isTranscriptionConfigured(opts))
@@ -21394,6 +21406,7 @@ async function transcribeAudio(filePath, opts = {}) {
21394
21406
  }
21395
21407
  async function extractFromAudio(filePath, opts = {}) {
21396
21408
  const tmpDir = `${filePath}_whisper_tmp`;
21409
+ const backend = opts.backend ?? WHISPER_BACKEND;
21397
21410
  try {
21398
21411
  mkdirSync21(tmpDir, { recursive: true });
21399
21412
  const mp3Path = join31(tmpDir, "audio.mp3");
@@ -21411,18 +21424,26 @@ async function extractFromAudio(filePath, opts = {}) {
21411
21424
  "16000",
21412
21425
  mp3Path
21413
21426
  ], { timeout: 60000 });
21414
- await execFileAsync(opts.pythonBin ?? PYTHON_BIN, [
21415
- opts.wrapperPath ?? FASTER_WHISPER_WRAPPER,
21427
+ const whisperArgs = [
21416
21428
  mp3Path,
21417
21429
  "--model",
21418
- opts.model ?? WHISPER_MODEL,
21430
+ opts.model ?? (backend === "mlx-whisper" ? WHISPER_MODEL_MLX : WHISPER_MODEL),
21419
21431
  "--language",
21420
21432
  opts.language ?? "ko",
21421
21433
  "--output-dir",
21422
21434
  tmpDir,
21423
21435
  "--output-format",
21424
21436
  "txt"
21425
- ], { timeout: 120000 });
21437
+ ];
21438
+ if (backend === "mlx-whisper") {
21439
+ const mlxWhisperBin = opts.mlxWhisperBin ?? MLX_WHISPER_BIN;
21440
+ if (!mlxWhisperBin) {
21441
+ return { text: null, method: "whisper", error: "MLX_WHISPER_BIN not configured" };
21442
+ }
21443
+ await execFileAsync(mlxWhisperBin, whisperArgs, { timeout: 300000 });
21444
+ } else {
21445
+ await execFileAsync(opts.pythonBin ?? PYTHON_BIN, [opts.wrapperPath ?? FASTER_WHISPER_WRAPPER, ...whisperArgs], { timeout: 120000 });
21446
+ }
21426
21447
  const txtPath = join31(tmpDir, "audio.txt");
21427
21448
  const text2 = existsSync21(txtPath) ? readFileSync17(txtPath, "utf-8").trim() : null;
21428
21449
  if (!text2) {
@@ -21430,7 +21451,7 @@ async function extractFromAudio(filePath, opts = {}) {
21430
21451
  }
21431
21452
  return { text: text2, method: "whisper" };
21432
21453
  } catch (e) {
21433
- logger.debug({ err: e, filePath }, "whisper extraction failed");
21454
+ logger.debug({ err: e, filePath, backend }, "whisper extraction failed");
21434
21455
  return {
21435
21456
  text: null,
21436
21457
  method: "whisper",
@@ -33212,13 +33233,60 @@ function compactDetail(decision) {
33212
33233
  const rationale = decision.reasoning.replace(/\s+/g, " ").trim();
33213
33234
  return `${rationale} \xB7 ${decision.agent}${decision.model ? `/${decision.model}` : ""}`;
33214
33235
  }
33236
+ function chronologicalSequenceEdges(ordered) {
33237
+ const parent = new Map;
33238
+ for (const decision of ordered)
33239
+ parent.set(decision.id, decision.id);
33240
+ const find = (id) => {
33241
+ let root = id;
33242
+ while (parent.get(root) !== root) {
33243
+ const next = parent.get(root);
33244
+ if (next === undefined)
33245
+ break;
33246
+ root = next;
33247
+ }
33248
+ return root;
33249
+ };
33250
+ const union = (a, b) => {
33251
+ const rootA = find(a);
33252
+ const rootB = find(b);
33253
+ if (rootA !== rootB)
33254
+ parent.set(rootA, rootB);
33255
+ };
33256
+ for (const decision of ordered) {
33257
+ for (const upstream of decision.causedBy ?? []) {
33258
+ if (parent.has(upstream))
33259
+ union(upstream, decision.id);
33260
+ }
33261
+ }
33262
+ const edges = [];
33263
+ for (let index = 1;index < ordered.length; index += 1) {
33264
+ const previous = ordered[index - 1];
33265
+ const current3 = ordered[index];
33266
+ if (!previous || !current3)
33267
+ continue;
33268
+ if (find(previous.id) === find(current3.id))
33269
+ continue;
33270
+ union(previous.id, current3.id);
33271
+ edges.push({
33272
+ id: `sequence:${previous.id}:${current3.id}`,
33273
+ source: previous.id,
33274
+ target: current3.id,
33275
+ kind: "sequence",
33276
+ direction: "none",
33277
+ style: "dashed"
33278
+ });
33279
+ }
33280
+ return edges;
33281
+ }
33215
33282
  function buildDecisionGraph(decisions2, topicTitle) {
33216
33283
  const ids = new Set(decisions2.map((decision) => decision.id));
33284
+ const ordered = [...decisions2].sort((a, b) => (a.timestamp ?? 0) - (b.timestamp ?? 0) || a.id.localeCompare(b.id));
33217
33285
  return {
33218
33286
  id: "decisions",
33219
33287
  title: topicTitle,
33220
33288
  direction: "DOWN",
33221
- nodes: decisions2.map((decision) => ({
33289
+ nodes: ordered.map((decision) => ({
33222
33290
  id: decision.id,
33223
33291
  label: `#${decision.id} ${decision.action}`,
33224
33292
  detail: compactDetail(decision),
@@ -33226,15 +33294,17 @@ function buildDecisionGraph(decisions2, topicTitle) {
33226
33294
  state: decisionNodeState(decision.status),
33227
33295
  metadata: { timestamp: decision.timestamp, agent: decision.agent, model: decision.model }
33228
33296
  })),
33229
- edges: decisions2.flatMap((decision) => (decision.causedBy ?? []).filter((upstream) => ids.has(upstream)).map((upstream) => ({
33230
- id: `caused:${upstream}:${decision.id}`,
33231
- source: upstream,
33232
- target: decision.id,
33233
- label: "caused",
33234
- kind: "caused",
33235
- direction: "forward",
33236
- style: "solid"
33237
- })))
33297
+ edges: [
33298
+ ...ordered.flatMap((decision) => (decision.causedBy ?? []).filter((upstream) => ids.has(upstream)).map((upstream) => ({
33299
+ id: `caused:${upstream}:${decision.id}`,
33300
+ source: upstream,
33301
+ target: decision.id,
33302
+ kind: "caused",
33303
+ direction: "forward",
33304
+ style: "solid"
33305
+ }))),
33306
+ ...chronologicalSequenceEdges(ordered)
33307
+ ]
33238
33308
  };
33239
33309
  }
33240
33310
  async function renderDecisionGraph(graph, spacing = DEFAULT_DECISION_GRAPH_SPACING, signal) {
@@ -33242,14 +33312,15 @@ async function renderDecisionGraph(graph, spacing = DEFAULT_DECISION_GRAPH_SPACI
33242
33312
  direction: "DOWN",
33243
33313
  spacing,
33244
33314
  signal,
33245
- timeoutMs: 15000
33315
+ timeoutMs: 15000,
33316
+ maxNodeWidth: DECISION_NODE_MAX_WIDTH
33246
33317
  });
33247
33318
  return {
33248
33319
  canvas: { ...renderTerminalGraph(graph, geometry), title: graph.title },
33249
33320
  svg: renderSvgGraph(graph, geometry, { title: graph.title })
33250
33321
  };
33251
33322
  }
33252
- var DEFAULT_DECISION_GRAPH_SPACING = 4, MIN_DECISION_GRAPH_SPACING = 2, MAX_DECISION_GRAPH_SPACING = 10;
33323
+ var DEFAULT_DECISION_GRAPH_SPACING = 4, MIN_DECISION_GRAPH_SPACING = 2, MAX_DECISION_GRAPH_SPACING = 10, DECISION_NODE_MAX_WIDTH = 30;
33253
33324
  var init_decision_graph = () => {};
33254
33325
 
33255
33326
  // ../../adapters/terminal/src/subagent-graph.ts
@@ -35556,7 +35627,7 @@ function decisionGraphLines(state, width, height) {
35556
35627
  bold: true
35557
35628
  }),
35558
35629
  line(` [/] spacing ${state.decisionGraphSpacing} \xB7 drag/wheel/arrows/hjkl move \xB7 Ctrl-D/Esc close${position}`, { fg: theme.muted }),
35559
- line(" \u25CB accepted \xB7 \u25F7 proposed \xB7 \u2713 executed \xB7 \u2717 rejected \xB7 ! superseded", {
35630
+ line(" \u25CB accepted \xB7 \u25CC proposed \xB7 \u2713 executed \xB7 \u2715 rejected \xB7 \u25C6 superseded", {
35560
35631
  fg: theme.subtle
35561
35632
  }),
35562
35633
  line("")
@@ -47589,4 +47660,4 @@ switch (command) {
47589
47660
  }
47590
47661
  }
47591
47662
 
47592
- //# debugId=A95E28BED5799E3A64756E2164756E21
47663
+ //# debugId=3B6A9C0748761A2464756E2164756E21