@doist/doistbot-cli 1.0.1 → 1.0.2

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.
@@ -0,0 +1,20 @@
1
+ const REVIEW_USAGE_COMMANDS = ['doistbot review [staged]', 'db review [staged]'];
2
+ const REVIEW_SETUP_COMMANDS = [
3
+ 'doistbot review',
4
+ 'doistbot review staged',
5
+ 'db review',
6
+ 'db review staged',
7
+ ];
8
+ export function formatReviewUsage() {
9
+ return `Usage: ${formatCommandList(REVIEW_USAGE_COMMANDS)}`;
10
+ }
11
+ export function formatSetupCompleteMessage() {
12
+ return `Setup complete. Run ${formatCommandList(REVIEW_SETUP_COMMANDS)} from a git repository.`;
13
+ }
14
+ function formatCommandList(commands) {
15
+ const quotedCommands = commands.map((command) => `\`${command}\``);
16
+ if (quotedCommands.length <= 2) {
17
+ return quotedCommands.join(' or ');
18
+ }
19
+ return `${quotedCommands.slice(0, -1).join(', ')}, or ${quotedCommands.at(-1)}`;
20
+ }
@@ -1,6 +1,7 @@
1
1
  import { getApiKeys } from '../config.js';
2
2
  import { getRepositoryRoot, loadSandboxFormatModule, loadSandboxReviewModule } from '../runtime.js';
3
3
  import { formatReviewProgress, renderAlert, renderMarkdown, withSpinner, writeLine, } from '../terminal.js';
4
+ import { formatReviewUsage } from './review-usage.js';
4
5
  const LOCAL_REVIEW_SOURCE_STAGED = 'staged';
