@lawaty/lacode 1.0.0 → 1.0.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.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,45 @@ All notable changes to LaCode are recorded here. The format follows
7
7
  Versions come from git release commits; the npm version is bumped in the same
8
8
  commit as the changelog entry it describes.
9
9
 
10
+ ## [1.0.2] — the permission chime plays when the popup appears
11
+
12
+ ### Fixed
13
+
14
+ - **An actionable notification no longer delays its sound until it is answered.**
15
+ `sendLocal()` played the chime after `notify-send` returned, but an actionable
16
+ send (`--action` implies `--wait`) blocks until the user clicks a button or
17
+ dismisses the popup. The chime therefore played at click time — and never at
18
+ all when the popup was left alone — which made permission sounds look
19
+ intermittent. The sound now starts before the notifier runs, and a test pins
20
+ the order with a blocking fake notifier.
21
+
22
+ ## [1.0.1] — notification sounds you can hear, and a title that names the workspace
23
+
24
+ ### Fixed
25
+
26
+ - **Notification sounds play again.** The plugin preferred the bash `oc-notify`
27
+ helper, which discards the sound field, so a chime was never played on that
28
+ path; it now prefers the lacode CLI, whose `sendLocal` plays
29
+ `sounds/<outcome>.wav`. The bash helper stays as a last-resort fallback.
30
+ - **The four chimes survive a suspended sink.** Each WAV was 0.20–0.32 s at 42%
31
+ full-scale, which a suspended Bluetooth output swallowed whole while the link
32
+ woke. They are now 1.0–1.46 s at 90% peak, and a test pins both the duration
33
+ and the peak so the regression cannot return.
34
+ - **A popup no longer fades on its own.** `interacted` is scoped to the popup it
35
+ was set on: a new popup starts un-interacted and auto-dismisses only when the
36
+ user interacts in that session while it is live. Previously every popup in a
37
+ session the user had ever typed in closed after five seconds.
38
+ - **The published `bin` entry uses the `./dist/…` form** the packaging check
39
+ requires, so the release tarball passes its own adoption test.
40
+
41
+ ### Changed
42
+
43
+ - **Notification titles name the workspace as well as the session.** The title
44
+ is now `{workspace} - {session}`, where the workspace is the basename of the
45
+ session's directory, falling back to the plugin directory. The popup header
46
+ stays `LaCode`. Internal cartographer sessions are still suppressed, because
47
+ the check runs on the session title before the prefix is added.
48
+
10
49
  ## [1.0.0] — images, ordered slot fill, and a limit that fails over
11
50
 
12
51
  ### Added
package/dist/index.js CHANGED
@@ -3668,7 +3668,7 @@ import * as path3 from "node:path";
3668
3668
  // src/lib/notify.ts
3669
3669
  import { closeSync as closeSync2, mkdirSync as mkdirSync5, openSync as openSync2, readFileSync as readFileSync7, renameSync as renameSync4, statSync as statSync5, unlinkSync as unlinkSync4, writeFileSync as writeFileSync5, writeSync as writeSync2 } from "node:fs";
3670
3670
  import { homedir as homedir5 } from "node:os";
