@tutorflow/cli 0.2.0 → 0.3.1

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
@@ -25,6 +25,8 @@ Then anywhere on the system:
25
25
  ```bash
26
26
  tutorflow --version
27
27
  tutorflow auth login
28
+ tutorflow agent register --name "My Agent Workspace" --slug my-agent-workspace --email me@example.com
29
+ tutorflow --json platform manifest
28
30
  tutorflow slide create "My first deck"
29
31
  ```
30
32
 
@@ -64,33 +66,36 @@ pnpm dev -- <command> [options]
64
66
 
65
67
  ## Releasing
66
68
 
67
- Releases are fully automated via tag-driven GitHub Actions. Auth uses **npm OIDC Trusted Publishing** — no `NPM_TOKEN` secret in CI.
69
+ Releases are automated by GitHub Actions on pushes to `master` / `main`.
70
+ Auth uses **npm OIDC Trusted Publishing** — no `NPM_TOKEN` secret in CI.
68
71
 
69
72
  ```bash
70
73
  git checkout master
71
74
  git pull
72
75
 
73
- npm version patch # 0.1.2 → 0.1.3 (or minor / major)
74
- git push origin master --follow-tags # tag triggers the Release workflow
76
+ npm version patch --no-git-tag-version # 0.3.0 → 0.3.1 (or minor / major)
77
+ git push origin master # Release workflow publishes if that version is not on npm yet
75
78
  ```
76
79
 
77
- The [`Release` workflow](.github/workflows/release.yml) runs on tags matching `v*.*.*` and:
80
+ The [`Release` workflow](.github/workflows/release.yml):
78
81
 
79
- 1. Verifies `package.json` version matches the git tag
80
- 2. `pnpm typecheck` + `pnpm build` + `pnpm test`
81
- 3. `npm publish --access public` (auth via OIDC)
82
- 4. Creates a GitHub Release with auto-generated notes
82
+ 1. Reads `package.json` name and version
83
+ 2. Skips npm publish if that exact version already exists
84
+ 3. Runs `pnpm typecheck` + `pnpm build` + `pnpm test`
85
+ 4. Publishes new versions with `npm publish --access public` (auth via OIDC)
86
+ 5. Creates a GitHub Release only for `v*.*.*` tag pushes
83
87
 
84
88
  For full setup (npm org, Trusted Publisher config) see [RELEASING.md](RELEASING.md).
85
89
 
86
90
  ### Pre-release / beta
87
91
 
88
92
  ```bash
89
- npm version prerelease --preid=beta # 0.1.3 → 0.1.4-beta.0
90
- git push origin master --follow-tags
93
+ npm version prerelease --preid=beta --no-git-tag-version # 0.3.1 → 0.3.2-beta.0
94
+ git push origin master
91
95
  ```
92
96
 
