maskweaver 0.11.0 → 0.11.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/LICENSE +21 -21
- package/README.ko.md +640 -640
- package/README.md +672 -672
- package/assets/agents/dummy-human.md +31 -31
- package/assets/agents/dummy-template.md +57 -57
- package/assets/agents/mask-weaver.md +412 -412
- package/assets/agents/squad-operator.md +242 -242
- package/assets/masks/ai-ml/andrew-ng.yaml +207 -207
- package/assets/masks/architecture/jeff-dean.yaml +208 -208
- package/assets/masks/index.json +65 -65
- package/assets/masks/software-engineering/dan-abramov.yaml +188 -188
- package/assets/masks/software-engineering/kent-beck.yaml +191 -191
- package/assets/masks/software-engineering/linus-torvalds.yaml +152 -152
- package/assets/masks/software-engineering/martin-fowler.yaml +173 -173
- package/dist/memory/store/sqlite.js +102 -102
- package/dist/plugin/tools/context.js +15 -15
- package/dist/plugin/tools/maskSave.js +8 -8
- package/dist/plugin/tools/memoryIndexer.js +5 -5
- package/dist/plugin/tools/memorySearch.js +8 -8
- package/dist/plugin/tools/memoryWrite.js +3 -3
- package/dist/plugin/tools/retrospect.js +3 -3
- package/dist/plugin/tools/squad.js +39 -39
- package/dist/retrospect/mask-save.js +21 -21
- package/dist/retrospect/retrospect.js +9 -9
- package/dist/shared/generate-agents.d.ts +3 -15
- package/dist/shared/generate-agents.js +13 -172
- package/dist/shared/subscription-detection.d.ts +20 -0
- package/dist/shared/subscription-detection.js +162 -0
- package/dist/verify/prompts.js +114 -114
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/weave/knowledge/global.js +86 -86
- package/dist/weave/verification/playwright.js +127 -127
- package/masks/ai-ml/andrew-ng.yaml +207 -207
- package/masks/architecture/jeff-dean.yaml +208 -208
- package/masks/index.json +65 -65
- package/masks/orchestration/squad-operator.yaml +205 -205
- package/masks/software-engineering/dan-abramov.yaml +188 -188
- package/masks/software-engineering/kent-beck.yaml +191 -191
- package/masks/software-engineering/linus-torvalds.yaml +152 -152
- package/masks/software-engineering/martin-fowler.yaml +173 -173
- package/package.json +1 -1
- package/postinstall.mjs +22 -112
|
@@ -80,51 +80,51 @@ export class MemoryDatabase {
|
|
|
80
80
|
return instance;
|
|
81
81
|
}
|
|
82
82
|
initSchema() {
|
|
83
|
-
this.db.exec(`
|
|
84
|
-
-- Chunks table
|
|
85
|
-
CREATE TABLE IF NOT EXISTS chunks (
|
|
86
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
87
|
-
path TEXT NOT NULL,
|
|
88
|
-
start_line INTEGER NOT NULL,
|
|
89
|
-
end_line INTEGER NOT NULL,
|
|
90
|
-
text TEXT NOT NULL,
|
|
91
|
-
hash TEXT NOT NULL,
|
|
92
|
-
source TEXT NOT NULL,
|
|
93
|
-
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
94
|
-
UNIQUE(path, start_line, end_line)
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
-- Embeddings table
|
|
98
|
-
CREATE TABLE IF NOT EXISTS embeddings (
|
|
99
|
-
chunk_id INTEGER PRIMARY KEY,
|
|
100
|
-
embedding BLOB NOT NULL,
|
|
101
|
-
FOREIGN KEY (chunk_id) REFERENCES chunks(id) ON DELETE CASCADE
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
-- Mask usage table
|
|
105
|
-
CREATE TABLE IF NOT EXISTS mask_usage (
|
|
106
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
107
|
-
mask_name TEXT NOT NULL,
|
|
108
|
-
task_description TEXT,
|
|
109
|
-
effectiveness_score INTEGER,
|
|
110
|
-
used_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
-- Indexes
|
|
114
|
-
CREATE INDEX IF NOT EXISTS idx_chunks_path ON chunks(path);
|
|
115
|
-
CREATE INDEX IF NOT EXISTS idx_chunks_source ON chunks(source);
|
|
116
|
-
CREATE INDEX IF NOT EXISTS idx_chunks_hash ON chunks(hash);
|
|
117
|
-
CREATE INDEX IF NOT EXISTS idx_mask_usage_name ON mask_usage(mask_name);
|
|
83
|
+
this.db.exec(`
|
|
84
|
+
-- Chunks table
|
|
85
|
+
CREATE TABLE IF NOT EXISTS chunks (
|
|
86
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
87
|
+
path TEXT NOT NULL,
|
|
88
|
+
start_line INTEGER NOT NULL,
|
|
89
|
+
end_line INTEGER NOT NULL,
|
|
90
|
+
text TEXT NOT NULL,
|
|
91
|
+
hash TEXT NOT NULL,
|
|
92
|
+
source TEXT NOT NULL,
|
|
93
|
+
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
94
|
+
UNIQUE(path, start_line, end_line)
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
-- Embeddings table
|
|
98
|
+
CREATE TABLE IF NOT EXISTS embeddings (
|
|
99
|
+
chunk_id INTEGER PRIMARY KEY,
|
|
100
|
+
embedding BLOB NOT NULL,
|
|
101
|
+
FOREIGN KEY (chunk_id) REFERENCES chunks(id) ON DELETE CASCADE
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
-- Mask usage table
|
|
105
|
+
CREATE TABLE IF NOT EXISTS mask_usage (
|
|
106
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
107
|
+
mask_name TEXT NOT NULL,
|
|
108
|
+
task_description TEXT,
|
|
109
|
+
effectiveness_score INTEGER,
|
|
110
|
+
used_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
-- Indexes
|
|
114
|
+
CREATE INDEX IF NOT EXISTS idx_chunks_path ON chunks(path);
|
|
115
|
+
CREATE INDEX IF NOT EXISTS idx_chunks_source ON chunks(source);
|
|
116
|
+
CREATE INDEX IF NOT EXISTS idx_chunks_hash ON chunks(hash);
|
|
117
|
+
CREATE INDEX IF NOT EXISTS idx_mask_usage_name ON mask_usage(mask_name);
|
|
118
118
|
`);
|
|
119
119
|
this.ftsAvailable = false;
|
|
120
120
|
try {
|
|
121
|
-
this.db.exec(`
|
|
122
|
-
CREATE VIRTUAL TABLE IF NOT EXISTS chunks_fts USING fts5(
|
|
123
|
-
text,
|
|
124
|
-
content='chunks',
|
|
125
|
-
content_rowid='id',
|
|
126
|
-
tokenize='unicode61'
|
|
127
|
-
);
|
|
121
|
+
this.db.exec(`
|
|
122
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS chunks_fts USING fts5(
|
|
123
|
+
text,
|
|
124
|
+
content='chunks',
|
|
125
|
+
content_rowid='id',
|
|
126
|
+
tokenize='unicode61'
|
|
127
|
+
);
|
|
128
128
|
`);
|
|
129
129
|
this.ftsAvailable = true;
|
|
130
130
|
}
|
|
@@ -133,22 +133,22 @@ export class MemoryDatabase {
|
|
|
133
133
|
}
|
|
134
134
|
if (this.ftsAvailable) {
|
|
135
135
|
try {
|
|
136
|
-
this.db.exec(`
|
|
137
|
-
-- INSERT trigger
|
|
138
|
-
CREATE TRIGGER IF NOT EXISTS chunks_ai AFTER INSERT ON chunks BEGIN
|
|
139
|
-
INSERT INTO chunks_fts(rowid, text) VALUES (new.id, new.text);
|
|
140
|
-
END;
|
|
141
|
-
|
|
142
|
-
-- DELETE trigger
|
|
143
|
-
CREATE TRIGGER IF NOT EXISTS chunks_ad AFTER DELETE ON chunks BEGIN
|
|
144
|
-
INSERT INTO chunks_fts(chunks_fts, rowid, text) VALUES('delete', old.id, old.text);
|
|
145
|
-
END;
|
|
146
|
-
|
|
147
|
-
-- UPDATE trigger
|
|
148
|
-
CREATE TRIGGER IF NOT EXISTS chunks_au AFTER UPDATE ON chunks BEGIN
|
|
149
|
-
INSERT INTO chunks_fts(chunks_fts, rowid, text) VALUES('delete', old.id, old.text);
|
|
150
|
-
INSERT INTO chunks_fts(rowid, text) VALUES (new.id, new.text);
|
|
151
|
-
END;
|
|
136
|
+
this.db.exec(`
|
|
137
|
+
-- INSERT trigger
|
|
138
|
+
CREATE TRIGGER IF NOT EXISTS chunks_ai AFTER INSERT ON chunks BEGIN
|
|
139
|
+
INSERT INTO chunks_fts(rowid, text) VALUES (new.id, new.text);
|
|
140
|
+
END;
|
|
141
|
+
|
|
142
|
+
-- DELETE trigger
|
|
143
|
+
CREATE TRIGGER IF NOT EXISTS chunks_ad AFTER DELETE ON chunks BEGIN
|
|
144
|
+
INSERT INTO chunks_fts(chunks_fts, rowid, text) VALUES('delete', old.id, old.text);
|
|
145
|
+
END;
|
|
146
|
+
|
|
147
|
+
-- UPDATE trigger
|
|
148
|
+
CREATE TRIGGER IF NOT EXISTS chunks_au AFTER UPDATE ON chunks BEGIN
|
|
149
|
+
INSERT INTO chunks_fts(chunks_fts, rowid, text) VALUES('delete', old.id, old.text);
|
|
150
|
+
INSERT INTO chunks_fts(rowid, text) VALUES (new.id, new.text);
|
|
151
|
+
END;
|
|
152
152
|
`);
|
|
153
153
|
}
|
|
154
154
|
catch (error) {
|
|
@@ -158,61 +158,61 @@ export class MemoryDatabase {
|
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
160
|
prepareStatements() {
|
|
161
|
-
this.statements.set('upsertChunk', this.db.prepare(`
|
|
162
|
-
INSERT INTO chunks (path, start_line, end_line, text, hash, source)
|
|
163
|
-
VALUES (?, ?, ?, ?, ?, ?)
|
|
164
|
-
ON CONFLICT(path, start_line, end_line) DO UPDATE SET
|
|
165
|
-
text = excluded.text,
|
|
166
|
-
hash = excluded.hash,
|
|
167
|
-
source = excluded.source,
|
|
168
|
-
created_at = CURRENT_TIMESTAMP
|
|
169
|
-
RETURNING id
|
|
161
|
+
this.statements.set('upsertChunk', this.db.prepare(`
|
|
162
|
+
INSERT INTO chunks (path, start_line, end_line, text, hash, source)
|
|
163
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
164
|
+
ON CONFLICT(path, start_line, end_line) DO UPDATE SET
|
|
165
|
+
text = excluded.text,
|
|
166
|
+
hash = excluded.hash,
|
|
167
|
+
source = excluded.source,
|
|
168
|
+
created_at = CURRENT_TIMESTAMP
|
|
169
|
+
RETURNING id
|
|
170
170
|
`));
|
|
171
|
-
this.statements.set('upsertEmbedding', this.db.prepare(`
|
|
172
|
-
INSERT INTO embeddings (chunk_id, embedding)
|
|
173
|
-
VALUES (?, ?)
|
|
174
|
-
ON CONFLICT(chunk_id) DO UPDATE SET
|
|
175
|
-
embedding = excluded.embedding
|
|
171
|
+
this.statements.set('upsertEmbedding', this.db.prepare(`
|
|
172
|
+
INSERT INTO embeddings (chunk_id, embedding)
|
|
173
|
+
VALUES (?, ?)
|
|
174
|
+
ON CONFLICT(chunk_id) DO UPDATE SET
|
|
175
|
+
embedding = excluded.embedding
|
|
176
176
|
`));
|
|
177
|
-
this.statements.set('getChunkById', this.db.prepare(`
|
|
178
|
-
SELECT * FROM chunks WHERE id = ?
|
|
177
|
+
this.statements.set('getChunkById', this.db.prepare(`
|
|
178
|
+
SELECT * FROM chunks WHERE id = ?
|
|
179
179
|
`));
|
|
180
|
-
this.statements.set('deleteChunksByPath', this.db.prepare(`
|
|
181
|
-
DELETE FROM chunks WHERE path = ?
|
|
180
|
+
this.statements.set('deleteChunksByPath', this.db.prepare(`
|
|
181
|
+
DELETE FROM chunks WHERE path = ?
|
|
182
182
|
`));
|
|
183
|
-
this.statements.set('checkChunkByHash', this.db.prepare(`
|
|
184
|
-
SELECT id FROM chunks WHERE path = ? AND hash = ?
|
|
183
|
+
this.statements.set('checkChunkByHash', this.db.prepare(`
|
|
184
|
+
SELECT id FROM chunks WHERE path = ? AND hash = ?
|
|
185
185
|
`));
|
|
186
|
-
this.statements.set('getAllEmbeddings', this.db.prepare(`
|
|
187
|
-
SELECT c.*, e.embedding
|
|
188
|
-
FROM chunks c
|
|
189
|
-
JOIN embeddings e ON c.id = e.chunk_id
|
|
186
|
+
this.statements.set('getAllEmbeddings', this.db.prepare(`
|
|
187
|
+
SELECT c.*, e.embedding
|
|
188
|
+
FROM chunks c
|
|
189
|
+
JOIN embeddings e ON c.id = e.chunk_id
|
|
190
190
|
`));
|
|
191
191
|
if (this.ftsAvailable) {
|
|
192
|
-
this.statements.set('searchFts', this.db.prepare(`
|
|
193
|
-
SELECT rowid, text, rank
|
|
194
|
-
FROM chunks_fts
|
|
195
|
-
WHERE chunks_fts MATCH ?
|
|
196
|
-
ORDER BY rank
|
|
197
|
-
LIMIT ?
|
|
192
|
+
this.statements.set('searchFts', this.db.prepare(`
|
|
193
|
+
SELECT rowid, text, rank
|
|
194
|
+
FROM chunks_fts
|
|
195
|
+
WHERE chunks_fts MATCH ?
|
|
196
|
+
ORDER BY rank
|
|
197
|
+
LIMIT ?
|
|
198
198
|
`));
|
|
199
199
|
}
|
|
200
|
-
this.statements.set('getChunksByPath', this.db.prepare(`
|
|
201
|
-
SELECT * FROM chunks WHERE path = ?
|
|
200
|
+
this.statements.set('getChunksByPath', this.db.prepare(`
|
|
201
|
+
SELECT * FROM chunks WHERE path = ?
|
|
202
202
|
`));
|
|
203
|
-
this.statements.set('insertMaskUsage', this.db.prepare(`
|
|
204
|
-
INSERT INTO mask_usage (mask_name, task_description, effectiveness_score)
|
|
205
|
-
VALUES (?, ?, ?)
|
|
203
|
+
this.statements.set('insertMaskUsage', this.db.prepare(`
|
|
204
|
+
INSERT INTO mask_usage (mask_name, task_description, effectiveness_score)
|
|
205
|
+
VALUES (?, ?, ?)
|
|
206
206
|
`));
|
|
207
|
-
this.statements.set('getMaskStats', this.db.prepare(`
|
|
208
|
-
SELECT
|
|
209
|
-
mask_name,
|
|
210
|
-
COUNT(*) as usage_count,
|
|
211
|
-
AVG(effectiveness_score) as avg_effectiveness,
|
|
212
|
-
MAX(used_at) as last_used
|
|
213
|
-
FROM mask_usage
|
|
214
|
-
GROUP BY mask_name
|
|
215
|
-
ORDER BY usage_count DESC
|
|
207
|
+
this.statements.set('getMaskStats', this.db.prepare(`
|
|
208
|
+
SELECT
|
|
209
|
+
mask_name,
|
|
210
|
+
COUNT(*) as usage_count,
|
|
211
|
+
AVG(effectiveness_score) as avg_effectiveness,
|
|
212
|
+
MAX(used_at) as last_used
|
|
213
|
+
FROM mask_usage
|
|
214
|
+
GROUP BY mask_name
|
|
215
|
+
ORDER BY usage_count DESC
|
|
216
216
|
`));
|
|
217
217
|
}
|
|
218
218
|
upsertChunk(chunk, embedding) {
|
|
@@ -25,21 +25,21 @@ function errorResponse(action, message) {
|
|
|
25
25
|
}
|
|
26
26
|
export function createContextTool() {
|
|
27
27
|
return {
|
|
28
|
-
description: `작업 컨텍스트를 관리합니다.
|
|
29
|
-
|
|
30
|
-
**액션:**
|
|
31
|
-
- \`start\`: 새 피처 시작 (name, goal 필요)
|
|
32
|
-
- \`switch\`: 피처 전환 (id 또는 name 필요)
|
|
33
|
-
- \`status\`: 현재 활성 피처 상태 표시
|
|
34
|
-
- \`done\`: 피처 완료 처리 (id 없으면 현재 피처)
|
|
35
|
-
- \`add\`: 현재 피처에 파일 추가 (file 필요)
|
|
36
|
-
- \`drop\`: 현재 피처에서 파일 제거 (file 필요)
|
|
37
|
-
- \`goal\`: 현재 피처 목표 변경 (goal 필요)
|
|
38
|
-
- \`list\`: 모든 피처 목록 조회
|
|
39
|
-
|
|
40
|
-
**예시:**
|
|
41
|
-
- 피처 시작: action="start", name="login-oauth", goal="OAuth 로그인 구현"
|
|
42
|
-
- 파일 추가: action="add", file="src/auth/oauth.ts"
|
|
28
|
+
description: `작업 컨텍스트를 관리합니다.
|
|
29
|
+
|
|
30
|
+
**액션:**
|
|
31
|
+
- \`start\`: 새 피처 시작 (name, goal 필요)
|
|
32
|
+
- \`switch\`: 피처 전환 (id 또는 name 필요)
|
|
33
|
+
- \`status\`: 현재 활성 피처 상태 표시
|
|
34
|
+
- \`done\`: 피처 완료 처리 (id 없으면 현재 피처)
|
|
35
|
+
- \`add\`: 현재 피처에 파일 추가 (file 필요)
|
|
36
|
+
- \`drop\`: 현재 피처에서 파일 제거 (file 필요)
|
|
37
|
+
- \`goal\`: 현재 피처 목표 변경 (goal 필요)
|
|
38
|
+
- \`list\`: 모든 피처 목록 조회
|
|
39
|
+
|
|
40
|
+
**예시:**
|
|
41
|
+
- 피처 시작: action="start", name="login-oauth", goal="OAuth 로그인 구현"
|
|
42
|
+
- 파일 추가: action="add", file="src/auth/oauth.ts"
|
|
43
43
|
- 상태 확인: action="status"`,
|
|
44
44
|
args: contextSchema,
|
|
45
45
|
async execute(args, context) {
|
|
@@ -2,14 +2,14 @@ import { z } from "zod";
|
|
|
2
2
|
import { saveMask } from "../../retrospect/index.js";
|
|
3
3
|
export function createMaskSaveTool() {
|
|
4
4
|
return {
|
|
5
|
-
description: `효과적인 가면을 라이브러리에 저장합니다.
|
|
6
|
-
새로운 가면을 추가하거나, 기존 가면의 효과성 점수와 사용 기록을 업데이트합니다.
|
|
7
|
-
|
|
8
|
-
사용 시점:
|
|
9
|
-
- 가면 사용 후 효과적이었을 때
|
|
10
|
-
- 새로운 전문가 가면을 발견했을 때
|
|
11
|
-
- 기존 가면의 효과성을 기록할 때
|
|
12
|
-
|
|
5
|
+
description: `효과적인 가면을 라이브러리에 저장합니다.
|
|
6
|
+
새로운 가면을 추가하거나, 기존 가면의 효과성 점수와 사용 기록을 업데이트합니다.
|
|
7
|
+
|
|
8
|
+
사용 시점:
|
|
9
|
+
- 가면 사용 후 효과적이었을 때
|
|
10
|
+
- 새로운 전문가 가면을 발견했을 때
|
|
11
|
+
- 기존 가면의 효과성을 기록할 때
|
|
12
|
+
|
|
13
13
|
효과성 점수는 이동 평균으로 계산됩니다 (새 점수 가중치: 0.3)`,
|
|
14
14
|
args: z.object({
|
|
15
15
|
name: z.string(),
|
|
@@ -32,11 +32,11 @@ async function getConfiguredProvider(worktree) {
|
|
|
32
32
|
}
|
|
33
33
|
export function createMemoryIndexerTool() {
|
|
34
34
|
return {
|
|
35
|
-
description: `Index memory files for semantic search. Chunks markdown files and stores embeddings.
|
|
36
|
-
|
|
37
|
-
Actions:
|
|
38
|
-
- index: Index a single file (only re-embeds changed chunks)
|
|
39
|
-
- reindex: Force reindex a file (deletes and re-embeds all chunks)
|
|
35
|
+
description: `Index memory files for semantic search. Chunks markdown files and stores embeddings.
|
|
36
|
+
|
|
37
|
+
Actions:
|
|
38
|
+
- index: Index a single file (only re-embeds changed chunks)
|
|
39
|
+
- reindex: Force reindex a file (deletes and re-embeds all chunks)
|
|
40
40
|
- index-all: Index all memory files (MEMORY.md, MASKS.md, RETROSPECT.md, USER.md)`,
|
|
41
41
|
args: z.object({
|
|
42
42
|
action: z.enum(["index", "reindex", "index-all"]),
|
|
@@ -52,14 +52,14 @@ async function getProvider(worktree) {
|
|
|
52
52
|
}
|
|
53
53
|
export function createMemorySearchTool() {
|
|
54
54
|
return {
|
|
55
|
-
description: `Search memories using semantic similarity and keyword matching.
|
|
56
|
-
|
|
57
|
-
Use this to:
|
|
58
|
-
- Recall previous conversations or decisions
|
|
59
|
-
- Find mask usage history and effectiveness
|
|
60
|
-
- Retrieve user preferences
|
|
61
|
-
- Check past retrospectives and lessons
|
|
62
|
-
|
|
55
|
+
description: `Search memories using semantic similarity and keyword matching.
|
|
56
|
+
|
|
57
|
+
Use this to:
|
|
58
|
+
- Recall previous conversations or decisions
|
|
59
|
+
- Find mask usage history and effectiveness
|
|
60
|
+
- Retrieve user preferences
|
|
61
|
+
- Check past retrospectives and lessons
|
|
62
|
+
|
|
63
63
|
Keywords: "remember", "before", "last time", "previous"`,
|
|
64
64
|
args: memorySearchArgsSchema,
|
|
65
65
|
async execute(args, context) {
|
|
@@ -9,9 +9,9 @@ const memoryWriteArgsSchema = z.object({
|
|
|
9
9
|
});
|
|
10
10
|
export function createMemoryWriteTool() {
|
|
11
11
|
return {
|
|
12
|
-
description: `Saves content to memory files.
|
|
13
|
-
- daily: Today's work log (appends to today's date file)
|
|
14
|
-
- memory: Long-term memory (adds to MEMORY.md)
|
|
12
|
+
description: `Saves content to memory files.
|
|
13
|
+
- daily: Today's work log (appends to today's date file)
|
|
14
|
+
- memory: Long-term memory (adds to MEMORY.md)
|
|
15
15
|
- user: User information (updates USER.md)`,
|
|
16
16
|
args: memoryWriteArgsSchema,
|
|
17
17
|
async execute(args, context) {
|
|
@@ -2,9 +2,9 @@ import { z } from "zod";
|
|
|
2
2
|
import { performRetrospect } from "../../retrospect/index.js";
|
|
3
3
|
export function createRetrospectTool() {
|
|
4
4
|
return {
|
|
5
|
-
description: `회고를 수행합니다.
|
|
6
|
-
- daily: 오늘의 작업 기록 (자동으로 오늘 날짜 파일에 추가)
|
|
7
|
-
- memory: 장기 기억 (MEMORY.md에 추가)
|
|
5
|
+
description: `회고를 수행합니다.
|
|
6
|
+
- daily: 오늘의 작업 기록 (자동으로 오늘 날짜 파일에 추가)
|
|
7
|
+
- memory: 장기 기억 (MEMORY.md에 추가)
|
|
8
8
|
- user: 유저 정보 (USER.md 업데이트)`,
|
|
9
9
|
args: z.object({
|
|
10
10
|
trigger: z.enum(["manual", "session_end", "periodic"]),
|
|
@@ -118,45 +118,45 @@ async function handlePlan(basePath, squadId) {
|
|
|
118
118
|
}
|
|
119
119
|
export function createSquadTool() {
|
|
120
120
|
return {
|
|
121
|
-
description: `Multi-agent collaboration management.
|
|
122
|
-
|
|
123
|
-
**⚠️ DELEGATION PRINCIPLE:**
|
|
124
|
-
Primary agent (가면술사) should delegate tactical operations to Squad Operator.
|
|
125
|
-
Direct use of assign/update/complete by primary agent pollutes strategic context.
|
|
126
|
-
|
|
127
|
-
**Role-based Action Guide:**
|
|
128
|
-
| Action | Primary Agent | Operator | Notes |
|
|
129
|
-
|--------|---------------|----------|-------|
|
|
130
|
-
| start | ✅ OK | ❌ | Session setup |
|
|
131
|
-
| squad | ✅ OK | ❌ | Squad creation |
|
|
132
|
-
| assign | ⚠️ Delegate | ✅ OK | Task assignment |
|
|
133
|
-
| update | ⚠️ Delegate | ✅ OK | Status updates |
|
|
134
|
-
| complete | ⚠️ Delegate | ✅ OK | Task completion |
|
|
135
|
-
| status | ✅ OK | ✅ OK | Read-only |
|
|
136
|
-
| watchdog | ✅ OK | ✅ OK | Health check |
|
|
137
|
-
| list | ✅ OK | ✅ OK | Read-only |
|
|
138
|
-
|
|
139
|
-
**Correct Workflow:**
|
|
140
|
-
1. Primary agent: start → squad → Task(squad-operator)
|
|
141
|
-
2. Operator (in separate session): assign → update → complete
|
|
142
|
-
3. Primary agent: receives summary only
|
|
143
|
-
|
|
144
|
-
**Actions:**
|
|
145
|
-
- \`start\`: Start new session (goal required)
|
|
146
|
-
- \`squad\`: Create new squad (mission, operator required)
|
|
147
|
-
- \`assign\`: Assign task to agent (squadId, assignee, description required)
|
|
148
|
-
- \`update\`: Update task status (squadId, taskId, status required)
|
|
149
|
-
- \`complete\`: Complete task (squadId, taskId, success required)
|
|
150
|
-
- \`status\`: View session or squad status (squadId optional)
|
|
151
|
-
- \`watchdog\`: Run timeout watchdog (dryRun optional)
|
|
152
|
-
- \`list\`: List all squads in session
|
|
153
|
-
- \`plan\`: Analyze task dependencies and create parallel execution plan (squadId required)
|
|
154
|
-
- \`models\`: Query available models, their capabilities, and concurrency status
|
|
155
|
-
|
|
156
|
-
**Examples:**
|
|
157
|
-
- Start session: action="start", goal="Implement OAuth login"
|
|
158
|
-
- Create squad: action="squad", mission="Auth module", operator="auth-agent"
|
|
159
|
-
- Assign task: action="assign", squadId="squad-abc", assignee="worker-1", description="Login form"
|
|
121
|
+
description: `Multi-agent collaboration management.
|
|
122
|
+
|
|
123
|
+
**⚠️ DELEGATION PRINCIPLE:**
|
|
124
|
+
Primary agent (가면술사) should delegate tactical operations to Squad Operator.
|
|
125
|
+
Direct use of assign/update/complete by primary agent pollutes strategic context.
|
|
126
|
+
|
|
127
|
+
**Role-based Action Guide:**
|
|
128
|
+
| Action | Primary Agent | Operator | Notes |
|
|
129
|
+
|--------|---------------|----------|-------|
|
|
130
|
+
| start | ✅ OK | ❌ | Session setup |
|
|
131
|
+
| squad | ✅ OK | ❌ | Squad creation |
|
|
132
|
+
| assign | ⚠️ Delegate | ✅ OK | Task assignment |
|
|
133
|
+
| update | ⚠️ Delegate | ✅ OK | Status updates |
|
|
134
|
+
| complete | ⚠️ Delegate | ✅ OK | Task completion |
|
|
135
|
+
| status | ✅ OK | ✅ OK | Read-only |
|
|
136
|
+
| watchdog | ✅ OK | ✅ OK | Health check |
|
|
137
|
+
| list | ✅ OK | ✅ OK | Read-only |
|
|
138
|
+
|
|
139
|
+
**Correct Workflow:**
|
|
140
|
+
1. Primary agent: start → squad → Task(squad-operator)
|
|
141
|
+
2. Operator (in separate session): assign → update → complete
|
|
142
|
+
3. Primary agent: receives summary only
|
|
143
|
+
|
|
144
|
+
**Actions:**
|
|
145
|
+
- \`start\`: Start new session (goal required)
|
|
146
|
+
- \`squad\`: Create new squad (mission, operator required)
|
|
147
|
+
- \`assign\`: Assign task to agent (squadId, assignee, description required)
|
|
148
|
+
- \`update\`: Update task status (squadId, taskId, status required)
|
|
149
|
+
- \`complete\`: Complete task (squadId, taskId, success required)
|
|
150
|
+
- \`status\`: View session or squad status (squadId optional)
|
|
151
|
+
- \`watchdog\`: Run timeout watchdog (dryRun optional)
|
|
152
|
+
- \`list\`: List all squads in session
|
|
153
|
+
- \`plan\`: Analyze task dependencies and create parallel execution plan (squadId required)
|
|
154
|
+
- \`models\`: Query available models, their capabilities, and concurrency status
|
|
155
|
+
|
|
156
|
+
**Examples:**
|
|
157
|
+
- Start session: action="start", goal="Implement OAuth login"
|
|
158
|
+
- Create squad: action="squad", mission="Auth module", operator="auth-agent"
|
|
159
|
+
- Assign task: action="assign", squadId="squad-abc", assignee="worker-1", description="Login form"
|
|
160
160
|
- Complete task: action="complete", squadId="squad-abc", taskId="task-123", success=true`,
|
|
161
161
|
args: squadSchema,
|
|
162
162
|
async execute(args, context) {
|
|
@@ -67,14 +67,14 @@ function generateNewMaskSection(input) {
|
|
|
67
67
|
const usageRecord = input.usageNote
|
|
68
68
|
? ` - ${timestamp} (점수: ${input.effectivenessScore}) - ${input.usageNote}`
|
|
69
69
|
: ` - ${timestamp} (점수: ${input.effectivenessScore})`;
|
|
70
|
-
return `### ${input.name}
|
|
71
|
-
- **전문 분야**: ${input.expertise}
|
|
72
|
-
- **사고 방식**: ${input.thinkingStyle}
|
|
73
|
-
- **강점**: ${input.strengths}
|
|
74
|
-
- **적합한 작업**: ${input.suitableFor}
|
|
75
|
-
- **효과성 점수**: ${input.effectivenessScore}
|
|
76
|
-
- **사용 기록**:
|
|
77
|
-
${usageRecord}
|
|
70
|
+
return `### ${input.name}
|
|
71
|
+
- **전문 분야**: ${input.expertise}
|
|
72
|
+
- **사고 방식**: ${input.thinkingStyle}
|
|
73
|
+
- **강점**: ${input.strengths}
|
|
74
|
+
- **적합한 작업**: ${input.suitableFor}
|
|
75
|
+
- **효과성 점수**: ${input.effectivenessScore}
|
|
76
|
+
- **사용 기록**:
|
|
77
|
+
${usageRecord}
|
|
78
78
|
`;
|
|
79
79
|
}
|
|
80
80
|
function updateExistingMask(content, section, newScore, usageNote) {
|
|
@@ -122,19 +122,19 @@ function addNewMask(content, input) {
|
|
|
122
122
|
function readMasksFile(basePath) {
|
|
123
123
|
const masksPath = getMemoryPath('masks', basePath);
|
|
124
124
|
if (!existsSync(masksPath)) {
|
|
125
|
-
return `# 가면 라이브러리 (Mask Library)
|
|
126
|
-
|
|
127
|
-
이 파일은 가면술사가 사용하는 가면들의 정의와 효과성을 기록합니다.
|
|
128
|
-
성공적으로 사용된 가면들을 저장하여 향후 유사한 작업에 활용합니다.
|
|
129
|
-
|
|
130
|
-
---
|
|
131
|
-
|
|
132
|
-
## 검증된 가면 목록
|
|
133
|
-
|
|
134
|
-
---
|
|
135
|
-
|
|
136
|
-
${CUSTOM_SECTION_HEADER}
|
|
137
|
-
|
|
125
|
+
return `# 가면 라이브러리 (Mask Library)
|
|
126
|
+
|
|
127
|
+
이 파일은 가면술사가 사용하는 가면들의 정의와 효과성을 기록합니다.
|
|
128
|
+
성공적으로 사용된 가면들을 저장하여 향후 유사한 작업에 활용합니다.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 검증된 가면 목록
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
${CUSTOM_SECTION_HEADER}
|
|
137
|
+
|
|
138
138
|
`;
|
|
139
139
|
}
|
|
140
140
|
return readFileSync(masksPath, 'utf-8');
|
|
@@ -11,15 +11,15 @@ function getDbPath(basePath) {
|
|
|
11
11
|
function readRetrospectFile(basePath) {
|
|
12
12
|
const retrospectPath = getMemoryPath('retrospect', basePath);
|
|
13
13
|
if (!existsSync(retrospectPath)) {
|
|
14
|
-
return `# 회고록 (Retrospective Journal)
|
|
15
|
-
|
|
16
|
-
이 파일은 가면술사의 회고와 성찰을 기록합니다.
|
|
17
|
-
세션 종료 시, 주기적으로, 또는 수동 요청 시 회고를 수행하고 기록합니다.
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
${RETROSPECT_SECTION_HEADER}
|
|
22
|
-
|
|
14
|
+
return `# 회고록 (Retrospective Journal)
|
|
15
|
+
|
|
16
|
+
이 파일은 가면술사의 회고와 성찰을 기록합니다.
|
|
17
|
+
세션 종료 시, 주기적으로, 또는 수동 요청 시 회고를 수행하고 기록합니다.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
${RETROSPECT_SECTION_HEADER}
|
|
22
|
+
|
|
23
23
|
`;
|
|
24
24
|
}
|
|
25
25
|
return readFileSync(retrospectPath, 'utf-8');
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import type { ModelPoolEntry } from './config.js';
|
|
2
|
+
import { detectSubscriptionsFromConfig, detectSubscriptionsFromCli, type DetectedSubscription, type ProviderInfo, type SubscriptionDetectionResult } from './subscription-detection.js';
|
|
3
|
+
export { detectSubscriptionsFromCli, detectSubscriptionsFromConfig, };
|
|
4
|
+
export type { DetectedSubscription, ProviderInfo, SubscriptionDetectionResult, };
|
|
2
5
|
export interface GenerateAgentsResult {
|
|
3
6
|
created: string[];
|
|
4
7
|
updated: string[];
|
|
@@ -17,21 +20,6 @@ export declare function generatePoolAgentFiles(pool: ModelPoolEntry[], agentsDir
|
|
|
17
20
|
export declare function generatePoolAgentFilesFromConfig(projectDir: string, agentsDir: string, options?: {
|
|
18
21
|
force?: boolean;
|
|
19
22
|
}): GenerateAgentsResult;
|
|
20
|
-
export type DetectedSubscription = 'opencode-go' | 'zai-coding-plan';
|
|
21
|
-
export interface SubscriptionDetectionResult {
|
|
22
|
-
subscriptions: DetectedSubscription[];
|
|
23
|
-
primary: DetectedSubscription;
|
|
24
|
-
evidence: string[];
|
|
25
|
-
allProviders: ProviderInfo[];
|
|
26
|
-
}
|
|
27
|
-
export interface ProviderInfo {
|
|
28
|
-
name: string;
|
|
29
|
-
subscription: DetectedSubscription | null;
|
|
30
|
-
authType: string;
|
|
31
|
-
active: boolean;
|
|
32
|
-
}
|
|
33
|
-
export declare function detectSubscriptionsFromCli(): SubscriptionDetectionResult;
|
|
34
|
-
export declare function detectSubscriptionsFromConfig(opencodeConfig: Record<string, any>): SubscriptionDetectionResult;
|
|
35
23
|
export declare function buildPoolFromDetection(detection: SubscriptionDetectionResult): any[];
|
|
36
24
|
export declare function buildConfigFromDetection(detection: SubscriptionDetectionResult): Record<string, any>;
|
|
37
25
|
export declare function formatProviderChecklist(detection: SubscriptionDetectionResult): string;
|