qwen-code/packages/sdk-typescript/package.json
jinye dcf7681d65
feat(core,cli): add generic atomicWriteFile, wire into Write/Edit tools, upgrade @types/node (#4096)
* feat(core): add generic atomicWriteFile and wire into Write/Edit tools

The Write and Edit tools used bare fs.writeFile, risking half-written
corrupt files on crash or power loss. Both tools' source code contained
explicit TODOs noting atomic write as the fix.

- Add atomicWriteFile() supporting string/Buffer with flush (fsync),
  permission preservation, symlink resolution, and EXDEV fallback
- Wire StandardFileSystemService.writeTextFile() through atomicWriteFile
- Refactor atomicWriteJSON to delegate to atomicWriteFile (adds fsync)
- Deduplicate renameWithRetry from runtimeStatus.ts
- Add flush:true to writeWithBackupSync for settings writes
- Upgrade @types/node to ^22.0.0 (flush option type support)

Closes the TODO in write-file.ts:371-385 and edit.ts:487-497.
Ref: #4095 (Phase 1)

🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)

* fix(core): address review comments on atomicWriteFile

- Fix permission window: separate existingMode from desiredMode so
  mode is set during writeFile (not just chmod after), eliminating
  the brief window where tmp file has overly permissive defaults
- Fix broken symlink handling: use lstat+readlink instead of realpath
  to correctly resolve symlinks whose targets don't exist yet,
  preventing the symlink from being replaced by rename
- Add test for writing through a broken symlink

🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)

* fix(core): address wenshao review on atomicWriteFile

- Fix Windows bug: use path.isAbsolute() instead of startsWith('/')
- Hoist path import to top-level static import
- Resolve full symlink chains via loop (handles A→B→C), with
  ELOOP guard at 40 hops matching POSIX SYMLOOP_MAX
- Mask stat.mode with 0o7777 to strip file-type bits
- Document EXDEV fallback atomicity loss in JSDoc
- Add tests for relative symlinks and multi-level symlink chains

🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code)

* fix(test): fix CI failures from atomic write changes

- edit.test.ts: mock writeTextFile instead of chmod 444 for write error
  test — atomic write creates tmp file in same dir, so readonly target
  no longer triggers a write error
- atomicFileWrite.test.ts: skip permission tests on Windows — chmod is
  a no-op and stat.mode always returns 0o666

* fix(core): address deepseek review on atomicWriteFile

- Add try/catch around chmod calls to handle FAT/exFAT filesystems
  where POSIX permissions are not supported
- Add explicit type annotation to lstats variable

* fix: restore version numbers to 0.15.11 after rebase

* fix(core): resolve relative symlinks through directory symlinks

resolveSymlinkChain used path.dirname() to resolve relative symlink
targets, which is purely string-based. When intermediate path
components are themselves directory symlinks, the result would be
wrong (e.g. /a/link/file → ../target resolves to /a/target instead
of the kernel-resolved /b/target).

Use fs.realpath() on the parent directory to get the kernel-resolved
base for relative-target resolution.

* fix(test): normalize path separators in directory symlink test

Windows readlink returns native separators (backslashes), causing
the directory-symlink test to fail on Windows CI. Wrap both sides
of the symlink-target comparison with path.normalize.

* refactor(core): dedupe write/chmod logic in atomicWriteFile

- Extract writeOptions construction and tryChmod helper, removing
  duplication between the main write path and the EXDEV fallback
- Document atomicWriteJSON's symlink-preservation behavior

Addresses deepseek review on PR #4096.
2026-05-15 17:52:50 +08:00

75 lines
1.9 KiB
JSON

{
"name": "@qwen-code/sdk",
"version": "0.1.7",
"description": "TypeScript SDK for programmatic access to qwen-code CLI",
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
},
"./package.json": "./package.json"
},
"files": [
"dist",
"README.md"
],
"scripts": {
"build": "node scripts/build.js",
"bundle:cli": "node scripts/bundle-cli.js",
"test": "vitest run",
"test:ci": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage",
"lint": "eslint src test",
"lint:fix": "eslint src test --fix",
"typecheck": "tsc --noEmit",
"clean": "rm -rf dist",
"prepublishOnly": "npm run clean && npm run build && npm run bundle:cli",
"prepack": "npm run build && npm run bundle:cli"
},
"keywords": [
"qwen",
"qwen-code",
"ai",
"code-assistant",
"sdk",
"typescript"
],
"author": "Qwen Team",
"license": "Apache-2.0",
"engines": {
"node": ">=22.0.0"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.25.1",
"zod": "^3.25.0"
},
"devDependencies": {
"@types/node": "^22.0.0",
"@typescript-eslint/eslint-plugin": "^7.13.0",
"@typescript-eslint/parser": "^7.13.0",
"@vitest/coverage-v8": "^1.6.0",
"dts-bundle-generator": "^9.5.1",
"esbuild": "^0.25.12",
"eslint": "^8.57.0",
"typescript": "^5.4.5",
"vitest": "^1.6.0"
},
"peerDependencies": {
"typescript": ">=5.0.0"
},
"repository": {
"type": "git",
"url": "https://github.com/QwenLM/qwen-code.git",
"directory": "packages/sdk-typescript"
},
"bugs": {
"url": "https://github.com/QwenLM/qwen-code/issues"
},
"homepage": "https://qwenlm.github.io/qwen-code-docs/"
}