93
- **Note:** the workflow currently publishes everything to `latest`. To route beta tags to a separate dist-tag, see the snippet in [RELEASING.md](RELEASING.md#pre-release-channels).
97
+ Pre-release versions publish to a dist-tag derived from the prerelease id
98
+ (`0.3.1-beta.0` publishes with `--tag beta`).
94
99
 
95
100
  ## ⚠️ Caveats & gotchas
96
101
 
@@ -103,7 +108,7 @@ These tripped us up during initial setup. Read before changing release infrastru
103
108
 
104
109
  ### npm Trusted Publishing (OIDC)
105
110
 
106
- - **npm CLI must be 11.5.1+** for OIDC auth. Node 20.x ships with npm 10.x, so the workflow runs `npm install -g npm@latest` before publish. Removing that step will break publishes with a misleading `404 Not Found` (npm hides auth failures as 404s to prevent enumeration).
111
+ - **npm CLI must be 11.5.1+** for OIDC auth. npm also requires a modern Node 22 runtime for trusted publishing, so the workflow uses Node 22.x and invokes `pnpm dlx npm@latest ...` for registry checks and publish. Do not replace that with the runner's bundled npm unless you verify its version supports OIDC trusted publishing.
107
112
  - The Trusted Publisher binding at [npmjs.com/package/@tutorflow/cli/access](https://www.npmjs.com/package/@tutorflow/cli/access) hardcodes:
108
113
  - GitHub org: `tutorflow-io`
109
114
  - Repo: `cli`
@@ -119,8 +124,7 @@ These tripped us up during initial setup. Read before changing release infrastru
119
124
 
120
125
  ### Node + tooling
121
126
 
122
- - **Vitest 4.x requires Node 20+** (uses `node:util.styleText`). The CI matrix dropped Node 18 for this reason. The runtime CLI itself still supports Node 18 (declared in `package.json#engines`).
123
- - `actions/setup-node@v4` and friends emit Node 20 deprecation warnings. They'll be force-upgraded to Node 24 on June 2, 2026.
127
+ - **Vitest 4.x requires Node 20+** (uses `node:util.styleText`). CI tests Node 20 and Node 22, while release publishing runs on Node 22 for npm OIDC. The runtime CLI itself still supports Node 18 (declared in `package.json#engines`).
124
128
 
125
129
  ### Tarball hygiene
126
130
 
@@ -203,6 +207,13 @@ The error JSON includes a stable `code`: `EAUTH`, `EINVAL`, `ENOINTERACTIVE`, `E
203
207
  Commands that have required input expose every prompt as a flag:
204
208
 
205
209
  ```bash
210
+ # self-register a platform workspace and save the returned API key
211
+ tutorflow --json agent register \
212
+ --name "Agent Workspace" \
213
+ --slug agent-workspace \
214
+ --email agent@example.com \
215
+ --agent-identity "codex"
216
+
206
217
  # slide / video / course create — accept positional [prompt]
207
218
  tutorflow --json slide create "Photosynthesis" -n 12 -l en
208
219
  tutorflow --json video create "Newton's laws" -s 6 -r 16:9 -d 90
@@ -210,7 +221,7 @@ tutorflow --json course create "Beginner Python" -l 10 -lang en
210
221
 
211
222
  # evaluate — every input is a flag
212
223
  tutorflow --json evaluate \
213
- --type rubric \
224
+ --type exact \
214
225
  --question "What is 2+2?" \
215
226
  --student-answer "4" \
216
227
  --expected-answer "4"
@@ -254,7 +265,7 @@ Credentials are persisted to `~/.tutorflow/config.json`:
254
265
  }
255
266
  ```
256
267
 
257
- The API key is sent as the `X-API-Key` header on every request.
268
+ The API key is sent as the `Authorization: Bearer <apiKey>` header on authenticated requests.
258
269
 
259
270
  ### Config schema
260
271
 
@@ -287,6 +298,104 @@ tutorflow config set <key> <value> # update one key
287
298
  All resource commands require authentication. Without an API key they print:
288
299
  `✗ Not authenticated. Run "tutorflow auth login" first.`
289
300
 
301
+ ### `tutorflow agent`
302
+
303
+ Manage the agent-facing TutorFlow Platform account flow.
304
+
305
+ #### `agent register`
306
+
307
+ Public self-service registration. Creates a platform workspace through
308
+ `POST /v1/platform/agent/register`, returns the one-time API key, and saves it
309
+ to `~/.tutorflow/config.json` by default so the next CLI command can run
310
+ without a separate `auth login`.
311
+
312
+ | Option | Type | Default | Description |
313
+ | ------------------------------ | -------- | ------- | -------------------------------------------- |
314
+ | `--name <name>` | `string` | — | Workspace display name |
315
+ | `--slug <slug>` | `string` | — | Unique lowercase slug |
316
+ | `--email <email>` | `string` | none | Contact email for verification and billing |
317
+ | `--agent-identity <identity>` | `string` | none | Optional agent identity string |
318
+ | `--no-save` | boolean | false | Print the API key but do not persist it |
319
+
320
+ ```bash
321
+ tutorflow --json agent register \
322
+ --name "Agent Workspace" \
323
+ --slug agent-workspace \
324
+ --email agent@example.com \
325
+ --agent-identity "codex"
326
+ ```
327
+
328
+ #### `agent account`
329
+
330
+ GET `/v1/platform/agent/account`. Shows workspace status, credit balance,
331
+ email verification state, rate limits, and `restrictedActions`.
332
+
333
+ ```bash
334
+ tutorflow --json agent account
335
+ ```
336
+
337
+ #### `agent billing status`
338
+
339
+ GET `/v1/platform/agent/billing/status`. Shows payment-method state, credit
340
+ balance, billing mode, email verification state, and `restrictedActions`.
341
+
342
+ ```bash
343
+ tutorflow --json agent billing status
344
+ ```
345
+
346
+ #### `agent billing session`
347
+
348
+ POST `/v1/platform/agent/billing/session`. Returns a TutorFlow-hosted checkout
349
+ URL that an agent should forward to a human operator.
350
+
351
+ ```bash
352
+ tutorflow --json agent billing session
353
+ ```
354
+
355
+ #### `agent verify-email resend`
356
+
357
+ POST `/v1/platform/agent/verify-email/resend`. Resends the workspace email
358
+ verification message using the active API key.
359
+
360
+ ```bash
361
+ tutorflow --json agent verify-email resend
362
+ ```
363
+
364
+ #### `agent checkout info`
365
+
366
+ GET `/v1/platform/agent/checkout?token=<token>`. Reads workspace info for a
367
+ TutorFlow checkout token returned through the hosted billing-session flow.
368
+
369
+ ```bash
370
+ tutorflow --json agent checkout info --token checkout_123
371
+ ```
372
+
373
+ #### `agent checkout create`
374
+
375
+ POST `/v1/platform/agent/checkout`. Creates a Stripe Checkout URL from a
376
+ TutorFlow checkout token and amount. This is normally called by the hosted
377
+ checkout page; CLI support exists for complete automation and testing.
378
+
379
+ ```bash
380
+ tutorflow --json agent checkout create --token checkout_123 --amount-usd 25
381
+ ```
382
+
383
+ ### `tutorflow platform`
384
+
385
+ Inspect public discovery metadata and validate the active Platform API key.
386
+
387
+ | Subcommand | Endpoint | Auth |
388
+ | ---------- | -------- | ---- |
389
+ | `manifest` | `GET /v1/platform/.well-known/agent.json` | none |
390
+ | `pricing` | `GET /v1/platform/pricing-catalog` | none |
391
+ | `health` | `GET /v1/platform/health` | Platform API key |
392
+
393
+ ```bash
394
+ tutorflow --json platform manifest
395
+ tutorflow --json platform pricing
396
+ tutorflow --json platform health
397
+ ```
398
+
290
399
  ### `tutorflow slide`
291
400
 
292
401
  Create and manage slide decks.
@@ -428,36 +537,142 @@ Opens the course preview URL in the browser.
428
537
 
429
538
  ---
430
539
 
540
+ ### `tutorflow module`
541
+
542
+ Create and manage standalone lesson modules.
543
+
544
+ #### `module create [prompt]`
545
+
546
+ POST `/v1/platform/modules`. Generates one classroom-compatible standalone
547
+ lesson. `--idempotency-key` is sent as the `Idempotency-Key` header so agents
548
+ can safely retry a create call.
549
+
550
+ | Argument / Option | Type | Default | Description |
551
+ | ------------------------------ | --------------------- | -------- | -------------------------------- |
552
+ | `[prompt]` | `string` (positional) | — | Lesson/module prompt |
553
+ | `--title <title>` | `string` | none | Override generated title |
554
+ | `--description <description>` | `string` | none | Override generated description |
555
+ | `--target <target>` | `string` | none | Target learner audience |
556
+ | `--type <type>` | `string` | `lesson` | Module type |
557
+ | `--locale <locale>` | `string` | `en` | Locale code |
558
+ | `--language <language>` | `string` | `en` | Language code |
559
+ | `--slug <slug>` | `string` | none | Optional slug |
560
+ | `--private` | boolean | false | Set `isPublic: false` |
561
+ | `--no-quiz` | boolean | false | Set `hasQuiz: false` |
562
+ | `--idempotency-key <key>` | `string` | none | Safe retry key |
563
+
564
+ ```bash
565
+ tutorflow --json module create "Fractions for 5th grade" \
566
+ --title "Fractions" \
567
+ --target "5th grade" \
568
+ --no-quiz \
569
+ --idempotency-key lesson-001
570
+ ```
571
+
572
+ #### `module list`
573
+
574
+ GET `/v1/platform/modules?limit=<n>&offset=<n>[&search=<q>]`.
575
+
576
+ ```bash
577
+ tutorflow --json module list --limit 20 --offset 0 --search fractions
578
+ ```
579
+
580
+ #### `module get <id>` / `module open <id>`
581
+
582
+ Fetch a module by ID or open its `publicUrl`.
583
+
584
+ ---
585
+
586
+ ### `tutorflow test`
587
+
588
+ Create and manage generated assessments.
589
+
590
+ #### `test create [prompt]`
591
+
592
+ POST `/v1/platform/tests`. Generates a test/assessment. `--idempotency-key` is
593
+ sent as the `Idempotency-Key` header.
594
+
595
+ | Argument / Option | Type | Default | Description |
596
+ | ------------------------- | --------------------- | ---------- | ------------------------------ |
597
+ | `[prompt]` | `string` (positional) | — | Test generation prompt |
598
+ | `--title <title>` | `string` | none | Override generated title |
599
+ | `--description <text>` | `string` | none | Override generated description |
600
+ | `-l, --language <lang>` | `string` | `en` | Language code |
601
+ | `--level <level>` | `string` | none | Difficulty level |
602
+ | `--subject <subject>` | `string` | none | Subject area |
603
+ | `-n, --items <number>` | `string -> int` | none | Target item count |
604
+ | `--time-limit <minutes>` | `string -> int` | none | Time limit in minutes |
605
+ | `--classroom-id <id>` | `string` | none | Classroom ID |
606
+ | `--tier <tier>` | `string` | `standard` | Pricing tier |
607
+ | `--mode <mode>` | `string` | `sync` | `sync` or `async` |
608
+ | `--idempotency-key <key>` | `string` | none | Safe retry key |
609
+
610
+ ```bash
611
+ tutorflow --json test create "Algebra quiz" \
612
+ --title "Algebra Basics" \
613
+ --items 8 \
614
+ --time-limit 30 \
615
+ --idempotency-key test-001
616
+ ```
617
+
618
+ #### `test list`
619
+
620
+ GET `/v1/platform/tests?limit=<n>&offset=<n>[&status=<s>]`.
621
+
622
+ ```bash
623
+ tutorflow --json test list --limit 20 --status READY
624
+ ```
625
+
626
+ #### `test get <id>` / `test open <id>` / `test edit-token <id>`
627
+
628
+ Fetch a test, open its preview URL, or generate a fresh edit token.
629
+
630
+ ---
631
+
431
632
  ### `tutorflow evaluate`
432
633
 
433
- Evaluates a single student response. Fully interactive; only the type can be passed as a flag.
634
+ Evaluates a single learner response through the Platform Evaluations API.
434
635
 
435
- | Option | Type | Default | Allowed values |
436
- | ------------------- | -------- | ---------- | ------------------------------- |
437
- | `-t, --type <type>` | `string` | (prompted) | `exact`, `rubric`, `open-ended` |
636
+ | Option | Type | Default | Allowed values / notes |
637
+ | ------------------------- | -------- | ---------- | ---------------------- |
638
+ | `-t, --type <type>` | `string` | (prompted) | `exact`, `rubric_short_answer`, `open_ended`. Aliases: `rubric`, `open-ended` |
639
+ | `-q, --question <text>` | `string` | (prompted) | Question text |
640
+ | `-a, --student-answer <text>` | `string` | (prompted) | Learner answer |
641
+ | `-e, --expected-answer <text>` | `string` | none | Required for `exact`; sent as `referenceAnswer` |
642
+ | `--rubric-json <json>` | `string` | none | Required for `rubric_short_answer` |
643
+ | `--max-score <number>` | `number` | backend default | Maximum score |
644
+ | `-l, --language <lang>` | `string` | `en` | Feedback language |
645
+ | `--idempotency-key <key>` | `string` | none | Safe retry key |
438
646
 
439
647
  Interactive flow:
440
648
 
441
649
  1. Type (if not supplied)
442
650
  2. Question
443
651
  3. Student answer
444
- 4. Expected answer — **skipped** when type is `open-ended`
652
+ 4. Expected answer — required only when type is `exact`
445
653
 
446
- POST `/v1/platform/evaluate` body:
654
+ POST `/v1/platform/evaluations` body:
447
655
 
448
656
  ```json
449
657
  {
450
- "evaluationType": "rubric",
451
- "question": "...",
452
- "studentAnswer": "...",
453
- "expectedAnswer": "..."
658
+ "evaluationType": "exact",
659
+ "questionText": "What is 2+2?",
660
+ "learnerAnswer": "4",
661
+ "referenceAnswer": "4",
662
+ "language": "en",
663
+ "mode": "sync"
454
664
  }
455
665
  ```
456
666
 
457
- `expectedAnswer` is omitted when `evaluationType` is `open-ended`. Response prints `score` and `feedback`.
667
+ `referenceAnswer` is omitted when `evaluationType` is `open_ended`.
668
+ `rubric_short_answer` requires `--rubric-json`, for example:
458
669
 
459
670
  ```bash
460
- tutorflow evaluate -t open-ended
671
+ tutorflow --json evaluate \
672
+ --type rubric_short_answer \
673
+ --question "Explain the water cycle" \
674
+ --student-answer "Water evaporates and condenses." \
675
+ --rubric-json '{"criteria":[{"name":"Accuracy","description":"Scientific correctness","maxScore":10}]}'
461
676
  ```
462
677
 
463
678
  ---
@@ -490,7 +705,7 @@ class ApiClient {
490
705
  ```
491
706
 
492
707
  - Uses [`undici.fetch`](https://github.com/nodejs/undici).
493
- - Headers always include `Content-Type: application/json` and `X-API-Key: <apiKey>`.
708
+ - Headers always include `Content-Type: application/json`. Authenticated requests also include `Authorization: Bearer <apiKey>`.
494
709
  - Throws `Error('API Error: <status> <body>')` on non-2xx.
495
710
 
496
711
  ## Project layout
@@ -502,7 +717,7 @@ class ApiClient {
502
717
  ├── vitest.config.ts
503
718
  ├── .github/workflows/
504
719
  │ ├── ci.yml # typecheck + build + test on PRs and master
505
- │ └── release.yml # OIDC publish on v*.*.* tags
720
+ │ └── release.yml # OIDC publish on master/main pushes when version is new
506
721
  ├── RELEASING.md # full release procedure + Trusted Publisher setup
507
722
  └── src/
508
723
  ├── index.ts # commander entrypoint, registers all commands
@@ -512,11 +727,15 @@ class ApiClient {
512
727
  ├── config.test.ts
513
728
  ├── types.ts # API response interfaces (SlideResource, etc.)
514
729
  ├── commands/
730
+ │ ├── agent.ts # register / account / billing / email verification
515
731
  │ ├── auth.ts # login / logout / whoami
516
732
  │ ├── config.ts # get / set
517
733
  │ ├── course.ts # create / list / open
518
734
  │ ├── evaluate.ts # interactive evaluation
735
+ │ ├── module.ts # standalone lesson modules
736
+ │ ├── platform.ts # discovery / pricing / health
519
737
  │ ├── slide.ts # create / list / open
738
+ │ ├── test.ts # generated assessments
520
739
  │ └── video.ts # create / list / open
521
740
  └── utils/
522
741
  ├── output.ts # formatTable, formatJson
package/dist/client.d.ts CHANGED
@@ -6,13 +6,14 @@ export declare class ApiClient {
6
6
  private config;
7
7
  constructor(config?: IClientConfig);
8
8
  static create(): Promise<ApiClient>;
9
+ static createPublic(): Promise<ApiClient>;
9
10
  /**
10
11
  * Like `create` but throws CliError if no API key is resolvable. Use this
11
12
  * in any command that talks to the API so we get a single, consistent
12
13
  * "not authenticated" path.
13
14
  */
14
15
  static createAuthenticated(): Promise<ApiClient>;
15
- request<T>(method: string, endpoint: string, body?: Record<string, unknown>): Promise<T>;
16
+ request<T>(method: string, endpoint: string, body?: Record<string, unknown>, extraHeaders?: Record<string, string>): Promise<T>;
16
17
  setApiKey(apiKey: string): void;
17
18
  setBaseUrl(baseUrl: string): void;
18
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAqBD,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAgB;gBAElB,MAAM,CAAC,EAAE,aAAa;WAIrB,MAAM,IAAI,OAAO,CAAC,SAAS,CAAC;IAIzC;;;;OAIG;WACU,mBAAmB,IAAI,OAAO,CAAC,SAAS,CAAC;IAWhD,OAAO,CAAC,CAAC,EACb,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAAC,CAAC,CAAC;IAuCb,SAAS,CAAC,MAAM,EAAE,MAAM;IAIxB,UAAU,CAAC,OAAO,EAAE,MAAM;CAG3B"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAqBD,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAgB;gBAElB,MAAM,CAAC,EAAE,aAAa;WAIrB,MAAM,IAAI,OAAO,CAAC,SAAS,CAAC;WAI5B,YAAY,IAAI,OAAO,CAAC,SAAS,CAAC;IAK/C;;;;OAIG;WACU,mBAAmB,IAAI,OAAO,CAAC,SAAS,CAAC;IAWhD,OAAO,CAAC,CAAC,EACb,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACpC,OAAO,CAAC,CAAC,CAAC;IA4Cb,SAAS,CAAC,MAAM,EAAE,MAAM;IAIxB,UAAU,CAAC,OAAO,EAAE,MAAM;CAG3B"}
package/dist/client.js CHANGED
@@ -27,6 +27,10 @@ class ApiClient {
27
27
  static async create() {
28
28
  return new ApiClient(await resolveConfig());
29
29
  }
30
+ static async createPublic() {
31
+ const config = await resolveConfig();
32
+ return new ApiClient({ ...config, apiKey: '' });
33
+ }
30
34
  /**
31
35
  * Like `create` but throws CliError if no API key is resolvable. Use this
32
36
  * in any command that talks to the API so we get a single, consistent
@@ -39,14 +43,18 @@ class ApiClient {
39
43
  }
40
44
  return new ApiClient(config);
41
45
  }
42
- async request(method, endpoint, body) {
46
+ async request(method, endpoint, body, extraHeaders) {
43
47
  const url = `${this.config.baseUrl}${endpoint}`;
48
+ const headers = {
49
+ 'Content-Type': 'application/json',
50
+ ...extraHeaders,
51
+ };
52
+ if (this.config.apiKey) {
53
+ headers.Authorization = `Bearer ${this.config.apiKey}`;
54
+ }
44
55
  const init = {
45
56
  method,
46
- headers: {
47
- 'Content-Type': 'application/json',
48
- 'X-API-Key': this.config.apiKey,
49
- },
57
+ headers,
50
58
  };
51
59
  if (body)
52
60
  init.body = JSON.stringify(body);
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function agentCommand(): Command;
3
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/commands/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuBpC,wBAAgB,YAAY,IAAI,OAAO,CAiKtC"}
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.agentCommand = agentCommand;
4
+ const commander_1 = require("commander");
5
+ const prompts_1 = require("@clack/prompts");
6
+ const client_1 = require("../client");
7
+ const config_1 = require("../config");
8
+ const output_1 = require("../utils/output");
9
+ const runtime_1 = require("../utils/runtime");
10
+ const DEFAULT_BASE_URL = 'https://api.tutorflow.io';
11
+ function agentCommand() {
12
+ const agent = new commander_1.Command('agent').description('Manage TutorFlow agent platform account');
13
+ agent
14
+ .command('register')
15
+ .description('Self-register a TutorFlow Platform workspace and receive an API key')
16
+ .option('--name <name>', 'Workspace display name')
17
+ .option('--slug <slug>', 'Unique workspace slug')
18
+ .option('--email <email>', 'Contact email for the workspace')
19
+ .option('--agent-identity <identity>', 'Optional agent identity string')
20
+ .option('--no-save', 'Do not save the returned API key to ~/.tutorflow/config.json')
21
+ .action((0, runtime_1.command)(async (options) => {
22
+ const name = await requiredOptionOrPrompt(options.name, 'Workspace display name:', '--name <name>');
23
+ const slug = await requiredOptionOrPrompt(options.slug, 'Workspace slug:', '--slug <slug>');
24
+ const baseUrl = await resolveBaseUrl();
25
+ const client = await client_1.ApiClient.createPublic();
26
+ const body = {
27
+ name,
28
+ slug,
29
+ email: options.email,
30
+ agentIdentity: options.agentIdentity,
31
+ };
32
+ Object.keys(body).forEach((key) => {
33
+ if (body[key] === undefined || body[key] === '')
34
+ delete body[key];
35
+ });
36
+ const response = await client.request('POST', '/v1/platform/agent/register', body);
37
+ if (options.save !== false) {
38
+ await (0, config_1.updateConfig)({ apiKey: response.apiKey, baseUrl });
39
+ }
40
+ (0, output_1.printResult)(response);
41
+ }));
42
+ agent
43
+ .command('account')
44
+ .description('Show the authenticated agent account')
45
+ .action((0, runtime_1.command)(async () => {
46
+ const client = await client_1.ApiClient.createAuthenticated();
47
+ const response = await client.request('GET', '/v1/platform/agent/account');
48
+ (0, output_1.printResult)(response);
49
+ }));
50
+ const billing = new commander_1.Command('billing').description('Manage agent billing');
51
+ billing
52
+ .command('status')
53
+ .description('Show billing status and currently restricted actions')
54
+ .action((0, runtime_1.command)(async () => {
55
+ const client = await client_1.ApiClient.createAuthenticated();
56
+ const response = await client.request('GET', '/v1/platform/agent/billing/status');
57
+ (0, output_1.printResult)(response);
58
+ }));
59
+ billing
60
+ .command('session')
61
+ .description('Create a TutorFlow-hosted checkout session URL')
62
+ .action((0, runtime_1.command)(async () => {
63
+ const client = await client_1.ApiClient.createAuthenticated();
64
+ const response = await client.request('POST', '/v1/platform/agent/billing/session');
65
+ (0, output_1.printResult)(response);
66
+ }));
67
+ agent.addCommand(billing);
68
+ const checkout = new commander_1.Command('checkout').description('Use public checkout token endpoints');
69
+ checkout
70
+ .command('info')
71
+ .description('Read workspace info for a TutorFlow checkout token')
72
+ .requiredOption('--token <token>', 'Checkout token from agent billing session URL')
73
+ .action((0, runtime_1.command)(async (options) => {
74
+ const client = await client_1.ApiClient.createPublic();
75
+ const qs = new URLSearchParams({ token: options.token });
76
+ const response = await client.request('GET', `/v1/platform/agent/checkout?${qs.toString()}`);
77
+ (0, output_1.printResult)(response);
78
+ }));
79
+ checkout
80
+ .command('create')
81
+ .description('Create a Stripe Checkout URL from a TutorFlow checkout token')
82
+ .requiredOption('--token <token>', 'Checkout token from agent billing session URL')
83
+ .requiredOption('--amount-usd <amount>', 'Top-up amount in USD')
84
+ .action((0, runtime_1.command)(async (options) => {
85
+ const amountUsd = Number.parseFloat(options.amountUsd);
86
+ if (!Number.isFinite(amountUsd)) {
87
+ throw new runtime_1.CliError('--amount-usd must be a number', {
88
+ code: 'EINVAL',
89
+ exitCode: 2,
90
+ });
91
+ }
92
+ const client = await client_1.ApiClient.createPublic();
93
+ const response = await client.request('POST', '/v1/platform/agent/checkout', { token: options.token, amountUsd });
94
+ (0, output_1.printResult)(response);
95
+ }));
96
+ agent.addCommand(checkout);
97
+ const verifyEmail = new commander_1.Command('verify-email').description('Manage agent email verification');
98
+ verifyEmail
99
+ .command('resend')
100
+ .description('Resend the platform email verification message')
101
+ .action((0, runtime_1.command)(async () => {
102
+ const client = await client_1.ApiClient.createAuthenticated();
103
+ const response = await client.request('POST', '/v1/platform/agent/verify-email/resend');
104
+ (0, output_1.printResult)(response);
105
+ }));
106
+ agent.addCommand(verifyEmail);
107
+ return agent;
108
+ }
109
+ async function requiredOptionOrPrompt(value, message, flagHint) {
110
+ if (value?.trim())
111
+ return value.trim();
112
+ (0, runtime_1.requireInteractive)(`Pass ${flagHint}.`);
113
+ const result = await (0, prompts_1.text)({ message });
114
+ if (!result || typeof result === 'symbol') {
115
+ throw new runtime_1.CliError('Cancelled', { code: 'ECANCELLED', exitCode: 130 });
116
+ }
117
+ return result;
118
+ }
119
+ async function resolveBaseUrl() {
120
+ const fileConfig = await (0, config_1.readConfig)();
121
+ return process.env.TUTORFLOW_BASE_URL ?? fileConfig.baseUrl ?? DEFAULT_BASE_URL;
122
+ }
123
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/commands/agent.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"course.d.ts","sourceRoot":"","sources":["../../src/commands/course.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBpC,wBAAgB,aAAa,IAAI,OAAO,CA2GvC"}
1
+ {"version":3,"file":"course.d.ts","sourceRoot":"","sources":["../../src/commands/course.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoBpC,wBAAgB,aAAa,IAAI,OAAO,CAgHvC"}
@@ -53,10 +53,15 @@ function courseCommand() {
53
53
  course
54
54
  .command('list')
55
55
  .option('-l, --limit <number>', 'Number of results', '10')
56
+ .option('-o, --offset <number>', 'Number of rows to skip', '0')
57
+ .option('-s, --status <status>', 'Filter by status')
56
58
  .action((0, runtime_1.command)(async (options) => {
57
59
  const client = await client_1.ApiClient.createAuthenticated();
58
- const response = await client.request('GET', `/v1/platform/courses?limit=${options.limit}`);
59
- const courses = response.data ?? [];
60
+ const qs = new URLSearchParams({ limit: options.limit, offset: options.offset });
61
+ if (options.status)
62
+ qs.set('status', options.status);
63
+ const response = await client.request('GET', `/v1/platform/courses?${qs.toString()}`);
64
+ const courses = Array.isArray(response) ? response : response.items ?? response.data ?? [];
60
65
  if ((0, runtime_1.isJsonMode)()) {
61
66
  (0, output_1.printResult)(courses);
62
67
  }