lazyclaw 5.4.4 → 6.0.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.
Files changed (91) hide show
  1. package/channels/handoff.mjs +36 -0
  2. package/channels-discord/index.mjs +76 -0
  3. package/channels-discord/package.json +14 -0
  4. package/channels-email/index.mjs +109 -0
  5. package/channels-email/package.json +14 -0
  6. package/channels-signal/index.mjs +69 -0
  7. package/channels-signal/package.json +9 -0
  8. package/channels-voice/index.mjs +81 -0
  9. package/channels-voice/package.json +9 -0
  10. package/channels-whatsapp/index.mjs +70 -0
  11. package/channels-whatsapp/package.json +13 -0
  12. package/cli.mjs +73 -7399
  13. package/commands/agents.mjs +669 -0
  14. package/commands/auth_nodes.mjs +323 -0
  15. package/commands/automation.mjs +582 -0
  16. package/commands/channels.mjs +255 -0
  17. package/commands/chat.mjs +1217 -0
  18. package/commands/config.mjs +315 -0
  19. package/commands/daemon.mjs +260 -0
  20. package/commands/misc.mjs +128 -0
  21. package/commands/providers.mjs +511 -0
  22. package/commands/sessions.mjs +343 -0
  23. package/commands/setup.mjs +741 -0
  24. package/commands/skills.mjs +218 -0
  25. package/commands/workflow.mjs +661 -0
  26. package/daemon/lib/auth.mjs +58 -0
  27. package/daemon/lib/cost.mjs +30 -0
  28. package/daemon/lib/provider.mjs +69 -0
  29. package/daemon/lib/respond.mjs +83 -0
  30. package/daemon/route_table.mjs +96 -0
  31. package/daemon/routes/_deps.mjs +36 -0
  32. package/daemon/routes/config.mjs +99 -0
  33. package/daemon/routes/conversation.mjs +371 -0
  34. package/daemon/routes/meta.mjs +239 -0
  35. package/daemon/routes/ops.mjs +185 -0
  36. package/daemon/routes/providers.mjs +211 -0
  37. package/daemon/routes/rates.mjs +90 -0
  38. package/daemon/routes/registry.mjs +223 -0
  39. package/daemon/routes/sessions.mjs +213 -0
  40. package/daemon/routes/skills.mjs +260 -0
  41. package/daemon/routes/workflows.mjs +224 -0
  42. package/daemon.mjs +23 -2085
  43. package/dotenv_min.mjs +23 -0
  44. package/first_run.mjs +15 -0
  45. package/goals_cron.mjs +37 -0
  46. package/lib/args.mjs +216 -0
  47. package/lib/config.mjs +113 -0
  48. package/lib/registry_boot.mjs +55 -0
  49. package/mas/agent_turn.mjs +2 -1
  50. package/mas/index_db.mjs +82 -0
  51. package/mas/learning.mjs +17 -1
  52. package/mas/mention_router.mjs +38 -10
  53. package/mas/provider_adapters.mjs +28 -4
  54. package/mas/scrub_env.mjs +34 -0
  55. package/mas/tool_runner.mjs +23 -7
  56. package/mas/tools/bash.mjs +10 -5
  57. package/mas/tools/browser.mjs +18 -0
  58. package/mas/tools/learning.mjs +24 -14
  59. package/mas/tools/recall.mjs +5 -1
  60. package/mas/tools/web.mjs +47 -11
  61. package/mas/trajectory_store.mjs +7 -4
  62. package/package.json +16 -2
  63. package/providers/auth_store.mjs +22 -0
  64. package/providers/claude_cli.mjs +28 -2
  65. package/providers/claude_cli_detect.mjs +46 -0
  66. package/providers/custom_provider.mjs +70 -0
  67. package/providers/model_catalogue.mjs +86 -0
  68. package/providers/orchestrator.mjs +30 -9
  69. package/providers/rates.mjs +12 -2
  70. package/providers/registry.mjs +10 -7
  71. package/sandbox/confiners/landlock.mjs +14 -8
  72. package/sandbox/confiners/seatbelt.mjs +18 -2
  73. package/scripts/loop-worker.mjs +18 -7
  74. package/scripts/migrate-v5.mjs +5 -61
  75. package/secure_write.mjs +46 -0
  76. package/sessions.mjs +0 -0
  77. package/tui/modal_filter.mjs +59 -0
  78. package/tui/modal_picker.mjs +12 -37
  79. package/tui/pickers.mjs +917 -0
  80. package/tui/provider_families.mjs +41 -0
  81. package/tui/repl.mjs +67 -36
  82. package/tui/slash_commands.mjs +2 -1
  83. package/tui/slash_dispatcher.mjs +717 -58
  84. package/tui/splash.mjs +5 -12
  85. package/tui/subcommands.mjs +17 -0
  86. package/tui/terminal_approve.mjs +37 -0
  87. package/web/dashboard.css +275 -0
  88. package/web/dashboard.html +2 -1685
  89. package/web/dashboard.js +1406 -0
  90. package/workflow/persistent.mjs +13 -6
  91. package/mas/tools/skill_view.mjs +0 -43
