@qilin-agent/tool-workspace-dependencies 3.1.4 → 3.1.6

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/lib/index.js CHANGED
@@ -1,9 +1,9 @@
1
- import { cp, lstat, mkdir, mkdtemp, readFile, rename, rm, stat } from "node:fs/promises";
1
+ import { cp, lstat, mkdir, mkdtemp, readFile, readlink, rename, rm, stat, symlink } from "node:fs/promises";
2
2
  import { dirname, isAbsolute, join } from "node:path";
3
3
  import z from "@qilin-agent/schemastery";
4
4
  import { defineTool } from "@qilin-agent/tools";
5
5
  //#region lib/types/index.js
6
- /** Model-facing query for a bundled Python, Node.js, and pnpm payload, in place or installed under the QiLin home. */
6
+ /** Model-facing query for a bundled Python, Node.js, and pnpm payload, in place or installed under the Harness home. */
7
7
  /** Cordis plugin identity. */
8
8
  const name = "tool-workspace-dependencies";
9
9
  /** Registry the tool registers into. */
@@ -75,6 +75,49 @@ async function readPrimaryRuntime(root) {
75
75
  return parsePrimaryRuntime(JSON.parse(await readFile(join(root, "runtime.json"), "utf8")));
76
76
  }
77
77
  /**
78
+ * Identify POSIX interpreter aliases that can survive payload relocation.
79
+ * @param root - Payload directory.
80
+ * @param manifest - Validated payload metadata.
81
+ * @returns Relative alias paths mapped to their sibling interpreter filename; regular command files are omitted.
82
+ * @throws When an interpreter alias does not point directly to the versioned regular file.
83
+ */
84
+ async function primaryRuntimePythonAliases(root, manifest) {
85
+ const aliases = /* @__PURE__ */ new Map();
86
+ if (manifest.platform === "win32") return aliases;
87
+ const interpreter = `python${manifest.python.split(".").slice(0, 2).join(".")}`;
88
+ for (const name of ["python", "python3"]) {
89
+ const path = `dependencies/python/bin/${name}`;
90
+ let entry;
91
+ try {
92
+ entry = await lstat(join(root, path));
93
+ } catch (error) {
94
+ if (error.code === "ENOENT") continue;
95
+ throw error;
96
+ }
97
+ if (!entry.isSymbolicLink()) continue;
98
+ if (await readlink(join(root, path)) !== interpreter || !(await lstat(join(root, "dependencies/python/bin", interpreter))).isFile()) throw new Error(`primary runtime: invalid Python alias ${path}`);
99
+ aliases.set(path, interpreter);
100
+ }
101
+ return aliases;
102
+ }
103
+ /**
104
+ * Copy a payload, retaining only validated Python interpreter aliases as relative links.
105
+ * @param source - Payload directory; all other links are materialized.
106
+ * @param destination - Empty destination owned by the caller.
107
+ * @param manifest - Validated source metadata.
108
+ * @returns Resolves after every copied file and interpreter alias is available independently of the source.
109
+ */
110
+ async function copyPrimaryRuntime(source, destination, manifest) {
111
+ const aliases = await primaryRuntimePythonAliases(source, manifest);
112
+ const excluded = new Set([...aliases.keys()].map((path) => join(source, path)));
113
+ await cp(source, destination, {
114
+ recursive: true,
115
+ dereference: true,
116
+ filter: (path) => !excluded.has(path)
117
+ });
118
+ for (const [path, target] of aliases) await symlink(target, join(destination, path));
119
+ }
120
+ /**
78
121
  * Resolve platform-specific interpreter and library locations without changing the environment.
79
122
  * @param root - Absolute payload or installation directory.
80
123
  * @param manifest - Validated runtime metadata.
@@ -129,14 +172,16 @@ async function compatibleManifest(source) {
129
172
  * @returns Paths into the payload itself.
130
173
  */
131
174
  async function resolvePrimaryRuntime(source) {
132
- const paths = workspaceDependencyPaths(source, await compatibleManifest(source));
175
+ const manifest = await compatibleManifest(source);
176
+ await primaryRuntimePythonAliases(source, manifest);
177
+ const paths = workspaceDependencyPaths(source, manifest);
133
178
  await validatePayloadEntries(paths);
134
179
  return paths;
135
180
  }
136
181
  /**
137
182
  * Install the application-owned payload locally, retaining a complete previous tree on copy failure.
138
183
  * @param source - Payload carried by the current installation.
139
- * @param root - Fixed primary runtime directory under the QiLin home.
184
+ * @param root - Fixed primary runtime directory under the Harness home.
140
185
  * @returns Paths into the installed payload; no PATH or package-manager configuration is changed.
141
186
  */
