@fotor-ai/dsh-fotor-plugin 0.6.0 → 0.6.1-test.2

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/INSTALL.md CHANGED
@@ -1,181 +1,100 @@
1
1
  # Install and use Fotor with DeepSeek Harness
2
2
 
3
- > Requires stable Node 24.2.0 or later within 24.x, or stable Node 26.x. The fixed DeepSeek Harness 0.2.1-rc.2 launcher needs `import.meta.main`, introduced in Node 24.2.0. Earlier Node 24 releases are outside the supported range. Use the release's recorded runtime results for the exact tested versions.
3
+ DeepSeek Harness is abbreviated as `dsh` in commands and native identifiers. This guide describes automatic configuration in Fotor 0.6.1. Version 0.6.0 uses its documented manual configuration. Read the package README's version and channel, and choose a source that actually contains the target version. A candidate snapshot does not publish the npm package or change either default branch.
4
4
 
5
- DeepSeek Harness is abbreviated as `dsh` in commands and native identifiers. This guide is self-contained for the independent 0.6.0 package. Test distributions are available; stable availability is separate. This internal refresh pins mcp-remote 0.15.2; published test.3 retains 0.15.1 until a refreshed channel is released. Check the selected GitHub revision or npm version before installing. Existing 0.5.1 installations retain their original guide until migrated to the scoped identity.
5
+ ## 1. Check prerequisites
6
6
 
