agent-sin 0.1.11 → 0.1.15

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 (97) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/README.md +2 -1
  3. package/builtin-skills/_shared/_todo_lib.py +290 -0
  4. package/builtin-skills/even-g2-setup/main.ts +896 -0
  5. package/builtin-skills/even-g2-setup/skill.yaml +133 -0
  6. package/builtin-skills/memo-delete/main.py +28 -107
  7. package/builtin-skills/memo-delete/skill.yaml +10 -21
  8. package/builtin-skills/memo-index/main.py +96 -64
  9. package/builtin-skills/memo-index/skill.yaml +4 -10
  10. package/builtin-skills/memo-list/main.py +179 -0
  11. package/builtin-skills/memo-list/skill.yaml +51 -0
  12. package/builtin-skills/memo-save/main.py +191 -25
  13. package/builtin-skills/memo-save/skill.yaml +29 -5
  14. package/builtin-skills/memo-search/main.py +38 -18
  15. package/builtin-skills/memo-vector-search/main.py +11 -6
  16. package/builtin-skills/nightly-topic-knowledge/_feedback_lib.py +391 -0
  17. package/builtin-skills/nightly-topic-knowledge/_topics_lib.py +415 -0
  18. package/builtin-skills/nightly-topic-knowledge/main.py +403 -0
  19. package/builtin-skills/nightly-topic-knowledge/skill.yaml +88 -0
  20. package/builtin-skills/schedule-add/main.py +26 -0
  21. package/builtin-skills/service-restart/main.ts +249 -0
  22. package/builtin-skills/service-restart/skill.yaml +49 -0
  23. package/builtin-skills/todo-add/main.py +3 -1
  24. package/builtin-skills/todo-delete/main.py +3 -1
  25. package/builtin-skills/todo-done/main.py +3 -1
  26. package/builtin-skills/todo-list/main.py +4 -1
  27. package/builtin-skills/todo-tick/main.py +3 -1
  28. package/builtin-skills/topic-knowledge-read/main.py +118 -0
  29. package/builtin-skills/topic-knowledge-read/skill.yaml +49 -0
  30. package/dist/builder/build-action-classifier.d.ts +18 -0
  31. package/dist/builder/build-action-classifier.js +82 -1
  32. package/dist/builder/build-flow.d.ts +33 -4
  33. package/dist/builder/build-flow.js +251 -89
  34. package/dist/builder/builder-session.d.ts +1 -1
  35. package/dist/builder/builder-session.js +112 -7
  36. package/dist/builder/conversation-router.d.ts +4 -2
  37. package/dist/builder/conversation-router.js +19 -2
  38. package/dist/cli/index.js +323 -20
  39. package/dist/core/ai-provider.d.ts +1 -0
  40. package/dist/core/ai-provider.js +8 -3
  41. package/dist/core/chat-engine.d.ts +10 -3
  42. package/dist/core/chat-engine.js +1563 -197
  43. package/dist/core/config.d.ts +4 -0
  44. package/dist/core/config.js +82 -0
  45. package/dist/core/daily-memory-promotion.d.ts +7 -0
  46. package/dist/core/daily-memory-promotion.js +568 -14
  47. package/dist/core/image-attachments.d.ts +31 -0
  48. package/dist/core/image-attachments.js +237 -0
  49. package/dist/core/logger.d.ts +2 -1
  50. package/dist/core/logger.js +77 -1
  51. package/dist/core/memo-migration.d.ts +3 -0
  52. package/dist/core/memo-migration.js +422 -0
  53. package/dist/core/native-modules.d.ts +24 -0
  54. package/dist/core/native-modules.js +99 -0
  55. package/dist/core/notifier.d.ts +8 -3
  56. package/dist/core/notifier.js +191 -17
  57. package/dist/core/obsidian-vault.d.ts +19 -0
  58. package/dist/core/obsidian-vault.js +477 -0
  59. package/dist/core/operating-model.d.ts +2 -0
  60. package/dist/core/operating-model.js +15 -0
  61. package/dist/core/output-writer.d.ts +3 -2
  62. package/dist/core/output-writer.js +108 -7
  63. package/dist/core/profile-memory.js +22 -1
  64. package/dist/core/runtime.d.ts +2 -0
  65. package/dist/core/runtime.js +9 -1
  66. package/dist/core/secrets.d.ts +4 -0
  67. package/dist/core/secrets.js +34 -0
  68. package/dist/core/skill-history.d.ts +44 -0
  69. package/dist/core/skill-history.js +329 -0
  70. package/dist/core/skill-registry.d.ts +5 -0
  71. package/dist/core/skill-registry.js +11 -0
  72. package/dist/discord/bot.d.ts +13 -0
  73. package/dist/discord/bot.js +542 -10
  74. package/dist/even-g2/gateway.d.ts +15 -0
  75. package/dist/even-g2/gateway.js +868 -0
  76. package/dist/runtimes/codex-app-server.d.ts +5 -1
  77. package/dist/runtimes/codex-app-server.js +147 -8
  78. package/dist/runtimes/python-runner.js +82 -0
  79. package/dist/runtimes/typescript-runner.js +13 -1
  80. package/dist/skills-sdk/types.d.ts +19 -4
  81. package/dist/telegram/bot.d.ts +1 -0
  82. package/dist/telegram/bot.js +122 -31
  83. package/package.json +3 -1
  84. package/templates/even-g2-agent/README.md +83 -0
  85. package/templates/even-g2-agent/app.json +20 -0
  86. package/templates/even-g2-agent/index.html +31 -0
  87. package/templates/even-g2-agent/package-lock.json +1836 -0
  88. package/templates/even-g2-agent/package.json +22 -0
  89. package/templates/even-g2-agent/scripts/qr-auto.mjs +182 -0
  90. package/templates/even-g2-agent/src/embedded-config.ts +4 -0
  91. package/templates/even-g2-agent/src/main.ts +539 -0
  92. package/templates/even-g2-agent/src/style.css +70 -0
  93. package/templates/even-g2-agent/tsconfig.json +11 -0
  94. package/templates/skill-python/main.py +20 -2
  95. package/templates/skill-python/skill.yaml +9 -0
  96. package/templates/skill-typescript/main.ts +40 -5
  97. package/templates/skill-typescript/skill.yaml +9 -0
