@proletariat/cli 0.3.16 → 0.3.18
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/dist/commands/action/create.d.ts +1 -0
- package/dist/commands/action/create.js +74 -38
- package/dist/commands/action/delete.d.ts +1 -0
- package/dist/commands/action/delete.js +23 -24
- package/dist/commands/action/index.d.ts +1 -0
- package/dist/commands/action/index.js +5 -10
- package/dist/commands/action/list.d.ts +1 -0
- package/dist/commands/action/list.js +3 -1
- package/dist/commands/action/run.d.ts +1 -0
- package/dist/commands/action/run.js +44 -32
- package/dist/commands/action/show.d.ts +2 -0
- package/dist/commands/action/update.d.ts +1 -0
- package/dist/commands/action/update.js +80 -39
- package/dist/commands/agent/auth.d.ts +2 -0
- package/dist/commands/agent/auth.js +44 -3
- package/dist/commands/agent/discover.d.ts +2 -0
- package/dist/commands/agent/discover.js +35 -3
- package/dist/commands/agent/index.d.ts +1 -0
- package/dist/commands/agent/index.js +25 -45
- package/dist/commands/agent/list.d.ts +8 -3
- package/dist/commands/agent/list.js +16 -29
- package/dist/commands/agent/login.d.ts +1 -0
- package/dist/commands/agent/login.js +14 -32
- package/dist/commands/agent/rebuild.d.ts +1 -0
- package/dist/commands/agent/rebuild.js +2 -2
- package/dist/commands/agent/remove.d.ts +17 -0
- package/dist/commands/agent/remove.js +144 -0
- package/dist/commands/agent/restart.d.ts +1 -0
- package/dist/commands/agent/restart.js +2 -2
- package/dist/commands/agent/shell.d.ts +1 -0
- package/dist/commands/agent/shell.js +63 -76
- package/dist/commands/agent/staff/add.d.ts +1 -0
- package/dist/commands/agent/staff/add.js +7 -1
- package/dist/commands/agent/staff/index.d.ts +1 -0
- package/dist/commands/agent/staff/index.js +5 -4
- package/dist/commands/agent/staff/remove.d.ts +1 -0
- package/dist/commands/agent/status.d.ts +1 -0
- package/dist/commands/agent/status.js +11 -23
- package/dist/commands/agent/temp/cleanup.d.ts +1 -0
- package/dist/commands/agent/temp/index.d.ts +1 -0
- package/dist/commands/agent/temp/index.js +4 -3
- package/dist/commands/agent/themes/index.d.ts +1 -0
- package/dist/commands/agent/themes/index.js +9 -3
- package/dist/commands/agent/themes/set.d.ts +1 -0
- package/dist/commands/agent/themes/set.js +7 -1
- package/dist/commands/agent/visit.d.ts +1 -0
- package/dist/commands/agent/visit.js +11 -23
- package/dist/commands/autocomplete/setup.d.ts +11 -0
- package/dist/commands/autocomplete/setup.js +113 -8
- package/dist/commands/board/index.d.ts +4 -0
- package/dist/commands/board/index.js +32 -30
- package/dist/commands/board/watch.d.ts +2 -0
- package/dist/commands/branch/create.d.ts +1 -0
- package/dist/commands/branch/create.js +33 -41
- package/dist/commands/branch/index.d.ts +1 -0
- package/dist/commands/branch/list.d.ts +2 -0
- package/dist/commands/branch/validate.d.ts +2 -0
- package/dist/commands/branch/where.d.ts +1 -0
- package/dist/commands/claude.d.ts +6 -0
- package/dist/commands/claude.js +166 -116
- package/dist/commands/commit.d.ts +6 -0
- package/dist/commands/commit.js +68 -73
- package/dist/commands/config/index.d.ts +13 -0
- package/dist/commands/config/index.js +142 -98
- package/dist/commands/docker/clean.d.ts +2 -1
- package/dist/commands/docker/clean.js +20 -29
- package/dist/commands/docker/index.d.ts +1 -0
- package/dist/commands/docker/index.js +37 -41
- package/dist/commands/docker/prune.d.ts +2 -1
- package/dist/commands/docker/prune.js +20 -27
- package/dist/commands/docker/restart.d.ts +2 -1
- package/dist/commands/docker/restart.js +20 -29
- package/dist/commands/docker/stop.d.ts +2 -1
- package/dist/commands/docker/stop.js +20 -29
- package/dist/commands/epic/activate.d.ts +1 -0
- package/dist/commands/epic/archive.d.ts +1 -0
- package/dist/commands/epic/create.d.ts +1 -0
- package/dist/commands/epic/index.d.ts +1 -0
- package/dist/commands/epic/link/block.d.ts +1 -0
- package/dist/commands/epic/link/duplicates.d.ts +1 -0
- package/dist/commands/epic/link/index.d.ts +1 -0
- package/dist/commands/epic/link/relates.d.ts +1 -0
- package/dist/commands/epic/link/remove.d.ts +1 -0
- package/dist/commands/epic/list.d.ts +2 -0
- package/dist/commands/epic/move.d.ts +1 -0
- package/dist/commands/epic/progress.d.ts +1 -0
- package/dist/commands/epic/project.d.ts +1 -0
- package/dist/commands/epic/reorder.d.ts +1 -0
- package/dist/commands/epic/spec.d.ts +1 -0
- package/dist/commands/epic/ticket.d.ts +1 -0
- package/dist/commands/epic/view.d.ts +1 -0
- package/dist/commands/execution/index.d.ts +1 -0
- package/dist/commands/execution/index.js +9 -25
- package/dist/commands/execution/list.d.ts +2 -0
- package/dist/commands/execution/logs.d.ts +1 -0
- package/dist/commands/execution/logs.js +6 -16
- package/dist/commands/execution/stop.d.ts +1 -0
- package/dist/commands/execution/stop.js +4 -15
- package/dist/commands/gh/index.d.ts +1 -0
- package/dist/commands/gh/index.js +27 -27
- package/dist/commands/gh/login.d.ts +4 -0
- package/dist/commands/gh/login.js +31 -0
- package/dist/commands/gh/status.d.ts +4 -0
- package/dist/commands/gh/status.js +27 -4
- package/dist/commands/gh/token.d.ts +4 -0
- package/dist/commands/gh/token.js +49 -5
- package/dist/commands/phase/create.d.ts +1 -1
- package/dist/commands/phase/create.js +116 -74
- package/dist/commands/phase/delete.d.ts +1 -0
- package/dist/commands/phase/delete.js +23 -22
- package/dist/commands/phase/list.d.ts +1 -0
- package/dist/commands/phase/list.js +3 -5
- package/dist/commands/phase/move.d.ts +1 -0
- package/dist/commands/phase/move.js +39 -39
- package/dist/commands/phase/template/apply.d.ts +1 -0
- package/dist/commands/phase/template/create.d.ts +2 -0
- package/dist/commands/phase/template/delete.d.ts +1 -0
- package/dist/commands/phase/template/index.d.ts +1 -0
- package/dist/commands/phase/template/list.d.ts +1 -0
- package/dist/commands/phase/template/update.d.ts +2 -0
- package/dist/commands/phase/update.d.ts +1 -1
- package/dist/commands/phase/update.js +89 -55
- package/dist/commands/pmo/init.d.ts +2 -0
- package/dist/commands/pmo/init.js +84 -22
- package/dist/commands/pr/create.d.ts +12 -3
- package/dist/commands/pr/create.js +130 -147
- package/dist/commands/pr/index.d.ts +6 -3
- package/dist/commands/pr/index.js +41 -39
- package/dist/commands/pr/link.d.ts +7 -3
- package/dist/commands/pr/link.js +126 -150
- package/dist/commands/pr/status.d.ts +6 -3
- package/dist/commands/pr/status.js +101 -126
- package/dist/commands/project/archive.d.ts +1 -0
- package/dist/commands/project/archive.js +15 -20
- package/dist/commands/project/create.d.ts +1 -0
- package/dist/commands/project/create.js +13 -5
- package/dist/commands/project/delete.d.ts +1 -0
- package/dist/commands/project/delete.js +14 -28
- package/dist/commands/project/index.d.ts +1 -0
- package/dist/commands/project/index.js +0 -5
- package/dist/commands/project/list.d.ts +2 -0
- package/dist/commands/project/list.js +21 -3
- package/dist/commands/project/spec.d.ts +1 -0
- package/dist/commands/project/spec.js +17 -23
- package/dist/commands/project/unarchive.d.ts +2 -0
- package/dist/commands/project/unarchive.js +21 -2
- package/dist/commands/project/view.d.ts +1 -0
- package/dist/commands/project/view.js +34 -22
- package/dist/commands/repo/add.d.ts +2 -0
- package/dist/commands/repo/add.js +44 -1
- package/dist/commands/repo/index.d.ts +1 -0
- package/dist/commands/repo/index.js +20 -38
- package/dist/commands/repo/list.d.ts +2 -0
- package/dist/commands/repo/remove.d.ts +1 -0
- package/dist/commands/repo/remove.js +45 -63
- package/dist/commands/repo/view.d.ts +2 -0
- package/dist/commands/repo/view.js +30 -5
- package/dist/commands/roadmap/add-project.d.ts +1 -0
- package/dist/commands/roadmap/create.d.ts +1 -0
- package/dist/commands/roadmap/delete.d.ts +1 -0
- package/dist/commands/roadmap/generate.d.ts +1 -0
- package/dist/commands/roadmap/index.d.ts +1 -0
- package/dist/commands/roadmap/list.d.ts +2 -0
- package/dist/commands/roadmap/remove-project.d.ts +1 -0
- package/dist/commands/roadmap/reorder.d.ts +1 -0
- package/dist/commands/roadmap/update.d.ts +1 -0
- package/dist/commands/roadmap/view.d.ts +1 -0
- package/dist/commands/session/attach.d.ts +1 -0
- package/dist/commands/session/index.d.ts +1 -0
- package/dist/commands/session/index.js +8 -25
- package/dist/commands/session/list.d.ts +2 -0
- package/dist/commands/spec/create.d.ts +1 -1
- package/dist/commands/spec/create.js +64 -65
- package/dist/commands/spec/index.d.ts +1 -0
- package/dist/commands/spec/index.js +36 -22
- package/dist/commands/spec/link/depends.d.ts +1 -0
- package/dist/commands/spec/link/depends.js +6 -6
- package/dist/commands/spec/link/duplicates.d.ts +1 -0
- package/dist/commands/spec/link/duplicates.js +6 -6
- package/dist/commands/spec/link/index.d.ts +2 -1
- package/dist/commands/spec/link/index.js +0 -4
- package/dist/commands/spec/link/relates.d.ts +1 -0
- package/dist/commands/spec/link/relates.js +6 -6
- package/dist/commands/spec/link/remove.d.ts +2 -1
- package/dist/commands/spec/link/remove.js +6 -6
- package/dist/commands/spec/list.d.ts +2 -0
- package/dist/commands/spec/list.js +25 -0
- package/dist/commands/spec/plan.d.ts +2 -1
- package/dist/commands/spec/plan.js +19 -26
- package/dist/commands/spec/ticket.d.ts +2 -1
- package/dist/commands/spec/ticket.js +48 -34
- package/dist/commands/spec/view.d.ts +2 -1
- package/dist/commands/spec/view.js +25 -16
- package/dist/commands/status/create.d.ts +1 -1
- package/dist/commands/status/create.js +80 -64
- package/dist/commands/status/delete.d.ts +2 -1
- package/dist/commands/status/delete.js +26 -22
- package/dist/commands/status/index.d.ts +1 -0
- package/dist/commands/status/index.js +26 -19
- package/dist/commands/status/list.d.ts +1 -0
- package/dist/commands/status/list.js +12 -7
- package/dist/commands/status/move.d.ts +2 -1
- package/dist/commands/status/move.js +62 -61
- package/dist/commands/status/update.d.ts +2 -2
- package/dist/commands/status/update.js +110 -77
- package/dist/commands/template/delete.d.ts +1 -0
- package/dist/commands/template/delete.js +47 -48
- package/dist/commands/template/index.d.ts +1 -0
- package/dist/commands/template/index.js +26 -33
- package/dist/commands/template/list.d.ts +1 -0
- package/dist/commands/template/phase/create.d.ts +1 -0
- package/dist/commands/template/phase/create.js +6 -0
- package/dist/commands/template/phase/index.d.ts +1 -0
- package/dist/commands/template/phase/index.js +27 -26
- package/dist/commands/template/phase/update.d.ts +1 -0
- package/dist/commands/template/phase/update.js +6 -0
- package/dist/commands/template/ticket/index.d.ts +1 -0
- package/dist/commands/template/ticket/index.js +27 -26
- package/dist/commands/template/ticket/save.d.ts +1 -0
- package/dist/commands/template/ticket/save.js +6 -0
- package/dist/commands/terminal/title.d.ts +26 -0
- package/dist/commands/terminal/title.js +37 -3
- package/dist/commands/ticket/bulk.d.ts +1 -0
- package/dist/commands/ticket/complete.d.ts +1 -0
- package/dist/commands/ticket/complete.js +18 -14
- package/dist/commands/ticket/create.d.ts +1 -0
- package/dist/commands/ticket/create.js +45 -41
- package/dist/commands/ticket/delete.d.ts +1 -0
- package/dist/commands/ticket/delete.js +1 -1
- package/dist/commands/ticket/edit.d.ts +1 -0
- package/dist/commands/ticket/edit.js +1 -1
- package/dist/commands/ticket/epic.d.ts +1 -0
- package/dist/commands/ticket/epic.js +2 -2
- package/dist/commands/ticket/index.d.ts +1 -0
- package/dist/commands/ticket/link/block.d.ts +1 -0
- package/dist/commands/ticket/link/block.js +1 -1
- package/dist/commands/ticket/link/duplicates.d.ts +1 -0
- package/dist/commands/ticket/link/duplicates.js +1 -1
- package/dist/commands/ticket/link/index.d.ts +1 -0
- package/dist/commands/ticket/link/index.js +9 -8
- package/dist/commands/ticket/link/relates.d.ts +1 -0
- package/dist/commands/ticket/link/relates.js +1 -1
- package/dist/commands/ticket/link/remove.d.ts +1 -0
- package/dist/commands/ticket/link/remove.js +1 -1
- package/dist/commands/ticket/list.d.ts +2 -0
- package/dist/commands/ticket/move.d.ts +1 -0
- package/dist/commands/ticket/move.js +27 -19
- package/dist/commands/ticket/project.d.ts +1 -0
- package/dist/commands/ticket/project.js +3 -3
- package/dist/commands/ticket/reassign.d.ts +1 -0
- package/dist/commands/ticket/reassign.js +1 -1
- package/dist/commands/ticket/spec.d.ts +1 -0
- package/dist/commands/ticket/spec.js +3 -3
- package/dist/commands/ticket/status.d.ts +1 -0
- package/dist/commands/ticket/status.js +1 -1
- package/dist/commands/ticket/template/apply.d.ts +1 -0
- package/dist/commands/ticket/template/create.d.ts +2 -0
- package/dist/commands/ticket/template/delete.d.ts +1 -0
- package/dist/commands/ticket/template/index.d.ts +1 -0
- package/dist/commands/ticket/template/list.d.ts +1 -0
- package/dist/commands/ticket/template/save.d.ts +2 -0
- package/dist/commands/ticket/update.d.ts +1 -0
- package/dist/commands/ticket/update.js +1 -1
- package/dist/commands/ticket/view.d.ts +1 -0
- package/dist/commands/ticket/view.js +1 -1
- package/dist/commands/work/complete.d.ts +1 -0
- package/dist/commands/work/index.d.ts +1 -0
- package/dist/commands/work/ready.d.ts +1 -0
- package/dist/commands/work/revise.d.ts +1 -0
- package/dist/commands/work/spawn-all.d.ts +2 -0
- package/dist/commands/work/spawn-all.js +11 -4
- package/dist/commands/work/spawn.d.ts +1 -0
- package/dist/commands/work/spawn.js +261 -166
- package/dist/commands/work/start.d.ts +1 -0
- package/dist/commands/work/start.js +270 -189
- package/dist/commands/work/watch.d.ts +1 -0
- package/dist/commands/work/watch.js +63 -58
- package/dist/commands/workflow/create.d.ts +1 -0
- package/dist/commands/workflow/create.js +2 -4
- package/dist/commands/workflow/delete.d.ts +1 -0
- package/dist/commands/workflow/delete.js +21 -33
- package/dist/commands/workflow/index.d.ts +1 -0
- package/dist/commands/workflow/list.d.ts +1 -0
- package/dist/commands/workflow/list.js +3 -6
- package/dist/commands/workflow/switch.d.ts +2 -0
- package/dist/commands/workflow/switch.js +46 -21
- package/dist/commands/workflow/view.d.ts +1 -0
- package/dist/commands/workflow/view.js +18 -27
- package/dist/commands/workspace/remove.d.ts +2 -2
- package/dist/commands/workspace/remove.js +16 -21
- package/dist/commands/workspace/use.d.ts +2 -2
- package/dist/commands/workspace/use.js +12 -18
- package/dist/lib/agents/commands.d.ts +1 -1
- package/dist/lib/agents/commands.js +4 -4
- package/dist/lib/database/drizzle-schema.d.ts +5009 -0
- package/dist/lib/database/drizzle-schema.js +699 -0
- package/dist/lib/database/drizzle.d.ts +29 -0
- package/dist/lib/database/drizzle.js +37 -0
- package/dist/lib/database/index.d.ts +1 -0
- package/dist/lib/database/index.js +1 -1
- package/dist/lib/execution/config.d.ts +6 -0
- package/dist/lib/execution/config.js +31 -13
- package/dist/lib/execution/devcontainer.js +13 -7
- package/dist/lib/execution/runners.js +24 -7
- package/dist/lib/execution/spawner.js +19 -0
- package/dist/lib/flags/index.d.ts +4 -0
- package/dist/lib/flags/index.js +4 -0
- package/dist/lib/flags/resolver.d.ts +224 -0
- package/dist/lib/flags/resolver.js +313 -0
- package/dist/lib/pmo/base-command.d.ts +53 -3
- package/dist/lib/pmo/base-command.js +92 -13
- package/dist/lib/pmo/find-pmo.d.ts +1 -1
- package/dist/lib/pmo/find-pmo.js +4 -4
- package/dist/lib/pmo/index.d.ts +1 -1
- package/dist/lib/pmo/index.js +1 -1
- package/dist/lib/pmo/storage/helpers.js +2 -1
- package/dist/lib/pmo/storage/index.d.ts +9 -0
- package/dist/lib/pmo/storage/index.js +14 -0
- package/dist/lib/pmo/storage/projects.d.ts +28 -13
- package/dist/lib/pmo/storage/projects.js +110 -34
- package/dist/lib/pmo/storage/roadmaps.d.ts +2 -0
- package/dist/lib/pmo/storage/roadmaps.js +182 -111
- package/dist/lib/pmo/storage/specs.js +13 -16
- package/dist/lib/pmo/storage/subtasks.js +17 -2
- package/dist/lib/pmo/storage/tickets.d.ts +12 -2
- package/dist/lib/pmo/storage/tickets.js +63 -5
- package/dist/lib/pmo/storage/types.d.ts +7 -3
- package/dist/lib/pmo/storage/views.d.ts +12 -1
- package/dist/lib/pmo/storage/views.js +61 -6
- package/dist/lib/prompt-command.d.ts +90 -0
- package/dist/lib/prompt-command.js +102 -0
- package/dist/lib/prompt-json.d.ts +34 -4
- package/dist/lib/prompt-json.js +35 -3
- package/dist/lib/repos/index.js +15 -15
- package/dist/lib/workspace.d.ts +4 -3
- package/dist/lib/workspace.js +3 -3
- package/oclif.manifest.json +4610 -2997
- package/package.json +13 -5
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drizzle ORM Database Connection
|
|
3
|
+
*
|
|
4
|
+
* This module provides type-safe database connections using Drizzle ORM
|
|
5
|
+
* with better-sqlite3 as the underlying driver.
|
|
6
|
+
*/
|
|
7
|
+
import { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
|
|
8
|
+
import Database from 'better-sqlite3';
|
|
9
|
+
import * as schema from './drizzle-schema.js';
|
|
10
|
+
export type DrizzleDB = BetterSQLite3Database<typeof schema>;
|
|
11
|
+
/**
|
|
12
|
+
* Create a Drizzle database connection from an existing better-sqlite3 database.
|
|
13
|
+
* This allows gradual migration by wrapping existing database connections.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createDrizzleConnection(db: Database.Database): DrizzleDB;
|
|
16
|
+
/**
|
|
17
|
+
* Create a new Drizzle database connection from a file path.
|
|
18
|
+
* Configures pragmas for optimal performance and reliability.
|
|
19
|
+
*/
|
|
20
|
+
export declare function openDrizzleDatabase(dbPath: string): {
|
|
21
|
+
db: DrizzleDB;
|
|
22
|
+
sqliteDb: Database.Database;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Close a Drizzle database connection.
|
|
26
|
+
* Since Drizzle wraps better-sqlite3, we need to close the underlying connection.
|
|
27
|
+
*/
|
|
28
|
+
export declare function closeDrizzleDatabase(sqliteDb: Database.Database): void;
|
|
29
|
+
export * from './drizzle-schema.js';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drizzle ORM Database Connection
|
|
3
|
+
*
|
|
4
|
+
* This module provides type-safe database connections using Drizzle ORM
|
|
5
|
+
* with better-sqlite3 as the underlying driver.
|
|
6
|
+
*/
|
|
7
|
+
import { drizzle } from 'drizzle-orm/better-sqlite3';
|
|
8
|
+
import Database from 'better-sqlite3';
|
|
9
|
+
import * as schema from './drizzle-schema.js';
|
|
10
|
+
/**
|
|
11
|
+
* Create a Drizzle database connection from an existing better-sqlite3 database.
|
|
12
|
+
* This allows gradual migration by wrapping existing database connections.
|
|
13
|
+
*/
|
|
14
|
+
export function createDrizzleConnection(db) {
|
|
15
|
+
return drizzle(db, { schema });
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Create a new Drizzle database connection from a file path.
|
|
19
|
+
* Configures pragmas for optimal performance and reliability.
|
|
20
|
+
*/
|
|
21
|
+
export function openDrizzleDatabase(dbPath) {
|
|
22
|
+
const sqliteDb = new Database(dbPath);
|
|
23
|
+
// Configure pragmas
|
|
24
|
+
sqliteDb.pragma('foreign_keys = ON');
|
|
25
|
+
sqliteDb.pragma('busy_timeout = 5000'); // Wait up to 5 seconds if database is locked
|
|
26
|
+
const db = drizzle(sqliteDb, { schema });
|
|
27
|
+
return { db, sqliteDb };
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Close a Drizzle database connection.
|
|
31
|
+
* Since Drizzle wraps better-sqlite3, we need to close the underlying connection.
|
|
32
|
+
*/
|
|
33
|
+
export function closeDrizzleDatabase(sqliteDb) {
|
|
34
|
+
sqliteDb.close();
|
|
35
|
+
}
|
|
36
|
+
// Re-export schema for convenience
|
|
37
|
+
export * from './drizzle-schema.js';
|
|
@@ -52,6 +52,7 @@ export interface AgentWorktree {
|
|
|
52
52
|
is_clean: boolean;
|
|
53
53
|
last_checked?: string;
|
|
54
54
|
}
|
|
55
|
+
export declare const CREATE_TABLES_SQL = "\n-- Core workspace metadata\nCREATE TABLE IF NOT EXISTS workspace (\n id INTEGER PRIMARY KEY CHECK (id = 1),\n type TEXT NOT NULL CHECK (type IN ('hq', 'workspace')),\n workspace_name TEXT NOT NULL,\n has_pmo BOOLEAN DEFAULT FALSE,\n active_theme_id TEXT,\n created_at TEXT NOT NULL,\n FOREIGN KEY (active_theme_id) REFERENCES agent_themes(id) ON DELETE SET NULL\n);\n\n-- Repository management\nCREATE TABLE IF NOT EXISTS repositories (\n name TEXT PRIMARY KEY,\n path TEXT NOT NULL,\n type TEXT DEFAULT 'main' CHECK (type IN ('main', 'dependency')),\n source_url TEXT,\n action TEXT CHECK (action IN ('clone', 'move', 'link')),\n added_at TEXT NOT NULL\n);\n\n-- Agent naming themes (optional)\nCREATE TABLE IF NOT EXISTS agent_themes (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL UNIQUE,\n display_name TEXT NOT NULL,\n description TEXT,\n builtin BOOLEAN DEFAULT FALSE,\n created_at TEXT NOT NULL\n);\n\n-- Names available within each theme\nCREATE TABLE IF NOT EXISTS agent_theme_names (\n theme_id TEXT NOT NULL,\n name TEXT NOT NULL,\n PRIMARY KEY (theme_id, name),\n FOREIGN KEY (theme_id) REFERENCES agent_themes(id) ON DELETE CASCADE\n);\n\n-- Agent instances in workspace\nCREATE TABLE IF NOT EXISTS agents (\n name TEXT PRIMARY KEY,\n type TEXT NOT NULL DEFAULT 'persistent' CHECK (type IN ('persistent', 'ephemeral')),\n status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'cleaned')),\n base_name TEXT,\n theme_id TEXT,\n worktree_path TEXT,\n mount_mode TEXT NOT NULL DEFAULT 'worktree' CHECK (mount_mode IN ('worktree', 'clone')),\n created_at TEXT NOT NULL,\n cleaned_at TEXT,\n FOREIGN KEY (theme_id) REFERENCES agent_themes(id) ON DELETE SET NULL\n);\n\n-- Agent-owned worktrees\nCREATE TABLE IF NOT EXISTS agent_worktrees (\n agent_name TEXT NOT NULL,\n repo_name TEXT NOT NULL,\n worktree_path TEXT NOT NULL,\n branch TEXT NOT NULL,\n created_at TEXT NOT NULL,\n PRIMARY KEY (agent_name, repo_name),\n FOREIGN KEY (agent_name) REFERENCES agents(name) ON DELETE CASCADE,\n FOREIGN KEY (repo_name) REFERENCES repositories(name) ON DELETE CASCADE\n);\n\n-- Workspace-level settings (key-value store)\nCREATE TABLE IF NOT EXISTS workspace_settings (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n);\n\n-- =============================================================================\n-- Indexes\n-- =============================================================================\n\nCREATE INDEX IF NOT EXISTS idx_worktrees_agent ON agent_worktrees(agent_name);\nCREATE INDEX IF NOT EXISTS idx_worktrees_repo ON agent_worktrees(repo_name);\nCREATE INDEX IF NOT EXISTS idx_theme_names_theme ON agent_theme_names(theme_id);\nCREATE INDEX IF NOT EXISTS idx_agents_theme ON agents(theme_id);\n";
|
|
55
56
|
/**
|
|
56
57
|
* Get the database path for a workspace
|
|
57
58
|
*/
|
|
@@ -3,7 +3,7 @@ import * as fs from 'node:fs';
|
|
|
3
3
|
import * as path from 'node:path';
|
|
4
4
|
import { getThemePersistentDir, isEphemeralAgentName } from '../themes.js';
|
|
5
5
|
import { PMO_SCHEMA_SQL } from '../pmo/schema.js';
|
|
6
|
-
const CREATE_TABLES_SQL = `
|
|
6
|
+
export const CREATE_TABLES_SQL = `
|
|
7
7
|
-- Core workspace metadata
|
|
8
8
|
CREATE TABLE IF NOT EXISTS workspace (
|
|
9
9
|
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import Database from 'better-sqlite3';
|
|
8
8
|
import { ExecutionConfig, TerminalApp, Shell, DisplayMode, OutputMode, ExecutionEnvironment } from './types.js';
|
|
9
|
+
import { type JsonFlags } from '../prompt-json.js';
|
|
9
10
|
declare const CONFIG_KEYS: {
|
|
10
11
|
terminalApp: string;
|
|
11
12
|
terminalOpenInBackground: string;
|
|
@@ -106,6 +107,11 @@ export interface ExecutionPromptOptions {
|
|
|
106
107
|
reconfigure?: boolean;
|
|
107
108
|
/** Log function for status messages */
|
|
108
109
|
log?: (msg: string) => void;
|
|
110
|
+
/** JSON mode configuration for AI agents */
|
|
111
|
+
jsonMode?: {
|
|
112
|
+
flags: JsonFlags & Record<string, unknown>;
|
|
113
|
+
commandName: string;
|
|
114
|
+
};
|
|
109
115
|
}
|
|
110
116
|
export interface ExecutionPromptResult {
|
|
111
117
|
/** Execution config with terminal/shell/output settings */
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import inquirer from 'inquirer';
|
|
8
8
|
import { DEFAULT_EXECUTION_CONFIG } from './types.js';
|
|
9
9
|
import { isGHInstalled, isGHAuthenticated } from '../pr/index.js';
|
|
10
|
+
import { shouldOutputJson, outputPromptAsJson, createMetadata, buildPromptConfig, } from '../prompt-json.js';
|
|
10
11
|
import { execSync } from 'node:child_process';
|
|
11
12
|
const SETTINGS_TABLE = 'workspace_settings';
|
|
12
13
|
// Config keys stored in workspace_settings table
|
|
@@ -342,7 +343,9 @@ export async function getShell(db) {
|
|
|
342
343
|
* Used by work start, work spawn, and work watch commands.
|
|
343
344
|
*/
|
|
344
345
|
export async function promptExecutionSettings(db, options) {
|
|
345
|
-
const { displayMode, environment, log = () => { } } = options;
|
|
346
|
+
const { displayMode, environment, log = () => { }, jsonMode } = options;
|
|
347
|
+
// Check if JSON mode is active
|
|
348
|
+
const isJsonMode = jsonMode && shouldOutputJson(jsonMode.flags);
|
|
346
349
|
// Load execution config from database
|
|
347
350
|
const executionConfig = loadExecutionConfig(db);
|
|
348
351
|
// If terminal display mode, ensure terminal and shell preferences are set (prompts on first use)
|
|
@@ -373,15 +376,20 @@ export async function promptExecutionSettings(db, options) {
|
|
|
373
376
|
let outputMode = options.outputMode ?? DEFAULT_EXECUTION_CONFIG.outputMode;
|
|
374
377
|
const streamingDisplayModes = ['terminal'];
|
|
375
378
|
if (options.outputMode === undefined && streamingDisplayModes.includes(displayMode)) {
|
|
379
|
+
const outputChoices = [
|
|
380
|
+
{ name: 'interactive - Watch Claude work in real-time (streaming UI)', value: 'interactive' },
|
|
381
|
+
{ name: 'print - Show final result only (better for logs)', value: 'print' },
|
|
382
|
+
];
|
|
383
|
+
// In JSON mode, output the output mode prompt
|
|
384
|
+
if (isJsonMode && jsonMode) {
|
|
385
|
+
outputPromptAsJson(buildPromptConfig('list', 'selectedOutputMode', 'How should Claude display output?', outputChoices, 'interactive'), createMetadata(jsonMode.commandName, jsonMode.flags));
|
|
386
|
+
}
|
|
376
387
|
const { selectedOutputMode } = await inquirer.prompt([
|
|
377
388
|
{
|
|
378
389
|
type: 'list',
|
|
379
390
|
name: 'selectedOutputMode',
|
|
380
391
|
message: 'How should Claude display output?',
|
|
381
|
-
choices:
|
|
382
|
-
{ name: 'interactive - Watch Claude work in real-time (streaming UI)', value: 'interactive' },
|
|
383
|
-
{ name: 'print - Show final result only (better for logs)', value: 'print' },
|
|
384
|
-
],
|
|
392
|
+
choices: outputChoices,
|
|
385
393
|
default: 'interactive',
|
|
386
394
|
},
|
|
387
395
|
]);
|
|
@@ -394,15 +402,20 @@ export async function promptExecutionSettings(db, options) {
|
|
|
394
402
|
const containerNote = (environment === 'devcontainer' || environment === 'docker')
|
|
395
403
|
? ' (container provides additional isolation)'
|
|
396
404
|
: '';
|
|
405
|
+
const permissionChoices = [
|
|
406
|
+
{ name: '🔒 safe - Requires approval for dangerous operations (recommended)', value: 'safe' },
|
|
407
|
+
{ name: '⚠️ danger - Skip permission checks (--dangerously-skip-permissions)', value: 'danger' },
|
|
408
|
+
];
|
|
409
|
+
// In JSON mode, output the permissions prompt
|
|
410
|
+
if (isJsonMode && jsonMode) {
|
|
411
|
+
outputPromptAsJson(buildPromptConfig('list', 'permissionMode', `Permission mode for Claude Code${containerNote}:`, permissionChoices, 'safe'), createMetadata(jsonMode.commandName, jsonMode.flags));
|
|
412
|
+
}
|
|
397
413
|
const { permissionMode } = await inquirer.prompt([
|
|
398
414
|
{
|
|
399
415
|
type: 'list',
|
|
400
416
|
name: 'permissionMode',
|
|
401
417
|
message: `Permission mode for Claude Code${containerNote}:`,
|
|
402
|
-
choices:
|
|
403
|
-
{ name: '🔒 safe - Requires approval for dangerous operations (recommended)', value: 'safe' },
|
|
404
|
-
{ name: '⚠️ danger - Skip permission checks (--dangerously-skip-permissions)', value: 'danger' },
|
|
405
|
-
],
|
|
418
|
+
choices: permissionChoices,
|
|
406
419
|
default: 'safe',
|
|
407
420
|
},
|
|
408
421
|
]);
|
|
@@ -413,15 +426,20 @@ export async function promptExecutionSettings(db, options) {
|
|
|
413
426
|
if (options.createPR === undefined) {
|
|
414
427
|
const ghAvailable = isGHInstalled() && isGHAuthenticated();
|
|
415
428
|
if (ghAvailable) {
|
|
429
|
+
const prChoices = [
|
|
430
|
+
{ name: '✓ Yes - Create PR when running `prlt work ready`', value: 'yes' },
|
|
431
|
+
{ name: '✗ No - Just move ticket to review (can create PR later)', value: 'no' },
|
|
432
|
+
];
|
|
433
|
+
// In JSON mode, output the PR creation prompt
|
|
434
|
+
if (isJsonMode && jsonMode) {
|
|
435
|
+
outputPromptAsJson(buildPromptConfig('list', 'prChoice', 'Create a pull request when work is ready?', prChoices, 'yes'), createMetadata(jsonMode.commandName, jsonMode.flags));
|
|
436
|
+
}
|
|
416
437
|
const { prChoice } = await inquirer.prompt([
|
|
417
438
|
{
|
|
418
439
|
type: 'list',
|
|
419
440
|
name: 'prChoice',
|
|
420
441
|
message: 'Create a pull request when work is ready?',
|
|
421
|
-
choices:
|
|
422
|
-
{ name: '✓ Yes - Create PR when running `prlt work ready`', value: 'yes' },
|
|
423
|
-
{ name: '✗ No - Just move ticket to review (can create PR later)', value: 'no' },
|
|
424
|
-
],
|
|
442
|
+
choices: prChoices,
|
|
425
443
|
default: 'yes',
|
|
426
444
|
},
|
|
427
445
|
]);
|
|
@@ -36,32 +36,37 @@ export function generateDevcontainerJson(options, config) {
|
|
|
36
36
|
buildArgs.GITHUB_TOKEN = '${localEnv:GITHUB_TOKEN}';
|
|
37
37
|
}
|
|
38
38
|
// Build mounts array - parent repo mounts only needed for worktree mode
|
|
39
|
+
// TKT-801: Use consistency=cached to reduce grpcfuse contention on Docker Desktop.
|
|
40
|
+
// This helps prevent kernel panics when multiple containers mount the same paths concurrently.
|
|
39
41
|
const mounts = [
|
|
40
|
-
'source=${localWorkspaceFolder},target=/workspace,type=bind',
|
|
42
|
+
'source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached',
|
|
41
43
|
'source=claude-bash-history,target=/commandhistory,type=volume',
|
|
42
44
|
'source=claude-credentials,target=/home/node/.claude,type=volume',
|
|
43
45
|
// NOTE: ~/.claude.json is COPIED (not mounted) to /workspace/.claude.json
|
|
44
46
|
// to avoid corruption from concurrent writes by multiple containers
|
|
45
47
|
// NOTE: SSH agent socket mounting doesn't work reliably on Docker Desktop for Mac
|
|
46
48
|
// So we use HTTPS + token approach instead. The token is fetched fresh at spawn time.
|
|
47
|
-
'source=${localEnv:PRLT_HQ_PATH}/.proletariat,target=/hq/.proletariat,type=bind',
|
|
49
|
+
'source=${localEnv:PRLT_HQ_PATH}/.proletariat,target=/hq/.proletariat,type=bind,consistency=cached',
|
|
48
50
|
// PMO path can be anywhere (e.g., /hq/pmo or /hq/repos/myrepo/pmo)
|
|
49
51
|
// Use PRLT_PMO_PATH env var to mount the actual location to /hq/pmo
|
|
50
|
-
'source=${localEnv:PRLT_PMO_PATH},target=/hq/pmo,type=bind',
|
|
52
|
+
'source=${localEnv:PRLT_PMO_PATH},target=/hq/pmo,type=bind,consistency=cached',
|
|
51
53
|
];
|
|
52
54
|
// Only add parent repo mounts for worktree mode
|
|
53
55
|
// Worktree .git files reference paths like /Users/.../repos/{repoName}/.git/worktrees/name
|
|
54
56
|
// These mounts make those paths accessible inside the container at /hq/repos/{repoName}
|
|
55
57
|
// Clone mode doesn't need this because each clone has its own self-contained .git directory
|
|
58
|
+
// NOTE: Cannot use readonly because git worktrees share the object store with parent repo.
|
|
59
|
+
// Commits write to parent's .git/objects/ and refs update in .git/worktrees/<name>/
|
|
56
60
|
if (mountMode === 'worktree' && options.repoWorktrees) {
|
|
57
61
|
for (const repoName of options.repoWorktrees) {
|
|
58
|
-
mounts.push(`source=\${localEnv:PRLT_HQ_PATH}/repos/${repoName},target=/hq/repos/${repoName},type=bind`);
|
|
62
|
+
mounts.push(`source=\${localEnv:PRLT_HQ_PATH}/repos/${repoName},target=/hq/repos/${repoName},type=bind,consistency=cached`);
|
|
59
63
|
}
|
|
60
64
|
}
|
|
61
65
|
// If using "mount" channel, mount local prlt build from PRLT_REPO_PATH
|
|
62
66
|
// The setup-prlt.sh script will detect /opt/prlt and configure the wrapper
|
|
67
|
+
// TKT-801: Use readonly,consistency=cached to reduce grpcfuse contention
|
|
63
68
|
if (useMount) {
|
|
64
|
-
mounts.push('source=${localEnv:PRLT_REPO_PATH},target=/opt/prlt,type=bind,readonly');
|
|
69
|
+
mounts.push('source=${localEnv:PRLT_REPO_PATH},target=/opt/prlt,type=bind,readonly,consistency=cached');
|
|
65
70
|
}
|
|
66
71
|
const devcontainerJson = {
|
|
67
72
|
name: `Agent: ${options.agentName}`,
|
|
@@ -470,7 +475,7 @@ if [ -d "/opt/prlt/apps/cli" ]; then
|
|
|
470
475
|
# Install only better-sqlite3 with correct architecture
|
|
471
476
|
cd "$PRLT_LOCAL"
|
|
472
477
|
npm init -y > /dev/null 2>&1
|
|
473
|
-
npm install better-sqlite3@
|
|
478
|
+
npm install better-sqlite3@12.6.2 --build-from-source 2>&1 || {
|
|
474
479
|
echo "Warning: better-sqlite3 rebuild failed"
|
|
475
480
|
}
|
|
476
481
|
|
|
@@ -601,8 +606,9 @@ export function updateDevcontainerMounts(agentDir, _repoWorktrees) {
|
|
|
601
606
|
// Use single mount for entire workspace - includes all repos and temp files
|
|
602
607
|
// NOTE: ~/.claude.json is COPIED (not mounted) to /workspace/.claude.json
|
|
603
608
|
// to avoid corruption from concurrent writes by multiple containers
|
|
609
|
+
// TKT-801: Use consistency=cached to reduce grpcfuse contention on Docker Desktop
|
|
604
610
|
devcontainerJson.mounts = [
|
|
605
|
-
'source=${localWorkspaceFolder},target=/workspace,type=bind',
|
|
611
|
+
'source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached',
|
|
606
612
|
'source=claude-bash-history,target=/commandhistory,type=volume',
|
|
607
613
|
'source=claude-credentials,target=/home/node/.claude,type=volume',
|
|
608
614
|
];
|
|
@@ -735,17 +735,23 @@ function createDockerContainer(context, containerName, imageName, config) {
|
|
|
735
735
|
// KEY: Use a named Docker volume for Claude credentials - this is how devcontainer.json
|
|
736
736
|
// was handling it. The volume persists across containers, so login once = logged in everywhere.
|
|
737
737
|
// This avoids corruption from concurrent writes to host filesystem.
|
|
738
|
+
//
|
|
739
|
+
// TKT-801: Use :cached mount option to reduce grpcfuse contention on Docker Desktop.
|
|
740
|
+
// This improves performance and helps prevent kernel panics when multiple containers
|
|
741
|
+
// mount the same paths concurrently.
|
|
738
742
|
const mounts = [
|
|
739
743
|
// Agent workspace
|
|
740
|
-
`-v "${context.agentDir}:/workspace"`,
|
|
741
|
-
// HQ .proletariat directory (for database access)
|
|
742
|
-
...(context.hqPath ? [`-v "${context.hqPath}/.proletariat:/hq/.proletariat"`] : []),
|
|
743
|
-
// PMO path
|
|
744
|
-
...(context.pmoPath ? [`-v "${context.pmoPath}:/hq/pmo"`] : []),
|
|
745
|
-
// Mount parent repos for git worktree resolution
|
|
744
|
+
`-v "${context.agentDir}:/workspace:cached"`,
|
|
745
|
+
// HQ .proletariat directory (for database access) - use :cached to reduce contention
|
|
746
|
+
...(context.hqPath ? [`-v "${context.hqPath}/.proletariat:/hq/.proletariat:cached"`] : []),
|
|
747
|
+
// PMO path - use :cached to reduce contention
|
|
748
|
+
...(context.pmoPath ? [`-v "${context.pmoPath}:/hq/pmo:cached"`] : []),
|
|
749
|
+
// Mount parent repos for git worktree resolution - use :cached to reduce contention
|
|
750
|
+
// NOTE: Cannot use :ro because git worktrees share the object store with parent repo.
|
|
751
|
+
// Commits write to parent's .git/objects/ and refs update in .git/worktrees/<name>/
|
|
746
752
|
// Worktree .git files reference paths like /Users/.../repos/{repoName}/.git/worktrees/name
|
|
747
753
|
// These mounts make those paths accessible inside the container at /hq/repos/{repoName}
|
|
748
|
-
...(context.repoWorktrees || []).map(repoName => `-v "${context.hqPath}/repos/${repoName}:/hq/repos/${repoName}"`),
|
|
754
|
+
...(context.repoWorktrees || []).map(repoName => `-v "${context.hqPath}/repos/${repoName}:/hq/repos/${repoName}:cached"`),
|
|
749
755
|
// Claude credentials - shared named volume (login once, all containers share)
|
|
750
756
|
`-v "claude-credentials:/home/node/.claude"`,
|
|
751
757
|
];
|
|
@@ -814,6 +820,17 @@ function runContainerSetup(containerId, sandboxed = true) {
|
|
|
814
820
|
console.debug(`[runners:docker] Container setup scripts failed:`, error);
|
|
815
821
|
// Continue - setup might partially work
|
|
816
822
|
}
|
|
823
|
+
// Configure pnpm to use container-local store to prevent contention
|
|
824
|
+
// Multiple agents sharing the same pnpm store causes hangs and ERR_PNPM errors (TKT-718)
|
|
825
|
+
// Each container gets its own store at /tmp/pnpm-store for reliability
|
|
826
|
+
try {
|
|
827
|
+
execSync(`docker exec ${containerId} pnpm config set store-dir /tmp/pnpm-store`, { stdio: 'pipe' });
|
|
828
|
+
console.debug(`[runners:docker] Configured pnpm store-dir to /tmp/pnpm-store`);
|
|
829
|
+
}
|
|
830
|
+
catch (error) {
|
|
831
|
+
console.debug(`[runners:docker] Failed to configure pnpm store (pnpm may not be installed):`, error);
|
|
832
|
+
// Non-fatal - pnpm may not be installed in all containers
|
|
833
|
+
}
|
|
817
834
|
// Copy Claude settings file (.claude.json) from host to container
|
|
818
835
|
// This is needed for Claude Code to recognize settings and bypass prompts
|
|
819
836
|
// Note: Auth tokens are in the claude-credentials volume at /home/node/.claude/.credentials.json
|
|
@@ -77,6 +77,16 @@ function findBaseBranchInContainer(containerId, containerRepoPath, candidates =
|
|
|
77
77
|
return 'HEAD';
|
|
78
78
|
}
|
|
79
79
|
// =============================================================================
|
|
80
|
+
// Constants
|
|
81
|
+
// =============================================================================
|
|
82
|
+
/**
|
|
83
|
+
* Delay between container spawns to prevent Docker kernel panics (TKT-801).
|
|
84
|
+
* When spawning multiple agents simultaneously, Docker Desktop on Apple Silicon
|
|
85
|
+
* can hit kernel panics in grpcfuse (file sharing layer) due to spinlock
|
|
86
|
+
* contention when all agents mount the same shared volumes concurrently.
|
|
87
|
+
*/
|
|
88
|
+
const SPAWN_STAGGER_DELAY_MS = 2000;
|
|
89
|
+
// =============================================================================
|
|
80
90
|
// Agent Selection
|
|
81
91
|
// =============================================================================
|
|
82
92
|
/**
|
|
@@ -517,6 +527,15 @@ export async function spawnForColumn(projectId, columnName, storage, executionSt
|
|
|
517
527
|
roundRobinState.lastIndex = -1;
|
|
518
528
|
}
|
|
519
529
|
}
|
|
530
|
+
// Staggered spawn delay to prevent Docker kernel panics (TKT-801)
|
|
531
|
+
// When spawning multiple containers, add delay between spawns to avoid
|
|
532
|
+
// mount storms that cause spinlock contention in Docker's grpcfuse layer
|
|
533
|
+
const remainingTickets = ticketsToProcess.length - (ticketsToProcess.indexOf(ticket) + 1);
|
|
534
|
+
if (remainingTickets > 0 && availableAgents.length > 0) {
|
|
535
|
+
log(`Waiting ${SPAWN_STAGGER_DELAY_MS / 1000}s before next spawn (${remainingTickets} remaining)...`);
|
|
536
|
+
// eslint-disable-next-line no-await-in-loop -- Intentional staggered delay for Docker stability
|
|
537
|
+
await new Promise(resolve => setTimeout(resolve, SPAWN_STAGGER_DELAY_MS));
|
|
538
|
+
}
|
|
520
539
|
}
|
|
521
540
|
else {
|
|
522
541
|
result.failed.push(spawnResult);
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flag resolution utilities for unified human/machine interactive modes
|
|
3
|
+
*/
|
|
4
|
+
export { FlagResolver, createFlagResolver, shouldOutputJson, isMachineOutput, type FlagResolverOptions, type PromptDefinition, type ResolverChoice, type ResolverContext, type ResolveResult, } from './resolver.js';
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlagResolver - Unified flag resolution for human and machine interactive modes
|
|
3
|
+
*
|
|
4
|
+
* This abstraction unifies the two interaction patterns in the CLI:
|
|
5
|
+
* - Human interactive mode: Uses inquirer prompts, collects input, returns flags
|
|
6
|
+
* - Machine/JSON mode: Outputs prompt schema as JSON, exits for agent to process
|
|
7
|
+
*
|
|
8
|
+
* Both modes use the same underlying pattern: prompts PRODUCE flags.
|
|
9
|
+
* The execution logic only sees flags, not prompt results.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* // Define prompts for missing flags
|
|
14
|
+
* const resolver = new FlagResolver({
|
|
15
|
+
* commandName: 'ticket create',
|
|
16
|
+
* baseCommand: 'prlt ticket create',
|
|
17
|
+
* jsonMode: shouldOutputJson(flags),
|
|
18
|
+
* flags,
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* // Add prompts - they execute in order, can depend on previously resolved flags
|
|
22
|
+
* resolver.addPrompt({
|
|
23
|
+
* flagName: 'column',
|
|
24
|
+
* type: 'list',
|
|
25
|
+
* message: 'Select column:',
|
|
26
|
+
* choices: async () => columns.map(c => ({ name: c, value: c })),
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* resolver.addPrompt({
|
|
30
|
+
* flagName: 'title',
|
|
31
|
+
* type: 'input',
|
|
32
|
+
* message: 'Enter title:',
|
|
33
|
+
* when: (ctx) => ctx.flags.column !== undefined, // Only after column is selected
|
|
34
|
+
* });
|
|
35
|
+
*
|
|
36
|
+
* // Resolve all missing flags
|
|
37
|
+
* const resolved = await resolver.resolve();
|
|
38
|
+
* // resolved.column and resolved.title are now guaranteed to have values
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
/**
|
|
42
|
+
* Context available during prompt resolution
|
|
43
|
+
*/
|
|
44
|
+
export interface ResolverContext<TFlags = Record<string, unknown>> {
|
|
45
|
+
/** Currently resolved flags (includes original flags + newly resolved) */
|
|
46
|
+
flags: TFlags;
|
|
47
|
+
/** Command args */
|
|
48
|
+
args: Record<string, unknown>;
|
|
49
|
+
/** Command name for metadata */
|
|
50
|
+
commandName: string;
|
|
51
|
+
/** Base command for building follow-up commands (e.g., "prlt ticket create") */
|
|
52
|
+
baseCommand: string;
|
|
53
|
+
/** Project ID if available */
|
|
54
|
+
projectId?: string;
|
|
55
|
+
/** Any additional custom context */
|
|
56
|
+
[key: string]: unknown;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Choice item for list/checkbox prompts
|
|
60
|
+
*/
|
|
61
|
+
export interface ResolverChoice<T = string> {
|
|
62
|
+
/** Display text */
|
|
63
|
+
name: string;
|
|
64
|
+
/** Value returned when selected */
|
|
65
|
+
value: T;
|
|
66
|
+
/** Whether this choice is disabled */
|
|
67
|
+
disabled?: boolean | string;
|
|
68
|
+
/** Full CLI command for this choice (for JSON mode) - if not provided, auto-generated */
|
|
69
|
+
command?: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Definition for a single prompt that resolves a flag
|
|
73
|
+
*/
|
|
74
|
+
export interface PromptDefinition<TValue = unknown, TFlags = Record<string, unknown>> {
|
|
75
|
+
/** The flag name this prompt resolves (e.g., 'column', 'title') */
|
|
76
|
+
flagName: string;
|
|
77
|
+
/** Prompt type */
|
|
78
|
+
type: 'list' | 'checkbox' | 'input' | 'confirm' | 'editor';
|
|
79
|
+
/** User-facing prompt message */
|
|
80
|
+
message: string | ((ctx: ResolverContext<TFlags>) => string);
|
|
81
|
+
/**
|
|
82
|
+
* Get choices for list/checkbox prompts.
|
|
83
|
+
* Can be async to fetch dynamic data.
|
|
84
|
+
*/
|
|
85
|
+
choices?: (ctx: ResolverContext<TFlags>) => Promise<ResolverChoice<TValue>[]> | ResolverChoice<TValue>[];
|
|
86
|
+
/**
|
|
87
|
+
* Default value for the prompt.
|
|
88
|
+
* Can be a function to compute based on context.
|
|
89
|
+
*/
|
|
90
|
+
default?: TValue | ((ctx: ResolverContext<TFlags>) => TValue | undefined);
|
|
91
|
+
/**
|
|
92
|
+
* Validation function for input prompts.
|
|
93
|
+
* Return true if valid, or error message string if invalid.
|
|
94
|
+
*/
|
|
95
|
+
validate?: (value: TValue, ctx: ResolverContext<TFlags>) => boolean | string;
|
|
96
|
+
/**
|
|
97
|
+
* Conditional function - prompt is skipped if this returns false.
|
|
98
|
+
* Use for prompts that depend on other flags.
|
|
99
|
+
*/
|
|
100
|
+
when?: (ctx: ResolverContext<TFlags>) => boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Transform the flag value before storing.
|
|
103
|
+
* Useful for parsing/formatting.
|
|
104
|
+
*/
|
|
105
|
+
transform?: (value: TValue, ctx: ResolverContext<TFlags>) => unknown;
|
|
106
|
+
/**
|
|
107
|
+
* For JSON mode: additional context to include in the prompt output.
|
|
108
|
+
* Useful for providing hints, examples, etc.
|
|
109
|
+
*/
|
|
110
|
+
context?: Record<string, unknown> | ((ctx: ResolverContext<TFlags>) => Record<string, unknown>);
|
|
111
|
+
/**
|
|
112
|
+
* For JSON mode: generate the command string for a specific choice.
|
|
113
|
+
* If not provided, auto-generates based on flagName and value.
|
|
114
|
+
*/
|
|
115
|
+
getCommand?: (value: TValue, ctx: ResolverContext<TFlags>) => string;
|
|
116
|
+
/**
|
|
117
|
+
* Skip auto-generating commands for choices (useful when choices already have custom commands)
|
|
118
|
+
*/
|
|
119
|
+
skipAutoCommand?: boolean;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Options for creating a FlagResolver
|
|
123
|
+
*/
|
|
124
|
+
export interface FlagResolverOptions<TFlags extends Record<string, unknown>> {
|
|
125
|
+
/** Command name for metadata (e.g., "ticket create") */
|
|
126
|
+
commandName: string;
|
|
127
|
+
/** Base command for building commands (e.g., "prlt ticket create") */
|
|
128
|
+
baseCommand: string;
|
|
129
|
+
/** Whether JSON mode is active */
|
|
130
|
+
jsonMode: boolean;
|
|
131
|
+
/** Initial flags from CLI parsing */
|
|
132
|
+
flags: Partial<TFlags>;
|
|
133
|
+
/** Command args */
|
|
134
|
+
args?: Record<string, unknown>;
|
|
135
|
+
/** Additional custom context */
|
|
136
|
+
context?: Record<string, unknown>;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Result of flag resolution
|
|
140
|
+
*/
|
|
141
|
+
export interface ResolveResult<TFlags> {
|
|
142
|
+
/** The fully resolved flags */
|
|
143
|
+
flags: TFlags;
|
|
144
|
+
/** Whether all required prompts were resolved (false if user cancelled) */
|
|
145
|
+
complete: boolean;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* FlagResolver handles unified flag resolution for both human and machine modes.
|
|
149
|
+
*
|
|
150
|
+
* Usage pattern:
|
|
151
|
+
* 1. Create resolver with command info and current flags
|
|
152
|
+
* 2. Add prompt definitions for flags that may need resolution
|
|
153
|
+
* 3. Call resolve() to get complete flags
|
|
154
|
+
*
|
|
155
|
+
* In JSON mode, resolve() outputs the first unresolved prompt and exits.
|
|
156
|
+
* In interactive mode, resolve() prompts for each unresolved flag sequentially.
|
|
157
|
+
*/
|
|
158
|
+
export declare class FlagResolver<TFlags extends Record<string, unknown> = Record<string, unknown>> {
|
|
159
|
+
private prompts;
|
|
160
|
+
private options;
|
|
161
|
+
private resolvedFlags;
|
|
162
|
+
private resolverContext;
|
|
163
|
+
constructor(options: FlagResolverOptions<TFlags>);
|
|
164
|
+
/**
|
|
165
|
+
* Add a prompt definition for resolving a flag.
|
|
166
|
+
* Prompts are processed in the order they are added.
|
|
167
|
+
*/
|
|
168
|
+
addPrompt<TValue = unknown>(prompt: PromptDefinition<TValue, TFlags>): this;
|
|
169
|
+
/**
|
|
170
|
+
* Add multiple prompt definitions at once.
|
|
171
|
+
*/
|
|
172
|
+
addPrompts(prompts: PromptDefinition<unknown, TFlags>[]): this;
|
|
173
|
+
/**
|
|
174
|
+
* Update the context with additional data.
|
|
175
|
+
* Useful for adding computed values that prompts might need.
|
|
176
|
+
*/
|
|
177
|
+
setContext(key: string, value: unknown): this;
|
|
178
|
+
/**
|
|
179
|
+
* Get current context value
|
|
180
|
+
*/
|
|
181
|
+
getContext<T = unknown>(key: string): T | undefined;
|
|
182
|
+
/**
|
|
183
|
+
* Check if a flag has a value (not undefined)
|
|
184
|
+
*/
|
|
185
|
+
hasFlag(flagName: keyof TFlags): boolean;
|
|
186
|
+
/**
|
|
187
|
+
* Get current flag value
|
|
188
|
+
*/
|
|
189
|
+
getFlag<K extends keyof TFlags>(flagName: K): TFlags[K] | undefined;
|
|
190
|
+
/**
|
|
191
|
+
* Set a flag value directly (bypasses prompting)
|
|
192
|
+
*/
|
|
193
|
+
setFlag<K extends keyof TFlags>(flagName: K, value: TFlags[K]): this;
|
|
194
|
+
/**
|
|
195
|
+
* Resolve all prompts and return complete flags.
|
|
196
|
+
*
|
|
197
|
+
* In JSON mode: outputs the first unresolved prompt as JSON and exits (never returns).
|
|
198
|
+
* In interactive mode: prompts for each unresolved flag and returns all flags.
|
|
199
|
+
*
|
|
200
|
+
* @returns The fully resolved flags
|
|
201
|
+
*/
|
|
202
|
+
resolve(): Promise<TFlags>;
|
|
203
|
+
/**
|
|
204
|
+
* Output prompt as JSON for machine mode
|
|
205
|
+
*/
|
|
206
|
+
private outputJsonPrompt;
|
|
207
|
+
/**
|
|
208
|
+
* Prompt for value in interactive mode
|
|
209
|
+
*/
|
|
210
|
+
private promptInteractive;
|
|
211
|
+
/**
|
|
212
|
+
* Build a command string for a flag value
|
|
213
|
+
*/
|
|
214
|
+
private buildCommand;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Convenience function to create a FlagResolver from command context
|
|
218
|
+
*/
|
|
219
|
+
export declare function createFlagResolver<TFlags extends Record<string, unknown>>(options: FlagResolverOptions<TFlags>): FlagResolver<TFlags>;
|
|
220
|
+
/**
|
|
221
|
+
* Helper to check if we should use JSON mode
|
|
222
|
+
* Re-exported from prompt-json for convenience
|
|
223
|
+
*/
|
|
224
|
+
export { shouldOutputJson, isMachineOutput } from '../prompt-json.js';
|