142
187
  async function installPrimaryRuntime(source, root) {
@@ -146,16 +191,14 @@ async function installPrimaryRuntime(source, root) {
146
191
  const previousExists = await exists(previous);
147
192
  if (!await exists(root) && previousExists) await rename(previous, root);
148
193
  if (await exists(join(root, "runtime.json")) && JSON.stringify(await readPrimaryRuntime(root)) === JSON.stringify(manifest)) {
194
+ await primaryRuntimePythonAliases(root, manifest);
149
195
  const paths = workspaceDependencyPaths(root, manifest);
150
196
  await validatePayloadEntries(paths);
151
197
  return paths;
152
198
  }
153
199
  const staging = await mkdtemp(join(dirname(root), ".primary-runtime-"));
154
200
  try {
155
- await cp(source, staging, {
156
- recursive: true,
157
- dereference: true
158
- });
201
+ await copyPrimaryRuntime(source, staging, manifest);
159
202
  await validatePayloadEntries(workspaceDependencyPaths(staging, manifest));
160
203
  await rm(previous, {
161
204
  recursive: true,
@@ -249,4 +292,4 @@ function apply(ctx, config) {
249
292
  }));
250
293
  }
251
294
  //#endregion
252
- export { Config, apply, inject, installPrimaryRuntime, name, parsePrimaryRuntime, readPrimaryRuntime, resolvePrimaryRuntime, workspaceDependencyPaths };
295
+ export { Config, apply, copyPrimaryRuntime, inject, installPrimaryRuntime, name, parsePrimaryRuntime, primaryRuntimePythonAliases, readPrimaryRuntime, resolvePrimaryRuntime, workspaceDependencyPaths };
@@ -1,4 +1,4 @@
1
- /** Model-facing query for a bundled Python, Node.js, and pnpm payload, in place or installed under the QiLin home. */
1
+ /** Model-facing query for a bundled Python, Node.js, and pnpm payload, in place or installed under the Harness home. */
2
2
  import type { Context } from '@qilin-agent/kylin';
3
3
  import z from '@qilin-agent/schemastery';
4
4
  /** Cordis plugin identity. */
@@ -10,8 +10,8 @@ export interface Config {
10
10
  /** Payload directory carrying `runtime.json` and `dependencies/`. */
11
11
  readonly source: string;
12
12
  /**
13
- * Installation directory under the QiLin home. When set, the payload is copied there on the
14
- * first call (the copy-on-first-use behavior); when omitted, the payload is used in place without copying,
13
+ * Installation directory under the Harness home. When set, the payload is copied there on the
14
+ * first call (the Desktop behavior); when omitted, the payload is used in place without copying,
15
15
  * which suits read-only carriers such as container image layers.
16
16
  */
17
17
  readonly root?: string;
@@ -57,6 +57,22 @@ export declare function parsePrimaryRuntime(value: unknown): PrimaryRuntimeManif
57
57
  * @returns Validated top-level versions and target identifiers, including for legacy components manifests.
58
58
  */
59
59
  export declare function readPrimaryRuntime(root: string): Promise<PrimaryRuntimeManifest>;
60
+ /**
61
+ * Identify POSIX interpreter aliases that can survive payload relocation.
62
+ * @param root - Payload directory.
63
+ * @param manifest - Validated payload metadata.
64
+ * @returns Relative alias paths mapped to their sibling interpreter filename; regular command files are omitted.
65
+ * @throws When an interpreter alias does not point directly to the versioned regular file.
66
+ */
67
+ export declare function primaryRuntimePythonAliases(root: string, manifest: PrimaryRuntimeManifest): Promise<ReadonlyMap<string, string>>;
68
+ /**
69
+ * Copy a payload, retaining only validated Python interpreter aliases as relative links.
70
+ * @param source - Payload directory; all other links are materialized.
71
+ * @param destination - Empty destination owned by the caller.
72
+ * @param manifest - Validated source metadata.
73
+ * @returns Resolves after every copied file and interpreter alias is available independently of the source.
74
+ */
75
+ export declare function copyPrimaryRuntime(source: string, destination: string, manifest: PrimaryRuntimeManifest): Promise<void>;
60
76
  /**
61
77
  * Resolve platform-specific interpreter and library locations without changing the environment.
62
78
  * @param root - Absolute payload or installation directory.
@@ -73,7 +89,7 @@ export declare function resolvePrimaryRuntime(source: string): Promise<Workspace
73
89
  /**
74
90
  * Install the application-owned payload locally, retaining a complete previous tree on copy failure.
75
91
  * @param source - Payload carried by the current installation.
76
- * @param root - Fixed primary runtime directory under the QiLin home.
92
+ * @param root - Fixed primary runtime directory under the Harness home.
77
93
  * @returns Paths into the installed payload; no PATH or package-manager configuration is changed.
78
94
  */
79
95
  export declare function installPrimaryRuntime(source: string, root: string): Promise<WorkspaceDependencies>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@qilin-agent/tool-workspace-dependencies",
3
3
  "description": "The load_workspace_dependencies tool: absolute paths into a bundled Python, Node.js, and pnpm payload",
4
- "version": "3.1.4",
4
+ "version": "3.1.6",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -29,19 +29,19 @@
29
29
  ],
30
30
  "license": "MIT",
31
31
  "peerDependencies": {
32
- "@qilin-agent/tools": "3.1.4",
33
- "@qilin-agent/kylin": "~4.0.3"
32
+ "@qilin-agent/tools": "3.1.6",
33
+ "@qilin-agent/kylin": "~4.0.5"
34
34
  },
35
35
  "devDependencies": {
36
- "@qilin-agent/llm": "3.1.4",
37
- "@qilin-agent/system-prompt": "3.1.4",
38
- "@qilin-agent/kylin": "~4.0.3",
39
- "@qilin-agent/tools": "3.1.4",
40
- "@qilin-agent/agent": "3.1.4",
41
- "@qilin-agent/kylin-plugin-include": "~1.0.8",
42
- "@qilin-agent/kylin-plugin-loader": "~1.0.4"
36
+ "@qilin-agent/agent": "3.1.6",
37
+ "@qilin-agent/llm": "3.1.6",
38
+ "@qilin-agent/system-prompt": "3.1.6",
39
+ "@qilin-agent/kylin": "~4.0.5",
40
+ "@qilin-agent/tools": "3.1.6",
41
+ "@qilin-agent/kylin-plugin-include": "~1.0.10",
42
+ "@qilin-agent/kylin-plugin-loader": "~1.0.6"
43
43
  },
44
44
  "dependencies": {
45
- "@qilin-agent/schemastery": "~3.18.3"
45
+ "@qilin-agent/schemastery": "~3.18.5"
46
46
  }
47
47
  }