signetai 0.138.26 → 0.138.30

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/bin/launch.js CHANGED
@@ -42,10 +42,21 @@ export function launchSignet() {
42
42
  process.exit(1);
43
43
  }
44
44
 
45
+ // Point the binary at the wrapper's installed runtime tree so the
46
+ // connector's `getPluginSourceDir()` `SIGNET_DIR/runtime/connectors/...`
47
+ // fallback can find per-harness plugin assets that the native binary
48
+ // doesn't carry inline. The env is only set when the wrapper actually
49
+ // has a runtime tree to share; the binary's own bootstrap can derive
50
+ // its own path otherwise.
51
+ const env = { ...process.env };
52
+ if (!env.SIGNET_DIR && existsSync(join(packageDir, "runtime", "connectors"))) {
53
+ env.SIGNET_DIR = packageDir;
54
+ }
55
+
45
56
  const args = process.argv.slice(2);
46
57
  const child = spawn(resolvedBinaryPath, args, {
47
58
  stdio: "inherit",
48
- env: process.env,
59
+ env,
49
60
  windowsHide: true,
50
61
  });
51
62
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "signetai",
3
- "version": "0.138.26",
3
+ "version": "0.138.30",
4
4
  "description": "Signet native CLI installer wrapper",
5
5
  "type": "module",
6
6
  "bin": {
@@ -12,6 +12,7 @@
12
12
  "bin/native-platforms.js",
13
13
  "bin/signet.js",
14
14
  "dist/mcp-stdio.js",
15
+ "native-manifest.json",
15
16
  "scripts/install-native.js",
16
17
  "scripts/verify-wrapper.js",
17
18
  "README.md",
@@ -64,10 +65,10 @@
64
65
  "access": "public"
65
66
  },
66
67
  "optionalDependencies": {
67
- "signetai-darwin-arm64": "https://github.com/Signet-AI/signetai/releases/download/v0.138.26/signetai-darwin-arm64-0.138.26.tgz",
68
- "signetai-darwin-x64": "https://github.com/Signet-AI/signetai/releases/download/v0.138.26/signetai-darwin-x64-0.138.26.tgz",
69
- "signetai-linux-arm64": "https://github.com/Signet-AI/signetai/releases/download/v0.138.26/signetai-linux-arm64-0.138.26.tgz",
70
- "signetai-linux-x64": "https://github.com/Signet-AI/signetai/releases/download/v0.138.26/signetai-linux-x64-0.138.26.tgz",
71
- "signetai-win32-x64": "https://github.com/Signet-AI/signetai/releases/download/v0.138.26/signetai-win32-x64-0.138.26.tgz"
68
+ "signetai-darwin-arm64": "https://github.com/Signet-AI/signetai/releases/download/v0.138.30/signetai-darwin-arm64-0.138.30.tgz",
69
+ "signetai-darwin-x64": "https://github.com/Signet-AI/signetai/releases/download/v0.138.30/signetai-darwin-x64-0.138.30.tgz",
70
+ "signetai-linux-arm64": "https://github.com/Signet-AI/signetai/releases/download/v0.138.30/signetai-linux-arm64-0.138.30.tgz",
71
+ "signetai-linux-x64": "https://github.com/Signet-AI/signetai/releases/download/v0.138.30/signetai-linux-x64-0.138.30.tgz",
72
+ "signetai-win32-x64": "https://github.com/Signet-AI/signetai/releases/download/v0.138.30/signetai-win32-x64-0.138.30.tgz"
72
73
  }
73
74
  }
@@ -1,8 +1,19 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { copyFileSync, existsSync, linkSync, mkdirSync, readFileSync, rmSync, unlinkSync } from "node:fs";
3
+ import { createHash } from "node:crypto";
4
+ import {
5
+ copyFileSync,
6
+ existsSync,
7
+ linkSync,
8
+ mkdirSync,
9
+ readFileSync,
10
+ rmSync,
11
+ unlinkSync,
12
+ writeFileSync,
13
+ } from "node:fs";
4
14
  import { chmod } from "node:fs/promises";
5
15
  import { createRequire } from "node:module";
16
+ import { spawnSync } from "node:child_process";
6
17
  import { basename, dirname, join } from "node:path";
7
18
  import { fileURLToPath } from "node:url";
8
19
 
@@ -11,6 +22,8 @@ import { detectNativePlatform, nativePlatforms } from "../bin/native-platforms.j
11
22
  const packageDir = dirname(dirname(fileURLToPath(import.meta.url)));
12
23
  const require = createRequire(import.meta.url);
13
24
 
