Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 43 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,10 @@ jobs:
cache: 'pnpm'

- name: Install dependencies
run: pnpm install --filter @parallel-web/dsh-web-search... --frozen-lockfile
run: pnpm install --filter @parallel-web/dsh-web-search... --filter @parallel-web/dsh-responses-subagent... --frozen-lockfile

- name: Run deterministic plugin checks
run: pnpm --filter @parallel-web/dsh-web-search check
run: pnpm --filter @parallel-web/dsh-web-search --filter @parallel-web/dsh-responses-subagent run check

- name: Verify packed DSH profile lifecycle
shell: bash
Expand All @@ -133,6 +133,47 @@ jobs:
node packages/dsh-web-search/scripts/verify-packed-profile.mjs \
--dsh-home "$dsh_home" \
--expected-version "$version"

pnpm --dir packages/dsh-responses-subagent pack --pack-destination "$pack_dir"
responses_artifact="$(find "$pack_dir" -name '*dsh-responses-subagent*.tgz' -print -quit)"
tar -xOzf "$responses_artifact" package/package.json | node -e '
const manifest = JSON.parse(require("node:fs").readFileSync(0, "utf8"));
if (manifest.private || manifest.publishConfig?.access !== "public" ||
manifest.dsh?.bundle?.patch !== "./cordis.patch.yml") {
throw new Error("invalid packed Responses plugin manifest");
}
'
DSH_HOME="$dsh_home" pnpm --dir packages/dsh-web-search exec dsh \
plugin --profile web add "$responses_artifact"
DSH_HOME="$dsh_home" pnpm --dir packages/dsh-web-search exec dsh \
--profile web --dump-config > "$dsh_home/combined.yml"
grep -Fq 'id: subagent-parallel-responses' "$dsh_home/combined.yml"
grep -Fq 'toolName: parallel_research' "$dsh_home/combined.yml"
grep -Fq 'id: web-search-parallel' "$dsh_home/combined.yml"

node --input-type=module -e '
import assert from "node:assert/strict";
import { createRequire } from "node:module";
import { join } from "node:path";

const require = createRequire(join(process.argv[1], "profiles/web/package.json"));
const plugin = await import(require.resolve("@parallel-web/dsh-responses-subagent"));
const { Context } = await import(require.resolve("@deepseek-ai/cordis"));
const subagents = await import(require.resolve("@deepseek-ai/dsh-subagent"));
const context = new Context();
context.provide("systemPrompt", { section() {} });
await context.plugin(subagents.default);
await context.plugin(plugin, { apiKey: "parallel_test_packed_profile" });
assert.equal(plugin.Config.dict.apiKey.meta.role, "secret");
assert.equal(context.subagents.getProvider("parallel-responses")?.inheritsParentContext, false);
' "$dsh_home"

DSH_HOME="$dsh_home" pnpm --dir packages/dsh-web-search exec dsh \
plugin --profile web remove @parallel-web/dsh-responses-subagent
DSH_HOME="$dsh_home" pnpm --dir packages/dsh-web-search exec dsh \
--profile web --dump-config > "$dsh_home/responses-removed.yml"
cmp "$dsh_home/after.yml" "$dsh_home/responses-removed.yml"

DSH_HOME="$dsh_home" pnpm --dir packages/dsh-web-search exec dsh \
plugin --profile web remove @parallel-web/dsh-web-search
DSH_HOME="$dsh_home" pnpm --dir packages/dsh-web-search exec dsh \
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ node_modules/
# Build output
dist/
packages/dsh-web-search/lib/
packages/dsh-responses-subagent/lib/
*.tsbuildinfo

# Testing
Expand Down
13 changes: 9 additions & 4 deletions PUBLISHING.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
# Publishing Guide

This monorepo publishes four npm packages, each versioned, tagged, and released **independently**:
This monorepo tracks five publishable npm packages, each versioned, tagged, and released
**independently**:

- `@parallel-web/ai-sdk-tools` — `packages/ai-sdk-tools`
- `@parallel-web/dsh-responses-subagent` — `packages/dsh-responses-subagent`
- `@parallel-web/dsh-web-search` — `packages/dsh-web-search`
- `@parallel-web/opencode-plugin` — `packages/opencode-plugin`
- `@parallel-web/pi-extension` — `packages/pi-extension`

`@parallel-web/dsh-responses-subagent` has not yet been published. It can be installed only
from a local tarball until an npm organization owner completes its reviewed first release.