@@ -7,6 +7,8 @@ import fs from 'node:fs';
7
7
  import path from 'node:path';
8
8
  import { performance } from 'node:perf_hooks';
9
9
  import { topologicalLevels, retryWithBackoff, runWithTimeout, settleWithConcurrency } from './executor.mjs';
10
+ // Workflow state can carry transcript content; persist it owner-only (0600).
11
+ import { writeJsonSecure } from '../secure_write.mjs';
10
12
 
11
13
  const DEFAULT_DIR = '.workflow-state';
12
14
 
@@ -46,7 +48,15 @@ export function statePath(sessionId, dir = DEFAULT_DIR) {
46
48
  export function loadState(sessionId, dir = DEFAULT_DIR) {
47
49
  const p = statePath(sessionId, dir);
48
50
  if (!fs.existsSync(p)) return null;
49
- return JSON.parse(fs.readFileSync(p, 'utf8'));
51
+ // A corrupt/truncated state file (kill -9 mid-write, disk-full, hand-edit)
52
+ // must not crash `inspect`/`resume` with a raw SyntaxError — treat it as
53
+ // "no prior state" (start fresh), matching loops.readMeta / goals.getGoal.
54
+ try {
55
+ return JSON.parse(fs.readFileSync(p, 'utf8'));
56
+ } catch (e) {
57
+ process.stderr.write(`[workflow] ignoring unreadable state ${p}: ${e?.message || e}\n`);
58
+ return null;
59
+ }
50
60
  }
51
61
 
52
62
  /**
@@ -54,12 +64,9 @@ export function loadState(sessionId, dir = DEFAULT_DIR) {
54
64
  * @param {string} [dir]
55
65
  */
56
66
  export function saveState(state, dir = DEFAULT_DIR) {
57
- fs.mkdirSync(dir, { recursive: true });
58
67
  state.updatedAt = Date.now();
59
- const p = statePath(state.sessionId, dir);
60
- const tmp = `${p}.tmp`;
61
- fs.writeFileSync(tmp, JSON.stringify(state, null, 2));
62
- fs.renameSync(tmp, p);
68
+ // Atomic owner-only write (tmp + rename + 0600), same as the gateway store.
69
+ writeJsonSecure(statePath(state.sessionId, dir), state);
63
70
  }
64
71
 
65
72
  function initState(sessionId, nodes) {
@@ -1,43 +0,0 @@
1
- // skill_view tool — Phase 20.
2
- //
3
- // Read-only progressive-disclosure loader: the mention-router injects a
4
- // compact skills *index* (name + one-line summary) into the system
5
- // prompt, and the agent calls skill_view to pull the FULL text of a
6
- // skill only when it decides one is relevant. This keeps skill bodies
7
- // out of the prompt until they're actually needed.
8
- //
9
- // Unlike bash/read/write/grep this tool is rooted at the lazyclaw
10
- // config dir (where skills live), not the task cwd, so it takes
11
- // configDir from the tool-runner opts rather than cwd.
12
-
13
- import * as skills from '../../skills.mjs';
14
-
15
- export const NAME = 'skill_view';
16
- export const DESCRIPTION =
17
- 'Load the full text of a named skill from the skills index (its When-to-Use, Procedure, Pitfalls and Verification sections). Call this when a skill listed in the index looks relevant to the current task.';
18
- export const PARAMETERS = {
19
- type: 'object',
20
- properties: {
21
- name: { type: 'string', description: 'The skill name exactly as shown in the skills index.' },
22
- },
23
- required: ['name'],
24
- };
25
-
26
- export async function exec(args, { configDir } = {}) {
27
- if (!args || typeof args.name !== 'string' || !args.name.trim()) {
28
- return { ok: false, error: 'skill_view: name is required' };
29
- }
30
- const name = args.name.trim();
31
- try {
32
- const content = skills.loadSkill(name, configDir);
33
- // Record the recall so the curator can age out never-used skills.
34
- // Best-effort: a usage-write hiccup must never fail the tool call.
35
- try {
36
- const curator = await import('../../skills_curator.mjs');
37
- curator.recordUsage(name, configDir, Date.now());
38
- } catch { /* non-fatal */ }
39
- return { ok: true, name, content };
40
- } catch (err) {
41
- return { ok: false, error: `skill_view: ${err?.message || err}` };
42
- }
43
- }