@@ -0,0 +1,477 @@
1
+ import { mkdir, readFile, readlink, stat, symlink, unlink, writeFile } from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { l } from "./i18n.js";
5
+ export function defaultObsidianVaultDir() {
6
+ return path.join(os.homedir(), "Obsidian", "Agent-Sin");
7
+ }
8
+ export function resolvedObsidianVaultDir(config) {
9
+ const raw = config.obsidian_vault_dir;
10
+ if (raw === undefined)
11
+ return defaultObsidianVaultDir();
12
+ const trimmed = raw.trim();
13
+ return trimmed;
14
+ }
15
+ const HOME_TEMPLATE_JA = `---
16
+ tags: [moc, home]
17
+ ---
18
+
19
+ # Agent-Sin Vault
20
+
21
+ Agent-Sin が扱う記憶・メモを Obsidian で読み書きしやすくしたビューです。実体は \`~/.agent-sin/\` 配下にあり、ここからはシンボリックリンクで参照しています。**ファイルを移動・リネームすると Agent-Sin 側の動作に影響する**ため、編集は本文の追記・修正に留めてください。
22
+
23
+ ## プロフィール(長期記憶)
24
+
25
+ - [[01 Profile/user|user.md]] — 固定プロフィール
26
+ - [[01 Profile/soul|soul.md]] — Agent-Sin 自身の姿勢メモ
27
+ - [[01 Profile/memory|memory.md]] — 嗜好・価値観・コミュニケーション傾向
28
+
29
+ ## 日次メモリ(会話の要約)
30
+
31
+ \`02 Daily Memory/YYYY/MM/YYYY-MM-DD.md\` に日次で Agent-Sin との会話が整形保存されています。生の jsonl ログは Vault 外(\`~/.agent-sin/logs/conversations/\`)にあります。
32
+
33
+ ## ノート
34
+
35
+ \`03 Notes/memo/{タイトル}.md\` 形式で 1メモ=1ファイル として保存されます。AIが自動でタイトルを付与し、同じタイトルで保存すると本文末尾に追記されます。最新メモはファイルエクスプローラーを「更新日時の新しい順」に並べると上から見えます。旧 \`YYYY/MM/YYYY-MM-DD.md\` 形式のファイルは \`03 Notes/legacy/\` 配下に退避済みです。
36
+
37
+ 会話で添付した画像は Vault 外の \`~/.agent-sin/memory/attachments/\` に保存され、daily memory の md から絶対パスで参照されます(md を開けば画像も表示されます)。どこからも参照されなくなった画像は 7 日経過後に自動削除されます。
38
+
39
+ ## トピック知識(JSON・閲覧専用)
40
+
41
+ \`04 Topics/topics/*.json\` に Agent-Sin が夜間に蒸留したトピック別の長期知識が入っています。Obsidian 上では読み取り中心で扱ってください(書き換えると Agent-Sin 側で上書きされる可能性があります)。
42
+
43
+ ## ToDo
44
+
45
+ \`05 ToDo/todos.md\` に未完了/完了の ToDo が一覧表示されます。Obsidian 上でチェックを切ったり、行を追加・削除すると、次回の todo スキル実行時に Agent-Sin 側へ取り込まれます(Obsidian 優先)。\`^id-xxxx\` のアンカーは触らないでください。
46
+
47
+ ## スキル成果物
48
+
49
+ \`06 Skills/<スキル名>/\` 配下に、各スキルが書き出したユーザー閲覧前提の md(マーケログ、SNS下書き、買い物リスト、健康ログ等)が並びます。ファイル名はスキルが用途名で付け、日付ディレクトリは作りません。**読む・本文を編集するのは OK** ですが、ファイル名や置き場所を変えるとスキル側の追記処理が当たらなくなるので、リネームは控えてください。スキル内部の状態(ユーザーに見せないもの)はここではなく、スキルのメモリや SQLite に置かれます。
50
+
51
+ ## 編集ルール
52
+
53
+ - **触ってよい**: profile 配下の \`.md\` 本文、\`03 Notes/memo/\` 配下のファイル追加・編集、daily memory の加筆メモ、\`05 ToDo/todos.md\` のチェック・追加・削除、\`06 Skills/\` 配下の本文編集
54
+ - **触らない**: \`04 Topics\` 配下の JSON、\`02 Daily Memory\` のタイムスタンプ見出し、\`03 Notes/legacy/\` 配下
55
+ - **してはいけない**: シンボリックリンクの削除・リネーム、フォルダの場所変更、\`06 Skills/\` 配下のファイル名・配置変更
56
+ `;
57
+ const HOME_TEMPLATE_EN = `---
58
+ tags: [moc, home]
59
+ ---
60
+
61
+ # Agent-Sin Vault
62
+
63
+ A human-readable Obsidian view over the memory and notes that Agent-Sin manages. The real files live under \`~/.agent-sin/\` and are exposed here through symlinks. **Do not move or rename the linked folders** — Agent-Sin reads/writes them directly.
64
+
65
+ ## Profile (long-term memory)
66
+
67
+ - [[01 Profile/user|user.md]] — fixed profile
68
+ - [[01 Profile/soul|soul.md]] — Agent-Sin's posture notes
69
+ - [[01 Profile/memory|memory.md]] — preferences, values, communication patterns
70
+
71
+ ## Daily Memory
72
+
73
+ \`02 Daily Memory/YYYY/MM/YYYY-MM-DD.md\` holds Agent-Sin's formatted conversation memory per day. Raw jsonl logs stay outside the vault under \`~/.agent-sin/logs/conversations/\`.
74
+
75
+ ## Notes
76
+
77
+ \`03 Notes/memo/{title}.md\` stores one memo per file. The title is generated by AI; saving the same title appends to the existing file. Sort the file explorer by "Modified time (newest)" to see the latest memos at the top. Older daily-style files (\`YYYY/MM/YYYY-MM-DD.md\`) have been moved to \`03 Notes/legacy/\`.
78
+
79
+ Image attachments uploaded in chat are stored outside the vault under \`~/.agent-sin/memory/attachments/\` and referenced from daily memory md files by absolute path (clicking through the md renders the image). Images that nothing references anymore are pruned 7 days after they go stale.
80
+
81
+ ## Topic knowledge (JSON, read-only)
82
+
83
+ \`04 Topics/topics/*.json\` stores per-topic long-term knowledge distilled by Agent-Sin nightly. Treat as read-only; Agent-Sin will overwrite manual edits.
84
+
85
+ ## ToDo
86
+
87
+ \`05 ToDo/todos.md\` lists open and completed ToDos. Toggling a checkbox or adding/removing a line here is picked up by Agent-Sin on the next todo skill run (Obsidian wins). Do not edit the \`^id-xxxx\` block anchors.
88
+
89
+ ## Skill outputs
90
+
91
+ \`06 Skills/<skill-id>/\` is where each skill writes user-visible markdown (marketing logs, SNS drafts, shopping lists, health logs, etc.). Filenames are chosen by the skill (no date subfolders). **Reading and editing the body is safe**, but do not rename or move the files — the skill's append/merge logic relies on the path. Internal state that the user shouldn't see is stored in skill memory or SQLite instead, not here.
92
+
93
+ ## Editing rules
94
+
95
+ - **Safe to edit**: profile \`.md\` bodies, files under \`03 Notes/memo/\`, daily memory annotations, \`05 ToDo/todos.md\` (check/add/remove), file bodies under \`06 Skills/\`
96
+ - **Do not edit**: JSON under \`04 Topics\`, timestamp headers in \`02 Daily Memory\`, files under \`03 Notes/legacy/\`
97
+ - **Never**: delete or rename the symlinked folders, rename or move files under \`06 Skills/\`
98
+ `;
99
+ // 旧テンプレ (attachments を 03 Notes/attachments/ で案内していた頃の 06 Skills あり版)。
100
+ const LEGACY_HOME_TEMPLATE_JA_V3 = `---
101
+ tags: [moc, home]
102
+ ---
103
+
104
+ # Agent-Sin Vault
105
+
106
+ Agent-Sin が扱う記憶・メモを Obsidian で読み書きしやすくしたビューです。実体は \`~/.agent-sin/\` 配下にあり、ここからはシンボリックリンクで参照しています。**ファイルを移動・リネームすると Agent-Sin 側の動作に影響する**ため、編集は本文の追記・修正に留めてください。
107
+
108
+ ## プロフィール(長期記憶)
109
+
110
+ - [[01 Profile/user|user.md]] — 固定プロフィール
111
+ - [[01 Profile/soul|soul.md]] — Agent-Sin 自身の姿勢メモ
112
+ - [[01 Profile/memory|memory.md]] — 嗜好・価値観・コミュニケーション傾向
113
+
114
+ ## 日次メモリ(会話の要約)
115
+
116
+ \`02 Daily Memory/YYYY/MM/YYYY-MM-DD.md\` に日次で Agent-Sin との会話が整形保存されています。生の jsonl ログは Vault 外(\`~/.agent-sin/logs/conversations/\`)にあります。
117
+
118
+ ## ノート
119
+
120
+ \`03 Notes/memo/{タイトル}.md\` 形式で 1メモ=1ファイル として保存されます。AIが自動でタイトルを付与し、同じタイトルで保存すると本文末尾に追記されます。最新メモはファイルエクスプローラーを「更新日時の新しい順」に並べると上から見えます。旧 \`YYYY/MM/YYYY-MM-DD.md\` 形式のファイルは \`03 Notes/legacy/\` 配下に退避済みです。添付画像は \`03 Notes/attachments/\` 配下です。
121
+
122
+ ## トピック知識(JSON・閲覧専用)
123
+
124
+ \`04 Topics/topics/*.json\` に Agent-Sin が夜間に蒸留したトピック別の長期知識が入っています。Obsidian 上では読み取り中心で扱ってください(書き換えると Agent-Sin 側で上書きされる可能性があります)。
125
+
126
+ ## ToDo
127
+
128
+ \`05 ToDo/todos.md\` に未完了/完了の ToDo が一覧表示されます。Obsidian 上でチェックを切ったり、行を追加・削除すると、次回の todo スキル実行時に Agent-Sin 側へ取り込まれます(Obsidian 優先)。\`^id-xxxx\` のアンカーは触らないでください。
129
+
130
+ ## スキル成果物
131
+
132
+ \`06 Skills/<スキル名>/\` 配下に、各スキルが書き出したユーザー閲覧前提の md(マーケログ、SNS下書き、買い物リスト、健康ログ等)が並びます。ファイル名はスキルが用途名で付け、日付ディレクトリは作りません。**読む・本文を編集するのは OK** ですが、ファイル名や置き場所を変えるとスキル側の追記処理が当たらなくなるので、リネームは控えてください。スキル内部の状態(ユーザーに見せないもの)はここではなく、スキルのメモリや SQLite に置かれます。
133
+
134
+ ## 編集ルール
135
+
136
+ - **触ってよい**: profile 配下の \`.md\` 本文、\`03 Notes/memo/\` 配下のファイル追加・編集、daily memory の加筆メモ、\`05 ToDo/todos.md\` のチェック・追加・削除、\`06 Skills/\` 配下の本文編集
137
+ - **触らない**: \`04 Topics\` 配下の JSON、\`02 Daily Memory\` のタイムスタンプ見出し、\`03 Notes/legacy/\` 配下
138
+ - **してはいけない**: シンボリックリンクの削除・リネーム、フォルダの場所変更、\`06 Skills/\` 配下のファイル名・配置変更
139
+ `;
140
+ const LEGACY_HOME_TEMPLATE_EN_V3 = `---
141
+ tags: [moc, home]
142
+ ---
143
+
144
+ # Agent-Sin Vault
145
+
146
+ A human-readable Obsidian view over the memory and notes that Agent-Sin manages. The real files live under \`~/.agent-sin/\` and are exposed here through symlinks. **Do not move or rename the linked folders** — Agent-Sin reads/writes them directly.
147
+
148
+ ## Profile (long-term memory)
149
+
150
+ - [[01 Profile/user|user.md]] — fixed profile
151
+ - [[01 Profile/soul|soul.md]] — Agent-Sin's posture notes
152
+ - [[01 Profile/memory|memory.md]] — preferences, values, communication patterns
153
+
154
+ ## Daily Memory
155
+
156
+ \`02 Daily Memory/YYYY/MM/YYYY-MM-DD.md\` holds Agent-Sin's formatted conversation memory per day. Raw jsonl logs stay outside the vault under \`~/.agent-sin/logs/conversations/\`.
157
+
158
+ ## Notes
159
+
160
+ \`03 Notes/memo/{title}.md\` stores one memo per file. The title is generated by AI; saving the same title appends to the existing file. Sort the file explorer by "Modified time (newest)" to see the latest memos at the top. Older daily-style files (\`YYYY/MM/YYYY-MM-DD.md\`) have been moved to \`03 Notes/legacy/\`. Attachments live under \`03 Notes/attachments/\`.
161
+
162
+ ## Topic knowledge (JSON, read-only)
163
+
164
+ \`04 Topics/topics/*.json\` stores per-topic long-term knowledge distilled by Agent-Sin nightly. Treat as read-only; Agent-Sin will overwrite manual edits.
165
+
166
+ ## ToDo
167
+
168
+ \`05 ToDo/todos.md\` lists open and completed ToDos. Toggling a checkbox or adding/removing a line here is picked up by Agent-Sin on the next todo skill run (Obsidian wins). Do not edit the \`^id-xxxx\` block anchors.
169
+
170
+ ## Skill outputs
171
+
172
+ \`06 Skills/<skill-id>/\` is where each skill writes user-visible markdown (marketing logs, SNS drafts, shopping lists, health logs, etc.). Filenames are chosen by the skill (no date subfolders). **Reading and editing the body is safe**, but do not rename or move the files — the skill's append/merge logic relies on the path. Internal state that the user shouldn't see is stored in skill memory or SQLite instead, not here.
173
+
174
+ ## Editing rules
175
+
176
+ - **Safe to edit**: profile \`.md\` bodies, files under \`03 Notes/memo/\`, daily memory annotations, \`05 ToDo/todos.md\` (check/add/remove), file bodies under \`06 Skills/\`
177
+ - **Do not edit**: JSON under \`04 Topics\`, timestamp headers in \`02 Daily Memory\`, files under \`03 Notes/legacy/\`
178
+ - **Never**: delete or rename the symlinked folders, rename or move files under \`06 Skills/\`
179
+ `;
180
+ // さらに古い旧テンプレ (memo/legacy 区分が入った版。06 Skills 追加前)。
181
+ // writeIfMissingOrPristine がこれと完全一致するときだけ新版に自動更新する。
182
+ const LEGACY_HOME_TEMPLATE_JA_V2 = `---
183
+ tags: [moc, home]
184
+ ---
185
+
186
+ # Agent-Sin Vault
187
+
188
+ Agent-Sin が扱う記憶・メモを Obsidian で読み書きしやすくしたビューです。実体は \`~/.agent-sin/\` 配下にあり、ここからはシンボリックリンクで参照しています。**ファイルを移動・リネームすると Agent-Sin 側の動作に影響する**ため、編集は本文の追記・修正に留めてください。
189
+
190
+ ## プロフィール(長期記憶)
191
+
192
+ - [[01 Profile/user|user.md]] — 固定プロフィール
193
+ - [[01 Profile/soul|soul.md]] — Agent-Sin 自身の姿勢メモ
194
+ - [[01 Profile/memory|memory.md]] — 嗜好・価値観・コミュニケーション傾向
195
+
196
+ ## 日次メモリ(会話の要約)
197
+
198
+ \`02 Daily Memory/YYYY/MM/YYYY-MM-DD.md\` に日次で Agent-Sin との会話が整形保存されています。生の jsonl ログは Vault 外(\`~/.agent-sin/logs/conversations/\`)にあります。
199
+
200
+ ## ノート
201
+
202
+ \`03 Notes/memo/{タイトル}.md\` 形式で 1メモ=1ファイル として保存されます。AIが自動でタイトルを付与し、同じタイトルで保存すると本文末尾に追記されます。最新メモはファイルエクスプローラーを「更新日時の新しい順」に並べると上から見えます。旧 \`YYYY/MM/YYYY-MM-DD.md\` 形式のファイルは \`03 Notes/legacy/\` 配下に退避済みです。添付画像は \`03 Notes/attachments/\` 配下です。
203
+
204
+ ## トピック知識(JSON・閲覧専用)
205
+
206
+ \`04 Topics/topics/*.json\` に Agent-Sin が夜間に蒸留したトピック別の長期知識が入っています。Obsidian 上では読み取り中心で扱ってください(書き換えると Agent-Sin 側で上書きされる可能性があります)。
207
+
208
+ ## ToDo
209
+
210
+ \`05 ToDo/todos.md\` に未完了/完了の ToDo が一覧表示されます。Obsidian 上でチェックを切ったり、行を追加・削除すると、次回の todo スキル実行時に Agent-Sin 側へ取り込まれます(Obsidian 優先)。\`^id-xxxx\` のアンカーは触らないでください。
211
+
212
+ ## 編集ルール
213
+
214
+ - **触ってよい**: profile 配下の \`.md\` 本文、\`03 Notes/memo/\` 配下のファイル追加・編集、daily memory の加筆メモ、\`05 ToDo/todos.md\` のチェック・追加・削除
215
+ - **触らない**: \`04 Topics\` 配下の JSON、\`02 Daily Memory\` のタイムスタンプ見出し、\`03 Notes/legacy/\` 配下
216
+ - **してはいけない**: シンボリックリンクの削除・リネーム、フォルダの場所変更
217
+ `;
218
+ const LEGACY_HOME_TEMPLATE_EN_V2 = `---
219
+ tags: [moc, home]
220
+ ---
221
+
222
+ # Agent-Sin Vault
223
+
224
+ A human-readable Obsidian view over the memory and notes that Agent-Sin manages. The real files live under \`~/.agent-sin/\` and are exposed here through symlinks. **Do not move or rename the linked folders** — Agent-Sin reads/writes them directly.
225
+
226
+ ## Profile (long-term memory)
227
+
228
+ - [[01 Profile/user|user.md]] — fixed profile
229
+ - [[01 Profile/soul|soul.md]] — Agent-Sin's posture notes
230
+ - [[01 Profile/memory|memory.md]] — preferences, values, communication patterns
231
+
232
+ ## Daily Memory
233
+
234
+ \`02 Daily Memory/YYYY/MM/YYYY-MM-DD.md\` holds Agent-Sin's formatted conversation memory per day. Raw jsonl logs stay outside the vault under \`~/.agent-sin/logs/conversations/\`.
235
+
236
+ ## Notes
237
+
238
+ \`03 Notes/memo/{title}.md\` stores one memo per file. The title is generated by AI; saving the same title appends to the existing file. Sort the file explorer by "Modified time (newest)" to see the latest memos at the top. Older daily-style files (\`YYYY/MM/YYYY-MM-DD.md\`) have been moved to \`03 Notes/legacy/\`. Attachments live under \`03 Notes/attachments/\`.
239
+
240
+ ## Topic knowledge (JSON, read-only)
241
+
242
+ \`04 Topics/topics/*.json\` stores per-topic long-term knowledge distilled by Agent-Sin nightly. Treat as read-only; Agent-Sin will overwrite manual edits.
243
+
244
+ ## ToDo
245
+
246
+ \`05 ToDo/todos.md\` lists open and completed ToDos. Toggling a checkbox or adding/removing a line here is picked up by Agent-Sin on the next todo skill run (Obsidian wins). Do not edit the \`^id-xxxx\` block anchors.
247
+
248
+ ## Editing rules
249
+
250
+ - **Safe to edit**: profile \`.md\` bodies, files under \`03 Notes/memo/\`, daily memory annotations, \`05 ToDo/todos.md\` (check/add/remove)
251
+ - **Do not edit**: JSON under \`04 Topics\`, timestamp headers in \`02 Daily Memory\`, files under \`03 Notes/legacy/\`
252
+ - **Never**: delete or rename the symlinked folders
253
+ `;
254
+ // さらに古いテンプレ(メモが日付ベースで保存されていた頃の版)。
255
+ const LEGACY_HOME_TEMPLATE_JA = `---
256
+ tags: [moc, home]
257
+ ---
258
+
259
+ # Agent-Sin Vault
260
+
261
+ Agent-Sin が扱う記憶・メモを Obsidian で読み書きしやすくしたビューです。実体は \`~/.agent-sin/\` 配下にあり、ここからはシンボリックリンクで参照しています。**ファイルを移動・リネームすると Agent-Sin 側の動作に影響する**ため、編集は本文の追記・修正に留めてください。
262
+
263
+ ## プロフィール(長期記憶)
264
+
265
+ - [[01 Profile/user|user.md]] — 固定プロフィール
266
+ - [[01 Profile/soul|soul.md]] — Agent-Sin 自身の姿勢メモ
267
+ - [[01 Profile/memory|memory.md]] — 嗜好・価値観・コミュニケーション傾向
268
+
269
+ ## 日次メモリ(会話の要約)
270
+
271
+ \`02 Daily Memory/YYYY/MM/YYYY-MM-DD.md\` に日次で Agent-Sin との会話が整形保存されています。生の jsonl ログは Vault 外(\`~/.agent-sin/logs/conversations/\`)にあります。
272
+
273
+ ## ノート
274
+
275
+ \`03 Notes/YYYY/MM/YYYY-MM-DD.md\` 形式でメモやスキル出力が保存されます。添付画像は \`03 Notes/attachments/\` 配下です。
276
+
277
+ ## トピック知識(JSON・閲覧専用)
278
+
279
+ \`04 Topics/topics/*.json\` に Agent-Sin が夜間に蒸留したトピック別の長期知識が入っています。Obsidian 上では読み取り中心で扱ってください(書き換えると Agent-Sin 側で上書きされる可能性があります)。
280
+
281
+ ## ToDo
282
+
283
+ \`05 ToDo/todos.md\` に未完了/完了の ToDo が一覧表示されます。Obsidian 上でチェックを切ったり、行を追加・削除すると、次回の todo スキル実行時に Agent-Sin 側へ取り込まれます(Obsidian 優先)。\`^id-xxxx\` のアンカーは触らないでください。
284
+
285
+ ## 編集ルール
286
+
287
+ - **触ってよい**: profile 配下の \`.md\` 本文、notes 配下の追記、daily memory の加筆メモ、\`05 ToDo/todos.md\` のチェック・追加・削除
288
+ - **触らない**: \`04 Topics\` 配下の JSON、\`02 Daily Memory\` のタイムスタンプ見出し
289
+ - **してはいけない**: シンボリックリンクの削除・リネーム、フォルダの場所変更
290
+ `;
291
+ const LEGACY_HOME_TEMPLATE_EN = `---
292
+ tags: [moc, home]
293
+ ---
294
+
295
+ # Agent-Sin Vault
296
+
297
+ A human-readable Obsidian view over the memory and notes that Agent-Sin manages. The real files live under \`~/.agent-sin/\` and are exposed here through symlinks. **Do not move or rename the linked folders** — Agent-Sin reads/writes them directly.
298
+
299
+ ## Profile (long-term memory)
300
+
301
+ - [[01 Profile/user|user.md]] — fixed profile
302
+ - [[01 Profile/soul|soul.md]] — Agent-Sin's posture notes
303
+ - [[01 Profile/memory|memory.md]] — preferences, values, communication patterns
304
+
305
+ ## Daily Memory
306
+
307
+ \`02 Daily Memory/YYYY/MM/YYYY-MM-DD.md\` holds Agent-Sin's formatted conversation memory per day. Raw jsonl logs stay outside the vault under \`~/.agent-sin/logs/conversations/\`.
308
+
309
+ ## Notes
310
+
311
+ \`03 Notes/YYYY/MM/YYYY-MM-DD.md\` is where memo and skill output is written. Attachments live under \`03 Notes/attachments/\`.
312
+
313
+ ## Topic knowledge (JSON, read-only)
314
+
315
+ \`04 Topics/topics/*.json\` stores per-topic long-term knowledge distilled by Agent-Sin nightly. Treat as read-only; Agent-Sin will overwrite manual edits.
316
+
317
+ ## ToDo
318
+
319
+ \`05 ToDo/todos.md\` lists open and completed ToDos. Toggling a checkbox or adding/removing a line here is picked up by Agent-Sin on the next todo skill run (Obsidian wins). Do not edit the \`^id-xxxx\` block anchors.
320
+
321
+ ## Editing rules
322
+
323
+ - **Safe to edit**: profile \`.md\` bodies, notes additions, daily memory annotations, \`05 ToDo/todos.md\` (check/add/remove)
324
+ - **Do not edit**: JSON under \`04 Topics\`, timestamp headers in \`02 Daily Memory\`
325
+ - **Never**: delete or rename the symlinked folders
326
+ `;
327
+ const OBSIDIAN_APP_JSON = `${JSON.stringify({
328
+ showUnsupportedFiles: true,
329
+ newFileLocation: "current",
330
+ attachmentFolderPath: "./",
331
+ alwaysUpdateLinks: false,
332
+ useMarkdownLinks: false,
333
+ promptDelete: true,
334
+ }, null, 2)}\n`;
335
+ const OBSIDIAN_APPEARANCE_JSON = `${JSON.stringify({
336
+ showInlineTitle: true,
337
+ showViewHeader: true,
338
+ }, null, 2)}\n`;
339
+ export async function ensureObsidianVault(config) {
340
+ const vaultDir = resolvedObsidianVaultDir(config);
341
+ if (!vaultDir) {
342
+ return {
343
+ enabled: false,
344
+ vaultDir: "",
345
+ created: false,
346
+ links: [],
347
+ homeCreated: false,
348
+ configCreated: false,
349
+ };
350
+ }
351
+ const alreadyExisted = await pathExists(vaultDir);
352
+ await mkdir(vaultDir, { recursive: true });
353
+ await mkdir(path.join(vaultDir, ".obsidian"), { recursive: true });
354
+ const linkSpecs = [
355
+ { name: "01 Profile", target: path.join(config.memory_dir, "profile") },
356
+ { name: "02 Daily Memory", target: path.join(config.memory_dir, "daily") },
357
+ { name: "03 Notes", target: config.notes_dir },
358
+ { name: "04 Topics", target: path.join(config.memory_dir, "topic-knowledge") },
359
+ { name: "05 ToDo", target: path.join(config.workspace, "todo") },
360
+ { name: "06 Skills", target: config.skill_outputs_dir },
361
+ ];
362
+ const links = [];
363
+ let symlinkError;
364
+ for (const spec of linkSpecs) {
365
+ const linkPath = path.join(vaultDir, spec.name);
366
+ const existing = await readSymlinkTarget(linkPath);
367
+ if (existing !== null) {
368
+ // 既存リンクが正しい場所を指していればそのまま
369
+ if (existing === spec.target) {
370
+ links.push({ name: spec.name, target: spec.target, created: false, ok: true });
371
+ continue;
372
+ }
373
+ // 別の場所を指していて、その先が dangling なら作り直す。生きている場合は触らない (ユーザーが意図して張り替えた可能性あり)
374
+ if (!(await pathExists(existing))) {
375
+ try {
376
+ await unlink(linkPath);
377
+ }
378
+ catch {
379
+ // unlink 失敗時は下のフォールバックに任せる
380
+ }
381
+ }
382
+ else {
383
+ links.push({ name: spec.name, target: spec.target, created: false, ok: false });
384
+ continue;
385
+ }
386
+ }
387
+ else if (await pathExists(linkPath)) {
388
+ // 同名の実体(ディレクトリ等)があれば触らない
389
+ links.push({ name: spec.name, target: spec.target, created: false, ok: false });
390
+ continue;
391
+ }
392
+ try {
393
+ // make sure the target dir exists so the link is not dangling
394
+ await mkdir(spec.target, { recursive: true });
395
+ await symlink(spec.target, linkPath, "dir");
396
+ links.push({ name: spec.name, target: spec.target, created: true, ok: true });
397
+ }
398
+ catch (error) {
399
+ symlinkError = error instanceof Error ? error.message : String(error);
400
+ links.push({ name: spec.name, target: spec.target, created: false, ok: false });
401
+ }
402
+ }
403
+ const todoDir = path.join(config.workspace, "todo");
404
+ await mkdir(todoDir, { recursive: true });
405
+ await writeIfMissing(path.join(todoDir, "todos.md"), l("# ToDo\n\n_(no ToDos yet)_\n", "# ToDo\n\n_(まだ ToDo はありません)_\n"));
406
+ const homePath = path.join(vaultDir, "Home.md");
407
+ const homeTemplate = l(HOME_TEMPLATE_EN, HOME_TEMPLATE_JA);
408
+ const homeCreated = await writeIfMissingOrPristine(homePath, homeTemplate, [
409
+ HOME_TEMPLATE_EN,
410
+ HOME_TEMPLATE_JA,
411
+ LEGACY_HOME_TEMPLATE_EN_V3,
412
+ LEGACY_HOME_TEMPLATE_JA_V3,
413
+ LEGACY_HOME_TEMPLATE_EN_V2,
414
+ LEGACY_HOME_TEMPLATE_JA_V2,
415
+ LEGACY_HOME_TEMPLATE_EN,
416
+ LEGACY_HOME_TEMPLATE_JA,
417
+ ]);
418
+ const appJsonPath = path.join(vaultDir, ".obsidian", "app.json");
419
+ const appearancePath = path.join(vaultDir, ".obsidian", "appearance.json");
420
+ const appCreated = await writeIfMissing(appJsonPath, OBSIDIAN_APP_JSON);
421
+ const appearanceCreated = await writeIfMissing(appearancePath, OBSIDIAN_APPEARANCE_JSON);
422
+ return {
423
+ enabled: true,
424
+ vaultDir,
425
+ created: !alreadyExisted,
426
+ links,
427
+ homeCreated,
428
+ configCreated: appCreated || appearanceCreated,
429
+ symlinkError,
430
+ };
431
+ }
432
+ async function readSymlinkTarget(file) {
433
+ try {
434
+ return await readlink(file);
435
+ }
436
+ catch {
437
+ return null;
438
+ }
439
+ }
440
+ async function pathExists(file) {
441
+ try {
442
+ await stat(file);
443
+ return true;
444
+ }
445
+ catch {
446
+ return false;
447
+ }
448
+ }
449
+ async function writeIfMissing(file, content) {
450
+ try {
451
+ await stat(file);
452
+ return false;
453
+ }
454
+ catch {
455
+ await writeFile(file, content, "utf8");
456
+ return true;
457
+ }
458
+ }
459
+ // 既存ファイルが「過去のデフォルトテンプレ」のままなら、現ロケールの版に差し替える。
460
+ // ユーザーが手で編集していれば触らない。
461
+ async function writeIfMissingOrPristine(file, desired, pristineTemplates) {
462
+ let existing = null;
463
+ try {
464
+ existing = await readFile(file, "utf8");
465
+ }
466
+ catch {
467
+ await writeFile(file, desired, "utf8");
468
+ return true;
469
+ }
470
+ if (existing === desired)
471
+ return false;
472
+ const isPristine = pristineTemplates.some((tpl) => tpl === existing);
473
+ if (!isPristine)
474
+ return false;
475
+ await writeFile(file, desired, "utf8");
476
+ return true;
477
+ }
@@ -0,0 +1,2 @@
1
+ export type AgentSinOperatingMode = "chat" | "builder";
2
+ export declare function agentSinOperatingModelLines(mode: AgentSinOperatingMode): string[];
@@ -0,0 +1,15 @@
1
+ export function agentSinOperatingModelLines(mode) {
2
+ const lines = [
3
+ "Agent-Sin operating model:",
4
+ "- Visible reply text informs the user; by itself, it does not execute actions, change modes, write files, restart services, register commands, or run tests.",
5
+ "- Agent-Sin can act only through the structured mechanisms that the host consumes for the current mode. Choose one of those mechanisms when action is intended.",
6
+ "- Before replying, decide whether the user needs an answer, an executable action, implementation work, or a clarifying question. Then emit the matching structured output instead of narrating an internal intention.",
7
+ ];
8
+ if (mode === "chat") {
9
+ lines.push("- In conversation mode, executable skill actions happen through skill_calls. If you intend to run a registered skill, include the skill call; do not merely say that you will run it.", "- In conversation mode, implementation handoff happens through build_suggestion. If a skill should be created or edited now, include build_suggestion; do not merely say that you are switching, handing off, or passing the task to build mode.", "- If no registered skill or build_suggestion matches the user's intent, answer the user or ask the smallest useful question. Do not promise an action that Agent-Sin cannot perform from the current mode.", "- Build mode is a host-managed state. The user-visible words 'I will switch to build mode' are not a mode transition unless the response also includes the build_suggestion structure.");
10
+ }
11
+ else {
12
+ lines.push("- In build mode, file blocks are the write mechanism. If you intend to create or edit a skill, emit the required file blocks; do not only write a completion report.", "- A completion report tells the user what is now possible, but it does not run the new skill, restart Agent-Sin, register slash commands, or modify host settings.", "- If a follow-up host action is needed after implementation, describe the next user-visible step briefly. Do not imply that the report text itself performed the action.");
13
+ }
14
+ return lines;
15
+ }
@@ -8,6 +8,7 @@ export interface SavedOutput {
8
8
  append: boolean;
9
9
  show_saved: boolean;
10
10
  }
11
+ export type MergeMode = "overwrite" | "append" | "update_or_append";
11
12
  export declare function writeSkillOutputs(config: AppConfig, manifest: SkillManifest, result: SkillResult, date?: Date): Promise<SavedOutput[]>;
12
- export declare function resolveOutputFile(config: AppConfig, output: SkillOutputDefinition, date: Date): string;
13
- export declare function renderTemplate(template: string, date: Date): string;
13
+ export declare function resolveOutputFile(config: AppConfig, output: SkillOutputDefinition, date: Date, overrideFilename?: string): string;
14
+ export declare function renderTemplate(template: string, date: Date, vars?: Record<string, string>): string;