@gavin-hu/my-pi-agent 0.13.1 → 0.14.0

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 (42) hide show
  1. package/README.md +14 -11
  2. package/README.zh-CN.md +12 -12
  3. package/extensions/bytefly/README.md +140 -58
  4. package/extensions/bytefly/doctor/config.ts +4 -1
  5. package/extensions/bytefly/footer/price/config.ts +3 -2
  6. package/extensions/bytefly/header/component.ts +30 -8
  7. package/extensions/bytefly/header/config.ts +22 -0
  8. package/extensions/bytefly/header/register.ts +2 -1
  9. package/extensions/bytefly/index.ts +3 -3
  10. package/extensions/bytefly/notify/config.ts +1 -1
  11. package/extensions/bytefly/panel/commands.ts +1 -1
  12. package/extensions/bytefly/panel/format.ts +12 -19
  13. package/extensions/bytefly/panel/settings-runtime.ts +62 -18
  14. package/extensions/bytefly/panel/settings.ts +239 -43
  15. package/extensions/bytefly/panel/tui/settings-view.ts +49 -3
  16. package/extensions/bytefly/panel/tui.ts +87 -19
  17. package/extensions/bytefly/separator/component.ts +7 -6
  18. package/extensions/bytefly/separator/config.ts +15 -0
  19. package/extensions/bytefly/separator/format.ts +60 -6
  20. package/extensions/bytefly/separator/register.ts +68 -9
  21. package/extensions/bytefly/separator/types.ts +8 -0
  22. package/extensions/bytefly/working/config.ts +4 -5
  23. package/extensions/bytefly/working/format.ts +24 -7
  24. package/extensions/bytefly/working/register.ts +34 -3
  25. package/extensions/memory/README.md +2 -0
  26. package/extensions/plan/README.md +12 -0
  27. package/extensions/subagent/README.md +60 -5
  28. package/extensions/subagent/config.ts +58 -0
  29. package/extensions/subagent/index.ts +27 -1
  30. package/extensions/subagent/orchestrate.ts +16 -3
  31. package/extensions/subagent/render.ts +12 -0
  32. package/extensions/subagent/run.ts +100 -37
  33. package/extensions/subagent/transcripts.ts +202 -0
  34. package/extensions/subagent/types.ts +12 -0
  35. package/extensions/watch/README.md +2 -0
  36. package/extensions/wechat/README.md +2 -0
  37. package/lib/README.md +1 -1
  38. package/lib/config.ts +33 -9
  39. package/lib/format.ts +6 -0
  40. package/package.json +2 -1
  41. package/themes/bytefly-dark.json +2 -3
  42. package/themes/bytefly-light.json +2 -3
package/lib/config.ts CHANGED
@@ -246,27 +246,51 @@ function setPath(source: Record<string, unknown>, path: readonly string[], value
246
246
  }
247
247
 
248
248
  /**
249
- * Delete one key from one top-level section, preserving its siblings and the
250
- * rest of the document. An emptied section is removed rather than left as `{}`.
251
- * A no-op when the file, section, or key is absent; refuses a malformed
252
- * document.
249
+ * Delete the leaf at `keyPath` from one top-level section, preserving every
250
+ * sibling key, every other section, and document metadata. An object left empty
251
+ * by the deletion goes with it, the section included, so a file does not fill
252
+ * with `{}` shells. A no-op when the file, section, or leaf is absent; refuses a
253
+ * malformed document and an empty path.
253
254
  */
