@make-u-free/migi 0.5.1 → 0.5.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@make-u-free/migi",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "Your AI right-hand agent. Works anywhere, with any LLM API.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/agent.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import OpenAI from 'openai'
2
2
  import chalk from 'chalk'
3
3
  import { homedir } from 'os'
4
- import { existsSync, appendFileSync, mkdirSync } from 'fs'
5
- import { join, dirname } from 'path'
4
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs'
5
+ import { join } from 'path'
6
6
  import { toolSchemas, teamsToolSchema, executeTool } from './tools.js'
7
7
  import { createPermissionChecker } from './permissions.js'
8
8
  import { httpsAgent } from './tls.js'
@@ -57,17 +57,18 @@ ${userNameLine}
57
57
  - 完了したら1〜2文で報告。途中経過は出さない
58
58
 
59
59
  ## メモリと文脈の継続
60
- - グローバルメモリ: ${homedir()}/.migi/memory.md(ユーザーの好み・習慣・横断的な情報)
61
- - ワークスペースメモリ: ${cwd}/.migi/memory.md(このプロジェクト固有の情報・決定事項)
62
- - 形式: "## YYYY-MM-DD" の見出しの下に箇条書きで記録。既存ファイルがあれば追記
63
- - ユーザーが「覚えておいて」「remember」と言ったら必ず書き出す
64
- - 言われなくても、以下は自発的に記録する:
65
- - 重要な意思決定・方針転換
66
- - ユーザーの好み・こだわり・やり方のクセ
67
- - 繰り返し登場するテーマやプロジェクト
68
- - 「次回やること」として明確になったタスク
69
- - セッション開始時にメモリの内容を参照し、前回の続きから自然に入る
70
- - 過去の記録と矛盾することをユーザーが言ったら「前回と変わりましたか?」と確認する
60
+ ワークスペースメモリは ${cwd}/.migi/memory/ に構造化して保存する:
61
+ - projects.md ── 進行中の仕事・状況
62
+ - feedback.md ── ユーザーの好み・作業スタイル・こだわり
63
+ - next-actions.md ── 次回やること(毎セッション更新)
64
+
65
+ グローバルメモリ: ${homedir()}/.migi/memory.md(横断的なユーザー情報)
66
+
67
+ 運用ルール:
68
+ - セッション開始時にメモリを参照し、前回の続きから自然に入る
69
+ - ユーザーが「覚えておいて」と言ったら write_file で即座に該当ファイルを更新
70
+ - 重要な決定・好み・方針転換は言われなくても「記録しておきましょうか?」と提案
71
+ - 過去の記録と矛盾したら「前回と変わりましたか?」と確認する
71
72
 
72
73
  ## 環境
73
74
  - 今日の日付: ${new Date().toISOString().split('T')[0]}
@@ -82,9 +83,8 @@ ${userNameLine}
82
83
  (context ? `\n## ロードされたコンテキスト\n${context}` : '')
83
84
  }
84
85
 