25
+ const CONNECTOR_COMPONENT = "connectors";
26
+
14
27
  function isWorkspacePackage() {
15
28
  const workspaceRoot = dirname(dirname(packageDir));
16
29
  if (basename(dirname(packageDir)) !== "dist") return false;
@@ -60,11 +73,16 @@ async function main() {
60
73
  } catch {
61
74
  console.error(`Signet native package ${nativePackage.packageName} was not installed.`);
62
75
  console.error("The signet wrapper will try to resolve the optional native package at runtime.");
76
+ // Fall through — connector assets are independent of the binary
77
+ // link, so users who only have the wrapper package can still
78
+ // benefit from a populated runtime tree.
79
+ await installConnectorAssets();
63
80
  return;
64
81
  }
65
82
 
66
83
  if (!existsSync(source)) {
67
84
  console.error(`Signet native binary is missing from ${nativePackage.packageName}: ${source}`);
85
+ await installConnectorAssets();
68
86
  return;
69
87
  }
70
88
 
@@ -81,6 +99,113 @@ async function main() {
81
99
  rmSync(destination, { force: true });
82
100
  throw err;
83
101
  }
102
+
103
+ // Connector plugin assets. The native binary has the connector JS
104
+ // compiled in, but each connector's on-disk plugin payload (e.g. the
105
+ // Hermes Python memory provider) ships separately. The wrapper pulls
106
+ // the verified tarball at install time so the runtime can find
107
+ // `$SIGNET_DIR/runtime/connectors/<harness>/...` without a first-run
108
+ // network fetch.
109
+ await installConnectorAssets();
110
+ }
111
+
112
+ function loadManifest() {
113
+ const manifestPath = join(packageDir, "native-manifest.json");
114
+ if (!existsSync(manifestPath)) return null;
115
+ try {
116
+ return JSON.parse(readFileSync(manifestPath, "utf8"));
117
+ } catch {
118
+ return null;
119
+ }
120
+ }
121
+
122
+ async function downloadTo(url, destPath) {
123
+ const response = await fetch(url);
124
+ if (!response.ok) {
125
+ throw new Error(`HTTP ${response.status} fetching ${url}`);
126
+ }
127
+ const arrayBuffer = await response.arrayBuffer();
128
+ writeFileSync(destPath, Buffer.from(arrayBuffer));
129
+ }
130
+
131
+ function verifySha256(path, expected) {
132
+ const actual = createHash("sha256").update(readFileSync(path)).digest("hex");
133
+ if (actual.toLowerCase() !== expected.toLowerCase()) {
134
+ rmSync(path, { force: true });
135
+ throw new Error(`SHA-256 mismatch for ${path}: expected ${expected}, got ${actual}`);
136
+ }
137
+ }
138
+
139
+ function nativePackageVersion() {
140
+ try {
141
+ return JSON.parse(readFileSync(join(packageDir, "package.json"), "utf8")).version;
142
+ } catch {
143
+ return "0.0.0";
144
+ }
145
+ }
146
+
147
+ function releaseBaseUrl() {
148
+ // Allow full-URL override (e.g. for mirrors or local file:// testing)
149
+ // before falling back to the GitHub release URL.
150
+ const overrideBase = process.env.SIGNET_DOWNLOAD_BASE?.trim();
151
+ if (overrideBase) return overrideBase.replace(/\/$/, "");
152
+ const repo = process.env.SIGNET_RELEASE_REPO?.trim() || "Signet-AI/signetai";
153
+ const tag = process.env.SIGNET_RELEASE_TAG?.trim() || `v${nativePackageVersion()}`;
154
+ return `https://github.com/${repo}/releases/download/${tag}`;
155
+ }
156
+
157
+ async function installConnectorAssets() {
158
+ const manifest = loadManifest();
159
+ const component = manifest?.components?.[CONNECTOR_COMPONENT];
160
+ if (!component) {
161
+ // No connector assets in this release (e.g. early versions, or the
162
+ // wrapper is running from a workspace without a synced manifest).
163
+ // Skip silently — connectors without runtime assets keep working.
164
+ return;
165
+ }
166
+
167
+ const targetDir = join(packageDir, "runtime", "connectors");
168
+ const targetMarker = join(targetDir, ".signet-connectors-version");
169
+ if (
170
+ existsSync(targetMarker) &&
171
+ readFileSync(targetMarker, "utf8").trim() === manifest.version
172
+ ) {
173
+ // Already extracted for this version. Skip to keep postinstall fast
174
+ // and to avoid clobbering user-tweaked assets.
175
+ return;
176
+ }
177
+
178
+ const tempPath = join(packageDir, `signet-connectors-${manifest.version}.tar.gz.tmp`);
179
+ const url = component.url.startsWith("http")
180
+ ? component.url
181
+ : `${releaseBaseUrl()}/${component.url}`;
182
+
183
+ try {
184
+ await downloadTo(url, tempPath);
185
+ verifySha256(tempPath, component.sha256);
186
+ const stat = readFileSync(tempPath);
187
+ if (stat.length !== component.size) {
188
+ rmSync(tempPath, { force: true });
189
+ throw new Error(`Tarball size mismatch: expected ${component.size}, got ${stat.length}`);
190
+ }
191
+
192
+ if (existsSync(targetDir)) {
193
+ rmSync(targetDir, { recursive: true, force: true });
194
+ }
195
+ // Tarball layout is `./runtime/connectors/<harness>/...`. Extract
196
+ // at `<packageDir>/` so the tarball's own `runtime/` prefix
197
+ // lands naturally at `<packageDir>/runtime/connectors/...`.
198
+ mkdirSync(packageDir, { recursive: true });
199
+
200
+ const result = spawnSync("tar", ["xzf", tempPath, "-C", packageDir], { stdio: "inherit" });
201
+ if (result.status !== 0) {
202
+ throw new Error(`tar extraction failed with status ${result.status ?? "unknown"}`);
203
+ }
204
+ writeFileSync(targetMarker, `${manifest.version}\n`);
205
+ console.log(`Installed connector assets to ${targetDir}`);
206
+ } finally {
207
+ rmSync(tempPath, { force: true });
208
+ }
84
209
  }
85
210
 
86
211
  main().catch((err) => {