@argszero/cordis-plugin-thinking-loop-guard 0.1.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/LICENSE +21 -0
- package/README.md +90 -0
- package/cordis.patch.yml +16 -0
- package/lib/index.js +151 -0
- package/lib/types/index.d.ts +72 -0
- package/package.json +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 argszero
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# @argszero/cordis-plugin-thinking-loop-guard
|
|
2
|
+
|
|
3
|
+
Thinking-loop guard for the DeepSeek Harness (`dsh`). Detects an agent that
|
|
4
|
+
degrades into a **pure-thinking loop** — a step that emits only `reasoning-delta`
|
|
5
|
+
chunks, with **zero `text-delta` and zero `tool-call-delta`** — and reacts to break
|
|
6
|
+
the loop before it burns tokens until a human manually aborts the turn.
|
|
7
|
+
|
|
8
|
+
## The gap it closes
|
|
9
|
+
|
|
10
|
+
The in-tree `guard/` family watches two failure modes, both **tool-call-centric**:
|
|
11
|
+
|
|
12
|
+
| Guard | Hook | Catches |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| `guard/timeout-policy` | `tools/execute` | a tool call that exceeds a declared `timeoutMs` |
|
|
15
|
+
| `guard/repeat-tool-reminder` | `tools/post-execute` | the model repeating the **same tool call** chain |
|
|
16
|
+
|
|
17
|
+
Neither fires when the model emits **no tool call at all** — the exact shape of a
|
|
18
|
+
thinking loop. When a model (observed with
|
|
19
|
+
`deepseek-v4.1-flash-expires-on-0910` under `max`/`high` reasoning effort and a
|
|
20
|
+
long context) keeps emitting low-entropy reasoning ("好。执行。好。", repeated
|
|
21
|
+
"Let me / Wait / Actually / Hmm"), the agent-loop `turn()` `while (true)` never
|
|
22
|
+
sets `turnEnds` (`StepEndReason` only carries `completed` / `max-tokens`), so the
|
|
23
|
+
turn never ends until the user aborts it. See
|
|
24
|
+
[deepseek-ai/deepseek-harness discussion #5976](https://github.com/deepseek-ai/deepseek-harness/discussions/5976).
|
|
25
|
+
|
|
26
|
+
## How it works
|
|
27
|
+
|
|
28
|
+
This plugin is a **community-side fix** that needs no harness patch. It subscribes
|
|
29
|
+
to the public `agent/assistant-stream` event (scoped emit) and tallies the
|
|
30
|
+
`StreamChunk` composition of each attempt:
|
|
31
|
+
|
|
32
|
+
- a chunk of type `text-delta` or `tool-call-delta` **resets** the counter — this
|
|
33
|
+
step produced output, so it is not a thinking loop;
|
|
34
|
+
- a step that is **only** `reasoning-delta`, and at least `minReasoningChars`
|
|
35
|
+
long, counts toward `maxThinkingSteps`.
|
|
36
|
+
|
|
37
|
+
When the threshold is crossed (or the reasoning text shows an unambiguous
|
|
38
|
+
low-entropy repetition, i.e. `repeatRatio`), it escalates:
|
|
39
|
+
|
|
40
|
+
1. `escalate: 'warn'` → `agent.inject(...)` a notice into the next pre-step;
|
|
41
|
+
2. `escalate: 'steer'` (default) → `agent.steer(...)` a "stop deliberating and act"
|
|
42
|
+
steering message into the next step boundary;
|
|
43
|
+
3. `escalate: 'cancel'` → `agent.cancel(cause)` hard-aborts the active turn.
|
|
44
|
+
|
|
45
|
+
`agent.steer()`, `agent.inject()`, and `agent.cancel()` are all public methods on
|
|
46
|
+
the live `Agent`. A listener can react but cannot veto/rewrite an in-flight step;
|
|
47
|
+
steer and cancel are sufficient to break the loop.
|
|
48
|
+
|
|
49
|
+
## Install
|
|
50
|
+
|
|
51
|
+
Load it as an `@deepseek-ai/cordis` plugin in your `dsh` profile, or mount the
|
|
52
|
+
bundle patch:
|
|
53
|
+
|
|
54
|
+
```yaml
|
|
55
|
+
# cordis.patch.yml (already packaged in this plugin)
|
|
56
|
+
- insert:
|
|
57
|
+
- id: thinking-loop-guard
|
|
58
|
+
name: '@argszero/cordis-plugin-thinking-loop-guard'
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Configuration
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
interface Config {
|
|
65
|
+
/** Consecutive reasoning-only steps (each ≥ minReasoningChars, no output) before reacting. Default 3. */
|
|
66
|
+
maxThinkingSteps?: number
|
|
67
|
+
/** Minimum reasoning text in one step before it counts. Default 2048 chars. */
|
|
68
|
+
minReasoningChars?: number
|
|
69
|
+
/** Longest repeated token / total tokens at which the step is flagged. Default 0.5. */
|
|
70
|
+
repeatRatio?: number
|
|
71
|
+
/** Action on the threshold: 'warn' | 'steer' (default) | 'cancel'. */
|
|
72
|
+
escalate?: 'warn' | 'steer' | 'cancel'
|
|
73
|
+
/** Cancel cause when escalate is 'cancel'. Default 'thinking-loop'. */
|
|
74
|
+
cancelCause?: string
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Notes
|
|
79
|
+
|
|
80
|
+
- The detector is deliberately **conservative**: a step must be long
|
|
81
|
+
(`minReasoningChars`) and reasoning-only; a short thinking burst or a step with
|
|
82
|
+
any real output is ignored.
|
|
83
|
+
- Per-`Agent` state is kept in a `WeakMap`, so a disposed agent is collected and
|
|
84
|
+
its counters dropped.
|
|
85
|
+
- The low-entropy check is a cheap heuristic (longest repeated whitespace token
|
|
86
|
+
over total tokens); it runs only once a step is already long, so cost is bound.
|
|
87
|
+
|
|
88
|
+
## License
|
|
89
|
+
|
|
90
|
+
MIT
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# The @argszero/cordis-plugin-thinking-loop-guard bundle patch: the guard needs no
|
|
2
|
+
# deployment-specific config to mount (its defaults detect reasoning-only steps
|
|
3
|
+
# and steer on the second strike). Tune via a profile layer if desired:
|
|
4
|
+
#
|
|
5
|
+
# - set:
|
|
6
|
+
# - id: thinking-loop-guard
|
|
7
|
+
# config:
|
|
8
|
+
# maxThinkingSteps: 3
|
|
9
|
+
# minReasoningChars: 2048
|
|
10
|
+
# repeatRatio: 0.5
|
|
11
|
+
# escalate: steer
|
|
12
|
+
# cancelCause: thinking-loop
|
|
13
|
+
|
|
14
|
+
- insert:
|
|
15
|
+
- id: thinking-loop-guard
|
|
16
|
+
name: '@argszero/cordis-plugin-thinking-loop-guard'
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thinking-loop guard for the dsh harness.
|
|
3
|
+
*
|
|
4
|
+
* Closes a guard-layer gap the in-tree `guard/` family does not cover.
|
|
5
|
+
* `guard/timeout-policy` is a per-tool `tools/execute` deadline and
|
|
6
|
+
* `guard/repeat-tool-reminder` is a same-tool-call chain detector — only a tool
|
|
7
|
+
* *call* arms either. When a model degrades into a pure-thinking loop
|
|
8
|
+
* (`deepseek-v4.1-flash-expires-on-0910` under `max`/`high` reasoning effort and
|
|
9
|
+
* a long context), it emits only `reasoning-delta` chunks — zero `text-delta`,
|
|
10
|
+
* zero `tool-call-delta` — so neither fires, `turn()` never sets `turnEnds`, and
|
|
11
|
+
* the agent-loop `while (true)` never breaks until the user manually aborts.
|
|
12
|
+
*
|
|
13
|
+
* This plugin is the community-side fix. It listens to the public
|
|
14
|
+
* `agent/assistant-stream` event, tallies the `StreamChunk` composition per
|
|
15
|
+
* `(agent, turn, step)`, and detects a step that is reasoning-only AND shows a
|
|
16
|
+
* low-entropy repetition. It then escalates through configured reactions:
|
|
17
|
+
* a `warn` inject, then a `steer`, then a `cancel`.
|
|
18
|
+
*
|
|
19
|
+
* Mechanism notes (verified against packages/core/agent-loop/src/agent.ts and
|
|
20
|
+
* packages/core/agent/src/runtime-types.ts on dsh 0.1.5-alpha.1):
|
|
21
|
+
* - `agent/assistant-stream` is scoped emit; `frame` is one
|
|
22
|
+
* `AssistantStreamFrame` (`start` | `chunk` | `end`).
|
|
23
|
+
* - `frame.chunk: StreamChunk` distinguishes `reasoning-delta` / `text-delta` /
|
|
24
|
+
* `tool-call-delta` (packages/llm/llm/src/types.ts).
|
|
25
|
+
* - `payload.agent.steer(message)`, `payload.agent.inject(message)`, and
|
|
26
|
+
* `payload.agent.cancel(cause)` are public methods.
|
|
27
|
+
* - A listener can react but cannot veto/rewrite an in-flight step; steer and
|
|
28
|
+
* cancel are sufficient to break the loop.
|
|
29
|
+
*
|
|
30
|
+
* @module @argszero/cordis-plugin-thinking-loop-guard
|
|
31
|
+
*/
|
|
32
|
+
import { Context } from '@deepseek-ai/cordis';
|
|
33
|
+
import z from '@deepseek-ai/schemastery';
|
|
34
|
+
import { createUserMessage } from '@deepseek-ai/dsh-llm';
|
|
35
|
+
export const Config = z.object({
|
|
36
|
+
maxThinkingSteps: z.number().min(2).default(3),
|
|
37
|
+
minReasoningChars: z.number().min(256).default(2048),
|
|
38
|
+
repeatRatio: z.number().min(0).max(1).default(0.5),
|
|
39
|
+
escalate: z.union(['warn', 'steer', 'cancel']).default('steer'),
|
|
40
|
+
cancelCause: z.string().default('thinking-loop'),
|
|
41
|
+
});
|
|
42
|
+
export const name = 'thinking-loop-guard';
|
|
43
|
+
const PLUGIN_SOURCE = { kind: 'plugin', plugin: 'thinking-loop-guard' };
|
|
44
|
+
function message(text, form) {
|
|
45
|
+
return createUserMessage({
|
|
46
|
+
content: [{ type: 'text', text }],
|
|
47
|
+
source: { ...PLUGIN_SOURCE, form, summary: 'thinking-loop-guard' },
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/** Low-entropy ratio: longest repeated whitespace token / total tokens. */
|
|
51
|
+
function repeatRatio(reasoning) {
|
|
52
|
+
if (reasoning.length < 16)
|
|
53
|
+
return 0;
|
|
54
|
+
const tokens = reasoning.split(/\s+/u).filter((t) => t.length > 0);
|
|
55
|
+
if (tokens.length < 8)
|
|
56
|
+
return 0;
|
|
57
|
+
const counts = new Map();
|
|
58
|
+
for (const tok of tokens) {
|
|
59
|
+
const key = tok.toLowerCase();
|
|
60
|
+
counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
61
|
+
}
|
|
62
|
+
let best = 1;
|
|
63
|
+
for (const [, count] of counts)
|
|
64
|
+
if (count > best)
|
|
65
|
+
best = count;
|
|
66
|
+
return best / tokens.length;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Install the listener. Per-`Agent` state is keyed in a `WeakMap` so a disposed
|
|
70
|
+
* agent is collected; counters are scoped to one agent lifecycle.
|
|
71
|
+
*/
|
|
72
|
+
export function apply(ctx, config) {
|
|
73
|
+
const maxThinkingSteps = config.maxThinkingSteps;
|
|
74
|
+
const minReasoningChars = config.minReasoningChars;
|
|
75
|
+
const repeatRatioThreshold = config.repeatRatio;
|
|
76
|
+
const escalate = config.escalate;
|
|
77
|
+
const cancelCause = config.cancelCause;
|
|
78
|
+
const states = new WeakMap();
|
|
79
|
+
function stateFor(agent) {
|
|
80
|
+
let state = states.get(agent);
|
|
81
|
+
if (state === undefined) {
|
|
82
|
+
state = { attempt: null, thinkingSteps: 0, reacted: false };
|
|
83
|
+
states.set(agent, state);
|
|
84
|
+
}
|
|
85
|
+
return state;
|
|
86
|
+
}
|
|
87
|
+
function reset(state) {
|
|
88
|
+
state.thinkingSteps = 0;
|
|
89
|
+
state.reacted = false;
|
|
90
|
+
}
|
|
91
|
+
function react(state, agent) {
|
|
92
|
+
if (state.reacted)
|
|
93
|
+
return;
|
|
94
|
+
state.reacted = true;
|
|
95
|
+
switch (escalate) {
|
|
96
|
+
case 'warn':
|
|
97
|
+
agent.inject(message('The agent has produced several long reasoning-only steps with no output. '
|
|
98
|
+
+ 'If this continues it will be interrupted.', 'notice'));
|
|
99
|
+
return;
|
|
100
|
+
case 'steer':
|
|
101
|
+
agent.steer(message('You are repeating the same reasoning without acting. Stop deliberating and '
|
|
102
|
+
+ 'either call a tool or produce a concise answer now.', 'notice'));
|
|
103
|
+
return;
|
|
104
|
+
case 'cancel':
|
|
105
|
+
agent.cancel(cancelCause);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
ctx.on('agent/assistant-stream', (payload) => {
|
|
110
|
+
const { agent, frame } = payload;
|
|
111
|
+
const state = stateFor(agent);
|
|
112
|
+
if (frame.type === 'start') {
|
|
113
|
+
state.attempt = { reasoning: '', hasOutput: false };
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (frame.type === 'chunk') {
|
|
117
|
+
if (state.attempt === null)
|
|
118
|
+
return;
|
|
119
|
+
const chunk = frame.chunk;
|
|
120
|
+
if (chunk.type === 'reasoning-delta') {
|
|
121
|
+
state.attempt.reasoning += chunk.text;
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (chunk.type === 'text-delta' || chunk.type === 'tool-call-delta') {
|
|
125
|
+
state.attempt.hasOutput = true;
|
|
126
|
+
}
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (frame.type === 'end') {
|
|
130
|
+
if (state.attempt === null)
|
|
131
|
+
return;
|
|
132
|
+
const attempt = state.attempt;
|
|
133
|
+
state.attempt = null;
|
|
134
|
+
if (attempt.hasOutput) {
|
|
135
|
+
// Any text or tool output means this is NOT a thinking loop.
|
|
136
|
+
reset(state);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (attempt.reasoning.length < minReasoningChars) {
|
|
140
|
+
// Too short to be a degenerate run; do not count it.
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
// A long reasoning-only step: count it toward the threshold.
|
|
144
|
+
state.thinkingSteps += 1;
|
|
145
|
+
const ratio = repeatRatio(attempt.reasoning);
|
|
146
|
+
if (state.thinkingSteps >= maxThinkingSteps || ratio >= repeatRatioThreshold) {
|
|
147
|
+
react(state, agent);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thinking-loop guard for the dsh harness.
|
|
3
|
+
*
|
|
4
|
+
* Closes a guard-layer gap the in-tree `guard/` family does not cover.
|
|
5
|
+
* `guard/timeout-policy` is a per-tool `tools/execute` deadline and
|
|
6
|
+
* `guard/repeat-tool-reminder` is a same-tool-call chain detector — only a tool
|
|
7
|
+
* *call* arms either. When a model degrades into a pure-thinking loop
|
|
8
|
+
* (`deepseek-v4.1-flash-expires-on-0910` under `max`/`high` reasoning effort and
|
|
9
|
+
* a long context), it emits only `reasoning-delta` chunks — zero `text-delta`,
|
|
10
|
+
* zero `tool-call-delta` — so neither fires, `turn()` never sets `turnEnds`, and
|
|
11
|
+
* the agent-loop `while (true)` never breaks until the user manually aborts.
|
|
12
|
+
*
|
|
13
|
+
* This plugin is the community-side fix. It listens to the public
|
|
14
|
+
* `agent/assistant-stream` event, tallies the `StreamChunk` composition per
|
|
15
|
+
* `(agent, turn, step)`, and detects a step that is reasoning-only AND shows a
|
|
16
|
+
* low-entropy repetition. It then escalates through configured reactions:
|
|
17
|
+
* a `warn` inject, then a `steer`, then a `cancel`.
|
|
18
|
+
*
|
|
19
|
+
* Mechanism notes (verified against packages/core/agent-loop/src/agent.ts and
|
|
20
|
+
* packages/core/agent/src/runtime-types.ts on dsh 0.1.5-alpha.1):
|
|
21
|
+
* - `agent/assistant-stream` is scoped emit; `frame` is one
|
|
22
|
+
* `AssistantStreamFrame` (`start` | `chunk` | `end`).
|
|
23
|
+
* - `frame.chunk: StreamChunk` distinguishes `reasoning-delta` / `text-delta` /
|
|
24
|
+
* `tool-call-delta` (packages/llm/llm/src/types.ts).
|
|
25
|
+
* - `payload.agent.steer(message)`, `payload.agent.inject(message)`, and
|
|
26
|
+
* `payload.agent.cancel(cause)` are public methods.
|
|
27
|
+
* - A listener can react but cannot veto/rewrite an in-flight step; steer and
|
|
28
|
+
* cancel are sufficient to break the loop.
|
|
29
|
+
*
|
|
30
|
+
* @module @argszero/cordis-plugin-thinking-loop-guard
|
|
31
|
+
*/
|
|
32
|
+
import { Context } from '@deepseek-ai/cordis';
|
|
33
|
+
import z from '@deepseek-ai/schemastery';
|
|
34
|
+
/** Plugin configuration. */
|
|
35
|
+
export interface Config {
|
|
36
|
+
/**
|
|
37
|
+
* Consecutive reasoning-only steps (each at least `minReasoningChars` long,
|
|
38
|
+
* no text/tool output) before a reaction. Default `3`.
|
|
39
|
+
*/
|
|
40
|
+
maxThinkingSteps?: number;
|
|
41
|
+
/**
|
|
42
|
+
* Minimum reasoning text within one step before it counts as a thinking step
|
|
43
|
+
* at all; a short burst is normal. Default `2048` chars.
|
|
44
|
+
*/
|
|
45
|
+
minReasoningChars?: number;
|
|
46
|
+
/**
|
|
47
|
+
* Approximate low-entropy repeat detection: the longest single repeated
|
|
48
|
+
* whitespace-delimited token, as a fraction of total tokens in the step's
|
|
49
|
+
* reasoning text. A degenerate "好。执行。" loop is near 1.0; coherent
|
|
50
|
+
* exploration is low. Only consulted once `minReasoningChars` is met.
|
|
51
|
+
* Default `0.5`.
|
|
52
|
+
*/
|
|
53
|
+
repeatRatio?: number;
|
|
54
|
+
/**
|
|
55
|
+
* Reaction to fire when the threshold is crossed. `warn` injects a notice,
|
|
56
|
+
* `steer` sends a steering message, `cancel` hard-aborts the turn. Default
|
|
57
|
+
* `steer`.
|
|
58
|
+
*/
|
|
59
|
+
escalate?: 'warn' | 'steer' | 'cancel';
|
|
60
|
+
/** Cancel cause used when `escalate` is `cancel`. Default `'thinking-loop'`. */
|
|
61
|
+
cancelCause?: string;
|
|
62
|
+
}
|
|
63
|
+
/** Resolved config: every field carries its validated default. */
|
|
64
|
+
type ResolvedConfig = Required<Config>;
|
|
65
|
+
export declare const Config: z<Config>;
|
|
66
|
+
export declare const name = "thinking-loop-guard";
|
|
67
|
+
/**
|
|
68
|
+
* Install the listener. Per-`Agent` state is keyed in a `WeakMap` so a disposed
|
|
69
|
+
* agent is collected; counters are scoped to one agent lifecycle.
|
|
70
|
+
*/
|
|
71
|
+
export declare function apply(ctx: Context, config: ResolvedConfig): void;
|
|
72
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@argszero/cordis-plugin-thinking-loop-guard",
|
|
3
|
+
"description": "Thinking-loop guard for dsh: detects reasoning-only degenerate steps (no text, no tool call) via the agent/assistant-stream event and escalates warn -> steer -> cancel to break the loop.",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"types": "lib/types/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/types/index.d.ts",
|
|
11
|
+
"default": "./lib/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./src/*": "./src/*",
|
|
14
|
+
"./package.json": "./package.json"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"lib/index.js",
|
|
18
|
+
"lib/types/**/*.d.ts",
|
|
19
|
+
"cordis.patch.yml",
|
|
20
|
+
"README.md",
|
|
21
|
+
"LICENSE"
|
|
22
|
+
],
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"keywords": [
|
|
25
|
+
"cordis",
|
|
26
|
+
"deepseek-harness",
|
|
27
|
+
"dsh",
|
|
28
|
+
"plugin",
|
|
29
|
+
"guard",
|
|
30
|
+
"thinking-loop",
|
|
31
|
+
"reasoning"
|
|
32
|
+
],
|
|
33
|
+
"dsh": {
|
|
34
|
+
"bundle": {
|
|
35
|
+
"patch": "./cordis.patch.yml"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"@deepseek-ai/cordis": "^4.0.2"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@deepseek-ai/dsh-agent": "^0.1.5-alpha.1",
|
|
43
|
+
"@deepseek-ai/dsh-llm": "^0.1.5-alpha.1",
|
|
44
|
+
"@deepseek-ai/schemastery": "^3.18.1"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
48
|
+
"typescript": "^5.5.0"
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "tsc",
|
|
52
|
+
"prepublishOnly": "tsc"
|
|
53
|
+
}
|
|
54
|
+
}
|