@hasna/todos 0.11.45 → 0.11.46

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 (57) hide show
  1. package/README.md +125 -3
  2. package/dist/cli/commands/config-serve-commands.d.ts.map +1 -1
  3. package/dist/cli/commands/help-commands.d.ts +3 -0
  4. package/dist/cli/commands/help-commands.d.ts.map +1 -0
  5. package/dist/cli/commands/local-backup-commands.d.ts +3 -0
  6. package/dist/cli/commands/local-backup-commands.d.ts.map +1 -0
  7. package/dist/cli/commands/mcp-hooks-commands.d.ts.map +1 -1
  8. package/dist/cli/commands/query-commands.d.ts.map +1 -1
  9. package/dist/cli/commands/scale-hardening-commands.d.ts +3 -0
  10. package/dist/cli/commands/scale-hardening-commands.d.ts.map +1 -0
  11. package/dist/cli/commands/usage-ledger-commands.d.ts +3 -0
  12. package/dist/cli/commands/usage-ledger-commands.d.ts.map +1 -0
  13. package/dist/cli/components/Dashboard.d.ts.map +1 -1
  14. package/dist/cli/index.js +3822 -547
  15. package/dist/cli-mcp-parity.d.ts +1 -1
  16. package/dist/cli-mcp-parity.d.ts.map +1 -1
  17. package/dist/contracts.d.ts +6 -0
  18. package/dist/contracts.d.ts.map +1 -1
  19. package/dist/contracts.js +1506 -24
  20. package/dist/db/agent-names.d.ts +2 -1
  21. package/dist/db/agent-names.d.ts.map +1 -1
  22. package/dist/db/schema.d.ts.map +1 -1
  23. package/dist/db/task-runs.d.ts +3 -0
  24. package/dist/db/task-runs.d.ts.map +1 -1
  25. package/dist/index.d.ts +16 -2
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +2822 -282
  28. package/dist/json-contracts.d.ts.map +1 -1
  29. package/dist/lib/cli-help.d.ts +38 -0
  30. package/dist/lib/cli-help.d.ts.map +1 -0
  31. package/dist/lib/config.d.ts +38 -0
  32. package/dist/lib/config.d.ts.map +1 -1
  33. package/dist/lib/local-backups.d.ts +129 -0
  34. package/dist/lib/local-backups.d.ts.map +1 -0
  35. package/dist/lib/local-extensions.d.ts +18 -1
  36. package/dist/lib/local-extensions.d.ts.map +1 -1
  37. package/dist/lib/local-reports.d.ts +149 -0
  38. package/dist/lib/local-reports.d.ts.map +1 -0
  39. package/dist/lib/redaction.d.ts.map +1 -1
  40. package/dist/lib/scale-hardening.d.ts +74 -0
  41. package/dist/lib/scale-hardening.d.ts.map +1 -0
  42. package/dist/lib/tui-dashboard.d.ts +49 -0
  43. package/dist/lib/tui-dashboard.d.ts.map +1 -0
  44. package/dist/lib/usage-ledger.d.ts +82 -0
  45. package/dist/lib/usage-ledger.d.ts.map +1 -0
  46. package/dist/lib/workflow-states.d.ts +70 -0
  47. package/dist/lib/workflow-states.d.ts.map +1 -0
  48. package/dist/mcp/index.js +8245 -6445
  49. package/dist/mcp/token-utils.d.ts.map +1 -1
  50. package/dist/mcp/tools/task-project-tools.d.ts.map +1 -1
  51. package/dist/mcp/tools/task-resources.d.ts.map +1 -1
  52. package/dist/mcp.js +12 -0
  53. package/dist/registry.js +1487 -24
  54. package/dist/server/index.js +152 -20
  55. package/dist/storage.js +164 -21
  56. package/package.json +1 -1
  57. package/dist/release-provenance.json +0 -7
