dsh-agy-link 0.4.81 → 0.4.83
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/CHANGELOG.md +28 -0
- package/dist/index.js +16 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.83 (2026-10-29)
|
|
4
|
+
|
|
5
|
+
### English
|
|
6
|
+
|
|
7
|
+
- **Fix(media): a malformed `file://` percent-escape no longer throws out of the media route.**
|
|
8
|
+
- `resolveLocalMediaPath()` called `decodeURIComponent()` unguarded on the `file://` path. A double-encoded query (`?path=file%3A%2F%2F%2F%25E0...`) decodes to the literal `file:///%E0%A4%A`, whose inner decode throws `URIError: URI malformed` straight out of `handleMediaRequest()` (unhandled). Malformed escapes are now decoded via a safe helper that returns `null`, so the route answers `404` instead of throwing. Adds a regression test.
|
|
9
|
+
|
|
10
|
+
### 中文
|
|
11
|
+
|
|
12
|
+
- **修复(media):畸形的 `file://` 百分号转义不再把异常抛出媒体路由。**
|
|
13
|
+
- `resolveLocalMediaPath()` 对 `file://` 路径直接 `decodeURIComponent()`,未做保护。经双重编码的查询(`?path=file%3A%2F%2F%2F%25E0...`)解析出字面量 `file:///%E0%A4%A`,其内部解码抛出 `URIError: URI malformed` 并从 `handleMediaRequest()` 直接逃逸。现在改用安全解码助手,畸形转义返回 `null`,路由回 `404` 而非抛异常。补充回归测试。
|
|
14
|
+
|
|
15
|
+
**Full Changelog**: https://github.com/amlyczz/dsh-agy-link/compare/v0.4.82...v0.4.83
|
|
16
|
+
|
|
17
|
+
## 0.4.82 (2026-10-29)
|
|
18
|
+
|
|
19
|
+
### English
|
|
20
|
+
|
|
21
|
+
- **Fix(sessions): don't mis-purge live bindings whose session key contains `:`.**
|
|
22
|
+
- `cleanupStaleAccounts()` split the binding key on the FIRST `:`. A DSH session id can itself be composite and contain `:` (as several plugins produce), so `ns:sess:acc_valid` parsed its "account id" as `sess:acc_valid`, which is never in the valid set — the cleanup then **deleted a live binding**. It now splits on the LAST `:` and only treats the suffix as an account id when it matches the pool shape `acc_<...>`, so colon-containing session keys are never mistaken for accounts. Adds a regression test.
|
|
23
|
+
|
|
24
|
+
### 中文
|
|
25
|
+
|
|
26
|
+
- **修复(sessions):不再误删会话键本身含 `:` 的有效绑定。**
|
|
27
|
+
- `cleanupStaleAccounts()` 之前按**第一个** `:` 切分绑定键。DSH 的会话 id 有可能本身是含 `:` 的复合键(部分插件如此),于是 `ns:sess:acc_valid` 被解析出的「账号 id」为 `sess:acc_valid`,永远不在有效集合里——清理逻辑因此**删掉了一个有效绑定**。现在改为按**最后一个** `:` 切分,且仅当后缀符合账号池形态 `acc_<...>` 时才当作账号 id,含 `:` 的会话键不会被误判为账号。补充回归测试。
|
|
28
|
+
|
|
29
|
+
**Full Changelog**: https://github.com/amlyczz/dsh-agy-link/compare/v0.4.81...v0.4.82
|
|
30
|
+
|
|
3
31
|
## 0.4.81 (2026-10-29)
|
|
4
32
|
|
|
5
33
|
### English
|
package/dist/index.js
CHANGED
|
@@ -29503,10 +29503,10 @@ var SessionStore = class {
|
|
|
29503
29503
|
cleanupStaleAccounts(validAccountIds) {
|
|
29504
29504
|
let changed = false;
|
|
29505
29505
|
for (const key of Object.keys(this.data)) {
|
|
29506
|
-
const colon = key.
|
|
29506
|
+
const colon = key.lastIndexOf(":");
|
|
29507
29507
|
if (colon >= 0) {
|
|
29508
29508
|
const accId = key.slice(colon + 1);
|
|
29509
|
-
if (accId && !validAccountIds.has(accId)) {
|
|
29509
|
+
if (/^acc_[A-Za-z0-9_]+$/.test(accId) && !validAccountIds.has(accId)) {
|
|
29510
29510
|
delete this.data[key];
|
|
29511
29511
|
this.dirty.delete(key);
|
|
29512
29512
|
this.removed.add(key);
|
|
@@ -35029,6 +35029,14 @@ const MIME_MAP = {
|
|
|
35029
35029
|
".json": "application/json; charset=utf-8"
|
|
35030
35030
|
};
|
|
35031
35031
|
const IS_WIN = process.platform === "win32";
|
|
35032
|
+
/** decodeURIComponent that returns null instead of throwing on malformed input. */
|
|
35033
|
+
function safeDecodeUri(s) {
|
|
35034
|
+
try {
|
|
35035
|
+
return decodeURIComponent(s);
|
|
35036
|
+
} catch {
|
|
35037
|
+
return null;
|
|
35038
|
+
}
|
|
35039
|
+
}
|
|
35032
35040
|
/**
|
|
35033
35041
|
* Normalize and resolve a raw path or file:// URL into a system file path.
|
|
35034
35042
|
* Converts WSL /mnt/X/ and /home/ paths on Windows where possible.
|
|
@@ -35037,10 +35045,14 @@ function resolveLocalMediaPath(rawPath, workspaceRoot) {
|
|
|
35037
35045
|
if (!rawPath || typeof rawPath !== "string") return null;
|
|
35038
35046
|
let p = rawPath.trim();
|
|
35039
35047
|
if (p.startsWith("file:///")) {
|
|
35040
|
-
|
|
35048
|
+
const decoded = safeDecodeUri(p.slice(8));
|
|
35049
|
+
if (decoded === null) return null;
|
|
35050
|
+
p = decoded;
|
|
35041
35051
|
if (IS_WIN && !/^[A-Za-z]:/.test(p) && /^\/[A-Za-z]:/.test(p)) p = p.slice(1);
|
|
35042
35052
|
} else if (p.startsWith("file://")) {
|
|
35043
|
-
|
|
35053
|
+
const decoded = safeDecodeUri(p.slice(7));
|
|
35054
|
+
if (decoded === null) return null;
|
|
35055
|
+
p = decoded;
|
|
35044
35056
|
if (IS_WIN && p.startsWith("wsl.localhost/")) p = "\\\\" + p.replace(/\//g, "\\");
|
|
35045
35057
|
}
|
|
35046
35058
|
if (IS_WIN) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-agy-link",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.83",
|
|
4
4
|
"description": "Google Antigravity (agy CLI) models for DeepSeek Harness — stream Gemini/Claude/GPT-OSS subscriptions into DSH with thinking, tool activity, token usage and in-GUI Google OAuth login.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|