5
6
  const PROVIDER_DISPLAY_NAMES = {
6
7
  gemini: 'Gemini',
@@ -88,7 +89,7 @@ function formatReviewOutput({ formatReviewForTerminal, review, }) {
88
89
  }
89
90
  export async function runReview(sourceArg) {
90
91
  if (sourceArg !== undefined && sourceArg !== LOCAL_REVIEW_SOURCE_STAGED) {
91
- throw new Error('Usage: doistbot review [staged]');
92
+ throw new Error(formatReviewUsage());
92
93
  }
93
94
  const source = sourceArg === LOCAL_REVIEW_SOURCE_STAGED ? LOCAL_REVIEW_SOURCE_STAGED : 'base';
94
95
  const reviewModule = await loadSandboxReviewModule();
@@ -1,6 +1,7 @@
1
1
  import { checkGit, checkPiDependency, checkSandboxBuild } from '../runtime.js';
2
2
  import { renderDiagnosticCheck, writeLine } from '../terminal.js';
3
3
  import { runAuthSetup } from './auth.js';
4
+ import { formatSetupCompleteMessage } from './review-usage.js';
4
5
  export async function runSetup() {
5
6
  writeLine('Checking DoistBot CLI prerequisites...');
6
7
  await renderDiagnosticCheck('git', checkGit);
@@ -9,5 +10,5 @@ export async function runSetup() {
9
10
  writeLine();
10
11
  await runAuthSetup();
11
12
  writeLine();
12
- writeLine('Setup complete. Run `doistbot review` or `doistbot review staged` from a git repository.');
13
+ writeLine(formatSetupCompleteMessage());
13
14
  }
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@doist/doistbot-cli",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Local self-review CLI for DoistBot",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "bin": {
8
+ "db": "dist/index.js",
8
9
  "doistbot": "dist/index.js"
9
10
  },
10
11
  "keywords": [
@@ -41,8 +42,8 @@
41
42
  "dependencies": {
42
43
  "@inquirer/checkbox": "5.1.5",
43
44
  "@inquirer/password": "5.0.13",
44
- "@mariozechner/pi-ai": "0.73.0",
45
- "@mariozechner/pi-coding-agent": "0.73.0",
45
+ "@mariozechner/pi-ai": "0.73.1",
46
+ "@mariozechner/pi-coding-agent": "0.73.1",
46
47
  "@napi-rs/keyring": "1.3.0",
47
48
  "ajv": "8.20.0",
48
49
  "chalk": "4.1.2",
@@ -52,6 +53,6 @@
52
53
  "yocto-spinner": "1.2.0"
53
54
  },
54
55
  "devDependencies": {
55
- "vitest": "4.1.5"
56
+ "vitest": "4.1.6"
56
57
  }
57
58
  }
@@ -161,13 +161,7 @@ async function main() {
161
161
  octokit: writeOctokit,
162
162
  triageOutput,
163
163
  fixAssessment,
164
- clonedRepos: clonedRepositories.map(({ repository, localPath }) => ({
165
- owner: repository.owner,
166
- repo: repository.repo,
167
- fullName: repository.fullName,
168
- localPath,
169
- repository,
170
- })),
164
+ clonedRepos: clonedRepositories,
171
165
  issueTitle: issue.title ?? 'Untitled issue',
172
166
  issueUrl: issue.html_url ?? getIssueUrl(ctx.owner, ctx.repo, ctx.issueNumber),
173
167
  ghToken: issueInstallationAuth.token,
@@ -80,7 +80,7 @@ export function parsePRBodyFromOutput(output) {
80
80
  function buildFixPrompt({ ctx, triageOutput, fixAssessment, issueTitle, issueUrl, targetRepo, prTemplate, }) {
81
81
  const template = loadFixPromptTemplate();
82
82
  return fillPromptTemplate(template, {
83
- REPO_FULL: targetRepo.fullName,
83
+ REPO_FULL: targetRepo.repository.fullName,
84
84
  ISSUE_NUMBER: String(ctx.issueNumber),
85
85
  ISSUE_TITLE: issueTitle,
86
86
  ISSUE_URL: issueUrl,
@@ -213,7 +213,7 @@ export async function runFixCore(input) {
213
213
  logger.warn('Failed to reset repo state before fix attempt', {
214
214
  task: 'issue-triage',
215
215
  issueNumber: ctx.issueNumber,
216
- targetRepo: targetRepo.fullName,
216
+ targetRepo: targetRepo.repository.fullName,
217
217
  error: reason,
218
218
  });
219
219
  return {
@@ -226,7 +226,7 @@ export async function runFixCore(input) {
226
226
  logger.info('PR template found for fix attempt', {
227
227
  task: 'issue-triage',
228
228
  issueNumber: ctx.issueNumber,
229
- targetRepo: targetRepo.fullName,
229
+ targetRepo: targetRepo.repository.fullName,
230
230
  templateChars: prTemplate.length,
231
231
  });
232
232
  }
@@ -328,7 +328,9 @@ export async function attemptFix(input) {
328
328
  const { ctx, octokit, triageOutput, fixAssessment, clonedRepos, force } = input;
329
329
  const startedAt = Date.now();
330
330
  const fallbackRepository = fixAssessment.targetRepo ??
331
- (clonedRepos.length === 1 ? clonedRepos[0].fullName : `${ctx.owner}/${ctx.repo}`);
331
+ (clonedRepos.length === 1
332
+ ? clonedRepos[0].repository.fullName
333
+ : `${ctx.owner}/${ctx.repo}`);
332
334
  if (!force && !shouldAttemptFix(fixAssessment)) {
333
335
  logger.info('Fix attempt skipped — assessment does not qualify', {
334
336
  task: 'issue-triage',
@@ -350,7 +352,7 @@ export async function attemptFix(input) {
350
352
  };
351
353
  }
352
354
  const matched = fixAssessment.targetRepo
353
- ? clonedRepos.find((r) => r.fullName === fixAssessment.targetRepo)
355
+ ? clonedRepos.find((r) => r.repository.fullName === fixAssessment.targetRepo)
354
356
  : clonedRepos.length === 1
355
357
  ? clonedRepos[0]
356
358
  : undefined;
@@ -365,7 +367,7 @@ export async function attemptFix(input) {
365
367
  logger.info('Fix attempt starting', {
366
368
  task: 'issue-triage',
367
369
  issueNumber: ctx.issueNumber,
368
- targetRepo: targetRepo.fullName,
370
+ targetRepo: targetRepo.repository.fullName,
369
371
  trigger: ctx.triggerType,
370
372
  });
371
373
  const coreResult = await runFixCore({
@@ -380,7 +382,7 @@ export async function attemptFix(input) {
380
382
  if (!coreResult.ok) {
381
383
  return {
382
384
  attempted: true,
383
- repository: targetRepo.fullName,
385
+ repository: targetRepo.repository.fullName,
384
386
  prCreated: false,
385
387
  reason: coreResult.reason,
386
388
  };
@@ -389,20 +391,20 @@ export async function attemptFix(input) {
389
391
  logger.info('Fix attempt dry run — would create PR', {
390
392
  task: 'issue-triage',
391
393
  issueNumber: ctx.issueNumber,
392
- targetRepo: targetRepo.fullName,
394
+ targetRepo: targetRepo.repository.fullName,
393
395
  diffLines: coreResult.diff.split('\n').length,
394
396
  });
395
397
  return {
396
398
  attempted: true,
397
- repository: targetRepo.fullName,
399
+ repository: targetRepo.repository.fullName,
398
400
  prCreated: false,
399
401
  reason: 'Dry run — PR not created.',
400
402
  };
401
403
  }
402
404
  try {
403
405
  const { branch } = await commitAndPushFix({
404
- repoOwner: targetRepo.owner,
405
- repoName: targetRepo.repo,
406
+ repoOwner: targetRepo.repository.owner,
407
+ repoName: targetRepo.repository.repo,
406
408
  repoLocalPath: targetRepo.localPath,
407
409
  githubToken: ctx.githubToken,
408
410
  issueNumber: ctx.issueNumber,
@@ -410,8 +412,8 @@ export async function attemptFix(input) {
410
412
  prTitle: coreResult.generatedPRTitle ?? undefined,
411
413
  });
412
414
  const prResult = await openDraftFixPR({
413
- repoOwner: targetRepo.owner,
414
- repoName: targetRepo.repo,
415
+ repoOwner: targetRepo.repository.owner,
416
+ repoName: targetRepo.repository.repo,
415
417
  octokit,
416
418
  issueNumber: ctx.issueNumber,
417
419
  issueTitle: input.issueTitle,
@@ -441,7 +443,7 @@ export async function attemptFix(input) {
441
443
  });
442
444
  return {
443
445
  attempted: true,
444
- repository: targetRepo.fullName,
446
+ repository: targetRepo.repository.fullName,
445
447
  prCreated: true,
446
448
  prUrl: prResult.prUrl,
447
449
  prNumber: prResult.prNumber,
@@ -456,7 +458,7 @@ export async function attemptFix(input) {
456
458
  });
457
459
  return {
458
460
  attempted: true,
459
- repository: targetRepo.fullName,
461
+ repository: targetRepo.repository.fullName,
460
462
  prCreated: false,
461
463
  reason: `PR creation failed: ${error instanceof Error ? error.message : String(error)}`,
462
464
  };
@@ -441,13 +441,7 @@ async function runIssueTriagePipeline(ctx, mode) {
441
441
  octokit: writeOctokit,
442
442
  triageOutput: normalized.output,
443
443
  fixAssessment,
444
- clonedRepos: clonedRepositories.map(({ repository, localPath }) => ({
445
- owner: repository.owner,
446
- repo: repository.repo,
447
- fullName: repository.fullName,
448
- localPath,
449
- repository,
450
- })),
444
+ clonedRepos: clonedRepositories,
451
445
  issueTitle: issue.title ?? 'Untitled issue',
452
446
  issueUrl: issue.html_url ?? getIssueUrl(ctx.owner, ctx.repo, ctx.issueNumber),
453
447
  ghToken: issueInstallationAuth.token,