trakt-tools 1.9.5 → 1.11.0

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,7 @@ Or set `TRAKT_CLI_PATH` environment variable, or configure `cliPath` in plugin s
25
25
  | `cliPath` | Path to trakt-cli binary (auto-detected on PATH) |
26
26
  | `clientId` | Trakt API client ID (from https://trakt.tv/oauth/applications) |
27
27
  | `clientSecret` | Trakt API client secret |
28
+ | `syncEnabled` | Register the opt-in `trakt_sync` tool (default `false`) |
28
29
 
29
30
  ## Available Tools
30
31
 
@@ -36,6 +37,7 @@ Or set `TRAKT_CLI_PATH` environment variable, or configure `cliPath` in plugin s
36
37
  | `trakt_watchlist` | View watchlist |
37
38
  | `trakt_progress` | Show watch progress for TV shows |
38
39
  | `trakt_auth` | Set up Trakt.tv authentication |
40
+ | `trakt_sync` | Opt-in: import from streaming services (only when `syncEnabled`) |
39
41
 
40
42
  ## License
41
43
 
package/dist/index.js CHANGED
@@ -29,6 +29,16 @@ function whichBinary(name) {
29
29
  }
30
30
 
31
31
  // src/index.ts
32
+ var SYNC_TOOL = {
33
+ name: "trakt_sync",
34
+ command: "sync",
35
+ description: "Import watched items from streaming services (Apple TV Up Next, Netflix, HBO Max, Paramount+) into Trakt history, using the sync config at ~/.config/trakt-cli/sync.yaml. Skips denied titles, items older than the configured window, and anything already in history. Shows not yet in history and all movies are returned in pending_review and NOT written; ask the user before approving any. Use dry_run first to preview.",
36
+ parameters: Type.Object({
37
+ dry_run: Type.Optional(
38
+ Type.Boolean({ description: "Preview what would be added without writing (default false)" })
39
+ )
40
+ })
41
+ };
32
42
  var TOOLS = [
33
43
  {
34
44
  name: "trakt_search",
@@ -262,12 +272,13 @@ var index_default = definePluginEntry({
262
272
  description: "Track movies and TV shows using trakt.tv",
263
273
  register(api) {
264
274
  const config = api.pluginConfig;
275
+ const tools = config?.syncEnabled ? [...TOOLS, SYNC_TOOL] : TOOLS;
265
276
  let cliPath;
266
277
  try {
267
278
  cliPath = resolveCliPath(config);
268
279
  } catch (error) {
269
280
  const errorMessage = error instanceof Error ? error.message : String(error);
270
- for (const tool of TOOLS) {
281
+ for (const tool of tools) {
271
282
  api.registerTool({
272
283
  name: tool.name,
273
284
  label: tool.name,
@@ -282,7 +293,7 @@ var index_default = definePluginEntry({
282
293
  }
283
294
  return;
284
295
  }
285
- for (const tool of TOOLS) {
296
+ for (const tool of tools) {
286
297
  api.registerTool({
287
298
  name: tool.name,
288
299
  label: tool.name,
@@ -304,7 +315,8 @@ var index_default = definePluginEntry({
304
315
  try {
305
316
  const args = buildCliArgs(tool.command, tool.subcommand, params, config);
306
317
  const { stdout } = await runCli(cliPath, args, {
307
- timeout: 12e4,
318
+ // sync walks several services plus per-show history lookups.
319
+ timeout: tool.command === "sync" ? 6e5 : 12e4,
308
320
  maxBuffer: 4 * 1024 * 1024
309
321
  });
310
322
  let result;
@@ -2,7 +2,7 @@
2
2
  "id": "trakt-tools",
3
3
  "name": "Trakt",
4
4
  "description": "Track movies and TV shows using trakt.tv",
5
- "version": "1.9.5",
5
+ "version": "1.11.0",
6
6
  "configSchema": {
7
7
  "type": "object",
8
8
  "properties": {
@@ -18,6 +18,11 @@
18
18
  "clientSecret": {
19
19
  "type": "string",
20
20
  "description": "Trakt API client secret"
21
+ },
22
+ "syncEnabled": {
23
+ "type": "boolean",
24
+ "description": "Opt in to the trakt_sync tool (imports from streaming services). Off by default.",
25
+ "default": false
21
26
  }
22
27
  },
23
28
  "additionalProperties": false
@@ -37,6 +42,10 @@
37
42
  "label": "Client Secret",
38
43
  "help": "Trakt API client secret from https://trakt.tv/oauth/applications",
39
44
  "sensitive": true
45
+ },
46
+ "syncEnabled": {
47
+ "label": "Enable streaming sync",
48
+ "help": "Registers trakt_sync. Also requires ~/.config/trakt-cli/sync.yaml with enabled: true; see `trakt-cli sync --help`."
40
49
  }
41
50
  },
42
51
  "contracts": {
@@ -50,7 +59,8 @@
50
59
  "trakt_watchlist_remove",
51
60
  "trakt_calendar",
52
61
  "trakt_progress",
53
- "trakt_auth"
62
+ "trakt_auth",
63
+ "trakt_sync"
54
64
  ]
55
65
  }
56
66
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trakt-tools",
3
- "version": "1.9.5",
3
+ "version": "1.11.0",
4
4
  "description": "OpenClaw plugin for Trakt.tv - track movies and TV shows",
5
5
  "type": "module",
6
6
  "openclaw": {
@@ -36,7 +36,7 @@
36
36
  ],
37
37
  "author": {
38
38
  "name": "Omar Shahine",
39
- "email": "omar@shahine.com"
39
+ "email": "10343873+omarshahine@users.noreply.github.com"
40
40
  },
41
41
  "license": "MIT",
42
42
  "repository": {
@@ -98,6 +98,21 @@ trakt-cli history add --rewatch "Severance" --json
98
98
  and exits 1 with `{"error": ..., "retry_after": N}` (marker also on
99
99
  stderr) — wait out `retry_after` before calling any trakt tool again
100
100
 
101
+ ### Streaming Sync (opt-in)
102
+
103
+ Only if the user has set up `~/.config/trakt-cli/sync.yaml` (otherwise `sync` reports `"enabled": false` and does nothing).
104
+
105
+ ```bash
106
+ trakt-cli sync --dry-run --json
107
+ trakt-cli sync --json
108
+ trakt-cli sync approve "Title"
109
+ trakt-cli sync deny "Title"
110
+ ```
111
+
112
+ - JSON output: `{ "enabled", "sources": {name: {items, error}}, "planned", "pending_review", "skipped_denied", "skipped_old", "already_watched", "unresolved", "added" }`
113
+ - Confirmed episodes of shows already in history sync automatically; new shows, all movies, and implied episodes (e.g. skipped ones before an Up Next pointer) land in `pending_review` and are NOT written. Ask the user before running `sync approve` for any title; never approve on their behalf
114
+ - Use `sync deny` for titles the user says belong to someone else
115
+
101
116
  ### Search
102
117
 
103
118
  ```bash
@@ -116,6 +131,7 @@ trakt-cli search "Inception" --type movie --json
116
131
 
117
132
  ## Changelog
118
133
 
134
+ - **v2.3.0** — Add opt-in `sync` (`trakt_sync` tool, only when `syncEnabled`): imports watched items from Apple TV Up Next, Netflix, HBO Max and Paramount+ with a deny list, profile checks, and a `pending_review` queue (`sync approve` / `sync deny`) for new shows, movies and implied episodes
119
135
  - **v2.0.0** — Add `progress` command, `--json` flag for all commands (agent-friendly output)
120
136
  - **v1.1.0** — Add `watchlist` command, `--type` filter for `history`, `history add` with `--watched-at`
121
137
  - **v1.0.0** — Initial skill (upstream `history` and `search` only)
package/src/index.ts CHANGED
@@ -16,6 +16,8 @@ interface PluginConfig {
16
16
  cliPath?: string;
17
17
  clientId?: string;
18
18
  clientSecret?: string;
19
+ /** Opt-in: register trakt_sync. Off by default so existing installs are unchanged. */
20
+ syncEnabled?: boolean;
19
21
  }
20
22
 
21
23
  interface ToolDef {
@@ -26,6 +28,20 @@ interface ToolDef {
26
28
  parameters: ReturnType<typeof Type.Object>;
27
29
  }
28
30
 
31
+ // Opt-in streaming sync tool. Registered only when pluginConfig.syncEnabled is
32
+ // true; the CLI itself also stays inert without ~/.config/trakt-cli/sync.yaml.
33
+ const SYNC_TOOL: ToolDef = {
34
+ name: 'trakt_sync',
35
+ command: 'sync',
36
+ description:
37
+ 'Import watched items from streaming services (Apple TV Up Next, Netflix, HBO Max, Paramount+) into Trakt history, using the sync config at ~/.config/trakt-cli/sync.yaml. Skips denied titles, items older than the configured window, and anything already in history. Shows not yet in history and all movies are returned in pending_review and NOT written; ask the user before approving any. Use dry_run first to preview.',
38
+ parameters: Type.Object({
39
+ dry_run: Type.Optional(
40
+ Type.Boolean({ description: 'Preview what would be added without writing (default false)' })
41
+ ),
42
+ }),
43
+ };
44
+
29
45
  // Tool metadata — each maps to a CLI subcommand
30
46
  const TOOLS: ToolDef[] = [
31
47
  {
@@ -306,6 +322,7 @@ export default definePluginEntry({
306
322
 
307
323
  register(api) {
308
324
  const config = api.pluginConfig as PluginConfig | undefined;
325
+ const tools = config?.syncEnabled ? [...TOOLS, SYNC_TOOL] : TOOLS;
309
326
 
310
327
  let cliPath: string;
311
328
  try {
@@ -314,7 +331,7 @@ export default definePluginEntry({
314
331
  // Defer error to tool execution time — plugin still loads
315
332
  const errorMessage = error instanceof Error ? error.message : String(error);
316
333
 
317
- for (const tool of TOOLS) {
334
+ for (const tool of tools) {
318
335
  api.registerTool({
319
336
  name: tool.name,
320
337
  label: tool.name,
@@ -330,7 +347,7 @@ export default definePluginEntry({
330
347
  return;
331
348
  }
332
349
 
333
- for (const tool of TOOLS) {
350
+ for (const tool of tools) {
334
351
  api.registerTool({
335
352
  name: tool.name,
336
353
  label: tool.name,
@@ -362,7 +379,8 @@ export default definePluginEntry({
362
379
  // Follow-up: parallelize GetShowProgress loop or add a --filter
363
380
  // flag so per-show progress checks don't hammer 50 API calls.
364
381
  const { stdout } = await runCli(cliPath, args, {
365
- timeout: 120_000,
382
+ // sync walks several services plus per-show history lookups.
383
+ timeout: tool.command === 'sync' ? 600_000 : 120_000,
366
384
  maxBuffer: 4 * 1024 * 1024,
367
385
  });
368
386