Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@devlln/helm

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@devlln/helm - npm Package Compare versions

Comparing version
0.2.1
to
0.3.0
+2
-2
bridge/package-lock.json
{
"name": "codex-voice-remote-bridge",
"version": "0.2.1",
"version": "0.3.0",
"lockfileVersion": 3,

@@ -9,3 +9,3 @@ "requires": true,

"name": "codex-voice-remote-bridge",
"version": "0.2.1",
"version": "0.3.0",
"dependencies": {

@@ -12,0 +12,0 @@ "dotenv": "^16.6.1",

{
"name": "codex-voice-remote-bridge",
"version": "0.2.1",
"version": "0.3.0",
"private": true,

@@ -5,0 +5,0 @@ "type": "module",

@@ -9,2 +9,3 @@ import test from "node:test";

detectBridgeInstallMethod,
getBridgeUpdateStatus,
shouldEnableBridgeAutoUpdate,

@@ -105,1 +106,19 @@ } from "./bridgeAutoUpdater.js";

});
test("getBridgeUpdateStatus reports available updates with a user-facing link and command", async () => {
const result = await getBridgeUpdateStatus({
rootDir: "/opt/homebrew/Cellar/helm/0.2.0/libexec",
packageInfo: { name: "@devlln/helm", version: "0.2.0" },
hasGitDir: false,
env: {},
installMethod: "homebrew",
fetchLatestVersion: async () => "0.2.1",
scriptExists: () => true,
});
assert.equal(result.status, "available");
assert.equal(result.currentVersion, "0.2.0");
assert.equal(result.latestVersion, "0.2.1");
assert.equal(result.updateURL, "https://www.npmjs.com/package/@devlln/helm/v/0.2.1");
assert.equal(result.updateCommand, "brew update && brew upgrade devlln/helm/helm");
});

@@ -23,2 +23,4 @@ import { spawn } from "node:child_process";

installMethod?: BridgeInstallMethod;
updateURL?: string;
updateCommand?: string;
}

@@ -38,2 +40,12 @@

export interface BridgeUpdateStatus {
status: "disabled" | "current" | "available" | "skipped";
reason?: string;
currentVersion?: string;
latestVersion?: string;
installMethod?: BridgeInstallMethod;
updateURL?: string;
updateCommand?: string;
}
export interface StartBridgeAutoUpdaterOptions extends BridgeUpdateCheckOptions {

@@ -133,2 +145,24 @@ setTimeoutFn?: typeof setTimeout;

function updateCommandForDisplay(installMethod: BridgeInstallMethod): string {
switch (installMethod) {
case "homebrew":
return "brew update && brew upgrade devlln/helm/helm";
case "npm":
return "npm install -g @devlln/helm@latest";
case "git":
return "git pull && npm --prefix bridge install";
case "unknown":
default:
return "helm update";
}
}
function updateURLForVersion(version: string | undefined): string | undefined {
if (!version) {
return undefined;
}
return `https://www.npmjs.com/package/${PUBLIC_PACKAGE_NAME}/v/${version}`;
}
function readPackageInfo(rootDir: string): BridgePackageInfo | null {

@@ -175,2 +209,34 @@ try {

export async function checkForBridgeUpdate(options: BridgeUpdateCheckOptions): Promise<BridgeUpdateCheckResult> {
const status = await getBridgeUpdateStatus(options);
switch (status.status) {
case "disabled":
case "current":
case "skipped":
return {
...status,
status: status.status,
};
case "available":
break;
}
const installMethod = status.installMethod ?? "unknown";
const updateCommand = buildBridgeUpdateCommand({ rootDir: options.rootDir, installMethod });
const runUpdate = options.runUpdate ?? runDetachedUpdate;
runUpdate(updateCommand.command, updateCommand.args);
options.logger?.log(
`[bridge] Helm ${status.currentVersion ?? "<unknown>"} is older than ${status.latestVersion ?? "<unknown>"}; started ${installMethod} update.`
);
return {
status: "started",
currentVersion: status.currentVersion,
latestVersion: status.latestVersion,
installMethod,
updateURL: status.updateURL,
updateCommand: status.updateCommand,
};
}
export async function getBridgeUpdateStatus(options: BridgeUpdateCheckOptions): Promise<BridgeUpdateStatus> {
const env = options.env ?? process.env;

@@ -195,2 +261,3 @@ const packageInfo = options.packageInfo ?? readPackageInfo(options.rootDir);

installMethod,
updateCommand: updateCommandForDisplay(installMethod),
};

@@ -207,2 +274,3 @@ }

installMethod,
updateCommand: updateCommandForDisplay(installMethod),
};

@@ -222,2 +290,3 @@ }

