dsh-py-codeact 0.3.1 → 0.3.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.
Files changed (2) hide show
  1. package/lib/index.js +8 -3
  2. package/package.json +1 -1
package/lib/index.js CHANGED
@@ -10,11 +10,14 @@
10
10
  * @module dsh-py-codeact
11
11
  */
12
12
 
13
- import { CallId } from '@deepseek-ai/dsh-llm/brand'
13
+ import * as brand from '@deepseek-ai/dsh-llm/brand'
14
14
  import { contentHasImage, createUserMessage } from '@deepseek-ai/dsh-llm'
15
15
  import { defineTool, jsonSchemaToPy, renderToolsSdkPy } from '@deepseek-ai/dsh-tools'
16
16
  import { KERNEL_PY, PythonKernel } from './kernel.js'
17
17
 
18
+ // dsh renamed this brander in 0.1.2-alpha.2; both names remain in the declared peer range.
19
+ const CallId = brand.ToolCallId ?? brand.CallId
20
+
18
21
  /** Same prompt band as Code Mode's `tools:sdk`: tool guidance is 100–199. */
19
22
  const TOOLS_MODULE = '__dsh__.tools'
20
23
 
@@ -416,9 +419,11 @@ export function renderToolsSection(schemas) {
416
419
  // Python. That collision guard, and the `head` parameter it read, went with the Protocol stubs.
417
420
  // `async def f(*, ) -> T` is still a SyntaxError, which is why a parameterless tool emits no `*`.
418
421
  // Escaped for the block to stay COMPILABLE, which matters more here than fidelity: one description carrying a `\"\"\"` or ending in a backslash would close its own docstring and take every tool below it with it — the failure class where one tool invalidates the whole block. Neither appears in a live catalogue; a future MCP server is not bound by that.
422
+ // dsh-system-prompt has no literal `{{...}}` escape, so split whole runs of openers before tool prose enters a prompt section; pairwise replacement leaves a pair behind in odd runs.
423
+ const escapePromptGroups = (doc) => doc.replace(/\{{2,}/g, (run) => [...run].join(' '))
419
424
  const docstring = (doc) => {
420
425
  if (!doc) return [' ...']
421
- const text = doc.trim().replaceAll('\\', '\\\\').replaceAll('"""', '\\"\\"\\"')
426
+ const text = escapePromptGroups(doc.trim()).replaceAll('\\', '\\\\').replaceAll('"""', '\\"\\"\\"')
422
427
  // Split on every terminator Python's tokenizer honours, not just `\n`: CPython applies universal-newline translation to source, so a lone `\r` reaching the render becomes a real line break. Inside a COMMENTED MCP entry that break escapes the `# ` prefix and the rest of the description becomes live code.
423
428
  //
424
429
  // EXACTLY these three, which is narrower than it looks like it should be. `str.splitlines()` splits on eight more (`\v`, `\f`, `\x1c`-`\x1e`, `\x85`, `\u2028`, `\u2029`) and PCRE's `\R` on five of those — and every one of them stays INSIDE a `#` comment as far as the tokenizer is concerned, verified by compiling `# comment<ch>x = 1`. Widening to either would break descriptions apart at characters that never needed it.
@@ -426,7 +431,7 @@ export function renderToolsSection(schemas) {
426
431
  return lines.length === 1 ? [` """${lines[0]}"""`] : [' """', ...lines.map((line) => ` ${line}`.trimEnd()), ' """']
427
432
  }
428
433
  // A `#` comment cannot span lines, so a description that carries newlines is collapsed rather than emitted: left alone its second line parses as code.
429
- const trailing = (doc) => (doc ? ` # ${doc.trim().replace(/\s*(?:\r\n?|\n)\s*/g, ' ')}` : '')
434
+ const trailing = (doc) => (doc ? ` # ${escapePromptGroups(doc.trim()).replace(/\s*(?:\r\n?|\n)\s*/g, ' ')}` : '')
430
435
  /** @returns the lines to emit, and — separately — the type expressions they spell, which is what the `typing` import is derived from. Kept apart because prose is now emitted too: a description mentioning "Any file" must not import `Any`. */
431
436
  const signature = (spec) => {
432
437
  const body = docstring(spec.doc)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-py-codeact",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "CodeAct agent loop for the DeepSeek Harness: a persistent IPython session as the model's action space, with harness tools bridged in as a virtual `__dsh__.tools` module.",
5
5
  "license": "MIT",
6
6
  "repository": {