@xp266/dshtui 0.1.0 → 0.1.1

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/bin/dshtui.js CHANGED
@@ -29,7 +29,11 @@ function fail(message) {
29
29
  process.exit(1)
30
30
  }
31
31
 
32
- const dshProbe = spawnSync('dsh', ['--version'], { stdio: 'ignore', shell: process.platform === 'win32' })
32
+ // Windows resolves `dsh` through a .cmd shim, which only spawns with a
33
+ // shell; the command line is built as one quoted string there because
34
+ // passing an args array alongside shell:true is deprecated (DEP0190).
35
+ const windows = process.platform === 'win32'
36
+ const dshProbe = spawnSync('dsh', ['--version'], { stdio: 'ignore', shell: windows })
33
37
  if (dshProbe.error !== undefined) {
34
38
  fail('the dsh CLI was not found on PATH; install it with: npm install -g @deepseek-ai/dsh')
35
39
  }
@@ -47,11 +51,11 @@ if (!existsSync(profileDir)) {
47
51
  }
48
52
 
49
53
  const argv = process.argv.slice(2)
50
- const child = spawn('dsh', ['--profile', profile, ...argv], {
54
+ const quote = arg => /^[A-Za-z0-9_@%+=:,./-]+$/.test(arg) ? arg : `"${arg.replaceAll('"', '\\"')}"`
55
+ const command = ['dsh', '--profile', profile, ...argv].map(quote).join(' ')
56
+ const child = spawn(windows ? command : 'dsh', windows ? [] : ['--profile', profile, ...argv], {
51
57
  stdio: 'inherit',
52
- ...(process.platform === 'win32'
53
- ? { shell: true, windowsVerbatimArguments: true }
54
- : {}),
58
+ ...(windows ? { shell: true } : {}),
55
59
  })
56
60
  child.on('error', () => {
57
61
  fail('the dsh CLI was not found on PATH; install it with: npm install -g @deepseek-ai/dsh')
package/cordis.patch.yml CHANGED
@@ -1,29 +1,14 @@
1
1
  - insert:
2
- - id: storage
3
- name: '@deepseek-ai/dsh-storage'
4
- - id: storage-json
5
- name: '@deepseek-ai/dsh-storage-json'
6
- config:
7
- root: !!js dshHomePath('storages')
8
- - id: storage-domain
9
- name: '@deepseek-ai/dsh-storage-domain'
10
- config:
11
- backend: json
12
- # Persisted title/blank hints so the session picker lists cold sessions
13
- # without reading their logs.
14
- - id: session-projection-cache
15
- name: '@deepseek-ai/dsh-session-projection-cache'
16
- config:
17
- writeEveryEvents: 200
18
- writeIntervalMs: 5000
2
+ # The durable storage stack (storage, storage-json, storage-domain,
3
+ # session-projection-cache) is inserted by the dsh-base bundle since
4
+ # 0.1.2-rc.1 with the same configuration this file used to carry —
5
+ # re-inserting it here would collide with duplicate loader entry ids.
19
6
  - id: workspace
20
7
  name: '@deepseek-ai/dsh-workspace'
21
8
  - id: agent-presets
22
9
  name: '@deepseek-ai/dsh-agent-presets'
23
10
  config:
24
11
  default: standard
25
- - id: cordis-host-runner
26
- name: '@deepseek-ai/dsh-cordis-host-runner'
27
12
  # Durable image storage comes from the dsh base bundle's attachment-local
28
13
  # row; the TUI resolves ctx.attachments at send time and degrades to a
29
14
  # plain text message when the service is absent.
package/lib/index.mjs CHANGED
@@ -14,7 +14,6 @@ import Prism from "prismjs";
14
14
  import { marked } from "marked";
15
15
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
16
16
  import { fileURLToPath, pathToFileURL } from "node:url";
17
- import { resolveSessionPreset } from "@deepseek-ai/dsh-agent-presets";
18
17
  import { installModelSelection } from "@deepseek-ai/dsh-agent";
19
18
  import { ReasoningEffortId, createUserMessage } from "@deepseek-ai/dsh-llm";
20
19
  import { SessionId } from "@deepseek-ai/dsh-session";
@@ -10173,6 +10172,16 @@ async function createChatBridge(ctx) {
10173
10172
  image: info.inputModalities?.includes("image") ?? false
10174
10173
  };
10175
10174
  }
10175
+ function resolveSessionPreset(session) {
10176
+ for (let index = session.events.length - 1; index >= 0; index -= 1) {
10177
+ const event = session.events[index];
10178
+ if (event?.type === "agent-preset/selected") {
10179
+ const data = event.data;
10180
+ if (data?.agentPreset !== void 0) return data.agentPreset;
10181
+ }
10182
+ }
10183
+ return session.header?.agentPreset;
10184
+ }
10176
10185
  async function createAgent(cwd, presetId) {
10177
10186
  const resolved = presetId ?? (await presets?.resolve())?.id;
10178
10187
  const meta = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xp266/dshtui",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "description": "ink-based terminal UI plugin for DeepSeek Harness",
6
6
  "engines": {
@@ -5,7 +5,6 @@ import type {} from '@deepseek-ai/dsh-credentials'
5
5
  import type {} from '@deepseek-ai/dsh-settings'
6
6
  import type {} from '@deepseek-ai/dsh-agent-default-model'
7
7
  import type {} from '@deepseek-ai/dsh-agent-presets'
8
- import { resolveSessionPreset } from '@deepseek-ai/dsh-agent-presets'
9
8
  import { installModelSelection } from '@deepseek-ai/dsh-agent'
10
9
  import type { Agent, AgentHandle, AgentOptions, ModelSelection, ModelSelectionRef } from '@deepseek-ai/dsh-agent'
11
10
  import type { ContentBlock, LlmDiscoveredModel } from '@deepseek-ai/dsh-llm'
@@ -136,6 +135,11 @@ async function sendContent(
136
135
  agent.followup(createUserMessage({ content, source: { kind: 'user' } }))
137
136
  }
138
137
 
138
+ interface PresetSessionLike {
139
+ events: ReadonlyArray<{ type?: string; data?: unknown }>
140
+ header?: { agentPreset?: string }
141
+ }
142
+
139
143
  export const PERMISSION_PRESETS = ['workspace-write', 'danger-full-access', 'read-only'] as const
140
144
 
141
145
  interface PermissionPresetsLike {
@@ -663,6 +667,21 @@ export async function createChatBridge(ctx: Context): Promise<ChatBridge> {
663
667
  }
664
668
  }
665
669
 
670
+ // The 0.1.2 presets package dropped its resolveSessionPreset helper, so the
671
+ // session log is read directly: the newest selection event wins over the
672
+ // creation-time header value, matching the upstream semantics on every
673
+ // host version the peer range admits.
674
+ function resolveSessionPreset(session: PresetSessionLike): string | undefined {
675
+ for (let index = session.events.length - 1; index >= 0; index -= 1) {
676
+ const event = session.events[index]
677
+ if (event?.type === 'agent-preset/selected') {
678
+ const data = event.data as { agentPreset?: string } | undefined
679
+ if (data?.agentPreset !== undefined) return data.agentPreset
680
+ }
681
+ }
682
+ return session.header?.agentPreset
683
+ }
684
+
666
685
  async function createAgent(cwd: string, presetId?: string): Promise<AgentHandle> {
667
686
  const resolved = presetId ?? (await presets?.resolve())?.id
668
687
  const meta = { cwd, ...(resolved === undefined ? {} : { agentPreset: resolved }) }
@@ -701,7 +720,7 @@ export async function createChatBridge(ctx: Context): Promise<ChatBridge> {
701
720
  const setup = async (agentCtx: Context) => {
702
721
  installSelection(agentCtx)
703
722
  const session = agentCtx.agent?.session
704
- const resolved = session === undefined ? undefined : resolveSessionPreset(session)
723
+ const resolved = session === undefined ? undefined : resolveSessionPreset(session as PresetSessionLike)
705
724
  await presets?.mount(agentCtx, resolved)
706
725
  }
707
726
  const spawnResumedAgent = async (snapshot: { session: { cwd?: string }; events: SessionEvent[] }): Promise<AgentHandle> => {
@@ -809,7 +828,7 @@ export async function createChatBridge(ctx: Context): Promise<ChatBridge> {
809
828
  }
810
829
 
811
830
  function currentPreset(): string {
812
- const resolved = resolveSessionPreset(activeAgent.session)
831
+ const resolved = resolveSessionPreset(activeAgent.session as PresetSessionLike)
813
832
  return resolved ?? presets?.defaultId ?? 'standard'
814
833
  }
815
834