@mcoda/integrations 0.1.9 → 0.1.10

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.
@@ -5,6 +5,8 @@ export declare class CliQaAdapter implements QaAdapter {
5
5
  private resolveCwd;
6
6
  ensureInstalled(profile: QaProfile, ctx: QaContext): Promise<QaEnsureResult>;
7
7
  private persistLogs;
8
+ private formatCommandHeader;
9
+ private runCommand;
8
10
  invoke(profile: QaProfile, ctx: QaContext): Promise<QaRunResult>;
9
11
  }
10
12
  //# sourceMappingURL=CliQaAdapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CliQaAdapter.d.ts","sourceRoot":"","sources":["../../src/qa/CliQaAdapter.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAKtE,qBAAa,YAAa,YAAW,SAAS;IAC5C,OAAO,CAAC,UAAU;IASZ,eAAe,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,cAAc,CAAC;YAapE,WAAW;IAYnB,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;CAiDvE"}
1
+ {"version":3,"file":"CliQaAdapter.d.ts","sourceRoot":"","sources":["../../src/qa/CliQaAdapter.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAKtE,qBAAa,YAAa,YAAW,SAAS;IAC5C,OAAO,CAAC,UAAU;IASZ,eAAe,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,cAAc,CAAC;YAapE,WAAW;IAkBzB,OAAO,CAAC,mBAAmB;YAWb,UAAU;IAiDlB,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;CAoEvE"}
@@ -26,33 +26,25 @@ export class CliQaAdapter {
26
26
  return { ok: false, message: error?.message ?? 'QA install failed' };
27
27
  }
28
28
  }
