@jmoyers/harness 0.1.7 → 0.1.8

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/README.md CHANGED
@@ -40,6 +40,10 @@ bunx @jmoyers/harness@latest
40
40
 
41
41
  # Or install globally
42
42
  bun add -g --trust @jmoyers/harness
43
+
44
+ # Upgrade an existing global install
45
+ harness update
46
+ # alias: harness upgrade
43
47
  ```
44
48
 
45
49
  ### Install (from source)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jmoyers/harness",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -83,6 +83,7 @@ const DEFAULT_SESSION_ROOT_PATH = 'sessions';
83
83
  const PROFILE_STATE_FILE_NAME = 'active-profile.json';
84
84
  const PROFILE_CLIENT_FILE_NAME = 'client.cpuprofile';
85
85
  const PROFILE_GATEWAY_FILE_NAME = 'gateway.cpuprofile';
86
+ const DEFAULT_HARNESS_UPDATE_PACKAGE = '@jmoyers/harness@latest';
86
87
  const PROFILE_STATE_VERSION = 2;
87
88
  const PROFILE_LIVE_INSPECT_MODE = 'live-inspector';
88
89
  const SESSION_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/u;
@@ -793,6 +794,60 @@ function parseGatewayCommand(argv: readonly string[]): ParsedGatewayCommand {
793
794
  throw new Error(`unknown gateway subcommand: ${subcommand}`);
794
795
  }
795
796
 
797
+ function resolveHarnessUpdatePackageSpec(env: NodeJS.ProcessEnv): string {
798
+ const configured = env.HARNESS_UPDATE_PACKAGE;
799
+ if (typeof configured !== 'string') {
800
+ return DEFAULT_HARNESS_UPDATE_PACKAGE;
801
+ }
802
+ const trimmed = configured.trim();
803
+ return trimmed.length > 0 ? trimmed : DEFAULT_HARNESS_UPDATE_PACKAGE;
804
+ }
805
+
806
+ function formatExecErrorOutput(value: unknown): string {
807
+ if (typeof value === 'string') {
808
+ return value;
809
+ }
810
+ if (value instanceof Buffer) {
811
+ return value.toString('utf8');
812
+ }
813
+ return '';
814
+ }
815
+
816
+ function runHarnessUpdateCommand(invocationDirectory: string, env: NodeJS.ProcessEnv): number {
817
+ const packageSpec = resolveHarnessUpdatePackageSpec(env);
818
+ process.stdout.write(`updating Harness package: ${packageSpec}\n`);
819
+ try {
820
+ const stdout = execFileSync('bun', ['add', '-g', '--trust', packageSpec], {
821
+ cwd: invocationDirectory,
822
+ env,
823
+ encoding: 'utf8',
824
+ stdio: ['ignore', 'pipe', 'pipe'],
825
+ });
826
+ if (stdout.length > 0) {
827
+ process.stdout.write(stdout);
828
+ }
829
+ process.stdout.write(`harness update complete: ${packageSpec}\n`);
830
+ return 0;
831
+ } catch (error: unknown) {
832
+ const typed = error as NodeJS.ErrnoException & {
833
+ readonly stdout?: unknown;
834
+ readonly stderr?: unknown;
835
+ readonly status?: number | null;
836
+ };
837
+ const stdout = formatExecErrorOutput(typed.stdout);
838
+ const stderr = formatExecErrorOutput(typed.stderr);
839
+ if (stdout.length > 0) {
840
+ process.stdout.write(stdout);
841
+ }
842
+ if (stderr.length > 0) {
843
+ process.stderr.write(stderr);
844
+ }
845
+ const statusText =
846
+ typeof typed.status === 'number' ? `exit=${String(typed.status)}` : 'exit=unknown';
847
+ throw new Error(`harness update command failed (${statusText})`);
848
+ }
849
+ }
850
+
796
851
  function printUsage(): void {
797
852
  process.stdout.write(
798
853
  [
@@ -814,6 +869,8 @@ function printUsage(): void {
814
869
  ' harness [--session <name>] render-trace start [--output-path <path>] [--conversation-id <id>]',
815
870
  ' harness [--session <name>] render-trace stop',
816
871
  ' harness [--session <name>] render-trace [--output-path <path>] [--conversation-id <id>]',
872
+ ' harness update',
873
+ ' harness upgrade',
817
874
  ' harness cursor-hooks install [--hooks-file <path>]',
818
875
  ' harness cursor-hooks uninstall [--hooks-file <path>]',
819
876
  ' harness animate [--fps <fps>] [--frames <count>] [--duration-ms <ms>] [--seed <seed>] [--no-color]',
@@ -2499,6 +2556,13 @@ async function main(): Promise<number> {
2499
2556
  );
2500
2557
  }
2501
2558
 
2559
+ if (argv.length > 0 && (argv[0] === 'update' || argv[0] === 'upgrade')) {
2560
+ if (argv.length > 1) {
2561
+ throw new Error(`unknown ${argv[0]} option: ${argv[1]}`);
2562
+ }
2563
+ return runHarnessUpdateCommand(invocationDirectory, process.env);
2564
+ }
2565
+
2502
2566
  if (argv.length > 0 && argv[0] === 'cursor-hooks') {
2503
2567
  const command = parseCursorHooksCommand(argv.slice(1));
2504
2568
  return await runCursorHooksCommandEntry(invocationDirectory, command);