@pi-claudian/auto-save-to-markdown 0.2.0 → 0.3.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.
package/README.md CHANGED
@@ -88,12 +88,9 @@ The login page redirects in a loop after the auth refactor...
88
88
  Assistant · 13:05:40 · claude-sonnet-4-5
89
89
  ===
90
90
 
91
- <details>
92
- <summary>Thinking</summary>
93
-
94
- Let me check the redirect chain...
95
-
96
- </details>
91
+ > [!tldr]- Thinking
92
+ >
93
+ > Let me check the redirect chain...
97
94
 
98
95
  I'll trace the middleware order first.
99
96
 
@@ -106,10 +103,13 @@ I'll trace the middleware order first.
106
103
  ---
107
104
  ```
108
105
 
109
- The body renders user and assistant messages in full (assistant thinking is
110
- kept in a collapsible `<details>` block) and summarizes each tool call and
111
- result in one line, so the file stays readable while still showing what the
112
- agent did.
106
+ The body renders user and assistant messages in full (assistant thinking and
107
+ per-turn tool calls are each folded into a collapsed Obsidian callout —
108
+ `> [!tldr]- Thinking` and `> [!quote]- Tool Calls · …`) and summarizes each
109
+ tool call and result in one line, so the file stays readable while still
110
+ showing what the agent did. Callouts are used instead of HTML `<details>`
111
+ because Obsidian renders markdown inside HTML blocks unreliably; outside
112
+ Obsidian the callouts degrade to plain blockquotes.
113
113
 
114
114
  Each message block opens with a setext level-1 info header (`User · …`,
115
115
  underlined with `===`) — one level above the `##` headings AI content
package/README.zh.md CHANGED
@@ -78,12 +78,9 @@ auth 重构之后登录页一直重定向死循环……
78
78
  Assistant · 13:05:40 · claude-sonnet-4-5
79
79
  ===
80
80
 
81
- <details>
82
- <summary>Thinking</summary>
83
-
84
- 先看中间件的执行顺序……
85
-
86
- </details>
81
+ > [!tldr]- Thinking
82
+ >
83
+ > 先看中间件的执行顺序……
87
84
 
88
85
  我先追踪一下中间件链。
89
86
 
@@ -96,9 +93,12 @@ Assistant · 13:05:40 · claude-sonnet-4-5
96
93
  ---
97
94
  ```
98
95
 
99
- 正文完整渲染 user / assistant 消息(assistant 的 thinking 放在可折叠的
100
- `<details>` 块中),每个工具调用和结果各压缩成一行摘要,既可读又能看出
101
- agent 做了什么。
96
+ 正文完整渲染 user / assistant 消息(assistant 的 thinking 与每轮工具调用
97
+ 分别折叠在可折叠的 Obsidian callout 中——`> [!tldr]- Thinking` 和
98
+ `> [!quote]- Tool Calls · …`),每个工具调用和结果各压缩成一行摘要,既可读
99
+ 又能看出 agent 做了什么。之所以用 callout 而不是 HTML `<details>`,是因为
100
+ Obsidian 对 HTML 块内嵌 Markdown 的渲染不可靠;在非 Obsidian 环境下 callout
101
+ 退化为普通引用块。
102
102
 
103
103
  每个消息块以 setext 一级信息头(`User · …`,下一行以 `===` 下划)开头——
104
104
  高于 AI 内容常见的 `##` 二级标题,解析时也能与内容中的 `#` 一级标题区分
package/index.ts CHANGED
@@ -27,11 +27,14 @@
27
27
  * - Tool call/result folding: calls live in the assistant entry while their
28
28
  * results are separate toolResult entries; saves pair them by toolCall id
29
29
  * and fold each assistant block's calls, with a short result preview each,
