@automagik/genie 4.260331.6 → 4.260331.8

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.
@@ -2,7 +2,7 @@
2
2
  "id": "genie",
3
3
  "name": "Genie",
4
4
  "description": "Skills, agents, and hooks for the Genie CLI terminal orchestration toolkit",
5
- "version": "4.260331.6",
5
+ "version": "4.260331.8",
6
6
  "configSchema": {
7
7
  "type": "object",
8
8
  "additionalProperties": false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automagik/genie",
3
- "version": "4.260331.6",
3
+ "version": "4.260331.8",
4
4
  "description": "Collaborative terminal toolkit for human + AI workflows",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genie",
3
- "version": "4.260331.6",
3
+ "version": "4.260331.8",
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"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genie-plugin",
3
- "version": "4.260331.6",
3
+ "version": "4.260331.8",
4
4
  "private": true,
5
5
  "description": "Runtime dependencies for genie bundled CLIs",
6
6
  "type": "module",
@@ -33,26 +33,6 @@ ALTER TABLE agents ADD CONSTRAINT agents_state_check
33
33
  'done', 'error', 'suspended', 'archived'
34
34
  ));
35
35
 
36
- -- ============================================================================
37
- -- App store: add 'archived' to approval_status CHECK constraint
38
- -- ============================================================================
39
-
40
- DO $$
41
- BEGIN
42
- EXECUTE (
43
- SELECT string_agg('ALTER TABLE app_store DROP CONSTRAINT ' || quote_ident(conname), '; ')
44
- FROM pg_constraint
45
- WHERE conrelid = 'app_store'::regclass
46
- AND contype = 'c'
47
- AND pg_get_constraintdef(oid) LIKE '%approval_status%'
48
- );
49
- EXCEPTION WHEN OTHERS THEN
50
- NULL;
51
- END $$;
52
-
53
- ALTER TABLE app_store ADD CONSTRAINT app_store_approval_status_check
54
- CHECK (approval_status IN ('local', 'pending', 'approved', 'rejected', 'archived'));
55
-
56
36
  -- ============================================================================
57
37
  -- Index: fast lookup for non-archived agents in directory listings
58
38
  -- ============================================================================
@@ -0,0 +1,4 @@
1
+ -- 018: Drop app_store tables — feature belongs in genie-os, not genie CLI.
2
+ DROP TABLE IF EXISTS app_versions CASCADE;
3
+ DROP TABLE IF EXISTS installed_apps CASCADE;
4
+ DROP TABLE IF EXISTS app_store CASCADE;
package/src/genie.ts CHANGED
@@ -53,16 +53,12 @@ import { registerExportCommands } from './term-commands/export.js';
53
53
  import * as historyCmd from './term-commands/history.js';
54
54
  import { registerImportCommands } from './term-commands/import.js';
55
55
  import { registerInitCommands } from './term-commands/init.js';
56
- import { registerInstallCommand } from './term-commands/install.js';
57
- import { registerItemUninstallCommand } from './term-commands/item-uninstall.js';
58
- import { registerItemUpdateCommand } from './term-commands/item-update.js';
59
56
  import { type LogOptions, logCommand } from './term-commands/log.js';
60
57
  import { registerMetricsCommands } from './term-commands/metrics.js';
61
58
  import { registerSendInboxCommands } from './term-commands/msg.js';
62
59
  import { registerNotifyCommands } from './term-commands/notify.js';
63
60
  import * as orchestrateCmd from './term-commands/orchestrate.js';
64
61
  import { registerProjectCommands } from './term-commands/project.js';
