@klaudworks/rmr 0.4.2 → 0.4.3

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
@@ -7,14 +7,9 @@ Define multi-step coding workflows that match how you actually work. `rmr` orche
7
7
  ## Quick Start
8
8
 
9
9
  ```bash
10
- npx @klaudworks/rmr@latest install feature-dev # add the feature-dev workflow
11
- npx @klaudworks/rmr@latest run .rmr/workflows/feature-dev/workflow.yaml --task "Implement feature X" # run it
12
- ```
13
-
14
- Using `npx` with `@latest` always runs the newest version. To avoid the prefix, install globally:
15
-
16
- ```bash
17
- npm install -g @klaudworks/rmr@latest
10
+ npm install -g @klaudworks/rmr
11
+ rmr install feature-dev
12
+ rmr run .rmr/workflows/feature-dev/workflow.yaml --task "Implement feature X"
18
13
  ```
19
14
 
20
15
  ## Sample Workflows
package/dist/index.js CHANGED
@@ -8865,15 +8865,6 @@ var isOptionSymbol = Symbol(`clipanion/isOption`);
8865
8865
  function makeCommandOption(spec) {
8866
8866
  return { ...spec, [isOptionSymbol]: true };
8867
8867
  }
8868
- function rerouteArguments(a, b) {
8869
- if (typeof a === `undefined`)
8870
- return [a, b];
8871
- if (typeof a === `object` && a !== null && !Array.isArray(a)) {
8872
- return [undefined, a];
8873
- } else {
8874
- return [a, b];
8875
- }
8876
- }
8877
8868
  function cleanValidationError(message, { mergeName = false } = {}) {
8878
8869
  const match = message.match(/^([^:]+): (.*)$/m);
8879
8870
  if (!match)
@@ -8893,23 +8884,6 @@ ${errors.map((error) => `
8893
8884
  - ${cleanValidationError(error)}`).join(``)}`);
8894
8885
  }
8895
8886
  }
8896
- function applyValidator(name, value, validator) {
8897
- if (typeof validator === `undefined`)
8898
- return value;
8899
- const errors = [];
8900
- const coercions = [];
8901
- const coercion = (v) => {
8902
- const orig = value;
8903
- value = v;
8904
- return coercion.bind(null, orig);
8905
- };
8906
- const check = validator(value, { errors, coercions, coercion });
8907
- if (!check)
8908
- throw formatError(`Invalid value for ${name}`, errors);
8909
- for (const [, op] of coercions)
8910
- op();
8911
- return value;
8912
- }
8913
8887
 
8914
8888
  // node_modules/clipanion/lib/advanced/Command.mjs
8915
8889
  class Command {
@@ -9415,208 +9389,19 @@ VersionCommand.paths = [[`-v`], [`--version`]];
9415
9389
  var exports_options = {};
9416
9390
  __export(exports_options, {
9417
9391
  rerouteArguments: () => rerouteArguments,
9418
- makeCommandOption: () => makeCommandOption,
9419
- isOptionSymbol: () => isOptionSymbol,
9420
- formatError: () => formatError,
9421
- cleanValidationError: () => cleanValidationError,
9392
+ makeCommandOption: () => makeCommandOption2,
9393
+ isOptionSymbol: () => isOptionSymbol2,
9394
+ formatError: () => formatError2,
9395
+ cleanValidationError: () => cleanValidationError2,
9422
9396
  applyValidator: () => applyValidator,
9423
9397
  String: () => String2,
9424
9398
  Rest: () => Rest,
9425
- Proxy: () => Proxy,
9399
+ Proxy: () => Proxy2,
9426
9400
  Counter: () => Counter,
9427
9401
  Boolean: () => Boolean2,
9428
9402
  Array: () => Array2
9429
9403
  });
9430
9404
 
9431
- // node_modules/clipanion/lib/advanced/options/Array.mjs
9432
- function Array2(descriptor, initialValueBase, optsBase) {
9433
- const [initialValue, opts] = rerouteArguments(initialValueBase, optsBase !== null && optsBase !== undefined ? optsBase : {});
9434
- const { arity = 1 } = opts;
9435
- const optNames = descriptor.split(`,`);
9436
- const nameSet = new Set(optNames);
9437
- return makeCommandOption({
9438
- definition(builder) {
9439
- builder.addOption({
9440
- names: optNames,
9441
- arity,
9442
- hidden: opts === null || opts === undefined ? undefined : opts.hidden,
9443
- description: opts === null || opts === undefined ? undefined : opts.description,
9444
- required: opts.required
9445
- });
9446
- },
9447
- transformer(builder, key, state) {
9448
- let usedName;
9449
- let currentValue = typeof initialValue !== `undefined` ? [...initialValue] : undefined;
9450
- for (const { name, value } of state.options) {
9451
- if (!nameSet.has(name))
9452
- continue;
9453
- usedName = name;
9454
- currentValue = currentValue !== null && currentValue !== undefined ? currentValue : [];
9455
- currentValue.push(value);
9456
- }
9457
- if (typeof currentValue !== `undefined`) {
9458
- return applyValidator(usedName !== null && usedName !== undefined ? usedName : key, currentValue, opts.validator);
9459
- } else {
9460
- return currentValue;
9461
- }
9462
- }
9463
- });
9464
- }
9465
- // node_modules/clipanion/lib/advanced/options/Boolean.mjs
9466
- function Boolean2(descriptor, initialValueBase, optsBase) {
9467
- const [initialValue, opts] = rerouteArguments(initialValueBase, optsBase !== null && optsBase !== undefined ? optsBase : {});
9468
- const optNames = descriptor.split(`,`);
9469
- const nameSet = new Set(optNames);
9470
- return makeCommandOption({
9471
- definition(builder) {
9472
- builder.addOption({
9473
- names: optNames,
9474
- allowBinding: false,
9475
- arity: 0,
9476
- hidden: opts.hidden,
9477
- description: opts.description,
9478
- required: opts.required
9479
- });
9480
- },
9481
- transformer(builer, key, state) {
9482
- let currentValue = initialValue;
9483
- for (const { name, value } of state.options) {
9484
- if (!nameSet.has(name))
9485
- continue;
9486
- currentValue = value;
9487
- }
9488
- return currentValue;
9489
- }
9490
- });
9491
- }
9492
- // node_modules/clipanion/lib/advanced/options/Counter.mjs
9493
- function Counter(descriptor, initialValueBase, optsBase) {
9494
- const [initialValue, opts] = rerouteArguments(initialValueBase, optsBase !== null && optsBase !== undefined ? optsBase : {});
9495
- const optNames = descriptor.split(`,`);
9496
- const nameSet = new Set(optNames);
9497
- return makeCommandOption({
9498
- definition(builder) {
9499
- builder.addOption({
9500
- names: optNames,
9501
- allowBinding: false,
9502
- arity: 0,
9503
- hidden: opts.hidden,
9504
- description: opts.description,
9505
- required: opts.required
9506
- });
9507
- },
9508
- transformer(builder, key, state) {
9509
- let currentValue = initialValue;
9510
- for (const { name, value } of state.options) {
9511
- if (!nameSet.has(name))
9512
- continue;
9513
- currentValue !== null && currentValue !== undefined || (currentValue = 0);
9514
- if (!value) {
9515
- currentValue = 0;
9516
- } else {
9517
- currentValue += 1;
9518
- }
9519
- }
9520
- return currentValue;
9521
- }
9522
- });
9523
- }
9524
- // node_modules/clipanion/lib/advanced/options/Rest.mjs
9525
- function Rest(opts = {}) {
9526
- return makeCommandOption({
9527
- definition(builder, key) {
9528
- var _a;
9529
- builder.addRest({
9530
- name: (_a = opts.name) !== null && _a !== undefined ? _a : key,
9531
- required: opts.required
9532
- });
9533
- },
9534
- transformer(builder, key, state) {
9535
- const isRestPositional = (index) => {
9536
- const positional = state.positionals[index];
9537
- if (positional.extra === NoLimits)
9538
- return true;
9539
- if (positional.extra === false && index < builder.arity.leading.length)
9540
- return true;
9541
- return false;
9542
- };
9543
- let count = 0;
9544
- while (count < state.positionals.length && isRestPositional(count))
9545
- count += 1;
9546
- return state.positionals.splice(0, count).map(({ value }) => value);
9547
- }
9548
- });
9549
- }
9550
- // node_modules/clipanion/lib/advanced/options/String.mjs
9551
- function StringOption(descriptor, initialValueBase, optsBase) {
9552
- const [initialValue, opts] = rerouteArguments(initialValueBase, optsBase !== null && optsBase !== undefined ? optsBase : {});
9553
- const { arity = 1 } = opts;
9554
- const optNames = descriptor.split(`,`);
9555
- const nameSet = new Set(optNames);
9556
- return makeCommandOption({
9557
- definition(builder) {
9558
- builder.addOption({
9559
- names: optNames,
9560
- arity: opts.tolerateBoolean ? 0 : arity,
9561
- hidden: opts.hidden,
9562
- description: opts.description,
9563
- required: opts.required
9564
- });
9565
- },
9566
- transformer(builder, key, state, context) {
9567
- let usedName;
9568
- let currentValue = initialValue;
9569
- if (typeof opts.env !== `undefined` && context.env[opts.env]) {
9570
- usedName = opts.env;
9571
- currentValue = context.env[opts.env];
9572
- }
9573
- for (const { name, value } of state.options) {
9574
- if (!nameSet.has(name))
9575
- continue;
9576
- usedName = name;
9577
- currentValue = value;
9578
- }
9579
- if (typeof currentValue === `string`) {
9580
- return applyValidator(usedName !== null && usedName !== undefined ? usedName : key, currentValue, opts.validator);
9581
- } else {
9582
- return currentValue;
9583
- }
9584
- }
9585
- });
9586
- }
9587
- function StringPositional(opts = {}) {
9588
- const { required = true } = opts;
9589
- return makeCommandOption({
9590
- definition(builder, key) {
9591
- var _a;
9592
- builder.addPositional({
9593
- name: (_a = opts.name) !== null && _a !== undefined ? _a : key,
9594
- required: opts.required
9595
- });
9596
- },
9597
- transformer(builder, key, state) {
9598
- var _a;
9599
- for (let i = 0;i < state.positionals.length; ++i) {
9600
- if (state.positionals[i].extra === NoLimits)
9601
- continue;
9602
- if (required && state.positionals[i].extra === true)
9603
- continue;
9604
- if (!required && state.positionals[i].extra === false)
9605
- continue;
9606
- const [positional] = state.positionals.splice(i, 1);
9607
- return applyValidator((_a = opts.name) !== null && _a !== undefined ? _a : key, positional.value, opts.validator);
9608
- }
9609
- return;
9610
- }
9611
- });
9612
- }
9613
- function String2(descriptor, ...args) {
9614
- if (typeof descriptor === `string`) {
9615
- return StringOption(descriptor, ...args);
9616
- } else {
9617
- return StringPositional(descriptor);
9618
- }
9619
- }
9620
9405
  // src/lib/config.ts
9621
9406
  import { mkdir } from "node:fs/promises";
9622
9407
  import { resolve } from "node:path";
@@ -11162,9 +10947,91 @@ function parseHarnessOverride(value) {
11162
10947
  return value;
11163
10948
  }
11164
10949
 
10950
+ // src/lib/version.ts
10951
+ import { readFileSync } from "node:fs";
10952
+ import { dirname as dirname2, resolve as resolve5 } from "node:path";
10953
+ import { fileURLToPath } from "node:url";
10954
+ var cached;
10955
+ function getVersion() {
10956
+ if (cached)
10957
+ return cached;
10958
+ const thisDir = dirname2(fileURLToPath(import.meta.url));
10959
+ const candidates = [
10960
+ resolve5(thisDir, "..", "package.json"),
10961
+ resolve5(thisDir, "..", "..", "package.json")
10962
+ ];
10963
+ for (const candidate of candidates) {
10964
+ try {
10965
+ const pkg = JSON.parse(readFileSync(candidate, "utf8"));
10966
+ if (pkg.version) {
10967
+ cached = pkg.version;
10968
+ return cached;
10969
+ }
10970
+ } catch {}
10971
+ }
10972
+ cached = "0.0.0";
10973
+ return cached;
10974
+ }
10975
+
10976
+ // src/lib/update-check.ts
10977
+ var PACKAGE_NAME = "@klaudworks/rmr";
10978
+ var REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
10979
+ var FETCH_TIMEOUT_MS = 3000;
10980
+ function isNewer(latest, current) {
10981
+ const l = latest.split(".").map(Number);
10982
+ const c = current.split(".").map(Number);
10983
+ for (let i = 0;i < 3; i++) {
10984
+ const lv = l[i] ?? 0;
10985
+ const cv = c[i] ?? 0;
10986
+ if (lv > cv)
10987
+ return true;
10988
+ if (lv < cv)
10989
+ return false;
10990
+ }
10991
+ return false;
10992
+ }
10993
+ async function fetchLatestVersion() {
10994
+ try {
10995
+ const controller = new AbortController;
10996
+ const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
10997
+ const response = await fetch(REGISTRY_URL, {
10998
+ signal: controller.signal,
10999
+ headers: { accept: "application/json" }
11000
+ });
11001
+ clearTimeout(timeout);
11002
+ if (!response.ok)
11003
+ return null;
11004
+ const data = await response.json();
11005
+ return data.version ?? null;
11006
+ } catch {
11007
+ return null;
11008
+ }
11009
+ }
11010
+ function startUpdateCheck() {
11011
+ const currentVersion = getVersion();
11012
+ let result = null;
11013
+ const check = fetchLatestVersion().then((latestVersion) => {
11014
+ if (latestVersion && isNewer(latestVersion, currentVersion)) {
11015
+ result = { latestVersion };
11016
+ }
11017
+ }).catch(() => {});
11018
+ return () => {
11019
+ check.then(() => {
11020
+ if (result) {
11021
+ process.stderr.write(`
11022
+ `);
11023
+ ui.dim(`Update available: ${currentVersion} → ${result.latestVersion}
11024
+ `);
11025
+ ui.dim(`Run: npm install -g ${PACKAGE_NAME}@${result.latestVersion}
11026
+ `);
11027
+ }
11028
+ }).catch(() => {});
11029
+ };
11030
+ }
11031
+
11165
11032
  // src/lib/workflow-loader.ts
11166
11033
  import { readFile as readFile3 } from "node:fs/promises";
11167
- import { resolve as resolve5 } from "node:path";
11034
+ import { resolve as resolve6 } from "node:path";
11168
11035
 
11169
11036
  // node_modules/yaml/dist/index.js
11170
11037
  var composer = require_composer();
@@ -11246,7 +11113,7 @@ function validateUniqueness(items, kind) {
11246
11113
  }
11247
11114
  }
11248
11115
  async function loadWorkflowDefinition(workflowPath) {
11249
- const absolutePath = resolve5(workflowPath);
11116
+ const absolutePath = resolve6(workflowPath);
11250
11117
  const raw = await readFile3(absolutePath, "utf8");
11251
11118
  const parsed = $parse(raw);
11252
11119
  if (!parsed || typeof parsed !== "object") {
@@ -11368,6 +11235,7 @@ class ContinueCommand extends Command {
11368
11235
  description: "Inject a one-time hint into the resumed harness prompt."
11369
11236
  });
11370
11237
  async execute() {
11238
+ const showUpdateNotice = startUpdateCheck();
11371
11239
  const config = await loadConfig();
11372
11240
  const runState = await loadRunState(config, this.runId);
11373
11241
  const workflow = await loadWorkflowDefinition(runState.workflow_path);
@@ -11405,6 +11273,7 @@ class ContinueCommand extends Command {
11405
11273
  allowAll: true,
11406
11274
  overrides
11407
11275
  });
11276
+ showUpdateNotice();
11408
11277
  return 0;
11409
11278
  }
11410
11279
  }
@@ -11412,12 +11281,12 @@ class ContinueCommand extends Command {
11412
11281
  // src/commands/install.ts
11413
11282
  import { cp, readdir as readdir2 } from "node:fs/promises";
11414
11283
  import { existsSync } from "node:fs";
11415
- import { dirname as dirname2, resolve as resolve6 } from "node:path";
11416
- import { fileURLToPath } from "node:url";
11284
+ import { dirname as dirname3, resolve as resolve7 } from "node:path";
11285
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
11417
11286
  function getExamplesWorkflowsDir() {
11418
- const thisDir = dirname2(fileURLToPath(import.meta.url));
11419
- const fromDist = resolve6(thisDir, "..", "examples", "workflows");
11420
- const fromSrc = resolve6(thisDir, "..", "..", "examples", "workflows");
11287
+ const thisDir = dirname3(fileURLToPath2(import.meta.url));
11288
+ const fromDist = resolve7(thisDir, "..", "examples", "workflows");
11289
+ const fromSrc = resolve7(thisDir, "..", "..", "examples", "workflows");
11421
11290
  if (existsSync(fromDist))
11422
11291
  return fromDist;
11423
11292
  if (existsSync(fromSrc))
@@ -11442,8 +11311,8 @@ class InstallCommand extends Command {
11442
11311
  if (!existsSync(examplesDir)) {
11443
11312
  throw new UserInputError(`Bundled workflows directory not found: ${examplesDir}`);
11444
11313
  }
11445
- const sourceDir = resolve6(examplesDir, this.workflowName);
11446
- const destinationDir = resolve6(config.workflowsDir, this.workflowName);
11314
+ const sourceDir = resolve7(examplesDir, this.workflowName);
11315
+ const destinationDir = resolve7(config.workflowsDir, this.workflowName);
11447
11316
  if (!existsSync(sourceDir)) {
11448
11317
  const available = (await readdir2(examplesDir, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort();
11449
11318
  const hint = available.length > 0 ? ` Available: ${available.join(", ")}.` : " No bundled workflows found.";
@@ -11463,34 +11332,6 @@ class InstallCommand extends Command {
11463
11332
 
11464
11333
  // src/commands/root.ts
11465
11334
  import { basename } from "node:path";
11466
-
11467
- // src/lib/version.ts
11468
- import { readFileSync } from "node:fs";
11469
- import { dirname as dirname3, resolve as resolve7 } from "node:path";
11470
- import { fileURLToPath as fileURLToPath2 } from "node:url";
11471
- var cached;
11472
- function getVersion() {
11473
- if (cached)
11474
- return cached;
11475
- const thisDir = dirname3(fileURLToPath2(import.meta.url));
11476
- const candidates = [
11477
- resolve7(thisDir, "..", "package.json"),
11478
- resolve7(thisDir, "..", "..", "package.json")
11479
- ];
11480
- for (const candidate of candidates) {
11481
- try {
11482
- const pkg = JSON.parse(readFileSync(candidate, "utf8"));
11483
- if (pkg.version) {
11484
- cached = pkg.version;
11485
- return cached;
11486
- }
11487
- } catch {}
11488
- }
11489
- cached = "0.0.0";
11490
- return cached;
11491
- }
11492
-
11493
- // src/commands/root.ts
11494
11335
  function detectShell() {
11495
11336
  const raw = process.env.SHELL;
11496
11337
  if (!raw) {
@@ -11691,6 +11532,7 @@ class RunCommand extends Command {
11691
11532
  throw new UserInputError("No task provided. Use --task/-t or --task-file/-f.");
11692
11533
  }
11693
11534
  async execute() {
11535
+ const showUpdateNotice = startUpdateCheck();
11694
11536
  const config = await loadConfig();
11695
11537
  const { task, displayTask } = await this.resolveTask();
11696
11538
  const harnessOverride = parseHarnessOverride(this.harness);
@@ -11732,6 +11574,7 @@ class RunCommand extends Command {
11732
11574
  allowAll: effectiveAllowAll,
11733
11575
  ...Object.keys(overrides).length > 0 && { overrides }
11734
11576
  });
11577
+ showUpdateNotice();
11735
11578
  return 0;
11736
11579
  }
11737
11580
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@klaudworks/rex",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@klaudworks/rex",
9
- "version": "0.4.2",
9
+ "version": "0.4.3",
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.2",
3
+ "version": "0.4.3",
4
4
  "description": "Define multi-step coding workflows for AI agents",
5
5
  "repository": {
6
6
  "type": "git",