lazyclaw 6.9.0 → 6.9.2

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.
@@ -243,8 +243,8 @@ export async function cmdMessage(sub, positional, flags = {}) {
243
243
  process.exit(2);
244
244
  }
245
245
  try { m.messageAdd(cfg, name, url, flags.kind); writeConfig(cfg); }
246
- catch (e) { console.error(`error: ${e.message}`); process.exit(1); }
247
- console.log(JSON.stringify({ ok: true, name }));
246
+ catch (e) { console.error(`✗ ${e.message}`); process.exit(1); }
247
+ console.log(`✓ added "${name}" webhook.`);
248
248
  return;
249
249
  }
250
250
  case 'remove': {
@@ -254,8 +254,8 @@ export async function cmdMessage(sub, positional, flags = {}) {
254
254
  process.exit(2);
255
255
  }
256
256
  try { m.messageRemove(cfg, name); writeConfig(cfg); }
257
- catch (e) { console.error(`error: ${e.message}`); process.exit(1); }
258
- console.log(JSON.stringify({ ok: true, removed: name }));
257
+ catch (e) { console.error(`✗ ${e.message}`); process.exit(1); }
258
+ console.log(`✓ removed "${name}".`);
259
259
  return;
260
260
  }
261
261
  case 'send': {
@@ -280,9 +280,9 @@ export async function cmdMessage(sub, positional, flags = {}) {
280
280
  }
281
281
  try {
282
282
  const r = await m.messageSend(cfg, name, text);
283
- console.log(JSON.stringify(r));
283
+ console.log(`✓ sent to "${name}" (${r.kind}).`);
284
284
  } catch (e) {
285
- console.error(`error: ${e.message}`); process.exit(1);
285
+ console.error(`✗ ${e.message}`); process.exit(1);
286
286
  }
287
287
  return;
288
288
  }
package/commands/chat.mjs CHANGED
@@ -176,7 +176,8 @@ export async function cmdChat(flags = {}) {
176
176
  if (sys) _inkSysParts.push(sys);
177
177
  } catch (err) { console.error(`skill error: ${err.message}`); process.exit(2); }
178
178
  }