(`@parallel-web/oauth` in `packages/parallel-oauth` is `private` — it is bundled into the
OpenCode plugin and Pi extension at build time and is never published.)

Expand Down Expand Up @@ -57,12 +62,12 @@ the reviewed bootstrap release manually from a clean, updated `main` checkout:

```bash
pnpm install --frozen-lockfile
pnpm --filter @parallel-web/dsh-web-search check
pnpm --filter @parallel-web/dsh-responses-subagent check
BOOTSTRAP_DIR="$(mktemp -d)"
pnpm --dir packages/dsh-web-search pack --pack-destination "$BOOTSTRAP_DIR"
pnpm --dir packages/dsh-responses-subagent pack --pack-destination "$BOOTSTRAP_DIR"
BOOTSTRAP_TARBALL="$(find "$BOOTSTRAP_DIR" -name '*.tgz' -print -quit)"
npm publish "$BOOTSTRAP_TARBALL" --access public --tag rc
npm view @parallel-web/dsh-web-search dist-tags --json
npm view @parallel-web/dsh-responses-subagent dist-tags --json
```

The npm owner should inspect the tarball listing before the publish and complete npm's 2FA prompt.
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Monorepo for @parallel-web npm packages.
## Packages

- [`@parallel-web/ai-sdk-tools`](./packages/ai-sdk-tools) - AI SDK tools for Parallel Web
- [`@parallel-web/dsh-responses-subagent`](./packages/dsh-responses-subagent) - Parallel Responses research subagent for DeepSeek Harness
- [`@parallel-web/dsh-web-search`](./packages/dsh-web-search) - Parallel Search provider for DeepSeek Harness
- [`@parallel-web/opencode-plugin`](./packages/opencode-plugin) - Opencode plugin for Parallel Web
- [`@parallel-web/pi-extension`](./packages/pi-extension) - pi agent extension for Parallel Web
Expand Down
124 changes: 124 additions & 0 deletions packages/dsh-responses-subagent/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# Parallel Responses for DeepSeek Harness