65
- import { registerPublishCommand } from './term-commands/publish.js';
66
62
  import {
67
63
  type QaCheckOptions,
68
64
  type QaOptions,
@@ -219,13 +215,6 @@ registerImportCommands(program);
219
215
  registerTemplateCommands(program);
220
216
  registerBriefCommands(program);
221
217
 
222
- // Item registry commands — install, publish (top-level), item uninstall/update (namespaced)
223
- registerInstallCommand(program);
224
- registerPublishCommand(program);
225
- const itemCmd = program.command('item').description('Item registry management');
226
- registerItemUninstallCommand(itemCmd);
227
- registerItemUpdateCommand(itemCmd);
228
-
229
218
  // ============================================================================
230
219
  // CLI audit hooks — record every command execution to audit_events
231
220
  // ============================================================================
@@ -3,13 +3,12 @@
3
3
  *
4
4
  * Scans {workspace}/agents/ for directories containing AGENTS.md (the discovery marker).
5
5
  * For each found agent, reads the git remote to derive repo_path, then registers or
6
- * updates the entry in the app_store.
6
+ * updates the entry in the agent directory.
7
7
  *
8
8
  * Handles lifecycle:
9
- * - New agent dir → register in app_store + agents table
9
+ * - New agent dir → register in agent directory
10
10
  * - Existing agent with stale data → update
11
- * - Archived agent reappearingreactivate with full backfill
12
- * - Missing agent dir → archive (never delete — preserves history)
11
+ * - Missing agent dirremove
13
12
  *
14
13
  * Used by:
15
14
  * - `genie serve` (startup sync + file watcher)
@@ -20,13 +19,7 @@
20
19
  import { execSync } from 'node:child_process';
21
20
  import { existsSync, watch as fsWatch, readdirSync, realpathSync } from 'node:fs';
22
21
  import { join } from 'node:path';
23
- import {
24
- getItemFromStore,
25
- listItemsFromStore,
26
- regenerateAgentCache,
27
- registerItemInStore,
28
- updateItemInStore,
29
- } from './agent-cache.js';
22
+ import * as directory from './agent-directory.js';
30
23
 
31
24
  // ============================================================================
32
25
  // Types
@@ -128,98 +121,6 @@ function discoverSingleAgent(workspaceRoot: string, agentName: string): AgentInf
128
121
  };
129
122
  }
130
123
 
131
- // ============================================================================
132
- // Archive / Reactivation helpers
133
- // ============================================================================
134
-
135
- /** Archive an agent in both agents table and app_store. Never deletes rows. */
136
- async function archiveAgent(name: string): Promise<boolean> {
137
- let archived = false;
138
- try {
139
- const { getConnection } = await import('./db.js');
140
- const sql = await getConnection();
141
- // Archive in agents table (set state='archived')
142
- const result = await sql`
143
- UPDATE agents SET state = 'archived', updated_at = now()
144
- WHERE (custom_name = ${name} OR role = ${name})
145
- AND (state IS NULL OR state != 'archived')
146
- `;
147
- if (result.count > 0) archived = true;
148
- } catch {
149
- // DB may not be available
150
- }
151
-
152
- // Archive in app_store (set approval_status='archived')
153
- try {
154
- const existing = await getItemFromStore(name).catch(() => null);
155
- if (existing && existing.approval_status !== 'archived') {
156
- await updateItemInStore(name, {
157
- manifest: {
158
- ...(existing.manifest as Record<string, unknown>),
159
- archived: true,
160
- archivedAt: new Date().toISOString(),
161
- },
162
- });
163
- archived = true;
164
- }
165
- } catch {
166
- // Best-effort
167
- }
168
-
169
- return archived;
170
- }
171
-
172
- /** Reactivate an archived agent with full backfill. */
173
- async function reactivateAgent(agent: AgentInfo): Promise<void> {
174
- const orgRepo = agent.repoUrl ? extractOrgRepo(agent.repoUrl) : null;
175
- const repoPath = orgRepo ?? agent.repoUrl ?? agent.dir;
176
-
177
- // Update app_store entry — clear archived flag, refresh paths
178
- const existing = await getItemFromStore(agent.name).catch(() => null);
179
- if (existing) {
180
- const manifest = { ...(existing.manifest as Record<string, unknown>) };
181
- manifest.archived = undefined;
182
- manifest.archivedAt = undefined;
183
- manifest.repo = repoPath;
184
- manifest.productRepo = agent.productRepo;
185
- manifest.source = 'auto-sync';
186
- await updateItemInStore(agent.name, {
187
- installPath: agent.dir,
188
- gitUrl: agent.repoUrl ?? undefined,
189
- manifest,
190
- });
191
- }
192
-
193
- // Reactivate in agents table
194
- try {
195
- const { getConnection } = await import('./db.js');
196
- const sql = await getConnection();
197
- await sql`
198
- UPDATE agents SET state = 'idle', repo_path = ${repoPath}, updated_at = now()
199
- WHERE (custom_name = ${agent.name} OR role = ${agent.name})
200
- AND state = 'archived'
201
- `;
202
- } catch {
203
- // DB may not be available
204
- }
205
-
206
- // Trigger session backfill for conversation history recovery
207
- await triggerSessionBackfill(agent).catch(() => {});
208
- }
209
-
210
- /** Trigger session backfill for a reactivated agent. */
211
- async function triggerSessionBackfill(_agent: AgentInfo): Promise<void> {
212
- try {
213
- const { getConnection, isAvailable } = await import('./db.js');
214
- if (!(await isAvailable())) return;
215
- const sql = await getConnection();
216
- const { startBackfill } = await import('./session-backfill.js');
217
- await startBackfill(sql);
218
- } catch {
219
- // Best-effort — backfill may not be ready
220
- }
221
- }
222
-
223
124
  // ============================================================================