7
- During the 0.6.0 test rollout, GitHub's default branch still supplies 0.5.1 and npm `latest` retains the accepted first-publication exception, `0.6.0-test.1`. Bare-name npm installation therefore selects a prerelease until the formal rollout replaces it. Use the GitHub test branch or a verified npm test version during that interval; use production examples only after the selected channel contains the intended stable release.
7
+ The current acceptance baseline is Linux DeepSeek Harness Web `0.2.1-rc.3` and stable Node `>=24.2.0 <25.0.0 || 26.x`. Earlier rc.2 results retain their original scope; the declared host range remains `>=0.2.1-rc.2 <0.3.0-0`. Node is not bundled. Check `dsh --version` and `node --version`; do not upgrade a daily installation implicitly. See the official [DeepSeek Harness repository](https://github.com/deepseek-ai/deepseek-harness) and [Node downloads](https://nodejs.org/en/download). Desktop, headless and ACP require separate acceptance.
8
8
 
9
- ## 1. Check prerequisites and select a profile
9
+ ## 2. Choose one source
10
10
 
11
- Use Linux DeepSeek Harness Web `0.2.1-rc.2` (source `687f282e8625c6b8d11ff58211a90524be2e4317`), its available native package manager, and a stable Node **24.2.0 or later within 24.x, or 26.x**. Node 24.0.x, 24.1.x, 25.x, 27.x and prereleases are outside the declared range. The host range remains `>=0.2.1-rc.2 <0.3.0-0`; admission is not evidence that every host/runtime combination has been tested. Consult the installed release's acceptance record. Desktop, headless and ACP require separate acceptance.
11
+ GitHub downloads the pinned **mcp-remote 0.15.2** dependency through the host package manager. npm artifacts carry its complete reviewed runtime tree. Neither path needs a separate bridge installation. Skills remain script-free; the package has no installation lifecycle hook.
12
12
 
13
- ```bash
14
- dsh --version
15
- node --version
16
- dsh plugin --profile web root
17
- ```
18
-
19
- Git sources additionally require Git. Follow the [host quickstart](https://deepseek-harness.github.io/deepseek-harness/en/guide/quickstart) or [Node downloads](https://nodejs.org/en/download/) for missing prerequisites. Node is not bundled. Preserve daily installations; do not upgrade them to satisfy an acceptance run.
20
-
21
- Select one profile, working directory and Fotor-only credential directory outside the installed package. Inspect existing Fotor components before changing anything. A model-provider account is separate from Fotor OAuth. If installation uses a custom `--store-dir /absolute/path/to/store`, record it and pass that same argument on later add, update and remove commands. Retain the original profile and source as well.
22
-
23
- **Done when:** the host and Node versions are known, the native package manager works, and the profile and external storage locations are selected.
24
-
25
- ## 2. Install one Bundle source
26
-
27
- The package name is **`@fotor-ai/dsh-fotor-plugin`** for both sources. Installing it automatically obtains the pinned **mcp-remote 0.15.2** runtime. There is no separate bridge installation command. Git installation downloads the dependency through the host package manager; npm artifacts already carry the bridge and its complete runtime dependency tree. Installation starts neither the bridge nor OAuth.
28
-
29
- Choose exactly one command after its channel is published:
13
+ Choose one source and a profile. Test channels must actually contain the requested version before use:
30
14
 
31
15
  ```bash
32
- # GitHub production: default branch.
33
- dsh plugin --profile web add "git+https://github.com/fotor-ai/dsh-fotor-plugin.git" --ignore-scripts
34
- # GitHub test channel.
35
- dsh plugin --profile web add "git+https://github.com/fotor-ai/dsh-fotor-plugin.git#release/test" --ignore-scripts
36
- # npm production: only after latest is the intended stable release.
37
- dsh plugin --profile web add "@fotor-ai/dsh-fotor-plugin" --ignore-scripts
38
- # npm test channel.
39
- dsh plugin --profile web add "@fotor-ai/dsh-fotor-plugin@next" --ignore-scripts
16
+ FOTOR_PROFILE=web
17
+ # GitHub default branch, after the target version is published:
18
+ dsh plugin --profile "$FOTOR_PROFILE" add "git+https://github.com/fotor-ai/dsh-fotor-plugin.git" --ignore-scripts
19
+ # GitHub test branch:
20
+ dsh plugin --profile "$FOTOR_PROFILE" add "git+https://github.com/fotor-ai/dsh-fotor-plugin.git#release/test" --ignore-scripts
21
+ # npm default or test channel:
22
+ dsh plugin --profile "$FOTOR_PROFILE" add "@fotor-ai/dsh-fotor-plugin" --ignore-scripts
23
+ dsh plugin --profile "$FOTOR_PROFILE" add "@fotor-ai/dsh-fotor-plugin@next" --ignore-scripts
24
+ # A complete local package for development:
25
+ dsh plugin --profile "$FOTOR_PROFILE" add /absolute/path/to/fotor-package --ignore-scripts
40
26
  ```
41
27
 
42
- For an internal or local rehearsal, replace the source with the absolute path to the complete independent package. The multi-platform repository root is Pi's facade and is not a DeepSeek Harness package. Never install both sources, aliases, or the legacy `fotor` alongside the scoped package.
43
-
44
- **Done when:** native installation succeeds and reports the scoped identity and expected version. Preserve a failed dependency download as a failed installation; do not continue with a missing bridge or use an unpinned `npx` workaround.
28
+ Run only the command for the chosen source. The Web **Plugins → Add plugin** entry accepts the same npm or GitHub source. After installation, click the host's **Enable now** button (or the Bundle switch). This selects the Bundle; its two components then activate automatically. The package cannot enable a Bundle the host has not loaded. Package name is `@fotor-ai/dsh-fotor-plugin` for both. Keep the original custom `--store-dir` argument for every later update/removal.
45
29
 
46
- ## 3. Resolve the installed package and bridge
47
-
48
- Use the original profile and package-manager store. Set variables from native output and verified absolute paths:
30
+ ## 3. Verify installation
49
31
 
50
32
  ```bash
51
- FOTOR_PROFILE=web
52
- dsh plugin --profile "$FOTOR_PROFILE" why @fotor-ai/dsh-fotor-plugin
53
33
  dsh plugin --profile "$FOTOR_PROFILE" root
54
- FOTOR_INSTALLED="$(realpath "$(dsh plugin --profile "$FOTOR_PROFILE" root)/@fotor-ai/dsh-fotor-plugin")"
55
- dsh plugin --profile "$FOTOR_PROFILE" list mcp-remote --depth Infinity --parseable
56
- dsh plugin --profile "$FOTOR_PROFILE" why mcp-remote --json
34
+ dsh plugin --profile "$FOTOR_PROFILE" list --depth Infinity --json
35
+ dsh plugin --profile "$FOTOR_PROFILE" why @fotor-ai/dsh-fotor-plugin
57
36
  ```
58
37
 
59
- Choose the resolution route matching the installed manifest:
38
+ Use the returned package root and actual dependency resolution for diagnosis, not a guessed pnpm store directory. Bundled npm dependencies can be absent from the ordinary dependency list; the installed package carries `node_modules/mcp-remote/package.json` and its `dist/client.js` and `dist/proxy.js`. Git installations use package-manager-owned links. Verify the bridge is 0.15.2.
60
39
 
61
- - **Git source:** the dependency query can return multiple paths. Select the mcp-remote 0.15.2 dependency owned by this exact Fotor installation; stop on ambiguity. pnpm can place it beside the package rather than inside it. Set `FOTOR_BRIDGE` to that verified absolute dependency path.
62
- - **npm artifact:** after verifying `bundleDependencies` names mcp-remote, resolve the bundled directory below. The native dependency list may omit bundled packages; an empty list alone is not a missing bridge.
40
+ Installation success is the expected version/source and complete files. It does not prove MCP connection. Never read the bridge's token files to diagnose installation.
63
41
 
64
- ```bash
65
- # npm artifact only, after inspecting its manifest.
66
- FOTOR_BRIDGE="$(realpath "$FOTOR_INSTALLED/node_modules/mcp-remote")"
67
- ```
42
+ ## 4. Load the Bundle and resolve configuration
68
43
 
69
- For either source, verify the selected location before configuring it:
44
+ New installations require **no manual path configuration**. Start the chosen profile or allow the running Web host to load the Bundle:
70
45
 
71
46
  ```bash
72
- FOTOR_NODE=/absolute/path/to/node
73
- cat "$FOTOR_INSTALLED/package.json"
74
- cat "$FOTOR_BRIDGE/package.json"
75
- test -f "$FOTOR_BRIDGE/dist/client.js"
76
- test -f "$FOTOR_BRIDGE/dist/proxy.js"
47
+ dsh --profile "$FOTOR_PROFILE"
77
48
  ```
78
49
 
79
- Git pins the direct bridge version; its transitive graph is resolved by the host and should be recorded when reproducing a result. The packaged lock file is the npm release-build input, not a promise that pnpm honors it during Git installation.
80
-
81
- **Done when:** the scoped package/version, bridge 0.15.2, both bridge entrypoints and all selected absolute paths are verified. A `why` result alone does not establish file completeness or the Git commit.
50
+ The package declares both adapters enabled. A saved explicit disabled override still wins. Skills are resolved relative to the installed Fotor package; Node comes from the running Web host; the bridge is resolved from the package's dependencies. Only this package's skill root is scanned.
82
51
 
83
- ## 4. Prepare complete configuration
52
+ The adapter creates complete native `command`, `args`, `env` and `cwd` values in memory. Credentials default to `<active-profile-directory>/fotor/mcp-auth`, outside the installation. The default callback is loopback port 3335. A conflicting listener produces a diagnosis; stop the conflicting task or configure an unused port without changing an existing authorization's parameters casually.
84
53
 
85
- Copy [configuration.example.yml](configuration.example.yml) outside the installation and fill every placeholder:
54
+ Optional MCP settings include `endpoint` (production Fotor by default; a loopback service is for isolated acceptance), `callbackPort`, and existing native stdio fields. A supplied `args` array is complete, not an append. Explicit `env.MCP_REMOTE_CONFIG_DIR` is preserved. The [full legacy configuration example](configuration.example.yml) remains available for advanced overrides; it is never auto-applied. Overrides replace the complete `config` object, not a deep merge.
86
55
 
87
- | Parameter | Source and lifetime |
88
- | --- | --- |
89
- | Profile | The native profile selected for installation; keep it for updates/removal |
90
- | Skill directory | Actual `FOTOR_INSTALLED` plus `/skills`; re-resolve after updates |
91
- | Node command | Absolute executable for the selected supported Node version |
92
- | Proxy/client entry | Actual `FOTOR_BRIDGE` plus `/dist/proxy.js` or `/dist/client.js`; re-resolve after updates |
93
- | Home and agents home | Actual host locations; dedicated directories during acceptance |
94
- | Working directory | Selected existing absolute workspace |
95
- | `MCP_REMOTE_CONFIG_DIR` | Fotor-only external directory, separate from model credentials; retain across updates and source changes |
96
- | Callback | One available port; example `3335`, host copied unchanged from `configuration.example.yml`; identical for client and proxy |
97
- | Endpoint/resource | Both `https://mcp.fotor.com/mcp`; retain production and OAuth security parameters |
56
+ ## 5. Verify skills and existing overrides
98
57
 
99
- Overrides replace whole `config` objects, not individual nested fields. Retain both complete rows and all arguments. Keep native reconnect disabled. Do not copy credentials into the package, command arguments or documentation.
58
+ For ordinary use, verify the native skill menu/provider discovers the actual Fotor skills and their own `references` directories. A green component indicator without discovered entries is insufficient. Read known references through native `read`; the Shell sandbox may hide an otherwise readable host path.
100
59
 
101
- **Done when:** the full override is external, all paths are real and no conflicting `fotor` service or duplicate provider exists.
60
+ Old complete configuration is accepted. If an old skill or bridge path no longer exists, preserve the record and remove only the obsolete override using native profile configuration to adopt automatic resolution, or supply the corrected path. Do not edit package caches, reset unrelated settings or clear credentials. Resolve duplicate Fotor providers/services before enabling another copy.
102
61
 
103
- ## 5. Apply complete configuration and load skills
62
+ <a id="6-authorize-then-enable-the-connection"></a>
104
63
 
105
- Use the selected profile's native patch mechanism or an explicit external patch:
64
+ ## 6. Authorize and verify the connection
106
65
 
107
- ```bash
108
- dsh --profile "$FOTOR_PROFILE" --patch /absolute/path/to/fotor.local.yml
109
- ```
66
+ In 0.6.1 this sequence is managed automatically after host activation. The independent bridge client reuses authorization or opens the daily browser. Complete login/consent there. It must connect and discover tools, then exit with its callback listener closed before the proxy starts. Model account login remains a separate user action.
110
67
 
111
- The installed Bundle declares both components disabled. The example enables only skills; its MCP row stays disabled. Keep `includeDefaultRoots: false` and scan only the actual installed Fotor skill directory.
68
+ Connection diagnostics are `preparing`, `waiting-authorization`, `connected`, `failed` or `stopped`. The adapter being active is not a connected MCP. Authorization waits at most ten minutes and can be cancelled by disabling the MCP component. Failure does not loop through browser prompts; deliberately disable/enable to retry. Use the [authentication guide](skills/fotor-connect/references/authentication.md) for bounded recovery and browser handling.
112
69
 
113
- In the native menu, select `/fotor-connect`; ask it to read its instructions without authorizing or calling MCP. Confirm the resource path and one discovered copy of each actual Fotor skill. Each skill has four local reference documents.
70
+ Once connected, ask for a read-only model query. Website access is a separate request; preserve browser login and open each original handoff once. Never infer website login from MCP success.
114
71
 
115
- Use the host's native `read` tool for those files. The Linux Shell sandbox can hide a `/tmp` installation while native reading still works; a failed Shell `ls` is not proof of a broken package. If native reading fails, stop and report the actual path/error rather than searching other installations.
72
+ ## 7. Use, update, or remove Fotor
116
73
 
117
- **Done when:** the native provider discovers the package's actual skills and their local references, and MCP is still disabled.
74
+ Examples: “Use Fotor's existing connection to list image models”; “Connect to the Fotor website”; or explicitly choose `/fotor-connect`. Media requests follow their own skill and credit notice rules.
118
75
 
119
- ## 6. Authorize then enable the connection
120
-
121
- Read [this package's authentication guide](skills/fotor-connect/references/authentication.md) before connecting. Confirm the opener targets the user's daily ordinary browser, preserve its login state, and keep the proxy stopped while the independent authorization client runs.
76
+ For the recorded Git source:
122
77
 
123
78
  ```bash
124
- MCP_REMOTE_CONFIG_DIR=/absolute/path/to/dsh-home/mcp-auth/fotor "$FOTOR_NODE" "$FOTOR_BRIDGE/dist/client.js" https://mcp.fotor.com/mcp 3335 --host "$FOTOR_CALLBACK_HOST" --transport http-only --resource https://mcp.fotor.com/mcp --auth-timeout 600 --connect-timeout 20 --headers-timeout 20 --body-timeout 20
79
+ dsh plugin --profile "$FOTOR_PROFILE" update @fotor-ai/dsh-fotor-plugin --ignore-scripts
125
80
  ```
126
81
 
127
- Set `FOTOR_CALLBACK_HOST` to the callback host verified in the configuration example. Run in an interactive terminal that keeps stdin open. After the user selects Continue, require successful connection and actual tool discovery. A callback page or exit code alone is insufficient. Stop the client and callback listener before enabling the MCP row and restarting the profile. Keep the same endpoint, resource, callback and credential directory. Cancel/timeout stops the flow; human waiting is limited to ten minutes.
128
-
129
- The bridge owns OAuth; this is not native remote OAuth in DeepSeek Harness. Model login, package installation, skills, Fotor authorization and website login are separate steps.
130
-
131
- **Done when:** authorization-client discovery completes, that client/listener exits, and the enabled native stdio connection discovers actual Fotor tools.
132
-
133
- ## 7. Use, update or remove Fotor
134
-
135
- Example requests:
136
-
137
- - MCP-only: “Connect only to Fotor MCP and list image models. Do not open the website.”
138
- - Website: “Connect to Fotor and introduce its capabilities.” Prepare the daily browser before requesting the one-use handoff; report website success only after user confirmation.
139
- - Explicit skill: select `/fotor-image` and describe a task. Every successful `submit_*_task` may consume credits; preserve the existing authorization and retry rules.
140
-
141
- Stop Fotor components and record their source, profile, store and external configuration before updating. Choose one command for the recorded source. For npm, replace `<target-version>` with an explicitly published and approved version, such as the exact version in the selected release notes:
82
+ For npm, select an explicitly published target:
142
83
 
143
84
  ```bash
144
- # Recorded Git source only.
145
- dsh plugin --profile "$FOTOR_PROFILE" update @fotor-ai/dsh-fotor-plugin --ignore-scripts
146
- # Recorded npm source: select an exact published target, not a moving tag.
147
85
  dsh plugin --profile "$FOTOR_PROFILE" update "@fotor-ai/dsh-fotor-plugin@<target-version>" --ignore-scripts
148
- dsh plugin --profile "$FOTOR_PROFILE" why @fotor-ai/dsh-fotor-plugin
149
86
  ```
150
87
 
151
- For a custom store, append the original `--store-dir` argument to the selected update command. An unqualified update can remain on the saved npm version. In the recorded test.1-to-test.2 acceptance, immediate `update ...@next` returned success but retained test.1 on both Node 24.2.0 and 26.0.0, even after an approved exception for that exact version's release age. Exact-version native updates passed. The guide therefore uses exact versions for npm updates; this does not establish that `@latest` updates work or that waiting 24 hours always resolves tag updates. Keep Git installations on their recorded Git source: applying an npm version selector is a source change, not a Git update.
152
-
153
- Keep the package manager's release-age policy. If it blocks a newly published version, report the target and wait, or obtain separate approval for an exception limited to that exact version and isolated profile. The earlier test.2 approval does not cover later versions. Do not disable the policy globally, clear metadata caches or reinstall to manufacture an update pass.
154
-
155
- **Done when:** the installed version and source match the selected target, files and managed bridge are complete, and a new process discovers one copy of each skill at the re-resolved paths. A zero exit code alone is insufficient. Update complete configuration rows if paths moved; preserve the external credential store, model settings and security parameters. Record a failed native update separately from any later reinstall.
88
+ During historical 0.6.0-test.2 acceptance, immediate `@next` updates retained 0.6.0-test.1; exact-version updates passed. Neither `@latest` success nor success after 24 hours is established. Keep release-age protection; an acceptance-only exception needs separate approval for the exact target version. Do not treat reinstall or cache clearing as a successful upgrade. Verify installed version/files and restart the host so its module generation and paths are refreshed. Preserve the profile and custom store.
156
89
 
157
- ### Migrate from the legacy package or switch sources
90
+ Before upgrading 0.6.0, record the native source, profile, store, enabled state and explicit configuration without reading token files. With no overrides, 0.6.1 resolves paths when the host loads the Bundle. Existing complete configuration and explicit disabled settings remain authoritative: upgrading does not reopen a component the user disabled. Preserve valid custom paths and connection parameters; use native configuration only to correct or remove an obsolete path override. An npm version selector is not a Git-source update; source changes use the deliberate remove/add procedure below.
158
91
 
159
- Legacy 0.5.1 and older packages are named `fotor`. A normal update does not rename them. Record source/profile/store/path and the external configuration, stop both components, and remove only their override rows. Remove the old identity, then install one scoped source from step 2:
160
-
161
- ```bash
162
- dsh plugin --profile "$FOTOR_PROFILE" remove fotor --config.ignore-scripts=true
163
- ```
164
-
165
- For GitHub/npm switching or scoped-package removal, use:
92
+ For removal:
166
93
 
167
94
  ```bash
168
95
  dsh plugin --profile "$FOTOR_PROFILE" remove @fotor-ai/dsh-fotor-plugin --config.ignore-scripts=true
169
96
  ```
170
97
 
171
- This host baseline rejects `--ignore-scripts` on removal; use the configuration form above and append the original `--store-dir` argument when a custom store was used. After adding the new source, resolve package and managed bridge paths again and restore a complete override. Keep one scoped installation and one component pair. Keep the credential directory, model settings and all connection/security parameters unchanged. Do not automatically delete the old external bridge directory or claim real credential reuse from an offline migration rehearsal.
172
-
173
- ### Troubleshooting
174
-
175
- - Missing bridge: inspect native install/download results and this package's dependency tree; finish installation before connecting.
176
- - Changed installation path: re-query the native root/dependency paths and replace complete override rows.
177
- - pnpm store mismatch: use the original profile/store; do not edit caches or move package-manager links manually.
178
- - Duplicate skills/components: inspect selected sources and override rows before enabling either component.
179
- - Authorization failure: follow the authentication guide's single-client bounded recovery sequence. Installation or restart success does not prove recovery from rejected credentials.
98
+ Stop the components first. Removal stops their processes but leaves credentials and explicit user configuration. Source switching uses deliberate removal/addition in the same profile/store; keep one source and one component pair. For the older unscoped `fotor` identity, remove that exact name before adding the scoped package. Keep old external bridge directories unless separately authorized to remove them.
180
99
 
181
- Uninstalling the Bundle does not revoke server-side consent. Delete only explicitly authorized temporary state after its processes stop; retain daily client configuration, credentials and browser login.
100
+ Uninstall does not revoke server-side consent. Reinstalling in the same profile and credential directory can reuse accepted authorization; enabling still establishes a new connection. Verify that connection with an actual read-only query. A different `DSH_HOME`, profile, explicit `MCP_REMOTE_CONFIG_DIR` or connection parameters can select a different cache, and expired or rejected authorization can require new consent. Automatic configuration never migrates or copies tokens. Isolated acceptance cleanup may remove only that task's temporary state after all owned processes stop.
package/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # Fotor for DeepSeek Harness
2
2
 
3
- > Requires stable Node 24.2.0 or later within 24.x, or stable Node 26.x. The fixed DeepSeek Harness 0.2.1-rc.2 launcher needs `import.meta.main`, introduced in Node 24.2.0. Earlier Node 24 releases are outside the supported range. Use the release's recorded runtime results for the exact tested versions.
3
+ > Requires stable Node 24.2.0 or later within 24.x, or stable Node 26.x. Current acceptance uses Linux DeepSeek Harness Web 0.2.1-rc.3. Earlier rc.2 results retain their original scope. Use the release's recorded results for the exact tested host, runtime and installation route.
4
4
 
5
5
  <p align="center"><img src="assets/logo.svg" width="72" alt="Fotor logo" /></p>
6
6
 
7
7
  <p align="center">
8
- <img src="https://img.shields.io/static/v1?label=version&amp;message=0.6.0&amp;color=087f8c&amp;style=flat-square" alt="Version" />
9
- <img src="https://img.shields.io/static/v1?label=channel&amp;message=production&amp;color=238636&amp;style=flat-square" alt="Release channel" />
8
+ <img src="https://img.shields.io/static/v1?label=version&amp;message=0.6.1-test.2&amp;color=087f8c&amp;style=flat-square" alt="Version" />
9
+ <img src="https://img.shields.io/static/v1?label=channel&amp;message=test&amp;color=a56800&amp;style=flat-square" alt="Release channel" />
10
10
  <a href="LICENSE"><img src="https://img.shields.io/static/v1?label=license&amp;message=Apache-2.0&amp;color=57606a&amp;style=flat-square" alt="Apache-2.0 license" /></a>
11
11
  </p>
12
12
  <p align="center">
@@ -18,12 +18,12 @@ Use Fotor's shared skills with DeepSeek Harness Web and an automatically install
18
18
  | Field | Value |
19
19
  | --- | --- |
20
20
  | Bundle | `@fotor-ai/dsh-fotor-plugin` |
21
- | Version | `0.6.0` |
22
- | Release channel | `production` |
21
+ | Version | `0.6.1-test.2` |
22
+ | Release channel | `test` |
23
23
  | Service environment | `production` |
24
24
  | MCP endpoint | `https://mcp.fotor.com/mcp` |
25
25
  | Declared host range | `>=0.2.1-rc.2 <0.3.0-0` |
26
- | Host baseline | Linux DeepSeek Harness Web 0.2.1-rc.2 |
26
+ | Host baseline | Linux DeepSeek Harness Web 0.2.1-rc.3 |
27
27
  | Bridge | mcp-remote 0.15.2 |
28
28
  | Node range | `>=24.2.0 <25.0.0 \|\| 26.x`, stable versions |
29
29
  | License | Apache-2.0 |
@@ -32,7 +32,7 @@ Use Fotor's shared skills with DeepSeek Harness Web and an automatically install
32
32
 
33
33
  Package checks cover files, references, and configuration. Verify installation, MCP authorization and calls, website login, credit links, uploads, and media execution separately in the selected host and environment. A release or model query does not establish successful website login or completed media results.
34
34
 
35
- The Bundle only declares host-owned components and resources. The bridge is acquired by the package manager and owns OAuth. npm artifacts carry its full runtime dependency tree; Git installs download the dependency. Complete support requires real controlled reauthorization recovery as well as installation, calls, website access and restart reuse; consult the evidence for the installed release. Media execution and expiry-driven refresh are not established by static checks.
35
+ The Bundle supplies two small native Host adapters that configure the host-owned components automatically. The bridge is acquired by the package manager and owns OAuth. npm artifacts carry its full runtime dependency tree; Git installs download the dependency. Complete support requires real controlled reauthorization recovery as well as installation, calls, website access and restart reuse; consult the evidence for the installed release. Media execution and expiry-driven refresh are not established by static checks.
36
36
 
37
37
  <a id="dsh"></a>
38
38
 
@@ -44,27 +44,27 @@ DeepSeek Harness is abbreviated as `dsh` in commands and native identifiers.
44
44
 
45
45
  ### DeepSeek Harness installation
46
46
 
47
- #### Production release
47
+ #### Test release
48
48
 
49
- First verify that the selected revision contains the DeepSeek Harness Bundle. Install this scoped package and its pinned bridge dependency to the chosen profile. Both components stay disabled until local setup.
49
+ First verify that the selected revision contains the DeepSeek Harness Bundle. Install this scoped package and its pinned bridge dependency to the chosen profile. Select Web **Enable now** or load the CLI profile; both components then configure automatically unless explicit user settings disable them.
50
50
 
51
51
  ```bash
52
- dsh plugin --profile web add "git+https://github.com/fotor-ai/dsh-fotor-plugin.git" --ignore-scripts
52
+ dsh plugin --profile web add "git+https://github.com/fotor-ai/dsh-fotor-plugin.git#release/test" --ignore-scripts
53
53
  ```
54
54
 
55
55
  This is the standalone root Bundle for [https://github.com/fotor-ai/dsh-fotor-plugin](https://github.com/fotor-ai/dsh-fotor-plugin). Use its root Git source only after the selected channel contains this version. The [multi-platform repository](https://github.com/fotor-ai/fotor-agent-plugins) documents this external source; it no longer distributes new DeepSeek Harness packages. Existing subdirectory installations require a one-way native source migration.
56
56
 
57
- The Bundle identity is `@fotor-ai/dsh-fotor-plugin`. After the corresponding npm channel is published, its alternative is `dsh plugin --profile web add "@fotor-ai/dsh-fotor-plugin" --ignore-scripts` (production) or `dsh plugin --profile web add "@fotor-ai/dsh-fotor-plugin@next" --ignore-scripts` (test). Verify the resolved version and select one source only. Bare-name npm installation follows `latest`; until the formal 0.6.0 rollout, that tag retains the accepted test.1 bootstrap exception and does not mean stable 0.6.0.
57
+ The Bundle identity is `@fotor-ai/dsh-fotor-plugin`. After the corresponding npm channel is published, its alternative is `dsh plugin --profile web add "@fotor-ai/dsh-fotor-plugin" --ignore-scripts` (production) or `dsh plugin --profile web add "@fotor-ai/dsh-fotor-plugin@next" --ignore-scripts` (test). Verify the resolved version and select one source only. Bare-name npm installation follows `latest`.
58
58
 
59
- Installation automatically obtains **mcp-remote 0.15.2**. Git sources download it through the host package manager; npm artifacts carry its complete locked runtime tree. Fotor skills remain script-free. No installation hook starts the bridge or OAuth, and Node is not bundled.
59
+ Installation automatically obtains **mcp-remote 0.15.2**. Git sources download it through the host package manager; npm artifacts carry its complete locked runtime tree. Fotor skills remain script-free. No installation hook runs code; host activation starts connection and may open browser consent. Node is not bundled.
60
60
 
61
61
  Follow the [complete installation guide](INSTALL.md):
62
62
 
63
- 1. Check Linux DeepSeek Harness Web `0.2.1-rc.2` and stable Node **24.2.0 or later within 24.x, or 26.x**.
63
+ 1. Check Linux DeepSeek Harness Web `0.2.1-rc.3` and stable Node **24.2.0 or later within 24.x, or 26.x**.
64
64
  2. Install one source with lifecycle scripts disabled.
65
- 3. Query actual package and dependency paths; verify both bridge entrypoints.
66
- 4. Apply full external configuration and enable only skills first.
67
- 5. Configure the model account separately; complete bridge-client Fotor authorization and actual tool discovery, stop that client, then enable MCP. Website access is a separate request.
65
+ 3. In Web, click **Enable now** after installation; in CLI, start the selected profile. Both enabled-by-default adapters resolve their paths automatically.
66
+ 4. Complete browser consent when required; existing valid authorization is reused.
67
+ 5. Verify actual skill and tool discovery. Configure the model account separately; website access is a separate request.
68
68
 
69
69
  The declared host range is `>=0.2.1-rc.2 <0.3.0-0`; matching versions are not automatically verified. Desktop, headless and ACP require separate acceptance.
70
70
 
@@ -72,9 +72,9 @@ The declared host range is `>=0.2.1-rc.2 <0.3.0-0`; matching versions are not au
72
72
 
73
73
  ### DeepSeek Harness configuration and connection
74
74
 
75
- Installation adds two disabled components. Use native `root`, `list` and `why` queries as described in the guide; do not guess pnpm storage paths. A bundled npm dependency can be absent from the ordinary native list; follow the guide to verify the declared bundle under the actual installed package. Copy the [full configuration example](configuration.example.yml) outside the package and fill every absolute path. Overrides replace complete `config` objects. Keep default skill roots and native MCP reconnect disabled.
75
+ The native adapters resolve skills, Node and the pinned bridge at activation. Existing explicit overrides and disabled states take precedence. The [full configuration example](configuration.example.yml) is optional and never auto-applied. Overrides replace complete `config` objects. Keep default skill roots and native MCP reconnect disabled.
76
76
 
77
- The native client directly runs the installed dependency using structured `command`, `args`, `env` and `cwd`. Keep `MCP_REMOTE_CONFIG_DIR` dedicated to Fotor and outside updates. Follow [authentication instructions](skills/fotor-connect/references/authentication.md), retaining independent-client discovery, user Continue / Wait / Cancel and client shutdown before the proxy starts. The bridge owns OAuth.
77
+ Credentials remain outside the installation, in the configured `MCP_REMOTE_CONFIG_DIR` or the active profile's dedicated Fotor directory. Follow [authentication instructions](skills/fotor-connect/references/authentication.md). The adapter runs client discovery, closes that client and its callback, then starts the native MCP proxy. User consent remains required; disabling MCP cancels its connection task.
78
78
 
79
79
  Use the user's confirmed daily ordinary browser. MCP-only requests do not request website links; website requests prepare the browser, open the original handoff once through native permission controls, and wait for actual page confirmation. An existing login is not a first-login result.
80
80
 
@@ -95,7 +95,7 @@ For a recorded npm source, replace `<target-version>` with the approved, publish
95
95
  dsh plugin --profile web update "@fotor-ai/dsh-fotor-plugin@<target-version>" --ignore-scripts
96
96
  ```
97
97
 
98
- Immediate `@next` updates retained test.1 during test.2 acceptance; exact-version native updates passed. An unqualified update can also retain the saved version. Neither `@latest` update success nor eventual success after 24 hours is established. Use the [maintenance procedure](INSTALL.md#7-use-update-or-remove-fotor); keep release-age protection and request separate approval for any exact-version exception. Never apply an npm selector to a Git source as an ordinary update.
98
+ During historical 0.6.0-test.2 acceptance, immediate `@next` updates retained 0.6.0-test.1; exact-version native updates passed. An unqualified update can also retain the saved version. Neither `@latest` update success nor eventual success after 24 hours is established. Use the [maintenance procedure](INSTALL.md#7-use-update-or-remove-fotor); keep release-age protection and request separate approval for any exact-version exception. Never apply an npm selector to a Git source as an ordinary update.
99
99
 
100
100
  Verify the source, version, files and actual skill/bridge directories in a new process. Preserve profile/store, credentials and connection parameters. If installation used a custom `--store-dir`, pass that same argument to updates and removal. A zero exit code with the old version is not an upgrade; cache clearing or reinstall does not turn it into a pass.
101
101
 
@@ -105,7 +105,7 @@ Verify the source, version, files and actual skill/bridge directories in a new p
105
105
 
106
106
  #### Production release
107
107
 
108
- First verify that the selected revision contains the DeepSeek Harness Bundle. Install this scoped package and its pinned bridge dependency to the chosen profile. Both components stay disabled until local setup. Record the old source and scope, remove only this Fotor Bundle through native controls, then add the selected source. Preserve the external credential directory; resolve both bridge and installed skill paths before enabling the new package.
108
+ First verify that the selected revision contains the DeepSeek Harness Bundle. Install this scoped package and its pinned bridge dependency to the chosen profile. Select Web **Enable now** or load the CLI profile; both components then configure automatically unless explicit user settings disable them. Record the old source and scope, remove only this Fotor Bundle through native controls, then add the selected source. Preserve the external credential directory and valid overrides; verify automatically resolved paths when enabling the new package.
109
109
 
110
110
  ```bash
111
111
  dsh plugin --profile web add "git+https://github.com/fotor-ai/dsh-fotor-plugin.git" --ignore-scripts
@@ -113,16 +113,18 @@ dsh plugin --profile web add "git+https://github.com/fotor-ai/dsh-fotor-plugin.g
113
113
 
114
114
  #### Test release
115
115
 
116
- First verify that the selected revision contains the DeepSeek Harness Bundle. Install this scoped package and its pinned bridge dependency to the chosen profile. Both components stay disabled until local setup. Record the old source and scope, remove only this Fotor Bundle through native controls, then add the selected source. Preserve the external credential directory; resolve both bridge and installed skill paths before enabling the new package.
116
+ First verify that the selected revision contains the DeepSeek Harness Bundle. Install this scoped package and its pinned bridge dependency to the chosen profile. Select Web **Enable now** or load the CLI profile; both components then configure automatically unless explicit user settings disable them. Record the old source and scope, remove only this Fotor Bundle through native controls, then add the selected source. Preserve the external credential directory and valid overrides; verify automatically resolved paths when enabling the new package.
117
117
 
118
118
  ```bash
119
119
  dsh plugin --profile web add "git+https://github.com/fotor-ai/dsh-fotor-plugin.git#release/test" --ignore-scripts
120
120
  ```
121
121
 
122
- Legacy `fotor` and scoped packages are different identities. Stop Fotor components, record old source/profile/store/paths, remove only their override rows, then remove the old Bundle with `dsh plugin --profile web remove fotor --config.ignore-scripts=true`. Add one scoped source and resolve both installed skill and bridge paths again. Preserve model settings, the external credential directory, callback/security parameters and daily browser state; do not automatically remove the old external bridge.
122
+ Legacy `fotor` and scoped packages are different identities. Stop Fotor components and record old source/profile/store/paths and explicit overrides, then remove the old Bundle with `dsh plugin --profile web remove fotor --config.ignore-scripts=true`. Add one scoped source. Version 0.6.1 resolves its runtime paths automatically unless explicit overrides apply; preserve valid values and correct or remove only obsolete path overrides through native configuration. Preserve disabled settings, model settings, the external credential directory, callback/security parameters and daily browser state; do not automatically remove the old external bridge.
123
123
 
124
124
  GitHub/npm switching uses the same explicit remove/add sequence, with `@fotor-ai/dsh-fotor-plugin` as the removal target. Keep one installed source and one component pair. Ordinary update does not rename packages or switch sources. See [maintenance](INSTALL.md#7-use-update-or-remove-fotor).
125
125
 
126
+ Uninstall retains external credentials but does not revoke server consent. Same-profile reinstall can reuse accepted authorization; enabling still establishes a new connection that requires actual discovery/query verification. Expired or rejected credentials may need new consent. Reinstall is not evidence of a successful native upgrade.
127
+
126
128
 
127
129
  ## Workflows
128
130
 
@@ -130,10 +132,11 @@ Start with [connection and model discovery](skills/fotor-connect/references/mcp-
130
132
 
131
133
  ## Bundle contents
132
134
 
133
- - `package.json` and `cordis.patch.yml`: the declarative Bundle and two initially disabled components.
134
- - `configuration.example.yml`: complete local setup example; never auto-applied.
135
+ - `package.json` and `cordis.patch.yml`: the Bundle and two enabled-by-default adapters.
136
+ - `configuration.example.yml`: optional complete legacy override; never auto-applied.
135
137
  - `INSTALL.md`: self-contained setup and migration guide.
136
138
  - `package-lock.json`: reviewed npm release-build input in Git snapshots; not a host-level Git dependency lock.
139
+ - `runtime/`: automatic configuration and cancellable connection ownership; no installation hooks.
137
140
  - npm artifacts additionally contain the pinned third-party runtime; Fotor skills remain script-free.
138
141
  - `.github/`: Git snapshot publication tooling, excluded from installed packages.
139
142
  - `skills/`, including each skill's `references/`: shared workflows and DeepSeek Harness bridge/browser guidance.
@@ -1,5 +1,6 @@
1
- # Copy outside the installed package and fill every absolute path.
2
- # Select a free callback port; use the same connection arguments for the client.
1
+ # Optional legacy full override. New installations need no path configuration.
2
+ # Copy outside the package only when intentionally overriding automatic values.
3
+ # The adapter runs its client with the same connection arguments before the proxy.
3
4
  # Overrides replace the complete config object; fields are not deep-merged.
4
5
  - id: fotor-skills
5
6
  disabled: false
package/cordis.patch.yml CHANGED
@@ -1,18 +1,10 @@
1
- # Installation declares inert host-owned components. Configure before enabling.
1
+ # Host activation resolves local paths; package installation has no lifecycle hook.
2
2
  - insert:
3
3
  - id: fotor-skills
4
- name: '@deepseek-ai/dsh-skill-filesystem'
5
- disabled: true
6
- config:
7
- providerName: fotor
8
- includeDefaultRoots: false
9
- customSkillDirs: []
4
+ name: '@fotor-ai/dsh-fotor-plugin/skills'
5
+ disabled: false
6
+ config: {}
10
7
  - id: fotor-mcp
11
- name: '@deepseek-ai/dsh-mcp-client'
12
- disabled: true
13
- config:
14
- serverName: fotor
15
- transport: stdio
16
- failOnStartupError: false
17
- reconnect:
18
- enabled: false
8
+ name: '@fotor-ai/dsh-fotor-plugin/mcp'
9
+ disabled: false
10
+ config: {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fotor-ai/dsh-fotor-plugin",
3
- "version": "0.6.0",
3
+ "version": "0.6.1-test.2",
4
4
  "description": "Connect to Fotor's production MCP service.",
5
5
  "author": {
6
6
  "name": "Fotor"
@@ -20,7 +20,8 @@
20
20
  "skills",
21
21
  "assets",
22
22
  "README.md",
23
- "LICENSE"
23
+ "LICENSE",
24
+ "runtime"
24
25
  ],
25
26
  "dsh": {
26
27
  "bundle": {
@@ -30,6 +31,11 @@
30
31
  "dependencies": {
31
32
  "mcp-remote": "0.15.2"
32
33
  },
34
+ "type": "module",
35
+ "exports": {
36
+ "./skills": "./runtime/skills.mjs",
37
+ "./mcp": "./runtime/mcp.mjs"
38
+ },
33
39
  "bundleDependencies": [
34
40
  "mcp-remote"
35
41
  ],
@@ -0,0 +1,84 @@
1
+ /** Bound the pinned bridge CLI without exposing its OAuth output or token files. */
2
+ import { spawn } from 'node:child_process';
3
+ import { createServer } from 'node:net';
4
+ import { childEnvironment } from './config.mjs';
5
+
6
+ export function toolsDiscovered(text) {
7
+ const marker = text.indexOf('Tools:');
8
+ if (marker < 0) return false;
9
+ const start = text.indexOf('{', marker);
10
+ if (start < 0) return false;
11
+ let depth = 0, quoted = false, escaped = false;
12
+ for (let index = start; index < text.length; index++) {
13
+ const char = text[index];
14
+ if (quoted) {
15
+ if (escaped) escaped = false;
16
+ else if (char === '\\') escaped = true;
17
+ else if (char === '"') quoted = false;
18
+ } else if (char === '"') quoted = true;
19
+ else if (char === '{') depth++;
20
+ else if (char === '}' && --depth === 0) {
21
+ try { const value = JSON.parse(text.slice(start, index + 1)); return Array.isArray(value.tools) && value.tools.every(tool => typeof tool.name === 'string'); }
22
+ catch { return false; }
23
+ }
24
+ }
25
+ return false;
26
+ }
27
+ export async function checkCallbackPort(args) {
28
+ if (!/^\d+$/.test(args[2] ?? '')) return;
29
+ const port = Number(args[2]);
30
+ const hostIndex = args.indexOf('--host');
31
+ const host = hostIndex < 0 ? 'localhost' : args[hostIndex + 1];
32
+ await new Promise((resolve, reject) => {
33
+ const probe = createServer(socket => socket.destroy());
34
+ probe.once('error', () => reject(new Error('Fotor callback port is unavailable; stop the conflicting task before retrying')));
35
+ probe.listen({port, host, exclusive:true}, () => probe.close(resolve));
36
+ });
37
+ }
38
+ export function authorize(connection, { signal, status, automaticMs = 90000, humanMs = 600000, spawnProcess = spawn } = {}) {
39
+ return new Promise((resolve, reject) => {
40
+ if (signal.aborted) return reject(new Error('Fotor connection cancelled'));
41
+ const config = connection.native;
42
+ const child = spawnProcess(config.command, [connection.client, ...config.args.slice(1)], {
43
+ cwd: config.cwd, env: childEnvironment(config.env), stdio: ['pipe', 'pipe', 'pipe'], shell: false,
44
+ });
45
+ let output = '', waiting = false, waited = false, failure, killTimer;
46
+ let started = Date.now(), remaining = automaticMs;
47
+ const finish = error => { failure ??= error; child.kill('SIGTERM'); killTimer ??= setTimeout(() => child.kill('SIGKILL'), 1500); };
48
+ const aborted = () => finish(new Error('Fotor connection cancelled'));
49
+ signal.addEventListener('abort', aborted, { once: true });
50
+ let timer = setTimeout(() => finish(new Error('Fotor automatic connection budget exceeded')), remaining);
51
+ const receive = chunk => {
52
+ output += chunk.toString('utf8');
53
+ if (Buffer.byteLength(output) > 1024 * 1024) return finish(new Error('Fotor bridge output exceeded its bound'));
54
+ if (/EADDRINUSE|address already in use/i.test(output)) return finish(new Error('Fotor callback port is already in use; stop the conflicting task or preserve and adjust its explicit configuration'));
55
+ if (/Could not open a browser automatically/.test(output)) return finish(new Error('Fotor browser unavailable; configure the ordinary browser before retrying'));
56
+ if (!waited && /Please authorize this client by visiting:|Authentication required\. Waiting for authorization/.test(output)) {
57
+ remaining = Math.max(1, remaining - (Date.now() - started));
58
+ clearTimeout(timer); waiting = true; waited = true;
59
+ status('waiting-authorization');
60
+ timer = setTimeout(() => finish(new Error('Fotor authorization wait expired')), humanMs);
61
+ }
62
+ if (waiting && /Connected successfully!/.test(output)) {
63
+ waiting = false; started = Date.now(); clearTimeout(timer);
64
+ timer = setTimeout(() => finish(new Error('Fotor automatic connection budget exceeded')), remaining);
65
+ status('preparing');
66
+ }
67
+ };
68
+ child.stdout.on('data', receive); child.stderr.on('data', receive);
69
+ child.on('error', () => { failure = new Error('Fotor authorization client could not start'); });
70
+ child.on('close', code => {
71
+ clearTimeout(timer); clearTimeout(killTimer); signal.removeEventListener('abort', aborted);
72
+ const discovered = toolsDiscovered(output);
73
+ const connected = /Connected successfully!/.test(output);
74
+ const transient = !waited && /EAI_AGAIN|ENOTFOUND|ECONNRESET|ETIMEDOUT|ECONNREFUSED/.test(output);
75
+ output = '';
76
+ if (failure) reject(failure);
77
+ else if (code === 0 && connected && discovered) resolve({ automaticMsUsed: automaticMs - remaining + (waiting ? 0 : Date.now() - started) });
78
+ else {
79
+ const error = new Error(waited ? 'Fotor authorization did not complete; disable and enable MCP to try again' : 'Fotor client did not connect and discover tools');
80
+ error.transient = transient; reject(error);
81
+ }
82
+ });
83
+ });
84
+ }