3671
- import { join as join7 } from "node:path";
3671
+ import { basename as basename3, join as join7 } from "node:path";
3672
3672
  var INTERNAL_TITLE_PREFIXES = [
3673
3673
  // context-autoupdate spawns the cartographer through the session API, with no
3674
3674
  // parentID, so it looks exactly like a root session going idle. Notifying for
@@ -3748,8 +3748,8 @@ var shouldNotify = (input) => {
3748
3748
  const { info, outcome, detail } = input;
3749
3749
  if (!info?.id) return { notify: false, reason: "no session info" };
3750
3750
  if (info.parentID) return { notify: false, reason: "subagent" };
3751
- const title = safeTitle(info.title);
3752
- if (INTERNAL_TITLE_PREFIXES.some((prefix) => title.startsWith(prefix))) {
3751
+ const sessionTitle = safeTitle(info.title);
3752
+ if (INTERNAL_TITLE_PREFIXES.some((prefix) => sessionTitle.startsWith(prefix))) {
3753
3753
  return { notify: false, reason: "internal session" };
3754
3754
  }
3755
3755
  if (info.time?.compacting) return { notify: false, reason: "compacting" };
@@ -3759,12 +3759,10 @@ var shouldNotify = (input) => {
3759
3759
  if (outcome === "done" && input.awaitingResponse) {
3760
3760
  return { notify: false, reason: "awaiting your response" };
3761
3761
  }
3762
+ const workspace = safeTitle(info.directory ? basename3(info.directory) : "", "");
3763
+ const title = workspace ? safeTitle(`${workspace} - ${sessionTitle}`, sessionTitle) : sessionTitle;
3762
3764
  const notification = {
3763
3765
  notify: true,
3764
- // The session's name on its own, with nothing in front of it. The popup's
3765
- // header is the notification's APP name, and that is "LaCode" -- so a
3766
- // prefix here would only repeat the app, and it would repeat it wrongly:
3767
- // the app is not "opencode".
3768
3766
  title,
3769
3767
  message: notifyMessage(outcome, detail),
3770
3768
  urgency: outcome === "error" ? "critical" : "normal"
@@ -4037,10 +4035,10 @@ var findHelper = () => {
4037
4035
  const candidates = [
4038
4036
  process.env.OC_NOTIFY_HELPER,
4039
4037
  path3.join(home, "bin", "lacode"),
4040
- path3.join(home, "bin", "oc-notify"),
4041
- path3.join(PACKAGE_ROOT, "bin", "oc-notify"),
4042
4038
  path3.join(PACKAGE_ROOT, "dist", "lacode.js"),
4043
- path3.join(PACKAGE_ROOT, "bin", "lacode")
4039
+ path3.join(PACKAGE_ROOT, "bin", "lacode"),
4040
+ path3.join(home, "bin", "oc-notify"),
4041
+ path3.join(PACKAGE_ROOT, "bin", "oc-notify")
4044
4042
  ].filter((candidate) => typeof candidate === "string" && candidate.length > 0);
4045
4043
  for (const candidate of candidates) if (existsSync3(candidate)) return candidate;
4046
4044
  return void 0;
@@ -4316,7 +4314,7 @@ var notifyHooks = (async ({ client, directory }, options, deps = {}) => {
4316
4314
  void log("debug", "session info unavailable; not notifying", { sessionID });
4317
4315
  return;
4318
4316
  }
4319
- const titled = info.title ? info : { ...info, title: titles.get(sessionID) };
4317
+ const titled = { ...info, title: info.title ?? titles.get(sessionID), directory: info.directory ?? directory };
4320
4318
  const isRemote = Boolean(process.env.SSH_CLIENT || process.env.SSH_TTY);
4321
4319
  const decision = shouldNotify({
4322
4320
  info: titled,
@@ -4355,8 +4353,7 @@ var notifyHooks = (async ({ client, directory }, options, deps = {}) => {
4355
4353
  }
4356
4354
  const message = isRemote ? `${decision.message} (remote)` : decision.message;
4357
4355
  const sound = soundOn && NOTIFY_OUTCOMES.includes(outcome) ? outcome : "none";
4358
- const previous = live.get(sessionID);
4359
- const popup = { raisedAt: Date.now(), interacted: previous?.interacted ?? false };
4356
+ const popup = { raisedAt: Date.now(), interacted: false };
4360
4357
  rememberLive(sessionID, popup);
4361
4358
  if (popup.interacted) scheduleDismiss(sessionID);
4362
4359
  let sent = { ok: false };
package/dist/lacode.js CHANGED
@@ -14,7 +14,7 @@ import { join as join4 } from "node:path";
14
14
  // src/lib/notify.ts
15
15
  import { closeSync, mkdirSync as mkdirSync2, openSync, readFileSync as readFileSync3, renameSync as renameSync2, statSync as statSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2, writeSync } from "node:fs";
16
16
  import { homedir as homedir2 } from "node:os";
17
- import { join as join3 } from "node:path";
17
+ import { basename, join as join3 } from "node:path";
18
18
 
19
19
  // src/lib/pool.ts
20
20
  import { existsSync, mkdirSync, readdirSync, readFileSync as readFileSync2, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
@@ -369,8 +369,8 @@ function sendLocal(request, platform = process.platform) {
369
369
  // Never auto-dismissed: the notification waits for the user to close it.
370
370
  [title, body, APP_NAME_FLAG, `--urgency=${normalizeUrgency(request.urgency)}`, `--icon=${normalizeIcon(request.icon)}`, NEVER_EXPIRE_FLAG, ...trackable ? ["--print-id"] : [], ...actionArgs]
371
371
  );
372
- const result = run(CHANNEL_BINARY[channel], args, actionable ? ACTION_WAIT_MS : 5e3);
373
372
  playSound();
373
+ const result = run(CHANNEL_BINARY[channel], args, actionable ? ACTION_WAIT_MS : 5e3);
374
374
  const printed = trackable ? splitNotifyOutput(result.stdout) : { id: "", action: result.stdout.trim() };
375
375
  const action = actionable ? printed.action : "";
376
376
  if (correlationKey !== void 0 && printed.id) recordNotificationId(correlationKey, printed.id);
package/dist/tunnel.js CHANGED
@@ -7,7 +7,7 @@ import { join as join4 } from "node:path";
7
7
  // src/lib/notify.ts
8
8
  import { closeSync, mkdirSync as mkdirSync2, openSync, readFileSync as readFileSync3, renameSync as renameSync2, statSync as statSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2, writeSync } from "node:fs";
9
9
  import { homedir as homedir2 } from "node:os";
10
- import { join as join3 } from "node:path";
10
+ import { basename, join as join3 } from "node:path";
11
11
 
12
12
  // src/lib/pool.ts
13
13
  import { existsSync, mkdirSync, readdirSync, readFileSync as readFileSync2, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
@@ -362,8 +362,8 @@ function sendLocal(request, platform = process.platform) {
362
362
  // Never auto-dismissed: the notification waits for the user to close it.
363
363
  [title, body, APP_NAME_FLAG, `--urgency=${normalizeUrgency(request.urgency)}`, `--icon=${normalizeIcon(request.icon)}`, NEVER_EXPIRE_FLAG, ...trackable ? ["--print-id"] : [], ...actionArgs]
364
364
  );
365
- const result = run(CHANNEL_BINARY[channel], args, actionable ? ACTION_WAIT_MS : 5e3);
366
365
  playSound();
366
+ const result = run(CHANNEL_BINARY[channel], args, actionable ? ACTION_WAIT_MS : 5e3);
367
367
  const printed = trackable ? splitNotifyOutput(result.stdout) : { id: "", action: result.stdout.trim() };
368
368
  const action = actionable ? printed.action : "";
369
369
  if (correlationKey !== void 0 && printed.id) recordNotificationId(correlationKey, printed.id);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lawaty/lacode",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Ultimate opencode setup for Go users — cost-controlled pooled subagents, hang recovery, and notifications for opencode.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -38,7 +38,7 @@
38
38
  "./package.json": "./package.json"
39
39
  },
40
40
  "bin": {
41
- "lacode": "dist/lacode.js"
41
+ "lacode": "./dist/lacode.js"
42
42
  },
43
43
  "files": [
44
44
  "dist",
package/sounds/done.wav CHANGED
Binary file
package/sounds/error.wav CHANGED
Binary file
Binary file
Binary file