installMethod,
updateCommand: updateCommandForDisplay(installMethod),
};

@@ -232,2 +301,3 @@ }

installMethod,
updateCommand: updateCommandForDisplay(installMethod),
};

@@ -242,14 +312,14 @@ }

installMethod,
updateURL: updateURLForVersion(latestVersion),
updateCommand: updateCommandForDisplay(installMethod),
};
}
const runUpdate = options.runUpdate ?? runDetachedUpdate;
runUpdate(updateCommand.command, updateCommand.args);
options.logger?.log(`[bridge] Helm ${packageInfo.version} is older than ${latestVersion}; started ${installMethod} update.`);
return {
status: "started",
status: "available",
currentVersion: packageInfo.version,
latestVersion,
installMethod,
updateURL: updateURLForVersion(latestVersion),
updateCommand: updateCommandForDisplay(installMethod),
};

@@ -256,0 +326,0 @@ }

@@ -84,2 +84,8 @@ import test from "node:test";

request(method: string, params?: JSONValue): Promise<JSONValue | undefined>;
sendRequestInBackground(
method: string,
params?: JSONValue,
timeoutMs?: number,
onSettle?: (settlement: { result?: JSONValue; error?: Error }) => void
): Promise<string | number>;
readCodexDesktopActiveWorkspaceRoots(): Promise<string[]>;

