@vibedeckx/linux-x64 0.2.11 → 0.2.13

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.
Files changed (2) hide show
  1. package/dist/bin.js +200 -6
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -229047,6 +229047,7 @@ function buildReviewerPrompt(opts) {
229047
229047
  const brief = opts.intentBrief || null;
229048
229048
  const hasExcerpt = Boolean(intent || opts.taskContext || opts.authorSelfReport);
229049
229049
  const scope = opts.scope && opts.scope.changedFiles.length > 0 ? opts.scope : null;
229050
+ const noDiffWithAnalysis = Boolean(opts.authorSelfReport) && opts.authorSelfReport.trim().length >= SELF_REPORT_MIN_CHARS;
229050
229051
  return [
229051
229052
  "You are a code reviewer agent. Another agent just completed work in this workspace; review it critically and independently.",
229052
229053
  brief ? `
@@ -229067,15 +229068,18 @@ ${opts.taskContext}` : null,
229067
229068
  ${opts.reviewFocus}` : null,
229068
229069
  scope ? `
229069
229070
  ## Scope \u2014 the change under review
229071
+
229070
229072
  The reviewed turn changed exactly these files:
229071
229073
  ${scope.changedFiles.map((f2) => `- ${f2}`).join("\n")}
229074
+
229072
229075
  It starts from commit \`${scope.startHead}\` \u2014 use \`git diff ${scope.startHead} -- <file>\` and \`git log ${scope.startHead}..HEAD\` to see the content.
229073
- Confine your review to these files and changes. Other uncommitted or pre-existing changes in the worktree, or changes from other turns, are out of scope unless this change depends on them.` : opts.scope != null && opts.scope.changedFiles.length === 0 ? "\n## Scope \u2014 the change under review\nThe reviewed turn changed no files. Do not review unrelated uncommitted or pre-existing changes in the worktree \u2014 there is nothing in scope for this turn. If you believe the turn should have changed something, say so rather than reviewing out-of-scope code." : opts.scope === null ? "\n## Scope\nThe changed-file set could not be determined (scope unknown) \u2014 inspect `git diff`/`git status`/`git log` and judge the relevant range yourself." : null,
229076
+
229077
+ Confine your review to these files and changes. Other uncommitted or pre-existing changes in the worktree, or changes from other turns, are out of scope unless this change depends on them.` : opts.scope != null && opts.scope.changedFiles.length === 0 ? noDiffWithAnalysis ? "\n## Scope \u2014 the change under review\n\nThe reviewed turn changed no files. Its deliverable is the analysis and proposed approach in the author self-report above, not a diff \u2014 review THAT. Verify the diagnosis against the actual code: are the cited files/lines real and the described mechanism correct? Then stress-test the proposed fix as a plan, before implementation \u2014 correctness, side-effects, and completeness. If you instead conclude the turn should have produced a code change and didn't, say so. Do not review unrelated uncommitted or pre-existing changes in the worktree." : "\n## Scope \u2014 the change under review\n\nThe reviewed turn changed no files. Do not review unrelated uncommitted or pre-existing changes in the worktree \u2014 there is nothing in scope for this turn. If you believe the turn should have changed something, say so rather than reviewing out-of-scope code." : opts.scope === null ? "\n## Scope\n\nThe changed-file set could not be determined (scope unknown) \u2014 inspect `git diff`/`git status`/`git log` and judge the relevant range yourself." : null,
229074
229078
  "\n## How to review",
229075
229079
  "- Do NOT modify any files \u2014 you are in read-only review mode.",
229076
229080
  "- Inspect the actual workspace state yourself: read the relevant files, run `git diff`, `git status` and `git log`.",
229077
229081
  reviewTargetPromptLine(opts.target),
229078
- "- Judge correctness, completeness against the task, and code quality. Be specific: reference files and lines.",
229082
+ noDiffWithAnalysis ? "- Judge correctness and completeness against the task. For this analysis/plan turn the work under review is the reasoning and the proposal, not code quality of a diff. Be specific: reference files and lines." : "- Judge correctness, completeness against the task, and code quality. Be specific: reference files and lines.",
229079
229083
  "\nEnd your final message with a clear, actionable list of feedback items \u2014 or state explicitly that the work looks good.",
229080
229084
  brief ? opts.authorSelfReport ? "\n(review context: distilled intent brief + author self-report + live workspace)" : "\n(review context: distilled intent brief + live workspace)" : hasExcerpt ? "\n(review context: deterministic excerpt of the source conversation + live workspace)" : "\n(review context: live workspace only \u2014 the source conversation was unavailable)"
229081
229085
  ].filter((l) => l !== null).join("\n");
@@ -238006,6 +238010,20 @@ var import_fastify_plugin23 = __toESM(require_plugin2(), 1);
238006
238010
  import { randomBytes as randomBytes2, createHash as createHash3, verify as cryptoVerify } from "crypto";
238007
238011
  var MACHINE_HANDSHAKE_TIMEOUT_MS = 5e3;
238008
238012
  var routes22 = async (fastify2) => {
238013
+ fastify2.get("/api/reverse-connect/identity", async (req, reply) => {
238014
+ const token = req.headers["x-vibedeckx-connect-token"];
238015
+ if (typeof token !== "string" || token.length === 0) {
238016
+ return reply.code(401).send({ error: "Connect token required" });
238017
+ }
238018
+ const server = await fastify2.storage.remoteServers.getByToken(token);
238019
+ if (!server) {
238020
+ return reply.code(401).send({ error: "Invalid token" });
238021
+ }
238022
+ if (server.connection_mode !== "inbound") {
238023
+ return reply.code(403).send({ error: "Server is not configured for inbound connections" });
238024
+ }
238025
+ return { serverId: server.id, name: server.name };
238026
+ });
238009
238027
  fastify2.after(() => {
238010
238028
  fastify2.get(
238011
238029
  "/api/reverse-connect",
@@ -241159,6 +241177,10 @@ var createServer = async (opts) => {
241159
241177
  if (!API_KEY) return done();
241160
241178
  if (!req.url.startsWith("/api/")) return done();
241161
241179
  if (req.method === "OPTIONS") return done();
241180
+ const pathname = req.url.split("?")[0];
241181
+ if (pathname === "/api/config" || pathname === "/api/reverse-connect/identity") {
241182
+ return done();
241183
+ }
241162
241184
  const providedKey = req.headers["x-vibedeckx-api-key"] || req.query?.apiKey;
241163
241185
  if (!providedKey && authEnabled) {
241164
241186
  return done();
@@ -241200,7 +241222,12 @@ var createServer = async (opts) => {
241200
241222
  server.get("/api/config", async () => ({
241201
241223
  authEnabled,
241202
241224
  clerkPublishableKey: authEnabled ? process.env.CLERK_PUBLISHABLE_KEY : void 0,
241203
- localProjectsEnabled: !noLocalProjects
241225
+ localProjectsEnabled: !noLocalProjects,
241226
+ // Capability flag for the reverse-connect identity preflight. Workers
241227
+ // check this before calling /api/reverse-connect/identity so an auth
241228
+ // middleware 401 from an older hub (which lacks the endpoint AND its
241229
+ // exemptions) is never confused with a genuinely rejected token.
241230
+ reverseConnectIdentity: true
241204
241231
  }));
241205
241232
  server.register(shared_services_default, { storage: opts.storage, authEnabled });
241206
241233
  server.register(import_websocket2.default);
@@ -241211,6 +241238,7 @@ var createServer = async (opts) => {
241211
241238
  server.decorateRequest("auth", null);
241212
241239
  server.addHook("preHandler", async (req, reply) => {
241213
241240
  if (req.headers.upgrade?.toLowerCase() === "websocket") return;
241241
+ if (req.url.split("?")[0] === "/api/reverse-connect/identity") return;
241214
241242
  const headers = new Headers();
241215
241243
  for (const [key, value] of Object.entries(req.headers)) {
241216
241244
  if (value) headers.set(key, Array.isArray(value) ? value.join(",") : String(value));
@@ -241756,6 +241784,69 @@ import { spawn as spawn5 } from "node:child_process";
241756
241784
  import { randomUUID as randomUUID22 } from "node:crypto";
241757
241785
  import fs7 from "node:fs";
241758
241786
  import path19 from "node:path";
241787
+
241788
+ // src/update-check.ts
241789
+ var SEMVER_RE = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*)?$/;
241790
+ async function fetchLatestPublishedVersion(pkg = "vibedeckx", fetchImpl = fetch) {
241791
+ try {
241792
+ const response = await fetchImpl(
241793
+ `https://registry.npmjs.org/${pkg}/latest`,
241794
+ { signal: AbortSignal.timeout(4e3) }
241795
+ );
241796
+ if (!response.ok) return void 0;
241797
+ const body = await response.json();
241798
+ return typeof body.version === "string" && parseSemver(body.version) ? body.version : void 0;
241799
+ } catch {
241800
+ return void 0;
241801
+ }
241802
+ }
241803
+ function parseSemver(version2) {
241804
+ const match2 = SEMVER_RE.exec(version2);
241805
+ if (!match2) return void 0;
241806
+ return {
241807
+ core: [match2[1], match2[2], match2[3]],
241808
+ prerelease: match2[4]?.split(".")
241809
+ };
241810
+ }
241811
+ function compareNumericStrings(a, b2) {
241812
+ if (a.length !== b2.length) return a.length - b2.length;
241813
+ return a < b2 ? -1 : a > b2 ? 1 : 0;
241814
+ }
241815
+ function comparePrereleaseIdentifiers(a, b2) {
241816
+ const aNumeric = /^\d+$/.test(a);
241817
+ const bNumeric = /^\d+$/.test(b2);
241818
+ if (aNumeric && bNumeric) return compareNumericStrings(a, b2);
241819
+ if (aNumeric !== bNumeric) return aNumeric ? -1 : 1;
241820
+ return a < b2 ? -1 : a > b2 ? 1 : 0;
241821
+ }
241822
+ function compareSemver(a, b2) {
241823
+ for (let i = 0; i < 3; i += 1) {
241824
+ const compared = compareNumericStrings(a.core[i], b2.core[i]);
241825
+ if (compared !== 0) return compared;
241826
+ }
241827
+ if (!a.prerelease && !b2.prerelease) return 0;
241828
+ if (!a.prerelease) return 1;
241829
+ if (!b2.prerelease) return -1;
241830
+ const length = Math.max(a.prerelease.length, b2.prerelease.length);
241831
+ for (let i = 0; i < length; i += 1) {
241832
+ const aId = a.prerelease[i];
241833
+ const bId = b2.prerelease[i];
241834
+ if (aId === void 0) return -1;
241835
+ if (bId === void 0) return 1;
241836
+ const compared = comparePrereleaseIdentifiers(aId, bId);
241837
+ if (compared !== 0) return compared;
241838
+ }
241839
+ return 0;
241840
+ }
241841
+ function compareUpdateStatus(current, latest) {
241842
+ if (latest === void 0) return "unknown";
241843
+ const currentParsed = parseSemver(current);
241844
+ const latestParsed = parseSemver(latest);
241845
+ if (!currentParsed || !latestParsed) return "unknown";
241846
+ return compareSemver(latestParsed, currentParsed) > 0 ? "update-available" : "up-to-date";
241847
+ }
241848
+
241849
+ // src/connect-daemon.ts
241759
241850
  var CONNECT_DAEMON_CHILD_ENV = "VIBEDECKX_INTERNAL_CONNECT_DAEMON";
