@gobing-ai/knowledge-kit 0.1.4 → 0.1.5

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.
Files changed (68) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/dist/board/collect/index.css +447 -0
  3. package/dist/board/collect/index.js +2505 -453
  4. package/dist/board/daily-voice/index.css +447 -0
  5. package/dist/board/daily-voice/index.js +415 -8
  6. package/dist/board/itc/index.css +447 -0
  7. package/dist/board/itc/index.js +415 -8
  8. package/dist/index.js +475 -136
  9. package/package.json +6 -5
  10. package/plugins/generations/content-gen/dist/index.js +9 -9
  11. package/plugins/generations/core-facts-gen/dist/index.js +12 -12
  12. package/plugins/generations/daily-article-gen/dist/index.js +12 -12
  13. package/plugins/generations/dailynews-gen/dist/index.js +9 -9
  14. package/plugins/generations/episode-plan-gen/dist/index.js +12 -12
  15. package/plugins/generations/gemini-tts/dist/index.js +9 -9
  16. package/plugins/generations/image-gen/dist/index.js +28 -12
  17. package/plugins/generations/image-gen/src/compose/card.ts +19 -3
  18. package/plugins/generations/news-report-gen/dist/index.js +12 -12
  19. package/plugins/generations/voice-gen/dist/index.js +9 -9
  20. package/plugins/generations/voxcpm-tts/dist/index.js +9 -9
  21. package/plugins/ingestions/aihot-ingest/dist/index.js +12 -12
  22. package/plugins/ingestions/horizon-ingest/dist/index.js +12 -12
  23. package/plugins/ingestions/karakeep-local/dist/index.js +13 -13
  24. package/plugins/ingestions/last30days-ingest/dist/index.js +12 -12
  25. package/plugins/ingestions/web-search/dist/index.js +10 -10
  26. package/plugins/kk/decisions/kk-podcast.yaml +44 -0
  27. package/plugins/kk/decisions/kk-safety.yaml +46 -0
  28. package/plugins/kk/plugin.json +1 -1
  29. package/plugins/kk/scripts/daily-stages.ts +117 -0
  30. package/plugins/kk/scripts/kk-workflow-stages.ts +10 -0
  31. package/plugins/kk/workflows/kk-daily-ai-voice2.yaml +6 -3
  32. package/plugins/kk/workflows/kk-daily-safety.yaml +37 -10
  33. package/plugins/kk/workflows/kk-solo-podcast.yaml +65 -1
  34. package/plugins/publishings/bilibili-pub/dist/index.js +22 -22
  35. package/plugins/publishings/bilibili-pub/dist/profile-check.js +22 -22
  36. package/plugins/publishings/cnblogs-pub/dist/index.js +22 -22
  37. package/plugins/publishings/cnblogs-pub/dist/profile-check.js +22 -22
  38. package/plugins/publishings/csdn-pub/dist/index.js +22 -22
  39. package/plugins/publishings/csdn-pub/dist/profile-check.js +22 -22
  40. package/plugins/publishings/emdash-pub/dist/index.js +9 -9
  41. package/plugins/publishings/infoq-pub/dist/index.js +22 -22
  42. package/plugins/publishings/infoq-pub/dist/profile-check.js +22 -22
  43. package/plugins/publishings/jike-pub/dist/index.js +22 -22
  44. package/plugins/publishings/jike-pub/dist/profile-check.js +22 -22
  45. package/plugins/publishings/juejin-pub/dist/index.js +22 -22
  46. package/plugins/publishings/juejin-pub/dist/profile-check.js +22 -22
  47. package/plugins/publishings/medium-pub/dist/index.js +9 -9
  48. package/plugins/publishings/podcast-pub/dist/index.js +9 -9
  49. package/plugins/publishings/qiita-pub/dist/index.js +9 -9
  50. package/plugins/publishings/shipinhao-pub/dist/index.js +22 -22
  51. package/plugins/publishings/shipinhao-pub/dist/profile-check.js +22 -22
  52. package/plugins/publishings/sspai-pub/dist/index.js +22 -22
  53. package/plugins/publishings/sspai-pub/dist/profile-check.js +22 -22
  54. package/plugins/publishings/substack-pub/dist/index.js +22 -22
  55. package/plugins/publishings/substack-pub/dist/profile-check.js +22 -22
  56. package/plugins/publishings/surfdash-pub/dist/index.js +9 -9
  57. package/plugins/publishings/threads-pub/dist/index.js +9 -9
  58. package/plugins/publishings/wechatmp-pub/dist/index.js +22 -22
  59. package/plugins/publishings/wechatmp-pub/dist/profile-check.js +22 -22
  60. package/plugins/publishings/weibo-pub/dist/index.js +22 -22
  61. package/plugins/publishings/weibo-pub/dist/profile-check.js +22 -22
  62. package/plugins/publishings/x-pub/dist/index.js +22 -22
  63. package/plugins/publishings/x-pub/dist/profile-check.js +22 -22
  64. package/plugins/publishings/xhs-pub/dist/index.js +22 -22
  65. package/plugins/publishings/xhs-pub/dist/profile-check.js +22 -22
  66. package/plugins/publishings/xiaoyuzhou-pub/dist/index.js +22 -22
  67. package/plugins/publishings/xiaoyuzhou-pub/dist/profile-check.js +22 -22
  68. package/plugins/publishings/zenn-pub/dist/index.js +9 -9
package/dist/index.js CHANGED
@@ -2127,7 +2127,7 @@ var init_commander = __esm(() => {
2127
2127
  program = new Command;
2128
2128
  });
2129
2129
 
2130
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.30/node_modules/@gobing-ai/ts-utils/dist/errors.js
2130
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/errors.js
2131
2131
  var ErrorCode;
