@program-video/cli 0.1.0 → 0.1.3

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/README.md CHANGED
@@ -1,74 +1,121 @@
1
- # @program-video/cli
1
+ <p align="center">
2
+ <img src="https://program.video/favicon.ico" alt="Program" width="60" height="60" />
3
+ </p>
2
4
 
3
- CLI for the Program video creation platform.
5
+ <h1 align="center">@program-video/cli</h1>
6
+
7
+ <p align="center">
8
+ Command-line interface for <a href="https://program.video">Program</a> — AI-powered video creation platform
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://www.npmjs.com/package/@program-video/cli"><img src="https://img.shields.io/npm/v/@program-video/cli.svg" alt="npm version"></a>
13
+ <a href="https://www.npmjs.com/package/@program-video/cli"><img src="https://img.shields.io/npm/dm/@program-video/cli.svg" alt="npm downloads"></a>
14
+ </p>
15
+
16
+ ---
4
17
 
5
18
  ## Installation
6
19
 
7
20
  ```bash
8
- # Build and link globally
9
- pnpm build
10
- pnpm link --global
21
+ npm install -g @program-video/cli
22
+ ```
23
+
24
+ Or run directly with npx:
11
25
 
12
- # Verify installation
13
- program --version
26
+ ```bash
27
+ npx @program-video/cli <command>
14
28
  ```
15
29
 
16
- ## Development
30
+ ## Authentication
17
31
 
18
32
  ```bash
19
- # Watch mode
20
- pnpm dev
33
+ # Sign in (opens browser for device authorization)
34
+ program auth login
21
35
 
22
- # Type checking
23
- pnpm typecheck
36
+ # Check authentication status
37
+ program auth status
24
38
 
25
- # Lint
26
- pnpm lint
39
+ # Sign out
40
+ program auth logout
27
41
  ```
28
42
 
29
- ## Configuration
43
+ ## Commands
30
44
 
31
- | Variable | Description | Default |
32
- |----------|-------------|---------|
33
- | `PROGRAM_BASE_URL` | OAuth provider URL | `http://localhost:3000` |
34
- | `PROGRAM_CONVEX_URL` | Convex deployment URL | Uses `NEXT_PUBLIC_CONVEX_URL` |
45
+ ### Projects
35
46
 
36
- Credentials are stored in `~/.program/credentials.json`.
47
+ ```bash
48
+ # List all projects
49
+ program project list
37
50
 
38
- ## Commands
51
+ # Create a new project
52
+ program project create --title "My Video"
53
+
54
+ # Get project details
55
+ program project get <project-id>
56
+ ```
57
+
58
+ ### Workflows
59
+
60
+ ```bash
61
+ # List available workflow templates
62
+ program workflow list
63
+
64
+ # Run a workflow
65
+ program workflow run <template-id> --project <project-id>
66
+
67
+ # Check workflow execution status
68
+ program workflow status <execution-id>
69
+
70
+ # Watch execution progress
71
+ program workflow status <execution-id> --watch
72
+ ```
73
+
74
+ ### Tools
39
75
 
40
76
  ```bash
41
- # Authentication
42
- program auth login # OAuth browser flow
43
- program auth status --json # Check auth state
44
- program auth logout # Clear credentials
45
-
46
- # Projects
47
- program project list --json
48
- program project create --title "My Video" --json
49
-
50
- # Workflows
51
- program workflow list --json
52
- program workflow run <templateId> --project <id> --json
53
- program workflow status <execId> --watch --json
54
-
55
- # Tools (direct composition manipulation)
56
- program tool list --json
57
- program tool exec <name> --project <id> --params '{}' --json
58
-
59
- # Messages
60
- program message send "text" --project <id> --json
77
+ # List available tools
78
+ program tool list
79
+
80
+ # Execute a tool
81
+ program tool exec <tool-name> --project <project-id> --params '{"key": "value"}'
61
82
  ```
62
83
 
63
- ## Documentation
84
+ ### Messages
85
+
86
+ ```bash
87
+ # List messages in project chat
88
+ program message list --project <project-id>
89
+
90
+ # Send a message to project chat
91
+ program message send "Your message" --project <project-id>
92
+ ```
93
+
94
+ ### Documentation
95
+
96
+ ```bash
97
+ # View CLI documentation
98
+ program docs
99
+ ```
100
+
101
+ ## Options
102
+
103
+ All commands support these options:
104
+
105
+ | Option | Description |
106
+ |--------|-------------|
107
+ | `--json` | Output in JSON format (for scripting) |
108
+ | `--help` | Show command help |
109
+
110
+ ## Credentials
111
+
112
+ Credentials are stored locally in `~/.program/credentials.json`.
113
+
114
+ ## Links
64
115
 