224
125
  // Sync
225
126
  // ============================================================================
@@ -227,9 +128,8 @@ async function triggerSessionBackfill(_agent: AgentInfo): Promise<void> {
227
128
  /**
228
129
  * Sync all agents from {workspaceRoot}/agents/ into the directory.
229
130
  * - New agents → registered
230
- * - Existing agents with stale repo_path → updated
231
- * - Archived agents reappearing reactivated with backfill
232
- * - Agents in store whose dirs are gone → archived
131
+ * - Existing agents with stale data → updated
132
+ * - Agents whose dirs are gone removed
233
133
  *
234
134
  * Idempotent — safe to run repeatedly.
235
135
  */
@@ -249,15 +149,8 @@ export async function syncAgentDirectory(workspaceRoot: string): Promise<SyncRes
249
149
  }
250
150
  }
251
151
 
252
- // Archive agents in store whose dirs no longer exist
253
- await archiveMissingAgents(workspaceRoot, discoveredNames, result);
254
-
255
- // Regenerate cache after mutations
256
- const hasMutations =
257
- result.registered.length + result.updated.length + result.archived.length + result.reactivated.length;
258
- if (hasMutations > 0) {
259
- await regenerateAgentCache().catch(() => {});
260
- }
152
+ // Remove agents whose dirs no longer exist
153
+ await removeMissingAgents(discoveredNames, result);
261
154
 
262
155
  return result;
263
156
  }
@@ -267,58 +160,30 @@ export function printSyncResult(result: SyncResult): void {
267
160
  if (result.registered.length > 0) console.log(` Registered: ${result.registered.join(', ')}`);
268
161
  if (result.updated.length > 0) console.log(` Updated: ${result.updated.join(', ')}`);
269
162
  if (result.reactivated.length > 0) console.log(` Reactivated: ${result.reactivated.join(', ')}`);
270
- if (result.archived.length > 0) console.log(` Archived: ${result.archived.join(', ')}`);
163
+ if (result.archived.length > 0) console.log(` Removed: ${result.archived.join(', ')}`);
271
164
  if (result.unchanged.length > 0) console.log(` Unchanged: ${result.unchanged.join(', ')}`);
272
165
  for (const err of result.errors) {
273
166
  console.error(` Error (${err.name}): ${err.error}`);
274
167
  }
275
168
  const total = result.registered.length + result.updated.length + result.unchanged.length + result.reactivated.length;
276
- console.log(`\nSync complete: ${total} active agent(s), ${result.archived.length} archived.`);
169
+ console.log(`\nSync complete: ${total} active agent(s), ${result.archived.length} removed.`);
277
170
  }
278
171
 