241760
241851
  var CONNECT_DAEMON_TOKEN_ENV = "VIBEDECKX_INTERNAL_CONNECT_TOKEN";
241761
241852
  function buildDaemonChildArgs(argv) {
@@ -242303,18 +242394,31 @@ function inspectDaemonState(dataDir) {
242303
242394
  const actualTicks = readLinuxProcessStartTicks(parsed.pid);
242304
242395
  return actualTicks === parsed.processStartTicks ? { kind: "running", state: parsed } : { kind: "stale", state: parsed };
242305
242396
  }
242306
- function describeConnectDaemon(dataDir) {
242397
+ function describeUpdateStatus(current, latest) {
242398
+ switch (compareUpdateStatus(current, latest)) {
242399
+ case "update-available":
242400
+ return `(update available: ${latest})`;
242401
+ case "up-to-date":
242402
+ return "(up to date)";
242403
+ case "unknown":
242404
+ return "(update check failed)";
242405
+ }
242406
+ }
242407
+ async function describeConnectDaemon(dataDir, fetchLatestVersion = fetchLatestPublishedVersion) {
242307
242408
  const inspection = inspectDaemonState(dataDir);
242308
242409
  switch (inspection.kind) {
242309
- case "running":
242410
+ case "running": {
242411
+ const latest = await fetchLatestVersion();
242310
242412
  return {
242311
242413
  exitCode: 0,
242312
242414
  message: [
242313
242415
  `Running (PID ${inspection.state.pid}, since ${inspection.state.startedAt})`,
242416
+ `Version: ${inspection.state.version} ${describeUpdateStatus(inspection.state.version, latest)}`,
242314
242417
  `Target: ${inspection.state.connectTo}`,
242315
242418
  `Logs: ${path19.join(dataDir, "logs", "vibedeckx.log")}`
242316
242419
  ].join("\n")
242317
242420
  };
242421
+ }
242318
242422
  case "missing":
242319
242423
  return { exitCode: 1, message: "Vibedeckx connect is not running" };
242320
242424
  case "stale":
@@ -242537,6 +242641,78 @@ function removeVerifiedStaleStateUnlocked(dataDir) {
242537
242641
  }
242538
242642
  }
242539
242643
 
242644
+ // src/connect-preflight.ts
242645
+ var CONNECT_IDENTITY_HEADER = "x-vibedeckx-connect-token";
242646
+ var PINNED_IDENTITY_SETTING_PREFIX = "reverse_pinned_identity:";
242647
+ function canonicalizeHubUrl(raw) {
242648
+ let url2;
242649
+ try {
242650
+ url2 = new URL(raw);
242651
+ } catch {
242652
+ throw new Error(`Invalid --connect-to URL: ${raw}`);
242653
+ }
242654
+ if (url2.protocol !== "http:" && url2.protocol !== "https:") {
242655
+ throw new Error(`--connect-to must be an http(s) URL, got: ${raw}`);
242656
+ }
242657
+ const pathname = url2.pathname.replace(/\/+$/, "");
242658
+ return `${url2.origin}${pathname}`;
242659
+ }
242660
+ function parsePin(raw) {
242661
+ try {
242662
+ const parsed = JSON.parse(raw);
242663
+ if (parsed && typeof parsed === "object") return parsed;
242664
+ } catch {
242665
+ }
242666
+ return {};
242667
+ }
242668
+ async function preflightIdentityCheck(opts) {
242669
+ const fetchImpl = opts.fetchImpl ?? fetch;
242670
+ const hubUrl = canonicalizeHubUrl(opts.connectTo);
242671
+ let config2;
242672
+ try {
242673
+ const res2 = await fetchImpl(`${hubUrl}/api/config`);
242674
+ if (res2.ok) config2 = await res2.json();
242675
+ } catch {
242676
+ }
242677
+ if (config2?.reverseConnectIdentity !== true) return { checked: false };
242678
+ const res = await fetchImpl(`${hubUrl}/api/reverse-connect/identity`, {
242679
+ headers: { [CONNECT_IDENTITY_HEADER]: opts.token }
242680
+ });
242681
+ if (res.status === 401) {
242682
+ throw new Error("Connect token was rejected by the server (invalid or revoked)");
242683
+ }
242684
+ if (res.status === 403) {
242685
+ throw new Error("This token's remote is not configured for inbound connections");
242686
+ }
242687
+ if (!res.ok) {
242688
+ throw new Error(`Identity preflight failed with status ${res.status}`);
242689
+ }
242690
+ const body = await res.json();
242691
+ if (!body || typeof body.serverId !== "string" || body.serverId.length === 0) {
242692
+ throw new Error("Malformed identity response from server");
242693
+ }
242694
+ const identity = { serverId: body.serverId, name: body.name ?? "" };
242695
+ const key = `${PINNED_IDENTITY_SETTING_PREFIX}${hubUrl}`;
242696
+ const desired = JSON.stringify(identity);
242697
+ if (opts.force) {
242698
+ await opts.settings.set(key, desired);
242699
+ return { checked: true, identity };
242700
+ }
242701
+ const persisted = await opts.settings.getOrCreate(key, () => desired);
242702
+ const pinned = parsePin(persisted);
242703
+ if (pinned.serverId && pinned.serverId !== identity.serverId) {
242704
+ const pinnedLabel = pinned.name || pinned.serverId;
242705
+ const tokenLabel = identity.name || identity.serverId;
242706
+ throw new Error(
242707
+ `This machine previously served remote "${pinnedLabel}" on ${hubUrl}, but the provided token belongs to "${tokenLabel}". If this is intentional, re-run with --force to re-pin.`
242708
+ );
242709
+ }
242710
+ if (!pinned.serverId || pinned.name !== identity.name) {
242711
+ await opts.settings.set(key, desired);
242712
+ }
242713
+ return { checked: true, identity };
242714
+ }
242715
+
242540
242716
  // ../../node_modules/.pnpm/open@10.2.0/node_modules/open/index.js
242541
242717
  import process8 from "node:process";
242542
242718
  import { Buffer as Buffer2 } from "node:buffer";
@@ -243233,6 +243409,11 @@ var connectCommand = buildCommand({
243233
243409
  brief: "Run in the background after initialization (Linux only)",
243234
243410
  optional: true
243235
243411
  },
243412
+ force: {
243413
+ kind: "boolean",
243414
+ brief: "Re-pin this machine to the token's remote, overriding the pinned-identity mismatch guard",
243415
+ optional: true
243416
+ },
243236
243417
  port: {
243237
243418
  kind: "parsed",
243238
243419
  parse: parseInt,
@@ -243332,6 +243513,17 @@ var connectCommand = buildCommand({
243332
243513
  console.log("Starting vibedeckx in reverse-connect mode...");
243333
243514
  const dbPath = path21.join(dataDir, "data.sqlite");
243334
243515
  storage = await createSqliteStorage(dbPath);
243516
+ const preflight = await preflightIdentityCheck({
243517
+ connectTo: flags["connect-to"],
243518
+ token,
243519
+ settings: storage.settings,
243520
+ force: flags.force ?? false
243521
+ });
243522
+ if (preflight.checked && preflight.identity) {
243523
+ console.log(
243524
+ `Remote identity verified: ${preflight.identity.name || preflight.identity.serverId}`
243525
+ );
243526
+ }
243335
243527
  server = await createServer({
243336
243528
  storage,
243337
243529
  acceptRemote: true,
@@ -243404,7 +243596,9 @@ var connectStatusCommand = buildCommand({
243404
243596
  parameters: { flags: connectManagementFlags },
243405
243597
  func: async (flags) => {
243406
243598
  assertConnectDaemonPlatform();
243407
- const result = describeConnectDaemon(flags["data-dir"] ?? VIBEDECKX_HOME);
243599
+ const result = await describeConnectDaemon(
243600
+ flags["data-dir"] ?? VIBEDECKX_HOME
243601
+ );
243408
243602
  return reportDaemonCommandResult(result);
243409
243603
  },
243410
243604
  docs: { brief: "Show the connect daemon status" }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibedeckx/linux-x64",
3
- "version": "0.2.11",
3
+ "version": "0.2.13",
4
4
  "description": "Vibedeckx platform binaries for Linux x64",
5
5
  "os": [
6
6
  "linux"