30
- * into one `<details><summary>Tool Calls</summary>` section. Previews stay
31
- * short (500 chars): full content is one Obsidian link away, and oversized
32
- * details bodies render unfolded in Obsidian. A result whose call was
33
- * saved in an earlier file (mid-turn manual save) falls back to a
34
- * standalone one-line block.
30
+ * into one collapsed Obsidian callout (`> [!quote]- Tool Calls · …`).
31
+ * Thinking folds the same way into `> [!tldr]- Thinking`. Callouts are used
32
+ * instead of HTML `<details>` because Obsidian's views render embedded
33
+ * markdown inside HTML blocks unreliably, while callouts fold and render
34
+ * markdown in both Live Preview and Reading view. Outside Obsidian the
35
+ * callouts degrade to plain blockquotes. A result whose call was saved in
36
+ * an earlier file (mid-turn manual save) falls back to a standalone
37
+ * one-line block.
35
38
  * - Branching: each file records exactly ONE branch (the root→leaf path
36
39
  * returned by sessionManager.getBranch()). State is persisted via
37
40
  * `pi.appendEntry()` custom entries, which are part of the session tree
@@ -333,21 +336,25 @@ export default function (pi: ExtensionAPI) {
333
336
  }
334
337
 
335
338
  /**
336
- * Fold tool calls and their paired results into one collapsible section.
337
- * Deliberately compact: Obsidian only collapses a details body it can
338
- * render in view, so long previews make the section render unfolded.
339
+ * Collapsed Obsidian callout (`> [!type]- title`) wrapping a markdown body:
340
+ * every body line is prefixed with `>` (empty lines become bare `>`), so the
341
+ * body keeps rendering as markdown while folding works in both Obsidian
342
+ * views. Outside Obsidian the callout degrades to a plain blockquote.
339
343
  */
340
- function renderToolCallsDetails(calls: RenderedToolCall[]): string {
344
+ function callout(type: string, title: string, body: string): string {
345
+ const lines = body.split("\n").map((line) => (line ? `> ${line}` : ">"));
346
+ return `> [!${type}]- ${title}\n${lines.join("\n")}`;
347
+ }
348
+
349
+ /** Fold tool calls and their paired results into one collapsed callout. */
350
+ function renderToolCallsCallout(calls: RenderedToolCall[]): string {
341
351
  const summary = summarizeToolNames(calls.map((c) => c.name));
342
352
  const items = calls.map((c) => {
343
353
  const head = c.args ? `**\`${c.name}\`** \`${c.args}\`` : `**\`${c.name}\`**`;
344
354
  const result = c.result === null ? "_(no result)_" : c.result || "_(empty result)_";
345
355
  return `${head}\n\n> ${result}`;
346
356
  });
347
- return (
348
- `<details>\n<summary>Tool Calls · ${calls.length} (${summary})</summary>\n\n` +
349
- `${items.join("\n\n")}\n\n</details>`
350
- );
357
+ return callout("quote", `Tool Calls · ${calls.length} (${summary})`, items.join("\n\n"));
351
358
  }
352
359
 
353
360
  function renderAssistant(
@@ -364,9 +371,7 @@ export default function (pi: ExtensionAPI) {
364
371
  const thinkings: string[] = [];
365
372
  const flushThinking = () => {
366
373
  if (thinkings.length) {
367
- parts.push(
368
- `<details>\n<summary>Thinking</summary>\n\n${thinkings.join("\n\n")}\n\n</details>`,
369
- );
374
+ parts.push(callout("tldr", "Thinking", thinkings.join("\n\n")));
370
375
  thinkings.length = 0;
371
376
  }
372
377
  };
@@ -389,7 +394,7 @@ export default function (pi: ExtensionAPI) {
389
394
  }
390
395
  }
391
396
  flushThinking();
392
- if (calls.length) parts.push(renderToolCallsDetails(calls));
397
+ if (calls.length) parts.push(renderToolCallsCallout(calls));
393
398
  if (m.errorMessage) parts.push(`> Error: ${m.errorMessage.replace(/\s+/g, " ").trim()}`);
394
399
  if (parts.length === 0) parts.push("_(empty response)_");
395
400
  return `${header}\n\n${parts.join("\n\n")}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-claudian/auto-save-to-markdown",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Pi extension that automatically saves each completed conversation turn as a markdown file with YAML frontmatter, one file per session-tree branch.",
5
5
  "type": "module",
6
6
  "license": "MIT",