@automagik/genie 4.260405.3 → 4.260405.4
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.
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"plugins": [
|
|
11
11
|
{
|
|
12
12
|
"name": "genie",
|
|
13
|
-
"version": "4.260405.
|
|
13
|
+
"version": "4.260405.4",
|
|
14
14
|
"source": "./plugins/genie",
|
|
15
15
|
"description": "Human-AI partnership for Claude Code. Share a terminal, orchestrate workers, evolve together. Brainstorm ideas, wish them into plans, make with parallel agents, ship as one team. A coding genie that grows with your project."
|
|
16
16
|
}
|
package/dist/genie.js
CHANGED
|
@@ -515,7 +515,12 @@ ${body}`;writeFileSync8(filePath,output,"utf-8")}function serializeSdkConfig(sdk
|
|
|
515
515
|
INSERT INTO agents (id, role, custom_name, started_at, metadata)
|
|
516
516
|
VALUES (${`dir:${entry.name}`}, ${entry.name}, ${entry.name}, now(), ${sql.json(metadata)})
|
|
517
517
|
ON CONFLICT (id) DO UPDATE SET metadata = ${sql.json(metadata)}
|
|
518
|
-
`,full}async function rm3(name,_options){let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db));return(await(await getConnection2())`DELETE FROM agents WHERE id = ${`dir:${name}`}`).count>0}async function resolve3(name){try{let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),rows=await(await getConnection2())`
|
|
518
|
+
`,full}async function rm3(name,_options){let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db));return(await(await getConnection2())`DELETE FROM agents WHERE id = ${`dir:${name}`}`).count>0}async function resolve3(name){try{let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),rows=await(await getConnection2())`
|
|
519
|
+
SELECT role, metadata FROM agents
|
|
520
|
+
WHERE role = ${name}
|
|
521
|
+
ORDER BY (CASE WHEN id LIKE 'dir:%' THEN 0 ELSE 1 END), started_at DESC
|
|
522
|
+
LIMIT 1
|
|
523
|
+
`;if(rows.length>0){let meta=parseMetadata(rows[0].metadata);return{entry:roleToEntry(name,void 0,meta),builtin:!1}}}catch{}let builtinRole=BUILTIN_ROLES.find((r)=>r.name===name);if(builtinRole)return{entry:builtinToEntry(builtinRole),builtin:!0};let councilMember=BUILTIN_COUNCIL_MEMBERS.find((m)=>m.name===name);if(councilMember)return{entry:builtinToEntry(councilMember),builtin:!0};return null}async function findSessionByRepo(repoPath){try{let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),rows=await(await getConnection2())`
|
|
519
524
|
SELECT session FROM agents
|
|
520
525
|
WHERE repo_path = ${repoPath}
|
|
521
526
|
AND session IS NOT NULL
|
|
@@ -528,7 +533,7 @@ ${body}`;writeFileSync8(filePath,output,"utf-8")}function serializeSdkConfig(sdk
|
|
|
528
533
|
FROM agents a
|
|
529
534
|
LEFT JOIN executors e ON a.current_executor_id = e.id
|
|
530
535
|
WHERE a.role IS NOT NULL
|
|
531
|
-
ORDER BY a.role, a.started_at DESC
|
|
536
|
+
ORDER BY a.role, (CASE WHEN a.id LIKE 'dir:%' THEN 0 ELSE 1 END), a.started_at DESC
|
|
532
537
|
`;for(let row of rows){let name=row.role;if(!seen.has(name)){let meta=parseMetadata(row.metadata),entry=roleToEntry(name,row.team,meta),repoPath=row.repo_path;if(repoPath)entry.dir=repoPath,entry.repo=repoPath;result2.push({...entry,scope:"global"}),seen.add(name)}}}catch{}return result2}async function get2(name,_options){return(await resolve3(name))?.entry??null}async function edit(name,updates,_options){if(updates.dir){if(!existsSync18(updates.dir))throw Error(`Directory does not exist: ${updates.dir}`);let agentsPath=join20(updates.dir,"AGENTS.md");if(!existsSync18(agentsPath))throw Error(`AGENTS.md not found in ${updates.dir}.`)}let existing=await get2(name);if(!existing)throw Error(`Agent "${name}" not found in directory.`);let updated=Object.assign(existing,updates),metadataPatch=buildMetadata(updated);try{let{getConnection:getConnection2}=await Promise.resolve().then(() => (init_db(),exports_db)),sql=await getConnection2();if((await sql`
|
|
533
538
|
UPDATE agents
|
|
534
539
|
SET metadata = metadata || ${sql.json(metadataPatch)}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genie",
|
|
3
|
-
"version": "4.260405.
|
|
3
|
+
"version": "4.260405.4",
|
|
4
4
|
"description": "Human-AI partnership for Claude Code. Share a terminal, orchestrate workers, evolve together. Brainstorm ideas, turn them into wishes, execute with /work, validate with /review, and ship as one team.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Namastex Labs"
|
|
@@ -79,6 +79,22 @@ describe.skipIf(!DB_AVAILABLE)('pg', () => {
|
|
|
79
79
|
test('returns null for unknown name', async () => {
|
|
80
80
|
expect(await directory.resolve('nonexistent-xyz')).toBeNull();
|
|
81
81
|
});
|
|
82
|
+
|
|
83
|
+
test('prefers dir: row over stale runtime rows with same role', async () => {
|
|
84
|
+
const sql = await getConnection();
|
|
85
|
+
// Insert stale runtime row (empty metadata, older started_at)
|
|
86
|
+
await sql`INSERT INTO agents (id, pane_id, session, repo_path, state, role, started_at, last_state_change, metadata) VALUES ('stale-uuid', '%1', 's', '/tmp', 'done', 'my-dup', now() - interval '1 hour', now(), '{}')`;
|
|
87
|
+
// Insert another stale runtime row (empty metadata, recent started_at — would win ORDER BY started_at DESC)
|
|
88
|
+
await sql`INSERT INTO agents (id, pane_id, session, repo_path, state, role, started_at, last_state_change, metadata) VALUES ('recent-uuid', '%2', 's', '/tmp', 'done', 'my-dup', now(), now(), '{}')`;
|
|
89
|
+
// Insert directory row (has real metadata — oldest started_at, but should still win via dir: prefix)
|
|
90
|
+
await sql`INSERT INTO agents (id, role, custom_name, started_at, metadata) VALUES ('dir:my-dup', 'my-dup', 'my-dup', now() - interval '2 hours', '{"dir":"/some/path","model":"opus","color":"teal","description":"The real entry"}')`;
|
|
91
|
+
|
|
92
|
+
const resolved = await directory.resolve('my-dup');
|
|
93
|
+
expect(resolved).not.toBeNull();
|
|
94
|
+
expect(resolved!.entry.model).toBe('opus');
|
|
95
|
+
expect(resolved!.entry.color).toBe('teal');
|
|
96
|
+
expect(resolved!.entry.description).toBe('The real entry');
|
|
97
|
+
});
|
|
82
98
|
});
|
|
83
99
|
|
|
84
100
|
// ============================================================================
|
|
@@ -101,6 +117,18 @@ describe.skipIf(!DB_AVAILABLE)('pg', () => {
|
|
|
101
117
|
expect(await directory.ls()).toEqual([]);
|
|
102
118
|
});
|
|
103
119
|
|
|
120
|
+
test('ls prefers dir: row over stale runtime rows', async () => {
|
|
121
|
+
const sql = await getConnection();
|
|
122
|
+
await sql`INSERT INTO agents (id, pane_id, session, repo_path, state, role, started_at, last_state_change, metadata) VALUES ('runtime-1', '%1', 's', '/tmp', 'done', 'ls-dup', now(), now(), '{}')`;
|
|
123
|
+
await sql`INSERT INTO agents (id, role, custom_name, started_at, metadata) VALUES ('dir:ls-dup', 'ls-dup', 'ls-dup', now() - interval '1 hour', '{"dir":"/real/dir","model":"sonnet","description":"Directory entry"}')`;
|
|
124
|
+
|
|
125
|
+
const entries = await directory.ls();
|
|
126
|
+
const entry = entries.find((e) => e.name === 'ls-dup');
|
|
127
|
+
expect(entry).not.toBeNull();
|
|
128
|
+
expect(entry!.model).toBe('sonnet');
|
|
129
|
+
expect(entry!.description).toBe('Directory entry');
|
|
130
|
+
});
|
|
131
|
+
|
|
104
132
|
test('ls includes metadata fields from PG', async () => {
|
|
105
133
|
const sql = await getConnection();
|
|
106
134
|
await sql`INSERT INTO agents (id, role, custom_name, started_at, metadata) VALUES ('dir:ls-meta', 'ls-meta', 'ls-meta', now(), '{"model":"opus","color":"green","provider":"codex","description":"Ls test"}')`;
|
|
@@ -163,7 +163,12 @@ export async function resolve(name: string): Promise<ResolvedAgent | null> {
|
|
|
163
163
|
try {
|
|
164
164
|
const { getConnection } = await import('./db.js');
|
|
165
165
|
const sql = await getConnection();
|
|
166
|
-
const rows = await sql`
|
|
166
|
+
const rows = await sql`
|
|
167
|
+
SELECT role, metadata FROM agents
|
|
168
|
+
WHERE role = ${name}
|
|
169
|
+
ORDER BY (CASE WHEN id LIKE 'dir:%' THEN 0 ELSE 1 END), started_at DESC
|
|
170
|
+
LIMIT 1
|
|
171
|
+
`;
|
|
167
172
|
if (rows.length > 0) {
|
|
168
173
|
const meta = parseMetadata(rows[0].metadata);
|
|
169
174
|
return { entry: roleToEntry(name, undefined, meta), builtin: false };
|
|
@@ -228,7 +233,7 @@ export async function ls(): Promise<ScopedDirectoryEntry[]> {
|
|
|
228
233
|
FROM agents a
|
|
229
234
|
LEFT JOIN executors e ON a.current_executor_id = e.id
|
|
230
235
|
WHERE a.role IS NOT NULL
|
|
231
|
-
ORDER BY a.role, a.started_at DESC
|
|
236
|
+
ORDER BY a.role, (CASE WHEN a.id LIKE 'dir:%' THEN 0 ELSE 1 END), a.started_at DESC
|
|
232
237
|
`;
|
|
233
238
|
for (const row of rows) {
|
|
234
239
|
const name = row.role as string;
|