@@ -142,2 +148,9 @@ loadThreadDeliverySummary(threadId: string): Promise<{ sourceKind?: string | null; status?: string | null } | null>;

): Promise<JSONValue | undefined>;
startCodexDesktopMobileDeliveryViaAppServerFirst(
threadId: string,
text: string,
options: TestStartTurnOptions,
needsSteer: boolean,
baseline: unknown
): Promise<JSONValue | undefined>;
ensureAppServerThreadLoadedForDelivery(

@@ -332,2 +345,4 @@ threadId: string,

let startCalls = 0;
const ensureCalls: Array<{ threadId: string; options?: { forceResume?: boolean } }> = [];
const backgroundRequestCalls: Array<{ method: string; params?: JSONValue; timeoutMs?: number }> = [];

@@ -352,11 +367,11 @@ hooks.loadThreadDeliverySummary = async () => ({

startCalls += 1;
assert.equal(threadId, "thread-1");
assert.equal(text, "from mobile");
assert.equal(options.deliveryMode, "queue");
return {
ok: true,
mode: "codexDesktopIpcStart",
threadId,
};
throw new Error(`idle desktop sends should use app-server first: ${threadId} ${text} ${options.deliveryMode}`);
};
hooks.ensureAppServerThreadLoadedForDelivery = async (threadId, options) => {
ensureCalls.push({ threadId, options });
};
hooks.sendRequestInBackground = async (method: string, params?: JSONValue, timeoutMs?: number) => {
backgroundRequestCalls.push({ method, params, timeoutMs });
return 42;
};

@@ -368,7 +383,31 @@ const result = await client.startTurn("thread-1", "from mobile", {

assert.equal(enqueueCalls, 0);
assert.equal(startCalls, 1);
assert.equal(startCalls, 0);
assert.deepEqual(ensureCalls, [
{
threadId: "thread-1",
options: undefined,
},
]);
assert.deepEqual(backgroundRequestCalls, [
{
method: "turn/start",
timeoutMs: 90_000,
params: {
threadId: "thread-1",
input: [
{
type: "text",
text: "from mobile",
text_elements: [],
},
],
},
},
]);
assert.deepEqual(result, {
ok: true,
mode: "codexDesktopIpcStart",
accepted: true,
mode: "appServerStartAcceptedForCodexDesktopMobileDelivery",
threadId: "thread-1",
requestId: 42,
});

@@ -424,8 +463,10 @@ });

test("idle Codex desktop steer retries as an app-server start when route-refresh IPC has no loaded client", async () => {
test("idle Codex desktop steer uses app-server start before route-refresh IPC", async () => {
const client = new CodexAppServerClient("ws://127.0.0.1:0");
const hooks = client as unknown as CodexClientPrivateHooks;
const requestCalls: Array<{ method: string; params?: JSONValue }> = [];
const backgroundRequestCalls: Array<{ method: string; params?: JSONValue; timeoutMs?: number }> = [];
const ensureCalls: Array<{ threadId: string; options?: { forceResume?: boolean } }> = [];
const refreshCalls: Array<{ threadId: string; reason?: string }> = [];
let desktopStartCalls = 0;
let desktopSteerCalls = 0;

@@ -446,6 +487,8 @@ hooks.loadThreadDeliverySummary = async () => ({

hooks.startTurnViaCodexDesktopIpc = async () => {
throw new Error("Codex Desktop IPC thread-follower-start-turn failed: no-client-found");
desktopStartCalls += 1;
throw new Error("idle desktop sends should use app-server first");
};
hooks.steerTurnViaCodexDesktopIpc = async () => {
throw new Error("Codex Desktop IPC thread-follower-steer-turn failed: no-client-found");
desktopSteerCalls += 1;
throw new Error("idle desktop sends should use app-server first");
};

@@ -464,7 +507,5 @@ hooks.enqueueTurnViaCodexDesktopIpc = async () => {

hooks.waitForThreadDelivery = async () => false;
hooks.request = async (method: string, params?: JSONValue) => {
requestCalls.push({ method, params });
return {
ok: true,
};
hooks.sendRequestInBackground = async (method: string, params?: JSONValue, timeoutMs?: number) => {
backgroundRequestCalls.push({ method, params, timeoutMs });
return 43;
};

@@ -478,14 +519,19 @@

ok: true,
mode: "appServerStartAfterDesktopIpcNoClientWithDesktopRefresh",
accepted: true,
mode: "appServerStartAcceptedForCodexDesktopMobileDelivery",
threadId: "thread-1",
requestId: 43,
});
assert.equal(desktopStartCalls, 0);
assert.equal(desktopSteerCalls, 0);
assert.deepEqual(ensureCalls, [
{
threadId: "thread-1",
options: { forceResume: true },
options: undefined,
},
]);
assert.deepEqual(requestCalls, [
assert.deepEqual(backgroundRequestCalls, [
{
method: "turn/start",
timeoutMs: 90_000,
params: {

@@ -503,6 +549,3 @@ threadId: "thread-1",

]);
assert.deepEqual(refreshCalls, [
{ threadId: "thread-1", reason: "desktop-ipc-start-unavailable" },
{ threadId: "thread-1", reason: "desktop-ipc-no-client" },
]);
assert.deepEqual(refreshCalls, []);
});

@@ -529,2 +572,3 @@

});
hooks.startCodexDesktopMobileDeliveryViaAppServerFirst = async () => undefined;
hooks.startTurnViaCodexDesktopIpc = async () => {

@@ -584,2 +628,3 @@ throw new Error("Codex Desktop IPC thread-follower-start-turn failed: no-client-found");

});
hooks.startCodexDesktopMobileDeliveryViaAppServerFirst = async () => undefined;
hooks.startTurnViaCodexDesktopIpc = async () => {

@@ -646,2 +691,3 @@ throw new Error("Codex Desktop IPC thread-follower-start-turn failed: no-client-found");

});
hooks.startCodexDesktopMobileDeliveryViaAppServerFirst = async () => undefined;
hooks.startTurnViaCodexDesktopIpc = async () => {

@@ -710,2 +756,3 @@ throw new Error("Codex Desktop IPC request timed out: thread-follower-start-turn");

});
hooks.startCodexDesktopMobileDeliveryViaAppServerFirst = async () => undefined;
hooks.startTurnViaCodexDesktopIpc = async () => {

@@ -766,2 +813,3 @@ throw new Error("Codex Desktop IPC request timed out: thread-follower-start-turn");

});
hooks.startCodexDesktopMobileDeliveryViaAppServerFirst = async () => undefined;
hooks.startTurnViaCodexDesktopIpc = async () => {

@@ -959,10 +1007,8 @@ throw new Error("Codex Desktop IPC request timed out: thread-follower-start-turn");

test("running Codex desktop steer falls back to app-server steer when desktop IPC has no loaded client", async () => {
test("running Codex desktop steer acknowledges after background app-server steer handoff", async () => {
const client = new CodexAppServerClient("ws://127.0.0.1:0");
const hooks = client as unknown as CodexClientPrivateHooks;
const appServerSteerCalls: Array<{
threadId: string;
text: string;
activeTurnId: string | null;
}> = [];
const backgroundRequestCalls: Array<{ method: string; params?: JSONValue; timeoutMs?: number }> = [];
let desktopSteerCalls = 0;
let desktopStartCalls = 0;

@@ -982,5 +1028,7 @@ hooks.loadThreadDeliverySummary = async () => ({

hooks.steerTurnViaCodexDesktopIpc = async () => {
desktopSteerCalls += 1;
throw new Error("Codex Desktop IPC thread-follower-steer-turn failed: no-client-found");
};
hooks.startTurnViaCodexDesktopIpc = async () => {
desktopStartCalls += 1;
throw new Error("running steer must not start a side turn");

@@ -992,13 +1040,5 @@ };

};
hooks.startTurnViaAppServerSteer = async (threadId, text, baseline) => {
appServerSteerCalls.push({
threadId,
text,
activeTurnId: baseline.activeTurnId,
});
return {
ok: true,
mode: "appServerSteerQueued",
threadId,
};
hooks.sendRequestInBackground = async (method: string, params?: JSONValue, timeoutMs?: number) => {
backgroundRequestCalls.push({ method, params, timeoutMs });
return 44;
};

@@ -1012,10 +1052,24 @@

ok: true,
mode: "appServerSteerQueued",
accepted: true,
mode: "appServerSteerAcceptedForCodexDesktopMobileDelivery",
threadId: "thread-1",
requestId: 44,
});
assert.deepEqual(appServerSteerCalls, [
assert.equal(desktopSteerCalls, 0);
assert.equal(desktopStartCalls, 0);
assert.deepEqual(backgroundRequestCalls, [
{
threadId: "thread-1",
text: "testing mobile",
activeTurnId: "turn-1",
method: "turn/steer",
timeoutMs: 90_000,
params: {
threadId: "thread-1",
input: [
{
type: "text",
text: "testing mobile",
text_elements: [],
},
],
expectedTurnId: "turn-1",
},
},

@@ -1022,0 +1076,0 @@ ]);

@@ -9,3 +9,3 @@ import { dirname, resolve } from "node:path";

const rootDir = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..");
const server = new BridgeServer();
const server = new BridgeServer({ rootDir });
await server.start();

@@ -12,0 +12,0 @@ startBridgeAutoUpdater({ rootDir, logger: console });

{
"name": "@devlln/helm",
"version": "0.2.1",
"version": "0.3.0",
"private": false,

@@ -5,0 +5,0 @@ "description": "Helm CLI bridge installer and runtime helpers.",

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display