279
- /** Archive app_store agents whose directories no longer exist on disk. */
280
- async function archiveMissingAgents(
281
- workspaceRoot: string,
282
- discoveredNames: Set<string>,
283
- result: SyncResult,
284
- ): Promise<void> {
172
+ /** Remove directory entries whose agent dirs no longer exist on disk. */
173
+ async function removeMissingAgents(discoveredNames: Set<string>, result: SyncResult): Promise<void> {
285
174
  try {
286
- const storeItems = await listItemsFromStore('agent');
287
- const agentsDir = join(workspaceRoot, 'agents');
288
-
289
- for (const item of storeItems) {
290
- if (discoveredNames.has(item.name)) continue;
291
- const manifest = (item.manifest ?? {}) as Record<string, unknown>;
292
- if (manifest.archived) continue; // already archived
293
- if (manifest.source !== 'auto-sync') continue; // only archive auto-synced agents
294
-
295
- // Verify the agent was from this workspace
296
- if (item.install_path && !item.install_path.startsWith(agentsDir)) continue;
175
+ const entries = await directory.ls();
176
+ for (const entry of entries) {
177
+ if (discoveredNames.has(entry.name)) continue;
178
+ if (entry.scope === 'built-in') continue;
179
+ if (!entry.dir || !entry.dir.includes('/agents/')) continue; // only remove auto-synced
297
180
 
298
- const archived = await archiveAgent(item.name);
299
- if (archived) result.archived.push(item.name);
181
+ const removed = await directory.rm(entry.name);
182
+ if (removed) result.archived.push(entry.name);
300
183
  }
301
184
  } catch {
302
- // Best-effort — don't block sync on archive failures
303
- }
304
- }
305
-
306
- /** Sync a single agent by name from the workspace (used by file watcher). */
307
- async function syncSingleAgentByName(workspaceRoot: string, agentName: string): Promise<string> {
308
- const agent = discoverSingleAgent(workspaceRoot, agentName);
309
- if (!agent) return 'not-found';
310
-
311
- const result: SyncResult = { registered: [], updated: [], unchanged: [], archived: [], reactivated: [], errors: [] };
312
- await syncSingleAgent(agent, result);
313
-
314
- if (result.registered.length > 0 || result.updated.length > 0 || result.reactivated.length > 0) {
315
- await regenerateAgentCache().catch(() => {});
185
+ // Best-effort
316
186
  }
317
-
318
- if (result.reactivated.length > 0) return 'reactivated';
319
- if (result.registered.length > 0) return 'registered';
320
- if (result.updated.length > 0) return 'updated';
321
- return 'unchanged';
322
187
  }
323
188
 
324
189
  /** Core sync logic for a single agent. */
@@ -326,39 +191,26 @@ async function syncSingleAgent(agent: AgentInfo, result: SyncResult): Promise<vo
326
191
  const orgRepo = agent.repoUrl ? extractOrgRepo(agent.repoUrl) : null;
327
192
  const repoPath = orgRepo ?? agent.repoUrl ?? agent.dir;
328
193
 
329
- const existing = await getItemFromStore(agent.name).catch(() => null);
194
+ const existing = await directory.get(agent.name);
330
195
 
331
196
  if (!existing) {
332
- await registerItemInStore({
197
+ await directory.add({
333
198
  name: agent.name,
334
- itemType: 'agent',
335
- installPath: agent.dir,
336
- gitUrl: agent.repoUrl ?? undefined,
337
- manifest: { promptMode: 'append', repo: repoPath, productRepo: agent.productRepo, source: 'auto-sync' },
199
+ dir: agent.dir,
200
+ repo: repoPath,
201
+ promptMode: 'append',
338
202
  });
339
203
  result.registered.push(agent.name);
340
204
  return;
341
205
  }
342
206
 
343
- // Check if this is a reactivation (was archived)
344
- const manifest = (existing.manifest ?? {}) as Record<string, unknown>;
345
- if (manifest.archived) {
346
- await reactivateAgent(agent);
347
- result.reactivated.push(agent.name);
348
- return;
349
- }
350
-
351
207
  // Check if update needed
352
- const needsUpdate =
353
- (manifest.repo as string) !== repoPath ||
354
- existing.install_path !== agent.dir ||
355
- (agent.productRepo && manifest.productRepo !== agent.productRepo);
208
+ const needsUpdate = existing.repo !== repoPath || existing.dir !== agent.dir;
356
209
 
357
210
  if (needsUpdate) {
358
- await updateItemInStore(agent.name, {
359
- installPath: agent.dir,
360
- gitUrl: agent.repoUrl ?? undefined,
361
- manifest: { ...manifest, repo: repoPath, productRepo: agent.productRepo, source: 'auto-sync' },
211
+ await directory.edit(agent.name, {
212
+ dir: agent.dir,
213
+ repo: repoPath,
362
214
  });
363
215
  result.updated.push(agent.name);
364
216
  } else {
@@ -374,21 +226,17 @@ interface AgentWatcher {
374
226
  close: () => void;
375
227
  }
376
228
 
377
- /** Process a single watched agent change register, update, archive, or reactivate. */
378
- async function processWatchedAgent(workspaceRoot: string, agentsDir: string, name: string): Promise<string | null> {
379
- const agentDir = join(agentsDir, name);
380
- if (existsSync(agentDir) && existsSync(join(agentDir, 'AGENTS.md'))) {
381
- const action = await syncSingleAgentByName(workspaceRoot, name);
382
- return action !== 'unchanged' && action !== 'not-found' ? action : null;
383
- }
384
- if (!existsSync(agentDir)) {
385
- const archived = await archiveAgent(name);
386
- if (archived) {
387
- await regenerateAgentCache().catch(() => {});
388
- return 'archived';
389
- }
390
- }
391
- return null;
229
+ /** Sync a single agent by name from the workspace (used by file watcher). */
230
+ async function syncSingleAgentByName(workspaceRoot: string, agentName: string): Promise<string> {
231
+ const agent = discoverSingleAgent(workspaceRoot, agentName);
232
+ if (!agent) return 'not-found';
233
+
234
+ const result: SyncResult = { registered: [], updated: [], unchanged: [], archived: [], reactivated: [], errors: [] };
235
+ await syncSingleAgent(agent, result);
236
+
237
+ if (result.registered.length > 0) return 'registered';
238
+ if (result.updated.length > 0) return 'updated';
239
+ return 'unchanged';
392
240
  }
393
241
 
394
242
  /**
@@ -396,8 +244,7 @@ async function processWatchedAgent(workspaceRoot: string, agentsDir: string, nam
396
244
  * Debounces changes with a 2s window.
397
245
  *
398
246
  * - New directory with AGENTS.md → auto-register
399
- * - Archived agent reappearing reactivate with backfill
400
- * - Removed directory → archive (never delete)
247
+ * - Removed directoryremove from directory
401
248
  */
402
249
  export function watchAgentDirectory(
403
250
  workspaceRoot: string,
@@ -440,3 +287,17 @@ export function watchAgentDirectory(
440
287
  },
441
288
  };
442
289
  }
290
+
291
+ /** Process a single watched agent change. */
292
+ async function processWatchedAgent(workspaceRoot: string, agentsDir: string, name: string): Promise<string | null> {
293
+ const agentDir = join(agentsDir, name);
294
+ if (existsSync(agentDir) && existsSync(join(agentDir, 'AGENTS.md'))) {
295
+ const action = await syncSingleAgentByName(workspaceRoot, name);
296
+ return action !== 'unchanged' && action !== 'not-found' ? action : null;
297
+ }
298
+ if (!existsSync(agentDir)) {
299
+ const removed = await directory.rm(name);
300
+ if (removed) return 'removed';
301
+ }
302
+ return null;
303
+ }
@@ -18,16 +18,7 @@ export interface ExportDocument {
18
18
  data: Record<string, unknown[]>;
19
19
  }
20
20
 
21
- export type ExportGroup =
22
- | 'boards'
23
- | 'tasks'
24
- | 'tags'
25
- | 'projects'
26
- | 'schedules'
27
- | 'agents'
28
- | 'apps'
29
- | 'comms'
30
- | 'config';
21
+ export type ExportGroup = 'boards' | 'tasks' | 'tags' | 'projects' | 'schedules' | 'agents' | 'comms' | 'config';
31
22
 
32
23
  /** Tables belonging to each export group */
33
24
  export const GROUP_TABLES: Record<ExportGroup, string[]> = {
@@ -37,7 +28,6 @@ export const GROUP_TABLES: Record<ExportGroup, string[]> = {
37
28
  projects: ['projects'],
38
29
  schedules: ['schedules'],
39
30
  agents: ['agents', 'agent_templates', 'agent_checkpoints'],
40
- apps: ['app_store', 'installed_apps', 'app_versions'],
41
31
  comms: ['conversations', 'conversation_members', 'messages', 'mailbox', 'team_chat', 'notification_preferences'],
42
32
  config: ['os_config', 'instances', 'warm_pool', 'golden_images'],
43
33
  };
@@ -49,7 +39,6 @@ export const ALL_GROUPS: ExportGroup[] = [
49
39
  'projects',
50
40
  'schedules',
51
41
  'agents',
52
- 'apps',
53
42
  'comms',
54
43
  'config',
55
44
  ];
@@ -21,23 +21,13 @@ const IMPORT_LEVELS: string[][] = [
21
21
  'task_types',
22
22
  'notification_preferences',
23
23
  // Optional (KhalOS)
24
- 'app_store',
25
24
  'os_config',
26
25
  'golden_images',
27
26
  'warm_pool',
28
27
  'instances',
29
28
  ],
30
29
  // Level 1: Depend on Level 0
31
- [
32
- 'triggers',
33
- 'boards',
34
- 'board_templates',
35
- 'agents',
36
- 'conversations',
37
- // Optional (KhalOS)
38
- 'installed_apps',
39
- 'app_versions',
40
- ],
30
+ ['triggers', 'boards', 'board_templates', 'agents', 'conversations'],
41
31
  // Level 2: Depend on Level 1
42
32
  ['tasks', 'runs', 'messages', 'conversation_members', 'mailbox', 'team_chat'],
43
33
  // Level 3: Depend on Level 2
@@ -48,6 +48,8 @@ export interface ProjectRow {
48
48
  name: string;
49
49
  repoPath: string | null;
50
50
  description: string | null;
51
+ leaderAgent: string | null;
52
+ tmuxSession: string | null;
51
53
  status: string;
52
54
  archivedAt: string | null;
53
55
  createdAt: string;
@@ -391,6 +393,8 @@ function mapProject(row: Record<string, unknown>): ProjectRow {
391
393
  name: row.name as string,
392
394
  repoPath: str(row.repo_path),
393
395
  description: str(row.description),
396
+ leaderAgent: str(row.leader_agent),
397
+ tmuxSession: str(row.tmux_session),
394
398
  status: strOrDefault(row.status, 'active'),
395
399
  archivedAt: str(row.archived_at),
396
400
  createdAt: String(row.created_at),
@@ -4,7 +4,6 @@
4
4
  */
5
5
 
6
6
  import type { Command } from 'commander';
7
- import { type StoreRow, listItemsFromStore, migrateAgentDirectory } from '../../lib/agent-cache.js';
8
7
  import * as directory from '../../lib/agent-directory.js';
9
8
  import { printSyncResult, syncAgentDirectory } from '../../lib/agent-sync.js';
10
9
  import { ALL_BUILTINS } from '../../lib/builtin-agents.js';
@@ -82,42 +81,8 @@ function printBuiltinAgentsTable(): void {
82
81
  console.log('');
83
82
  }
84
83
 
85
- function normalizeRoles(roles?: string[]): string[] | undefined {
86
- if (!roles) return undefined;
87
- return roles
88
- .flatMap((r) => r.split(','))
89
- .map((r) => r.trim())
90
- .filter(Boolean);
91
- }
92
-
93
- async function listEntries(json?: boolean, includeBuiltins?: boolean, includeArchived?: boolean): Promise<void> {
94
- await migrateAgentDirectory().catch(() => {});
95
-
96
- let entries: directory.ScopedDirectoryEntry[];
97
- try {
98
- const storeItems = await listItemsFromStore('agent');
99
- entries = storeItems
100
- .filter((item: StoreRow) => {
101
- if (includeArchived) return true;
102
- const manifest = (item.manifest ?? {}) as Record<string, unknown>;
103
- return !manifest.archived;
104
- })
105
- .map((item: StoreRow) => {
106
- const manifest = (item.manifest ?? {}) as Record<string, unknown>;
107
- return {
108
- name: item.name,
109
- dir: (item.install_path as string) ?? '',
110
- repo: (manifest.repo as string) ?? '',
111
- promptMode: ((manifest.promptMode as string) ?? 'append') as directory.PromptMode,
112
- model: manifest.model as string | undefined,
113
- roles: normalizeRoles(manifest.roles as string[] | undefined),
114
- registeredAt: item.installed_at as string,
115
- scope: (manifest.archived ? 'archived' : 'global') as directory.DirectoryScope,
116
- };
117
- });
118
- } catch {
119
- entries = await directory.ls();
120
- }
84
+ async function listEntries(json?: boolean, includeBuiltins?: boolean, _includeArchived?: boolean): Promise<void> {
85
+ const entries = await directory.ls();
121
86
 
122
87
  if (json) {
123
88
  const result: Record<string, unknown>[] = entries.map((e) => ({ ...e, builtin: false }));