{"_id":"@27aaron/dsh-wakatime","_rev":"2-b7b6cc8f6208e8487141cb4f036cf853","name":"@27aaron/dsh-wakatime","dist-tags":{"next":"0.3.0","latest":"0.4.0"},"versions":{"0.3.0":{"name":"@27aaron/dsh-wakatime","version":"0.3.0","keywords":["deepseek-harness","dsh","dsh-plugin","wakatime","ai-coding","productivity","time-tracking"],"author":"Aaron","license":"MIT","_id":"@27aaron/dsh-wakatime@0.3.0","maintainers":[{"name":"27aaron","email":"niceboy@duck.com"}],"homepage":"https://github.com/27Aaron/agent-toolkit/tree/main/plugins/dsh-wakatime#readme","bugs":{"url":"https://github.com/27Aaron/agent-toolkit/issues"},"dsh":{"bundle":{"patch":"./cordis.patch.yml"}},"dist":{"shasum":"e816979650a48312e0f90ac22b7a51a94edc3c59","tarball":"https://registry.npmjs.org/@27aaron/dsh-wakatime/-/dsh-wakatime-0.3.0.tgz","fileCount":22,"integrity":"sha512-KaHefpH4d7sORwMoQ4F9R60UfKnlUCrc2ujToAqnxuQ9AiR/oMEXAjkG3aG33a+lmpTGCVl3JVV0cQoNVvV1qQ==","signatures":[{"sig":"MEQCIDmYDjb2eqN3cZvkjbGqUiFhKQpjPChIZdD5MRpzFe0AAiB1B+/LMik8QXVmyMeGwPIzuN8lHqxQwgK+i05RoqTrXw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":157493},"main":"lib/index.js","type":"module","types":"lib/types/index.d.ts","engines":{"node":"^22.19.0 || >=24.0.0"},"exports":{".":{"types":"./lib/types/index.d.ts","default":"./lib/index.js"},"./ui-contract":{"types":"./lib/types/ui-contract.d.ts","default":"./lib/ui-contract.js"},"./package.json":"./package.json"},"scripts":{"test":"vitest run","build":"tsc -p tsconfig.build.json && tsdown","check":"pnpm run typecheck && pnpm run test && pnpm run build && pnpm exec publint","typecheck":"tsc --noEmit","test:watch":"vitest","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"27aaron","email":"niceboy@duck.com"},"repository":{"url":"git+https://github.com/27Aaron/agent-toolkit.git","type":"git","directory":"plugins/dsh-wakatime"},"description":"WakaTime tracking for DeepSeek Harness (headless core; add @27aaron/dsh-wakatime-ui for the web dashboard)","directories":{},"_nodeVersion":"26.7.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsdown":"^0.22.2","vitest":"^4.1.8","publint":"^0.3.21","typescript":"^5.9.3","@types/node":"^22.20.0","@deepseek-ai/cordis":"4.0.1","@vitest/coverage-v8":"^4.1.8","@deepseek-ai/dsh-tools":"0.1.1-rc.2","@deepseek-ai/dsh-session":"0.1.1-rc.2","@deepseek-ai/schemastery":"3.18.1"},"peerDependencies":{"@deepseek-ai/cordis":">=4.0.1 <5","@deepseek-ai/dsh-tools":">=0.1.1-rc.2 <0.2","@deepseek-ai/dsh-session":">=0.1.1-rc.2 <0.2","@deepseek-ai/schemastery":">=3.18.1 <4"},"peerDependenciesMeta":{"@deepseek-ai/cordis":{"optional":true},"@deepseek-ai/dsh-tools":{"optional":true},"@deepseek-ai/dsh-session":{"optional":true},"@deepseek-ai/schemastery":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/dsh-wakatime_0.3.0_1787823257782_0.2701009260190217","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@27aaron/dsh-wakatime","version":"0.4.0","description":"WakaTime tracking for DeepSeek Harness (headless core; add @27aaron/dsh-wakatime-ui for the web dashboard)","author":"Aaron","license":"MIT","type":"module","main":"lib/index.js","types":"lib/types/index.d.ts","exports":{".":{"types":"./lib/types/index.d.ts","default":"./lib/index.js"},"./ui-contract":{"types":"./lib/types/ui-contract.d.ts","default":"./lib/ui-contract.js"},"./package.json":"./package.json"},"dsh":{"bundle":{"patch":"./cordis.patch.yml"}},"repository":{"type":"git","url":"git+https://github.com/27Aaron/agent-toolkit.git","directory":"plugins/dsh-wakatime"},"homepage":"https://github.com/27Aaron/agent-toolkit/tree/main/plugins/dsh-wakatime#readme","bugs":{"url":"https://github.com/27Aaron/agent-toolkit/issues"},"publishConfig":{"access":"public"},"engines":{"node":"^22.19.0 || >=24.0.0"},"peerDependencies":{"@deepseek-ai/cordis":">=4.0.1 <5","@deepseek-ai/dsh-session":">=0.1.1-rc.2 <0.2","@deepseek-ai/dsh-session-persistence":">=0.1.1-rc.2 <0.2","@deepseek-ai/schemastery":">=3.18.1 <4"},"peerDependenciesMeta":{"@deepseek-ai/cordis":{"optional":true},"@deepseek-ai/dsh-session":{"optional":true},"@deepseek-ai/dsh-session-persistence":{"optional":true},"@deepseek-ai/schemastery":{"optional":true}},"devDependencies":{"@deepseek-ai/cordis":"4.0.1","@deepseek-ai/dsh-session":"0.1.1-rc.2","@deepseek-ai/dsh-session-persistence":"0.1.1-rc.2","@deepseek-ai/schemastery":"3.18.1","@types/node":"^22.20.0","@vitest/coverage-v8":"^4.1.8","publint":"^0.3.21","tsdown":"^0.22.2","typescript":"^5.9.3","vitest":"^4.1.8"},"keywords":["deepseek-harness","dsh","dsh-plugin","wakatime","ai-coding","productivity","time-tracking"],"scripts":{"build":"tsdown && tsc -p tsconfig.build.json","check":"pnpm run typecheck && pnpm run test && pnpm run build && pnpm exec publint","test":"vitest run","test:coverage":"vitest run --coverage","test:watch":"vitest","typecheck":"tsc --noEmit"},"_nodeVersion":"26.7.0","_id":"@27aaron/dsh-wakatime@0.4.0","dist":{"integrity":"sha512-lUpbvQbfjiO7O1fRRzmBI82b5fDkzj2WpObQQ7yNJBzstDLTOQmTyOHH5HL6oTVYEdu7EjE7kUejJowAlm81QA==","shasum":"7065631e4a0d4df387c892aff736027e2350c539","tarball":"https://registry.npmjs.org/@27aaron/dsh-wakatime/-/dsh-wakatime-0.4.0.tgz","fileCount":21,"unpackedSize":154758,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCICcoWdaa8aGDHvVPcNYUBHllcOGka7a+Sy6bw0vIF7woAiEA/kjkpphAU3yHLkS07JzK/7BvoZ/PeIPKP01IJpkFhJM="}]},"_npmUser":{"name":"27aaron","email":"niceboy@duck.com"},"directories":{},"maintainers":[{"name":"27aaron","email":"niceboy@duck.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/dsh-wakatime_0.4.0_1787880708072_0.9995874386876356"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-27T09:34:17.584Z","modified":"2026-08-28T01:31:48.391Z","0.3.0":"2026-08-27T09:34:17.903Z","0.4.0":"2026-08-28T01:31:48.224Z"},"bugs":{"url":"https://github.com/27Aaron/agent-toolkit/issues"},"author":"Aaron","license":"MIT","homepage":"https://github.com/27Aaron/agent-toolkit/tree/main/plugins/dsh-wakatime#readme","keywords":["deepseek-harness","dsh","dsh-plugin","wakatime","ai-coding","productivity","time-tracking"],"repository":{"type":"git","url":"git+https://github.com/27Aaron/agent-toolkit.git","directory":"plugins/dsh-wakatime"},"description":"WakaTime tracking for DeepSeek Harness (headless core; add @27aaron/dsh-wakatime-ui for the web dashboard)","maintainers":[{"name":"27aaron","email":"niceboy@duck.com"}],"readme":"# DSH WakaTime\n\n[中文](README.zh.md)\n\nWakaTime integration for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness). It syncs session activity through upstream `wakatime-cli`, without changing tool behavior or maintaining a separate activity parser.\n\nThis package is the **tracking core**. Configuration happens through `.wakatime.cfg` and the plugin config below — no UI required. The web dashboard and settings page live in the separate [`@27aaron/dsh-wakatime-ui`](../dsh-wakatime-ui) bundle; install it instead of this package when you want the GUI. Both variants read and write the same WakaTime data directory, so switching between them keeps every setting.\n\n| Package                     | What you get                                             |\n| --------------------------- | -------------------------------------------------------- |\n| `@27aaron/dsh-wakatime`     | Headless tracking; browser bundle absent entirely.        |\n| `@27aaron/dsh-wakatime-ui`  | The same tracking plus the web dashboard and settings page. |\n\n## Highlights\n\n- Uses Harness's official `session/event` notification to schedule sync, then awaits `ctx.sessions.flush(session)` before the CLI reads local transcripts.\n- Runs `--sync-ai-activity`, followed by separate `--sync-offline-activity 1000` and `--offline-count` invocations. A remaining offline backlog keeps sync pending for another attempt. The CLI owns prompt, token, model, file, and line-change accounting; the plugin does not emit its own file heartbeats.\n- Syncs prompt-only sessions too, without waiting for tool activity or another editor's heartbeat.\n- Coalesces pending sync requests across sessions, applies a global sync interval, and retries transient failures.\n- Uses an explicit CLI path, a global `wakatime-cli`, or a managed download in that order.\n- Resolves the CLI lazily for sync; managed downloads require a settings-page action or explicit `autoInstall: true`.\n- Starts dashboard API refresh only after a dashboard or settings interaction; activity sync through the CLI is independent.\n- Reads WakaTime's standard HTTP(S) `proxy`, `no_ssl_verify`, and `debug` settings; the CLI continues to own filtering and project settings.\n- Flushes pending activity on session disposal and plugin teardown, including one-shot headless runs.\n\nThe two sync commands are intentionally separate: [upstream's command dispatcher](https://github.com/wakatime/wakatime-cli/blob/v2.25.0/cmd/run.go#L153-L165) selects offline sync first if both flags are supplied. Offline sync alone does not parse AI transcripts.\n\n## Requirements\n\n- DeepSeek Harness `>= 0.1.1-rc.2 < 0.2`.\n- Node.js `^22.19.0 || >=24.0.0`, matching the current Harness requirement.\n- A stable `wakatime-cli >= v2.25.0` with native DeepSeek Harness parsing.\n- A WakaTime API key in `~/.wakatime.cfg`, `$WAKATIME_HOME/.wakatime.cfg`, or `WAKATIME_API_KEY`.\n\n```ini\n[settings]\napi_key = waka_your_api_key_here\n```\n\n## Install from npm\n\nInstall the tracking-only bundle into profiles that should trigger activity sync:\n\n```sh\ndsh plugin --profile headless add @27aaron/dsh-wakatime\n```\n\nFor tracking plus the Web dashboard, install `@27aaron/dsh-wakatime-ui` instead:\n\n```sh\ndsh plugin --profile web add @27aaron/dsh-wakatime-ui\n```\n\nPick one variant per profile. Inspect the composed configuration and restart the profile after installation.\n\n## Install from this repository\n\nBuild the packages, add the variant you want as a Profile Bundle, inspect the composed layer, and restart the profile:\n\n```sh\npnpm install\npnpm build\n\n# Tracking only:\ndsh plugin --profile web add ./plugins/dsh-wakatime\n\n# Tracking plus the web dashboard:\ndsh plugin --profile web add ./plugins/dsh-wakatime-ui\n```\n\nInstall the bundle separately in each profile that should trigger sync:\n\n```sh\ndsh plugin --profile headless add ./plugins/dsh-wakatime\n```\n\nFor a portable core artifact, run `pnpm --filter @27aaron/dsh-wakatime pack` and install the tarball with `dsh plugin --profile <name> add <file.tgz>`. The UI tarball keeps this core as a normal registry dependency, so publish the matching core version before distributing `@27aaron/dsh-wakatime-ui`; use the local-directory commands above for an unpublished checkout.\n\nPick **one variant per profile**. Both declare `dsh.bundle` patches, so installing both into one profile composes two wakatime rows; the first row to activate owns tracking and the second stands down with a warning, so nothing is tracked twice — but the ambiguity is best avoided. The UI bundle installs this core transitively, so switching later means removing one package and adding the other; settings persist in the WakaTime data directory.\n\n## Configuration\n\n### Web dashboard\n\nThe dashboard and settings page are provided by the [`@27aaron/dsh-wakatime-ui`](../dsh-wakatime-ui) bundle; see its README for the feature tour. This core exposes the same RPC endpoints either way, keeps serving cached data to any installed dashboard, and starts background refresh only after that first interaction. Both variants read the API key from `.wakatime.cfg` and keep UI-managed options under the WakaTime data directory, so moving between variants never loses settings.\n\n### Plugin config\n\nThe bundle inserts a row with id `wakatime` (the UI variant inserts `wakatime-ui` and re-exports the same schema). Override that id in `$DSH_HOME/profiles/<name>/cordis.patch.yml`, `$DSH_HOME/cordis.patch.yml`, or a later `--patch` layer:\n\n```yaml\n- id: wakatime\n  config:\n    heartbeatIntervalMs: 60000\n    heartbeatTimeoutMs: 30000\n    cliUpdateCheckIntervalMs: 14400000\n    cliDownloadTimeoutMs: 120000\n    autoInstall: false\n    client: dsh\n    debug: false\n```\n\nAll keys are optional because defaults live in the exported Schemastery schema. Harness replaces a row's whole `config` value when applying a later layer; omitted keys are filled from that schema rather than copied from the bundle patch. The upstream DeepSeek parser assigns the `ai coding` category; the plugin has no category override.\n\n| Setting                    |     Default | Purpose                                                                |\n| -------------------------- | ----------: | ---------------------------------------------------------------------- |\n| `heartbeatIntervalMs`      |     `60000` | Minimum interval between global native-sync runs, across sessions.      |\n| `heartbeatTimeoutMs`       |     `30000` | Timeout for each CLI process or persistence checkpoint, not the whole sync run. |\n| `cliUpdateCheckIntervalMs` |  `14400000` | Managed CLI update-check interval.                                     |\n| `dashboardRefreshIntervalMs` | `300000` | Background Dashboard refresh interval; the settings page displays minutes. |\n| `insightsRefreshIntervalMs` | `1800000` | Background Insights refresh interval; the settings page displays minutes. |\n| `cliDownloadTimeoutMs`     |    `120000` | Timeout for each GitHub request or CLI download.                       |\n| `cliPath`                  |       unset | Absolute CLI path; `~` is expanded. Disables discovery and management. |\n| `autoInstall`              |     `false` | Allow background download/update of a managed CLI during sync.         |\n| `client`                   |       `dsh` | Safe identifier used in the CLI's `--plugin` tag.                       |\n| `debug`                    |     `false` | Enable debug logs independently of WakaTime settings.                  |\n\nStandard WakaTime network settings are read from `.wakatime.cfg`:\n\n```ini\n[settings]\ndebug = true\nproxy = https://user:pass@example.com:8080\n# Avoid this unless a controlled network requires it.\nno_ssl_verify = false\n```\n\n## CLI management and security\n\nResolution order is:\n\n1. Configured `cliPath`.\n2. `wakatime-cli` found on `PATH`.\n3. Platform-specific managed CLI under `~/.wakatime/` or `$WAKATIME_HOME`.\n\nBy default the page only inspects the configured path, PATH, and WakaTime directory; it does not make network requests or write files. The settings page provides **Download WakaTime CLI** and **Check and update** actions: the former installs a managed copy only after an explicit click, while the latter only operates on the managed copy and never changes a system or package-manager installation. Managed downloads use HTTPS, honor standard HTTP(S) WakaTime proxy settings, validate ZIP structure, size, CRC-32, expected binary name, and the downloaded executable's `--version` output, then replace the prior binary atomically. Set `autoInstall: true` in Host configuration only when background management is desired.\n\nThe update check follows GitHub's latest stable release, so pre-releases are never installed automatically. Sync requires a verified stable `wakatime-cli >= v2.25.0`. Older, prerelease, and unknown versions (including unversioned local builds) are not treated as supported; update or select a supported CLI. There is no fallback plugin parser. The settings page shows the resolved CLI's native-sync support.\n\n## Data and privacy\n\nThe plugin invokes the user's local WakaTime CLI with sync flags and a `--plugin` tag, and passes Harness's session root as `DSH_HOME`. The CLI reads local session transcripts and derives heartbeat metadata; it also owns API authentication, offline queuing, project detection, and privacy filters. Use standard WakaTime settings such as `hide_file_names`, `hide_project_names`, `exclude`, and `include` as required by your deployment policy.\n\nEnabling this plugin in a profile controls when it triggers sync, not which profiles are scanned. Native AI sync scans all supported local transcripts, including other Harness profiles and other supported AI tools, according to the CLI's settings.\n\nLogs are written to `~/.wakatime/dsh-wakatime.log` or `$WAKATIME_HOME/dsh-wakatime.log`. API keys are never passed as process arguments or included in plugin logs.\n\n## Diagnostics\n\n```sh\ndsh --profile web --dump-config\ngrep -iE 'warn|error' ~/.wakatime/dsh-wakatime.log\ngrep -iE 'warn|error' ~/.wakatime/wakatime.log\n```\n\nEnable `debug = true` in `.wakatime.cfg` or `debug: true` in the plugin row when more detail is needed.\n\n## Limitations\n\n- Native DeepSeek parsing reads local `session.jsonl` and `session.jsonl.zstd` files under `$DSH_HOME/sessions` (normally `~/.dsh/sessions`). Sessions kept only in memory or on a remote host must be persisted locally first. See [upstream's transcript discovery](https://github.com/wakatime/wakatime-cli/blob/v2.25.0/pkg/ai/deepseek.go#L176-L237).\n- File coverage and line-change accounting follow upstream. Arbitrary shell edits and unsupported custom tools are not inferred by this plugin.\n- In v2.25.0, upstream does not parse Code Mode's `tool/code-dispatch` events, so those subcalls lack file/line-change details; session prompts and token usage can still be synced. This needs an upstream parser change, not a second local producer. See [the supported event branches](https://github.com/wakatime/wakatime-cli/blob/v2.25.0/pkg/ai/deepseek.go#L380-L395).\n- Offline delivery and duplicate handling remain CLI responsibilities. A successful local sync invocation does not guarantee that the dashboard has already received every heartbeat.\n\n## Development\n\n```sh\npnpm typecheck\npnpm test\npnpm build\npnpm check\n```\n","readmeFilename":""}