@pi-claudian/auto-save-to-markdown 0.3.0 → 0.3.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/README.md CHANGED
@@ -94,11 +94,10 @@ Assistant · 13:05:40 · claude-sonnet-4-5
94
94
 
95
95
  I'll trace the middleware order first.
96
96
 
97
- **Tool calls**
98
-
99
- - `read` — {"filePath":"/Users/me/project/src/auth/middleware.ts"}
100
-
101
- > **Tool · read** /Users/me/project/src/auth/middleware.ts — 120 lines …
97
+ > [!quote]- Tool Calls · 1 (read)
98
+ > **`read`** `{"filePath":"/Users/me/project/src/auth/middleware.ts"}`
99
+ >
100
+ > > `import { NextResponse } from "next/server"; export function middleware(…) …`
102
101
 
103
102
  ---
104
103
  ```
@@ -109,7 +108,10 @@ per-turn tool calls are each folded into a collapsed Obsidian callout —
109
108
  tool call and result in one line, so the file stays readable while still
110
109
  showing what the agent did. Callouts are used instead of HTML `<details>`
111
110
  because Obsidian renders markdown inside HTML blocks unreliably; outside
112
- Obsidian the callouts degrade to plain blockquotes.
111
+ Obsidian the callouts degrade to plain blockquotes. Result and argument
112
+ previews are wrapped in inline code spans (with a delimiter sized to survive
113
+ backticks inside the content), so raw tool output renders literally instead of
114
+ being parsed as markdown.
113
115
 
114
116
  Each message block opens with a setext level-1 info header (`User · …`,
115
117
  underlined with `===`) — one level above the `##` headings AI content
@@ -163,6 +165,10 @@ always contains the complete conversation, not the compacted context.
163
165
  PI_CLAUDIAN_DEBUG=1 pi
164
166
  ```
165
167
 
168
+ Any value other than an explicit false token (empty, `0`, `false`, `no`, `off` —
169
+ case-insensitive) enables it; unset the variable (or set one of those tokens)
170
+ to turn it off.
171
+
166
172
  ## License
167
173
 
168
174
  MIT
package/README.zh.md CHANGED
@@ -84,11 +84,10 @@ Assistant · 13:05:40 · claude-sonnet-4-5
84
84
 
85
85
  我先追踪一下中间件链。
86
86
 
87
- **Tool calls**
88
-
89
- - `read` — {"filePath":"/Users/me/project/src/auth/middleware.ts"}
90
-
91
- > **Tool · read** /Users/me/project/src/auth/middleware.ts — 120 lines …
87
+ > [!quote]- Tool Calls · 1 (read)
88
+ > **`read`** `{"filePath":"/Users/me/project/src/auth/middleware.ts"}`
89
+ >
90
+ > > `import { NextResponse } from "next/server"; export function middleware(…) …`
92
91
 
93
92
  ---
94
93
  ```
@@ -98,7 +97,9 @@ Assistant · 13:05:40 · claude-sonnet-4-5
98
97
  `> [!quote]- Tool Calls · …`),每个工具调用和结果各压缩成一行摘要,既可读
99
98
  又能看出 agent 做了什么。之所以用 callout 而不是 HTML `<details>`,是因为
100
99
  Obsidian 对 HTML 块内嵌 Markdown 的渲染不可靠;在非 Obsidian 环境下 callout
101
- 退化为普通引用块。
100
+ 退化为普通引用块。结果与参数预览会包在 inline code 里(分隔符长度会自动
101
+ 压过内容中的反引号序列),工具的原始输出因此按字面渲染,不会被当作
102
+ Markdown 解析。
102
103
 
103
104
  每个消息块以 setext 一级信息头(`User · …`,下一行以 `===` 下划)开头——
104
105
  高于 AI 内容常见的 `##` 二级标题,解析时也能与内容中的 `#` 一级标题区分
@@ -143,6 +144,9 @@ markdown 文件只记录**一个分支**——即该分支看到的 root→leaf
143
144
  PI_CLAUDIAN_DEBUG=1 pi