179
- if (_inkSysParts.length && !_inkMessages.some((m) => m.role === 'system')) {
179
+ // Always send the base guard system prompt (even on a fresh install).
180
+ if (!_inkMessages.some((m) => m.role === 'system')) {
180
181
  const merged = [..._inkSysParts, LAZYCLAW_META_GUARD].join('\n\n---\n\n');
181
182
  _inkMessages.unshift({ role: 'system', content: merged });
182
183
  if (_inkSessionId) sessionsMod.appendTurn(_inkSessionId, 'system', merged, _inkCfgDir);
@@ -456,7 +457,7 @@ export async function cmdChat(flags = {}) {
456
457
  process.exit(2);
457
458
  }
458
459
  }
459
- if (sysParts.length && !messages.some(m => m.role === 'system')) {
460
+ if (!messages.some(m => m.role === 'system')) {
460
461
  const merged = [...sysParts, LAZYCLAW_META_GUARD].join('\n\n---\n\n');
461
462
  messages.unshift({ role: 'system', content: merged });
462
463
  if (sessionId) sessionsMod.appendTurn(sessionId, 'system', merged, cfgDir);
@@ -216,7 +216,7 @@ export function messageRemove(cfg, name) {
216
216
  export async function messageSend(cfg, name, text, opts = {}) {
217
217
  const map = (cfg.messaging || {}).webhooks || {};
218
218
  const hook = map[name];
219
- if (!hook) throw new Error(`webhook "${name}" not configured add via \`lazyclaw message add\``);
219
+ if (!hook) throw new Error(`no "${name}" channel is configured. Set up Slack with \`lazyclaw setup\` (channel step), or add a webhook: \`lazyclaw message add ${name} <webhook-url>\``);
220
220
  const fetchFn = opts.fetch || globalThis.fetch;
221
221
  if (!fetchFn) throw new Error('no fetch implementation');
222
222
 
@@ -17,12 +17,17 @@ import { orchestratorGet, orchestratorSet, orchestratorEnable } from '../config_
17
17
  // and planner/worker swaps ARE applied for real by detectConfigCommand above;
18
18
  // everything else must be redirected to a command, not faked.
19
19
  export const LAZYCLAW_META_GUARD =
20
- 'You are running inside the lazyclaw CLI. You CANNOT change lazyclaw\'s own configuration ' +
21
- '(provider, orchestrator planner/workers, models, agents, teams) from this chat you have no tool for it. ' +
22
- 'If the user asks you to change a setting, do NOT claim you did it. Instead give the exact command: ' +
23
- '`/orchestrator off | planner <provider:model> | worker add <provider:model>`, `lazyclaw agent add …`, ' +
24
- '`lazyclaw team …`, or `lazyclaw config set <key> <value>`. ' +
25
- '(Plain-language orchestrator on/off and planner/worker model changes are applied automatically others are not.)';
20
+ 'You are a user-facing assistant inside the lazyclaw CLI. ' +
21
+ 'Do NOT fabricate command execution or results: never print a fenced ```bash/```sh/```shell/```console block as ' +
22
+ 'if you are about to run it, never claim you ran, are running, or "will run" a command you cannot actually ' +
23
+ 'execute (no "Running it now"), and never invent command output, exit/error codes, stack traces, or JSON. ' +
24
+ 'Use the tools you actually have and report the result in plain language. ' +
25
+ 'You CANNOT change lazyclaw\'s own configuration (provider, orchestrator planner/workers, models, agents, ' +
26
+ 'teams) from this chat — if the user asks, do NOT claim you did it; give the exact command as ONE short plain ' +
27
+ 'instruction line they can run themselves (e.g. "Run: lazyclaw message send <name> <text>", "Run: lazyclaw ' +
28
+ 'setup", `/orchestrator off | planner <provider:model> | worker add <provider:model>`, `lazyclaw agent add …`, ' +
29
+ '`lazyclaw config set <key> <value>`) — not as a block you pretend to execute. ' +
30
+ '(Plain-language orchestrator on/off and planner/worker model changes ARE applied automatically — others are not.)';
26
31
 
27
32
  const ORCH = /오케스트라|오케스트레이터|오케스트레이션|orchestrat/i;
28
33
  const OFF = /\boff\b|\bdisable\b|끄|꺼|비활성/i;
package/mas/index_db.mjs CHANGED
@@ -55,14 +55,15 @@ export function _isNativeAbiError(e) {
55
55
  .test(String(e?.message || e || ''));
56
56
  }
57
57
  export function _warnIndexFailure(label, e) {
58
+ // Index internals stay off the user's screen: recorded in index-failures.jsonl
59
+ // (+ surfaced by `lazyclaw doctor`); echoed to the console only when an
60
+ // operator sets LAZYCLAW_DEBUG. End users never see DB error codes.
61
+ if (!process.env.LAZYCLAW_DEBUG) return;
58
62
  if (_isNativeAbiError(e)) {
59
63
  if (_nativeHintShown) return;
60
64
  _nativeHintShown = true;
61
65
  // eslint-disable-next-line no-console
62
- console.warn(
63
- '[index_db] recall index disabled — better-sqlite3 was built for a different Node.js version.\n' +
64
- ' Re-enable it once with: npm rebuild better-sqlite3 (in the lazyclaw install dir),\n' +
65
- ' or reinstall deps with the Node you run lazyclaw with. Chat is unaffected.');
66
+ console.warn('[index_db] recall index disabled — better-sqlite3 ABI mismatch; run `npm rebuild better-sqlite3`.');
66
67
  return;
67
68
  }
68
69
  // eslint-disable-next-line no-console
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lazyclaw",
3
- "version": "6.9.0",
3
+ "version": "6.9.2",
4
4
  "description": "Lazy, elegant terminal CLI for chatting with Claude / OpenAI / Gemini / Ollama, orchestrating multi-step LLM workflows, and running multi-agent Slack teams with cross-task memory. Banner-on-launch, slash-command ghost autocomplete, persistent sessions, local HTTP gateway.",
5
5
  "keywords": [
6
6
  "claude",
@@ -47,12 +47,13 @@ export const mockProvider = {
47
47
  async *sendMessage(messages, opts = {}) {
48
48
  const last = messages[messages.length - 1];
49
49
  const sys = messages.find((m) => m.role === 'system')?.content || '';
50
- // When a system message is present, prefix the echo with [sys:...]
51
- // so callers (and especially tests) can verify what the provider
52
- // saw in the system slot. No system byte-identical to the prior
53
- // shape so existing assertions stay green.
50
+ // When a system message is present, prefix the echo with [sys:…] so tests
51
+ // can verify the provider saw a system slot. Keep it SHORT (tests only check
52
+ // the prefix) the always-on guard prompt is ~1k chars and echoing it all
53
+ // made every reply huge, timing out the 5ms/char stream (phase5-memory).
54
+ // No system → byte-identical to the prior shape so existing assertions stay green.
54
55
  const reply = sys
55
- ? `[sys:${String(sys).slice(0, 8000)}]\nmock-reply: ${last?.content ?? ''}`
56
+ ? `[sys:${String(sys).slice(0, 80)}]\nmock-reply: ${last?.content ?? ''}`
56
57
  : `mock-reply: ${last?.content ?? ''}`;
57
58
  // Honor opts.signal so the chat REPL's Ctrl+C handler (and any
58
59
  // other caller) can stop the stream mid-flight. The other concrete
@@ -17,7 +17,8 @@ export const BLINK_MS = 450;
17
17
  // Pure (takes the current blink phase) so it's unit-testable without a timer.
18
18
  export function streamingIndicator(streaming, blinkOn, t = theme) {
19
19
  if (!streaming) return t.dim('○ idle');
20
- return blinkOn ? t.accent('● streaming') : t.dim('● streaming');
20
+ // Pulse a GREEN dot while streaming (live/working), not the amber accent.
21
+ return blinkOn ? t.success('● streaming') : t.dim('● streaming');
21
22
  }
22
23
 
23
24
  export function StatusBar({ provider, model, streaming, ctxUsed, ctxTotal, hud }) {
package/tui/theme.mjs CHANGED
@@ -9,6 +9,7 @@ import chalk from 'chalk';
9
9
 
10
10
  const AMBER_HEX = '#FFB347';
11
11
  const BORDER_HEX = '#5A5A5A';
12
+ const GREEN_HEX = '#34D399'; // emerald — "live/working" (matches the dashboard ring)
12
13
 
13
14
  // Central color gate. Color is OFF when the NO_COLOR standard applies
14
15
  // (https://no-color.org — any non-empty NO_COLOR), the terminal is `dumb`,
@@ -50,6 +51,10 @@ function accent(text) {
50
51
  return chalk.bold.hex(AMBER_HEX)(text);
51
52
  }
52
53
 
54
+ function success(text) {
55
+ return chalk.bold.hex(GREEN_HEX)(text);
56
+ }
57
+
53
58
  function muted(text) {
54
59
  return chalk.gray(text);
55
60
  }
@@ -65,6 +70,7 @@ export const theme = {
65
70
  colorize: amber,
66
71
  dim,
67
72
  accent,
73
+ success,
68
74
  muted,
69
75
  plain,
70
76
  };