@yanlinglabs/winter-agent-sdk 0.0.41 → 0.0.43
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/dist/index.js
CHANGED
|
@@ -1271,32 +1271,38 @@ function withTestKeychainRedirect(env) {
|
|
|
1271
1271
|
return { ...env, [TEST_KEYCHAIN_ENV]: redirect };
|
|
1272
1272
|
}
|
|
1273
1273
|
// src/version.ts
|
|
1274
|
-
var SDK_VERSION = "0.0.
|
|
1274
|
+
var SDK_VERSION = "0.0.43";
|
|
1275
1275
|
// src/paths/project-key.ts
|
|
1276
1276
|
var TRANSCRIPT_PROJECT_KEY_MAX_LENGTH = 64;
|
|
1277
1277
|
var VENDOR_PROJECT_KEY_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
|
|
1278
1278
|
function isVendorCompliantProjectKey(key) {
|
|
1279
1279
|
return VENDOR_PROJECT_KEY_PATTERN.test(key);
|
|
1280
1280
|
}
|
|
1281
|
-
function
|
|
1282
|
-
return
|
|
1281
|
+
function isAsciiAlphanumeric(code) {
|
|
1282
|
+
return code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122;
|
|
1283
1283
|
}
|
|
1284
|
-
function
|
|
1285
|
-
let
|
|
1286
|
-
for (let i = 0;i <
|
|
1287
|
-
|
|
1284
|
+
function sanitizeForKey(text) {
|
|
1285
|
+
let out = "";
|
|
1286
|
+
for (let i = 0;i < text.length; i++) {
|
|
1287
|
+
const code = text.charCodeAt(i);
|
|
1288
|
+
out += isAsciiAlphanumeric(code) ? text[i] : "-";
|
|
1288
1289
|
}
|
|
1289
|
-
return
|
|
1290
|
+
return out;
|
|
1290
1291
|
}
|
|
1291
|
-
function
|
|
1292
|
-
|
|
1292
|
+
function hashSuffix(text) {
|
|
1293
|
+
let hash = 0;
|
|
1294
|
+
for (let i = 0;i < text.length; i++) {
|
|
1295
|
+
hash = Math.imul(hash, 31) + text.charCodeAt(i) | 0;
|
|
1296
|
+
}
|
|
1297
|
+
return Math.abs(hash).toString(36);
|
|
1293
1298
|
}
|
|
1294
1299
|
function transcriptProjectKey(absPath) {
|
|
1295
|
-
const sanitized =
|
|
1300
|
+
const sanitized = sanitizeForKey(absPath);
|
|
1296
1301
|
if (sanitized.length <= TRANSCRIPT_PROJECT_KEY_MAX_LENGTH)
|
|
1297
1302
|
return sanitized;
|
|
1298
|
-
const suffix =
|
|
1299
|
-
|
|
1303
|
+
const suffix = hashSuffix(absPath);
|
|
1304
|
+
const prefixLength = TRANSCRIPT_PROJECT_KEY_MAX_LENGTH - 1 - suffix.length;
|
|
1305
|
+
return `${sanitized.slice(0, prefixLength)}-${suffix}`;
|
|
1300
1306
|
}
|
|
1301
1307
|
// src/paths/keys.ts
|
|
1302
1308
|
import { realpathSync } from "node:fs";
|
|
@@ -2053,52 +2059,52 @@ import { CATALOG_TAG_RENAMES } from "@yanlinglabs/winter-provider-catalog";
|
|
|
2053
2059
|
|
|
2054
2060
|
// src/plugins/manage.ts
|
|
2055
2061
|
import { mkdir, open, readFile as readFile2, rename, rmdir, unlink, writeFile } from "node:fs/promises";
|
|
2056
|
-
import { dirname as dirname3, isAbsolute as isAbsolute2, join as join3, resolve
|
|
2062
|
+
import { dirname as dirname3, isAbsolute as isAbsolute2, join as join3, resolve } from "node:path";
|
|
2057
2063
|
import { randomBytes } from "node:crypto";
|
|
2058
2064
|
|
|
2059
2065
|
// src/plugins/marketplace-path.ts
|
|
2060
|
-
import
|
|
2061
|
-
var
|
|
2062
|
-
function
|
|
2063
|
-
|
|
2064
|
-
}
|
|
2065
|
-
function normalizePluginRoot(pluginRoot) {
|
|
2066
|
-
if (typeof pluginRoot !== "string" || pluginRoot === "" || pluginRoot.startsWith("/") || pluginRoot.includes("\\") || pluginRoot.includes(":"))
|
|
2066
|
+
import path from "node:path";
|
|
2067
|
+
var MARKETPLACE_DIR = Symbol("marketplace-dir");
|
|
2068
|
+
function usableRoot(pluginRoot) {
|
|
2069
|
+
if (typeof pluginRoot !== "string")
|
|
2067
2070
|
return;
|
|
2068
|
-
|
|
2069
|
-
if (stripped === "" || stripped === ".")
|
|
2070
|
-
return ".";
|
|
2071
|
-
if (stripped.split("/").some((segment) => segment === "" || segment === "." || segment === ".."))
|
|
2071
|
+
if (pluginRoot === "" || pluginRoot.startsWith("/"))
|
|
2072
2072
|
return;
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
return normalized.startsWith("./") ? normalized : undefined;
|
|
2083
|
-
}
|
|
2084
|
-
function resolveWithinBase(base, relativePath) {
|
|
2085
|
-
const normalizedBase = resolve(base);
|
|
2086
|
-
const resolved = resolve(base, relativePath);
|
|
2087
|
-
if (resolved !== normalizedBase && !resolved.startsWith(normalizedBase + sep)) {
|
|
2088
|
-
throw new Error(`Path traversal detected: "${relativePath}" would escape the base directory`);
|
|
2073
|
+
if (pluginRoot.includes("\\") || pluginRoot.includes(":"))
|
|
2074
|
+
return;
|
|
2075
|
+
let rest = pluginRoot.startsWith("./") ? pluginRoot.slice(2) : pluginRoot;
|
|
2076
|
+
rest = rest.replace(/\/+$/, "");
|
|
2077
|
+
if (rest === "" || rest === ".")
|
|
2078
|
+
return MARKETPLACE_DIR;
|
|
2079
|
+
for (const piece of rest.split("/")) {
|
|
2080
|
+
if (piece === "" || piece === "." || piece === "..")
|
|
2081
|
+
return;
|
|
2089
2082
|
}
|
|
2090
|
-
return
|
|
2083
|
+
return rest;
|
|
2084
|
+
}
|
|
2085
|
+
function isBareName(source) {
|
|
2086
|
+
return /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(source) && !source.includes("..");
|
|
2091
2087
|
}
|
|
2092
2088
|
function resolveMarketplacePluginPath(installLocation, pluginRoot, source) {
|
|
2093
|
-
if (typeof source !== "string" || source === "")
|
|
2094
|
-
return;
|
|
2095
|
-
const normalizedRoot = normalizePluginRoot(pluginRoot);
|
|
2096
|
-
const prefixed = withPluginRootPrefix(source, normalizedRoot);
|
|
2097
|
-
const sourcePath = schemaSourcePath(prefixed);
|
|
2098
|
-
if (sourcePath === undefined)
|
|
2099
|
-
return;
|
|
2100
2089
|
try {
|
|
2101
|
-
|
|
2090
|
+
if (typeof source !== "string" || source === "")
|
|
2091
|
+
return;
|
|
2092
|
+
let relativePath = source;
|
|
2093
|
+
if (isBareName(source)) {
|
|
2094
|
+
const root = usableRoot(pluginRoot);
|
|
2095
|
+
if (root !== undefined) {
|
|
2096
|
+
relativePath = root === MARKETPLACE_DIR ? `./${source}` : `./${root}/${source}`;
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
if (relativePath === ".")
|
|
2100
|
+
relativePath = "./";
|
|
2101
|
+
if (!relativePath.startsWith("./"))
|
|
2102
|
+
return;
|
|
2103
|
+
const base = path.resolve(installLocation);
|
|
2104
|
+
const candidate = path.resolve(installLocation, relativePath);
|
|
2105
|
+
if (candidate === base || candidate.startsWith(base + path.sep))
|
|
2106
|
+
return candidate;
|
|
2107
|
+
return;
|
|
2102
2108
|
} catch {
|
|
2103
2109
|
return;
|
|
2104
2110
|
}
|
|
@@ -2244,7 +2250,7 @@ function classifySource(source) {
|
|
|
2244
2250
|
if (/^[a-zA-Z0-9](?:[a-zA-Z0-9._-]*[a-zA-Z0-9])?\/[a-zA-Z0-9](?:[a-zA-Z0-9._-]*[a-zA-Z0-9])?$/.test(source) && !source.includes("..")) {
|
|
2245
2251
|
return { kind: "github", locator: source };
|
|
2246
2252
|
}
|
|
2247
|
-
return { kind: "directory", locator: isAbsolute2(source) ? source :
|
|
2253
|
+
return { kind: "directory", locator: isAbsolute2(source) ? source : resolve(source) };
|
|
2248
2254
|
}
|
|
2249
2255
|
function marketplaceInfoOf(name, record) {
|
|
2250
2256
|
const kind = record.source.source;
|
|
@@ -1,10 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Resolve one marketplace manifest plugin entry's install path -- the ONE function
|
|
3
|
-
* `packages/runtime/src/plugins/installed.ts` (the daemon's own directory-marketplace fallback,
|
|
4
|
-
* SV-4) and `packages/sdk/src/plugins/manage.ts` (`resolvePluginSourcePath`, the CLI-facing install
|
|
5
|
-
* command) both call, so the two can never resolve the identical manifest entry to two different
|
|
6
|
-
* paths. `undefined` for anything invalid or refused -- a bare name with no usable `pluginRoot`, an
|
|
7
|
-
* absolute/malformed source, or a path that would escape `installLocation` -- NEVER a throw a
|
|
8
|
-
* caller must remember to catch; each caller renders its own typed rejection from `undefined`.
|
|
9
|
-
*/
|
|
10
1
|
export declare function resolveMarketplacePluginPath(installLocation: string, pluginRoot: unknown, source: unknown): string | undefined;
|
package/dist/settings/types.d.ts
CHANGED
|
@@ -69,12 +69,10 @@ export interface Settings {
|
|
|
69
69
|
* `permissions.deny`'s own union exists to prevent; see `unionSandboxFilesystemDenyArrays` below).
|
|
70
70
|
* CORRECTED in fix round 10, item C: round 9 reasoned `allowWrite` should NOT union (a widening
|
|
71
71
|
* key should never accumulate) and used the ordinary replace-by-higher-tier merge for it instead
|
|
72
|
-
* -- the controller's round-10 ruling reverses this
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* round) is claude's own read carve-out (`getFsReadConfig`'s `allowWithinDeny`) -- carried and
|
|
77
|
-
* unioned identically for merge-parity, though `packages/runtime/src/sandbox/profile.ts`'s own
|
|
72
|
+
* -- the controller's round-10 ruling reverses this: Claude Code accumulates allowWrite entries
|
|
73
|
+
* from every source rather than letting one replace another, so Winter unions the widening array
|
|
74
|
+
* too. `allowRead` (also new this round) is the settings key for re-permitting reads inside a
|
|
75
|
+
* denied region -- carried and unioned identically for merge-parity, though `packages/runtime/src/sandbox/profile.ts`'s own
|
|
78
76
|
* `buildSeatbeltProfile` does not yet enforce it (a disclosed, fails-CLOSED gap: see that file's
|
|
79
77
|
* own `SandboxFilesystemSettings.allowRead` doc comment).
|
|
80
78
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yanlinglabs/winter-agent-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.43",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -45,15 +45,15 @@
|
|
|
45
45
|
}
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@yanlinglabs/winter-provider-catalog": "0.0.
|
|
48
|
+
"@yanlinglabs/winter-provider-catalog": "0.0.43"
|
|
49
49
|
},
|
|
50
50
|
"optionalDependencies": {
|
|
51
|
-
"@yanlinglabs/winter-agent-sdk-darwin-arm64": "0.0.
|
|
51
|
+
"@yanlinglabs/winter-agent-sdk-darwin-arm64": "0.0.43"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@types/node": "^26.4.0",
|
|
55
|
-
"@yanlinglabs/winter-
|
|
56
|
-
"@yanlinglabs/winter-
|
|
55
|
+
"@yanlinglabs/winter-agent-runtime": "0.0.43",
|
|
56
|
+
"@yanlinglabs/winter-conformance": "0.0.43"
|
|
57
57
|
},
|
|
58
58
|
"scripts": {}
|
|
59
59
|
}
|