@workscribe/cli 1.13.0 → 1.14.0

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
@@ -148,6 +148,7 @@ workscribe summary --webhook https://custom.endpoint/hook # one-
148
148
  | `ai.model` | provider default | Model name override |
149
149
  | `ai.baseUrl` | — | Base URL for `openai-compatible` providers |
150
150
  | `session.idleTimeout` | `30` | Minutes of inactivity before a new session starts |
151
+ | `git.qualifyRepoName` | `false` | Use `owner/repo` instead of bare `repo` for `repo_name` — helpful if you work across repos whose bare names collide (e.g. an org that names its repos after the tool each one targets) |
151
152
  | `capture.ignore` | common shell builtins | Commands to exclude from capture |
152
153
  | `capture.aiTools` | `true` | Set to `false` to disable all AI session capture |
153
154
  | `capture.includeAiderPrompt` | `true` | Set to `false` to skip reading Aider's history file for prompt context |
package/dist/index.js CHANGED
@@ -436,15 +436,24 @@ function redact(command, extraPatterns = []) {
436
436
  var import_child_process = require("child_process");
437
437
  var import_path2 = __toESM(require("path"));
438
438
  var import_fs3 = __toESM(require("fs"));
439
- function nameFromRemote(root) {
439
+ function parseOwnerAndRepo(url) {
440
+ const normalized = url.trim().replace(/^[^/]+:(?!\/\/)/, (match) => match.replace(":", "/"));
441
+ const segments = normalized.split("/").filter(Boolean);
442
+ if (segments.length < 2) return null;
443
+ const repo = segments[segments.length - 1].replace(/\.git$/, "");
444
+ const owner = segments[segments.length - 2];
445
+ return owner && repo ? { owner, repo } : null;
446
+ }
447
+ function nameFromRemote(root, qualifyWithOwner) {
440
448
  try {
441
449
  const url = (0, import_child_process.execSync)("git remote get-url origin", {
442
450
  cwd: root,
443
451
  timeout: 2e3,
444
452
  stdio: "pipe"
445
453
  }).toString().trim();
446
- const match = url.match(/\/([^/]+?)(?:\.git)?$/);
447
- return match ? match[1] : null;
454
+ const parsed = parseOwnerAndRepo(url);
455
+ if (!parsed) return null;
456
+ return qualifyWithOwner ? `${parsed.owner}/${parsed.repo}` : parsed.repo;
448
457
  } catch {
449
458
  return null;
450
459
  }
@@ -459,14 +468,14 @@ function nameFromPackageJson(root) {
459
468
  return null;
460
469
  }
461
470
  }
462
- function getGitContext(cwd, nameOverride) {
471
+ function getGitContext(cwd, nameOverride, qualifyRepoName = false) {
463
472
  try {
464
473
  const root = (0, import_child_process.execSync)("git rev-parse --show-toplevel", {
465
474
  cwd,
466
475
  timeout: 2e3,
467
476
  stdio: "pipe"
468
477
  }).toString().trim();
469
- const repoName = nameOverride ?? nameFromRemote(root) ?? nameFromPackageJson(root) ?? import_path2.default.basename(root);
478
+ const repoName = nameOverride ?? nameFromRemote(root, qualifyRepoName) ?? nameFromPackageJson(root) ?? import_path2.default.basename(root);
470
479
  let branch = null;
471
480
  try {
472
481
  branch = (0, import_child_process.execSync)("git branch --show-current", {
@@ -694,6 +703,9 @@ var DEFAULTS = {
694
703
  session: {
695
704
  idleTimeout: 30
696
705
  },
706
+ git: {
707
+ qualifyRepoName: false
708
+ },
697
709
  capture: {
698
710
  ignore: ["cd", "ls", "ll", "la", "ls -la", "ls -l", "ls -a", "pwd", "clear", "exit", "history", "man"],
699
711
  aiTools: true,
@@ -1228,7 +1240,7 @@ function captureCommand(opts) {
1228
1240
  }
1229
1241
  const command2 = opts.command ?? opts.file ?? opts.type;
1230
1242
  const nameOverride2 = config.projects?.[cwd] ?? null;
1231
- const { repoName: repoName2, branch: branch2 } = getGitContext(cwd, nameOverride2);
1243
+ const { repoName: repoName2, branch: branch2 } = getGitContext(cwd, nameOverride2, config.git.qualifyRepoName);
1232
1244
  insertEvent({
1233
1245
  captured_at: (/* @__PURE__ */ new Date()).toISOString(),
1234
1246
  command: command2,
@@ -3577,7 +3589,7 @@ function registerBugReport(program2) {
3577
3589
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
3578
3590
  const reportPath = import_path16.default.join(WORKSCRIBE_DIR, `bug-report-${timestamp}.txt`);
3579
3591
  const systemInfo = [
3580
- `Workscribe version : ${"1.13.0"}`,
3592
+ `Workscribe version : ${"1.14.0"}`,
3581
3593
  `Node.js version : ${process.version}`,
3582
3594
  `Platform : ${process.platform}`,
3583
3595
  `Architecture : ${process.arch}`,
@@ -3608,7 +3620,7 @@ function registerBugReport(program2) {
3608
3620
  process.exit(1);
3609
3621
  }
3610
3622
  const params = new URLSearchParams({
3611
- title: `Bug report \u2014 workscribe ${"1.13.0"}`,
3623
+ title: `Bug report \u2014 workscribe ${"1.14.0"}`,
3612
3624
  body: `<!-- Attach ${import_path16.default.basename(reportPath)} or paste the relevant sections below -->
3613
3625
 
3614
3626
  **Describe the issue:**
@@ -3679,6 +3691,18 @@ function registerAlerts(program2) {
3679
3691
  // src/cli/context.ts
3680
3692
  var import_path17 = __toESM(require("path"));
3681
3693
  var import_chalk14 = __toESM(require("chalk"));
3694
+ function toContextJson(session) {
3695
+ return {
3696
+ date: session.date,
3697
+ startedAt: session.started_at,
3698
+ endedAt: session.ended_at,
3699
+ timeAgo: timeAgo(session.started_at),
3700
+ durationMinutes: (new Date(session.ended_at).getTime() - new Date(session.started_at).getTime()) / 6e4,
3701
+ branch: getSessionBranch(session.id),
3702
+ eventCount: session.event_count,
3703
+ summary: session.summary
3704
+ };
3705
+ }
3682
3706
  function printSessionContext(session, heading) {
3683
3707
  const ago = timeAgo(session.started_at);
3684
3708
  const branch = getSessionBranch(session.id);
@@ -3702,25 +3726,36 @@ function printSessionContext(session, heading) {
3702
3726
  log.plain("");
3703
3727
  }
3704
3728
  function registerContext(program2) {
3705
- program2.command("context").description("Show the last session for the current repo").option("--file <path>", "narrow to last session that touched this file").action((opts) => {
3729
+ program2.command("context").description("Show the last session for the current repo").option("--file <path>", "narrow to last session that touched this file").option("--json", "output as JSON instead of formatted text \u2014 null when no session is found").action((opts) => {
3706
3730
  if (opts.file) {
3707
3731
  const normalizedFile = import_path17.default.normalize(opts.file);
3708
3732
  const session = getLastSessionTouchingFile(normalizedFile);
3709
3733
  if (!session) {
3710
- log.plain(` No sessions found touching ${normalizedFile}`);
3734
+ if (opts.json) log.plain(JSON.stringify(null));
3735
+ else log.plain(` No sessions found touching ${normalizedFile}`);
3736
+ return;
3737
+ }
3738
+ if (opts.json) {
3739
+ log.plain(JSON.stringify(toContextJson(session)));
3711
3740
  return;
3712
3741
  }
3713
3742
  printSessionContext(session, `Last session touching ${import_path17.default.basename(normalizedFile)}`);
3714
3743
  return;
3715
3744
  }
3716
- const { repoName } = getGitContext(process.cwd());
3745
+ const { repoName } = getGitContext(process.cwd(), null, readConfig().git.qualifyRepoName);
3717
3746
  if (!repoName) {
3718
- log.plain(" Not in a git repository. Run workscribe context from a project directory.");
3747
+ if (opts.json) log.plain(JSON.stringify(null));
3748
+ else log.plain(" Not in a git repository. Run workscribe context from a project directory.");
3719
3749
  return;
3720
3750
  }
3721
3751
  const sessions = getRecentSessionsByRepo(repoName, 1);
3722
3752
  if (sessions.length === 0) {
3723
- log.plain(` No sessions found for ${repoName}`);
3753
+ if (opts.json) log.plain(JSON.stringify(null));
3754
+ else log.plain(` No sessions found for ${repoName}`);
3755
+ return;
3756
+ }
3757
+ if (opts.json) {
3758
+ log.plain(JSON.stringify(toContextJson(sessions[0])));
3724
3759
  return;
3725
3760
  }
3726
3761
  printSessionContext(sessions[0], `Last session on ${repoName}`);
@@ -3752,7 +3787,7 @@ function isNewer(latest, current) {
3752
3787
  return latestPatch > currentPatch;
3753
3788
  }
3754
3789
  function checkForUpdate() {
3755
- const current = "1.13.0";
3790
+ const current = "1.14.0";
3756
3791
  const cache = readCache();
3757
3792
  if (cache && isNewer(cache.latestVersion, current)) {
3758
3793
  process.stderr.write(
@@ -3777,7 +3812,7 @@ function checkForUpdate() {
3777
3812
  assertNodeVersion(process.versions.node);
3778
3813
  checkForUpdate();
3779
3814
  var program = new import_commander.Command();
3780
- program.name("workscribe").description("Automatic developer work journal").version("1.13.0");
3815
+ program.name("workscribe").description("Automatic developer work journal").version("1.14.0");
3781
3816
  registerCapture(program);
3782
3817
  registerHook(program);
3783
3818
  registerInit(program);