@@ -1711,6 +1711,10 @@ function ensureSchema(db) {
1711
1711
  ensureColumn("dispatches", "machine_id", "TEXT");
1712
1712
  ensureColumn("dispatches", "synced_at", "TEXT");
1713
1713
  ensureIndex("CREATE INDEX IF NOT EXISTS idx_tasks_plan ON tasks(plan_id)");
1714
+ ensureIndex("CREATE INDEX IF NOT EXISTS idx_tasks_project ON tasks(project_id)");
1715
+ ensureIndex("CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status)");
1716
+ ensureIndex("CREATE INDEX IF NOT EXISTS idx_tasks_archived_at ON tasks(archived_at)");
1717
+ ensureIndex("CREATE INDEX IF NOT EXISTS idx_tasks_updated_at ON tasks(updated_at)");
1714
1718
  ensureIndex("CREATE INDEX IF NOT EXISTS idx_tasks_task_list ON tasks(task_list_id)");
1715
1719
  ensureIndex("CREATE INDEX IF NOT EXISTS idx_tasks_due_at ON tasks(due_at)");
1716
1720
  ensureIndex("CREATE INDEX IF NOT EXISTS idx_tasks_short_id ON tasks(short_id) WHERE short_id IS NOT NULL");
@@ -2939,6 +2943,15 @@ var DEFAULT_SECRET_PATTERNS = [
2939
2943
  { name: "bearer-token", regex: /\b(bearer)\s+[A-Za-z0-9._~+/=-]{12,}/gi, replacement: "$1 [REDACTED]" }
2940
2944
  ];
2941
2945
  var DEFAULT_SECRET_KEY_PATTERN = /api[_-]?key|token|secret|password/i;
2946
+ var NON_SECRET_USAGE_KEYS = new Set([
2947
+ "tokens",
2948
+ "total_tokens",
2949
+ "token_count",
2950
+ "input_tokens",
2951
+ "output_tokens",
2952
+ "prompt_tokens",
2953
+ "completion_tokens"
2954
+ ]);
2942
2955
  function unique(values) {
2943
2956
  return Array.from(new Set((values || []).map((value) => value.trim()).filter(Boolean)));
2944
2957
  }
@@ -2958,6 +2971,8 @@ function secretPatterns() {
2958
2971
  return [...customPatterns(), ...DEFAULT_SECRET_PATTERNS];
2959
2972
  }
2960
2973
  function isSecretKey(key) {
2974
+ if (NON_SECRET_USAGE_KEYS.has(key.toLowerCase()))
2975
+ return false;
2961
2976
  if (DEFAULT_SECRET_KEY_PATTERN.test(key))
2962
2977
  return true;
2963
2978
  return unique(loadConfig().secret_safety?.redaction_keys).some((pattern) => key.toLowerCase().includes(pattern.toLowerCase()));
@@ -4838,10 +4853,63 @@ var NICE_AGENT_NAMES = [
4838
4853
  "vesper",
4839
4854
  "zephyr"
4840
4855
  ];
4856
+ var EXTENDED_AGENT_NAMES = [
4857
+ "agrippa",
4858
+ "antonius",
4859
+ "aurelian",
4860
+ "aurelius",
4861
+ "camillus",
4862
+ "cassius",
4863
+ "celer",
4864
+ "cincinnatus",
4865
+ "corvus",
4866
+ "drusus",
4867
+ "fabius",
4868
+ "faustus",
4869
+ "flaccus",
4870
+ "gallus",
4871
+ "gaius",
4872
+ "horatius",
4873
+ "lucius",
4874
+ "lucullus",
4875
+ "marius",
4876
+ "marcellus",
4877
+ "maximus",
4878
+ "nerva",
4879
+ "pompey",
4880
+ "quintus",
4881
+ "regulus",
4882
+ "romulus",
4883
+ "scipio",
4884
+ "seneca",
4885
+ "sertorius",
4886
+ "sulla",
4887
+ "tacitus",
4888
+ "varro",
4889
+ "vitruvius",
4890
+ "plato",
4891
+ "socrates",
4892
+ "aristotle",
4893
+ "heraclitus",
4894
+ "democritus",
4895
+ "pythagoras",
4896
+ "hipparchus",
4897
+ "euclid",
4898
+ "archimedes",
4899
+ "zeno",
4900
+ "anaximander",
4901
+ "epictetus",
4902
+ "aeschylus",
4903
+ "sophocles",
4904
+ "euripides",
4905
+ "xenophon",
4906
+ "diogenes"
4907
+ ];
4841
4908
  var PREFERRED_AGENT_NAMES = [
4842
4909
  ...ROMAN_AGENT_NAMES,
4843
4910
  ...GREEK_AGENT_NAMES,
4844
- ...NICE_AGENT_NAMES
4911
+ ...NICE_AGENT_NAMES,
4912
+ ...EXTENDED_AGENT_NAMES
4845
4913
  ];
4846
4914
  var RESERVED_GENERIC_NAMES = new Set([
4847
4915
  "agent",
@@ -4879,29 +4947,93 @@ function isGenericAgentName(name) {
4879
4947
  }
4880
4948
  return false;
4881
4949
  }
4882
- function alphabeticSuffix(index) {
4883
- const letters = "abcdefghijklmnopqrstuvwxyz";
4884
- let value = index;
4885
- let suffix = "";
4886
- do {
4887
- suffix = letters[value % letters.length] + suffix;
4888
- value = Math.floor(value / letters.length) - 1;
4889
- } while (value >= 0);
4890
- return suffix;
4950
+ var FALLBACK_PREFIXES = [
4951
+ "arv",
4952
+ "bel",
4953
+ "cyr",
4954
+ "dax",
4955
+ "elun",
4956
+ "feno",
4957
+ "gavor",
4958
+ "hiro",
4959
+ "ivar",
4960
+ "jaro",
4961
+ "kavo",
4962
+ "lumo",
4963
+ "myr",
4964
+ "navo",
4965
+ "prax",
4966
+ "quor",
4967
+ "riven",
4968
+ "sovan",
4969
+ "tavor",
4970
+ "ulmor",
4971
+ "vexo",
4972
+ "wiro",
4973
+ "yaro",
4974
+ "zel"
4975
+ ];
4976
+ var FALLBACK_STEMS = [
4977
+ "al",
4978
+ "ber",
4979
+ "cor",
4980
+ "dren",
4981
+ "el",
4982
+ "far",
4983
+ "gor",
4984
+ "hal",
4985
+ "ion",
4986
+ "jor",
4987
+ "kel",
4988
+ "lor",
4989
+ "mor",
4990
+ "nel",
4991
+ "or",
4992
+ "per",
4993
+ "quil",
4994
+ "ron",
4995
+ "ser",
4996
+ "tor",
4997
+ "um",
4998
+ "ver",
4999
+ "wyn",
5000
+ "xil"
5001
+ ];
5002
+ var FALLBACK_ENDINGS = [
5003
+ "a",
5004
+ "en",
5005
+ "ia",
5006
+ "is",
5007
+ "on",
5008
+ "or",
5009
+ "um",
5010
+ "us",
5011
+ "yn",
5012
+ "ar",
5013
+ "el",
5014
+ "ir"
5015
+ ];
5016
+ function generatedFallbackAgentName(index) {
5017
+ const perPrefix = FALLBACK_STEMS.length * FALLBACK_ENDINGS.length;
5018
+ const total = FALLBACK_PREFIXES.length * perPrefix;
5019
+ if (index >= total)
5020
+ return null;
5021
+ const prefix = FALLBACK_PREFIXES[Math.floor(index / perPrefix)];
5022
+ const rest = index % perPrefix;
5023
+ const stem = FALLBACK_STEMS[Math.floor(rest / FALLBACK_ENDINGS.length)];
5024
+ const ending = FALLBACK_ENDINGS[rest % FALLBACK_ENDINGS.length];
5025
+ return `${prefix}${stem}${ending}`;
4891
5026
  }
4892
5027
  function suggestAgentNames(existingNames = []) {
4893
5028
  const existing = new Set([...existingNames].map(normalizeAgentNameInput));
4894
5029
  const suggestions = PREFERRED_AGENT_NAMES.filter((name) => !existing.has(name));
4895
- for (let suffixIndex = 0;suggestions.length < 20 && suffixIndex < 1000; suffixIndex++) {
4896
- const suffix = alphabeticSuffix(suffixIndex);
4897
- for (const base of PREFERRED_AGENT_NAMES) {
4898
- const candidate = `${base}${suffix}`;
4899
- if (existing.has(candidate) || suggestions.includes(candidate))
4900
- continue;
4901
- suggestions.push(candidate);
4902
- if (suggestions.length >= 20)
4903
- break;
4904
- }
5030
+ for (let index = 0;suggestions.length < 20; index++) {
5031
+ const candidate = generatedFallbackAgentName(index);
5032
+ if (!candidate)
5033
+ break;
5034
+ if (existing.has(candidate) || suggestions.includes(candidate))
5035
+ continue;
5036
+ suggestions.push(candidate);
4905
5037
  }
4906
5038
  return suggestions;
4907
5039
  }
package/dist/storage.js CHANGED
@@ -1839,6 +1839,10 @@ function ensureSchema(db) {
1839
1839
  ensureColumn("dispatches", "machine_id", "TEXT");
1840
1840
  ensureColumn("dispatches", "synced_at", "TEXT");
1841
1841
  ensureIndex("CREATE INDEX IF NOT EXISTS idx_tasks_plan ON tasks(plan_id)");
1842
+ ensureIndex("CREATE INDEX IF NOT EXISTS idx_tasks_project ON tasks(project_id)");
1843
+ ensureIndex("CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status)");
1844
+ ensureIndex("CREATE INDEX IF NOT EXISTS idx_tasks_archived_at ON tasks(archived_at)");
1845
+ ensureIndex("CREATE INDEX IF NOT EXISTS idx_tasks_updated_at ON tasks(updated_at)");
1842
1846
  ensureIndex("CREATE INDEX IF NOT EXISTS idx_tasks_task_list ON tasks(task_list_id)");
1843
1847
  ensureIndex("CREATE INDEX IF NOT EXISTS idx_tasks_due_at ON tasks(due_at)");
1844
1848
  ensureIndex("CREATE INDEX IF NOT EXISTS idx_tasks_short_id ON tasks(short_id) WHERE short_id IS NOT NULL");
@@ -2943,6 +2947,15 @@ var DEFAULT_SECRET_PATTERNS = [
2943
2947
  { name: "bearer-token", regex: /\b(bearer)\s+[A-Za-z0-9._~+/=-]{12,}/gi, replacement: "$1 [REDACTED]" }
2944
2948
  ];
2945
2949
  var DEFAULT_SECRET_KEY_PATTERN = /api[_-]?key|token|secret|password/i;
2950
+ var NON_SECRET_USAGE_KEYS = new Set([
2951
+ "tokens",
2952
+ "total_tokens",
2953
+ "token_count",
2954
+ "input_tokens",
2955
+ "output_tokens",
2956
+ "prompt_tokens",
2957
+ "completion_tokens"
2958
+ ]);
2946
2959
  function unique(values) {
2947
2960
  return Array.from(new Set((values || []).map((value) => value.trim()).filter(Boolean)));
2948
2961
  }
@@ -2962,6 +2975,8 @@ function secretPatterns() {
2962
2975
  return [...customPatterns(), ...DEFAULT_SECRET_PATTERNS];
2963
2976
  }
2964
2977
  function isSecretKey(key) {
2978
+ if (NON_SECRET_USAGE_KEYS.has(key.toLowerCase()))
2979
+ return false;
2965
2980
  if (DEFAULT_SECRET_KEY_PATTERN.test(key))
2966
2981
  return true;
2967
2982
  return unique(loadConfig().secret_safety?.redaction_keys).some((pattern) => key.toLowerCase().includes(pattern.toLowerCase()));
@@ -7066,7 +7081,18 @@ function addTaskRunCommand(input, db) {
7066
7081
  run_id: run.id,
7067
7082
  event_type: "command",
7068
7083
  message: `${status}: ${command}`,
7069
- data: { command, status, exit_code: input.exit_code ?? null, output_summary: outputSummary, artifact_path: artifactPath },
7084
+ data: {
7085
+ command,
7086
+ status,
7087
+ exit_code: input.exit_code ?? null,
7088
+ output_summary: outputSummary,
7089
+ artifact_path: artifactPath,
7090
+ usage: {
7091
+ tokens: input.tokens ?? null,
7092
+ cost_usd: input.cost_usd ?? null,
7093
+ duration_ms: input.duration_ms ?? null
7094
+ }
7095
+ },
7070
7096
  agent_id: input.agent_id ?? run.agent_id ?? undefined,
7071
7097
  created_at: timestamp
7072
7098
  }, d);
@@ -7629,10 +7655,63 @@ var NICE_AGENT_NAMES = [
7629
7655
  "vesper",
7630
7656
  "zephyr"
7631
7657
  ];
7658
+ var EXTENDED_AGENT_NAMES = [
7659
+ "agrippa",
7660
+ "antonius",
7661
+ "aurelian",
7662
+ "aurelius",
7663
+ "camillus",
7664
+ "cassius",
7665
+ "celer",
7666
+ "cincinnatus",
7667
+ "corvus",
7668
+ "drusus",
7669
+ "fabius",
7670
+ "faustus",
7671
+ "flaccus",
7672
+ "gallus",
7673
+ "gaius",
7674
+ "horatius",
7675
+ "lucius",
7676
+ "lucullus",
7677
+ "marius",
7678
+ "marcellus",
7679
+ "maximus",
7680
+ "nerva",
7681
+ "pompey",
7682
+ "quintus",
7683
+ "regulus",
7684
+ "romulus",
7685
+ "scipio",
7686
+ "seneca",
7687
+ "sertorius",
7688
+ "sulla",
7689
+ "tacitus",
7690
+ "varro",
7691
+ "vitruvius",
7692
+ "plato",
7693
+ "socrates",
7694
+ "aristotle",
7695
+ "heraclitus",
7696
+ "democritus",
7697
+ "pythagoras",
7698
+ "hipparchus",
7699
+ "euclid",
7700
+ "archimedes",
7701
+ "zeno",
7702
+ "anaximander",
7703
+ "epictetus",
7704
+ "aeschylus",
7705
+ "sophocles",
7706
+ "euripides",
7707
+ "xenophon",
7708
+ "diogenes"
7709
+ ];
7632
7710
  var PREFERRED_AGENT_NAMES = [
7633
7711
  ...ROMAN_AGENT_NAMES,
7634
7712
  ...GREEK_AGENT_NAMES,
7635
- ...NICE_AGENT_NAMES
7713
+ ...NICE_AGENT_NAMES,
7714
+ ...EXTENDED_AGENT_NAMES
7636
7715
  ];
7637
7716
  var RESERVED_GENERIC_NAMES = new Set([
7638
7717
  "agent",
@@ -7674,29 +7753,93 @@ function isBlockedAgentName(name) {
7674
7753
  const normalized = normalizeAgentNameInput(name);
7675
7754
  return isGenericAgentName(normalized) || hasGeneratedNumericSuffix(normalized) || !ONE_WORD_NAME_RE.test(normalized);
7676
7755
  }
7677
- function alphabeticSuffix(index) {
7678
- const letters = "abcdefghijklmnopqrstuvwxyz";
7679
- let value = index;
7680
- let suffix = "";
7681
- do {
7682
- suffix = letters[value % letters.length] + suffix;
7683
- value = Math.floor(value / letters.length) - 1;
7684
- } while (value >= 0);
7685
- return suffix;
7756
+ var FALLBACK_PREFIXES = [
7757
+ "arv",
7758
+ "bel",
7759
+ "cyr",
7760
+ "dax",
7761
+ "elun",
7762
+ "feno",
7763
+ "gavor",
7764
+ "hiro",
7765
+ "ivar",
7766
+ "jaro",
7767
+ "kavo",
7768
+ "lumo",
7769
+ "myr",
7770
+ "navo",
7771
+ "prax",
7772
+ "quor",
7773
+ "riven",
7774
+ "sovan",
7775
+ "tavor",
7776
+ "ulmor",
7777
+ "vexo",
7778
+ "wiro",
7779
+ "yaro",
7780
+ "zel"
7781
+ ];
7782
+ var FALLBACK_STEMS = [
7783
+ "al",
7784
+ "ber",
7785
+ "cor",
7786
+ "dren",
7787
+ "el",
7788
+ "far",
7789
+ "gor",
7790
+ "hal",
7791
+ "ion",
7792
+ "jor",
7793
+ "kel",
7794
+ "lor",
7795
+ "mor",
7796
+ "nel",
7797
+ "or",
7798
+ "per",
7799
+ "quil",
7800
+ "ron",
7801
+ "ser",
7802
+ "tor",
7803
+ "um",
7804
+ "ver",
7805
+ "wyn",
7806
+ "xil"
7807
+ ];
7808
+ var FALLBACK_ENDINGS = [
7809
+ "a",
7810
+ "en",
7811
+ "ia",
7812
+ "is",
7813
+ "on",
7814
+ "or",
7815
+ "um",
7816
+ "us",
7817
+ "yn",
7818
+ "ar",
7819
+ "el",
7820
+ "ir"
7821
+ ];
7822
+ function generatedFallbackAgentName(index) {
7823
+ const perPrefix = FALLBACK_STEMS.length * FALLBACK_ENDINGS.length;
7824
+ const total = FALLBACK_PREFIXES.length * perPrefix;
7825
+ if (index >= total)
7826
+ return null;
7827
+ const prefix = FALLBACK_PREFIXES[Math.floor(index / perPrefix)];
7828
+ const rest = index % perPrefix;
7829
+ const stem = FALLBACK_STEMS[Math.floor(rest / FALLBACK_ENDINGS.length)];
7830
+ const ending = FALLBACK_ENDINGS[rest % FALLBACK_ENDINGS.length];
7831
+ return `${prefix}${stem}${ending}`;
7686
7832
  }
7687
7833
  function suggestAgentNames(existingNames = []) {
7688
7834
  const existing = new Set([...existingNames].map(normalizeAgentNameInput));
7689
7835
  const suggestions = PREFERRED_AGENT_NAMES.filter((name) => !existing.has(name));
7690
- for (let suffixIndex = 0;suggestions.length < 20 && suffixIndex < 1000; suffixIndex++) {
7691
- const suffix = alphabeticSuffix(suffixIndex);
7692
- for (const base of PREFERRED_AGENT_NAMES) {
7693
- const candidate = `${base}${suffix}`;
7694
- if (existing.has(candidate) || suggestions.includes(candidate))
7695
- continue;
7696
- suggestions.push(candidate);
7697
- if (suggestions.length >= 20)
7698
- break;
7699
- }
7836
+ for (let index = 0;suggestions.length < 20; index++) {
7837
+ const candidate = generatedFallbackAgentName(index);
7838
+ if (!candidate)
7839
+ break;
7840
+ if (existing.has(candidate) || suggestions.includes(candidate))
7841
+ continue;
7842
+ suggestions.push(candidate);
7700
7843
  }
7701
7844
  return suggestions;
7702
7845
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/todos",
3
- "version": "0.11.45",
3
+ "version": "0.11.46",
4
4
  "description": "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,7 +0,0 @@
1
- {
2
- "packageName": "@hasna/todos",
3
- "packageVersion": "0.11.45",
4
- "repository": "https://github.com/hasna/todos.git",
5
- "gitCommit": "a5e49ad803bae740cedd076cb94bb981541d8a3f",
6
- "generatedAt": "2026-05-22T05:05:05.186Z"
7
- }