@klaudworks/rmr 0.4.3 → 0.4.5

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
@@ -8,6 +8,8 @@ Define multi-step coding workflows that match how you actually work. `rmr` orche
8
8
 
9
9
  ```bash
10
10
  npm install -g @klaudworks/rmr
11
+
12
+ # run from the root of your project
11
13
  rmr install feature-dev
12
14
  rmr run .rmr/workflows/feature-dev/workflow.yaml --task "Implement feature X"
13
15
  ```
package/dist/index.js CHANGED
@@ -1,5 +1,4 @@
1
- #!/usr/bin/env bun
2
- // @bun
1
+ #!/usr/bin/env node
3
2
  import { createRequire } from "node:module";
4
3
  var __create = Object.create;
5
4
  var __getProtoOf = Object.getPrototypeOf;
@@ -7944,46 +7943,6 @@ var require_public_api = __commonJS((exports) => {
7944
7943
  exports.parseDocument = parseDocument;
7945
7944
  exports.stringify = stringify;
7946
7945
  });
7947
- // node_modules/clipanion/lib/platform/node.mjs
7948
- import tty from "tty";
7949
- function getDefaultColorDepth() {
7950
- if (tty && `getColorDepth` in tty.WriteStream.prototype)
7951
- return tty.WriteStream.prototype.getColorDepth();
7952
- if (process.env.FORCE_COLOR === `0`)
7953
- return 1;
7954
- if (process.env.FORCE_COLOR === `1`)
7955
- return 8;
7956
- if (typeof process.stdout !== `undefined` && process.stdout.isTTY)
7957
- return 8;
7958
- return 1;
7959
- }
7960
- var gContextStorage;
7961
- function getCaptureActivator(context) {
7962
- let contextStorage = gContextStorage;
7963
- if (typeof contextStorage === `undefined`) {
7964
- if (context.stdout === process.stdout && context.stderr === process.stderr)
7965
- return null;
7966
- const { AsyncLocalStorage: LazyAsyncLocalStorage } = __require("async_hooks");
7967
- contextStorage = gContextStorage = new LazyAsyncLocalStorage;
7968
- const origStdoutWrite = process.stdout._write;
7969
- process.stdout._write = function(chunk, encoding, cb) {
7970
- const context2 = contextStorage.getStore();
7971
- if (typeof context2 === `undefined`)
7972
- return origStdoutWrite.call(this, chunk, encoding, cb);
7973
- return context2.stdout.write(chunk, encoding, cb);
7974
- };
7975
- const origStderrWrite = process.stderr._write;
7976
- process.stderr._write = function(chunk, encoding, cb) {
7977
- const context2 = contextStorage.getStore();
7978
- if (typeof context2 === `undefined`)
7979
- return origStderrWrite.call(this, chunk, encoding, cb);
7980
- return context2.stderr.write(chunk, encoding, cb);
7981
- };
7982
- }
7983
- return (fn) => {
7984
- return contextStorage.run(context, fn);
7985
- };
7986
- }
7987
7946
 
7988
7947
  // node_modules/clipanion/lib/constants.mjs
7989
7948
  var SpecialToken;
@@ -8077,6 +8036,136 @@ var whileRunning = (input) => `While running ${input.filter((token) => {
8077
8036
  }
8078
8037
  }).join(` `)}`;
8079
8038
 
