@lawaty/lacode 1.3.0-beta.1 → 1.3.0-beta.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.
Files changed (2) hide show
  1. package/dist/tui.js +76 -6
  2. package/package.json +12 -2
package/dist/tui.js CHANGED
@@ -85,17 +85,17 @@ function createRecorder(deps) {
85
85
  const child = childHandle;
86
86
  const filePath = currentPath;
87
87
  if (!exited) {
88
- await new Promise((resolve) => {
88
+ await new Promise((resolve2) => {
89
89
  let done = false;
90
90
  let timer;
91
91
  const finish = () => {
92
92
  if (done) return;
93
93
  done = true;
94
94
  if (timer) clearTimeout(timer);
95
- if (resolveWait === resolve) resolveWait = null;
96
- resolve();
95
+ if (resolveWait === resolve2) resolveWait = null;
96
+ resolve2();
97
97
  };
98
- resolveWait = resolve;
98
+ resolveWait = resolve2;
99
99
  timer = setTimeout(() => {
100
100
  try {
101
101
  child.kill("SIGKILL");
@@ -821,6 +821,68 @@ function createVoiceClient(options, deps) {
821
821
  return client;
822
822
  }
823
823
 
824
+ // src/tui/timeline.tsx
825
+ import { createSignal, createEffect, onCleanup, For } from "solid-js";
826
+ import { readFileSync as readFileSync3 } from "node:fs";
827
+ import { homedir as homedir2 } from "node:os";
828
+ import { join as join3, resolve } from "node:path";
829
+ import { jsx, jsxs } from "@opentui/solid/jsx-runtime";
830
+ var registered = false;
831
+ var tui = async (api) => {
832
+ if (registered) return;
833
+ registered = true;
834
+ api.slots.register({
835
+ order: 150,
836
+ slots: {
837
+ sidebar_content(ctx, props) {
838
+ const [entries, setEntries] = createSignal([]);
839
+ const read = (id) => {
840
+ if (typeof id !== "string" || !/^[A-Za-z0-9_.-]+$/.test(id)) {
841
+ setEntries([]);
842
+ return;
843
+ }
844
+ const rawDir = process.env.LACODE_TIMELINE_DIR;
845
+ const dir = rawDir ? resolve(rawDir) : join3(homedir2(), ".local/share/opencode/lacode/timeline");
846
+ const file = join3(dir, id + ".jsonl");
847
+ try {
848
+ const raw = readFileSync3(file, "utf8");
849
+ const parsed = [];
850
+ for (const line of raw.split("\n")) {
851
+ const trimmed = line.trim();
852
+ if (!trimmed) continue;
853
+ try {
854
+ const obj = JSON.parse(trimmed);
855
+ if (obj && typeof obj.ts === "number" && typeof obj.text === "string") {
856
+ parsed.push(obj.text);
857
+ }
858
+ } catch {
859
+ }
860
+ }
861
+ setEntries(parsed.slice(-14).reverse());
862
+ } catch {
863
+ setEntries([]);
864
+ }
865
+ };
866
+ createEffect(() => {
867
+ const id = props.session_id;
868
+ read(id);
869
+ const timer = setInterval(() => read(id), 1e3);
870
+ onCleanup(() => clearInterval(timer));
871
+ });
872
+ return /* @__PURE__ */ jsxs("box", { flexDirection: "column", children: [
873
+ /* @__PURE__ */ jsx("text", { fg: ctx.theme.current.textMuted, children: "Timeline" }),
874
+ entries().length === 0 ? /* @__PURE__ */ jsx("text", { fg: ctx.theme.current.textMuted, children: "No timeline yet" }) : /* @__PURE__ */ jsx(For, { each: entries(), children: (text) => /* @__PURE__ */ jsx("text", { children: `\u2022 ${text}` }) })
875
+ ] });
876
+ }
877
+ }
878
+ });
879
+ };
880
+ var plugin = {
881
+ id: "lacode.timeline",
882
+ tui
883
+ };
884
+ var timeline_default = plugin;
885
+
824
886
  // src/tui/index.ts
825
887
  var DEFAULT_MODEL = "whisper-large-v3-turbo";
826
888
  var DEFAULT_LANGUAGE = "en";
@@ -1049,7 +1111,7 @@ async function answerWithText(api, opts, text, request) {
1049
1111
  const labels = answers.map((answer) => answer.join(", ")).filter((answer) => answer.length > 0).join("; ");
1050
1112
  toast(api, { variant: "success", message: labels });
1051
1113
  }
1052
- var tui = async (api, options) => {
1114
+ var tui2 = async (api, options) => {
1053
1115
  const opts = resolveOptions(options);
1054
1116
  if (!opts.enabled) return;
1055
1117
  daemonConnected = false;
@@ -1271,10 +1333,18 @@ var tui = async (api, options) => {
1271
1333
  bindings.push({ key: opts.answerKey, cmd: "lacode.voice.answer", desc: "Voice answer" });
1272
1334
  }
1273
1335
  api.keymap.registerLayer({ mode: "base", commands, bindings });
1336
+ const timelineOpts = options ?? {};
1337
+ const timelineOff = timelineOpts.timeline === false || typeof timelineOpts.timeline === "object" && timelineOpts.timeline !== null && timelineOpts.timeline.enabled === false;
1338
+ if (!timelineOff) {
1339
+ try {
1340
+ await timeline_default.tui(api, options);
1341
+ } catch {
1342
+ }
1343
+ }
1274
1344
  };
1275
1345
  var mod = {
1276
1346
  id: "lacode.voice",
1277
- tui
1347
+ tui: tui2
1278
1348
  };
1279
1349
  var index_default = mod;
1280
1350
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lawaty/lacode",
3
- "version": "1.3.0-beta.1",
3
+ "version": "1.3.0-beta.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",
@@ -64,7 +64,17 @@
64
64
  "esbuild": "^0.28.2"
65
65
  },
66
66
  "peerDependencies": {
67
- "@opencode-ai/plugin": "1.18.34"
67
+ "@opencode-ai/plugin": "1.18.34",
68
+ "solid-js": "*",
69
+ "@opentui/solid": "*"
70
+ },
71
+ "peerDependenciesMeta": {
72
+ "solid-js": {
73
+ "optional": true
74
+ },
75
+ "@opentui/solid": {
76
+ "optional": true
77
+ }
68
78
  },
69
79
  "optionalDependencies": {
70
80
  "@picovoice/porcupine-node": "^4.0.2",