29
- async persistLogs(ctx, stdout, stderr) {
29
+ async persistLogs(ctx, stdout, stderr, suffix) {
30
30
  const artifacts = [];
31
31
  if (!ctx.artifactDir)
32
32
  return artifacts;
33
33
  await fs.mkdir(ctx.artifactDir, { recursive: true });
34
- const outPath = path.join(ctx.artifactDir, 'stdout.log');
35
- const errPath = path.join(ctx.artifactDir, 'stderr.log');
34
+ const suffixLabel = suffix ? `-${suffix}` : '';
35
+ const outPath = path.join(ctx.artifactDir, `stdout${suffixLabel}.log`);
36
+ const errPath = path.join(ctx.artifactDir, `stderr${suffixLabel}.log`);
36
37
  await fs.writeFile(outPath, stdout ?? '', 'utf8');
37
38
  await fs.writeFile(errPath, stderr ?? '', 'utf8');
38
39
  artifacts.push(path.relative(ctx.workspaceRoot, outPath), path.relative(ctx.workspaceRoot, errPath));
39
40
  return artifacts;
40
41
  }
41
- async invoke(profile, ctx) {
42
- const command = ctx.testCommandOverride ?? profile.test_command;
42
+ formatCommandHeader(command, index, total, outcome, exitCode) {
43
+ const label = total > 1 ? `command ${index}/${total}` : 'command';
44
+ return `=== ${label} outcome=${outcome} exit=${exitCode ?? 'null'} cmd=${command} ===`;
45
+ }
46
+ async runCommand(command, profile, ctx, index, total) {
43
47
  const startedAt = new Date().toISOString();
44
- if (!command) {
45
- const finishedAt = new Date().toISOString();
46
- return {
47
- outcome: 'infra_issue',
48
- exitCode: null,
49
- stdout: '',
50
- stderr: 'No test_command configured for QA profile',
51
- artifacts: [],
52
- startedAt,
53
- finishedAt,
54
- };
55
- }
56
48
  const cwd = this.resolveCwd(profile, ctx);
57
49
  try {
58
50
  const { stdout, stderr } = await exec(command, {
@@ -60,15 +52,18 @@ export class CliQaAdapter {
60
52
  env: { ...process.env, ...profile.env, ...ctx.env },
61
53
  });
62
54
  const finishedAt = new Date().toISOString();
63
- const artifacts = await this.persistLogs(ctx, stdout, stderr);
55
+ const artifacts = await this.persistLogs(ctx, stdout, stderr, total > 1 ? String(index) : undefined);
64
56
  return {
65
- outcome: 'pass',
66
- exitCode: 0,
67
- stdout,
68
- stderr,
69
- artifacts,
70
- startedAt,
71
- finishedAt,
57
+ command,
58
+ result: {
59
+ outcome: 'pass',
60
+ exitCode: 0,
61
+ stdout,
62
+ stderr,
63
+ artifacts,
64
+ startedAt,
65
+ finishedAt,
66
+ },
72
67
  };
73
68
  }
74
69
  catch (error) {
@@ -76,16 +71,76 @@ export class CliQaAdapter {
76
71
  const stderr = error?.stderr ?? String(error);
77
72
  const exitCode = typeof error?.code === 'number' ? error.code : null;
78
73
  const finishedAt = new Date().toISOString();
79
- const artifacts = await this.persistLogs(ctx, stdout, stderr);
74
+ const artifacts = await this.persistLogs(ctx, stdout, stderr, total > 1 ? String(index) : undefined);
80
75
  return {
81
- outcome: exitCode === null ? 'infra_issue' : exitCode === 0 ? 'pass' : 'fail',
82
- exitCode,
83
- stdout,
84
- stderr,
85
- artifacts,
86
- startedAt,
87
- finishedAt,
76
+ command,
77
+ result: {
78
+ outcome: exitCode === null ? 'infra_issue' : exitCode === 0 ? 'pass' : 'fail',
79
+ exitCode,
80
+ stdout,
81
+ stderr,
82
+ artifacts,
83
+ startedAt,
84
+ finishedAt,
85
+ },
88
86
  };
89
87
  }
90
88
  }
89
+ async invoke(profile, ctx) {
90
+ const commandList = (ctx.commands ?? []).map((cmd) => cmd.trim()).filter(Boolean);
91
+ const fallback = ctx.testCommandOverride ?? profile.test_command;
92
+ const commands = commandList.length ? commandList : fallback ? [fallback] : [];
93
+ if (!commands.length) {
94
+ const now = new Date().toISOString();
95
+ return {
96
+ outcome: 'infra_issue',
97
+ exitCode: null,
98
+ stdout: '',
99
+ stderr: 'No test_command configured for QA profile',
100
+ artifacts: [],
101
+ startedAt: now,
102
+ finishedAt: now,
103
+ };
104
+ }
105
+ if (commands.length === 1) {
106
+ return (await this.runCommand(commands[0], profile, ctx, 1, 1)).result;
107
+ }
108
+ const runs = [];
109
+ for (let index = 0; index < commands.length; index += 1) {
110
+ runs.push(await this.runCommand(commands[index], profile, ctx, index + 1, commands.length));
111
+ }
112
+ const outcome = runs.some((run) => run.result.outcome === 'infra_issue')
113
+ ? 'infra_issue'
114
+ : runs.some((run) => run.result.outcome === 'fail')
115
+ ? 'fail'
116
+ : 'pass';
117
+ const exitCode = outcome === 'infra_issue'
118
+ ? null
119
+ : outcome === 'pass'
120
+ ? 0
121
+ : runs.find((run) => typeof run.result.exitCode === 'number' && run.result.exitCode !== 0)?.result
122
+ .exitCode ?? 1;
123
+ const stdout = runs
124
+ .map((run, index) => [this.formatCommandHeader(run.command, index + 1, runs.length, run.result.outcome, run.result.exitCode), run.result.stdout]
125
+ .filter(Boolean)
126
+ .join('\n'))
127
+ .join('\n\n');
128
+ const stderr = runs
129
+ .map((run, index) => [this.formatCommandHeader(run.command, index + 1, runs.length, run.result.outcome, run.result.exitCode), run.result.stderr]
130
+ .filter(Boolean)
131
+ .join('\n'))
132
+ .join('\n\n');
133
+ const artifacts = runs.flatMap((run) => run.result.artifacts ?? []);
134
+ const startedAt = runs.reduce((min, run) => (run.result.startedAt < min ? run.result.startedAt : min), runs[0].result.startedAt);
135
+ const finishedAt = runs.reduce((max, run) => (run.result.finishedAt > max ? run.result.finishedAt : max), runs[0].result.finishedAt);
136
+ return {
137
+ outcome,
138
+ exitCode,
139
+ stdout,
140
+ stderr,
141
+ artifacts,
142
+ startedAt,
143
+ finishedAt,
144
+ };
145
+ }
91
146
  }
@@ -1,3 +1,4 @@
1
+ import type { QaBrowserAction } from '@mcoda/shared/qa/QaPlan.js';
1
2
  export type QaOutcome = 'pass' | 'fail' | 'infra_issue';
2
3
  export interface QaRunResult {
3
4
  outcome: QaOutcome;
@@ -19,6 +20,9 @@ export interface QaContext {
19
20
  taskKey: string;
20
21
  env: NodeJS.ProcessEnv;
21
22
  testCommandOverride?: string;
23
+ commands?: string[];
24
+ browserActions?: QaBrowserAction[];
25
+ browserBaseUrl?: string;
22
26
  artifactDir?: string;
23
27
  }
24
28
  //# sourceMappingURL=QaTypes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"QaTypes.d.ts","sourceRoot":"","sources":["../../src/qa/QaTypes.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC;AAExD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,SAAS,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,SAAS;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB"}
1
+ {"version":3,"file":"QaTypes.d.ts","sourceRoot":"","sources":["../../src/qa/QaTypes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAElE,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC;AAExD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,SAAS,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,SAAS;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,cAAc,CAAC,EAAE,eAAe,EAAE,CAAC;IACnC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB"}
@@ -11,6 +11,10 @@ export interface TokenUsageSummaryRow {
11
11
  tokens_prompt: number;
12
12
  tokens_completion: number;
13
13
  tokens_total: number;
14
+ tokens_cached?: number;
15
+ tokens_cache_read?: number;
16
+ tokens_cache_write?: number;
17
+ duration_ms?: number;
14
18
  cost_estimate: number | null;
15
19
  }
16
20
  export interface TokenUsageRow {
@@ -27,11 +31,20 @@ export interface TokenUsageRow {
27
31
  tokens_prompt: number | null;
28
32
  tokens_completion: number | null;
29
33
  tokens_total: number | null;
34
+ tokens_cached?: number | null;
35
+ tokens_cache_read?: number | null;
36
+ tokens_cache_write?: number | null;
30
37
  cost_estimate: number | null;
31
38
  duration_seconds: number | null;
39
+ duration_ms?: number | null;
40
+ started_at?: string | null;
41
+ finished_at?: string | null;
32
42
  timestamp: string;
33
43
  command_name?: string | null;
34
44
  action?: string | null;
45
+ invocation_kind?: string | null;
46
+ provider?: string | null;
47
+ currency?: string | null;
35
48
  error_kind?: string | null;
36
49
  metadata?: Record<string, unknown>;
37
50
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TelemetryClient.d.ts","sourceRoot":"","sources":["../../src/telemetry/TelemetryClient.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TelemetryClient.d.ts","sourceRoot":"","sources":["../../src/telemetry/TelemetryClient.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  export declare class VcsClient {
2
2
  private runGit;
3
3
  private gitDirExists;
4
+ isRepo(cwd: string): Promise<boolean>;
4
5
  ensureRepo(cwd: string): Promise<void>;
5
6
  hasRemote(cwd: string): Promise<boolean>;
6
7
  currentBranch(cwd: string): Promise<string | null>;
@@ -10,20 +11,37 @@ export declare class VcsClient {
10
11
  ensureBaseBranch(cwd: string, base: string): Promise<void>;
11
12
  checkoutBranch(cwd: string, branch: string): Promise<void>;
12
13
  createOrCheckoutBranch(cwd: string, branch: string, base: string): Promise<void>;
14
+ addWorktree(cwd: string, worktreePath: string, branch: string, options?: {
15
+ detach?: boolean;
16
+ }): Promise<void>;
17
+ removeWorktree(cwd: string, worktreePath: string): Promise<void>;
18
+ cherryPick(cwd: string, commit: string): Promise<void>;
19
+ abortCherryPick(cwd: string): Promise<void>;
13
20
  applyPatch(cwd: string, patch: string): Promise<void>;
21
+ applyPatchWithReject(cwd: string, patch: string): Promise<{
22
+ stdout?: string;
23
+ stderr?: string;
24
+ error?: string;
25
+ }>;
14
26
  stage(cwd: string, paths: string[]): Promise<void>;
15
27
  commit(cwd: string, message: string, options?: {
16
28
  noVerify?: boolean;
17
29
  noGpgSign?: boolean;
30
+ env?: NodeJS.ProcessEnv;
18
31
  }): Promise<void>;
19
32
  merge(cwd: string, source: string, target: string, ensureClean?: boolean): Promise<void>;
20
33
  abortMerge(cwd: string): Promise<void>;
34
+ resolveMergeConflicts(cwd: string, strategy: "theirs" | "ours", paths?: string[]): Promise<string[]>;
21
35
  push(cwd: string, remote: string, branch: string): Promise<void>;
22
36
  pull(cwd: string, remote: string, branch: string, ffOnly?: boolean): Promise<void>;
23
37
  status(cwd: string): Promise<string>;
24
38
  dirtyPaths(cwd: string): Promise<string[]>;
25
39
  conflictPaths(cwd: string): Promise<string[]>;
26
40
  ensureClean(cwd: string, ignoreDotMcoda?: boolean, ignorePaths?: string[]): Promise<void>;
41
+ resetHard(cwd: string, options?: {
42
+ exclude?: string[];
43
+ }): Promise<void>;
44
+ restorePaths(cwd: string, paths: string[]): Promise<void>;
27
45
  lastCommitSha(cwd: string): Promise<string>;
28
46
  diff(cwd: string, base: string, head: string, paths?: string[]): Promise<string>;
29
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"VcsClient.d.ts","sourceRoot":"","sources":["../../src/vcs/VcsClient.ts"],"names":[],"mappings":"AAQA,qBAAa,SAAS;YACN,MAAM;YAKN,YAAY;IASpB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtC,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASxC,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IASlD,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;YASnD,UAAU;YASV,gBAAgB;IAaxB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY1D,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1D,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQhF,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAyBrD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlD,MAAM,CACV,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAO,GACxD,OAAO,CAAC,IAAI,CAAC;IAOV,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAQtF,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQtC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhE,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAO/E,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKpC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAsB1C,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAS7C,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,UAAO,EAAE,WAAW,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAW1F,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAK3C,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;CAQvF"}
1
+ {"version":3,"file":"VcsClient.d.ts","sourceRoot":"","sources":["../../src/vcs/VcsClient.ts"],"names":[],"mappings":"AAQA,qBAAa,SAAS;YACN,MAAM;YAYN,YAAY;IASpB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASrC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtC,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASxC,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IASlD,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;YASnD,UAAU;YASV,gBAAgB;IAaxB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY1D,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1D,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQhF,WAAW,CACf,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAC7B,OAAO,CAAC,IAAI,CAAC;IASV,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQhE,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAItD,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAyBrD,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAiB/G,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlD,MAAM,CACV,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;KAAO,GACjF,OAAO,CAAC,IAAI,CAAC;IAQV,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAQtF,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQtC,qBAAqB,CACzB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,QAAQ,GAAG,MAAM,EAC3B,KAAK,CAAC,EAAE,MAAM,EAAE,GACf,OAAO,CAAC,MAAM,EAAE,CAAC;IAUd,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhE,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAO/E,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKpC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAsB1C,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAS7C,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,UAAO,EAAE,WAAW,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAyB1F,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAYvE,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAOzD,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAK3C,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;CAQvF"}
@@ -5,9 +5,12 @@ import path from "node:path";
5
5
  const exec = promisify(execCb);
6
6
  const execFile = promisify(execFileCb);
7
7
  export class VcsClient {
8
- async runGit(cwd, args) {
9
- const { stdout, stderr } = await execFile("git", args, { cwd });
10
- return { stdout, stderr };
8
+ async runGit(cwd, args, options = {}) {
9
+ const { stdout, stderr } = await execFile("git", args, { cwd, ...options });
10
+ return {
11
+ stdout: typeof stdout === "string" ? stdout : stdout?.toString?.() ?? "",
12
+ stderr: typeof stderr === "string" ? stderr : stderr?.toString?.() ?? "",
13
+ };
11
14
  }
12
15
  async gitDirExists(cwd) {
13
16
  try {
@@ -18,6 +21,15 @@ export class VcsClient {
18
21
  return false;
19
22
  }
20
23
  }
24
+ async isRepo(cwd) {
25
+ try {
26
+ await this.runGit(cwd, ["rev-parse", "--is-inside-work-tree"]);
27
+ return true;
28
+ }
29
+ catch {
30
+ return this.gitDirExists(cwd);
31
+ }
32
+ }
21
33
  async ensureRepo(cwd) {
22
34
  if (await this.gitDirExists(cwd))
23
35
  return;
@@ -95,6 +107,28 @@ export class VcsClient {
95
107
  }
96
108
  await this.runGit(cwd, ["checkout", "-b", branch, base]);
97
109
  }
110
+ async addWorktree(cwd, worktreePath, branch, options) {
111
+ const args = ["worktree", "add", "--force"];
112
+ if (options?.detach) {
113
+ args.push("--detach");
114
+ }
115
+ args.push(worktreePath, branch);
116
+ await this.runGit(cwd, args);
117
+ }
118
+ async removeWorktree(cwd, worktreePath) {
119
+ try {
120
+ await this.runGit(cwd, ["worktree", "remove", "--force", worktreePath]);
121
+ }
122
+ catch {
123
+ // ignore; cleanup caller will remove directory
124
+ }
125
+ }
126
+ async cherryPick(cwd, commit) {
127
+ await this.runGit(cwd, ["cherry-pick", commit]);
128
+ }
129
+ async abortCherryPick(cwd) {
130
+ await this.runGit(cwd, ["cherry-pick", "--abort"]);
131
+ }
98
132
  async applyPatch(cwd, patch) {
99
133
  const opts = { cwd, shell: true };
100
134
  const applyCmd = `cat <<'__PATCH__' | git apply --whitespace=nowarn\n${patch}\n__PATCH__`;
@@ -122,6 +156,23 @@ export class VcsClient {
122
156
  }
123
157
  }
124
158
  }
159
+ async applyPatchWithReject(cwd, patch) {
160
+ const opts = { cwd, shell: true };
161
+ const applyCmd = `cat <<'__PATCH__' | git apply --reject --whitespace=nowarn\n${patch}\n__PATCH__`;
162
+ try {
163
+ const { stdout, stderr } = await exec(applyCmd, opts);
164
+ return {
165
+ stdout: typeof stdout === "string" ? stdout : stdout?.toString?.() ?? "",
166
+ stderr: typeof stderr === "string" ? stderr : stderr?.toString?.() ?? "",
167
+ };
168
+ }
169
+ catch (error) {
170
+ const stdout = typeof error?.stdout === "string" ? error.stdout : error?.stdout?.toString?.() ?? "";
171
+ const stderr = typeof error?.stderr === "string" ? error.stderr : error?.stderr?.toString?.() ?? "";
172
+ const message = error instanceof Error ? error.message : String(error);
173
+ return { stdout, stderr, error: stderr || message };
174
+ }
175
+ }
125
176
  async stage(cwd, paths) {
126
177
  await this.runGit(cwd, ["add", ...paths]);
127
178
  }
@@ -131,7 +182,8 @@ export class VcsClient {
131
182
  args.push("--no-verify");
132
183
  if (options.noGpgSign)
133
184
  args.push("--no-gpg-sign");
134
- await this.runGit(cwd, args);
185
+ const execOptions = options.env ? { env: options.env } : {};
186
+ await this.runGit(cwd, args, execOptions);
135
187
  }
136
188
  async merge(cwd, source, target, ensureClean = false) {
137
189
  await this.checkoutBranch(cwd, target);
@@ -148,6 +200,16 @@ export class VcsClient {
148
200
  // Ignore when no merge is in progress.
149
201
  }
150
202
  }
203
+ async resolveMergeConflicts(cwd, strategy, paths) {
204
+ const conflicts = paths?.length ? paths : await this.conflictPaths(cwd);
205
+ if (!conflicts.length)
206
+ return [];
207
+ const flag = strategy === "theirs" ? "--theirs" : "--ours";
208
+ await this.runGit(cwd, ["checkout", flag, "--", ...conflicts]);
209
+ await this.runGit(cwd, ["add", "--", ...conflicts]);
210
+ await this.runGit(cwd, ["commit", "--no-edit"]);
211
+ return conflicts;
212
+ }
151
213
  async push(cwd, remote, branch) {
152
214
  await this.runGit(cwd, ["push", remote, branch]);
153
215
  }
@@ -197,15 +259,46 @@ export class VcsClient {
197
259
  }
198
260
  async ensureClean(cwd, ignoreDotMcoda = true, ignorePaths = []) {
199
261
  const dirty = await this.dirtyPaths(cwd);
200
- const filtered = dirty.filter((p) => {
201
- if (ignoreDotMcoda && p.startsWith(".mcoda"))
202
- return false;
203
- return !ignorePaths.some((prefix) => p.startsWith(prefix));
204
- });
262
+ const normalize = (value) => value.replace(/\\/g, "/").replace(/^\.\/+/, "").replace(/^\/+/, "");
263
+ const normalizedIgnore = ignorePaths
264
+ .map((entry) => normalize(entry.trim()))
265
+ .filter(Boolean)
266
+ .map((entry) => (entry.endsWith("/") ? `${entry.replace(/\/+$/, "")}/` : entry));
267
+ const isIgnored = (value) => {
268
+ const normalized = normalize(value);
269
+ if (ignoreDotMcoda && normalized.startsWith(".mcoda"))
270
+ return true;
271
+ return normalizedIgnore.some((entry) => {
272
+ if (entry.endsWith("/")) {
273
+ const dir = entry.slice(0, -1);
274
+ return normalized === dir || normalized.startsWith(entry);
275
+ }
276
+ return normalized === entry || normalized.startsWith(`${entry}/`);
277
+ });
278
+ };
279
+ const filtered = dirty.filter((p) => !isIgnored(p));
205
280
  if (filtered.length) {
206
281
  throw new Error(`Working tree dirty: ${filtered.join(", ")}`);
207
282
  }
208
283
  }
284
+ async resetHard(cwd, options) {
285
+ await this.runGit(cwd, ["reset", "--hard"]);
286
+ const args = ["clean", "-fd"];
287
+ (options?.exclude ?? [])
288
+ .map((entry) => entry.trim())
289
+ .filter(Boolean)
290
+ .forEach((entry) => {
291
+ args.push("-e", entry);
292
+ });
293
+ await this.runGit(cwd, args);
294
+ }
295
+ async restorePaths(cwd, paths) {
296
+ const cleaned = paths.map((entry) => entry.trim()).filter(Boolean);
297
+ if (!cleaned.length)
298
+ return;
299
+ await this.runGit(cwd, ["checkout", "--", ...cleaned]);
300
+ await this.runGit(cwd, ["clean", "-fd", "--", ...cleaned]);
301
+ }
209
302
  async lastCommitSha(cwd) {
210
303
  const { stdout } = await this.runGit(cwd, ["rev-parse", "HEAD"]);
211
304
  return stdout.trim();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcoda/integrations",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "External integrations for mcoda (vcs, QA, telemetry).",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -38,7 +38,7 @@
38
38
  },
39
39
  "dependencies": {
40
40
  "docdex": "^0.2.22",
41
- "@mcoda/shared": "0.1.9"
41
+ "@mcoda/shared": "0.1.10"
42
42
  },
43
43
  "scripts": {
44
44
  "build": "tsc -p tsconfig.json",