8039
+ // node_modules/clipanion/lib/advanced/options/utils.mjs
8040
+ var isOptionSymbol = Symbol(`clipanion/isOption`);
8041
+ function makeCommandOption(spec) {
8042
+ return { ...spec, [isOptionSymbol]: true };
8043
+ }
8044
+ function rerouteArguments(a, b) {
8045
+ if (typeof a === `undefined`)
8046
+ return [a, b];
8047
+ if (typeof a === `object` && a !== null && !Array.isArray(a)) {
8048
+ return [undefined, a];
8049
+ } else {
8050
+ return [a, b];
8051
+ }
8052
+ }
8053
+ function cleanValidationError(message, { mergeName = false } = {}) {
8054
+ const match = message.match(/^([^:]+): (.*)$/m);
8055
+ if (!match)
8056
+ return `validation failed`;
8057
+ let [, path, line] = match;
8058
+ if (mergeName)
8059
+ line = line[0].toLowerCase() + line.slice(1);
8060
+ line = path !== `.` || !mergeName ? `${path.replace(/^\.(\[|$)/, `$1`)}: ${line}` : `: ${line}`;
8061
+ return line;
8062
+ }
8063
+ function formatError(message, errors) {
8064
+ if (errors.length === 1) {
8065
+ return new UsageError(`${message}${cleanValidationError(errors[0], { mergeName: true })}`);
8066
+ } else {
8067
+ return new UsageError(`${message}:
8068
+ ${errors.map((error) => `
8069
+ - ${cleanValidationError(error)}`).join(``)}`);
8070
+ }
8071
+ }
8072
+ function applyValidator(name, value, validator) {
8073
+ if (typeof validator === `undefined`)
8074
+ return value;
8075
+ const errors = [];
8076
+ const coercions = [];
8077
+ const coercion = (v) => {
8078
+ const orig = value;
8079
+ value = v;
8080
+ return coercion.bind(null, orig);
8081
+ };
8082
+ const check = validator(value, { errors, coercions, coercion });
8083
+ if (!check)
8084
+ throw formatError(`Invalid value for ${name}`, errors);
8085
+ for (const [, op] of coercions)
8086
+ op();
8087
+ return value;
8088
+ }
8089
+
8090
+ // node_modules/clipanion/lib/advanced/Command.mjs
8091
+ class Command {
8092
+ constructor() {
8093
+ this.help = false;
8094
+ }
8095
+ static Usage(usage) {
8096
+ return usage;
8097
+ }
8098
+ async catch(error) {
8099
+ throw error;
8100
+ }
8101
+ async validateAndExecute() {
8102
+ const commandClass = this.constructor;
8103
+ const cascade = commandClass.schema;
8104
+ if (Array.isArray(cascade)) {
8105
+ const { isDict, isUnknown, applyCascade } = await Promise.resolve().then(() => __toESM(require_lib(), 1));
8106
+ const schema = applyCascade(isDict(isUnknown()), cascade);
8107
+ const errors = [];
8108
+ const coercions = [];
8109
+ const check = schema(this, { errors, coercions });
8110
+ if (!check)
8111
+ throw formatError(`Invalid option schema`, errors);
8112
+ for (const [, op] of coercions) {
8113
+ op();
8114
+ }
8115
+ } else if (cascade != null) {
8116
+ throw new Error(`Invalid command schema`);
8117
+ }
8118
+ const exitCode = await this.execute();
8119
+ if (typeof exitCode !== `undefined`) {
8120
+ return exitCode;
8121
+ } else {
8122
+ return 0;
8123
+ }
8124
+ }
8125
+ }
8126
+ Command.isOption = isOptionSymbol;
8127
+ Command.Default = [];
8128
+ // node_modules/clipanion/lib/platform/node.mjs
8129
+ import tty from "tty";
8130
+ function getDefaultColorDepth() {
8131
+ if (tty && `getColorDepth` in tty.WriteStream.prototype)
8132
+ return tty.WriteStream.prototype.getColorDepth();
8133
+ if (process.env.FORCE_COLOR === `0`)
8134
+ return 1;
8135
+ if (process.env.FORCE_COLOR === `1`)
8136
+ return 8;
8137
+ if (typeof process.stdout !== `undefined` && process.stdout.isTTY)
8138
+ return 8;
8139
+ return 1;
8140
+ }
8141
+ var gContextStorage;
8142
+ function getCaptureActivator(context) {
8143
+ let contextStorage = gContextStorage;
8144
+ if (typeof contextStorage === `undefined`) {
8145
+ if (context.stdout === process.stdout && context.stderr === process.stderr)
8146
+ return null;
8147
+ const { AsyncLocalStorage: LazyAsyncLocalStorage } = __require("async_hooks");
8148
+ contextStorage = gContextStorage = new LazyAsyncLocalStorage;
8149
+ const origStdoutWrite = process.stdout._write;
8150
+ process.stdout._write = function(chunk, encoding, cb) {
8151
+ const context2 = contextStorage.getStore();
8152
+ if (typeof context2 === `undefined`)
8153
+ return origStdoutWrite.call(this, chunk, encoding, cb);
8154
+ return context2.stdout.write(chunk, encoding, cb);
8155
+ };
8156
+ const origStderrWrite = process.stderr._write;
8157
+ process.stderr._write = function(chunk, encoding, cb) {
8158
+ const context2 = contextStorage.getStore();
8159
+ if (typeof context2 === `undefined`)
8160
+ return origStderrWrite.call(this, chunk, encoding, cb);
8161
+ return context2.stderr.write(chunk, encoding, cb);
8162
+ };
8163
+ }
8164
+ return (fn) => {
8165
+ return contextStorage.run(context, fn);
8166
+ };
8167
+ }
8168
+
8080
8169
  // node_modules/clipanion/lib/core.mjs