254
- export function unsetConfigValue(path: string, section: string, key: string): void {
255
+ export function unsetConfigValueAt(path: string, section: string, keyPath: readonly string[]): void {
256
+ if (keyPath.length === 0) throw new Error(`Cannot update ${path}: empty key path`);
255
257
  const result = readJsonResult(path);
256
258
  if (result.state === "absent") return;
257
259
  if (result.state === "error") throw new Error(`Cannot update ${path}: ${result.error}`);
258
260
 
259
261
  const document = result.value;
260
262
  const current = configSection(document, section);
261
- if (!current || !(key in current)) return;
263
+ if (!current) return;
262
264
 
263
- const next = { ...current };
264
- delete next[key];
265
- if (Object.keys(next).length === 0) delete document[section];
265
+ const next = withoutPath(current, keyPath);
266
+ if (next === current) return;
267
+ if (next === undefined) delete document[section];
266
268
  else document[section] = next;
267
269
  writeConfigFile(path, document);
268
270
  }
269
271
 
272
+ /**
273
+ * Copy `source` without the leaf at `path`, or `undefined` once nothing is left.
274
+ * Returns `source` itself when the leaf is absent or sits behind a non-object,
275
+ * so the caller can tell "nothing to delete" from "a deletion happened".
276
+ */
277
+ function withoutPath(source: Record<string, unknown>, path: readonly string[]): Record<string, unknown> | undefined {
278
+ const [head, ...rest] = path;
279
+ if (head === undefined || !(head in source)) return source;
280
+ const next = { ...source };
281
+ if (rest.length === 0) {
282
+ delete next[head];
283
+ } else {
284
+ const child = asRecord(source[head]);
285
+ if (!child) return source;
286
+ const pruned = withoutPath(child, rest);
287
+ if (pruned === child) return source;
288
+ if (pruned === undefined) delete next[head];
289
+ else next[head] = pruned;
290
+ }
291
+ return Object.keys(next).length === 0 ? undefined : next;
292
+ }
293
+
270
294
  /** Write a whole config document atomically (sibling temp file, then rename). */
271
295
  export function writeConfigFile(path: string, document: Record<string, unknown>): void {
272
296
  mkdirSync(dirname(path), { recursive: true });
package/lib/format.ts CHANGED
@@ -49,6 +49,12 @@ export function formatDuration(ms: number): string {
49
49
  return `${hours}h${String(minutes % 60).padStart(2, "0")}m`;
50
50
  }
51
51
 
52
+ /** `1 tool`, `3 tools`: a tool count with the right word. */
53
+ export function formatToolCount(count: number): string {
54
+ const n = Number.isFinite(count) ? Math.max(0, Math.trunc(count)) : 0;
55
+ return `${formatCount(n)} ${n === 1 ? "tool" : "tools"}`;
56
+ }
57
+
52
58
  /**
53
59
  * Replace terminal control characters (including ESC and the C1 block) with
54
60
  * spaces, keeping `\n` and `\t` for callers that render multi-line text.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gavin-hu/my-pi-agent",
3
- "version": "0.13.1",
3
+ "version": "0.14.0",
4
4
  "description": "Personal Pi customizations, packaged as a Pi package: worktree isolation and rewind snapshots, question, todo, goal, plan, subagent, job, watch, web-access, file-browse, file-open, document, memory, wechat, and bytefly.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -105,6 +105,7 @@
105
105
  "config:migrate": "bun run scripts/migrate-config.ts",
106
106
  "compat:versions": "bun run scripts/peer-versions.ts",
107
107
  "bench:render": "bun run scripts/render-bench.ts",
108
+ "screenshot:file-browse": "bun run scripts/file-browse-shot.ts",
108
109
  "screenshot:plan": "bun run scripts/plan-review-shot.ts",
109
110
  "screenshot:tools": "bun run scripts/tool-renderings.ts gallery assets/tool-renderings.png",
110
111
  "screenshot:tool-pngs": "bun run scripts/tool-renderings.ts tools assets/tools",
@@ -17,7 +17,6 @@
17
17
  "purple": "#bc8cff",
18
18
  "pink": "#f778ba",
19
19
  "selectionBg": "#17273a",
20
- "customBg": "#26233a",
21
20
  "successBg": "#12271a",
22
21
  "errorBg": "#3d1a21",
23
22
  "searchBg": "#3d331a",
@@ -43,9 +42,9 @@
43
42
  "searchMatchText": "text",
44
43
  "userMessageBg": "",
45
44
  "userMessageText": "text",
46
- "customMessageBg": "customBg",
45
+ "customMessageBg": "",
47
46
  "customMessageText": "muted",
48
- "customMessageLabel": "purple",
47
+ "customMessageLabel": "blue",
49
48
  "toolPendingBg": "canvasSubtle",
50
49
  "toolSuccessBg": "successBg",
51
50
  "toolErrorBg": "errorBg",
@@ -16,7 +16,6 @@
16
16
  "yellow": "#9a6700",
17
17
  "purple": "#8250df",
18
18
  "pink": "#bf3989",
19
- "customBg": "#f5f1fd",
20
19
  "successBg": "#e9f6ed",
21
20
  "errorBg": "#fcf0f1",
22
21
  "selectionBg": "#e8f2fc",
@@ -43,9 +42,9 @@
43
42
  "searchMatchText": "text",
44
43
  "userMessageBg": "",
45
44
  "userMessageText": "text",
46
- "customMessageBg": "customBg",
45
+ "customMessageBg": "",
47
46
  "customMessageText": "muted",
48
- "customMessageLabel": "purple",
47
+ "customMessageLabel": "blue",
49
48
  "toolPendingBg": "canvasSubtle",
50
49
  "toolSuccessBg": "successBg",
51
50
  "toolErrorBg": "errorBg",