2132
2132
  var init_errors = __esm(() => {
2133
2133
  ErrorCode = {
@@ -2138,7 +2138,7 @@ var init_errors = __esm(() => {
2138
2138
  };
2139
2139
  });
2140
2140
 
2141
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.30/node_modules/@gobing-ai/ts-utils/dist/api-response.js
2141
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/api-response.js
2142
2142
  var API_ERROR_CODES, ERROR_CODE_TO_HTTP, CLIENT_SAFE_CODES;
2143
2143
  var init_api_response = __esm(() => {
2144
2144
  init_errors();
@@ -2161,10 +2161,10 @@ var init_api_response = __esm(() => {
2161
2161
  CLIENT_SAFE_CODES = new Set([ErrorCode.NotFound, ErrorCode.Validation, ErrorCode.Conflict]);
2162
2162
  });
2163
2163
 
2164
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.30/node_modules/@gobing-ai/ts-utils/dist/cursor.js
2164
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/cursor.js
2165
2165
  var init_cursor = () => {};
2166
2166
 
2167
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.30/node_modules/@gobing-ai/ts-utils/dist/env.js
2167
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/env.js
2168
2168
  function getEnvVar(name, fallback) {
2169
2169
  const raw = process.env[name];
2170
2170
  return raw === undefined ? fallback : raw;
@@ -2173,10 +2173,10 @@ function getEnvVars() {
2173
2173
  return process.env;
2174
2174
  }
2175
2175
 
2176
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.30/node_modules/@gobing-ai/ts-utils/dist/event-severity.js
2176
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/event-severity.js
2177
2177
  var init_event_severity = () => {};
2178
2178
 
2179
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.30/node_modules/@gobing-ai/ts-utils/dist/object.js
2179
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/object.js
2180
2180
  function isPlainObject(value) {
2181
2181
  return typeof value === "object" && value !== null && !Array.isArray(value);
2182
2182
  }
@@ -2194,7 +2194,7 @@ function deepMerge(target, source) {
2194
2194
  return result;
2195
2195
  }
2196
2196
 
2197
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.30/node_modules/@gobing-ai/ts-utils/dist/output.js
2197
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/output.js
2198
2198
  function processStream(name) {
2199
2199
  const proc = globalThis.process;
2200
2200
  const stream = proc?.[name];
@@ -2215,7 +2215,7 @@ function echoError(message, target = defaultStderrTarget ?? processStream("stder
2215
2215
  }
2216
2216
  var defaultStdoutTarget, defaultStderrTarget;
2217
2217
 
2218
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.30/node_modules/@gobing-ai/ts-utils/dist/index.js
2218
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.32/node_modules/@gobing-ai/ts-utils/dist/index.js
2219
2219
  var init_dist = __esm(() => {
2220
2220
  init_api_response();
2221
2221
  init_cursor();
@@ -23838,7 +23838,7 @@ var init_zod = __esm(() => {
23838
23838
  init_external();
23839
23839
  });
23840
23840
 
23841
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.30+fa3ca66e1fba4d51/node_modules/@gobing-ai/ts-runtime/dist/config.js
23841
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/config.js
23842
23842
  function getProcessEnv() {
23843
23843
  return getEnvVars();
23844
23844
  }
@@ -23916,7 +23916,7 @@ var init_config = __esm(() => {
23916
23916
  };
23917
23917
  });
23918
23918
 
23919
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.30+fa3ca66e1fba4d51/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
23919
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
23920
23920
  import { appendFileSync, cpSync, createReadStream, createWriteStream, existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "fs";
23921
23921
  import { dirname, resolve as resolvePath } from "path";
23922
23922
  function createNodeFileSystem(root, paths) {
@@ -24003,7 +24003,7 @@ function findProjectRoot(startDir) {
24003
24003
  }
24004
24004
  var init_file_system_node = () => {};
24005
24005
 
24006
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.30+fa3ca66e1fba4d51/node_modules/@gobing-ai/ts-runtime/dist/db-errors.js
24006
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/db-errors.js
24007
24007
  var DbModuleNotInstalledError;
24008
24008
  var init_db_errors = __esm(() => {
24009
24009
  DbModuleNotInstalledError = class DbModuleNotInstalledError extends Error {
@@ -31214,7 +31214,7 @@ var init_execa = __esm(() => {
31214
31214
  } = getIpcExport());
31215
31215
  });
31216
31216
 
31217
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.30+fa3ca66e1fba4d51/node_modules/@gobing-ai/ts-runtime/dist/process-group.js
31217
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/process-group.js
31218
31218
  function resolveDeadline(optionTimeout, defaultTimeout) {
31219
31219
  if (optionTimeout === null)
31220
31220
  return null;
@@ -31306,7 +31306,7 @@ function ownProcessGroupLifecycle(ownership) {
31306
31306
  }
31307
31307
  var MAX_TIMEOUT_MS = 2147483647, DEFAULT_KILL_GRACE_MS = 5000, GROUP_POLL_INTERVAL_MS = 25, GROUP_KILL_PATIENCE_MS = 2000;
31308
31308
 
31309
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.30+fa3ca66e1fba4d51/node_modules/@gobing-ai/ts-runtime/dist/process-executor.js
31309
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/process-executor.js
31310
31310
  import { spawnSync as spawnSync2 } from "child_process";
31311
31311
  import { isatty } from "tty";
31312
31312
  function processEventSeverity(reason, exitCode) {
@@ -31708,7 +31708,7 @@ var init_process_executor = __esm(() => {
31708
31708
  init_config();
31709
31709
  });
31710
31710
 
31711
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.30+fa3ca66e1fba4d51/node_modules/@gobing-ai/ts-runtime/dist/runtime-node-bun.js
31711
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/runtime-node-bun.js
31712
31712
  function getNodeFileSystem() {
31713
31713
  if (!_nodeFileSystem)
31714
31714
  _nodeFileSystem = createNodeFileSystem();
@@ -31768,10 +31768,10 @@ var init_runtime_node_bun = __esm(() => {
31768
31768
  };
31769
31769
  });
31770
31770
 
31771
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.30+fa3ca66e1fba4d51/node_modules/@gobing-ai/ts-runtime/dist/context.js
31771
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/context.js
31772
31772
  var init_context = () => {};
31773
31773
 
31774
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.30+fa3ca66e1fba4d51/node_modules/@gobing-ai/ts-runtime/dist/path.js
31774
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/path.js
31775
31775
  function normalizeSeparators(path) {
31776
31776
  return path.replaceAll("\\", "/");
31777
31777
  }
@@ -31832,17 +31832,17 @@ var init_path = __esm(() => {
31832
31832
  SEP = globalThis.process?.platform === "win32" ? "\\" : "/";
31833
31833
  });
31834
31834
 
31835
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.30+fa3ca66e1fba4d51/node_modules/@gobing-ai/ts-runtime/dist/schema-validation.js
31835
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/schema-validation.js
31836
31836
  var REMOTE_SCHEMA_MAX_BYTES;
31837
31837
  var init_schema_validation = __esm(() => {
31838
31838
  init_dist2();
31839
31839
  REMOTE_SCHEMA_MAX_BYTES = 5 * 1024 * 1024;
31840
31840
  });
31841
31841
 
31842
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.30+fa3ca66e1fba4d51/node_modules/@gobing-ai/ts-runtime/dist/types.js
31842
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/types.js
31843
31843
  var init_types = () => {};
31844
31844
 
31845
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.30+fa3ca66e1fba4d51/node_modules/@gobing-ai/ts-runtime/dist/index.js
31845
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+180a6e424da77181/node_modules/@gobing-ai/ts-runtime/dist/index.js
31846
31846
  var init_dist3 = __esm(() => {
31847
31847
  init_file_system_node();
31848
31848
  init_process_executor();
@@ -31855,7 +31855,7 @@ var init_dist3 = __esm(() => {
31855
31855
  init_types();
31856
31856
  });
31857
31857
 
31858
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.30+4bbef1a3d28d9ec1/node_modules/@gobing-ai/ts-runtime/dist/config.js
31858
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+98832255fbfe9409/node_modules/@gobing-ai/ts-runtime/dist/config.js
31859
31859
  var configSchema2;
31860
31860
  var init_config2 = __esm(() => {
31861
31861
  init_dist2();
@@ -31879,7 +31879,7 @@ var init_config2 = __esm(() => {
31879
31879
  });
31880
31880
  });
31881
31881
 
31882
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.30+4bbef1a3d28d9ec1/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
31882
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+98832255fbfe9409/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
31883
31883
  import { appendFileSync as appendFileSync3, cpSync as cpSync2, createReadStream as createReadStream3, createWriteStream as createWriteStream3, existsSync as existsSync4, mkdirSync as mkdirSync2, readdirSync as readdirSync3, readFileSync as readFileSync6, realpathSync as realpathSync3, renameSync as renameSync2, rmSync as rmSync2, statSync as statSync5, writeFileSync as writeFileSync3 } from "fs";
31884
31884
  import { dirname as dirname4, resolve as resolvePath3 } from "path";
31885
31885
  function createNodeFileSystem2(root, paths) {
@@ -31966,10 +31966,10 @@ function findProjectRoot2(startDir) {
31966
31966
  }
31967
31967
  var init_file_system_node2 = () => {};
31968
31968
 
31969
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.30+4bbef1a3d28d9ec1/node_modules/@gobing-ai/ts-runtime/dist/context.js
31969
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+98832255fbfe9409/node_modules/@gobing-ai/ts-runtime/dist/context.js
31970
31970
  var init_context2 = () => {};
31971
31971
 
31972
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.30+4bbef1a3d28d9ec1/node_modules/@gobing-ai/ts-runtime/dist/path.js
31972
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+98832255fbfe9409/node_modules/@gobing-ai/ts-runtime/dist/path.js
31973
31973
  function normalizeSeparators2(path) {
31974
31974
  return path.replaceAll("\\", "/");
31975
31975
  }
@@ -32030,17 +32030,17 @@ var init_path2 = __esm(() => {
32030
32030
  SEP2 = globalThis.process?.platform === "win32" ? "\\" : "/";
32031
32031
  });
32032
32032
 
32033
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.30+4bbef1a3d28d9ec1/node_modules/@gobing-ai/ts-runtime/dist/schema-validation.js
32033
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+98832255fbfe9409/node_modules/@gobing-ai/ts-runtime/dist/schema-validation.js
32034
32034
  var REMOTE_SCHEMA_MAX_BYTES2;
32035
32035
  var init_schema_validation2 = __esm(() => {
32036
32036
  init_dist2();
32037
32037
  REMOTE_SCHEMA_MAX_BYTES2 = 5 * 1024 * 1024;
32038
32038
  });
32039
32039
 
32040
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.30+4bbef1a3d28d9ec1/node_modules/@gobing-ai/ts-runtime/dist/types.js
32040
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+98832255fbfe9409/node_modules/@gobing-ai/ts-runtime/dist/types.js
32041
32041
  var init_types2 = () => {};
32042
32042
 
32043
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.30+4bbef1a3d28d9ec1/node_modules/@gobing-ai/ts-runtime/dist/index.js
32043
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+98832255fbfe9409/node_modules/@gobing-ai/ts-runtime/dist/index.js
32044
32044
  var init_dist4 = __esm(() => {
32045
32045
  init_file_system_node2();
32046
32046
  init_config2();
@@ -32050,7 +32050,7 @@ var init_dist4 = __esm(() => {
32050
32050
  init_types2();
32051
32051
  });
32052
32052
 
32053
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.30+4bbef1a3d28d9ec1/node_modules/@gobing-ai/ts-runtime/dist/bun-sqlite.js
32053
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.32+98832255fbfe9409/node_modules/@gobing-ai/ts-runtime/dist/bun-sqlite.js
32054
32054
  import { Database } from "bun:sqlite";
32055
32055
  var init_bun_sqlite = () => {};
32056
32056
 
@@ -36437,7 +36437,7 @@ var init_bun_sqlite2 = __esm(() => {
36437
36437
  init_session2();
36438
36438
  });
36439
36439
 
36440
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.30+9a4ec6b3f76cf7f1/node_modules/@gobing-ai/ts-db/dist/schema/inbox-messages.js
36440
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.32+91736011317b4165/node_modules/@gobing-ai/ts-db/dist/schema/inbox-messages.js
36441
36441
  var inboxMessages;
36442
36442
  var init_inbox_messages = __esm(() => {
36443
36443
  init_sqlite_core();
@@ -36457,7 +36457,7 @@ var init_inbox_messages = __esm(() => {
36457
36457
  }, (table) => [index("idx_inbox_messages_to_status").on(table.toId, table.status)]);
36458
36458
  });
36459
36459
 
36460
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.30+9a4ec6b3f76cf7f1/node_modules/@gobing-ai/ts-db/dist/schema/common.js
36460
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.32+91736011317b4165/node_modules/@gobing-ai/ts-db/dist/schema/common.js
36461
36461
  function nowTimestamp() {
36462
36462
  return Date.now();
36463
36463
  }
@@ -36486,7 +36486,7 @@ var init_common2 = __esm(() => {
36486
36486
  appendOnlyColumns = buildAppendOnlyColumns();
36487
36487
  });
36488
36488
 
36489
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.30+9a4ec6b3f76cf7f1/node_modules/@gobing-ai/ts-db/dist/schema/queue-jobs.js
36489
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.32+91736011317b4165/node_modules/@gobing-ai/ts-db/dist/schema/queue-jobs.js
36490
36490
  var queueJobs;
36491
36491
  var init_queue_jobs = __esm(() => {
36492
36492
  init_sqlite_core();
@@ -36510,7 +36510,7 @@ var init_queue_jobs = __esm(() => {
36510
36510
  }, (table) => [index("queue_jobs_ready_idx").on(table.status, table.nextRetryAt, table.createdAt)]);
36511
36511
  });
36512
36512
 
36513
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.30+9a4ec6b3f76cf7f1/node_modules/@gobing-ai/ts-db/dist/schema/runtime.js
36513
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.32+91736011317b4165/node_modules/@gobing-ai/ts-db/dist/schema/runtime.js
36514
36514
  var exports_runtime = {};
36515
36515
  __export(exports_runtime, {
36516
36516
  inboxMessages: () => inboxMessages,
@@ -36521,7 +36521,7 @@ var init_runtime = __esm(() => {
36521
36521
  init_queue_jobs();
36522
36522
  });
36523
36523
 
36524
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.30+9a4ec6b3f76cf7f1/node_modules/@gobing-ai/ts-db/dist/adapters/bun-sqlite.js
36524
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.32+91736011317b4165/node_modules/@gobing-ai/ts-db/dist/adapters/bun-sqlite.js
36525
36525
  class BunSqliteAdapter {
36526
36526
  sqlite;
36527
36527
  drizzleDb;
@@ -36827,7 +36827,7 @@ var init_d1 = __esm(() => {
36827
36827
  init_session3();
36828
36828
  });
36829
36829
 
36830
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.30+9a4ec6b3f76cf7f1/node_modules/@gobing-ai/ts-db/dist/adapters/d1.js
36830
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.32+91736011317b4165/node_modules/@gobing-ai/ts-db/dist/adapters/d1.js
36831
36831
  class D1Adapter {
36832
36832
  binding;
36833
36833
  drizzleDb;
@@ -36886,7 +36886,7 @@ var init_d12 = __esm(() => {
36886
36886
  init_runtime();
36887
36887
  });
36888
36888
 
36889
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.30+9a4ec6b3f76cf7f1/node_modules/@gobing-ai/ts-db/dist/adapter.js
36889
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.32+91736011317b4165/node_modules/@gobing-ai/ts-db/dist/adapter.js
36890
36890
  async function createDbAdapter(config) {
36891
36891
  switch (config.driver) {
36892
36892
  case "bun-sqlite": {
@@ -36920,7 +36920,7 @@ var init_drizzle_orm = __esm(() => {
36920
36920
  init_view_common();
36921
36921
  });
36922
36922
 
36923
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.30+9a4ec6b3f76cf7f1/node_modules/@gobing-ai/ts-db/dist/query-spec.js
36923
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.32+91736011317b4165/node_modules/@gobing-ai/ts-db/dist/query-spec.js
36924
36924
  function compilePredicate(predicate) {
36925
36925
  if ("and" in predicate) {
36926
36926
  const parts = predicate.and.map(compilePredicate).filter((p) => p !== undefined);
@@ -36958,7 +36958,7 @@ var init_query_spec = __esm(() => {
36958
36958
  };
36959
36959
  });
36960
36960
 
36961
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.30+9a4ec6b3f76cf7f1/node_modules/@gobing-ai/ts-db/dist/base-dao.js
36961
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.32+91736011317b4165/node_modules/@gobing-ai/ts-db/dist/base-dao.js
36962
36962
  function asSelectQuery(query) {
36963
36963
  return query;
36964
36964
  }
@@ -37000,7 +37000,7 @@ var init_base_dao = __esm(() => {
37000
37000
  init_query_spec();
37001
37001
  });
37002
37002
 
37003
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.30+9a4ec6b3f76cf7f1/node_modules/@gobing-ai/ts-db/dist/entity-dao.js
37003
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.32+91736011317b4165/node_modules/@gobing-ai/ts-db/dist/entity-dao.js
37004
37004
  var EntityDao;
37005
37005
  var init_entity_dao = __esm(() => {
37006
37006
  init_drizzle_orm();
@@ -37162,7 +37162,7 @@ var init_entity_dao = __esm(() => {
37162
37162
  };
37163
37163
  });
37164
37164
 
37165
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.30+9a4ec6b3f76cf7f1/node_modules/@gobing-ai/ts-db/dist/index.js
37165
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.32+91736011317b4165/node_modules/@gobing-ai/ts-db/dist/index.js
37166
37166
  var init_dist5 = __esm(() => {
37167
37167
  init_base_dao();
37168
37168
  init_entity_dao();
@@ -37635,7 +37635,7 @@ var init_ledger2 = __esm(() => {
37635
37635
  init_output2();
37636
37636
  });
37637
37637
 
37638
- // ../../node_modules/.bun/@gobing-ai+ts-browser-automation@0.5.30+6d005366f784ddaf/node_modules/@gobing-ai/ts-browser-automation/dist/errors.js
37638
+ // ../../node_modules/.bun/@gobing-ai+ts-browser-automation@0.5.32+0f5f0476d0d466a6/node_modules/@gobing-ai/ts-browser-automation/dist/errors.js
37639
37639
  var BrowserAutomationError, InvalidProfileDirError, BrowserProfileMissingError, BrowserProfileBusyError, PlaywrightUnavailableError, LoginTimeoutError, OperationAbortedError;
37640
37640
  var init_errors5 = __esm(() => {
37641
37641
  BrowserAutomationError = class BrowserAutomationError extends Error {
@@ -37682,7 +37682,7 @@ var init_errors5 = __esm(() => {
37682
37682
  };
37683
37683
  });
37684
37684
 
37685
- // ../../node_modules/.bun/@gobing-ai+ts-browser-automation@0.5.30+6d005366f784ddaf/node_modules/@gobing-ai/ts-browser-automation/dist/profile-dir.js
37685
+ // ../../node_modules/.bun/@gobing-ai+ts-browser-automation@0.5.32+0f5f0476d0d466a6/node_modules/@gobing-ai/ts-browser-automation/dist/profile-dir.js
37686
37686
  function resolveProfileDir(profileDir) {
37687
37687
  if (profileDir.trim() === "") {
37688
37688
  throw new InvalidProfileDirError;
@@ -37698,7 +37698,7 @@ var init_profile_dir = __esm(() => {
37698
37698
  init_errors5();
37699
37699
  });
37700
37700
 
37701
- // ../../node_modules/.bun/@gobing-ai+ts-browser-automation@0.5.30+6d005366f784ddaf/node_modules/@gobing-ai/ts-browser-automation/dist/launcher.js
37701
+ // ../../node_modules/.bun/@gobing-ai+ts-browser-automation@0.5.32+0f5f0476d0d466a6/node_modules/@gobing-ai/ts-browser-automation/dist/launcher.js
37702
37702
  import { mkdir } from "fs/promises";
37703
37703
  async function ensureProfileDir(profileDir, headless, fs) {
37704
37704
  const existing = await fs.stat(profileDir);
@@ -37755,7 +37755,7 @@ var init_launcher = __esm(() => {
37755
37755
  CHROMIUM_MISSING_PATTERN = /playwright install|executable doesn't exist/i;
37756
37756
  });
37757
37757
 
37758
- // ../../node_modules/.bun/@gobing-ai+ts-browser-automation@0.5.30+6d005366f784ddaf/node_modules/@gobing-ai/ts-browser-automation/dist/operations.js
37758
+ // ../../node_modules/.bun/@gobing-ai+ts-browser-automation@0.5.32+0f5f0476d0d466a6/node_modules/@gobing-ai/ts-browser-automation/dist/operations.js
37759
37759
  function getDefaultLauncher() {
37760
37760
  if (defaultLauncher === undefined)
37761
37761
  defaultLauncher = createPersistentLauncher();
@@ -37853,7 +37853,7 @@ var init_operations = __esm(() => {
37853
37853
  init_profile_dir();
37854
37854
  });
37855
37855
 
37856
- // ../../node_modules/.bun/@gobing-ai+ts-browser-automation@0.5.30+6d005366f784ddaf/node_modules/@gobing-ai/ts-browser-automation/dist/index.js
37856
+ // ../../node_modules/.bun/@gobing-ai+ts-browser-automation@0.5.32+0f5f0476d0d466a6/node_modules/@gobing-ai/ts-browser-automation/dist/index.js
37857
37857
  var init_dist6 = __esm(() => {
37858
37858
  init_errors5();
37859
37859
  init_operations();
@@ -41769,7 +41769,7 @@ var ConfigError = class extends Error {
41769
41769
  }
41770
41770
  };
41771
41771
 
41772
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.5.30+72430983864a6768/node_modules/@gobing-ai/ts-infra/dist/logger.js
41772
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.5.32+7037256b2d91fd75/node_modules/@gobing-ai/ts-infra/dist/logger.js
41773
41773
  var ROOT_CATEGORY = "app";
41774
41774
  function toLogTapeLevel(level) {
41775
41775
  return level === "warn" ? "warning" : level;
@@ -43712,11 +43712,11 @@ async function resolveStorePath(configFile, explicitPath) {
43712
43712
  // ../../packages/kk-store/src/dao/collect-runs.ts
43713
43713
  init_dist5();
43714
43714
 
43715
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.30+9a4ec6b3f76cf7f1/node_modules/@gobing-ai/ts-db/dist/schema/index.js
43715
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.32+91736011317b4165/node_modules/@gobing-ai/ts-db/dist/schema/index.js
43716
43716
  init_sqlite_core();
43717
43717
  init_common2();
43718
43718
 
43719
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.30+9a4ec6b3f76cf7f1/node_modules/@gobing-ai/ts-db/dist/schema/define-table.js
43719
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.32+91736011317b4165/node_modules/@gobing-ai/ts-db/dist/schema/define-table.js
43720
43720
  init_sqlite_core();
43721
43721
 
43722
43722
  // ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/index.js
@@ -43988,10 +43988,10 @@ var createInsertSchema = (entity, refine) => {
43988
43988
  return handleColumns(columns, refine ?? {}, insertConditions);
43989
43989
  };
43990
43990
 
43991
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.30+9a4ec6b3f76cf7f1/node_modules/@gobing-ai/ts-db/dist/schema/ddl.js
43991
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.32+91736011317b4165/node_modules/@gobing-ai/ts-db/dist/schema/ddl.js
43992
43992
  init_sqlite_core();
43993
43993
 
43994
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.30+9a4ec6b3f76cf7f1/node_modules/@gobing-ai/ts-db/dist/schema/drizzle-internals.js
43994
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.32+91736011317b4165/node_modules/@gobing-ai/ts-db/dist/schema/drizzle-internals.js
43995
43995
  function sqlExpressionToText(value) {
43996
43996
  if (typeof value !== "object" || value === null || !("queryChunks" in value)) {
43997
43997
  return;
@@ -44014,7 +44014,7 @@ function getDrizzleTableName(table) {
44014
44014
  return String(table[nameSym]);
44015
44015
  }
44016
44016
 
44017
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.30+9a4ec6b3f76cf7f1/node_modules/@gobing-ai/ts-db/dist/schema/ddl.js
44017
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.32+91736011317b4165/node_modules/@gobing-ai/ts-db/dist/schema/ddl.js
44018
44018
  function quoteIdent(name) {
44019
44019
  return `"${name.replace(/"/g, '""')}"`;
44020
44020
  }
@@ -44105,7 +44105,7 @@ function generateCreateTableSql(table) {
44105
44105
  )`;
44106
44106
  }
44107
44107
 
44108
- // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.30+9a4ec6b3f76cf7f1/node_modules/@gobing-ai/ts-db/dist/schema/define-table.js
44108
+ // ../../node_modules/.bun/@gobing-ai+ts-db@0.5.32+91736011317b4165/node_modules/@gobing-ai/ts-db/dist/schema/define-table.js
44109
44109
  function defineTable(name, columns) {
44110
44110
  const table = sqliteTable(name, columns);
44111
44111
  let insert;
@@ -44717,21 +44717,33 @@ class CollectViewDao extends BaseDao {
44717
44717
  const rows = await this.adapter.queryAll("SELECT DISTINCT source AS source FROM items WHERE source <> '' ORDER BY source");
44718
44718
  return rows.map((row) => row.source);
44719
44719
  }
44720
+ async selectionTopics() {
44721
+ const rows = await this.adapter.queryAll("SELECT DISTINCT topic AS topic FROM selections WHERE topic <> '' ORDER BY topic");
44722
+ return rows.map((row) => row.topic);
44723
+ }
44720
44724
  async itemsPage(runId, filter, page, policy) {
44721
44725
  const params = [];
44722
- const conditions = ["(it.first_seen_run = ? OR it.last_seen_run = ?)"];
44723
- params.push(runId, runId);
44724
- if (filter.seen === "new") {
44725
- conditions.push("it.first_seen_run = ?");
44726
- params.push(runId);
44727
- } else if (filter.seen === "reseen") {
44728
- conditions.push("it.last_seen_run = ? AND it.first_seen_run <> ?");
44726
+ const conditions = [];
44727
+ if (runId !== undefined && runId !== null && runId !== "" && runId !== "all") {
44728
+ conditions.push("(it.first_seen_run = ? OR it.last_seen_run = ?)");
44729
44729
  params.push(runId, runId);
44730
+ if (filter.seen === "new") {
44731
+ conditions.push("it.first_seen_run = ?");
44732
+ params.push(runId);
44733
+ } else if (filter.seen === "reseen") {
44734
+ conditions.push("it.last_seen_run = ? AND it.first_seen_run <> ?");
44735
+ params.push(runId, runId);
44736
+ }
44730
44737
  }
44731
44738
  if (filter.source !== undefined) {
44732
44739
  conditions.push("it.source = ?");
44733
44740
  params.push(filter.source);
44734
44741
  }
44742
+ if (filter.search !== undefined && filter.search.trim() !== "") {
44743
+ const pattern = `%${filter.search.trim()}%`;
44744
+ conditions.push("(it.title LIKE ? OR it.id LIKE ? OR it.canonical_url LIKE ?)");
44745
+ params.push(pattern, pattern, pattern);
44746
+ }
44735
44747
  const rank = filter.selection === undefined || filter.selection === "none" ? undefined : { selected: 2, published: 3, dropped: 1 }[filter.selection];
44736
44748
  if (filter.selection === "none") {
44737
44749
  conditions.push("sel.rank IS NULL");
@@ -44750,18 +44762,21 @@ class CollectViewDao extends BaseDao {
44750
44762
  ` : "";
44751
44763
  const currentParams = usesCurrent ? current.params : [];
44752
44764
  const from = `items it LEFT JOIN (${SELECTION_RANK_SQL}) sel ON sel.item_id = it.id`;
44753
- const where = conditions.join(`
44754
- AND `);
44755
- const totalRow = await this.adapter.queryFirst(`${withClause}SELECT COUNT(*) AS n FROM ${from} WHERE ${where}`, ...currentParams, ...params);
44765
+ const where = conditions.length === 0 ? "" : `WHERE ${conditions.join(`
44766
+ AND `)}`;
44767
+ const totalRow = await this.adapter.queryFirst(`${withClause}SELECT COUNT(*) AS n FROM ${from} ${where}`, ...currentParams, ...params);
44756
44768
  const offset = (Math.max(1, page) - 1) * COLLECT_VIEW_PAGE_SIZE;
44757
44769
  const rows = await this.adapter.queryAll(`${withClause}SELECT it.id AS id, it.title AS title, it.canonical_url AS canonicalUrl,
44758
44770
  it.source AS source, it.story_id AS storyId,
44759
44771
  it.first_seen_run AS firstSeenRun, it.last_seen_run AS lastSeenRun,
44772
+ it.domain AS domain, it.lang AS lang, it.body_chars AS bodyChars,
44773
+ it.engagement AS engagement, it.first_seen_at AS firstSeenAt,
44774
+ it.published_at AS publishedAt,
44760
44775
  sel.rank AS selectionRank
44761
- FROM ${from} WHERE ${where}
44776
+ FROM ${from} ${where}
44762
44777
  ORDER BY it.last_seen_run DESC, it.id ASC
44763
44778
  LIMIT ? OFFSET ?`, ...currentParams, ...params, COLLECT_VIEW_PAGE_SIZE, offset);
44764
- const labelsOf = await this.currentLabels(rows.map((row) => row.id), policy);
44779
+ const labelsData = await this.currentLabels(rows.map((row) => row.id), policy);
44765
44780
  return {
44766
44781
  total: totalRow?.n ?? 0,
44767
44782
  items: rows.map((row) => ({
@@ -44771,26 +44786,85 @@ class CollectViewDao extends BaseDao {
44771
44786
  source: row.source,
44772
44787
  storyId: row.storyId,
44773
44788
  seen: row.firstSeenRun === runId ? "new" : "reseen",
44774
- labels: labelsOf.get(row.id) ?? {},
44775
- selection: statusOf(row.selectionRank)
44789
+ labels: labelsData.labels.get(row.id) ?? {},
44790
+ labelDetails: labelsData.labelDetails.get(row.id) ?? {},
44791
+ selection: statusOf(row.selectionRank),
44792
+ domain: row.domain,
44793
+ lang: row.lang,
44794
+ bodyChars: row.bodyChars,
44795
+ engagement: row.engagement,
44796
+ firstSeenAt: row.firstSeenAt,
44797
+ publishedAt: row.publishedAt
44798
+ }))
44799
+ };
44800
+ }
44801
+ async selectionsPage(filter = {}, page = 1) {
44802
+ const params = [];
44803
+ const conditions = [];
44804
+ if (filter.runId !== undefined && filter.runId !== "" && filter.runId !== "all") {
44805
+ conditions.push("s.run_id = ?");
44806
+ params.push(filter.runId);
44807
+ }
44808
+ if (filter.topic !== undefined && filter.topic !== "" && filter.topic !== "all") {
44809
+ conditions.push("s.topic = ?");
44810
+ params.push(filter.topic);
44811
+ }
44812
+ if (filter.status !== undefined && filter.status !== "" && filter.status !== "all") {
44813
+ conditions.push("s.status = ?");
44814
+ params.push(filter.status);
44815
+ }
44816
+ if (filter.search !== undefined && filter.search.trim() !== "") {
44817
+ const pattern = `%${filter.search.trim()}%`;
44818
+ conditions.push("(it.title LIKE ? OR s.item_id LIKE ? OR s.reason LIKE ?)");
44819
+ params.push(pattern, pattern, pattern);
44820
+ }
44821
+ const where = conditions.length === 0 ? "" : `WHERE ${conditions.join(`
44822
+ AND `)}`;
44823
+ const from = "selections s LEFT JOIN items it ON it.id = s.item_id";
44824
+ const totalRow = await this.adapter.queryFirst(`SELECT COUNT(*) AS n FROM ${from} ${where}`, ...params);
44825
+ const offset = (Math.max(1, page) - 1) * COLLECT_VIEW_PAGE_SIZE;
44826
+ const rows = await this.adapter.queryAll(`SELECT s.topic AS topic, s.item_id AS itemId, s.run_id AS runId, s.story_id AS storyId,
44827
+ s.workflow AS workflow, s.rank AS rank, s.reason AS reason, s.status AS status,
44828
+ s.selected_at AS selectedAt, s.published_at AS publishedAt,
44829
+ it.title AS title, it.source AS source, it.canonical_url AS canonicalUrl
44830
+ FROM ${from} ${where}
44831
+ ORDER BY s.selected_at DESC, s.rank ASC
44832
+ LIMIT ? OFFSET ?`, ...params, COLLECT_VIEW_PAGE_SIZE, offset);
44833
+ const topics = await this.selectionTopics();
44834
+ return {
44835
+ total: totalRow?.n ?? 0,
44836
+ topics,
44837
+ selections: rows.map((r) => ({
44838
+ ...r,
44839
+ status: r.status
44776
44840
  }))
44777
44841
  };
44778
44842
  }
44779
44843
  async currentLabels(itemIds, policy) {
44780
- const result = new Map;
44844
+ const labels = new Map;
44845
+ const labelDetails = new Map;
44781
44846
  if (itemIds.length === 0)
44782
- return result;
44847
+ return { labels, labelDetails };
44783
44848
  const current = labelsCurrentSql(policy);
44784
44849
  const rows = await this.adapter.queryAll(`WITH ${current.sql}
44785
- SELECT item_id AS itemId, decision_id AS decisionId, value AS value
44850
+ SELECT item_id AS itemId, decision_id AS decisionId, value AS value,
44851
+ confidence AS confidence, maker AS maker, score AS score
44786
44852
  FROM labels_current WHERE item_id IN (${placeholders(itemIds.length)})
44787
44853
  ORDER BY item_id, decision_id`, ...current.params, ...itemIds);
44788
44854
  for (const row of rows) {
44789
- const labels = result.get(row.itemId) ?? {};
44790
- labels[row.decisionId] = row.value;
44791
- result.set(row.itemId, labels);
44855
+ const itemLabels = labels.get(row.itemId) ?? {};
44856
+ itemLabels[row.decisionId] = row.value;
44857
+ labels.set(row.itemId, itemLabels);
44858
+ const itemDetails = labelDetails.get(row.itemId) ?? {};
44859
+ itemDetails[row.decisionId] = {
44860
+ value: row.value,
44861
+ confidence: row.confidence,
44862
+ maker: row.maker,
44863
+ score: row.score
44864
+ };
44865
+ labelDetails.set(row.itemId, itemDetails);
44792
44866
  }
44793
- return result;
44867
+ return { labels, labelDetails };
44794
44868
  }
44795
44869
  }
44796
44870
  // ../../packages/kk-store/src/dao/items.ts
@@ -45833,16 +45907,24 @@ function itemOf(item) {
45833
45907
  storyId: item.storyId,
45834
45908
  seen: item.seen,
45835
45909
  labels: item.labels,
45836
- selection: item.selection
45910
+ labelDetails: item.labelDetails,
45911
+ selection: item.selection,
45912
+ domain: item.domain,
45913
+ lang: item.lang,
45914
+ bodyChars: item.bodyChars,
45915
+ engagement: item.engagement,
45916
+ firstSeenAt: item.firstSeenAt,
45917
+ publishedAt: item.publishedAt
45837
45918
  };
45838
45919
  }
45839
45920
  async function storeItems(deps, runId, query) {
45840
45921
  const session = await sessionFor(deps);
45922
+ const resolvedRunId = runId ?? "";
45841
45923
  if (!session.ok) {
45842
45924
  return {
45843
45925
  schemaVersion: 1,
45844
45926
  availability: "unavailable",
45845
- runId,
45927
+ runId: resolvedRunId,
45846
45928
  page: query.page,
45847
45929
  pageSize: 25,
45848
45930
  total: 0,
@@ -45861,14 +45943,15 @@ async function storeItems(deps, runId, query) {
45861
45943
  ...query.seen === undefined ? {} : { seen: query.seen },
45862
45944
  ...query.decision === undefined ? {} : { decision: query.decision },
45863
45945
  ...query.value === undefined ? {} : { value: query.value },
45864
- ...query.selection === undefined ? {} : { selection: query.selection }
45946
+ ...query.selection === undefined ? {} : { selection: query.selection },
45947
+ ...query.search === undefined ? {} : { search: query.search }
45865
45948
  };
45866
45949
  const effectivePolicy = policy ?? { priority: [], decisionPriority: {}, minConfidence: 1 };
45867
45950
  const page = await store.collectView.itemsPage(runId, filter, query.page, effectivePolicy);
45868
45951
  return {
45869
45952
  schemaVersion: 1,
45870
45953
  availability: "available",
45871
- runId,
45954
+ runId: resolvedRunId,
45872
45955
  page: query.page,
45873
45956
  pageSize: 25,
45874
45957
  total: page.total,
@@ -45878,8 +45961,69 @@ async function storeItems(deps, runId, query) {
45878
45961
  };
45879
45962
  } catch {
45880
45963
  return {
45881
- ...emptyItems(runId, query, []),
45964
+ ...emptyItems(resolvedRunId, query, []),
45965
+ availability: "unavailable",
45966
+ diagnostics: [...diagnostics, UNREADABLE]
45967
+ };
45968
+ } finally {
45969
+ await store.close();
45970
+ }
45971
+ }
45972
+ async function storeSelections(deps, query) {
45973
+ const session = await sessionFor(deps);
45974
+ if (!session.ok) {
45975
+ return {
45976
+ schemaVersion: 1,
45977
+ availability: "unavailable",
45978
+ page: query.page,
45979
+ pageSize: 25,
45980
+ total: 0,
45981
+ selections: [],
45982
+ topics: [],
45983
+ diagnostics: session.diagnostics
45984
+ };
45985
+ }
45986
+ const { store, diagnostics } = session.session;
45987
+ try {
45988
+ const page = await store.collectView.selectionsPage({
45989
+ runId: query.runId,
45990
+ topic: query.topic,
45991
+ status: query.status,
45992
+ search: query.search
45993
+ }, query.page);
45994
+ return {
45995
+ schemaVersion: 1,
45996
+ availability: "available",
45997
+ page: query.page,
45998
+ pageSize: 25,
45999
+ total: page.total,
46000
+ topics: page.topics,
46001
+ selections: page.selections.map((s) => ({
46002
+ topic: s.topic,
46003
+ itemId: s.itemId,
46004
+ runId: s.runId,
46005
+ storyId: s.storyId,
46006
+ workflow: s.workflow,
46007
+ rank: s.rank,
46008
+ reason: s.reason,
46009
+ status: s.status,
46010
+ selectedAt: s.selectedAt,
46011
+ publishedAt: s.publishedAt,
46012
+ title: s.title ? s.title.slice(0, ITEM_TITLE_MAX) : null,
46013
+ source: s.source,
46014
+ url: linkOf(s.canonicalUrl)
46015
+ })),
46016
+ diagnostics
46017
+ };
46018
+ } catch {
46019
+ return {
46020
+ schemaVersion: 1,
45882
46021
  availability: "unavailable",
46022
+ page: query.page,
46023
+ pageSize: 25,
46024
+ total: 0,
46025
+ selections: [],
46026
+ topics: [],
45883
46027
  diagnostics: [...diagnostics, UNREADABLE]
45884
46028
  };
45885
46029
  } finally {
@@ -46456,6 +46600,25 @@ function isLoopbackHost(host) {
46456
46600
  const name = host.startsWith("[") ? host.slice(0, host.indexOf("]") + 1) : host.split(":")[0] ?? "";
46457
46601
  return name === "127.0.0.1" || name === "localhost" || name === "[::1]";
46458
46602
  }
46603
+ function isMatchingBoardOrigin(requestOrigin, configuredBoardOrigin) {
46604
+ if (requestOrigin === configuredBoardOrigin)
46605
+ return true;
46606
+ try {
46607
+ const req = new URL(requestOrigin);
46608
+ const conf = new URL(configuredBoardOrigin);
46609
+ if (req.protocol !== conf.protocol)
46610
+ return false;
46611
+ const reqPort = req.port || (req.protocol === "https:" ? "443" : "80");
46612
+ const confPort = conf.port || (conf.protocol === "https:" ? "443" : "80");
46613
+ if (reqPort !== confPort)
46614
+ return false;
46615
+ const isReqLoopback = req.hostname === "127.0.0.1" || req.hostname === "localhost" || req.hostname === "[::1]";
46616
+ const isConfLoopback = conf.hostname === "127.0.0.1" || conf.hostname === "localhost" || conf.hostname === "[::1]";
46617
+ return isReqLoopback && isConfLoopback;
46618
+ } catch {
46619
+ return false;
46620
+ }
46621
+ }
46459
46622
  function parseByteRange(header, size) {
46460
46623
  if (header === null || header === "")
46461
46624
  return null;
@@ -46852,18 +47015,23 @@ function createBoardReader(options) {
46852
47015
  }
46853
47016
  return { status: 200, body: items };
46854
47017
  }
47018
+ async function storeSelectionsFor(query) {
47019
+ return { status: 200, body: await storeSelections({ projectPath, fs }, query) };
47020
+ }
46855
47021
  const server = Bun.serve({
46856
47022
  hostname: "127.0.0.1",
46857
47023
  port,
46858
47024
  fetch: async (request) => {
47025
+ const origin = request.headers.get("origin");
47026
+ const originMatches = origin === null || isMatchingBoardOrigin(origin, boardOrigin);
47027
+ const allowedOrigin = origin !== null && originMatches ? origin : boardOrigin;
46859
47028
  const cors = {
46860
- "access-control-allow-origin": boardOrigin,
47029
+ "access-control-allow-origin": allowedOrigin,
46861
47030
  "access-control-allow-methods": "GET, HEAD, OPTIONS",
46862
47031
  "access-control-allow-headers": "range, content-type",
46863
47032
  vary: "origin"
46864
47033
  };
46865
- const origin = request.headers.get("origin");
46866
- if (origin !== null && origin !== boardOrigin) {
47034
+ if (!originMatches) {
46867
47035
  return jsonResponse({ code: "board.origin.refused", message: "Origin is not the configured Board." }, 403, cors);
46868
47036
  }
46869
47037
  if (!isLoopbackHost(request.headers.get("host") ?? "")) {
@@ -46880,9 +47048,12 @@ function createBoardReader(options) {
46880
47048
  return jsonResponse({ schemaVersion: 1, projectPath }, 200, cors);
46881
47049
  }
46882
47050
  const overviewMatch = /^\/api\/workflows\/([^/]+)\/store\/overview$/.exec(path);
47051
+ const selectionsMatch = /^\/api\/workflows\/([^/]+)\/store\/selections$/.exec(path);
47052
+ const storeItemsMatch = /^\/api\/workflows\/([^/]+)\/store\/items$/.exec(path);
47053
+ const runStoreSelectionsMatch = /^\/api\/workflows\/([^/]+)\/runs\/([^/]+)\/store\/selections$/.exec(path);
46883
47054
  const runStoreMatch = /^\/api\/workflows\/([^/]+)\/runs\/([^/]+)\/store$/.exec(path);
46884
47055
  const runStoreItemsMatch = /^\/api\/workflows\/([^/]+)\/runs\/([^/]+)\/store\/items$/.exec(path);
46885
- const storeMatch = overviewMatch ?? runStoreMatch ?? runStoreItemsMatch;
47056
+ const storeMatch = overviewMatch ?? selectionsMatch ?? storeItemsMatch ?? runStoreSelectionsMatch ?? runStoreMatch ?? runStoreItemsMatch;
46886
47057
  if (storeMatch !== null) {
46887
47058
  const storeRaw = storeMatch[1] ?? "";
46888
47059
  if (decodeURIComponent(storeRaw) !== STORE_WORKFLOW) {
@@ -46895,6 +47066,33 @@ function createBoardReader(options) {
46895
47066
  const response = await storeOverviewFor(runs.runIds);
46896
47067
  return jsonResponse(response.body, response.status, cors);
46897
47068
  }
47069
+ if (selectionsMatch !== null) {
47070
+ const query = parseSelectionsQuery(url.searchParams);
47071
+ if ("response" in query)
47072
+ return jsonResponse(query.response.body, query.response.status, cors);
47073
+ const response = await storeSelectionsFor(query.query);
47074
+ return jsonResponse(response.body, response.status, cors);
47075
+ }
47076
+ if (storeItemsMatch !== null) {
47077
+ const query = parseItemsQuery(url.searchParams);
47078
+ if ("response" in query)
47079
+ return jsonResponse(query.response.body, query.response.status, cors);
47080
+ const response = await storeItemsFor("", query.query);
47081
+ return jsonResponse(response.body, response.status, cors);
47082
+ }
47083
+ if (runStoreSelectionsMatch !== null) {
47084
+ const identified = identify(storeRaw, runStoreSelectionsMatch[2] ?? "");
47085
+ if ("response" in identified)
47086
+ return jsonResponse(identified.response.body, identified.response.status, cors);
47087
+ const query = parseSelectionsQuery(url.searchParams);
47088
+ if ("response" in query)
47089
+ return jsonResponse(query.response.body, query.response.status, cors);
47090
+ const authorized = await authorizeRun(identified.workflow, identified.runId);
47091
+ if (!authorized.ok)
47092
+ return jsonResponse(authorized.response.body, authorized.response.status, cors);
47093
+ const response = await storeSelectionsFor({ ...query.query, runId: identified.runId });
47094
+ return jsonResponse(response.body, response.status, cors);
47095
+ }
46898
47096
  if (runStoreMatch !== null) {
46899
47097
  const refused = parseQuery(url.searchParams);
46900
47098
  if (refused !== null)
@@ -46945,7 +47143,8 @@ var RUN_ID_PATTERN2 = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
46945
47143
  var MAX_OVERVIEW_RUNS = 25;
46946
47144
  var LABEL_VALUE_PATTERN = /^[A-Za-z0-9._-]{1,64}$/;
46947
47145
  var SELECTION_FILTERS = ["selected", "published", "dropped", "none"];
46948
- var ITEMS_QUERY_KEYS = new Set(["page", "source", "seen", "decision", "value", "selection"]);
47146
+ var ITEMS_QUERY_KEYS = new Set(["page", "source", "seen", "decision", "value", "selection", "search"]);
47147
+ var SELECTIONS_QUERY_KEYS = new Set(["page", "runId", "topic", "status", "search"]);
46949
47148
  function invalidQuery(message) {
46950
47149
  return { status: 400, body: { code: "board.query.invalid", message } };
46951
47150
  }
@@ -47000,6 +47199,7 @@ function parseItemsQuery(params) {
47000
47199
  if (selection !== null && !SELECTION_FILTERS.includes(selection)) {
47001
47200
  return { response: invalidQuery("`selection` must be selected, published, dropped or none.") };
47002
47201
  }
47202
+ const search = params.get("search");
47003
47203
  return {
47004
47204
  query: {
47005
47205
  page,
@@ -47007,7 +47207,41 @@ function parseItemsQuery(params) {
47007
47207
  ...seen === null ? {} : { seen },
47008
47208
  ...decision === null ? {} : { decision },
47009
47209
  ...value === null ? {} : { value },
47010
- ...selection === null ? {} : { selection }
47210
+ ...selection === null ? {} : { selection },
47211
+ ...search === null ? {} : { search }
47212
+ }
47213
+ };
47214
+ }
47215
+ function parseSelectionsQuery(params) {
47216
+ for (const key of params.keys()) {
47217
+ if (!SELECTIONS_QUERY_KEYS.has(key))
47218
+ return { response: invalidQuery("Unknown query parameter.") };
47219
+ }
47220
+ const rawPage = params.get("page");
47221
+ const page = rawPage === null ? 1 : Number(rawPage);
47222
+ if (rawPage !== null && (!/^\d+$/.test(rawPage) || !Number.isSafeInteger(page) || page < 1)) {
47223
+ return { response: invalidQuery("`page` must be an integer of at least 1.") };
47224
+ }
47225
+ const runId = params.get("runId");
47226
+ if (runId !== null && runId !== "" && !RUN_ID_PATTERN2.test(runId)) {
47227
+ return { response: invalidQuery("`runId` must be a single safe segment.") };
47228
+ }
47229
+ const topic = params.get("topic");
47230
+ if (topic !== null && (topic === "" || topic.length > 128)) {
47231
+ return { response: invalidQuery("`topic` must be a short non-empty value.") };
47232
+ }
47233
+ const status = params.get("status");
47234
+ if (status !== null && status !== "selected" && status !== "published" && status !== "dropped") {
47235
+ return { response: invalidQuery("`status` must be selected, published or dropped.") };
47236
+ }
47237
+ const search = params.get("search");
47238
+ return {
47239
+ query: {
47240
+ page,
47241
+ ...runId ? { runId } : {},
47242
+ ...topic ? { topic } : {},
47243
+ ...status ? { status } : {},
47244
+ ...search ? { search } : {}
47011
47245
  }
47012
47246
  };
47013
47247
  }
@@ -51362,15 +51596,144 @@ function registerStageCommand(program) {
51362
51596
  }
51363
51597
 
51364
51598
  // src/commands/store.ts
51365
- import { dirname as dirname12, join as join21, resolve as resolve21 } from "path";
51599
+ import { dirname as dirname12, join as join22, resolve as resolve22 } from "path";
51366
51600
  init_dist3();
51367
51601
  init_commander();
51602
+
51603
+ // src/decision-hub.ts
51604
+ init_dist3();
51605
+ import { randomUUID as randomUUID2 } from "crypto";
51606
+ import { tmpdir as tmpdir3 } from "os";
51607
+ import { join as join21, resolve as resolve21 } from "path";
51608
+ var STORE_CATALOG_PATH_REL = "plugins/kk/decisions/kk-items.yaml";
51609
+ var SPUR_CONFIG_PATH_REL = ".spur/config.yaml";
51610
+ var EVIDENCE_MAX_CHARS = 2000;
51611
+ var SUBPROCESS_FALLBACK_AFTER = 2;
51612
+ async function resolveCatalogPath(projectRoot, fs = createNodeFileSystem()) {
51613
+ const candidates = [
51614
+ resolve21(projectRoot, STORE_CATALOG_PATH_REL),
51615
+ resolve21(import.meta.dir, "../../..", STORE_CATALOG_PATH_REL),
51616
+ resolve21(import.meta.dir, "..", STORE_CATALOG_PATH_REL)
51617
+ ];
51618
+ for (const candidate of candidates) {
51619
+ if (await fs.exists(candidate))
51620
+ return candidate;
51621
+ }
51622
+ throw new Error(`decision catalog not found: tried ${candidates.join(", ")}`);
51623
+ }
51624
+ async function loadInjectedHub() {
51625
+ const modulePath = process.env.KK_DECISION_HUB;
51626
+ if (modulePath === undefined || modulePath === "")
51627
+ return;
51628
+ const loaded = await import(modulePath);
51629
+ const hub = loaded.default;
51630
+ if (hub === undefined)
51631
+ throw new Error(`KK_DECISION_HUB module ${modulePath} has no default export`);
51632
+ return hub;
51633
+ }
51634
+ async function readDecisionRouting(projectRoot, fs = createNodeFileSystem()) {
51635
+ const catalogPath = await resolveCatalogPath(projectRoot, fs);
51636
+ const configPath = join21(projectRoot, SPUR_CONFIG_PATH_REL);
51637
+ if (!await fs.exists(configPath))
51638
+ return { catalogPath, routing: { makers: {} } };
51639
+ let parsed;
51640
+ try {
51641
+ parsed = Bun.YAML.parse(await fs.readFile(configPath));
51642
+ } catch {
51643
+ return { catalogPath, routing: { makers: {} } };
51644
+ }
51645
+ const decisions = asRecord6(asRecord6(parsed).decisions);
51646
+ const makers = {};
51647
+ for (const [id, value] of Object.entries(asRecord6(decisions.makers))) {
51648
+ if (typeof value === "string" && value.trim() !== "")
51649
+ makers[id] = value.trim();
51650
+ }
51651
+ const maker = typeof decisions.maker === "string" && decisions.maker.trim() !== "" ? decisions.maker.trim() : undefined;
51652
+ return { catalogPath, routing: maker === undefined ? { makers } : { makers, maker } };
51653
+ }
51654
+ function asRecord6(value) {
51655
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
51656
+ }
51657
+ async function createItemDecisionAsker(options = {}) {
51658
+ const projectRoot = options.projectRoot ?? process.cwd();
51659
+ const fs = options.fs ?? createNodeFileSystem();
51660
+ const { catalogPath, routing } = await readDecisionRouting(projectRoot, fs);
51661
+ const injected = options.hub ?? await loadInjectedHub();
51662
+ const fallback = options.fallback ?? (injected === undefined ? (decisionId, input, maker) => runDecisionSubprocess(decisionId, input, maker, fs) : undefined);
51663
+ const hub = injected ?? await (await import("@gobing-ai/ts-ai-decision")).createDecisionHub({
51664
+ catalogs: [catalogPath]
51665
+ });
51666
+ const backendFailures = new Map;
51667
+ return {
51668
+ async ask(decisionId, input, maker) {
51669
+ const resolved = maker ?? routing.makers[decisionId] ?? routing.maker;
51670
+ const failures = backendFailures.get(decisionId) ?? 0;
51671
+ if (fallback !== undefined && failures >= SUBPROCESS_FALLBACK_AFTER) {
51672
+ return fallback(decisionId, input, resolved);
51673
+ }
51674
+ const started = Date.now();
51675
+ let answer;
51676
+ try {
51677
+ answer = await hub.decide(decisionId, {
51678
+ title: input.title,
51679
+ source: input.source,
51680
+ instructions: input.body.slice(0, EVIDENCE_MAX_CHARS)
51681
+ }, resolved === undefined ? {} : { maker: resolved });
51682
+ } catch {
51683
+ return;
51684
+ }
51685
+ if (answer.durationMs === undefined)
51686
+ answer = { ...answer, durationMs: Date.now() - started };
51687
+ if (answer.source !== "default" || answer.reason === "low-confidence") {
51688
+ backendFailures.delete(decisionId);
51689
+ return answer;
51690
+ }
51691
+ backendFailures.set(decisionId, failures + 1);
51692
+ return (fallback === undefined ? undefined : fallback(decisionId, input, resolved)) ?? answer;
51693
+ },
51694
+ async dispose() {
51695
+ await hub.registry.dispose();
51696
+ }
51697
+ };
51698
+ }
51699
+ function runDecisionSubprocess(decisionId, input, maker, fs = createNodeFileSystem()) {
51700
+ const command = process.env.KK_SPUR_BIN ?? "spur";
51701
+ const scratch = join21(tmpdir3(), `kk-decision-${randomUUID2()}`);
51702
+ const evidencePath = join21(scratch, "evidence.md");
51703
+ try {
51704
+ fs.writeFile(evidencePath, input.body);
51705
+ const args = [
51706
+ "decision",
51707
+ "run",
51708
+ decisionId,
51709
+ "--param",
51710
+ `title=${input.title}`,
51711
+ "--param",
51712
+ `source=${input.source}`,
51713
+ "--evidence",
51714
+ evidencePath
51715
+ ];
51716
+ if (maker !== undefined)
51717
+ args.push("--maker", maker);
51718
+ args.push("--json");
51719
+ const result = new NodeSyncProcessExecutor().runSync({ command, args });
51720
+ if (result.exitCode !== 0)
51721
+ return;
51722
+ return JSON.parse(result.stdout);
51723
+ } catch {
51724
+ return;
51725
+ } finally {
51726
+ fs.deleteFile(scratch);
51727
+ }
51728
+ }
51729
+
51730
+ // src/commands/store.ts
51368
51731
  init_output2();
51369
51732
  var HEURISTIC_MAKER = "heuristic";
51370
51733
  var LABEL_PLUGIN = "episode-plan-gen";
51371
51734
  var LABEL_SCRATCH_DIR = "label";
51372
51735
  var PROFILE_DIR_REL = "plugins/kk/decisions/extract";
51373
- var CHECKOUT_ROOT3 = resolve21(import.meta.dir, "../../../..");
51736
+ var CHECKOUT_ROOT3 = resolve22(import.meta.dir, "../../../..");
51374
51737
  var CATALOG_PATH_REL = "plugins/kk/decisions/kk-items.yaml";
51375
51738
  var TOPIC_SLUG = /^[a-z0-9][a-z0-9-]*$/;
51376
51739
  var WINDOW_UNITS2 = { s: 1000, m: 60000, h: 3600000, d: 86400000 };
@@ -51393,6 +51756,7 @@ var HEURISTIC_DECISION_IDS = [
51393
51756
  CATEGORY_DECISION_ID,
51394
51757
  ...SCORE_DIMENSIONS.map((dimension) => `kk-item-${dimension}`)
51395
51758
  ];
51759
+ var GRADED_DECISION_IDS = SCORE_DIMENSIONS.map((dimension) => `kk-item-${dimension}`);
51396
51760
  var KEYWORD_MAKER = "keyword";
51397
51761
  var CHINA_POLITICS_BODY_HEAD = 200;
51398
51762
  function failLoud5(code, error) {
@@ -51571,8 +51935,8 @@ async function readAnnotations(fs, outputPath) {
51571
51935
  async function heuristicAnnotations(fs, scratch, runId, items) {
51572
51936
  if (items.length === 0)
51573
51937
  return new Map;
51574
- const inputPath = join21(scratch, "label-input.json");
51575
- const outputPath = join21(scratch, "label-out.json");
51938
+ const inputPath = join22(scratch, "label-input.json");
51939
+ const outputPath = join22(scratch, "label-out.json");
51576
51940
  await fs.ensureDir(scratch);
51577
51941
  const docs = items.map((item) => ({
51578
51942
  id: item.id,
@@ -51604,35 +51968,6 @@ async function removeScratch(fs, scratch) {
51604
51968
  await fs.deleteFile(scratch);
51605
51969
  } catch {}
51606
51970
  }
51607
- function runDecision(decisionId, item, evidencePath, maker) {
51608
- const command = process.env.KK_SPUR_BIN ?? "spur";
51609
- const args = [
51610
- "decision",
51611
- "run",
51612
- decisionId,
51613
- "--param",
51614
- `title=${item.title}`,
51615
- "--param",
51616
- `source=${item.source}`,
51617
- "--evidence",
51618
- evidencePath
51619
- ];
51620
- if (maker) {
51621
- args.push("--maker", maker);
51622
- }
51623
- args.push("--json");
51624
- const result = new NodeSyncProcessExecutor().runSync({
51625
- command,
51626
- args
51627
- });
51628
- if (result.exitCode !== 0)
51629
- return;
51630
- try {
51631
- return parseJson4(result.stdout);
51632
- } catch {
51633
- return;
51634
- }
51635
- }
51636
51971
  function labelDecision(decisionId) {
51637
51972
  return LABEL_DECISIONS.find((decision) => decision.id === decisionId);
51638
51973
  }
@@ -51739,19 +52074,17 @@ function keywordRow(item, term, runId, catalogVersion) {
51739
52074
  contentHash: item.contentHash
51740
52075
  };
51741
52076
  }
51742
- async function labelItem(fs, scratch, item, annotation, mode, maker, runId, catalogVersion, chinaPoliticsTerms) {
52077
+ async function labelItem(item, annotation, mode, maker, runId, catalogVersion, chinaPoliticsTerms, asker) {
51743
52078
  const routed = mode === "decision" || annotation?.needsModel === true;
51744
- const evidencePath = join21(scratch, `evidence-${item.id}.md`);
51745
- await fs.writeFile(evidencePath, item.body);
51746
52079
  let consults = 0;
51747
52080
  let consultMs = 0;
51748
52081
  const refused = {};
51749
52082
  const onRefusal = (key) => {
51750
52083
  refused[key] = (refused[key] ?? 0) + 1;
51751
52084
  };
51752
- const decide = (decisionId) => {
52085
+ const decide = async (decisionId) => {
51753
52086
  consults += 1;
51754
- const result = runDecision(decisionId, item, evidencePath, maker);
52087
+ const result = await asker.ask(decisionId, { title: item.title, source: item.source, body: item.body }, maker);
51755
52088
  consultMs += result?.durationMs ?? 0;
51756
52089
  return result;
51757
52090
  };
@@ -51763,20 +52096,20 @@ async function labelItem(fs, scratch, item, annotation, mode, maker, runId, cata
51763
52096
  rows.push(heuristicRow(decision.id, item, heuristic, runId, catalogVersion));
51764
52097
  if (heuristicAnnotated && !routed)
51765
52098
  continue;
52099
+ if (GRADED_DECISION_IDS.includes(decision.id) && mode !== "decision")
52100
+ continue;
51766
52101
  if (decision.id === CHINA_POLITICS_DECISION_ID) {
51767
52102
  const term = matchedChinaPoliticsTerm(item, chinaPoliticsTerms);
51768
52103
  if (term !== null)
51769
52104
  rows.push(keywordRow(item, term, runId, catalogVersion));
51770
52105
  }
51771
- const row = makerRow(decision.id, item, heuristic, decide(decision.id), maker, runId, catalogVersion, onRefusal);
52106
+ const row = makerRow(decision.id, item, heuristic, await decide(decision.id), maker, runId, catalogVersion, onRefusal);
51772
52107
  if (row !== null)
51773
52108
  rows.push(row);
51774
52109
  }
51775
52110
  return { rows, consults, consultMs, refused };
51776
52111
  }
51777
- async function replayItem(fs, scratch, item, decisionIds, maker, runId, catalogVersion) {
51778
- const evidencePath = join21(scratch, `evidence-${item.id}.md`);
51779
- await fs.writeFile(evidencePath, item.body);
52112
+ async function replayItem(item, decisionIds, maker, runId, catalogVersion, asker) {
51780
52113
  const rows = [];
51781
52114
  let consults = 0;
51782
52115
  let consultMs = 0;
@@ -51786,7 +52119,7 @@ async function replayItem(fs, scratch, item, decisionIds, maker, runId, catalogV
51786
52119
  };
51787
52120
  for (const decisionId of decisionIds) {
51788
52121
  consults += 1;
51789
- const result = runDecision(decisionId, item, evidencePath, maker);
52122
+ const result = await asker.ask(decisionId, { title: item.title, source: item.source, body: item.body }, maker);
51790
52123
  consultMs += result?.durationMs ?? 0;
51791
52124
  const row = makerRow(decisionId, item, null, result, maker, runId, catalogVersion, onRefusal);
51792
52125
  if (row !== null)
@@ -51822,7 +52155,7 @@ function parseDecisions(raw) {
51822
52155
  return ids;
51823
52156
  }
51824
52157
  async function readCatalogVersion(fs) {
51825
- const candidates = [resolve21(process.cwd(), CATALOG_PATH_REL), resolve21(CHECKOUT_ROOT3, CATALOG_PATH_REL)];
52158
+ const candidates = [resolve22(process.cwd(), CATALOG_PATH_REL), resolve22(CHECKOUT_ROOT3, CATALOG_PATH_REL)];
51826
52159
  for (const path of candidates) {
51827
52160
  try {
51828
52161
  if (!await fs.exists(path))
@@ -51860,7 +52193,7 @@ async function writeRows(store, rows) {
51860
52193
  }
51861
52194
  }
51862
52195
  var DEGRADED_FALLBACK_SHARE = 0.5;
51863
- async function labelNewIds(fs, store, runId, newIds, maker, mode, catalogVersion, scratch, chinaPoliticsTerms) {
52196
+ async function labelNewIds(fs, store, runId, newIds, maker, mode, catalogVersion, scratch, chinaPoliticsTerms, asker) {
51864
52197
  const ids = await readNewIds(fs, newIds);
51865
52198
  const items = await readLabelItems(store.items, ids);
51866
52199
  const annotations = await heuristicAnnotations(fs, scratch, runId, items);
@@ -51869,7 +52202,7 @@ async function labelNewIds(fs, store, runId, newIds, maker, mode, catalogVersion
51869
52202
  let consultMs = 0;
51870
52203
  const totalRefused = {};
51871
52204
  for (const item of items) {
51872
- const outcome = await labelItem(fs, scratch, item, annotations.get(item.id), mode, maker, runId, catalogVersion, chinaPoliticsTerms);
52205
+ const outcome = await labelItem(item, annotations.get(item.id), mode, maker, runId, catalogVersion, chinaPoliticsTerms, asker);
51873
52206
  rows.push(...outcome.rows);
51874
52207
  consults += outcome.consults;
51875
52208
  consultMs += outcome.consultMs;
@@ -51909,7 +52242,7 @@ async function replayItemIds(fs, store, selector, window, policy) {
51909
52242
  const query = compileProfile(profile, { windowMs: parseWindow2(window), now: Date.now() });
51910
52243
  return (await store.items.selectByProfile(query, policy)).map((doc) => doc.id);
51911
52244
  }
51912
- async function replaySelected(fs, store, selector, decisions, window, maker, catalogVersion, scratch, policy) {
52245
+ async function replaySelected(fs, store, selector, decisions, window, maker, catalogVersion, policy, asker) {
51913
52246
  const decisionIds = parseDecisions(decisions);
51914
52247
  const ids = await replayItemIds(fs, store, selector, window, policy);
51915
52248
  const items = await readLabelItems(store.items, ids);
@@ -51917,14 +52250,18 @@ async function replaySelected(fs, store, selector, decisions, window, maker, cat
51917
52250
  const rows = [];
51918
52251
  let consults = 0;
51919
52252
  let consultMs = 0;
52253
+ const refused = {};
51920
52254
  for (const item of items) {
51921
- const outcome = await replayItem(fs, scratch, item, decisionIds, maker, runId, catalogVersion);
52255
+ const outcome = await replayItem(item, decisionIds, maker, runId, catalogVersion, asker);
51922
52256
  rows.push(...outcome.rows);
51923
52257
  consults += outcome.consults;
51924
52258
  consultMs += outcome.consultMs;
52259
+ for (const [key, count] of Object.entries(outcome.refused)) {
52260
+ refused[key] = (refused[key] ?? 0) + count;
52261
+ }
51925
52262
  }
51926
52263
  await writeRows(store, rows);
51927
- consoleOutput.write(JSON.stringify({ replayed: items.length, consults, consultMs, run: runId }));
52264
+ consoleOutput.write(JSON.stringify({ replayed: items.length, labeled: rows.length, consults, consultMs, refused, run: runId }));
51928
52265
  }
51929
52266
  function parseLabelPlan(options) {
51930
52267
  const { newIds, run } = options;
@@ -51950,17 +52287,19 @@ async function labelAction(options) {
51950
52287
  const mode = parseLabelMode(options.mode);
51951
52288
  const configPath = resolveKkConfigPath();
51952
52289
  const dbPath = await resolveStorePath(configPath, options.db);
51953
- const scratch = join21(dirname12(plan.kind === "new-ids" ? plan.newIds : dbPath), LABEL_SCRATCH_DIR);
52290
+ const scratch = join22(dirname12(plan.kind === "new-ids" ? plan.newIds : dbPath), LABEL_SCRATCH_DIR);
51954
52291
  const store = await openStore({ path: dbPath });
51955
52292
  const catalogVersion = await readCatalogVersion(fs);
51956
52293
  const labels = (await readStoreConfig(configPath)).labels;
52294
+ const asker = await createItemDecisionAsker();
51957
52295
  try {
51958
52296
  if (plan.kind === "replay") {
51959
- await replaySelected(fs, store, plan.selector, options.decisions, options.window, plan.maker, catalogVersion, scratch, labels);
52297
+ await replaySelected(fs, store, plan.selector, options.decisions, options.window, plan.maker, catalogVersion, labels, asker);
51960
52298
  } else {
51961
- await labelNewIds(fs, store, plan.runId, plan.newIds, options.maker, mode, catalogVersion, scratch, labels.chinaPoliticsTerms);
52299
+ await labelNewIds(fs, store, plan.runId, plan.newIds, options.maker, mode, catalogVersion, scratch, labels.chinaPoliticsTerms, asker);
51962
52300
  }
51963
52301
  } finally {
52302
+ await asker.dispose();
51964
52303
  await store.close();
51965
52304
  await removeScratch(fs, scratch);
51966
52305
  }
@@ -51993,8 +52332,8 @@ async function resolveProfilePath(fs, topic) {
51993
52332
  throw new Error(`--topic must be a lowercase slug (e.g. ai-news), got '${topic}'`);
51994
52333
  }
51995
52334
  const candidates = [
51996
- resolve21(process.cwd(), PROFILE_DIR_REL, `${topic}.yaml`),
51997
- resolve21(CHECKOUT_ROOT3, PROFILE_DIR_REL, `${topic}.yaml`)
52335
+ resolve22(process.cwd(), PROFILE_DIR_REL, `${topic}.yaml`),
52336
+ resolve22(CHECKOUT_ROOT3, PROFILE_DIR_REL, `${topic}.yaml`)
51998
52337
  ];
51999
52338
  for (const path of candidates) {
52000
52339
  if (await fs.exists(path))