65
- - **Full Command Reference**: `skill/references/COMMANDS.md`
66
- - **Usage Examples**: `skill/references/EXAMPLES.md`
67
- - **Known Issues**: `KNOWN_ISSUES.md`
68
- - **Video Quality Guide**: `VIDEO_QUALITY.md`
116
+ - [Website](https://program.video)
117
+ - [Documentation](https://docs.program.video)
69
118
 
70
- ## Agent Integration
119
+ ## License
71
120
 
72
- This CLI is designed to be used by AI agents via the Program skill:
73
- - Agents read `skill/SKILL.md` to learn available commands
74
- - All commands support `--json` for machine-readable output
121
+ Proprietary - Copyright © 2026 Latent Supply Pty Ltd
package/dist/index.js CHANGED
@@ -204,14 +204,7 @@ var BASE_URL = getEnvOrDefault(
204
204
  "BASE_URL",
205
205
  "https://program.video"
206
206
  );
207
- function getConvexUrl() {
208
- const override = process.env.PROGRAM_CONVEX_URL;
209
- if (override) return override;
210
- const convexUrl = process.env.NEXT_PUBLIC_CONVEX_URL;
211
- if (convexUrl) return convexUrl;
212
- return "https://mild-hyena-697.convex.cloud";
213
- }
214
- var CONVEX_URL = getConvexUrl();
207
+ var CONVEX_URL = "https://keen-eel-920.convex.cloud";
215
208
  var oauthConfig = {
216
209
  baseUrl: BASE_URL
217
210
  };
@@ -275,10 +268,12 @@ function formatUserCode(code) {
275
268
  return code;
276
269
  }
277
270
  async function loginCommand(options) {
278
- const spinner = ora("Requesting device code...").start();
271
+ const showSpinner = process.stdout.isTTY;
272
+ const spinner = showSpinner ? ora("Requesting device code...").start() : null;
279
273
  try {
280
274
  const deviceAuth = await startDeviceAuth(oauthConfig);
281
- spinner.stop();
275
+ spinner?.stop();
276
+ spinner?.clear();
282
277
  console.log();
283
278
  console.log(chalk2.bold(" Sign in to Program"));
284
279
  console.log();
@@ -290,9 +285,10 @@ async function loginCommand(options) {
290
285
  console.log(chalk2.dim(` Or open: ${deviceAuth.verificationUrlComplete}`));
291
286
  console.log();
292
287
  }
293
- const waitingSpinner = ora("Waiting for authorization...").start();
288
+ const waitingSpinner = showSpinner ? ora("Waiting for authorization...").start() : null;
294
289
  const credentials = await deviceAuth.pollForCompletion();
295
- waitingSpinner.stop();
290
+ waitingSpinner?.stop();
291
+ waitingSpinner?.clear();
296
292
  if (options.json) {
297
293
  outputSuccess(
298
294
  {
@@ -525,13 +521,15 @@ function createConvexClient(config) {
525
521
 
526
522
  // src/commands/project/create.ts
527
523
  async function createCommand(options) {
528
- const spinner = options.json ? null : ora2("Creating project...").start();
524
+ const showSpinner = !options.json && process.stdout.isTTY;
525
+ const spinner = showSpinner ? ora2("Creating project...").start() : null;
529
526
  const client = createConvexClient(convexConfig);
530
527
  const result = await client.mutation("projects.create", {
531
528
  title: options.title,
532
529
  description: options.description
533
530
  });
534
531
  spinner?.stop();
532
+ spinner?.clear();
535
533
  if (!result.success || !result.data) {
536
534
  outputError(result.error ?? "Failed to create project", options);
537
535
  process.exit(1);
@@ -552,12 +550,14 @@ async function createCommand(options) {
552
550
  import chalk5 from "chalk";
553
551
  import ora3 from "ora";
554
552
  async function getCommand(projectId, options) {
555
- const spinner = options.json ? null : ora3("Fetching project...").start();
553
+ const showSpinner = !options.json && process.stdout.isTTY;
554
+ const spinner = showSpinner ? ora3("Fetching project...").start() : null;
556
555
  const client = createConvexClient(convexConfig);
557
556
  const result = await client.query("projects.byId", {
558
557
  id: projectId
559
558
  });
560
559
  spinner?.stop();
560
+ spinner?.clear();
561
561
  if (!result.success || !result.data) {
562
562
  outputError(result.error ?? "Failed to get project", options);
563
563
  process.exit(1);
@@ -616,12 +616,14 @@ async function getCommand(projectId, options) {
616
616
  import chalk6 from "chalk";
617
617
  import ora4 from "ora";
618
618
  async function listCommand(options) {
619
- const spinner = options.json ? null : ora4("Fetching projects...").start();
619
+ const showSpinner = !options.json && process.stdout.isTTY;
620
+ const spinner = showSpinner ? ora4("Fetching projects...").start() : null;
620
621
  const client = createConvexClient(convexConfig);
621
622
  const result = await client.query("projects.list", {
622
623
  limit: options.limit
623
624
  });
624
625
  spinner?.stop();
626
+ spinner?.clear();
625
627
  if (!result.success || !result.data) {
626
628
  outputError(result.error ?? "Failed to list projects", options);
627
629
  process.exit(1);
@@ -664,12 +666,14 @@ function formatDate(timestamp) {
664
666
  import chalk7 from "chalk";
665
667
  import ora5 from "ora";
666
668
  async function listCommand2(options) {
667
- const spinner = options.json ? null : ora5("Fetching workflow templates...").start();
669
+ const showSpinner = !options.json && process.stdout.isTTY;
670
+ const spinner = showSpinner ? ora5("Fetching workflow templates...").start() : null;
668
671
  const client = createConvexClient(convexConfig);
669
672
  const result = await client.query("workflows.listTemplates", {
670
673
  category: options.publicOnly ? "public" : void 0
671
674
  });
672
675
  spinner?.stop();
676
+ spinner?.clear();
673
677
  if (!result.success || !result.data) {
674
678
  outputError(result.error ?? "Failed to list templates", options);
675
679
  process.exit(1);
@@ -706,13 +710,15 @@ async function listCommand2(options) {
706
710
  import chalk8 from "chalk";
707
711
  import ora6 from "ora";
708
712
  async function runCommand(templateId, options) {
709
- const spinner = options.json ? null : ora6("Starting workflow execution...").start();
713
+ const showSpinner = !options.json && process.stdout.isTTY;
714
+ const spinner = showSpinner ? ora6("Starting workflow execution...").start() : null;
710
715
  let input;
711
716
  if (options.input) {
712
717
  try {
713
718
  input = JSON.parse(options.input);
714
719
  } catch {
715
720
  spinner?.stop();
721
+ spinner?.clear();
716
722
  outputError("Invalid JSON in --input parameter", options);
717
723
  process.exit(1);
718
724
  }
@@ -724,6 +730,7 @@ async function runCommand(templateId, options) {
724
730
  input
725
731
  });
726
732
  spinner?.stop();
733
+ spinner?.clear();
727
734
  if (!result.success || !result.data) {
728
735
  outputError(result.error ?? "Failed to start workflow", options);
729
736
  process.exit(1);
@@ -751,11 +758,13 @@ async function statusCommand2(executionId, options) {
751
758
  }
752
759
  }
753
760
  async function getStatusOnce(client, executionId, options) {
754
- const spinner = options.json ? null : ora7("Fetching execution status...").start();
761
+ const showSpinner = !options.json && process.stdout.isTTY;
762
+ const spinner = showSpinner ? ora7("Fetching execution status...").start() : null;
755
763
  const result = await client.query("workflows.status", {
756
764
  executionId
757
765
  });
758
766
  spinner?.stop();
767
+ spinner?.clear();
759
768
  if (!result.success) {
760
769
  outputError(result.error ?? "Failed to get status", options);
761
770
  process.exit(1);
@@ -878,10 +887,12 @@ function detectAgentSource() {
878
887
 
879
888
  // src/commands/tool/execute.ts
880
889
  async function executeCommand(toolName, options) {
881
- const spinner = options.json ? null : ora8(`Executing ${toolName}...`).start();
890
+ const showSpinner = !options.json && process.stdout.isTTY;
891
+ const spinner = showSpinner ? ora8(`Executing ${toolName}...`).start() : null;
882
892
  const accessToken = await ensureValidToken(oauthConfig);
883
893
  if (!accessToken) {
884
894
  spinner?.stop();
895
+ spinner?.clear();
885
896
  outputError("Not authenticated. Run 'program auth login' first.", options);
886
897
  process.exit(1);
887
898
  }
@@ -891,6 +902,7 @@ async function executeCommand(toolName, options) {
891
902
  params = JSON.parse(options.params);
892
903
  } catch {
893
904
  spinner?.stop();
905
+ spinner?.clear();
894
906
  outputError("Invalid JSON in --params", options);
895
907
  process.exit(1);
896
908
  }
@@ -912,6 +924,7 @@ async function executeCommand(toolName, options) {
912
924
  });
913
925
  const result = await response.json();
914
926
  spinner?.stop();
927
+ spinner?.clear();
915
928
  if (!response.ok || !result.success) {
916
929
  outputError(result.error ?? `Tool execution failed: ${response.status}`, options);
917
930
  process.exit(1);
@@ -928,6 +941,7 @@ async function executeCommand(toolName, options) {
928
941
  }
929
942
  } catch (error) {
930
943
  spinner?.stop();
944
+ spinner?.clear();
931
945
  outputError(error instanceof Error ? error.message : "Request failed", options);
932
946
  process.exit(1);
933
947
  }
@@ -937,13 +951,15 @@ async function executeCommand(toolName, options) {
937
951
  import chalk11 from "chalk";
938
952
  import ora9 from "ora";
939
953
  async function listCommand3(options) {
940
- const spinner = options.json ? null : ora9("Fetching available tools...").start();
954
+ const showSpinner = !options.json && process.stdout.isTTY;
955
+ const spinner = showSpinner ? ora9("Fetching available tools...").start() : null;
941
956
  try {
942
957
  const response = await fetch(`${BASE_URL}/api/cli/tool`, {
943
958
  method: "GET"
944
959
  });
945
960
  const result = await response.json();
946
961
  spinner?.stop();
962
+ spinner?.clear();
947
963
  if (!response.ok || !result.success) {
948
964
  outputError(result.error ?? "Failed to list tools", options);
949
965
  process.exit(1);
@@ -966,6 +982,7 @@ async function listCommand3(options) {
966
982
  }
967
983
  } catch (error) {
968
984
  spinner?.stop();
985
+ spinner?.clear();
969
986
  outputError(error instanceof Error ? error.message : "Request failed", options);
970
987
  process.exit(1);
971
988
  }
@@ -975,10 +992,12 @@ async function listCommand3(options) {
975
992
  import chalk12 from "chalk";
976
993
  import ora10 from "ora";
977
994
  async function sendCommand(text, options) {
978
- const spinner = options.json ? null : ora10("Sending message...").start();
995
+ const showSpinner = !options.json && process.stdout.isTTY;
996
+ const spinner = showSpinner ? ora10("Sending message...").start() : null;
979
997
  const accessToken = await ensureValidToken(oauthConfig);
980
998
  if (!accessToken) {
981
999
  spinner?.stop();
1000
+ spinner?.clear();
982
1001
  outputError("Not authenticated. Run 'program auth login' first.", options);
983
1002
  process.exit(1);
984
1003
  }
@@ -1000,6 +1019,7 @@ async function sendCommand(text, options) {
1000
1019
  });
1001
1020
  const result = await response.json();
1002
1021
  spinner?.stop();
1022
+ spinner?.clear();
1003
1023
  if (!response.ok || !result.success) {
1004
1024
  outputError(result.error ?? `Failed to send message: ${response.status}`, options);
1005
1025
  process.exit(1);
@@ -1014,6 +1034,7 @@ async function sendCommand(text, options) {
1014
1034
  }
1015
1035
  } catch (error) {
1016
1036
  spinner?.stop();
1037
+ spinner?.clear();
1017
1038
  outputError(error instanceof Error ? error.message : "Request failed", options);
1018
1039
  process.exit(1);
1019
1040
  }
@@ -1023,10 +1044,12 @@ async function sendCommand(text, options) {
1023
1044
  import chalk13 from "chalk";
1024
1045
  import ora11 from "ora";
1025
1046
  async function listCommand4(options) {
1026
- const spinner = options.json ? null : ora11("Fetching messages...").start();
1047
+ const showSpinner = !options.json && process.stdout.isTTY;
1048
+ const spinner = showSpinner ? ora11("Fetching messages...").start() : null;
1027
1049
  const accessToken = await ensureValidToken(oauthConfig);
1028
1050
  if (!accessToken) {
1029
1051
  spinner?.stop();
1052
+ spinner?.clear();
1030
1053
  outputError(
1031
1054
  "Not authenticated. Run 'program auth login' first.",
1032
1055
  options
@@ -1047,6 +1070,7 @@ async function listCommand4(options) {
1047
1070
  });
1048
1071
  const result = await response.json();
1049
1072
  spinner?.stop();
1073
+ spinner?.clear();
1050
1074
  if (!response.ok || !result.success) {
1051
1075
  outputError(
1052
1076
  result.error ?? `Failed to fetch messages: ${response.status}`,
@@ -1096,6 +1120,7 @@ async function listCommand4(options) {
1096
1120
  }
1097
1121
  } catch (error) {
1098
1122
  spinner?.stop();
1123
+ spinner?.clear();
1099
1124
  outputError(
1100
1125
  error instanceof Error ? error.message : "Request failed",
1101
1126
  options
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/auth/login.ts","../src/lib/auth/credentials.ts","../src/lib/auth/device.ts","../src/lib/config.ts","../src/lib/output.ts","../src/commands/auth/logout.ts","../src/commands/auth/status.ts","../src/commands/project/create.ts","../src/lib/auth/oauth.ts","../src/lib/auth/pkce.ts","../src/lib/auth/callback-server.ts","../src/lib/convex.ts","../src/commands/project/get.ts","../src/commands/project/list.ts","../src/commands/workflow/list.ts","../src/commands/workflow/run.ts","../src/commands/workflow/status.ts","../src/commands/tool/execute.ts","../src/lib/agent-detect.ts","../src/commands/tool/list.ts","../src/commands/message/send.ts","../src/commands/message/list.ts","../src/commands/docs.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { loginCommand } from \"./commands/auth/login.js\";\nimport type { LoginOptions } from \"./commands/auth/login.js\";\nimport { logoutCommand } from \"./commands/auth/logout.js\";\nimport type { LogoutOptions } from \"./commands/auth/logout.js\";\nimport { statusCommand as authStatusCommand } from \"./commands/auth/status.js\";\nimport type { StatusOptions as AuthStatusOptions } from \"./commands/auth/status.js\";\nimport { createCommand as projectCreateCommand } from \"./commands/project/create.js\";\nimport type { CreateOptions } from \"./commands/project/create.js\";\nimport { getCommand as projectGetCommand } from \"./commands/project/get.js\";\nimport type { GetOptions } from \"./commands/project/get.js\";\nimport { listCommand as projectListCommand } from \"./commands/project/list.js\";\nimport type { ListOptions as ProjectListOptions } from \"./commands/project/list.js\";\nimport { listCommand as workflowListCommand } from \"./commands/workflow/list.js\";\nimport type { ListOptions as WorkflowListOptions } from \"./commands/workflow/list.js\";\nimport { runCommand as workflowRunCommand } from \"./commands/workflow/run.js\";\nimport type { RunOptions } from \"./commands/workflow/run.js\";\nimport { statusCommand as workflowStatusCommand } from \"./commands/workflow/status.js\";\nimport type { StatusOptions as WorkflowStatusOptions } from \"./commands/workflow/status.js\";\nimport { executeCommand as toolExecuteCommand } from \"./commands/tool/execute.js\";\nimport type { ExecuteOptions } from \"./commands/tool/execute.js\";\nimport { listCommand as toolListCommand } from \"./commands/tool/list.js\";\nimport type { ListOptions as ToolListOptions } from \"./commands/tool/list.js\";\nimport { sendCommand as messageSendCommand } from \"./commands/message/send.js\";\nimport type { SendMessageOptions } from \"./commands/message/send.js\";\nimport { listCommand as messageListCommand } from \"./commands/message/list.js\";\nimport type { ListMessageOptions } from \"./commands/message/list.js\";\nimport { docsCommand } from \"./commands/docs.js\";\nimport type { DocsOptions } from \"./commands/docs.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"program\")\n .description(\"CLI for the Program video creation platform\")\n .version(\"0.1.0\");\n\n// Auth commands\nconst auth = program.command(\"auth\").description(\"Authentication commands\");\n\nauth\n .command(\"login\")\n .description(\"Authenticate with the Program platform\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (options: LoginOptions) => {\n await loginCommand(options);\n });\n\nauth\n .command(\"logout\")\n .description(\"Log out from the Program platform\")\n .option(\"--json\", \"Output as JSON\")\n .action((options: LogoutOptions) => {\n logoutCommand(options);\n });\n\nauth\n .command(\"status\")\n .description(\"Check authentication status\")\n .option(\"--json\", \"Output as JSON\")\n .action((options: AuthStatusOptions) => {\n authStatusCommand(options);\n });\n\n// Project commands\nconst project = program.command(\"project\").description(\"Project management commands\");\n\nproject\n .command(\"create\")\n .description(\"Create a new project\")\n .option(\"--title <title>\", \"Project title\")\n .option(\"--description <description>\", \"Project description\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (options: CreateOptions) => {\n await projectCreateCommand(options);\n });\n\nproject\n .command(\"list\")\n .description(\"List projects\")\n .option(\"--limit <limit>\", \"Maximum number of projects to return\", parseInt)\n .option(\"--json\", \"Output as JSON\")\n .action(async (options: ProjectListOptions) => {\n await projectListCommand(options);\n });\n\nproject\n .command(\"get <id>\")\n .description(\"Get project details including composition\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (id: string, options: GetOptions) => {\n await projectGetCommand(id, options);\n });\n\n// Workflow commands\nconst workflow = program.command(\"workflow\").description(\"Workflow template commands\");\n\nworkflow\n .command(\"list\")\n .description(\"List available workflow templates\")\n .option(\"--limit <limit>\", \"Maximum number of templates to return\", parseInt)\n .option(\"--public-only\", \"Only show public templates\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (options: WorkflowListOptions) => {\n await workflowListCommand(options);\n });\n\nworkflow\n .command(\"run <templateId>\")\n .description(\"Execute a workflow template\")\n .option(\"--project <projectId>\", \"Project ID to associate with execution\")\n .option(\"--input <json>\", \"JSON input for the workflow\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (templateId: string, options: RunOptions) => {\n await workflowRunCommand(templateId, options);\n });\n\nworkflow\n .command(\"status <executionId>\")\n .description(\"Check workflow execution status\")\n .option(\"--watch\", \"Continuously poll for status updates\")\n .option(\"--interval <ms>\", \"Poll interval in milliseconds\", parseInt)\n .option(\"--json\", \"Output as JSON\")\n .action(async (executionId: string, options: WorkflowStatusOptions) => {\n await workflowStatusCommand(executionId, options);\n });\n\n// Tool commands (direct agent tool access)\nconst tool = program.command(\"tool\").description(\"Execute agent tools directly\");\n\ntool\n .command(\"list\")\n .description(\"List available agent tools\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (options: ToolListOptions) => {\n await toolListCommand(options);\n });\n\ntool\n .command(\"exec <toolName>\")\n .description(\"Execute an agent tool\")\n .requiredOption(\"--project <projectId>\", \"Project ID to execute tool against\")\n .option(\"--params <json>\", \"JSON parameters for the tool\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (toolName: string, options: ExecuteOptions) => {\n await toolExecuteCommand(toolName, options);\n });\n\n// Message commands (send and list messages in project chat)\nconst message = program.command(\"message\").description(\"Manage messages in project chat\");\n\nmessage\n .command(\"list\")\n .description(\"List messages in the project chat\")\n .requiredOption(\"--project <projectId>\", \"Project ID to list messages from\")\n .option(\"--limit <limit>\", \"Maximum number of messages to return\", parseInt)\n .option(\"--json\", \"Output as JSON\")\n .action(async (options: ListMessageOptions) => {\n await messageListCommand(options);\n });\n\nmessage\n .command(\"send <text>\")\n .description(\n \"Log a text message to the project chat. NOTE: This only adds a message to the chat history - it does NOT trigger the AI agent. To perform actions, use 'tool exec' instead.\",\n )\n .requiredOption(\"--project <projectId>\", \"Project ID to send message to\")\n .option(\"--role <role>\", \"Message role: user or assistant (default: assistant)\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (text: string, options: SendMessageOptions) => {\n await messageSendCommand(text, options);\n });\n\n// Docs command\nprogram\n .command(\"docs\")\n .description(\"Display CLI documentation and command schema\")\n .option(\"--schema\", \"Output full command schema as JSON\")\n .option(\"--json\", \"Output as JSON\")\n .action((options: DocsOptions) => {\n docsCommand(options);\n });\n\n// Parse arguments\nprogram.parse();\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { startDeviceAuth } from \"../../lib/auth/device.js\";\nimport { oauthConfig } from \"../../lib/config.js\";\nimport { formatSuccess, outputError, outputSuccess } from \"../../lib/output.js\";\nimport type { OutputOptions } from \"../../lib/output.js\";\n\nexport type LoginOptions = OutputOptions;\n\n/**\n * Format user code with dash for readability (ABCD1234 -> ABCD-1234)\n */\nfunction formatUserCode(code: string): string {\n if (code.length === 8) {\n return `${code.slice(0, 4)}-${code.slice(4)}`;\n }\n return code;\n}\n\n/**\n * Device authorization flow - works everywhere including headless environments\n * User visits a URL on any device and enters the code shown in the terminal\n */\nexport async function loginCommand(options: LoginOptions): Promise<void> {\n const spinner = ora(\"Requesting device code...\").start();\n\n try {\n const deviceAuth = await startDeviceAuth(oauthConfig);\n spinner.stop();\n\n // Display the code and URL for the user\n console.log();\n console.log(chalk.bold(\" Sign in to Program\"));\n console.log();\n console.log(` Visit: ${chalk.cyan(deviceAuth.verificationUrl)}`);\n console.log();\n console.log(` Enter code: ${chalk.bold.yellow(formatUserCode(deviceAuth.userCode))}`);\n console.log();\n\n // If there's a complete URL with the code embedded, also show that\n if (deviceAuth.verificationUrlComplete) {\n console.log(chalk.dim(` Or open: ${deviceAuth.verificationUrlComplete}`));\n console.log();\n }\n\n const waitingSpinner = ora(\"Waiting for authorization...\").start();\n\n // Poll until the user completes auth\n const credentials = await deviceAuth.pollForCompletion();\n\n waitingSpinner.stop();\n\n if (options.json) {\n outputSuccess(\n {\n authenticated: true,\n email: credentials.email,\n userId: credentials.userId,\n organizationId: credentials.organizationId,\n },\n options\n );\n } else {\n console.log(formatSuccess(`Authenticated as ${chalk.cyan(credentials.email)}`));\n if (credentials.organizationId) {\n console.log(chalk.dim(` Organization: ${credentials.organizationId}`));\n }\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Authentication failed\";\n outputError(message, options);\n process.exit(1);\n }\n}\n","import Conf from \"conf\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\n\nexport interface Credentials {\n accessToken: string;\n refreshToken: string;\n expiresAt: number;\n userId: string;\n organizationId: string;\n email: string;\n}\n\n// Use ~/.program/ for credentials storage\nconst CREDENTIALS_DIR = path.join(os.homedir(), \".program\");\nconst CREDENTIALS_FILE = path.join(CREDENTIALS_DIR, \"credentials.json\");\n\n// Ensure directory exists with proper permissions\nfunction ensureCredentialsDir(): void {\n if (!fs.existsSync(CREDENTIALS_DIR)) {\n fs.mkdirSync(CREDENTIALS_DIR, { mode: 0o700, recursive: true });\n }\n}\n\n// Using conf for secure credential storage with automatic file permissions\nconst store = new Conf<{ credentials: Credentials | null }>({\n projectName: \"program-cli\",\n cwd: CREDENTIALS_DIR,\n configName: \"credentials\",\n fileExtension: \"json\",\n defaults: {\n credentials: null,\n },\n});\n\nexport function saveCredentials(credentials: Credentials): void {\n ensureCredentialsDir();\n store.set(\"credentials\", credentials);\n\n // Ensure file has restrictive permissions (owner read/write only)\n try {\n fs.chmodSync(CREDENTIALS_FILE, 0o600);\n } catch {\n // Ignore chmod errors on Windows\n }\n}\n\nexport function getCredentials(): Credentials | null {\n return store.get(\"credentials\");\n}\n\nexport function clearCredentials(): void {\n store.delete(\"credentials\");\n}\n\nexport function isAuthenticated(): boolean {\n const creds = getCredentials();\n if (!creds) return false;\n\n // Check if token is expired (with 5 minute buffer)\n const now = Date.now();\n const expiresAt = creds.expiresAt * 1000; // Convert to milliseconds\n const bufferMs = 5 * 60 * 1000; // 5 minutes\n\n return now < expiresAt - bufferMs;\n}\n\nexport function needsRefresh(): boolean {\n const creds = getCredentials();\n if (!creds) return false;\n\n // Needs refresh if within 5 minutes of expiry\n const now = Date.now();\n const expiresAt = creds.expiresAt * 1000;\n const bufferMs = 5 * 60 * 1000;\n\n return now >= expiresAt - bufferMs && now < expiresAt;\n}\n","import { saveCredentials, getCredentials } from \"./credentials.js\";\nimport type { Credentials } from \"./credentials.js\";\n\n// OAuth client ID - same as the main oauth.ts\nconst CLIENT_ID = \"program-cli\";\nconst SCOPES = [\"openid\", \"profile\", \"email\", \"offline_access\"];\n\nexport interface DeviceAuthConfig {\n baseUrl: string;\n}\n\ninterface DeviceCodeResponse {\n device_code: string;\n user_code: string;\n verification_uri: string;\n verification_uri_complete?: string;\n expires_in: number;\n interval: number;\n}\n\ninterface TokenResponse {\n access_token: string;\n refresh_token?: string;\n expires_in?: number;\n token_type?: string;\n scope?: string;\n}\n\ninterface TokenErrorResponse {\n error: string;\n error_description?: string;\n}\n\ninterface UserInfo {\n id: string;\n email: string;\n name: string;\n organizationId?: string;\n}\n\n/**\n * Request a device code from the server\n */\nexport async function requestDeviceCode(\n config: DeviceAuthConfig\n): Promise<DeviceCodeResponse> {\n const url = new URL(\"/api/auth/device/code\", config.baseUrl);\n\n const response = await fetch(url.toString(), {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n client_id: CLIENT_ID,\n scope: SCOPES.join(\" \"),\n }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to get device code: ${response.status} ${errorText}`);\n }\n\n return response.json() as Promise<DeviceCodeResponse>;\n}\n\n/**\n * Poll for the token after user authorizes\n * Returns the token response or an error code\n */\nexport async function pollForToken(\n config: DeviceAuthConfig,\n deviceCode: string\n): Promise<TokenResponse | TokenErrorResponse> {\n const url = new URL(\"/api/auth/device/token\", config.baseUrl);\n\n const response = await fetch(url.toString(), {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n device_code: deviceCode,\n client_id: CLIENT_ID,\n }),\n });\n\n // Device flow uses 400 status for pending/slow_down errors\n const data = (await response.json()) as TokenResponse | TokenErrorResponse;\n\n if (!response.ok) {\n // Check if it's an expected error (authorization_pending, slow_down)\n if (\"error\" in data) {\n return data;\n }\n throw new Error(`Token request failed: ${response.status}`);\n }\n\n return data as TokenResponse;\n}\n\n/**\n * Get user info from the BetterAuth session endpoint\n * Device authorization returns a BetterAuth token, not an OIDC token\n */\nasync function getUserInfo(\n config: DeviceAuthConfig,\n accessToken: string\n): Promise<UserInfo> {\n // Use the BetterAuth get-session endpoint with Bearer token\n const sessionUrl = new URL(\"/api/auth/get-session\", config.baseUrl);\n\n const response = await fetch(sessionUrl.toString(), {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n });\n\n if (!response.ok) {\n // Try the token/session endpoint if get-session doesn't work\n const tokenUrl = new URL(\"/api/auth/token\", config.baseUrl);\n const tokenResponse = await fetch(tokenUrl.toString(), {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n });\n\n if (!tokenResponse.ok) {\n throw new Error(`Failed to get user info: ${response.status}`);\n }\n\n const tokenData = (await tokenResponse.json()) as {\n user?: { id?: string; email?: string; name?: string };\n session?: { activeOrganizationId?: string };\n };\n\n if (!tokenData.user?.id || !tokenData.user.email) {\n throw new Error(\"Invalid token response: missing user info\");\n }\n\n return {\n id: tokenData.user.id,\n email: tokenData.user.email,\n name: tokenData.user.name ?? tokenData.user.email,\n organizationId: tokenData.session?.activeOrganizationId,\n };\n }\n\n const data = (await response.json()) as {\n user?: {\n id?: string;\n email?: string;\n name?: string;\n };\n session?: {\n activeOrganizationId?: string;\n };\n };\n\n if (!data.user?.id || !data.user.email) {\n throw new Error(\"Invalid session response: missing user info\");\n }\n\n return {\n id: data.user.id,\n email: data.user.email,\n name: data.user.name ?? data.user.email,\n organizationId: data.session?.activeOrganizationId,\n };\n}\n\n/**\n * Start the device authorization flow\n * Returns display info for the CLI to show the user\n */\nexport interface DeviceAuthDisplay {\n userCode: string;\n verificationUrl: string;\n verificationUrlComplete?: string;\n expiresIn: number;\n interval: number;\n pollForCompletion: () => Promise<Credentials>;\n}\n\nexport async function startDeviceAuth(\n config: DeviceAuthConfig\n): Promise<DeviceAuthDisplay> {\n const deviceCode = await requestDeviceCode(config);\n\n return {\n userCode: deviceCode.user_code,\n verificationUrl: deviceCode.verification_uri,\n verificationUrlComplete: deviceCode.verification_uri_complete,\n expiresIn: deviceCode.expires_in,\n interval: deviceCode.interval,\n pollForCompletion: async () => {\n return pollUntilComplete(config, deviceCode);\n },\n };\n}\n\n/**\n * Poll until the user completes authorization or the code expires\n */\nasync function pollUntilComplete(\n config: DeviceAuthConfig,\n deviceCode: DeviceCodeResponse\n): Promise<Credentials> {\n const startTime = Date.now();\n const expiresAt = startTime + deviceCode.expires_in * 1000;\n let interval = deviceCode.interval * 1000;\n\n while (Date.now() < expiresAt) {\n // Wait for the interval before polling\n await new Promise((resolve) => setTimeout(resolve, interval));\n\n const result = await pollForToken(config, deviceCode.device_code);\n\n // Check if it's an error response\n if (\"error\" in result) {\n switch (result.error) {\n case \"authorization_pending\":\n // User hasn't completed authorization yet, continue polling\n continue;\n\n case \"slow_down\":\n // Server asked us to slow down, increase interval\n interval += 5000;\n continue;\n\n case \"expired_token\":\n throw new Error(\"Device code expired. Please start a new login.\");\n\n case \"access_denied\":\n throw new Error(\"Access denied. You denied the authorization request.\");\n\n default:\n throw new Error(\n result.error_description ?? `Authorization failed: ${result.error}`\n );\n }\n }\n\n // Success! We got tokens\n const tokens = result;\n\n // Get user info\n const userInfo = await getUserInfo(config, tokens.access_token);\n\n // Calculate expiry timestamp (default to 1 hour if not provided)\n const expiresIn = tokens.expires_in ?? 3600;\n const expiresAtTimestamp = Math.floor(Date.now() / 1000) + expiresIn;\n\n // Save credentials (refresh token may not be present for device flow)\n const credentials: Credentials = {\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token ?? \"\",\n expiresAt: expiresAtTimestamp,\n userId: userInfo.id,\n organizationId: userInfo.organizationId ?? \"\",\n email: userInfo.email,\n };\n\n saveCredentials(credentials);\n\n return credentials;\n }\n\n throw new Error(\"Device code expired. Please start a new login.\");\n}\n\n/**\n * Check if we have valid credentials\n */\nexport function hasValidCredentials(): boolean {\n const creds = getCredentials();\n if (!creds) return false;\n\n // Check if token is expired (with 5 min buffer)\n const now = Date.now();\n const expiresAt = creds.expiresAt * 1000;\n const bufferMs = 5 * 60 * 1000;\n\n return now < expiresAt - bufferMs;\n}\n","import type { OAuthConfig } from \"./auth/index.js\";\nimport type { ConvexConfig } from \"./convex.js\";\n\n// Environment-based configuration\n// These can be overridden via environment variables\n\nfunction getEnvOrDefault(key: string, defaultValue: string): string {\n return process.env[key] ?? defaultValue;\n}\n\n// Base URL for the web app (OAuth provider)\n// Set via BASE_URL environment variable\nexport const BASE_URL = getEnvOrDefault(\n \"BASE_URL\",\n \"https://program.video\"\n);\n\n// Convex deployment URL\n// Uses NEXT_PUBLIC_CONVEX_URL from .env - the .convex.cloud URL for API calls\nfunction getConvexUrl(): string {\n const override = process.env.PROGRAM_CONVEX_URL;\n if (override) return override;\n\n const convexUrl = process.env.NEXT_PUBLIC_CONVEX_URL;\n if (convexUrl) return convexUrl;\n\n // Fallback for local development\n return \"https://mild-hyena-697.convex.cloud\";\n}\n\nexport const CONVEX_URL = getConvexUrl();\n\nexport const oauthConfig: OAuthConfig = {\n baseUrl: BASE_URL,\n};\n\nexport const convexConfig: ConvexConfig = {\n convexUrl: CONVEX_URL,\n oauthConfig,\n};\n","import chalk from \"chalk\";\n\nexport interface OutputOptions {\n json?: boolean;\n}\n\nexport interface SuccessResult<T> {\n success: true;\n data: T;\n}\n\nexport interface ErrorResult {\n success: false;\n error: string;\n}\n\nexport type Result<T> = SuccessResult<T> | ErrorResult;\n\n/**\n * Output a success result in the appropriate format\n */\nexport function outputSuccess<T>(data: T, options: OutputOptions = {}): void {\n if (options.json) {\n const result: SuccessResult<T> = { success: true, data };\n console.log(JSON.stringify(result, null, 2));\n } else {\n // For human-readable output, we'll handle this per-command\n // This is a fallback that just pretty-prints\n console.log(data);\n }\n}\n\n/**\n * Output an error result in the appropriate format\n */\nexport function outputError(error: string, options: OutputOptions = {}): void {\n if (options.json) {\n const result: ErrorResult = { success: false, error };\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.error(chalk.red(\"Error:\"), error);\n }\n}\n\n/**\n * Format a table for human-readable output\n */\nexport function formatTable(\n headers: string[],\n rows: string[][],\n options: { indent?: number } = {}\n): string {\n const indent = \" \".repeat(options.indent ?? 0);\n\n // Calculate column widths\n const widths = headers.map((h, i) => {\n const maxRow = Math.max(...rows.map((r) => (r[i] ?? \"\").length));\n return Math.max(h.length, maxRow);\n });\n\n // Format header\n const headerLine = headers\n .map((h, i) => chalk.bold(h.padEnd(widths[i] ?? 0)))\n .join(\" \");\n\n // Format separator\n const separator = widths.map((w) => \"-\".repeat(w)).join(\" \");\n\n // Format rows\n const formattedRows = rows.map((row) =>\n row.map((cell, i) => (cell || \"\").padEnd(widths[i] ?? 0)).join(\" \")\n );\n\n return [indent + headerLine, indent + separator, ...formattedRows.map((r) => indent + r)].join(\n \"\\n\"\n );\n}\n\n/**\n * Format a key-value list for human-readable output\n */\nexport function formatKeyValue(\n items: { key: string; value: string }[],\n options: { indent?: number } = {}\n): string {\n const indent = \" \".repeat(options.indent ?? 0);\n const maxKeyLength = Math.max(...items.map((item) => item.key.length));\n\n return items\n .map(\n (item) =>\n indent + chalk.dim(item.key.padEnd(maxKeyLength) + \":\") + \" \" + item.value\n )\n .join(\"\\n\");\n}\n\n/**\n * Format a success message\n */\nexport function formatSuccess(message: string): string {\n return chalk.green(\"✓\") + \" \" + message;\n}\n\n/**\n * Format a warning message\n */\nexport function formatWarning(message: string): string {\n return chalk.yellow(\"⚠\") + \" \" + message;\n}\n\n/**\n * Format an info message\n */\nexport function formatInfo(message: string): string {\n return chalk.blue(\"ℹ\") + \" \" + message;\n}\n","import { clearCredentials, getCredentials } from \"../../lib/auth/credentials.js\";\nimport { formatSuccess, outputSuccess } from \"../../lib/output.js\";\nimport type {OutputOptions} from \"../../lib/output.js\";\n\nexport type LogoutOptions = OutputOptions;\n\nexport function logoutCommand(options: LogoutOptions): void {\n const credentials = getCredentials();\n\n if (!credentials) {\n if (options.json) {\n outputSuccess({ loggedOut: true, wasAuthenticated: false }, options);\n } else {\n console.log(\"Not currently logged in.\");\n }\n return;\n }\n\n const email = credentials.email;\n clearCredentials();\n\n if (options.json) {\n outputSuccess({ loggedOut: true, wasAuthenticated: true, email }, options);\n } else {\n console.log(formatSuccess(`Logged out from ${email}`));\n }\n}\n","import chalk from \"chalk\";\nimport { getCredentials, isAuthenticated, needsRefresh } from \"../../lib/auth/credentials.js\";\nimport { formatKeyValue, formatSuccess, formatWarning, outputSuccess } from \"../../lib/output.js\";\nimport type {OutputOptions} from \"../../lib/output.js\";\n\nexport type StatusOptions = OutputOptions;\n\nexport function statusCommand(options: StatusOptions): void {\n const credentials = getCredentials();\n\n if (!credentials) {\n if (options.json) {\n outputSuccess({ authenticated: false }, options);\n } else {\n console.log(\"Not logged in. Run 'program auth login' to authenticate.\");\n }\n return;\n }\n\n const authenticated = isAuthenticated();\n const expiresAt = credentials.expiresAt;\n const now = Math.floor(Date.now() / 1000);\n const expiresIn = expiresAt - now;\n\n if (options.json) {\n outputSuccess(\n {\n authenticated,\n user: credentials.email,\n userId: credentials.userId,\n organizationId: credentials.organizationId,\n expiresAt,\n expiresIn,\n needsRefresh: needsRefresh(),\n },\n options\n );\n } else {\n if (!authenticated) {\n console.log(formatWarning(\"Token expired. Run 'program auth login' to re-authenticate.\"));\n return;\n }\n\n console.log(formatSuccess(\"Logged in\"));\n console.log();\n console.log(\n formatKeyValue([\n { key: \"Email\", value: credentials.email },\n { key: \"User ID\", value: credentials.userId },\n { key: \"Organization\", value: credentials.organizationId || chalk.dim(\"(none)\") },\n { key: \"Token expires\", value: formatExpiresIn(expiresIn) },\n ])\n );\n }\n}\n\nfunction formatExpiresIn(seconds: number): string {\n if (seconds <= 0) {\n return chalk.red(\"expired\");\n }\n\n if (seconds < 60) {\n return chalk.yellow(`in ${seconds} seconds`);\n }\n\n if (seconds < 3600) {\n const minutes = Math.floor(seconds / 60);\n return chalk.green(`in ${minutes} minute${minutes === 1 ? \"\" : \"s\"}`);\n }\n\n const hours = Math.floor(seconds / 3600);\n const minutes = Math.floor((seconds % 3600) / 60);\n return chalk.green(`in ${hours}h ${minutes}m`);\n}\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { createConvexClient } from \"../../lib/convex.js\";\nimport { convexConfig } from \"../../lib/config.js\";\nimport { formatSuccess, outputError, outputSuccess } from \"../../lib/output.js\";\nimport type {OutputOptions} from \"../../lib/output.js\";\n\nexport interface CreateOptions extends OutputOptions {\n title?: string;\n description?: string;\n}\n\ninterface CreateResult {\n id: string;\n title: string;\n}\n\nexport async function createCommand(options: CreateOptions): Promise<void> {\n const spinner = options.json ? null : ora(\"Creating project...\").start();\n\n const client = createConvexClient(convexConfig);\n\n const result = await client.mutation<string>(\"projects.create\", {\n title: options.title,\n description: options.description,\n });\n\n spinner?.stop();\n\n if (!result.success || !result.data) {\n outputError(result.error ?? \"Failed to create project\", options);\n process.exit(1);\n }\n\n const projectData: CreateResult = {\n id: result.data,\n title: options.title ?? \"Untitled Project\",\n };\n\n if (options.json) {\n outputSuccess(projectData, options);\n } else {\n console.log(formatSuccess(`Created project ${chalk.cyan(projectData.title)}`));\n console.log(chalk.dim(` ID: ${projectData.id}`));\n }\n}\n","import open from \"open\";\nimport { generateCodeChallenge, generateCodeVerifier, generateState } from \"./pkce.js\";\nimport { startCallbackServer } from \"./callback-server.js\";\nimport { saveCredentials, getCredentials } from \"./credentials.js\";\nimport type {Credentials} from \"./credentials.js\";\n\n// OAuth configuration\nconst CALLBACK_PORT = 8976;\nconst REDIRECT_URI = `http://localhost:${CALLBACK_PORT}/callback`;\n// Use standard OAuth scopes - email is required to identify the user\nconst SCOPES = [\"openid\", \"profile\", \"email\", \"offline_access\"];\n\n// OAuth client ID - same for all agents\n// Agent source is detected at runtime per-request (see lib/agent-detect.ts)\nconst CLIENT_ID = \"program-cli\";\n\nexport interface OAuthConfig {\n baseUrl: string;\n}\n\nexport interface TokenResponse {\n access_token: string;\n refresh_token?: string;\n expires_in: number;\n token_type: string;\n scope?: string;\n}\n\nexport interface UserInfo {\n id: string;\n email: string;\n name: string;\n organizationId?: string;\n}\n\n/**\n * Start the OAuth login flow\n * Opens browser for authentication and waits for callback\n */\nexport async function login(config: OAuthConfig): Promise<Credentials> {\n const codeVerifier = generateCodeVerifier();\n const codeChallenge = generateCodeChallenge(codeVerifier);\n const state = generateState();\n\n // Build authorization URL (use the page that handles the redirect properly)\n const authUrl = new URL(\"/oauth/authorize\", config.baseUrl);\n authUrl.searchParams.set(\"client_id\", CLIENT_ID);\n authUrl.searchParams.set(\"redirect_uri\", REDIRECT_URI);\n authUrl.searchParams.set(\"response_type\", \"code\");\n authUrl.searchParams.set(\"scope\", SCOPES.join(\" \"));\n authUrl.searchParams.set(\"state\", state);\n authUrl.searchParams.set(\"code_challenge\", codeChallenge);\n authUrl.searchParams.set(\"code_challenge_method\", \"S256\");\n\n // Start callback server before opening browser\n const callbackPromise = startCallbackServer(CALLBACK_PORT, state);\n\n // Open browser to authorization URL\n await open(authUrl.toString());\n\n // Wait for callback with authorization code\n const { code } = await callbackPromise;\n\n // Exchange code for tokens\n const tokens = await exchangeCodeForTokens(config, code, codeVerifier);\n\n // Get user info\n const userInfo = await getUserInfo(config, tokens.access_token);\n\n // Calculate expiry timestamp\n const expiresAt = Math.floor(Date.now() / 1000) + tokens.expires_in;\n\n // Validate we have a refresh token (required for token refresh)\n if (!tokens.refresh_token) {\n throw new Error(\"OAuth server did not return a refresh token\");\n }\n\n // Save credentials (source is detected at runtime per-request, not stored here)\n const credentials: Credentials = {\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n expiresAt,\n userId: userInfo.id,\n organizationId: userInfo.organizationId ?? \"\",\n email: userInfo.email,\n };\n\n saveCredentials(credentials);\n\n return credentials;\n}\n\n/**\n * Exchange authorization code for tokens\n */\nasync function exchangeCodeForTokens(\n config: OAuthConfig,\n code: string,\n codeVerifier: string\n): Promise<TokenResponse> {\n const tokenUrl = new URL(\"/api/auth/oauth2/token\", config.baseUrl);\n\n const body = new URLSearchParams({\n grant_type: \"authorization_code\",\n client_id: CLIENT_ID,\n code,\n redirect_uri: REDIRECT_URI,\n code_verifier: codeVerifier,\n });\n\n const response = await fetch(tokenUrl.toString(), {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: body.toString(),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token exchange failed: ${response.status} ${errorText}`);\n }\n\n return response.json() as Promise<TokenResponse>;\n}\n\n/**\n * Refresh the access token using the refresh token\n */\nexport async function refreshAccessToken(config: OAuthConfig): Promise<Credentials | null> {\n const creds = getCredentials();\n if (!creds?.refreshToken) {\n return null;\n }\n\n const tokenUrl = new URL(\"/api/auth/oauth2/token\", config.baseUrl);\n\n const body = new URLSearchParams({\n grant_type: \"refresh_token\",\n client_id: CLIENT_ID,\n refresh_token: creds.refreshToken,\n });\n\n const response = await fetch(tokenUrl.toString(), {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: body.toString(),\n });\n\n if (!response.ok) {\n // Refresh failed - user needs to re-authenticate\n return null;\n }\n\n const tokens = (await response.json()) as TokenResponse;\n const expiresAt = Math.floor(Date.now() / 1000) + tokens.expires_in;\n\n const newCredentials: Credentials = {\n ...creds,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token ?? creds.refreshToken,\n expiresAt,\n };\n\n saveCredentials(newCredentials);\n\n return newCredentials;\n}\n\n/**\n * Get user info from the OAuth server\n */\nasync function getUserInfo(config: OAuthConfig, accessToken: string): Promise<UserInfo> {\n const userInfoUrl = new URL(\"/api/auth/oauth2/userinfo\", config.baseUrl);\n\n const response = await fetch(userInfoUrl.toString(), {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n });\n\n if (!response.ok) {\n throw new Error(`Failed to get user info: ${response.status}`);\n }\n\n const data = (await response.json()) as {\n sub?: string;\n id?: string;\n email?: string;\n name?: string;\n organizationId?: string;\n };\n\n const id = data.sub ?? data.id;\n const email = data.email;\n\n if (!id || !email) {\n throw new Error(\"Invalid user info response: missing id or email\");\n }\n\n return {\n id,\n email,\n name: data.name ?? email,\n organizationId: data.organizationId,\n };\n}\n\n/**\n * Ensure we have a valid access token, refreshing if necessary\n */\nexport async function ensureValidToken(config: OAuthConfig): Promise<string | null> {\n const creds = getCredentials();\n if (!creds) {\n return null;\n }\n\n const now = Date.now();\n const expiresAt = creds.expiresAt * 1000;\n const bufferMs = 5 * 60 * 1000; // 5 minutes\n\n // If token is still valid, return it\n if (now < expiresAt - bufferMs) {\n return creds.accessToken;\n }\n\n // Try to refresh\n const refreshed = await refreshAccessToken(config);\n return refreshed?.accessToken ?? null;\n}\n","import * as crypto from \"node:crypto\";\n\n/**\n * Generate a cryptographically random code verifier for PKCE\n * Must be between 43-128 characters, using unreserved characters\n */\nexport function generateCodeVerifier(): string {\n // Generate 32 random bytes and encode as base64url\n const buffer = crypto.randomBytes(32);\n return buffer\n .toString(\"base64\")\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=/g, \"\");\n}\n\n/**\n * Generate the code challenge from a code verifier using S256 method\n */\nexport function generateCodeChallenge(verifier: string): string {\n const hash = crypto.createHash(\"sha256\").update(verifier).digest();\n return hash\n .toString(\"base64\")\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=/g, \"\");\n}\n\n/**\n * Generate a random state parameter for CSRF protection\n */\nexport function generateState(): string {\n return crypto.randomBytes(16).toString(\"hex\");\n}\n","import * as http from \"node:http\";\nimport { URL } from \"node:url\";\n\nexport interface CallbackResult {\n code: string;\n state: string;\n}\n\nexport interface CallbackError {\n error: string;\n errorDescription?: string;\n}\n\nconst SUCCESS_HTML = `\n<!DOCTYPE html>\n<html>\n<head>\n <title>Authentication Successful</title>\n <style>\n * { box-sizing: border-box; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n min-height: 100vh;\n margin: 0;\n padding: 2rem;\n background: #F5F5F0;\n color: #171717;\n }\n .card {\n width: 100%;\n max-width: 400px;\n background: white;\n border-radius: 12px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.1), 0 1px 2px rgba(0,0,0,0.06);\n padding: 2rem;\n text-align: center;\n }\n .logo {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n margin-bottom: 1.5rem;\n }\n .logo-icon {\n width: 16px;\n height: 16px;\n background: #EA580C;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n .logo-icon-inner {\n width: 3px;\n height: 3px;\n background: white;\n animation: flash 1.2s ease-in-out infinite;\n }\n @keyframes flash {\n 0%, 100% { opacity: 0.9; }\n 50% { opacity: 0.2; }\n }\n .logo-text {\n font-size: 1.25rem;\n font-weight: 300;\n color: #171717;\n }\n h1 {\n margin: 0 0 0.5rem 0;\n font-size: 1.25rem;\n font-weight: 500;\n letter-spacing: -0.01em;\n color: #171717;\n }\n p {\n margin: 0;\n color: #737373;\n font-size: 0.875rem;\n font-weight: 400;\n }\n </style>\n</head>\n<body>\n <div class=\"card\">\n <div class=\"logo\">\n <div class=\"logo-icon\"><div class=\"logo-icon-inner\"></div></div>\n <span class=\"logo-text\">Program.</span>\n </div>\n <h1>Authentication Successful</h1>\n <p>You can close this window and return to the terminal.</p>\n </div>\n</body>\n</html>\n`;\n\nconst ERROR_HTML = (error: string, description?: string) => `\n<!DOCTYPE html>\n<html>\n<head>\n <title>Authentication Failed</title>\n <style>\n * { box-sizing: border-box; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n min-height: 100vh;\n margin: 0;\n padding: 2rem;\n background: #F5F5F0;\n color: #171717;\n }\n .logo {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin-bottom: 2rem;\n }\n .logo-icon {\n width: 16px;\n height: 16px;\n background: #EA580C;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n .logo-icon-inner {\n width: 3px;\n height: 3px;\n background: white;\n animation: flash 1.2s infinite;\n }\n @keyframes flash {\n 0% { opacity: 0.8; }\n 50% { opacity: 0.1; }\n 100% { opacity: 0.8; }\n }\n .logo-text {\n font-size: 1.25rem;\n font-weight: 300;\n color: #171717;\n }\n .card {\n width: 100%;\n max-width: 400px;\n background: white;\n border-radius: 12px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.1), 0 1px 2px rgba(0,0,0,0.06);\n padding: 2rem;\n text-align: center;\n }\n .icon {\n width: 48px;\n height: 48px;\n background: #dc2626;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 0 auto 1.5rem;\n }\n .icon svg {\n width: 24px;\n height: 24px;\n }\n .icon svg path {\n fill: none;\n stroke: white;\n stroke-width: 2;\n stroke-linecap: round;\n stroke-linejoin: round;\n }\n h1 {\n margin: 0 0 0.5rem 0;\n font-size: 1.25rem;\n font-weight: 300;\n letter-spacing: -0.01em;\n }\n p {\n margin: 0;\n color: #737373;\n font-size: 0.875rem;\n font-weight: 400;\n }\n .error-detail {\n margin-top: 1rem;\n padding: 0.75rem;\n background: #fef2f2;\n border-radius: 8px;\n color: #dc2626;\n font-size: 0.8125rem;\n }\n </style>\n</head>\n<body>\n <div class=\"logo\">\n <div class=\"logo-icon\"><div class=\"logo-icon-inner\"></div></div>\n <span class=\"logo-text\">Program.</span>\n </div>\n <div class=\"card\">\n <div class=\"icon\">\n <svg viewBox=\"0 0 24 24\">\n <path d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </div>\n <h1>Authentication Failed</h1>\n <p>Unable to complete the authentication process.</p>\n <div class=\"error-detail\">${error}${description ? `: ${description}` : \"\"}</div>\n </div>\n</body>\n</html>\n`;\n\n/**\n * Start a local HTTP server to receive the OAuth callback\n * Returns a promise that resolves with the authorization code\n */\nexport function startCallbackServer(\n port: number,\n expectedState: string,\n timeoutMs = 120000\n): Promise<CallbackResult> {\n return new Promise((resolve, reject) => {\n const server = http.createServer((req, res) => {\n if (!req.url) {\n res.writeHead(400);\n res.end(\"Bad request\");\n return;\n }\n\n const url = new URL(req.url, `http://localhost:${port}`);\n\n // Only handle /callback path\n if (url.pathname !== \"/callback\") {\n res.writeHead(404);\n res.end(\"Not found\");\n return;\n }\n\n const code = url.searchParams.get(\"code\");\n const state = url.searchParams.get(\"state\");\n const error = url.searchParams.get(\"error\");\n const errorDescription = url.searchParams.get(\"error_description\");\n\n // Handle error response from OAuth server\n if (error) {\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(ERROR_HTML(error, errorDescription ?? undefined));\n\n server.close();\n reject(new Error(errorDescription ?? error));\n return;\n }\n\n // Validate state to prevent CSRF\n if (state !== expectedState) {\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(ERROR_HTML(\"Invalid state\", \"State mismatch - possible CSRF attack\"));\n\n server.close();\n reject(new Error(\"State mismatch - possible CSRF attack\"));\n return;\n }\n\n // Validate code exists\n if (!code) {\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(ERROR_HTML(\"Missing code\", \"No authorization code received\"));\n\n server.close();\n reject(new Error(\"No authorization code received\"));\n return;\n }\n\n // Success!\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(SUCCESS_HTML);\n\n server.close();\n resolve({ code, state });\n });\n\n // Handle server errors\n server.on(\"error\", (err) => {\n reject(new Error(`Failed to start callback server: ${err.message}`));\n });\n\n // Set timeout\n const timeout = setTimeout(() => {\n server.close();\n reject(new Error(\"Authentication timed out\"));\n }, timeoutMs);\n\n // Clear timeout when server closes\n server.on(\"close\", () => {\n clearTimeout(timeout);\n });\n\n // Start listening\n server.listen(port, \"127.0.0.1\", () => {\n // Server is ready\n });\n });\n}\n","import { getCredentials, ensureValidToken } from \"./auth/index.js\";\nimport type {OAuthConfig} from \"./auth/index.js\";\n\nexport interface ConvexConfig {\n convexUrl: string;\n oauthConfig: OAuthConfig;\n}\n\nexport interface ConvexResponse<T> {\n success: boolean;\n data?: T;\n error?: string;\n}\n\n/**\n * Create a Convex HTTP client for calling Convex functions via the CLI gateway\n */\nexport function createConvexClient(config: ConvexConfig) {\n const { convexUrl } = config;\n\n // The CLI gateway is on the .convex.site endpoint\n const gatewayUrl = convexUrl.replace(\".convex.cloud\", \".convex.site\");\n\n /**\n * Call a Convex query function via the CLI gateway\n */\n async function query<T>(\n functionPath: string,\n args: Record<string, unknown> = {}\n ): Promise<ConvexResponse<T>> {\n return callGateway<T>(functionPath, args);\n }\n\n /**\n * Call a Convex mutation function via the CLI gateway\n */\n async function mutation<T>(\n functionPath: string,\n args: Record<string, unknown> = {}\n ): Promise<ConvexResponse<T>> {\n return callGateway<T>(functionPath, args);\n }\n\n /**\n * Call a Convex action function via the CLI gateway\n */\n async function action<T>(\n functionPath: string,\n args: Record<string, unknown> = {}\n ): Promise<ConvexResponse<T>> {\n return callGateway<T>(functionPath, args);\n }\n\n /**\n * Call the CLI gateway with OAuth authentication\n */\n async function callGateway<T>(\n functionPath: string,\n args: Record<string, unknown>\n ): Promise<ConvexResponse<T>> {\n // Get valid access token\n const accessToken = await ensureValidToken(config.oauthConfig);\n if (!accessToken) {\n return {\n success: false,\n error: \"Not authenticated. Run 'program auth login' first.\",\n };\n }\n\n // Build the gateway URL\n const url = new URL(\"/cli\", gatewayUrl);\n\n try {\n const response = await fetch(url.toString(), {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${accessToken}`,\n },\n body: JSON.stringify({\n fn: functionPath,\n params: args,\n }),\n });\n\n const result = (await response.json()) as {\n success: boolean;\n data?: T;\n error?: string;\n };\n\n if (!response.ok || !result.success) {\n return {\n success: false,\n error: result.error ?? `Gateway error: ${response.status}`,\n };\n }\n\n return { success: true, data: result.data };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n }\n\n /**\n * Get the current credentials (for checking auth status)\n */\n function getAuth() {\n return getCredentials();\n }\n\n return {\n query,\n mutation,\n action,\n getAuth,\n };\n}\n\nexport type ConvexClient = ReturnType<typeof createConvexClient>;\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { createConvexClient } from \"../../lib/convex.js\";\nimport { convexConfig } from \"../../lib/config.js\";\nimport { formatKeyValue, outputError, outputSuccess } from \"../../lib/output.js\";\nimport type {OutputOptions} from \"../../lib/output.js\";\n\nexport type GetOptions = OutputOptions;\n\ninterface ProjectWithComposition {\n _id: string;\n title: string;\n description?: string;\n createdAt: number;\n updatedAt: number;\n latestVersion: {\n _id: string;\n version: number;\n compositionId: string;\n createdAt: number;\n } | null;\n composition: {\n _id: string;\n title: string;\n description?: string;\n duration: number;\n fps: number;\n width: number;\n height: number;\n sceneCount: number;\n scenes: unknown[];\n } | null;\n}\n\nexport async function getCommand(projectId: string, options: GetOptions): Promise<void> {\n const spinner = options.json ? null : ora(\"Fetching project...\").start();\n\n const client = createConvexClient(convexConfig);\n\n const result = await client.query<ProjectWithComposition>(\"projects.byId\", {\n id: projectId,\n });\n\n spinner?.stop();\n\n if (!result.success || !result.data) {\n outputError(result.error ?? \"Failed to get project\", options);\n process.exit(1);\n }\n\n const project = result.data;\n\n if (options.json) {\n outputSuccess(project, options);\n } else {\n console.log(chalk.bold(project.title || \"Untitled Project\"));\n if (project.description) {\n console.log(chalk.dim(project.description));\n }\n console.log();\n\n console.log(\n formatKeyValue([\n { key: \"ID\", value: project._id },\n { key: \"Created\", value: new Date(project.createdAt).toLocaleString() },\n { key: \"Updated\", value: new Date(project.updatedAt).toLocaleString() },\n ])\n );\n\n if (project.latestVersion) {\n console.log(chalk.bold(\"\\nVersion\"));\n console.log(\n formatKeyValue([\n { key: \"Version\", value: String(project.latestVersion.version) },\n { key: \"Composition ID\", value: project.latestVersion.compositionId },\n ])\n );\n } else {\n console.log(chalk.dim(\"\\nNo versions yet\"));\n }\n\n if (project.composition) {\n console.log(chalk.bold(\"\\nComposition\"));\n console.log(\n formatKeyValue([\n { key: \"Title\", value: project.composition.title },\n { key: \"Resolution\", value: `${project.composition.width}x${project.composition.height}` },\n { key: \"FPS\", value: String(project.composition.fps) },\n { key: \"Duration\", value: `${(project.composition.duration / 1000).toFixed(1)}s` },\n { key: \"Scenes\", value: String(project.composition.sceneCount) },\n ])\n );\n\n if (project.composition.sceneCount > 0 && Array.isArray(project.composition.scenes)) {\n console.log(chalk.bold(\"\\nScenes\"));\n for (const scene of project.composition.scenes as { id: string; type: string; duration: number }[]) {\n console.log(chalk.dim(` - ${scene.type} (${(scene.duration / 1000).toFixed(1)}s)`));\n }\n }\n } else {\n console.log(chalk.dim(\"\\nNo composition yet\"));\n }\n }\n}\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { createConvexClient } from \"../../lib/convex.js\";\nimport { convexConfig } from \"../../lib/config.js\";\nimport { formatTable, outputError, outputSuccess } from \"../../lib/output.js\";\nimport type {OutputOptions} from \"../../lib/output.js\";\n\nexport interface ListOptions extends OutputOptions {\n limit?: number;\n}\n\ninterface Project {\n _id: string;\n title: string;\n description?: string;\n createdAt: number;\n updatedAt: number;\n}\n\ninterface ListResult {\n items: Project[];\n nextCursor: string | null;\n}\n\nexport async function listCommand(options: ListOptions): Promise<void> {\n const spinner = options.json ? null : ora(\"Fetching projects...\").start();\n\n const client = createConvexClient(convexConfig);\n\n const result = await client.query<ListResult>(\"projects.list\", {\n limit: options.limit,\n });\n\n spinner?.stop();\n\n if (!result.success || !result.data) {\n outputError(result.error ?? \"Failed to list projects\", options);\n process.exit(1);\n }\n\n const projects = result.data.items;\n\n if (options.json) {\n outputSuccess(projects, options);\n } else {\n if (projects.length === 0) {\n console.log(chalk.dim(\"No projects found. Create one with 'program project create'\"));\n return;\n }\n\n console.log(`Found ${chalk.cyan(projects.length)} project${projects.length === 1 ? \"\" : \"s\"}:\\n`);\n\n const rows = projects.map((p) => [\n p._id,\n p.title || chalk.dim(\"Untitled\"),\n formatDate(p.createdAt),\n ]);\n\n console.log(formatTable([\"ID\", \"Title\", \"Created\"], rows));\n }\n}\n\nfunction formatDate(timestamp: number): string {\n const date = new Date(timestamp);\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));\n\n if (diffDays === 0) {\n return \"today\";\n } else if (diffDays === 1) {\n return \"yesterday\";\n } else if (diffDays < 7) {\n return `${diffDays} days ago`;\n } else {\n return date.toLocaleDateString();\n }\n}\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { createConvexClient } from \"../../lib/convex.js\";\nimport { convexConfig } from \"../../lib/config.js\";\nimport { formatTable, outputError, outputSuccess } from \"../../lib/output.js\";\nimport type {OutputOptions} from \"../../lib/output.js\";\n\nexport interface ListOptions extends OutputOptions {\n limit?: number;\n publicOnly?: boolean;\n}\n\ninterface Template {\n _id: string;\n name: string;\n description?: string;\n public: boolean;\n createdAt: number;\n updatedAt: number;\n}\n\nexport async function listCommand(options: ListOptions): Promise<void> {\n const spinner = options.json ? null : ora(\"Fetching workflow templates...\").start();\n\n const client = createConvexClient(convexConfig);\n\n const result = await client.query<Template[]>(\"workflows.listTemplates\", {\n category: options.publicOnly ? \"public\" : undefined,\n });\n\n spinner?.stop();\n\n if (!result.success || !result.data) {\n outputError(result.error ?? \"Failed to list templates\", options);\n process.exit(1);\n }\n\n const templates = result.data;\n\n if (options.json) {\n outputSuccess(\n templates.map((t) => ({\n id: t._id,\n name: t.name,\n description: t.description,\n public: t.public,\n })),\n options\n );\n } else {\n if (templates.length === 0) {\n console.log(chalk.dim(\"No workflow templates found.\"));\n return;\n }\n\n console.log(`Found ${chalk.cyan(templates.length)} template${templates.length === 1 ? \"\" : \"s\"}:\\n`);\n\n const rows = templates.map((t) => [\n t._id,\n t.name,\n t.description?.substring(0, 40) ?? chalk.dim(\"No description\"),\n t.public ? chalk.green(\"public\") : chalk.dim(\"private\"),\n ]);\n\n console.log(formatTable([\"ID\", \"Name\", \"Description\", \"Visibility\"], rows));\n }\n}\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { createConvexClient } from \"../../lib/convex.js\";\nimport { convexConfig } from \"../../lib/config.js\";\nimport { formatSuccess, outputError, outputSuccess } from \"../../lib/output.js\";\nimport type {OutputOptions} from \"../../lib/output.js\";\n\nexport interface RunOptions extends OutputOptions {\n project?: string;\n input?: string;\n}\n\nexport async function runCommand(templateId: string, options: RunOptions): Promise<void> {\n const spinner = options.json ? null : ora(\"Starting workflow execution...\").start();\n\n // Parse input JSON if provided\n let input: Record<string, unknown> | undefined;\n if (options.input) {\n try {\n input = JSON.parse(options.input) as Record<string, unknown>;\n } catch {\n spinner?.stop();\n outputError(\"Invalid JSON in --input parameter\", options);\n process.exit(1);\n }\n }\n\n const client = createConvexClient(convexConfig);\n\n const result = await client.mutation<string>(\"workflows.run\", {\n templateId,\n projectId: options.project,\n input,\n });\n\n spinner?.stop();\n\n if (!result.success || !result.data) {\n outputError(result.error ?? \"Failed to start workflow\", options);\n process.exit(1);\n }\n\n const executionId = result.data;\n\n if (options.json) {\n outputSuccess({ executionId }, options);\n } else {\n console.log(formatSuccess(`Workflow started`));\n console.log(chalk.dim(` Execution ID: ${executionId}`));\n console.log(chalk.dim(` Check status with: program workflow status ${executionId}`));\n }\n}\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { createConvexClient } from \"../../lib/convex.js\";\nimport { convexConfig } from \"../../lib/config.js\";\nimport { formatKeyValue, formatSuccess, formatWarning, outputError, outputSuccess } from \"../../lib/output.js\";\nimport type {OutputOptions} from \"../../lib/output.js\";\n\nexport interface StatusOptions extends OutputOptions {\n watch?: boolean;\n interval?: number;\n}\n\ninterface ExecutionStatus {\n status: \"pending\" | \"running\" | \"success\" | \"error\" | \"cancelled\";\n output?: unknown;\n error?: string;\n completedAt?: number;\n nodeStatuses?: { nodeId: string; status: string }[];\n}\n\nexport async function statusCommand(executionId: string, options: StatusOptions): Promise<void> {\n const client = createConvexClient(convexConfig);\n const pollInterval = options.interval ?? 2000;\n\n if (options.watch) {\n await watchStatus(client, executionId, pollInterval, options);\n } else {\n await getStatusOnce(client, executionId, options);\n }\n}\n\nasync function getStatusOnce(\n client: ReturnType<typeof createConvexClient>,\n executionId: string,\n options: StatusOptions\n): Promise<void> {\n const spinner = options.json ? null : ora(\"Fetching execution status...\").start();\n\n const result = await client.query<ExecutionStatus>(\"workflows.status\", {\n executionId,\n });\n\n spinner?.stop();\n\n if (!result.success) {\n outputError(result.error ?? \"Failed to get status\", options);\n process.exit(1);\n }\n\n const status = result.data;\n\n if (!status) {\n outputError(\"Execution not found\", options);\n process.exit(1);\n }\n\n if (options.json) {\n outputSuccess(status, options);\n } else {\n printStatus(status);\n }\n}\n\nasync function watchStatus(\n client: ReturnType<typeof createConvexClient>,\n executionId: string,\n pollInterval: number,\n options: StatusOptions\n): Promise<void> {\n let lastStatus: string | null = null;\n\n const poll = async (): Promise<boolean> => {\n const result = await client.query<ExecutionStatus>(\"workflows.status\", {\n executionId,\n });\n\n if (!result.success) {\n outputError(result.error ?? \"Failed to get status\", options);\n return true; // Stop polling\n }\n\n const status = result.data;\n\n if (!status) {\n outputError(\"Execution not found\", options);\n return true;\n }\n\n // For JSON mode, output each status change\n if (options.json) {\n if (status.status !== lastStatus) {\n console.log(JSON.stringify(status));\n lastStatus = status.status;\n }\n } else {\n // For human mode, clear and reprint\n if (status.status !== lastStatus) {\n console.clear();\n console.log(chalk.dim(`Watching execution ${executionId}...\\n`));\n printStatus(status);\n lastStatus = status.status;\n }\n }\n\n // Stop polling if complete\n if ([\"success\", \"error\", \"cancelled\"].includes(status.status)) {\n return true;\n }\n\n return false;\n };\n\n // Initial poll\n let done = await poll();\n\n // Continue polling until complete\n while (!done) {\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\n done = await poll();\n }\n}\n\nfunction printStatus(status: ExecutionStatus): void {\n const statusColor = getStatusColor(status.status);\n\n console.log(\n formatKeyValue([\n { key: \"Status\", value: statusColor(status.status) },\n ...(status.completedAt\n ? [{ key: \"Completed\", value: new Date(status.completedAt).toLocaleString() }]\n : []),\n ])\n );\n\n if (status.nodeStatuses && status.nodeStatuses.length > 0) {\n console.log(chalk.dim(\"\\nStep progress:\"));\n for (const node of status.nodeStatuses) {\n const nodeColor = getStatusColor(node.status);\n console.log(` ${nodeColor(getStatusIcon(node.status))} ${node.nodeId}`);\n }\n }\n\n if (status.error) {\n console.log(formatWarning(`\\nError: ${status.error}`));\n }\n\n if (status.status === \"success\" && status.output) {\n console.log(formatSuccess(\"\\nOutput:\"));\n console.log(JSON.stringify(status.output, null, 2));\n }\n}\n\nfunction getStatusColor(status: string): (text: string) => string {\n switch (status) {\n case \"success\":\n return chalk.green;\n case \"error\":\n return chalk.red;\n case \"cancelled\":\n return chalk.yellow;\n case \"running\":\n return chalk.blue;\n case \"pending\":\n default:\n return chalk.dim;\n }\n}\n\nfunction getStatusIcon(status: string): string {\n switch (status) {\n case \"success\":\n return \"✓\";\n case \"error\":\n return \"✕\";\n case \"running\":\n return \"●\";\n case \"pending\":\n default:\n return \"○\";\n }\n}\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { ensureValidToken } from \"../../lib/auth/index.js\";\nimport { oauthConfig, BASE_URL } from \"../../lib/config.js\";\nimport { outputError, outputSuccess } from \"../../lib/output.js\";\nimport type {OutputOptions} from \"../../lib/output.js\";\nimport { detectAgentSource } from \"../../lib/agent-detect.js\";\n\nexport interface ExecuteOptions extends OutputOptions {\n project: string;\n params?: string;\n}\n\nexport async function executeCommand(\n toolName: string,\n options: ExecuteOptions\n): Promise<void> {\n const spinner = options.json ? null : ora(`Executing ${toolName}...`).start();\n\n // Get valid access token\n const accessToken = await ensureValidToken(oauthConfig);\n if (!accessToken) {\n spinner?.stop();\n outputError(\"Not authenticated. Run 'program auth login' first.\", options);\n process.exit(1);\n }\n\n // Parse params if provided\n let params: Record<string, unknown> = {};\n if (options.params) {\n try {\n params = JSON.parse(options.params) as Record<string, unknown>;\n } catch {\n spinner?.stop();\n outputError(\"Invalid JSON in --params\", options);\n process.exit(1);\n }\n }\n\n // Detect agent at runtime (not login time) for correct multi-agent support\n const source = detectAgentSource();\n\n try {\n const response = await fetch(`${BASE_URL}/api/cli/tool`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${accessToken}`,\n },\n body: JSON.stringify({\n projectId: options.project,\n tool: toolName,\n params,\n source,\n }),\n });\n\n const result = (await response.json()) as {\n success: boolean;\n data?: unknown;\n error?: string;\n compositionId?: string;\n };\n\n spinner?.stop();\n\n if (!response.ok || !result.success) {\n outputError(result.error ?? `Tool execution failed: ${response.status}`, options);\n process.exit(1);\n }\n\n if (options.json) {\n outputSuccess(result.data, options);\n } else {\n console.log(chalk.green(`✓ ${toolName} executed successfully`));\n if (result.compositionId) {\n console.log(chalk.dim(` Composition: ${result.compositionId}`));\n }\n console.log();\n console.log(JSON.stringify(result.data, null, 2));\n }\n } catch (error) {\n spinner?.stop();\n outputError(error instanceof Error ? error.message : \"Request failed\", options);\n process.exit(1);\n }\n}\n","/**\n * Runtime agent detection\n *\n * Detects which agent/IDE is running the CLI based on environment variables.\n * This is checked per-request, not at login time, so multiple agents can\n * use the same credentials simultaneously with correct attribution.\n */\n\n/**\n * Detect which agent is currently running this CLI command.\n * Returns undefined for unknown agents (will show as \"Agent via CLI\").\n */\nexport function detectAgentSource(): string | undefined {\n // Claude Code sets CLAUDECODE=1 (external env var from IDE, not project-owned)\n // eslint-disable-next-line turbo/no-undeclared-env-vars\n if (process.env.CLAUDECODE === \"1\") {\n return \"claude-code\";\n }\n\n // Future: Add detection for other agents when we know their env vars\n // OpenCode, Codex, Cursor, etc.\n\n // Unknown agent - return undefined to use default display\n return undefined;\n}\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { BASE_URL } from \"../../lib/config.js\";\nimport { outputError, outputSuccess } from \"../../lib/output.js\";\nimport type {OutputOptions} from \"../../lib/output.js\";\n\nexport type ListOptions = OutputOptions;\n\ninterface Tool {\n name: string;\n description: string;\n inputs: string[];\n}\n\nexport async function listCommand(options: ListOptions): Promise<void> {\n const spinner = options.json ? null : ora(\"Fetching available tools...\").start();\n\n try {\n const response = await fetch(`${BASE_URL}/api/cli/tool`, {\n method: \"GET\",\n });\n\n const result = (await response.json()) as {\n success: boolean;\n tools?: Tool[];\n error?: string;\n };\n\n spinner?.stop();\n\n if (!response.ok || !result.success) {\n outputError(result.error ?? \"Failed to list tools\", options);\n process.exit(1);\n }\n\n const tools = result.tools ?? [];\n\n if (options.json) {\n outputSuccess(tools, options);\n } else {\n console.log(chalk.bold(`Available Tools (${tools.length}):\\n`));\n\n for (const tool of tools) {\n console.log(chalk.cyan(` ${tool.name}`));\n console.log(chalk.dim(` ${tool.description}`));\n if (tool.inputs.length > 0) {\n console.log(chalk.dim(` Inputs: ${tool.inputs.join(\", \")}`));\n }\n console.log();\n }\n\n console.log(chalk.dim(\"Usage: program tool exec <toolName> --project <id> --params '{...}'\"));\n }\n } catch (error) {\n spinner?.stop();\n outputError(error instanceof Error ? error.message : \"Request failed\", options);\n process.exit(1);\n }\n}\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { ensureValidToken } from \"../../lib/auth/index.js\";\nimport { oauthConfig, BASE_URL } from \"../../lib/config.js\";\nimport { outputError, outputSuccess } from \"../../lib/output.js\";\nimport type {OutputOptions} from \"../../lib/output.js\";\nimport { detectAgentSource } from \"../../lib/agent-detect.js\";\n\nexport interface SendMessageOptions extends OutputOptions {\n project: string;\n role?: \"user\" | \"assistant\";\n}\n\nexport async function sendCommand(\n text: string,\n options: SendMessageOptions\n): Promise<void> {\n const spinner = options.json ? null : ora(\"Sending message...\").start();\n\n // Get valid access token\n const accessToken = await ensureValidToken(oauthConfig);\n if (!accessToken) {\n spinner?.stop();\n outputError(\"Not authenticated. Run 'program auth login' first.\", options);\n process.exit(1);\n }\n\n const role = options.role ?? \"assistant\";\n\n // Detect agent at runtime (not login time) for correct multi-agent support\n const source = detectAgentSource();\n\n try {\n const response = await fetch(`${BASE_URL}/api/cli/message`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${accessToken}`,\n },\n body: JSON.stringify({\n projectId: options.project,\n role,\n text,\n source,\n }),\n });\n\n const result = (await response.json()) as {\n success: boolean;\n messageId?: string;\n error?: string;\n };\n\n spinner?.stop();\n\n if (!response.ok || !result.success) {\n outputError(result.error ?? `Failed to send message: ${response.status}`, options);\n process.exit(1);\n }\n\n if (options.json) {\n outputSuccess({ messageId: result.messageId, role, text }, options);\n } else {\n console.log(chalk.green(`✓ Message sent as ${role}`));\n if (result.messageId) {\n console.log(chalk.dim(` Message ID: ${result.messageId}`));\n }\n }\n } catch (error) {\n spinner?.stop();\n outputError(error instanceof Error ? error.message : \"Request failed\", options);\n process.exit(1);\n }\n}\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { ensureValidToken } from \"../../lib/auth/index.js\";\nimport { oauthConfig, BASE_URL } from \"../../lib/config.js\";\nimport { outputError, outputSuccess } from \"../../lib/output.js\";\nimport type { OutputOptions } from \"../../lib/output.js\";\n\nexport interface ListMessageOptions extends OutputOptions {\n project: string;\n limit?: number;\n}\n\ninterface MessagePart {\n type: string;\n text?: string;\n toolName?: string;\n toolCallId?: string;\n state?: string;\n}\n\ninterface Message {\n id: string;\n role: \"user\" | \"assistant\";\n parts: MessagePart[];\n source?: string;\n createdAt: number;\n}\n\nexport async function listCommand(options: ListMessageOptions): Promise<void> {\n const spinner = options.json ? null : ora(\"Fetching messages...\").start();\n\n // Get valid access token\n const accessToken = await ensureValidToken(oauthConfig);\n if (!accessToken) {\n spinner?.stop();\n outputError(\n \"Not authenticated. Run 'program auth login' first.\",\n options\n );\n process.exit(1);\n }\n\n try {\n const url = new URL(`${BASE_URL}/api/cli/message`);\n url.searchParams.set(\"projectId\", options.project);\n if (options.limit) {\n url.searchParams.set(\"limit\", options.limit.toString());\n }\n\n const response = await fetch(url.toString(), {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n });\n\n const result = (await response.json()) as {\n success: boolean;\n chatId?: string;\n messages?: Message[];\n error?: string;\n };\n\n spinner?.stop();\n\n if (!response.ok || !result.success) {\n outputError(\n result.error ?? `Failed to fetch messages: ${response.status}`,\n options\n );\n process.exit(1);\n }\n\n if (options.json) {\n outputSuccess(result, options);\n } else {\n const messages = result.messages ?? [];\n if (messages.length === 0) {\n console.log(chalk.dim(\"No messages in this chat yet.\"));\n return;\n }\n\n console.log(chalk.bold(`Chat Messages (${messages.length}):\\n`));\n\n for (const msg of messages) {\n // Format the role with source if available\n let roleLabel = msg.role === \"user\" ? \"You\" : \"Assistant\";\n if (msg.source) {\n if (msg.source === \"cli:claude-code\") {\n roleLabel = \"Claude via CLI\";\n } else if (msg.source.startsWith(\"cli:\")) {\n roleLabel = `${roleLabel} via CLI`;\n }\n }\n\n // Get text content from parts\n const textContent = msg.parts\n .filter((p): p is MessagePart & { text: string } => p.type === \"text\" && !!p.text)\n .map((p) => p.text)\n .join(\"\\n\");\n\n // Get tool calls\n const toolCalls = msg.parts.filter(\n (p) => p.type === \"tool-invocation\" || p.type === \"tool-call\"\n );\n\n // Format timestamp\n const time = new Date(msg.createdAt).toLocaleTimeString();\n\n // Print message\n const roleColor = msg.role === \"user\" ? chalk.blue : chalk.green;\n console.log(roleColor(`[${time}] ${roleLabel}:`));\n\n if (textContent) {\n // Indent and truncate long messages\n const truncated =\n textContent.length > 500\n ? textContent.substring(0, 500) + \"...\"\n : textContent;\n console.log(\n truncated\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\")\n );\n }\n\n if (toolCalls.length > 0) {\n console.log(\n chalk.dim(` [${toolCalls.length} tool call(s)]`)\n );\n }\n\n console.log();\n }\n }\n } catch (error) {\n spinner?.stop();\n outputError(\n error instanceof Error ? error.message : \"Request failed\",\n options\n );\n process.exit(1);\n }\n}\n","import { outputSuccess } from \"../lib/output.js\";\nimport type {OutputOptions} from \"../lib/output.js\";\n\nexport interface DocsOptions extends OutputOptions {\n schema?: boolean;\n}\n\n// Command schema for agents\nconst COMMAND_SCHEMA = {\n name: \"program\",\n version: \"0.1.0\",\n description: \"CLI for interacting with the Program video creation platform\",\n commands: {\n auth: {\n description: \"Authentication commands\",\n subcommands: {\n login: {\n description: \"Authenticate with the Program platform\",\n options: {\n \"--json\": \"Output as JSON\",\n },\n example: \"program auth login\",\n },\n logout: {\n description: \"Log out from the Program platform\",\n options: {\n \"--json\": \"Output as JSON\",\n },\n example: \"program auth logout\",\n },\n status: {\n description: \"Check authentication status\",\n options: {\n \"--json\": \"Output as JSON\",\n },\n example: \"program auth status --json\",\n },\n },\n },\n project: {\n description: \"Project management commands\",\n subcommands: {\n create: {\n description: \"Create a new project\",\n options: {\n \"--title <title>\": \"Project title\",\n \"--description <desc>\": \"Project description\",\n \"--json\": \"Output as JSON\",\n },\n example: 'program project create --title \"My Video\" --json',\n },\n list: {\n description: \"List projects\",\n options: {\n \"--limit <n>\": \"Maximum number of projects to return\",\n \"--json\": \"Output as JSON\",\n },\n example: \"program project list --json\",\n },\n },\n },\n workflow: {\n description: \"Workflow template commands\",\n subcommands: {\n list: {\n description: \"List available workflow templates\",\n options: {\n \"--limit <n>\": \"Maximum number of templates to return\",\n \"--public-only\": \"Only show public templates\",\n \"--json\": \"Output as JSON\",\n },\n example: \"program workflow list --json\",\n },\n run: {\n description: \"Execute a workflow template\",\n args: {\n templateId: \"ID of the template to run\",\n },\n options: {\n \"--project <id>\": \"Project ID to associate with execution\",\n \"--input <json>\": \"JSON input for the workflow\",\n \"--json\": \"Output as JSON\",\n },\n example: \"program workflow run tmpl_abc --project proj_123 --input '{\\\"files\\\":[\\\"src/main.ts\\\"]}' --json\",\n },\n status: {\n description: \"Check workflow execution status\",\n args: {\n executionId: \"ID of the execution to check\",\n },\n options: {\n \"--watch\": \"Continuously poll for status updates\",\n \"--interval <ms>\": \"Poll interval in milliseconds (default: 2000)\",\n \"--json\": \"Output as JSON\",\n },\n example: \"program workflow status exec_789 --watch --json\",\n },\n },\n },\n docs: {\n description: \"Display CLI documentation\",\n options: {\n \"--schema\": \"Output full command schema as JSON\",\n },\n example: \"program docs --schema\",\n },\n },\n globalOptions: {\n \"--help\": \"Display help information\",\n \"--version\": \"Display version number\",\n },\n notes: [\n \"Always use --json flag for parseable output when integrating with agents\",\n \"Workflow inputs should be valid JSON strings\",\n \"Run 'program auth login' first to authenticate\",\n ],\n};\n\nexport function docsCommand(options: DocsOptions): void {\n if (options.schema ?? options.json) {\n outputSuccess(COMMAND_SCHEMA, { json: true });\n } else {\n printHumanDocs();\n }\n}\n\nfunction printHumanDocs(): void {\n console.log(`\nProgram CLI v${COMMAND_SCHEMA.version}\n${COMMAND_SCHEMA.description}\n\nCOMMANDS:\n\n auth login Authenticate with the Program platform\n auth logout Log out from the Program platform\n auth status Check authentication status\n\n project create Create a new project\n project list List projects\n\n workflow list List available workflow templates\n workflow run <id> Execute a workflow template\n workflow status <id> Check workflow execution status\n\n docs Display this documentation\n docs --schema Output full command schema as JSON\n\nGLOBAL OPTIONS:\n\n --json Output as JSON (recommended for agents)\n --help Display help information\n --version Display version number\n\nEXAMPLES:\n\n # Authenticate\n program auth login\n\n # Create a project\n program project create --title \"My Video\" --json\n\n # Run a workflow\n program workflow run tmpl_abc --project proj_123 --json\n\n # Watch execution progress\n program workflow status exec_789 --watch --json\n\nFor agent integration, always use the --json flag.\n`);\n}\n"],"mappings":"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","names":["chalk","message","chalk","message","chalk","chalk","minutes","chalk","ora","URL","CLIENT_ID","CLIENT_ID","ora","chalk","chalk","ora","ora","project","chalk","chalk","ora","ora","chalk","chalk","ora","listCommand","ora","chalk","chalk","ora","ora","chalk","chalk","ora","statusCommand","ora","chalk","chalk","ora","ora","chalk","chalk","ora","listCommand","ora","chalk","tool","chalk","ora","ora","chalk","chalk","ora","listCommand","ora","chalk","listCommand","statusCommand"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/auth/login.ts","../src/lib/auth/credentials.ts","../src/lib/auth/device.ts","../src/lib/config.ts","../src/lib/output.ts","../src/commands/auth/logout.ts","../src/commands/auth/status.ts","../src/commands/project/create.ts","../src/lib/auth/oauth.ts","../src/lib/auth/pkce.ts","../src/lib/auth/callback-server.ts","../src/lib/convex.ts","../src/commands/project/get.ts","../src/commands/project/list.ts","../src/commands/workflow/list.ts","../src/commands/workflow/run.ts","../src/commands/workflow/status.ts","../src/commands/tool/execute.ts","../src/lib/agent-detect.ts","../src/commands/tool/list.ts","../src/commands/message/send.ts","../src/commands/message/list.ts","../src/commands/docs.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { loginCommand } from \"./commands/auth/login.js\";\nimport type { LoginOptions } from \"./commands/auth/login.js\";\nimport { logoutCommand } from \"./commands/auth/logout.js\";\nimport type { LogoutOptions } from \"./commands/auth/logout.js\";\nimport { statusCommand as authStatusCommand } from \"./commands/auth/status.js\";\nimport type { StatusOptions as AuthStatusOptions } from \"./commands/auth/status.js\";\nimport { createCommand as projectCreateCommand } from \"./commands/project/create.js\";\nimport type { CreateOptions } from \"./commands/project/create.js\";\nimport { getCommand as projectGetCommand } from \"./commands/project/get.js\";\nimport type { GetOptions } from \"./commands/project/get.js\";\nimport { listCommand as projectListCommand } from \"./commands/project/list.js\";\nimport type { ListOptions as ProjectListOptions } from \"./commands/project/list.js\";\nimport { listCommand as workflowListCommand } from \"./commands/workflow/list.js\";\nimport type { ListOptions as WorkflowListOptions } from \"./commands/workflow/list.js\";\nimport { runCommand as workflowRunCommand } from \"./commands/workflow/run.js\";\nimport type { RunOptions } from \"./commands/workflow/run.js\";\nimport { statusCommand as workflowStatusCommand } from \"./commands/workflow/status.js\";\nimport type { StatusOptions as WorkflowStatusOptions } from \"./commands/workflow/status.js\";\nimport { executeCommand as toolExecuteCommand } from \"./commands/tool/execute.js\";\nimport type { ExecuteOptions } from \"./commands/tool/execute.js\";\nimport { listCommand as toolListCommand } from \"./commands/tool/list.js\";\nimport type { ListOptions as ToolListOptions } from \"./commands/tool/list.js\";\nimport { sendCommand as messageSendCommand } from \"./commands/message/send.js\";\nimport type { SendMessageOptions } from \"./commands/message/send.js\";\nimport { listCommand as messageListCommand } from \"./commands/message/list.js\";\nimport type { ListMessageOptions } from \"./commands/message/list.js\";\nimport { docsCommand } from \"./commands/docs.js\";\nimport type { DocsOptions } from \"./commands/docs.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"program\")\n .description(\"CLI for the Program video creation platform\")\n .version(\"0.1.0\");\n\n// Auth commands\nconst auth = program.command(\"auth\").description(\"Authentication commands\");\n\nauth\n .command(\"login\")\n .description(\"Authenticate with the Program platform\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (options: LoginOptions) => {\n await loginCommand(options);\n });\n\nauth\n .command(\"logout\")\n .description(\"Log out from the Program platform\")\n .option(\"--json\", \"Output as JSON\")\n .action((options: LogoutOptions) => {\n logoutCommand(options);\n });\n\nauth\n .command(\"status\")\n .description(\"Check authentication status\")\n .option(\"--json\", \"Output as JSON\")\n .action((options: AuthStatusOptions) => {\n authStatusCommand(options);\n });\n\n// Project commands\nconst project = program.command(\"project\").description(\"Project management commands\");\n\nproject\n .command(\"create\")\n .description(\"Create a new project\")\n .option(\"--title <title>\", \"Project title\")\n .option(\"--description <description>\", \"Project description\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (options: CreateOptions) => {\n await projectCreateCommand(options);\n });\n\nproject\n .command(\"list\")\n .description(\"List projects\")\n .option(\"--limit <limit>\", \"Maximum number of projects to return\", parseInt)\n .option(\"--json\", \"Output as JSON\")\n .action(async (options: ProjectListOptions) => {\n await projectListCommand(options);\n });\n\nproject\n .command(\"get <id>\")\n .description(\"Get project details including composition\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (id: string, options: GetOptions) => {\n await projectGetCommand(id, options);\n });\n\n// Workflow commands\nconst workflow = program.command(\"workflow\").description(\"Workflow template commands\");\n\nworkflow\n .command(\"list\")\n .description(\"List available workflow templates\")\n .option(\"--limit <limit>\", \"Maximum number of templates to return\", parseInt)\n .option(\"--public-only\", \"Only show public templates\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (options: WorkflowListOptions) => {\n await workflowListCommand(options);\n });\n\nworkflow\n .command(\"run <templateId>\")\n .description(\"Execute a workflow template\")\n .option(\"--project <projectId>\", \"Project ID to associate with execution\")\n .option(\"--input <json>\", \"JSON input for the workflow\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (templateId: string, options: RunOptions) => {\n await workflowRunCommand(templateId, options);\n });\n\nworkflow\n .command(\"status <executionId>\")\n .description(\"Check workflow execution status\")\n .option(\"--watch\", \"Continuously poll for status updates\")\n .option(\"--interval <ms>\", \"Poll interval in milliseconds\", parseInt)\n .option(\"--json\", \"Output as JSON\")\n .action(async (executionId: string, options: WorkflowStatusOptions) => {\n await workflowStatusCommand(executionId, options);\n });\n\n// Tool commands (direct agent tool access)\nconst tool = program.command(\"tool\").description(\"Execute agent tools directly\");\n\ntool\n .command(\"list\")\n .description(\"List available agent tools\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (options: ToolListOptions) => {\n await toolListCommand(options);\n });\n\ntool\n .command(\"exec <toolName>\")\n .description(\"Execute an agent tool\")\n .requiredOption(\"--project <projectId>\", \"Project ID to execute tool against\")\n .option(\"--params <json>\", \"JSON parameters for the tool\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (toolName: string, options: ExecuteOptions) => {\n await toolExecuteCommand(toolName, options);\n });\n\n// Message commands (send and list messages in project chat)\nconst message = program.command(\"message\").description(\"Manage messages in project chat\");\n\nmessage\n .command(\"list\")\n .description(\"List messages in the project chat\")\n .requiredOption(\"--project <projectId>\", \"Project ID to list messages from\")\n .option(\"--limit <limit>\", \"Maximum number of messages to return\", parseInt)\n .option(\"--json\", \"Output as JSON\")\n .action(async (options: ListMessageOptions) => {\n await messageListCommand(options);\n });\n\nmessage\n .command(\"send <text>\")\n .description(\n \"Log a text message to the project chat. NOTE: This only adds a message to the chat history - it does NOT trigger the AI agent. To perform actions, use 'tool exec' instead.\",\n )\n .requiredOption(\"--project <projectId>\", \"Project ID to send message to\")\n .option(\"--role <role>\", \"Message role: user or assistant (default: assistant)\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (text: string, options: SendMessageOptions) => {\n await messageSendCommand(text, options);\n });\n\n// Docs command\nprogram\n .command(\"docs\")\n .description(\"Display CLI documentation and command schema\")\n .option(\"--schema\", \"Output full command schema as JSON\")\n .option(\"--json\", \"Output as JSON\")\n .action((options: DocsOptions) => {\n docsCommand(options);\n });\n\n// Parse arguments\nprogram.parse();\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { startDeviceAuth } from \"../../lib/auth/device.js\";\nimport { oauthConfig } from \"../../lib/config.js\";\nimport { formatSuccess, outputError, outputSuccess } from \"../../lib/output.js\";\nimport type { OutputOptions } from \"../../lib/output.js\";\n\nexport type LoginOptions = OutputOptions;\n\n/**\n * Format user code with dash for readability (ABCD1234 -> ABCD-1234)\n */\nfunction formatUserCode(code: string): string {\n if (code.length === 8) {\n return `${code.slice(0, 4)}-${code.slice(4)}`;\n }\n return code;\n}\n\n/**\n * Device authorization flow - works everywhere including headless environments\n * User visits a URL on any device and enters the code shown in the terminal\n */\nexport async function loginCommand(options: LoginOptions): Promise<void> {\n const showSpinner = process.stdout.isTTY;\n const spinner = showSpinner ? ora(\"Requesting device code...\").start() : null;\n\n try {\n const deviceAuth = await startDeviceAuth(oauthConfig);\n spinner?.stop();\n spinner?.clear();\n\n // Display the code and URL for the user\n console.log();\n console.log(chalk.bold(\" Sign in to Program\"));\n console.log();\n console.log(` Visit: ${chalk.cyan(deviceAuth.verificationUrl)}`);\n console.log();\n console.log(` Enter code: ${chalk.bold.yellow(formatUserCode(deviceAuth.userCode))}`);\n console.log();\n\n // If there's a complete URL with the code embedded, also show that\n if (deviceAuth.verificationUrlComplete) {\n console.log(chalk.dim(` Or open: ${deviceAuth.verificationUrlComplete}`));\n console.log();\n }\n\n const waitingSpinner = showSpinner ? ora(\"Waiting for authorization...\").start() : null;\n\n // Poll until the user completes auth\n const credentials = await deviceAuth.pollForCompletion();\n\n waitingSpinner?.stop();\n waitingSpinner?.clear();\n\n if (options.json) {\n outputSuccess(\n {\n authenticated: true,\n email: credentials.email,\n userId: credentials.userId,\n organizationId: credentials.organizationId,\n },\n options\n );\n } else {\n console.log(formatSuccess(`Authenticated as ${chalk.cyan(credentials.email)}`));\n if (credentials.organizationId) {\n console.log(chalk.dim(` Organization: ${credentials.organizationId}`));\n }\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Authentication failed\";\n outputError(message, options);\n process.exit(1);\n }\n}\n","import Conf from \"conf\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\n\nexport interface Credentials {\n accessToken: string;\n refreshToken: string;\n expiresAt: number;\n userId: string;\n organizationId: string;\n email: string;\n}\n\n// Use ~/.program/ for credentials storage\nconst CREDENTIALS_DIR = path.join(os.homedir(), \".program\");\nconst CREDENTIALS_FILE = path.join(CREDENTIALS_DIR, \"credentials.json\");\n\n// Ensure directory exists with proper permissions\nfunction ensureCredentialsDir(): void {\n if (!fs.existsSync(CREDENTIALS_DIR)) {\n fs.mkdirSync(CREDENTIALS_DIR, { mode: 0o700, recursive: true });\n }\n}\n\n// Using conf for secure credential storage with automatic file permissions\nconst store = new Conf<{ credentials: Credentials | null }>({\n projectName: \"program-cli\",\n cwd: CREDENTIALS_DIR,\n configName: \"credentials\",\n fileExtension: \"json\",\n defaults: {\n credentials: null,\n },\n});\n\nexport function saveCredentials(credentials: Credentials): void {\n ensureCredentialsDir();\n store.set(\"credentials\", credentials);\n\n // Ensure file has restrictive permissions (owner read/write only)\n try {\n fs.chmodSync(CREDENTIALS_FILE, 0o600);\n } catch {\n // Ignore chmod errors on Windows\n }\n}\n\nexport function getCredentials(): Credentials | null {\n return store.get(\"credentials\");\n}\n\nexport function clearCredentials(): void {\n store.delete(\"credentials\");\n}\n\nexport function isAuthenticated(): boolean {\n const creds = getCredentials();\n if (!creds) return false;\n\n // Check if token is expired (with 5 minute buffer)\n const now = Date.now();\n const expiresAt = creds.expiresAt * 1000; // Convert to milliseconds\n const bufferMs = 5 * 60 * 1000; // 5 minutes\n\n return now < expiresAt - bufferMs;\n}\n\nexport function needsRefresh(): boolean {\n const creds = getCredentials();\n if (!creds) return false;\n\n // Needs refresh if within 5 minutes of expiry\n const now = Date.now();\n const expiresAt = creds.expiresAt * 1000;\n const bufferMs = 5 * 60 * 1000;\n\n return now >= expiresAt - bufferMs && now < expiresAt;\n}\n","import { saveCredentials, getCredentials } from \"./credentials.js\";\nimport type { Credentials } from \"./credentials.js\";\n\n// OAuth client ID - same as the main oauth.ts\nconst CLIENT_ID = \"program-cli\";\nconst SCOPES = [\"openid\", \"profile\", \"email\", \"offline_access\"];\n\nexport interface DeviceAuthConfig {\n baseUrl: string;\n}\n\ninterface DeviceCodeResponse {\n device_code: string;\n user_code: string;\n verification_uri: string;\n verification_uri_complete?: string;\n expires_in: number;\n interval: number;\n}\n\ninterface TokenResponse {\n access_token: string;\n refresh_token?: string;\n expires_in?: number;\n token_type?: string;\n scope?: string;\n}\n\ninterface TokenErrorResponse {\n error: string;\n error_description?: string;\n}\n\ninterface UserInfo {\n id: string;\n email: string;\n name: string;\n organizationId?: string;\n}\n\n/**\n * Request a device code from the server\n */\nexport async function requestDeviceCode(\n config: DeviceAuthConfig\n): Promise<DeviceCodeResponse> {\n const url = new URL(\"/api/auth/device/code\", config.baseUrl);\n\n const response = await fetch(url.toString(), {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n client_id: CLIENT_ID,\n scope: SCOPES.join(\" \"),\n }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to get device code: ${response.status} ${errorText}`);\n }\n\n return response.json() as Promise<DeviceCodeResponse>;\n}\n\n/**\n * Poll for the token after user authorizes\n * Returns the token response or an error code\n */\nexport async function pollForToken(\n config: DeviceAuthConfig,\n deviceCode: string\n): Promise<TokenResponse | TokenErrorResponse> {\n const url = new URL(\"/api/auth/device/token\", config.baseUrl);\n\n const response = await fetch(url.toString(), {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n device_code: deviceCode,\n client_id: CLIENT_ID,\n }),\n });\n\n // Device flow uses 400 status for pending/slow_down errors\n const data = (await response.json()) as TokenResponse | TokenErrorResponse;\n\n if (!response.ok) {\n // Check if it's an expected error (authorization_pending, slow_down)\n if (\"error\" in data) {\n return data;\n }\n throw new Error(`Token request failed: ${response.status}`);\n }\n\n return data as TokenResponse;\n}\n\n/**\n * Get user info from the BetterAuth session endpoint\n * Device authorization returns a BetterAuth token, not an OIDC token\n */\nasync function getUserInfo(\n config: DeviceAuthConfig,\n accessToken: string\n): Promise<UserInfo> {\n // Use the BetterAuth get-session endpoint with Bearer token\n const sessionUrl = new URL(\"/api/auth/get-session\", config.baseUrl);\n\n const response = await fetch(sessionUrl.toString(), {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n });\n\n if (!response.ok) {\n // Try the token/session endpoint if get-session doesn't work\n const tokenUrl = new URL(\"/api/auth/token\", config.baseUrl);\n const tokenResponse = await fetch(tokenUrl.toString(), {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n });\n\n if (!tokenResponse.ok) {\n throw new Error(`Failed to get user info: ${response.status}`);\n }\n\n const tokenData = (await tokenResponse.json()) as {\n user?: { id?: string; email?: string; name?: string };\n session?: { activeOrganizationId?: string };\n };\n\n if (!tokenData.user?.id || !tokenData.user.email) {\n throw new Error(\"Invalid token response: missing user info\");\n }\n\n return {\n id: tokenData.user.id,\n email: tokenData.user.email,\n name: tokenData.user.name ?? tokenData.user.email,\n organizationId: tokenData.session?.activeOrganizationId,\n };\n }\n\n const data = (await response.json()) as {\n user?: {\n id?: string;\n email?: string;\n name?: string;\n };\n session?: {\n activeOrganizationId?: string;\n };\n };\n\n if (!data.user?.id || !data.user.email) {\n throw new Error(\"Invalid session response: missing user info\");\n }\n\n return {\n id: data.user.id,\n email: data.user.email,\n name: data.user.name ?? data.user.email,\n organizationId: data.session?.activeOrganizationId,\n };\n}\n\n/**\n * Start the device authorization flow\n * Returns display info for the CLI to show the user\n */\nexport interface DeviceAuthDisplay {\n userCode: string;\n verificationUrl: string;\n verificationUrlComplete?: string;\n expiresIn: number;\n interval: number;\n pollForCompletion: () => Promise<Credentials>;\n}\n\nexport async function startDeviceAuth(\n config: DeviceAuthConfig\n): Promise<DeviceAuthDisplay> {\n const deviceCode = await requestDeviceCode(config);\n\n return {\n userCode: deviceCode.user_code,\n verificationUrl: deviceCode.verification_uri,\n verificationUrlComplete: deviceCode.verification_uri_complete,\n expiresIn: deviceCode.expires_in,\n interval: deviceCode.interval,\n pollForCompletion: async () => {\n return pollUntilComplete(config, deviceCode);\n },\n };\n}\n\n/**\n * Poll until the user completes authorization or the code expires\n */\nasync function pollUntilComplete(\n config: DeviceAuthConfig,\n deviceCode: DeviceCodeResponse\n): Promise<Credentials> {\n const startTime = Date.now();\n const expiresAt = startTime + deviceCode.expires_in * 1000;\n let interval = deviceCode.interval * 1000;\n\n while (Date.now() < expiresAt) {\n // Wait for the interval before polling\n await new Promise((resolve) => setTimeout(resolve, interval));\n\n const result = await pollForToken(config, deviceCode.device_code);\n\n // Check if it's an error response\n if (\"error\" in result) {\n switch (result.error) {\n case \"authorization_pending\":\n // User hasn't completed authorization yet, continue polling\n continue;\n\n case \"slow_down\":\n // Server asked us to slow down, increase interval\n interval += 5000;\n continue;\n\n case \"expired_token\":\n throw new Error(\"Device code expired. Please start a new login.\");\n\n case \"access_denied\":\n throw new Error(\"Access denied. You denied the authorization request.\");\n\n default:\n throw new Error(\n result.error_description ?? `Authorization failed: ${result.error}`\n );\n }\n }\n\n // Success! We got tokens\n const tokens = result;\n\n // Get user info\n const userInfo = await getUserInfo(config, tokens.access_token);\n\n // Calculate expiry timestamp (default to 1 hour if not provided)\n const expiresIn = tokens.expires_in ?? 3600;\n const expiresAtTimestamp = Math.floor(Date.now() / 1000) + expiresIn;\n\n // Save credentials (refresh token may not be present for device flow)\n const credentials: Credentials = {\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token ?? \"\",\n expiresAt: expiresAtTimestamp,\n userId: userInfo.id,\n organizationId: userInfo.organizationId ?? \"\",\n email: userInfo.email,\n };\n\n saveCredentials(credentials);\n\n return credentials;\n }\n\n throw new Error(\"Device code expired. Please start a new login.\");\n}\n\n/**\n * Check if we have valid credentials\n */\nexport function hasValidCredentials(): boolean {\n const creds = getCredentials();\n if (!creds) return false;\n\n // Check if token is expired (with 5 min buffer)\n const now = Date.now();\n const expiresAt = creds.expiresAt * 1000;\n const bufferMs = 5 * 60 * 1000;\n\n return now < expiresAt - bufferMs;\n}\n","import type { OAuthConfig } from \"./auth/index.js\";\nimport type { ConvexConfig } from \"./convex.js\";\n\n// Environment-based configuration\n// These can be overridden via environment variables\n\nfunction getEnvOrDefault(key: string, defaultValue: string): string {\n return process.env[key] ?? defaultValue;\n}\n\n// Base URL for the web app (OAuth provider)\n// Set via BASE_URL environment variable\nexport const BASE_URL = getEnvOrDefault(\n \"BASE_URL\",\n \"https://program.video\"\n);\n\n// Convex deployment URL (production)\nexport const CONVEX_URL = \"https://keen-eel-920.convex.cloud\";\n\nexport const oauthConfig: OAuthConfig = {\n baseUrl: BASE_URL,\n};\n\nexport const convexConfig: ConvexConfig = {\n convexUrl: CONVEX_URL,\n oauthConfig,\n};\n","import chalk from \"chalk\";\n\nexport interface OutputOptions {\n json?: boolean;\n}\n\nexport interface SuccessResult<T> {\n success: true;\n data: T;\n}\n\nexport interface ErrorResult {\n success: false;\n error: string;\n}\n\nexport type Result<T> = SuccessResult<T> | ErrorResult;\n\n/**\n * Output a success result in the appropriate format\n */\nexport function outputSuccess<T>(data: T, options: OutputOptions = {}): void {\n if (options.json) {\n const result: SuccessResult<T> = { success: true, data };\n console.log(JSON.stringify(result, null, 2));\n } else {\n // For human-readable output, we'll handle this per-command\n // This is a fallback that just pretty-prints\n console.log(data);\n }\n}\n\n/**\n * Output an error result in the appropriate format\n */\nexport function outputError(error: string, options: OutputOptions = {}): void {\n if (options.json) {\n const result: ErrorResult = { success: false, error };\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.error(chalk.red(\"Error:\"), error);\n }\n}\n\n/**\n * Format a table for human-readable output\n */\nexport function formatTable(\n headers: string[],\n rows: string[][],\n options: { indent?: number } = {}\n): string {\n const indent = \" \".repeat(options.indent ?? 0);\n\n // Calculate column widths\n const widths = headers.map((h, i) => {\n const maxRow = Math.max(...rows.map((r) => (r[i] ?? \"\").length));\n return Math.max(h.length, maxRow);\n });\n\n // Format header\n const headerLine = headers\n .map((h, i) => chalk.bold(h.padEnd(widths[i] ?? 0)))\n .join(\" \");\n\n // Format separator\n const separator = widths.map((w) => \"-\".repeat(w)).join(\" \");\n\n // Format rows\n const formattedRows = rows.map((row) =>\n row.map((cell, i) => (cell || \"\").padEnd(widths[i] ?? 0)).join(\" \")\n );\n\n return [indent + headerLine, indent + separator, ...formattedRows.map((r) => indent + r)].join(\n \"\\n\"\n );\n}\n\n/**\n * Format a key-value list for human-readable output\n */\nexport function formatKeyValue(\n items: { key: string; value: string }[],\n options: { indent?: number } = {}\n): string {\n const indent = \" \".repeat(options.indent ?? 0);\n const maxKeyLength = Math.max(...items.map((item) => item.key.length));\n\n return items\n .map(\n (item) =>\n indent + chalk.dim(item.key.padEnd(maxKeyLength) + \":\") + \" \" + item.value\n )\n .join(\"\\n\");\n}\n\n/**\n * Format a success message\n */\nexport function formatSuccess(message: string): string {\n return chalk.green(\"✓\") + \" \" + message;\n}\n\n/**\n * Format a warning message\n */\nexport function formatWarning(message: string): string {\n return chalk.yellow(\"⚠\") + \" \" + message;\n}\n\n/**\n * Format an info message\n */\nexport function formatInfo(message: string): string {\n return chalk.blue(\"ℹ\") + \" \" + message;\n}\n","import { clearCredentials, getCredentials } from \"../../lib/auth/credentials.js\";\nimport { formatSuccess, outputSuccess } from \"../../lib/output.js\";\nimport type {OutputOptions} from \"../../lib/output.js\";\n\nexport type LogoutOptions = OutputOptions;\n\nexport function logoutCommand(options: LogoutOptions): void {\n const credentials = getCredentials();\n\n if (!credentials) {\n if (options.json) {\n outputSuccess({ loggedOut: true, wasAuthenticated: false }, options);\n } else {\n console.log(\"Not currently logged in.\");\n }\n return;\n }\n\n const email = credentials.email;\n clearCredentials();\n\n if (options.json) {\n outputSuccess({ loggedOut: true, wasAuthenticated: true, email }, options);\n } else {\n console.log(formatSuccess(`Logged out from ${email}`));\n }\n}\n","import chalk from \"chalk\";\nimport { getCredentials, isAuthenticated, needsRefresh } from \"../../lib/auth/credentials.js\";\nimport { formatKeyValue, formatSuccess, formatWarning, outputSuccess } from \"../../lib/output.js\";\nimport type {OutputOptions} from \"../../lib/output.js\";\n\nexport type StatusOptions = OutputOptions;\n\nexport function statusCommand(options: StatusOptions): void {\n const credentials = getCredentials();\n\n if (!credentials) {\n if (options.json) {\n outputSuccess({ authenticated: false }, options);\n } else {\n console.log(\"Not logged in. Run 'program auth login' to authenticate.\");\n }\n return;\n }\n\n const authenticated = isAuthenticated();\n const expiresAt = credentials.expiresAt;\n const now = Math.floor(Date.now() / 1000);\n const expiresIn = expiresAt - now;\n\n if (options.json) {\n outputSuccess(\n {\n authenticated,\n user: credentials.email,\n userId: credentials.userId,\n organizationId: credentials.organizationId,\n expiresAt,\n expiresIn,\n needsRefresh: needsRefresh(),\n },\n options\n );\n } else {\n if (!authenticated) {\n console.log(formatWarning(\"Token expired. Run 'program auth login' to re-authenticate.\"));\n return;\n }\n\n console.log(formatSuccess(\"Logged in\"));\n console.log();\n console.log(\n formatKeyValue([\n { key: \"Email\", value: credentials.email },\n { key: \"User ID\", value: credentials.userId },\n { key: \"Organization\", value: credentials.organizationId || chalk.dim(\"(none)\") },\n { key: \"Token expires\", value: formatExpiresIn(expiresIn) },\n ])\n );\n }\n}\n\nfunction formatExpiresIn(seconds: number): string {\n if (seconds <= 0) {\n return chalk.red(\"expired\");\n }\n\n if (seconds < 60) {\n return chalk.yellow(`in ${seconds} seconds`);\n }\n\n if (seconds < 3600) {\n const minutes = Math.floor(seconds / 60);\n return chalk.green(`in ${minutes} minute${minutes === 1 ? \"\" : \"s\"}`);\n }\n\n const hours = Math.floor(seconds / 3600);\n const minutes = Math.floor((seconds % 3600) / 60);\n return chalk.green(`in ${hours}h ${minutes}m`);\n}\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { createConvexClient } from \"../../lib/convex.js\";\nimport { convexConfig } from \"../../lib/config.js\";\nimport { formatSuccess, outputError, outputSuccess } from \"../../lib/output.js\";\nimport type {OutputOptions} from \"../../lib/output.js\";\n\nexport interface CreateOptions extends OutputOptions {\n title?: string;\n description?: string;\n}\n\ninterface CreateResult {\n id: string;\n title: string;\n}\n\nexport async function createCommand(options: CreateOptions): Promise<void> {\n // Only show spinner in TTY environments (not through npx/pipes)\n const showSpinner = !options.json && process.stdout.isTTY;\n const spinner = showSpinner ? ora(\"Creating project...\").start() : null;\n\n const client = createConvexClient(convexConfig);\n\n const result = await client.mutation<string>(\"projects.create\", {\n title: options.title,\n description: options.description,\n });\n\n spinner?.stop();\n spinner?.clear();\n\n if (!result.success || !result.data) {\n outputError(result.error ?? \"Failed to create project\", options);\n process.exit(1);\n }\n\n const projectData: CreateResult = {\n id: result.data,\n title: options.title ?? \"Untitled Project\",\n };\n\n if (options.json) {\n outputSuccess(projectData, options);\n } else {\n console.log(formatSuccess(`Created project ${chalk.cyan(projectData.title)}`));\n console.log(chalk.dim(` ID: ${projectData.id}`));\n }\n}\n","import open from \"open\";\nimport { generateCodeChallenge, generateCodeVerifier, generateState } from \"./pkce.js\";\nimport { startCallbackServer } from \"./callback-server.js\";\nimport { saveCredentials, getCredentials } from \"./credentials.js\";\nimport type {Credentials} from \"./credentials.js\";\n\n// OAuth configuration\nconst CALLBACK_PORT = 8976;\nconst REDIRECT_URI = `http://localhost:${CALLBACK_PORT}/callback`;\n// Use standard OAuth scopes - email is required to identify the user\nconst SCOPES = [\"openid\", \"profile\", \"email\", \"offline_access\"];\n\n// OAuth client ID - same for all agents\n// Agent source is detected at runtime per-request (see lib/agent-detect.ts)\nconst CLIENT_ID = \"program-cli\";\n\nexport interface OAuthConfig {\n baseUrl: string;\n}\n\nexport interface TokenResponse {\n access_token: string;\n refresh_token?: string;\n expires_in: number;\n token_type: string;\n scope?: string;\n}\n\nexport interface UserInfo {\n id: string;\n email: string;\n name: string;\n organizationId?: string;\n}\n\n/**\n * Start the OAuth login flow\n * Opens browser for authentication and waits for callback\n */\nexport async function login(config: OAuthConfig): Promise<Credentials> {\n const codeVerifier = generateCodeVerifier();\n const codeChallenge = generateCodeChallenge(codeVerifier);\n const state = generateState();\n\n // Build authorization URL (use the page that handles the redirect properly)\n const authUrl = new URL(\"/oauth/authorize\", config.baseUrl);\n authUrl.searchParams.set(\"client_id\", CLIENT_ID);\n authUrl.searchParams.set(\"redirect_uri\", REDIRECT_URI);\n authUrl.searchParams.set(\"response_type\", \"code\");\n authUrl.searchParams.set(\"scope\", SCOPES.join(\" \"));\n authUrl.searchParams.set(\"state\", state);\n authUrl.searchParams.set(\"code_challenge\", codeChallenge);\n authUrl.searchParams.set(\"code_challenge_method\", \"S256\");\n\n // Start callback server before opening browser\n const callbackPromise = startCallbackServer(CALLBACK_PORT, state);\n\n // Open browser to authorization URL\n await open(authUrl.toString());\n\n // Wait for callback with authorization code\n const { code } = await callbackPromise;\n\n // Exchange code for tokens\n const tokens = await exchangeCodeForTokens(config, code, codeVerifier);\n\n // Get user info\n const userInfo = await getUserInfo(config, tokens.access_token);\n\n // Calculate expiry timestamp\n const expiresAt = Math.floor(Date.now() / 1000) + tokens.expires_in;\n\n // Validate we have a refresh token (required for token refresh)\n if (!tokens.refresh_token) {\n throw new Error(\"OAuth server did not return a refresh token\");\n }\n\n // Save credentials (source is detected at runtime per-request, not stored here)\n const credentials: Credentials = {\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n expiresAt,\n userId: userInfo.id,\n organizationId: userInfo.organizationId ?? \"\",\n email: userInfo.email,\n };\n\n saveCredentials(credentials);\n\n return credentials;\n}\n\n/**\n * Exchange authorization code for tokens\n */\nasync function exchangeCodeForTokens(\n config: OAuthConfig,\n code: string,\n codeVerifier: string\n): Promise<TokenResponse> {\n const tokenUrl = new URL(\"/api/auth/oauth2/token\", config.baseUrl);\n\n const body = new URLSearchParams({\n grant_type: \"authorization_code\",\n client_id: CLIENT_ID,\n code,\n redirect_uri: REDIRECT_URI,\n code_verifier: codeVerifier,\n });\n\n const response = await fetch(tokenUrl.toString(), {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: body.toString(),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token exchange failed: ${response.status} ${errorText}`);\n }\n\n return response.json() as Promise<TokenResponse>;\n}\n\n/**\n * Refresh the access token using the refresh token\n */\nexport async function refreshAccessToken(config: OAuthConfig): Promise<Credentials | null> {\n const creds = getCredentials();\n if (!creds?.refreshToken) {\n return null;\n }\n\n const tokenUrl = new URL(\"/api/auth/oauth2/token\", config.baseUrl);\n\n const body = new URLSearchParams({\n grant_type: \"refresh_token\",\n client_id: CLIENT_ID,\n refresh_token: creds.refreshToken,\n });\n\n const response = await fetch(tokenUrl.toString(), {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: body.toString(),\n });\n\n if (!response.ok) {\n // Refresh failed - user needs to re-authenticate\n return null;\n }\n\n const tokens = (await response.json()) as TokenResponse;\n const expiresAt = Math.floor(Date.now() / 1000) + tokens.expires_in;\n\n const newCredentials: Credentials = {\n ...creds,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token ?? creds.refreshToken,\n expiresAt,\n };\n\n saveCredentials(newCredentials);\n\n return newCredentials;\n}\n\n/**\n * Get user info from the OAuth server\n */\nasync function getUserInfo(config: OAuthConfig, accessToken: string): Promise<UserInfo> {\n const userInfoUrl = new URL(\"/api/auth/oauth2/userinfo\", config.baseUrl);\n\n const response = await fetch(userInfoUrl.toString(), {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n });\n\n if (!response.ok) {\n throw new Error(`Failed to get user info: ${response.status}`);\n }\n\n const data = (await response.json()) as {\n sub?: string;\n id?: string;\n email?: string;\n name?: string;\n organizationId?: string;\n };\n\n const id = data.sub ?? data.id;\n const email = data.email;\n\n if (!id || !email) {\n throw new Error(\"Invalid user info response: missing id or email\");\n }\n\n return {\n id,\n email,\n name: data.name ?? email,\n organizationId: data.organizationId,\n };\n}\n\n/**\n * Ensure we have a valid access token, refreshing if necessary\n */\nexport async function ensureValidToken(config: OAuthConfig): Promise<string | null> {\n const creds = getCredentials();\n if (!creds) {\n return null;\n }\n\n const now = Date.now();\n const expiresAt = creds.expiresAt * 1000;\n const bufferMs = 5 * 60 * 1000; // 5 minutes\n\n // If token is still valid, return it\n if (now < expiresAt - bufferMs) {\n return creds.accessToken;\n }\n\n // Try to refresh\n const refreshed = await refreshAccessToken(config);\n return refreshed?.accessToken ?? null;\n}\n","import * as crypto from \"node:crypto\";\n\n/**\n * Generate a cryptographically random code verifier for PKCE\n * Must be between 43-128 characters, using unreserved characters\n */\nexport function generateCodeVerifier(): string {\n // Generate 32 random bytes and encode as base64url\n const buffer = crypto.randomBytes(32);\n return buffer\n .toString(\"base64\")\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=/g, \"\");\n}\n\n/**\n * Generate the code challenge from a code verifier using S256 method\n */\nexport function generateCodeChallenge(verifier: string): string {\n const hash = crypto.createHash(\"sha256\").update(verifier).digest();\n return hash\n .toString(\"base64\")\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=/g, \"\");\n}\n\n/**\n * Generate a random state parameter for CSRF protection\n */\nexport function generateState(): string {\n return crypto.randomBytes(16).toString(\"hex\");\n}\n","import * as http from \"node:http\";\nimport { URL } from \"node:url\";\n\nexport interface CallbackResult {\n code: string;\n state: string;\n}\n\nexport interface CallbackError {\n error: string;\n errorDescription?: string;\n}\n\nconst SUCCESS_HTML = `\n<!DOCTYPE html>\n<html>\n<head>\n <title>Authentication Successful</title>\n <style>\n * { box-sizing: border-box; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n min-height: 100vh;\n margin: 0;\n padding: 2rem;\n background: #F5F5F0;\n color: #171717;\n }\n .card {\n width: 100%;\n max-width: 400px;\n background: white;\n border-radius: 12px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.1), 0 1px 2px rgba(0,0,0,0.06);\n padding: 2rem;\n text-align: center;\n }\n .logo {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n margin-bottom: 1.5rem;\n }\n .logo-icon {\n width: 16px;\n height: 16px;\n background: #EA580C;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n .logo-icon-inner {\n width: 3px;\n height: 3px;\n background: white;\n animation: flash 1.2s ease-in-out infinite;\n }\n @keyframes flash {\n 0%, 100% { opacity: 0.9; }\n 50% { opacity: 0.2; }\n }\n .logo-text {\n font-size: 1.25rem;\n font-weight: 300;\n color: #171717;\n }\n h1 {\n margin: 0 0 0.5rem 0;\n font-size: 1.25rem;\n font-weight: 500;\n letter-spacing: -0.01em;\n color: #171717;\n }\n p {\n margin: 0;\n color: #737373;\n font-size: 0.875rem;\n font-weight: 400;\n }\n </style>\n</head>\n<body>\n <div class=\"card\">\n <div class=\"logo\">\n <div class=\"logo-icon\"><div class=\"logo-icon-inner\"></div></div>\n <span class=\"logo-text\">Program.</span>\n </div>\n <h1>Authentication Successful</h1>\n <p>You can close this window and return to the terminal.</p>\n </div>\n</body>\n</html>\n`;\n\nconst ERROR_HTML = (error: string, description?: string) => `\n<!DOCTYPE html>\n<html>\n<head>\n <title>Authentication Failed</title>\n <style>\n * { box-sizing: border-box; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n min-height: 100vh;\n margin: 0;\n padding: 2rem;\n background: #F5F5F0;\n color: #171717;\n }\n .logo {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin-bottom: 2rem;\n }\n .logo-icon {\n width: 16px;\n height: 16px;\n background: #EA580C;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n .logo-icon-inner {\n width: 3px;\n height: 3px;\n background: white;\n animation: flash 1.2s infinite;\n }\n @keyframes flash {\n 0% { opacity: 0.8; }\n 50% { opacity: 0.1; }\n 100% { opacity: 0.8; }\n }\n .logo-text {\n font-size: 1.25rem;\n font-weight: 300;\n color: #171717;\n }\n .card {\n width: 100%;\n max-width: 400px;\n background: white;\n border-radius: 12px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.1), 0 1px 2px rgba(0,0,0,0.06);\n padding: 2rem;\n text-align: center;\n }\n .icon {\n width: 48px;\n height: 48px;\n background: #dc2626;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 0 auto 1.5rem;\n }\n .icon svg {\n width: 24px;\n height: 24px;\n }\n .icon svg path {\n fill: none;\n stroke: white;\n stroke-width: 2;\n stroke-linecap: round;\n stroke-linejoin: round;\n }\n h1 {\n margin: 0 0 0.5rem 0;\n font-size: 1.25rem;\n font-weight: 300;\n letter-spacing: -0.01em;\n }\n p {\n margin: 0;\n color: #737373;\n font-size: 0.875rem;\n font-weight: 400;\n }\n .error-detail {\n margin-top: 1rem;\n padding: 0.75rem;\n background: #fef2f2;\n border-radius: 8px;\n color: #dc2626;\n font-size: 0.8125rem;\n }\n </style>\n</head>\n<body>\n <div class=\"logo\">\n <div class=\"logo-icon\"><div class=\"logo-icon-inner\"></div></div>\n <span class=\"logo-text\">Program.</span>\n </div>\n <div class=\"card\">\n <div class=\"icon\">\n <svg viewBox=\"0 0 24 24\">\n <path d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </div>\n <h1>Authentication Failed</h1>\n <p>Unable to complete the authentication process.</p>\n <div class=\"error-detail\">${error}${description ? `: ${description}` : \"\"}</div>\n </div>\n</body>\n</html>\n`;\n\n/**\n * Start a local HTTP server to receive the OAuth callback\n * Returns a promise that resolves with the authorization code\n */\nexport function startCallbackServer(\n port: number,\n expectedState: string,\n timeoutMs = 120000\n): Promise<CallbackResult> {\n return new Promise((resolve, reject) => {\n const server = http.createServer((req, res) => {\n if (!req.url) {\n res.writeHead(400);\n res.end(\"Bad request\");\n return;\n }\n\n const url = new URL(req.url, `http://localhost:${port}`);\n\n // Only handle /callback path\n if (url.pathname !== \"/callback\") {\n res.writeHead(404);\n res.end(\"Not found\");\n return;\n }\n\n const code = url.searchParams.get(\"code\");\n const state = url.searchParams.get(\"state\");\n const error = url.searchParams.get(\"error\");\n const errorDescription = url.searchParams.get(\"error_description\");\n\n // Handle error response from OAuth server\n if (error) {\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(ERROR_HTML(error, errorDescription ?? undefined));\n\n server.close();\n reject(new Error(errorDescription ?? error));\n return;\n }\n\n // Validate state to prevent CSRF\n if (state !== expectedState) {\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(ERROR_HTML(\"Invalid state\", \"State mismatch - possible CSRF attack\"));\n\n server.close();\n reject(new Error(\"State mismatch - possible CSRF attack\"));\n return;\n }\n\n // Validate code exists\n if (!code) {\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(ERROR_HTML(\"Missing code\", \"No authorization code received\"));\n\n server.close();\n reject(new Error(\"No authorization code received\"));\n return;\n }\n\n // Success!\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(SUCCESS_HTML);\n\n server.close();\n resolve({ code, state });\n });\n\n // Handle server errors\n server.on(\"error\", (err) => {\n reject(new Error(`Failed to start callback server: ${err.message}`));\n });\n\n // Set timeout\n const timeout = setTimeout(() => {\n server.close();\n reject(new Error(\"Authentication timed out\"));\n }, timeoutMs);\n\n // Clear timeout when server closes\n server.on(\"close\", () => {\n clearTimeout(timeout);\n });\n\n // Start listening\n server.listen(port, \"127.0.0.1\", () => {\n // Server is ready\n });\n });\n}\n","import { getCredentials, ensureValidToken } from \"./auth/index.js\";\nimport type {OAuthConfig} from \"./auth/index.js\";\n\nexport interface ConvexConfig {\n convexUrl: string;\n oauthConfig: OAuthConfig;\n}\n\nexport interface ConvexResponse<T> {\n success: boolean;\n data?: T;\n error?: string;\n}\n\n/**\n * Create a Convex HTTP client for calling Convex functions via the CLI gateway\n */\nexport function createConvexClient(config: ConvexConfig) {\n const { convexUrl } = config;\n\n // The CLI gateway is on the .convex.site endpoint\n const gatewayUrl = convexUrl.replace(\".convex.cloud\", \".convex.site\");\n\n /**\n * Call a Convex query function via the CLI gateway\n */\n async function query<T>(\n functionPath: string,\n args: Record<string, unknown> = {}\n ): Promise<ConvexResponse<T>> {\n return callGateway<T>(functionPath, args);\n }\n\n /**\n * Call a Convex mutation function via the CLI gateway\n */\n async function mutation<T>(\n functionPath: string,\n args: Record<string, unknown> = {}\n ): Promise<ConvexResponse<T>> {\n return callGateway<T>(functionPath, args);\n }\n\n /**\n * Call a Convex action function via the CLI gateway\n */\n async function action<T>(\n functionPath: string,\n args: Record<string, unknown> = {}\n ): Promise<ConvexResponse<T>> {\n return callGateway<T>(functionPath, args);\n }\n\n /**\n * Call the CLI gateway with OAuth authentication\n */\n async function callGateway<T>(\n functionPath: string,\n args: Record<string, unknown>\n ): Promise<ConvexResponse<T>> {\n // Get valid access token\n const accessToken = await ensureValidToken(config.oauthConfig);\n if (!accessToken) {\n return {\n success: false,\n error: \"Not authenticated. Run 'program auth login' first.\",\n };\n }\n\n // Build the gateway URL\n const url = new URL(\"/cli\", gatewayUrl);\n\n try {\n const response = await fetch(url.toString(), {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${accessToken}`,\n },\n body: JSON.stringify({\n fn: functionPath,\n params: args,\n }),\n });\n\n const result = (await response.json()) as {\n success: boolean;\n data?: T;\n error?: string;\n };\n\n if (!response.ok || !result.success) {\n return {\n success: false,\n error: result.error ?? `Gateway error: ${response.status}`,\n };\n }\n\n return { success: true, data: result.data };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n }\n\n /**\n * Get the current credentials (for checking auth status)\n */\n function getAuth() {\n return getCredentials();\n }\n\n return {\n query,\n mutation,\n action,\n getAuth,\n };\n}\n\nexport type ConvexClient = ReturnType<typeof createConvexClient>;\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { createConvexClient } from \"../../lib/convex.js\";\nimport { convexConfig } from \"../../lib/config.js\";\nimport { formatKeyValue, outputError, outputSuccess } from \"../../lib/output.js\";\nimport type {OutputOptions} from \"../../lib/output.js\";\n\nexport type GetOptions = OutputOptions;\n\ninterface ProjectWithComposition {\n _id: string;\n title: string;\n description?: string;\n createdAt: number;\n updatedAt: number;\n latestVersion: {\n _id: string;\n version: number;\n compositionId: string;\n createdAt: number;\n } | null;\n composition: {\n _id: string;\n title: string;\n description?: string;\n duration: number;\n fps: number;\n width: number;\n height: number;\n sceneCount: number;\n scenes: unknown[];\n } | null;\n}\n\nexport async function getCommand(projectId: string, options: GetOptions): Promise<void> {\n const showSpinner = !options.json && process.stdout.isTTY;\n const spinner = showSpinner ? ora(\"Fetching project...\").start() : null;\n\n const client = createConvexClient(convexConfig);\n\n const result = await client.query<ProjectWithComposition>(\"projects.byId\", {\n id: projectId,\n });\n\n spinner?.stop();\n spinner?.clear();\n\n if (!result.success || !result.data) {\n outputError(result.error ?? \"Failed to get project\", options);\n process.exit(1);\n }\n\n const project = result.data;\n\n if (options.json) {\n outputSuccess(project, options);\n } else {\n console.log(chalk.bold(project.title || \"Untitled Project\"));\n if (project.description) {\n console.log(chalk.dim(project.description));\n }\n console.log();\n\n console.log(\n formatKeyValue([\n { key: \"ID\", value: project._id },\n { key: \"Created\", value: new Date(project.createdAt).toLocaleString() },\n { key: \"Updated\", value: new Date(project.updatedAt).toLocaleString() },\n ])\n );\n\n if (project.latestVersion) {\n console.log(chalk.bold(\"\\nVersion\"));\n console.log(\n formatKeyValue([\n { key: \"Version\", value: String(project.latestVersion.version) },\n { key: \"Composition ID\", value: project.latestVersion.compositionId },\n ])\n );\n } else {\n console.log(chalk.dim(\"\\nNo versions yet\"));\n }\n\n if (project.composition) {\n console.log(chalk.bold(\"\\nComposition\"));\n console.log(\n formatKeyValue([\n { key: \"Title\", value: project.composition.title },\n { key: \"Resolution\", value: `${project.composition.width}x${project.composition.height}` },\n { key: \"FPS\", value: String(project.composition.fps) },\n { key: \"Duration\", value: `${(project.composition.duration / 1000).toFixed(1)}s` },\n { key: \"Scenes\", value: String(project.composition.sceneCount) },\n ])\n );\n\n if (project.composition.sceneCount > 0 && Array.isArray(project.composition.scenes)) {\n console.log(chalk.bold(\"\\nScenes\"));\n for (const scene of project.composition.scenes as { id: string; type: string; duration: number }[]) {\n console.log(chalk.dim(` - ${scene.type} (${(scene.duration / 1000).toFixed(1)}s)`));\n }\n }\n } else {\n console.log(chalk.dim(\"\\nNo composition yet\"));\n }\n }\n}\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { createConvexClient } from \"../../lib/convex.js\";\nimport { convexConfig } from \"../../lib/config.js\";\nimport { formatTable, outputError, outputSuccess } from \"../../lib/output.js\";\nimport type {OutputOptions} from \"../../lib/output.js\";\n\nexport interface ListOptions extends OutputOptions {\n limit?: number;\n}\n\ninterface Project {\n _id: string;\n title: string;\n description?: string;\n createdAt: number;\n updatedAt: number;\n}\n\ninterface ListResult {\n items: Project[];\n nextCursor: string | null;\n}\n\nexport async function listCommand(options: ListOptions): Promise<void> {\n // Only show spinner in TTY environments (not through npx/pipes)\n const showSpinner = !options.json && process.stdout.isTTY;\n const spinner = showSpinner ? ora(\"Fetching projects...\").start() : null;\n\n const client = createConvexClient(convexConfig);\n\n const result = await client.query<ListResult>(\"projects.list\", {\n limit: options.limit,\n });\n\n spinner?.stop();\n spinner?.clear();\n\n if (!result.success || !result.data) {\n outputError(result.error ?? \"Failed to list projects\", options);\n process.exit(1);\n }\n\n const projects = result.data.items;\n\n if (options.json) {\n outputSuccess(projects, options);\n } else {\n if (projects.length === 0) {\n console.log(chalk.dim(\"No projects found. Create one with 'program project create'\"));\n return;\n }\n\n console.log(`Found ${chalk.cyan(projects.length)} project${projects.length === 1 ? \"\" : \"s\"}:\\n`);\n\n const rows = projects.map((p) => [\n p._id,\n p.title || chalk.dim(\"Untitled\"),\n formatDate(p.createdAt),\n ]);\n\n console.log(formatTable([\"ID\", \"Title\", \"Created\"], rows));\n }\n}\n\nfunction formatDate(timestamp: number): string {\n const date = new Date(timestamp);\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));\n\n if (diffDays === 0) {\n return \"today\";\n } else if (diffDays === 1) {\n return \"yesterday\";\n } else if (diffDays < 7) {\n return `${diffDays} days ago`;\n } else {\n return date.toLocaleDateString();\n }\n}\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { createConvexClient } from \"../../lib/convex.js\";\nimport { convexConfig } from \"../../lib/config.js\";\nimport { formatTable, outputError, outputSuccess } from \"../../lib/output.js\";\nimport type {OutputOptions} from \"../../lib/output.js\";\n\nexport interface ListOptions extends OutputOptions {\n limit?: number;\n publicOnly?: boolean;\n}\n\ninterface Template {\n _id: string;\n name: string;\n description?: string;\n public: boolean;\n createdAt: number;\n updatedAt: number;\n}\n\nexport async function listCommand(options: ListOptions): Promise<void> {\n const showSpinner = !options.json && process.stdout.isTTY;\n const spinner = showSpinner ? ora(\"Fetching workflow templates...\").start() : null;\n\n const client = createConvexClient(convexConfig);\n\n const result = await client.query<Template[]>(\"workflows.listTemplates\", {\n category: options.publicOnly ? \"public\" : undefined,\n });\n\n spinner?.stop();\n spinner?.clear();\n\n if (!result.success || !result.data) {\n outputError(result.error ?? \"Failed to list templates\", options);\n process.exit(1);\n }\n\n const templates = result.data;\n\n if (options.json) {\n outputSuccess(\n templates.map((t) => ({\n id: t._id,\n name: t.name,\n description: t.description,\n public: t.public,\n })),\n options\n );\n } else {\n if (templates.length === 0) {\n console.log(chalk.dim(\"No workflow templates found.\"));\n return;\n }\n\n console.log(`Found ${chalk.cyan(templates.length)} template${templates.length === 1 ? \"\" : \"s\"}:\\n`);\n\n const rows = templates.map((t) => [\n t._id,\n t.name,\n t.description?.substring(0, 40) ?? chalk.dim(\"No description\"),\n t.public ? chalk.green(\"public\") : chalk.dim(\"private\"),\n ]);\n\n console.log(formatTable([\"ID\", \"Name\", \"Description\", \"Visibility\"], rows));\n }\n}\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { createConvexClient } from \"../../lib/convex.js\";\nimport { convexConfig } from \"../../lib/config.js\";\nimport { formatSuccess, outputError, outputSuccess } from \"../../lib/output.js\";\nimport type {OutputOptions} from \"../../lib/output.js\";\n\nexport interface RunOptions extends OutputOptions {\n project?: string;\n input?: string;\n}\n\nexport async function runCommand(templateId: string, options: RunOptions): Promise<void> {\n const showSpinner = !options.json && process.stdout.isTTY;\n const spinner = showSpinner ? ora(\"Starting workflow execution...\").start() : null;\n\n // Parse input JSON if provided\n let input: Record<string, unknown> | undefined;\n if (options.input) {\n try {\n input = JSON.parse(options.input) as Record<string, unknown>;\n } catch {\n spinner?.stop();\n spinner?.clear();\n outputError(\"Invalid JSON in --input parameter\", options);\n process.exit(1);\n }\n }\n\n const client = createConvexClient(convexConfig);\n\n const result = await client.mutation<string>(\"workflows.run\", {\n templateId,\n projectId: options.project,\n input,\n });\n\n spinner?.stop();\n spinner?.clear();\n\n if (!result.success || !result.data) {\n outputError(result.error ?? \"Failed to start workflow\", options);\n process.exit(1);\n }\n\n const executionId = result.data;\n\n if (options.json) {\n outputSuccess({ executionId }, options);\n } else {\n console.log(formatSuccess(`Workflow started`));\n console.log(chalk.dim(` Execution ID: ${executionId}`));\n console.log(chalk.dim(` Check status with: program workflow status ${executionId}`));\n }\n}\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { createConvexClient } from \"../../lib/convex.js\";\nimport { convexConfig } from \"../../lib/config.js\";\nimport { formatKeyValue, formatSuccess, formatWarning, outputError, outputSuccess } from \"../../lib/output.js\";\nimport type {OutputOptions} from \"../../lib/output.js\";\n\nexport interface StatusOptions extends OutputOptions {\n watch?: boolean;\n interval?: number;\n}\n\ninterface ExecutionStatus {\n status: \"pending\" | \"running\" | \"success\" | \"error\" | \"cancelled\";\n output?: unknown;\n error?: string;\n completedAt?: number;\n nodeStatuses?: { nodeId: string; status: string }[];\n}\n\nexport async function statusCommand(executionId: string, options: StatusOptions): Promise<void> {\n const client = createConvexClient(convexConfig);\n const pollInterval = options.interval ?? 2000;\n\n if (options.watch) {\n await watchStatus(client, executionId, pollInterval, options);\n } else {\n await getStatusOnce(client, executionId, options);\n }\n}\n\nasync function getStatusOnce(\n client: ReturnType<typeof createConvexClient>,\n executionId: string,\n options: StatusOptions\n): Promise<void> {\n const showSpinner = !options.json && process.stdout.isTTY;\n const spinner = showSpinner ? ora(\"Fetching execution status...\").start() : null;\n\n const result = await client.query<ExecutionStatus>(\"workflows.status\", {\n executionId,\n });\n\n spinner?.stop();\n spinner?.clear();\n\n if (!result.success) {\n outputError(result.error ?? \"Failed to get status\", options);\n process.exit(1);\n }\n\n const status = result.data;\n\n if (!status) {\n outputError(\"Execution not found\", options);\n process.exit(1);\n }\n\n if (options.json) {\n outputSuccess(status, options);\n } else {\n printStatus(status);\n }\n}\n\nasync function watchStatus(\n client: ReturnType<typeof createConvexClient>,\n executionId: string,\n pollInterval: number,\n options: StatusOptions\n): Promise<void> {\n let lastStatus: string | null = null;\n\n const poll = async (): Promise<boolean> => {\n const result = await client.query<ExecutionStatus>(\"workflows.status\", {\n executionId,\n });\n\n if (!result.success) {\n outputError(result.error ?? \"Failed to get status\", options);\n return true; // Stop polling\n }\n\n const status = result.data;\n\n if (!status) {\n outputError(\"Execution not found\", options);\n return true;\n }\n\n // For JSON mode, output each status change\n if (options.json) {\n if (status.status !== lastStatus) {\n console.log(JSON.stringify(status));\n lastStatus = status.status;\n }\n } else {\n // For human mode, clear and reprint\n if (status.status !== lastStatus) {\n console.clear();\n console.log(chalk.dim(`Watching execution ${executionId}...\\n`));\n printStatus(status);\n lastStatus = status.status;\n }\n }\n\n // Stop polling if complete\n if ([\"success\", \"error\", \"cancelled\"].includes(status.status)) {\n return true;\n }\n\n return false;\n };\n\n // Initial poll\n let done = await poll();\n\n // Continue polling until complete\n while (!done) {\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\n done = await poll();\n }\n}\n\nfunction printStatus(status: ExecutionStatus): void {\n const statusColor = getStatusColor(status.status);\n\n console.log(\n formatKeyValue([\n { key: \"Status\", value: statusColor(status.status) },\n ...(status.completedAt\n ? [{ key: \"Completed\", value: new Date(status.completedAt).toLocaleString() }]\n : []),\n ])\n );\n\n if (status.nodeStatuses && status.nodeStatuses.length > 0) {\n console.log(chalk.dim(\"\\nStep progress:\"));\n for (const node of status.nodeStatuses) {\n const nodeColor = getStatusColor(node.status);\n console.log(` ${nodeColor(getStatusIcon(node.status))} ${node.nodeId}`);\n }\n }\n\n if (status.error) {\n console.log(formatWarning(`\\nError: ${status.error}`));\n }\n\n if (status.status === \"success\" && status.output) {\n console.log(formatSuccess(\"\\nOutput:\"));\n console.log(JSON.stringify(status.output, null, 2));\n }\n}\n\nfunction getStatusColor(status: string): (text: string) => string {\n switch (status) {\n case \"success\":\n return chalk.green;\n case \"error\":\n return chalk.red;\n case \"cancelled\":\n return chalk.yellow;\n case \"running\":\n return chalk.blue;\n case \"pending\":\n default:\n return chalk.dim;\n }\n}\n\nfunction getStatusIcon(status: string): string {\n switch (status) {\n case \"success\":\n return \"✓\";\n case \"error\":\n return \"✕\";\n case \"running\":\n return \"●\";\n case \"pending\":\n default:\n return \"○\";\n }\n}\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { ensureValidToken } from \"../../lib/auth/index.js\";\nimport { oauthConfig, BASE_URL } from \"../../lib/config.js\";\nimport { outputError, outputSuccess } from \"../../lib/output.js\";\nimport type {OutputOptions} from \"../../lib/output.js\";\nimport { detectAgentSource } from \"../../lib/agent-detect.js\";\n\nexport interface ExecuteOptions extends OutputOptions {\n project: string;\n params?: string;\n}\n\nexport async function executeCommand(\n toolName: string,\n options: ExecuteOptions\n): Promise<void> {\n const showSpinner = !options.json && process.stdout.isTTY;\n const spinner = showSpinner ? ora(`Executing ${toolName}...`).start() : null;\n\n // Get valid access token\n const accessToken = await ensureValidToken(oauthConfig);\n if (!accessToken) {\n spinner?.stop();\n spinner?.clear();\n outputError(\"Not authenticated. Run 'program auth login' first.\", options);\n process.exit(1);\n }\n\n // Parse params if provided\n let params: Record<string, unknown> = {};\n if (options.params) {\n try {\n params = JSON.parse(options.params) as Record<string, unknown>;\n } catch {\n spinner?.stop();\n spinner?.clear();\n outputError(\"Invalid JSON in --params\", options);\n process.exit(1);\n }\n }\n\n // Detect agent at runtime (not login time) for correct multi-agent support\n const source = detectAgentSource();\n\n try {\n const response = await fetch(`${BASE_URL}/api/cli/tool`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${accessToken}`,\n },\n body: JSON.stringify({\n projectId: options.project,\n tool: toolName,\n params,\n source,\n }),\n });\n\n const result = (await response.json()) as {\n success: boolean;\n data?: unknown;\n error?: string;\n compositionId?: string;\n };\n\n spinner?.stop();\n spinner?.clear();\n\n if (!response.ok || !result.success) {\n outputError(result.error ?? `Tool execution failed: ${response.status}`, options);\n process.exit(1);\n }\n\n if (options.json) {\n outputSuccess(result.data, options);\n } else {\n console.log(chalk.green(`✓ ${toolName} executed successfully`));\n if (result.compositionId) {\n console.log(chalk.dim(` Composition: ${result.compositionId}`));\n }\n console.log();\n console.log(JSON.stringify(result.data, null, 2));\n }\n } catch (error) {\n spinner?.stop();\n spinner?.clear();\n outputError(error instanceof Error ? error.message : \"Request failed\", options);\n process.exit(1);\n }\n}\n","/**\n * Runtime agent detection\n *\n * Detects which agent/IDE is running the CLI based on environment variables.\n * This is checked per-request, not at login time, so multiple agents can\n * use the same credentials simultaneously with correct attribution.\n */\n\n/**\n * Detect which agent is currently running this CLI command.\n * Returns undefined for unknown agents (will show as \"Agent via CLI\").\n */\nexport function detectAgentSource(): string | undefined {\n // Claude Code sets CLAUDECODE=1 (external env var from IDE, not project-owned)\n // eslint-disable-next-line turbo/no-undeclared-env-vars\n if (process.env.CLAUDECODE === \"1\") {\n return \"claude-code\";\n }\n\n // Future: Add detection for other agents when we know their env vars\n // OpenCode, Codex, Cursor, etc.\n\n // Unknown agent - return undefined to use default display\n return undefined;\n}\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { BASE_URL } from \"../../lib/config.js\";\nimport { outputError, outputSuccess } from \"../../lib/output.js\";\nimport type {OutputOptions} from \"../../lib/output.js\";\n\nexport type ListOptions = OutputOptions;\n\ninterface Tool {\n name: string;\n description: string;\n inputs: string[];\n}\n\nexport async function listCommand(options: ListOptions): Promise<void> {\n const showSpinner = !options.json && process.stdout.isTTY;\n const spinner = showSpinner ? ora(\"Fetching available tools...\").start() : null;\n\n try {\n const response = await fetch(`${BASE_URL}/api/cli/tool`, {\n method: \"GET\",\n });\n\n const result = (await response.json()) as {\n success: boolean;\n tools?: Tool[];\n error?: string;\n };\n\n spinner?.stop();\n spinner?.clear();\n\n if (!response.ok || !result.success) {\n outputError(result.error ?? \"Failed to list tools\", options);\n process.exit(1);\n }\n\n const tools = result.tools ?? [];\n\n if (options.json) {\n outputSuccess(tools, options);\n } else {\n console.log(chalk.bold(`Available Tools (${tools.length}):\\n`));\n\n for (const tool of tools) {\n console.log(chalk.cyan(` ${tool.name}`));\n console.log(chalk.dim(` ${tool.description}`));\n if (tool.inputs.length > 0) {\n console.log(chalk.dim(` Inputs: ${tool.inputs.join(\", \")}`));\n }\n console.log();\n }\n\n console.log(chalk.dim(\"Usage: program tool exec <toolName> --project <id> --params '{...}'\"));\n }\n } catch (error) {\n spinner?.stop();\n spinner?.clear();\n outputError(error instanceof Error ? error.message : \"Request failed\", options);\n process.exit(1);\n }\n}\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { ensureValidToken } from \"../../lib/auth/index.js\";\nimport { oauthConfig, BASE_URL } from \"../../lib/config.js\";\nimport { outputError, outputSuccess } from \"../../lib/output.js\";\nimport type {OutputOptions} from \"../../lib/output.js\";\nimport { detectAgentSource } from \"../../lib/agent-detect.js\";\n\nexport interface SendMessageOptions extends OutputOptions {\n project: string;\n role?: \"user\" | \"assistant\";\n}\n\nexport async function sendCommand(\n text: string,\n options: SendMessageOptions\n): Promise<void> {\n const showSpinner = !options.json && process.stdout.isTTY;\n const spinner = showSpinner ? ora(\"Sending message...\").start() : null;\n\n // Get valid access token\n const accessToken = await ensureValidToken(oauthConfig);\n if (!accessToken) {\n spinner?.stop();\n spinner?.clear();\n outputError(\"Not authenticated. Run 'program auth login' first.\", options);\n process.exit(1);\n }\n\n const role = options.role ?? \"assistant\";\n\n // Detect agent at runtime (not login time) for correct multi-agent support\n const source = detectAgentSource();\n\n try {\n const response = await fetch(`${BASE_URL}/api/cli/message`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${accessToken}`,\n },\n body: JSON.stringify({\n projectId: options.project,\n role,\n text,\n source,\n }),\n });\n\n const result = (await response.json()) as {\n success: boolean;\n messageId?: string;\n error?: string;\n };\n\n spinner?.stop();\n spinner?.clear();\n\n if (!response.ok || !result.success) {\n outputError(result.error ?? `Failed to send message: ${response.status}`, options);\n process.exit(1);\n }\n\n if (options.json) {\n outputSuccess({ messageId: result.messageId, role, text }, options);\n } else {\n console.log(chalk.green(`✓ Message sent as ${role}`));\n if (result.messageId) {\n console.log(chalk.dim(` Message ID: ${result.messageId}`));\n }\n }\n } catch (error) {\n spinner?.stop();\n spinner?.clear();\n outputError(error instanceof Error ? error.message : \"Request failed\", options);\n process.exit(1);\n }\n}\n","import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { ensureValidToken } from \"../../lib/auth/index.js\";\nimport { oauthConfig, BASE_URL } from \"../../lib/config.js\";\nimport { outputError, outputSuccess } from \"../../lib/output.js\";\nimport type { OutputOptions } from \"../../lib/output.js\";\n\nexport interface ListMessageOptions extends OutputOptions {\n project: string;\n limit?: number;\n}\n\ninterface MessagePart {\n type: string;\n text?: string;\n toolName?: string;\n toolCallId?: string;\n state?: string;\n}\n\ninterface Message {\n id: string;\n role: \"user\" | \"assistant\";\n parts: MessagePart[];\n source?: string;\n createdAt: number;\n}\n\nexport async function listCommand(options: ListMessageOptions): Promise<void> {\n const showSpinner = !options.json && process.stdout.isTTY;\n const spinner = showSpinner ? ora(\"Fetching messages...\").start() : null;\n\n // Get valid access token\n const accessToken = await ensureValidToken(oauthConfig);\n if (!accessToken) {\n spinner?.stop();\n spinner?.clear();\n outputError(\n \"Not authenticated. Run 'program auth login' first.\",\n options\n );\n process.exit(1);\n }\n\n try {\n const url = new URL(`${BASE_URL}/api/cli/message`);\n url.searchParams.set(\"projectId\", options.project);\n if (options.limit) {\n url.searchParams.set(\"limit\", options.limit.toString());\n }\n\n const response = await fetch(url.toString(), {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n });\n\n const result = (await response.json()) as {\n success: boolean;\n chatId?: string;\n messages?: Message[];\n error?: string;\n };\n\n spinner?.stop();\n spinner?.clear();\n\n if (!response.ok || !result.success) {\n outputError(\n result.error ?? `Failed to fetch messages: ${response.status}`,\n options\n );\n process.exit(1);\n }\n\n if (options.json) {\n outputSuccess(result, options);\n } else {\n const messages = result.messages ?? [];\n if (messages.length === 0) {\n console.log(chalk.dim(\"No messages in this chat yet.\"));\n return;\n }\n\n console.log(chalk.bold(`Chat Messages (${messages.length}):\\n`));\n\n for (const msg of messages) {\n // Format the role with source if available\n let roleLabel = msg.role === \"user\" ? \"You\" : \"Assistant\";\n if (msg.source) {\n if (msg.source === \"cli:claude-code\") {\n roleLabel = \"Claude via CLI\";\n } else if (msg.source.startsWith(\"cli:\")) {\n roleLabel = `${roleLabel} via CLI`;\n }\n }\n\n // Get text content from parts\n const textContent = msg.parts\n .filter((p): p is MessagePart & { text: string } => p.type === \"text\" && !!p.text)\n .map((p) => p.text)\n .join(\"\\n\");\n\n // Get tool calls\n const toolCalls = msg.parts.filter(\n (p) => p.type === \"tool-invocation\" || p.type === \"tool-call\"\n );\n\n // Format timestamp\n const time = new Date(msg.createdAt).toLocaleTimeString();\n\n // Print message\n const roleColor = msg.role === \"user\" ? chalk.blue : chalk.green;\n console.log(roleColor(`[${time}] ${roleLabel}:`));\n\n if (textContent) {\n // Indent and truncate long messages\n const truncated =\n textContent.length > 500\n ? textContent.substring(0, 500) + \"...\"\n : textContent;\n console.log(\n truncated\n .split(\"\\n\")\n .map((line) => ` ${line}`)\n .join(\"\\n\")\n );\n }\n\n if (toolCalls.length > 0) {\n console.log(\n chalk.dim(` [${toolCalls.length} tool call(s)]`)\n );\n }\n\n console.log();\n }\n }\n } catch (error) {\n spinner?.stop();\n spinner?.clear();\n outputError(\n error instanceof Error ? error.message : \"Request failed\",\n options\n );\n process.exit(1);\n }\n}\n","import { outputSuccess } from \"../lib/output.js\";\nimport type {OutputOptions} from \"../lib/output.js\";\n\nexport interface DocsOptions extends OutputOptions {\n schema?: boolean;\n}\n\n// Command schema for agents\nconst COMMAND_SCHEMA = {\n name: \"program\",\n version: \"0.1.0\",\n description: \"CLI for interacting with the Program video creation platform\",\n commands: {\n auth: {\n description: \"Authentication commands\",\n subcommands: {\n login: {\n description: \"Authenticate with the Program platform\",\n options: {\n \"--json\": \"Output as JSON\",\n },\n example: \"program auth login\",\n },\n logout: {\n description: \"Log out from the Program platform\",\n options: {\n \"--json\": \"Output as JSON\",\n },\n example: \"program auth logout\",\n },\n status: {\n description: \"Check authentication status\",\n options: {\n \"--json\": \"Output as JSON\",\n },\n example: \"program auth status --json\",\n },\n },\n },\n project: {\n description: \"Project management commands\",\n subcommands: {\n create: {\n description: \"Create a new project\",\n options: {\n \"--title <title>\": \"Project title\",\n \"--description <desc>\": \"Project description\",\n \"--json\": \"Output as JSON\",\n },\n example: 'program project create --title \"My Video\" --json',\n },\n list: {\n description: \"List projects\",\n options: {\n \"--limit <n>\": \"Maximum number of projects to return\",\n \"--json\": \"Output as JSON\",\n },\n example: \"program project list --json\",\n },\n },\n },\n workflow: {\n description: \"Workflow template commands\",\n subcommands: {\n list: {\n description: \"List available workflow templates\",\n options: {\n \"--limit <n>\": \"Maximum number of templates to return\",\n \"--public-only\": \"Only show public templates\",\n \"--json\": \"Output as JSON\",\n },\n example: \"program workflow list --json\",\n },\n run: {\n description: \"Execute a workflow template\",\n args: {\n templateId: \"ID of the template to run\",\n },\n options: {\n \"--project <id>\": \"Project ID to associate with execution\",\n \"--input <json>\": \"JSON input for the workflow\",\n \"--json\": \"Output as JSON\",\n },\n example: \"program workflow run tmpl_abc --project proj_123 --input '{\\\"files\\\":[\\\"src/main.ts\\\"]}' --json\",\n },\n status: {\n description: \"Check workflow execution status\",\n args: {\n executionId: \"ID of the execution to check\",\n },\n options: {\n \"--watch\": \"Continuously poll for status updates\",\n \"--interval <ms>\": \"Poll interval in milliseconds (default: 2000)\",\n \"--json\": \"Output as JSON\",\n },\n example: \"program workflow status exec_789 --watch --json\",\n },\n },\n },\n docs: {\n description: \"Display CLI documentation\",\n options: {\n \"--schema\": \"Output full command schema as JSON\",\n },\n example: \"program docs --schema\",\n },\n },\n globalOptions: {\n \"--help\": \"Display help information\",\n \"--version\": \"Display version number\",\n },\n notes: [\n \"Always use --json flag for parseable output when integrating with agents\",\n \"Workflow inputs should be valid JSON strings\",\n \"Run 'program auth login' first to authenticate\",\n ],\n};\n\nexport function docsCommand(options: DocsOptions): void {\n if (options.schema ?? options.json) {\n outputSuccess(COMMAND_SCHEMA, { json: true });\n } else {\n printHumanDocs();\n }\n}\n\nfunction printHumanDocs(): void {\n console.log(`\nProgram CLI v${COMMAND_SCHEMA.version}\n${COMMAND_SCHEMA.description}\n\nCOMMANDS:\n\n auth login Authenticate with the Program platform\n auth logout Log out from the Program platform\n auth status Check authentication status\n\n project create Create a new project\n project list List projects\n\n workflow list List available workflow templates\n workflow run <id> Execute a workflow template\n workflow status <id> Check workflow execution status\n\n docs Display this documentation\n docs --schema Output full command schema as JSON\n\nGLOBAL OPTIONS:\n\n --json Output as JSON (recommended for agents)\n --help Display help information\n --version Display version number\n\nEXAMPLES:\n\n # Authenticate\n program auth login\n\n # Create a project\n program project create --title \"My Video\" --json\n\n # Run a workflow\n program workflow run tmpl_abc --project proj_123 --json\n\n # Watch execution progress\n program workflow status exec_789 --watch --json\n\nFor agent integration, always use the --json flag.\n`);\n}\n"],"mappings":"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","names":["chalk","message","chalk","message","chalk","chalk","minutes","chalk","ora","URL","CLIENT_ID","CLIENT_ID","ora","chalk","chalk","ora","ora","project","chalk","chalk","ora","ora","chalk","chalk","ora","listCommand","ora","chalk","chalk","ora","ora","chalk","chalk","ora","statusCommand","ora","chalk","chalk","ora","ora","chalk","chalk","ora","listCommand","ora","chalk","tool","chalk","ora","ora","chalk","chalk","ora","listCommand","ora","chalk","listCommand","statusCommand"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@program-video/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.3",
4
4
  "description": "CLI for Program Video",
5
5
  "private": false,
6
6
  "type": "module",