85
- // セッションの会話をサマリーして memory.md に保存する
86
+ // セッション終了時にメモリファイルを構造化更新する
86
87
  async saveSummary(cwd) {
87
- // ユーザー発言が2回未満なら保存しない(短すぎるセッション)
88
88
  const userTurns = this.history.filter(m => m.role === 'user').length
89
89
  if (userTurns < 2) return null
90
90
 
@@ -92,6 +92,20 @@ ${userNameLine}
92
92
  spinner.start('セッションを記録中…')
93
93
 
94
94
  try {
95
+ const memDir = join(cwd, '.migi', 'memory')
96
+ const files = ['projects.md', 'feedback.md', 'next-actions.md']
97
+
98
+ // 既存ファイルの内容を読む
99
+ const current = {}
100
+ for (const f of files) {
101
+ const p = join(memDir, f)
102
+ current[f] = existsSync(p) ? readFileSync(p, 'utf-8').trim() : '(未記録)'
103
+ }
104
+
105
+ const currentDump = files
106
+ .map(f => `### ${f}\n${current[f]}`)
107
+ .join('\n\n')
108
+
95
109
  const response = await this.client.chat.completions.create({
96
110
  model: this.model,
97
111
  messages: [
@@ -99,30 +113,42 @@ ${userNameLine}
99
113
  ...this.history,
100
114
  {
101
115
  role: 'user',
102
- content: `このセッションを次回の文脈引き継ぎ用に要約してください。
103
- 以下の形式で箇条書き3〜6行。日本語で簡潔に(1行50字以内)。
116
+ content: `このセッションの内容を踏まえ、以下のメモリファイルを更新してください。
104
117
 
105
- - 話し合ったこと・決定したこと
106
- - 完了したこと・作ったもの
107
- - ユーザーについて学んだこと(好み・やり方など)
108
- - 次回やること(あれば)
118
+ 現在の内容:
119
+ ${currentDump}
109
120
 
110
- 形式:「- 〜」の箇条書きのみ。見出しや前置きは不要。`
121
+ JSON形式のみで返答(他のテキスト不要):
122
+ {
123
+ "projects.md": "進行中の仕事・状況(15行以内)",
124
+ "feedback.md": "ユーザーの好み・作業スタイル・こだわり(15行以内)",
125
+ "next-actions.md": "次回やること(今回判明したもののみ・前回分は消す)"
126
+ }
127
+
128
+ ルール: 新情報は追加、古い情報は上書き、不要なものは削除。変化なければそのまま返す。`
111
129
  }
112
- ]
130
+ ],
131
+ response_format: { type: 'json_object' }
113
132
  })
114
133
 
115
- const summary = response.choices[0].message.content.trim()
116
- const today = new Date().toISOString().split('T')[0]
117
- const entry = `\n## ${today}\n${summary}\n`
134
+ const updates = JSON.parse(response.choices[0].message.content)
135
+
136
+ if (!existsSync(memDir)) mkdirSync(memDir, { recursive: true })
137
+
138
+ const updated = []
139
+ for (const [filename, content] of Object.entries(updates)) {
140
+ if (files.includes(filename) && content?.trim() && content.trim() !== '(未記録)') {
141
+ writeFileSync(join(memDir, filename), content.trim() + '\n', 'utf-8')
142
+ updated.push(filename)
143
+ }
144
+ }
118
145
 
119
- const memPath = join(cwd, '.migi', 'memory.md')
120
- const dir = dirname(memPath)
121
- if (!existsSync(dir)) mkdirSync(dir, { recursive: true })
122
- appendFileSync(memPath, entry, 'utf-8')
146
+ // インデックスを更新
147
+ const indexLines = updated.map(f => `- [memory/${f}](memory/${f})`).join('\n')
148
+ writeFileSync(join(cwd, '.migi', 'memory.md'), `# メモリインデックス\n\n${indexLines}\n`, 'utf-8')
123
149
 
124
150
  spinner.stop()
125
- return memPath
151
+ return memDir
126
152
  } catch (err) {
127
153
  spinner.stop()
128
154
  return null
package/src/context.js CHANGED
@@ -34,8 +34,21 @@ export async function loadContext(cwd = process.cwd()) {
34
34
  // 1. グローバルメモリ (~/.migi/memory.md)
35
35
  load('グローバルメモリ', join(homedir(), '.migi', 'memory.md'))
36
36
 
37
- // 2. ワークスペースメモリ (.migi/memory.md)
38
- load('ワークスペースメモリ', join(cwd, '.migi', 'memory.md'))
37
+ // 2. ワークスペースメモリ: インデックス + memory/ 以下の個別ファイル
38
+ load('ワークスペースメモリ(インデックス)', join(cwd, '.migi', 'memory.md'))
39
+ const memDir = join(cwd, '.migi', 'memory')
40
+ if (existsSync(memDir)) {
41
+ const memFiles = await glob('*.md', { cwd: memDir })
42
+ // next-actions を最後に(直近の文脈として読ませる)
43
+ memFiles.sort((a, b) => {
44
+ if (a === 'next-actions.md') return 1
45
+ if (b === 'next-actions.md') return -1
46
+ return a.localeCompare(b)
47
+ })
48
+ for (const f of memFiles) {
49
+ load(`メモリ/${f}`, join(memDir, f))
50
+ }
51
+ }
39
52
 
40
53
  // 3. ルートの MIGI.md → CLAUDE.md
41
54
  loadWithFallback('', cwd, 'CLAUDE.md')