8081
8170
  function debug(str) {
8082
8171
  if (IS_DEBUG) {
@@ -8860,70 +8949,6 @@ function formatMarkdownish(text, { format, paragraphs }) {
8860
8949
  ` : ``;
8861
8950
  }
8862
8951
 
8863
- // node_modules/clipanion/lib/advanced/options/utils.mjs
8864
- var isOptionSymbol = Symbol(`clipanion/isOption`);
8865
- function makeCommandOption(spec) {
8866
- return { ...spec, [isOptionSymbol]: true };
8867
- }
8868
- function cleanValidationError(message, { mergeName = false } = {}) {
8869
- const match = message.match(/^([^:]+): (.*)$/m);
8870
- if (!match)
8871
- return `validation failed`;
8872
- let [, path, line] = match;
8873
- if (mergeName)
8874
- line = line[0].toLowerCase() + line.slice(1);
8875
- line = path !== `.` || !mergeName ? `${path.replace(/^\.(\[|$)/, `$1`)}: ${line}` : `: ${line}`;
8876
- return line;
8877
- }
8878
- function formatError(message, errors) {
8879
- if (errors.length === 1) {
8880
- return new UsageError(`${message}${cleanValidationError(errors[0], { mergeName: true })}`);
8881
- } else {
8882
- return new UsageError(`${message}:
8883
- ${errors.map((error) => `
8884
- - ${cleanValidationError(error)}`).join(``)}`);
8885
- }
8886
- }
8887
-
8888
- // node_modules/clipanion/lib/advanced/Command.mjs
8889
- class Command {
8890
- constructor() {
8891
- this.help = false;
8892
- }
8893
- static Usage(usage) {
8894
- return usage;
8895
- }
8896
- async catch(error) {
8897
- throw error;
8898
- }
8899
- async validateAndExecute() {
8900
- const commandClass = this.constructor;
8901
- const cascade = commandClass.schema;
8902
- if (Array.isArray(cascade)) {
8903
- const { isDict, isUnknown, applyCascade } = await Promise.resolve().then(() => __toESM(require_lib(), 1));
8904
- const schema = applyCascade(isDict(isUnknown()), cascade);
8905
- const errors = [];
8906
- const coercions = [];
8907
- const check = schema(this, { errors, coercions });
8908
- if (!check)
8909
- throw formatError(`Invalid option schema`, errors);
8910
- for (const [, op] of coercions) {
8911
- op();
8912
- }
8913
- } else if (cascade != null) {
8914
- throw new Error(`Invalid command schema`);
8915
- }
8916
- const exitCode = await this.execute();
8917
- if (typeof exitCode !== `undefined`) {
8918
- return exitCode;
8919
- } else {
8920
- return 0;
8921
- }
8922
- }
8923
- }
8924
- Command.isOption = isOptionSymbol;
8925
- Command.Default = [];
8926
-
8927
8952
  // node_modules/clipanion/lib/advanced/HelpCommand.mjs
8928
8953
  class HelpCommand extends Command {
8929
8954
  static from(state, contexts) {
@@ -9389,19 +9414,208 @@ VersionCommand.paths = [[`-v`], [`--version`]];
9389
9414
  var exports_options = {};
9390
9415
  __export(exports_options, {
9391
9416
  rerouteArguments: () => rerouteArguments,
9392
- makeCommandOption: () => makeCommandOption2,
9393
- isOptionSymbol: () => isOptionSymbol2,
9394
- formatError: () => formatError2,
9395
- cleanValidationError: () => cleanValidationError2,
9417
+ makeCommandOption: () => makeCommandOption,
9418
+ isOptionSymbol: () => isOptionSymbol,
9419
+ formatError: () => formatError,
9420
+ cleanValidationError: () => cleanValidationError,
9396
9421
  applyValidator: () => applyValidator,
9397
9422
  String: () => String2,
9398
9423
  Rest: () => Rest,
9399
- Proxy: () => Proxy2,
9424
+ Proxy: () => Proxy,
9400
9425
  Counter: () => Counter,
9401
9426
  Boolean: () => Boolean2,
9402
9427
  Array: () => Array2
9403
9428
  });
9404
9429
 
9430
+ // node_modules/clipanion/lib/advanced/options/Array.mjs
9431
+ function Array2(descriptor, initialValueBase, optsBase) {
9432
+ const [initialValue, opts] = rerouteArguments(initialValueBase, optsBase !== null && optsBase !== undefined ? optsBase : {});
9433
+ const { arity = 1 } = opts;
9434
+ const optNames = descriptor.split(`,`);
9435
+ const nameSet = new Set(optNames);
9436
+ return makeCommandOption({
9437
+ definition(builder) {
9438
+ builder.addOption({
9439
+ names: optNames,
9440
+ arity,
9441
+ hidden: opts === null || opts === undefined ? undefined : opts.hidden,
9442
+ description: opts === null || opts === undefined ? undefined : opts.description,
9443
+ required: opts.required
9444
+ });
9445
+ },
9446
+ transformer(builder, key, state) {
9447
+ let usedName;
9448
+ let currentValue = typeof initialValue !== `undefined` ? [...initialValue] : undefined;
9449
+ for (const { name, value } of state.options) {
9450
+ if (!nameSet.has(name))
9451
+ continue;
9452
+ usedName = name;
9453
+ currentValue = currentValue !== null && currentValue !== undefined ? currentValue : [];
9454
+ currentValue.push(value);
9455
+ }
9456
+ if (typeof currentValue !== `undefined`) {
9457
+ return applyValidator(usedName !== null && usedName !== undefined ? usedName : key, currentValue, opts.validator);
9458
+ } else {
9459
+ return currentValue;
9460
+ }
9461
+ }
9462
+ });
9463
+ }
9464
+ // node_modules/clipanion/lib/advanced/options/Boolean.mjs
9465
+ function Boolean2(descriptor, initialValueBase, optsBase) {
9466
+ const [initialValue, opts] = rerouteArguments(initialValueBase, optsBase !== null && optsBase !== undefined ? optsBase : {});
9467
+ const optNames = descriptor.split(`,`);
9468
+ const nameSet = new Set(optNames);
9469
+ return makeCommandOption({
9470
+ definition(builder) {
9471
+ builder.addOption({
9472
+ names: optNames,
9473
+ allowBinding: false,
9474
+ arity: 0,
9475
+ hidden: opts.hidden,
9476
+ description: opts.description,
9477
+ required: opts.required
9478
+ });
9479
+ },
9480
+ transformer(builer, key, state) {
9481
+ let currentValue = initialValue;
9482
+ for (const { name, value } of state.options) {
9483
+ if (!nameSet.has(name))
9484
+ continue;
9485
+ currentValue = value;
9486
+ }
9487
+ return currentValue;
9488
+ }
9489
+ });
9490
+ }
9491
+ // node_modules/clipanion/lib/advanced/options/Counter.mjs
9492
+ function Counter(descriptor, initialValueBase, optsBase) {
9493
+ const [initialValue, opts] = rerouteArguments(initialValueBase, optsBase !== null && optsBase !== undefined ? optsBase : {});
9494
+ const optNames = descriptor.split(`,`);
9495
+ const nameSet = new Set(optNames);
9496
+ return makeCommandOption({
9497
+ definition(builder) {
9498
+ builder.addOption({
9499
+ names: optNames,
9500
+ allowBinding: false,
9501
+ arity: 0,
9502
+ hidden: opts.hidden,
9503
+ description: opts.description,
9504
+ required: opts.required
9505
+ });
9506
+ },
9507
+ transformer(builder, key, state) {
9508
+ let currentValue = initialValue;
9509
+ for (const { name, value } of state.options) {
9510
+ if (!nameSet.has(name))
9511
+ continue;
9512
+ currentValue !== null && currentValue !== undefined || (currentValue = 0);
9513
+ if (!value) {
9514
+ currentValue = 0;
9515
+ } else {
9516
+ currentValue += 1;
9517
+ }
9518
+ }
9519
+ return currentValue;
9520
+ }
9521
+ });
9522
+ }
9523
+ // node_modules/clipanion/lib/advanced/options/Rest.mjs
9524
+ function Rest(opts = {}) {
9525
+ return makeCommandOption({
9526
+ definition(builder, key) {
9527
+ var _a;
9528
+ builder.addRest({
9529
+ name: (_a = opts.name) !== null && _a !== undefined ? _a : key,
9530
+ required: opts.required
9531
+ });
9532
+ },
9533
+ transformer(builder, key, state) {
9534
+ const isRestPositional = (index) => {
9535
+ const positional = state.positionals[index];
9536
+ if (positional.extra === NoLimits)
9537
+ return true;
9538
+ if (positional.extra === false && index < builder.arity.leading.length)
9539
+ return true;
9540
+ return false;
9541
+ };
9542
+ let count = 0;
9543
+ while (count < state.positionals.length && isRestPositional(count))
9544
+ count += 1;
9545
+ return state.positionals.splice(0, count).map(({ value }) => value);
9546
+ }
9547
+ });
9548
+ }
9549
+ // node_modules/clipanion/lib/advanced/options/String.mjs
9550
+ function StringOption(descriptor, initialValueBase, optsBase) {
9551
+ const [initialValue, opts] = rerouteArguments(initialValueBase, optsBase !== null && optsBase !== undefined ? optsBase : {});
9552
+ const { arity = 1 } = opts;
9553
+ const optNames = descriptor.split(`,`);
9554
+ const nameSet = new Set(optNames);
9555
+ return makeCommandOption({
9556
+ definition(builder) {
9557
+ builder.addOption({
9558
+ names: optNames,
9559
+ arity: opts.tolerateBoolean ? 0 : arity,
9560
+ hidden: opts.hidden,
9561
+ description: opts.description,
9562
+ required: opts.required
9563
+ });
9564
+ },
9565
+ transformer(builder, key, state, context) {
9566
+ let usedName;
9567
+ let currentValue = initialValue;
9568
+ if (typeof opts.env !== `undefined` && context.env[opts.env]) {
9569
+ usedName = opts.env;
9570
+ currentValue = context.env[opts.env];
9571
+ }
9572
+ for (const { name, value } of state.options) {
9573
+ if (!nameSet.has(name))
9574
+ continue;
9575
+ usedName = name;
9576
+ currentValue = value;
9577
+ }
9578
+ if (typeof currentValue === `string`) {
9579
+ return applyValidator(usedName !== null && usedName !== undefined ? usedName : key, currentValue, opts.validator);
9580
+ } else {
9581
+ return currentValue;
9582
+ }
9583
+ }
9584
+ });
9585
+ }
9586
+ function StringPositional(opts = {}) {
9587
+ const { required = true } = opts;
9588
+ return makeCommandOption({
9589
+ definition(builder, key) {
9590
+ var _a;
9591
+ builder.addPositional({
9592
+ name: (_a = opts.name) !== null && _a !== undefined ? _a : key,
9593
+ required: opts.required
9594
+ });
9595
+ },
9596
+ transformer(builder, key, state) {
9597
+ var _a;
9598
+ for (let i = 0;i < state.positionals.length; ++i) {
9599
+ if (state.positionals[i].extra === NoLimits)
9600
+ continue;
9601
+ if (required && state.positionals[i].extra === true)
9602
+ continue;
9603
+ if (!required && state.positionals[i].extra === false)
9604
+ continue;
9605
+ const [positional] = state.positionals.splice(i, 1);
9606
+ return applyValidator((_a = opts.name) !== null && _a !== undefined ? _a : key, positional.value, opts.validator);
9607
+ }
9608
+ return;
9609
+ }
9610
+ });
9611
+ }
9612
+ function String2(descriptor, ...args) {
9613
+ if (typeof descriptor === `string`) {
9614
+ return StringOption(descriptor, ...args);
9615
+ } else {
9616
+ return StringPositional(descriptor);
9617
+ }
9618
+ }
9405
9619
  // src/lib/config.ts
9406
9620
  import { mkdir } from "node:fs/promises";
9407
9621
  import { resolve } from "node:path";
@@ -9890,6 +10104,9 @@ function getHarnessAdapter(name) {
9890
10104
  return adapter;
9891
10105
  }
9892
10106
 
10107
+ // src/lib/process-runner.ts
10108
+ import { spawn } from "node:child_process";
10109
+
9893
10110
  // node_modules/chalk/source/vendor/ansi-styles/index.js
9894
10111
  var ANSI_BACKGROUND_OFFSET = 10;
9895
10112
  var wrapAnsi16 = (offset = 0) => (code) => `\x1B[${code + offset}m`;
@@ -10608,25 +10825,6 @@ var ui = {
10608
10825
  };
10609
10826
 
10610
10827
  // src/lib/process-runner.ts
10611
- async function consumeStream(stream, onText) {
10612
- if (!stream) {
10613
- return "";
10614
- }
10615
- const reader = stream.getReader();
10616
- const decoder = new TextDecoder;
10617
- let fullText = "";
10618
- while (true) {
10619
- const { done, value } = await reader.read();
10620
- if (done) {
10621
- break;
10622
- }
10623
- const chunk = decoder.decode(value, { stream: true });
10624
- fullText += chunk;
10625
- onText(chunk);
10626
- }
10627
- fullText += decoder.decode();
10628
- return fullText;
10629
- }
10630
10828
  function formatToolInput(toolInput) {
10631
10829
  try {
10632
10830
  const parsed = JSON.parse(toolInput);
@@ -10644,95 +10842,83 @@ function formatToolInput(toolInput) {
10644
10842
  return toolInput.length > 100 ? toolInput.slice(0, 97) + "..." : toolInput;
10645
10843
  }
10646
10844
  }
10647
- async function consumeStreamParsed(stream, parser) {
10648
- if (!stream) {
10649
- return { rawOutput: "", displayText: "", sessionId: null };
10650
- }
10651
- const reader = stream.getReader();
10652
- const decoder = new TextDecoder;
10653
- let rawOutput = "";
10654
- let displayText = "";
10655
- let sessionId = null;
10656
- let lineBuf = "";
10657
- let lastTextWasContent = false;
10658
- function processLine(line) {
10659
- const parsed = parser(line);
10660
- if (!parsed) {
10661
- return;
10662
- }
10663
- if (parsed.toolName) {
10664
- if (lastTextWasContent) {
10665
- process.stderr.write(`
10845
+ async function runHarnessCommand(command, parseStreamLine) {
10846
+ return new Promise((resolve5, reject) => {
10847
+ const child = spawn(command.binary, command.args, {
10848
+ stdio: ["ignore", "pipe", "pipe"]
10849
+ });
10850
+ child.on("error", (err) => {
10851
+ if (err.code === "ENOENT") {
10852
+ reject(new StorageError(`Harness binary "${command.binary}" not found. ` + `Make sure it is installed and available on your PATH.`));
10853
+ } else if (err.code === "EACCES") {
10854
+ reject(new StorageError(`Permission denied when trying to run "${command.binary}". ` + `Check that the binary is executable.`));
10855
+ } else {
10856
+ reject(new StorageError(`Failed to launch harness binary "${command.binary}": ${err.message}`));
10857
+ }
10858
+ });
10859
+ let interrupted = false;
10860
+ const onSigint = () => {
10861
+ interrupted = true;
10862
+ };
10863
+ process.on("SIGINT", onSigint);
10864
+ let displayText = "";
10865
+ let sessionId = null;
10866
+ let stderrText = "";
10867
+ let stdoutLineBuf = "";
10868
+ let lastTextWasContent = false;
10869
+ function processLine(line) {
10870
+ const parsed = parseStreamLine(line);
10871
+ if (!parsed) {
10872
+ return;
10873
+ }
10874
+ if (parsed.toolName) {
10875
+ if (lastTextWasContent) {
10876
+ process.stderr.write(`
10666
10877
  `);
10667
- lastTextWasContent = false;
10878
+ lastTextWasContent = false;
10879
+ }
10880
+ const inputDisplay = parsed.toolInput ? formatToolInput(parsed.toolInput) : "";
10881
+ ui.printToolCall(parsed.toolName, inputDisplay);
10882
+ }
10883
+ if (parsed.text) {
10884
+ displayText += parsed.text;
10885
+ ui.content(parsed.text);
10886
+ lastTextWasContent = true;
10887
+ }
10888
+ if (parsed.sessionId) {
10889
+ sessionId = parsed.sessionId;
10668
10890
  }
10669
- const inputDisplay = parsed.toolInput ? formatToolInput(parsed.toolInput) : "";
10670
- ui.printToolCall(parsed.toolName, inputDisplay);
10671
- }
10672
- if (parsed.text) {
10673
- displayText += parsed.text;
10674
- ui.content(parsed.text);
10675
- lastTextWasContent = true;
10676
- }
10677
- if (parsed.sessionId) {
10678
- sessionId = parsed.sessionId;
10679
- }
10680
- }
10681
- while (true) {
10682
- const { done, value } = await reader.read();
10683
- if (done) {
10684
- break;
10685
10891
  }
10686
- const chunk = decoder.decode(value, { stream: true });
10687
- rawOutput += chunk;
10688
- lineBuf += chunk;
10689
- const lines = lineBuf.split(`
10892
+ child.stdout.on("data", (chunk) => {
10893
+ const text = chunk.toString();
10894
+ stdoutLineBuf += text;
10895
+ const lines = stdoutLineBuf.split(`
10690
10896
  `);
10691
- lineBuf = lines.pop() ?? "";
10692
- for (const line of lines) {
10693
- processLine(line);
10694
- }
10695
- }
10696
- rawOutput += decoder.decode();
10697
- if (lineBuf.trim()) {
10698
- processLine(lineBuf);
10699
- }
10700
- return { rawOutput, displayText, sessionId };
10701
- }
10702
- async function runHarnessCommand(command, parseStreamLine) {
10703
- let processRef;
10704
- try {
10705
- processRef = Bun.spawn({
10706
- cmd: [command.binary, ...command.args],
10707
- stdin: "ignore",
10708
- stdout: "pipe",
10709
- stderr: "pipe"
10897
+ stdoutLineBuf = lines.pop() ?? "";
10898
+ for (const line of lines) {
10899
+ processLine(line);
10900
+ }
10901
+ });
10902
+ child.stderr.on("data", (chunk) => {
10903
+ const text = chunk.toString();
10904
+ stderrText += text;
10905
+ process.stderr.write(text);
10906
+ });
10907
+ child.on("close", (code) => {
10908
+ if (stdoutLineBuf.trim()) {
10909
+ processLine(stdoutLineBuf);
10910
+ }
10911
+ process.removeListener("SIGINT", onSigint);
10912
+ const exitCode = interrupted && code === 0 ? 130 : code ?? 1;
10913
+ resolve5({
10914
+ exitCode,
10915
+ stdout: displayText,
10916
+ stderr: stderrText,
10917
+ combinedOutput: `${displayText}${stderrText}`,
10918
+ sessionId
10919
+ });
10710
10920
  });
10711
- } catch {
10712
- throw new StorageError(`Failed to launch harness binary "${command.binary}".`);
10713
- }
10714
- let interrupted = false;
10715
- const onSigint = () => {
10716
- interrupted = true;
10717
- };
10718
- process.on("SIGINT", onSigint);
10719
- const stdoutPromise = consumeStreamParsed(processRef.stdout, parseStreamLine);
10720
- const stderrPromise = consumeStream(processRef.stderr, (chunk) => {
10721
- process.stderr.write(chunk);
10722
10921
  });
10723
- const [exitCode, stdoutResult, stderr] = await Promise.all([
10724
- processRef.exited,
10725
- stdoutPromise,
10726
- stderrPromise
10727
- ]);
10728
- process.removeListener("SIGINT", onSigint);
10729
- return {
10730
- exitCode: interrupted && exitCode === 0 ? 130 : exitCode,
10731
- stdout: stdoutResult.displayText,
10732
- stderr,
10733
- combinedOutput: `${stdoutResult.displayText}${stderr}`,
10734
- sessionId: stdoutResult.sessionId
10735
- };
10736
10922
  }
10737
10923
 
10738
10924
  // src/lib/rmr-output-parser.ts
@@ -11395,16 +11581,6 @@ class RootCommand extends Command {
11395
11581
  }
11396
11582
  }
11397
11583
 
11398
- // src/lib/errors.ts
11399
- class RmrError2 extends Error {
11400
- code;
11401
- constructor(code, message) {
11402
- super(message);
11403
- this.name = "RmrError";
11404
- this.code = code;
11405
- }
11406
- }
11407
-
11408
11584
  // src/lib/logger.ts
11409
11585
  var colors = {
11410
11586
  reset: "\x1B[0m",
@@ -11579,37 +11755,11 @@ class RunCommand extends Command {
11579
11755
  }
11580
11756
  }
11581
11757
 
11582
- // src/lib/version.ts
11583
- import { readFileSync as readFileSync2 } from "node:fs";
11584
- import { dirname as dirname4, resolve as resolve9 } from "node:path";
11585
- import { fileURLToPath as fileURLToPath3 } from "node:url";
11586
- var cached2;
11587
- function getVersion2() {
11588
- if (cached2)
11589
- return cached2;
11590
- const thisDir = dirname4(fileURLToPath3(import.meta.url));
11591
- const candidates = [
11592
- resolve9(thisDir, "..", "package.json"),
11593
- resolve9(thisDir, "..", "..", "package.json")
11594
- ];
11595
- for (const candidate of candidates) {
11596
- try {
11597
- const pkg = JSON.parse(readFileSync2(candidate, "utf8"));
11598
- if (pkg.version) {
11599
- cached2 = pkg.version;
11600
- return cached2;
11601
- }
11602
- } catch {}
11603
- }
11604
- cached2 = "0.0.0";
11605
- return cached2;
11606
- }
11607
-
11608
11758
  // src/index.ts
11609
11759
  var [, , ...args] = process.argv;
11610
11760
  var cli = new Cli({
11611
11761
  binaryName: "rmr",
11612
- binaryVersion: getVersion2(),
11762
+ binaryVersion: getVersion(),
11613
11763
  enableColors: false
11614
11764
  });
11615
11765
  cli.register(exports_builtins.HelpCommand);
@@ -11624,7 +11774,7 @@ try {
11624
11774
  const exitCode = await cli.run(args);
11625
11775
  process.exitCode = exitCode;
11626
11776
  } catch (error) {
11627
- if (error instanceof RmrError2) {
11777
+ if (error instanceof RmrError) {
11628
11778
  logger.error(`${error.code}: ${error.message}`);
11629
11779
  process.exitCode = 1;
11630
11780
  } else if (error instanceof Error) {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@klaudworks/rex",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@klaudworks/rex",
9
- "version": "0.4.3",
9
+ "version": "0.4.5",
10
10
  "dependencies": {
11
11
  "clipanion": "^4.0.0-rc.4",
12
12
  "yaml": "^2.8.2"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@klaudworks/rmr",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "description": "Define multi-step coding workflows for AI agents",
5
5
  "repository": {
6
6
  "type": "git",