This DeepSeek Harness plugin adds `parallel_research`, an opt-in
[Parallel Responses](https://docs.parallel.ai/responses-api/examples/research-subagent)
subagent that returns complete, cited web research. It works alongside
`web_search` without changing the existing Parallel Search plugin.

Only the explicitly delegated question is forwarded as research input. Parent
history, files, workspace state, tools, and environment details are never
gathered automatically.

## Availability

This plugin is an unreleased preview. It is not published to npm, and there is
no release tarball to download yet. The setup below requires a locally built
preview tarball. If you want to build one yourself, see [Development](#development).

## Set up a preview

You will need:

- Node.js 22.19 or later in the 22.x series, or Node.js 24 or newer;
- pnpm 10 or newer, available in your terminal;
- a [Parallel API key](https://platform.parallel.ai/); and
- a preview `.tgz` file for this plugin.

### 1. Install the plugin

Install into Harness's `web` profile. Replace `/absolute/path/to/plugin.tgz`
with the path to your preview tarball:

```sh
npx --yes @deepseek-ai/dsh@0.1.1-rc.2 \
plugin --profile web add /absolute/path/to/plugin.tgz
```

### 2. Start Harness

Set your Parallel API key in the same terminal that starts Harness:

```sh
export PARALLEL_API_KEY="your-key"
npx --yes @deepseek-ai/dsh@0.1.1-rc.2 web
```

Open [http://127.0.0.1:3080](http://127.0.0.1:3080), configure your parent
model and its credentials in **Settings > Models**, choose a workspace, and
start a new session. Restart Harness if it was already running when you
installed the plugin or set the key.

### 3. Try a research question

Ask Harness to use the plugin, for example:

> Use parallel_research to compare Node.js 22 and 24 support schedules. Include
> links to the official sources.

The agent calls `parallel_research` and receives a researched answer with
source URLs. It can still use `web_search` separately.

To check that the plugin is installed in the profile:

```sh
npx --yes @deepseek-ai/dsh@0.1.1-rc.2 --profile web --dump-config
```

Look for `subagent-parallel-responses` and `toolName: parallel_research`.
If the plugin reports that `PARALLEL_API_KEY` is required, set the key in the
terminal that starts Harness and restart it.

## Research depth and parallelism

Ask the parent agent to delegate a complete, standalone research question. It
receives guidance to preserve constraints, prioritize primary sources, and
cite the returned URLs.

To choose the research depth, edit the `subagent-parallel-responses` entry in
`~/.dsh/profiles/web/cordis.patch.yml`:

```yaml
- id: subagent-parallel-responses
config:
effort: low
```

Choose `low` for focused questions, `medium` (the default) for ordinary
research, or `high` for deeper synthesis. At low effort, the parent is
encouraged to dispatch independent questions together. Harness schedules
parallel tool calls itself, allowing 10 by default. To allow more, increase
**Settings > Plugins > Agent loop > Parallel tool calls**.

Keep `PARALLEL_API_KEY` in the launch environment, not in this profile.

## Remove

```sh
npx --yes @deepseek-ai/dsh@0.1.1-rc.2 \
plugin --profile web remove @parallel-web/dsh-responses-subagent
```

Restart Harness after removing the plugin.

## Development

These steps are for building a preview from source. Use a checkout containing
this package, available in [PR #42](https://github.com/parallel-web/parallel-npm-packages/pull/42).
From the repository root, enable Corepack to use the pinned pnpm version,
install dependencies, and run the package checks:

```sh
corepack enable
pnpm install --frozen-lockfile
pnpm --filter @parallel-web/dsh-responses-subagent check
```

The checks include the build. Pack it into a local tarball:

```sh
PREVIEW_PACK_DIR="$(mktemp -d)"
pnpm --dir packages/dsh-responses-subagent pack --pack-destination "$PREVIEW_PACK_DIR"
```

Use the tarball path printed by `pack` in the [preview setup](#1-install-the-plugin).
This does not publish the package.
11 changes: 11 additions & 0 deletions packages/dsh-responses-subagent/cordis.patch.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
- insert:
- id: subagent-parallel-responses
name: '@parallel-web/dsh-responses-subagent'

- id: tool-subagent-parallel-responses
name: '@deepseek-ai/dsh-tool-subagent'
config:
provider: parallel-responses
toolName: parallel_research
enableRunInBackground: false
maxDepth: provider-managed
77 changes: 77 additions & 0 deletions packages/dsh-responses-subagent/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{
"name": "@parallel-web/dsh-responses-subagent",
"description": "Parallel Responses research subagent for DeepSeek Harness",
"version": "0.1.0-rc.0",
"author": "Parallel Web",
"license": "MIT",
"type": "module",
"sideEffects": false,
"engines": {
"node": "^22.19.0 || >=24.0.0"
},
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
"exports": {
".": {
"types": "./lib/index.d.ts",
"default": "./lib/index.js"
},
"./package.json": "./package.json"
},
"files": [
"lib/index.js",
"lib/index.d.ts",
"cordis.patch.yml",
"README.md"
],
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/parallel-web/parallel-npm-packages.git",
"directory": "packages/dsh-responses-subagent"
},
"keywords": [
"deepseek-harness",
"dsh-plugin",
"parallel-responses",
"research-agent"
],
"dsh": {
"bundle": {
"patch": "./cordis.patch.yml"
}
},
"scripts": {
"build": "tsdown",
"check": "pnpm run typecheck && pnpm run lint && pnpm run test && pnpm run build",
"clean": "rm -rf lib",
"lint": "oxlint src tests tsdown.config.ts",
"prepare": "pnpm run build",
"test": "vitest run",
"typecheck": "tsc --noEmit"
},
"peerDependencies": {
"@deepseek-ai/cordis": "4.0.1",
"@deepseek-ai/dsh-launch-environment": "^0.1.0-rc.6 || ^0.1.1-rc.2",
"@deepseek-ai/dsh-session": "^0.1.0-rc.6 || ^0.1.1-rc.2",
"@deepseek-ai/dsh-subagent": "^0.1.0-rc.6 || ^0.1.1-rc.2",
"@deepseek-ai/dsh-tool-subagent": "^0.1.0-rc.6 || ^0.1.1-rc.2"
},
"dependencies": {
"@deepseek-ai/schemastery": "3.18.1"
},
"devDependencies": {
"@deepseek-ai/cordis": "4.0.1",
"@deepseek-ai/dsh-launch-environment": "0.1.0-rc.6",
"@deepseek-ai/dsh-session": "0.1.0-rc.6",
"@deepseek-ai/dsh-subagent": "0.1.0-rc.6",
"@deepseek-ai/dsh-tool-subagent": "0.1.0-rc.6",
"@types/node": "26.2.0",
"oxlint": "1.76.0",
"tsdown": "0.22.2",
"typescript": "6.0.3",
"vitest": "4.1.8"
}
}
Loading
Loading