144
145
  ```
145
146
 
147
+ 除显式假值(空串、`0`、`false`、`no`、`off`,忽略大小写)以外的任何值都会开启
148
+ 调试;取消该变量或将其设为其中某个假值即可关闭。
149
+
146
150
  ## 许可
147
151
 
148
152
  MIT
package/debug.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  /**
2
2
  * Shared debug logging for all @pi-claudian extensions.
3
3
  *
4
- * Enable by setting the PI_CLAUDIAN_DEBUG environment variable to any truthy
5
- * value (e.g. "1"). Output goes to stderr via console.error, so it never mixes
6
- * with pi's stdout and can be captured separately:
4
+ * Enable by setting the PI_CLAUDIAN_DEBUG environment variable to any value
5
+ * other than an explicit false token (empty, "0", "false", "no", "off" —
6
+ * case-insensitive). Output goes to stderr via console.error, so it never
7
+ * mixes with pi's stdout and can be captured separately:
7
8
  *
8
9
  * PI_CLAUDIAN_DEBUG=1 pi # show inline
9
10
  * PI_CLAUDIAN_DEBUG=1 pi 2>debug.log # capture to a file
@@ -15,9 +16,11 @@
15
16
  */
16
17
 
17
18
  const TAG = "[pi-claudian]";
18
- const enabled = Boolean(process.env.PI_CLAUDIAN_DEBUG);
19
+ const FALSE_TOKENS = new Set(["", "0", "false", "no", "off"]);
20
+ const raw = process.env.PI_CLAUDIAN_DEBUG?.trim().toLowerCase();
21
+ const enabled = raw !== undefined && !FALSE_TOKENS.has(raw);
19
22
 
20
- /** Log a debug message when PI_CLAUDIAN_DEBUG is set. */
23
+ /** Log a debug message when PI_CLAUDIAN_DEBUG is set to an enabling value. */
21
24
  export function debug(...args: unknown[]): void {
22
25
  if (!enabled) return;
23
26
  console.error(TAG, ...args);
package/index.ts CHANGED
@@ -32,7 +32,10 @@
32
32
  * instead of HTML `<details>` because Obsidian's views render embedded
33
33
  * markdown inside HTML blocks unreliably, while callouts fold and render
34
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
35
+ * callouts degrade to plain blockquotes. Argument previews and result
36
+ * previews are wrapped in inline code spans (delimiter sized to survive
37
+ * backticks inside the content), so raw output renders literally instead
38
+ * of being parsed as markdown. A result whose call was saved in
36
39
  * an earlier file (mid-turn manual save) falls back to a standalone
37
40
  * one-line block.
38
41
  * - Branching: each file records exactly ONE branch (the root→leaf path
@@ -293,6 +296,19 @@ export default function (pi: ExtensionAPI) {
293
296
 
294
297
  // ---------- markdown rendering ----------
295
298
 
299
+ /**
300
+ * Inline code span for arbitrary raw output (tool results, argument JSON):
301
+ * the delimiter is always one backtick longer than the longest backtick run
302
+ * inside the text, so content that itself contains backticks cannot break
303
+ * the span. Tool output renders literally instead of being parsed as
304
+ * markdown (headings, bold, wiki links …).
305
+ */
306
+ function inlineCode(text: string): string {
307
+ const longest = (text.match(/`+/g) ?? []).reduce((a, r) => Math.max(a, r.length), 0);
308
+ const fence = "`".repeat(longest + 1);
309
+ return `${fence}${text}${fence}`;
310
+ }
311
+
296
312
  /**
297
313
  * Strip leading blank lines and trailing whitespace from a rendered block,
298
314
  * so joins and separators always keep exactly one blank line around them
@@ -325,7 +341,7 @@ export default function (pi: ExtensionAPI) {
325
341
 
326
342
  /** Standalone one-line block for a result whose call is not in this file. */
327
343
  function renderToolResult(m: ToolResultMessage): string {
328
- return `> **Tool · ${m.toolName}** ${resultPreview(m)}`.trim();
344
+ return `> **Tool · ${m.toolName}** ${inlineCode(resultPreview(m))}`.trim();
329
345
  }
330
346
 
331
347
  /** "read, web_search ×2" — tool names with repeat counts, first-seen order. */
@@ -346,12 +362,17 @@ export default function (pi: ExtensionAPI) {
346
362
  return `> [!${type}]- ${title}\n${lines.join("\n")}`;
347
363
  }
348
364
 
349
- /** Fold tool calls and their paired results into one collapsed callout. */
365
+ /**
366
+ * Fold tool calls and their paired results into one collapsed callout.
367
+ * Argument JSON and result previews are wrapped in inline code spans, so
368
+ * raw output renders literally instead of being parsed as markdown.
369
+ */
350
370
  function renderToolCallsCallout(calls: RenderedToolCall[]): string {
351
371
  const summary = summarizeToolNames(calls.map((c) => c.name));
352
372
  const items = calls.map((c) => {
353
- const head = c.args ? `**\`${c.name}\`** \`${c.args}\`` : `**\`${c.name}\`**`;
354
- const result = c.result === null ? "_(no result)_" : c.result || "_(empty result)_";
373
+ const head = c.args ? `**\`${c.name}\`** ${inlineCode(c.args)}` : `**\`${c.name}\`**`;
374
+ const result =
375
+ c.result === null ? "_(no result)_" : inlineCode(c.result || "_(empty result)_");
355
376
  return `${head}\n\n> ${result}`;
356
377
  });
357
378
  return callout("quote", `Tool Calls · ${calls.length} (${summary})`, items.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.3.0",
3
+ "version": "0.3.2",
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",