@idea1/cli 1.5.1 → 1.6.1
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 +124 -93
- package/dist/commands/approve-pr.d.ts.map +1 -1
- package/dist/commands/approve-pr.js +7 -163
- package/dist/commands/approve-pr.js.map +1 -1
- package/dist/commands/attach-project-item.d.ts.map +1 -1
- package/dist/commands/attach-project-item.js +38 -89
- package/dist/commands/attach-project-item.js.map +1 -1
- package/dist/commands/close-worktree.d.ts.map +1 -1
- package/dist/commands/close-worktree.js +3 -2
- package/dist/commands/close-worktree.js.map +1 -1
- package/dist/commands/help.d.ts.map +1 -1
- package/dist/commands/help.js +17 -14
- package/dist/commands/help.js.map +1 -1
- package/dist/commands/index.d.ts +3 -2
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +5 -3
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/join-project-item.d.ts.map +1 -1
- package/dist/commands/join-project-item.js +38 -77
- package/dist/commands/join-project-item.js.map +1 -1
- package/dist/commands/next-workflow-step.d.ts.map +1 -1
- package/dist/commands/next-workflow-step.js +66 -51
- package/dist/commands/next-workflow-step.js.map +1 -1
- package/dist/commands/ready-for-approval.d.ts.map +1 -1
- package/dist/commands/ready-for-approval.js +7 -66
- package/dist/commands/ready-for-approval.js.map +1 -1
- package/dist/commands/start-agent-implementation.d.ts +3 -0
- package/dist/commands/start-agent-implementation.d.ts.map +1 -0
- package/dist/commands/start-agent-implementation.js +41 -0
- package/dist/commands/start-agent-implementation.js.map +1 -0
- package/dist/commands/start-dev-implementation.d.ts.map +1 -1
- package/dist/commands/start-dev-implementation.js +8 -54
- package/dist/commands/start-dev-implementation.js.map +1 -1
- package/dist/commands/start.d.ts +13 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +81 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/interactive.d.ts.map +1 -1
- package/dist/interactive.js +29 -9
- package/dist/interactive.js.map +1 -1
- package/dist/lib/claude-options.d.ts +33 -0
- package/dist/lib/claude-options.d.ts.map +1 -0
- package/dist/lib/claude-options.js +83 -0
- package/dist/lib/claude-options.js.map +1 -0
- package/dist/lib/settings.d.ts.map +1 -1
- package/dist/lib/settings.js +5 -5
- package/dist/lib/settings.js.map +1 -1
- package/dist/lib/workflow-states.d.ts +21 -3
- package/dist/lib/workflow-states.d.ts.map +1 -1
- package/dist/lib/workflow-states.generated.d.ts +21 -0
- package/dist/lib/workflow-states.generated.d.ts.map +1 -0
- package/dist/lib/workflow-states.generated.js +34 -0
- package/dist/lib/workflow-states.generated.js.map +1 -0
- package/dist/lib/workflow-states.js +47 -26
- package/dist/lib/workflow-states.js.map +1 -1
- package/dist/services/branch-setup.d.ts +42 -0
- package/dist/services/branch-setup.d.ts.map +1 -0
- package/dist/services/branch-setup.js +116 -0
- package/dist/services/branch-setup.js.map +1 -0
- package/dist/services/claude.d.ts +14 -4
- package/dist/services/claude.d.ts.map +1 -1
- package/dist/services/claude.js +39 -4
- package/dist/services/claude.js.map +1 -1
- package/dist/services/git.d.ts +66 -0
- package/dist/services/git.d.ts.map +1 -1
- package/dist/services/git.js +161 -6
- package/dist/services/git.js.map +1 -1
- package/dist/services/workflow-engine.d.ts +67 -0
- package/dist/services/workflow-engine.d.ts.map +1 -0
- package/dist/services/workflow-engine.js +371 -0
- package/dist/services/workflow-engine.js.map +1 -0
- package/dist/services/workflow-handlers/agent-implementation.d.ts +9 -0
- package/dist/services/workflow-handlers/agent-implementation.d.ts.map +1 -0
- package/dist/services/workflow-handlers/agent-implementation.js +37 -0
- package/dist/services/workflow-handlers/agent-implementation.js.map +1 -0
- package/dist/services/workflow-handlers/approve-pr.d.ts +8 -0
- package/dist/services/workflow-handlers/approve-pr.d.ts.map +1 -0
- package/dist/services/workflow-handlers/approve-pr.js +161 -0
- package/dist/services/workflow-handlers/approve-pr.js.map +1 -0
- package/dist/services/workflow-handlers/dev-implementation.d.ts +8 -0
- package/dist/services/workflow-handlers/dev-implementation.d.ts.map +1 -0
- package/dist/services/workflow-handlers/dev-implementation.js +34 -0
- package/dist/services/workflow-handlers/dev-implementation.js.map +1 -0
- package/dist/services/workflow-handlers/index.d.ts +18 -0
- package/dist/services/workflow-handlers/index.d.ts.map +1 -0
- package/dist/services/workflow-handlers/index.js +36 -0
- package/dist/services/workflow-handlers/index.js.map +1 -0
- package/dist/services/workflow-handlers/ready-for-approval.d.ts +8 -0
- package/dist/services/workflow-handlers/ready-for-approval.d.ts.map +1 -0
- package/dist/services/workflow-handlers/ready-for-approval.js +60 -0
- package/dist/services/workflow-handlers/ready-for-approval.js.map +1 -0
- package/dist/services/workflow.d.ts +1 -21
- package/dist/services/workflow.d.ts.map +1 -1
- package/dist/services/workflow.js +1 -67
- package/dist/services/workflow.js.map +1 -1
- package/dist/services/worktree.d.ts +29 -27
- package/dist/services/worktree.d.ts.map +1 -1
- package/dist/services/worktree.js +51 -77
- package/dist/services/worktree.js.map +1 -1
- package/dist/types/index.d.ts +41 -4
- package/dist/types/index.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
- package/dist/commands/start-project-item.d.ts +0 -27
- package/dist/commands/start-project-item.d.ts.map +0 -1
- package/dist/commands/start-project-item.js +0 -325
- package/dist/commands/start-project-item.js.map +0 -1
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { logger } from '../lib/logger.js';
|
|
2
|
+
import { promptInput, promptSelect } from '../lib/prompt.js';
|
|
3
|
+
import { configService } from './config.js';
|
|
4
|
+
import * as git from './git.js';
|
|
5
|
+
import * as worktree from './worktree.js';
|
|
6
|
+
export const WORKFLOW_CHOICES = [
|
|
7
|
+
{ label: 'Independent Feature', value: 'independent' },
|
|
8
|
+
{ label: 'Work for Integration', value: 'integration' }
|
|
9
|
+
];
|
|
10
|
+
const STACK_CHOICES = [
|
|
11
|
+
{ label: 'No', value: 'no' },
|
|
12
|
+
{ label: 'Yes - specify a branch', value: 'branch' },
|
|
13
|
+
{ label: 'Yes - specify a project item URL', value: 'url' }
|
|
14
|
+
];
|
|
15
|
+
const INTEGRATION_BRANCH_CHOICES = [
|
|
16
|
+
{ label: 'Create new integration branch', value: 'new' },
|
|
17
|
+
{ label: 'Use existing integration branch', value: 'existing' }
|
|
18
|
+
];
|
|
19
|
+
/**
|
|
20
|
+
* The options every command that can create an item's branch shares: which
|
|
21
|
+
* branch to base it on and which branching workflow to use.
|
|
22
|
+
*/
|
|
23
|
+
export const branchCreationOptions = [
|
|
24
|
+
{
|
|
25
|
+
longName: 'branch-name',
|
|
26
|
+
shortName: 'n',
|
|
27
|
+
description: 'Branch name (auto-generated if not provided)',
|
|
28
|
+
defaultValue: undefined,
|
|
29
|
+
promptWhenDefaultExists: true
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
longName: 'base-branch',
|
|
33
|
+
shortName: 'b',
|
|
34
|
+
description: 'Base branch',
|
|
35
|
+
defaultValue: () => configService.getDefaultBaseBranch(),
|
|
36
|
+
promptWhenDefaultExists: false
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
longName: 'workflow-type',
|
|
40
|
+
shortName: 'w',
|
|
41
|
+
description: 'Development workflow type',
|
|
42
|
+
defaultValue: undefined,
|
|
43
|
+
choices: WORKFLOW_CHOICES
|
|
44
|
+
}
|
|
45
|
+
];
|
|
46
|
+
/**
|
|
47
|
+
* Collect every branching decision up front (stack branch, integration branch)
|
|
48
|
+
* so all user questions are asked before any slow git or MCP work starts.
|
|
49
|
+
*/
|
|
50
|
+
export async function collectBranchCreationChoices(resolved) {
|
|
51
|
+
const workflowType = (resolved['workflow-type'] || 'independent');
|
|
52
|
+
const stackBranch = await promptForStackBranch();
|
|
53
|
+
const integrationSelection = workflowType === 'integration' ? await promptForIntegrationBranch() : null;
|
|
54
|
+
return {
|
|
55
|
+
shortBranchName: resolved['branch-name'] || null,
|
|
56
|
+
baseBranch: resolved['base-branch'] || await worktree.resolveBaseBranch(),
|
|
57
|
+
workflowType,
|
|
58
|
+
stackBranch,
|
|
59
|
+
integrationSelection
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Prompt the user whether to stack this branch on another and resolve the
|
|
64
|
+
* chosen stack branch. Prompt-only: performs no branch writes. Returns the
|
|
65
|
+
* resolved stack branch name, or null when the user opts not to stack.
|
|
66
|
+
*/
|
|
67
|
+
export async function promptForStackBranch() {
|
|
68
|
+
const stackChoice = await promptSelect('Stack this branch on another?', STACK_CHOICES);
|
|
69
|
+
if (stackChoice === 'branch') {
|
|
70
|
+
const stackBranch = await promptInput('Branch to stack on');
|
|
71
|
+
if (!stackBranch) {
|
|
72
|
+
throw new Error('Stack branch is required when stacking');
|
|
73
|
+
}
|
|
74
|
+
const stackExists = await git.branchExists(stackBranch);
|
|
75
|
+
if (!stackExists) {
|
|
76
|
+
throw new Error(`Stack branch '${stackBranch}' does not exist locally or on origin`);
|
|
77
|
+
}
|
|
78
|
+
return stackBranch;
|
|
79
|
+
}
|
|
80
|
+
if (stackChoice === 'url') {
|
|
81
|
+
const stackUrl = await promptInput('Project item URL to stack on');
|
|
82
|
+
if (!stackUrl) {
|
|
83
|
+
throw new Error('Project item URL is required when stacking by URL');
|
|
84
|
+
}
|
|
85
|
+
const stackBranch = await git.resolveBranchFromProjectItemUrl(stackUrl);
|
|
86
|
+
if (!stackBranch) {
|
|
87
|
+
throw new Error(`No branch found for project item URL: ${stackUrl}. Make sure the project item has been started.`);
|
|
88
|
+
}
|
|
89
|
+
logger.info(`Resolved stack branch: ${stackBranch}`);
|
|
90
|
+
return stackBranch;
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Prompt the user for integration-branch selection. Prompt-only: does not
|
|
96
|
+
* perform any branch writes.
|
|
97
|
+
*/
|
|
98
|
+
export async function promptForIntegrationBranch() {
|
|
99
|
+
const existingBranches = await worktree.listExistingIntegrationBranches();
|
|
100
|
+
const branchChoice = existingBranches.length > 0
|
|
101
|
+
? await promptSelect('Integration branch', INTEGRATION_BRANCH_CHOICES)
|
|
102
|
+
: 'new';
|
|
103
|
+
if (branchChoice === 'existing') {
|
|
104
|
+
const branchChoices = existingBranches.map(b => ({ label: b, value: b }));
|
|
105
|
+
const integrationBranchName = await promptSelect('Select integration branch', branchChoices);
|
|
106
|
+
const integrationName = await worktree.extractIntegrationName(integrationBranchName);
|
|
107
|
+
return { integrationName, integrationBranchName, isNew: false };
|
|
108
|
+
}
|
|
109
|
+
const integrationName = await promptInput('Integration name (e.g., my-cool-feature)');
|
|
110
|
+
if (!integrationName) {
|
|
111
|
+
throw new Error('Integration name is required');
|
|
112
|
+
}
|
|
113
|
+
const integrationBranchName = await worktree.buildIntegrationBranchName(integrationName);
|
|
114
|
+
return { integrationName, integrationBranchName, isNew: true };
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=branch-setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch-setup.js","sourceRoot":"","sources":["../../src/services/branch-setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ClaudeEffortLevel, ClaudeModel } from '../types/index.js';
|
|
1
2
|
/**
|
|
2
3
|
* Ensure Claude CLI is available
|
|
3
4
|
*/
|
|
@@ -6,8 +7,10 @@ export declare function ensureClaudeCli(): Promise<boolean>;
|
|
|
6
7
|
* Options shared by non-interactive claude runs.
|
|
7
8
|
*/
|
|
8
9
|
export interface ClaudeRunOptions {
|
|
10
|
+
/** Model alias passed to claude via --model. */
|
|
11
|
+
model?: ClaudeModel;
|
|
9
12
|
/** Effort level passed to claude via --effort. */
|
|
10
|
-
effort?:
|
|
13
|
+
effort?: ClaudeEffortLevel;
|
|
11
14
|
}
|
|
12
15
|
/**
|
|
13
16
|
* Run claude with a specific prompt (non-interactive, returns output).
|
|
@@ -18,11 +21,18 @@ export declare function runWithPrompt(prompt: string, options?: ClaudeRunOptions
|
|
|
18
21
|
/**
|
|
19
22
|
* Launch interactive claude session
|
|
20
23
|
*/
|
|
21
|
-
export declare function runInteractive(initialPrompt?: string, cwd?: string, permissionMode?: string, effort?: string): Promise<number>;
|
|
24
|
+
export declare function runInteractive(initialPrompt?: string, cwd?: string, permissionMode?: string, model?: string, effort?: string): Promise<number>;
|
|
22
25
|
/**
|
|
23
|
-
* Set workflow status on an idea1.ai project item
|
|
26
|
+
* Set workflow status on an idea1.ai project item. When the item's branch is
|
|
27
|
+
* known it is recorded on the item too, so the web client can find the branch
|
|
28
|
+
* without scanning the repository.
|
|
24
29
|
*/
|
|
25
|
-
export declare function setWorkflowStatus(itemUrl: string, status: string): Promise<boolean>;
|
|
30
|
+
export declare function setWorkflowStatus(itemUrl: string, status: string, branchName?: string): Promise<boolean>;
|
|
31
|
+
/**
|
|
32
|
+
* Read the current workflow status of an idea1.ai project item. Returns null
|
|
33
|
+
* when the item has no status yet.
|
|
34
|
+
*/
|
|
35
|
+
export declare function getWorkflowStatus(itemUrl: string): Promise<string | null>;
|
|
26
36
|
/**
|
|
27
37
|
* Generate a branch name from a project item description
|
|
28
38
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/services/claude.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/services/claude.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAcxE;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAMxD;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,gDAAgD;IAChD,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,kDAAkD;IAClD,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC5B;AAwDD;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAS/F;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,aAAa,CAAC,EAAE,MAAM,EACtB,GAAG,CAAC,EAAE,MAAM,EACZ,cAAc,CAAC,EAAE,MAAM,EACvB,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,CAqBjB;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAsB9G;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiB/E;AAcD;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBzE;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAkBtE;AAcD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAa9E"}
|
package/dist/services/claude.js
CHANGED
|
@@ -28,6 +28,9 @@ async function runStructured(prompt, jsonSchema, options) {
|
|
|
28
28
|
'--output-format', 'json',
|
|
29
29
|
'--json-schema', JSON.stringify(jsonSchema)
|
|
30
30
|
];
|
|
31
|
+
if (options?.model) {
|
|
32
|
+
args.push('--model', options.model);
|
|
33
|
+
}
|
|
31
34
|
if (options?.effort) {
|
|
32
35
|
args.push('--effort', options.effort);
|
|
33
36
|
}
|
|
@@ -65,7 +68,7 @@ export async function runWithPrompt(prompt, options) {
|
|
|
65
68
|
/**
|
|
66
69
|
* Launch interactive claude session
|
|
67
70
|
*/
|
|
68
|
-
export async function runInteractive(initialPrompt, cwd, permissionMode, effort) {
|
|
71
|
+
export async function runInteractive(initialPrompt, cwd, permissionMode, model, effort) {
|
|
69
72
|
const hasClaude = await ensureClaudeCli();
|
|
70
73
|
if (!hasClaude) {
|
|
71
74
|
logger.error('Claude CLI is not available');
|
|
@@ -75,6 +78,9 @@ export async function runInteractive(initialPrompt, cwd, permissionMode, effort)
|
|
|
75
78
|
if (permissionMode) {
|
|
76
79
|
args.push('--permission-mode', permissionMode);
|
|
77
80
|
}
|
|
81
|
+
if (model) {
|
|
82
|
+
args.push('--model', model);
|
|
83
|
+
}
|
|
78
84
|
if (effort) {
|
|
79
85
|
args.push('--effort', effort);
|
|
80
86
|
}
|
|
@@ -84,17 +90,20 @@ export async function runInteractive(initialPrompt, cwd, permissionMode, effort)
|
|
|
84
90
|
return execWithOutput('claude', args, { cwd });
|
|
85
91
|
}
|
|
86
92
|
/**
|
|
87
|
-
* Set workflow status on an idea1.ai project item
|
|
93
|
+
* Set workflow status on an idea1.ai project item. When the item's branch is
|
|
94
|
+
* known it is recorded on the item too, so the web client can find the branch
|
|
95
|
+
* without scanning the repository.
|
|
88
96
|
*/
|
|
89
|
-
export async function setWorkflowStatus(itemUrl, status) {
|
|
97
|
+
export async function setWorkflowStatus(itemUrl, status, branchName) {
|
|
90
98
|
const hasClaude = await ensureClaudeCli();
|
|
91
99
|
if (!hasClaude) {
|
|
92
100
|
logger.warning('Claude CLI not available, skipping workflow status update');
|
|
93
101
|
return false;
|
|
94
102
|
}
|
|
95
103
|
logger.step(`Setting workflow status to "${status}"...`);
|
|
104
|
+
const branchClause = branchName ? ` and pass branchName "${branchName}"` : '';
|
|
96
105
|
try {
|
|
97
|
-
await runWithPrompt(`Set the workflow status of ${itemUrl} to "${status}". Put "done" in the "result" field on success, or an explanation in the "error" field on failure.`);
|
|
106
|
+
await runWithPrompt(`Set the workflow status of ${itemUrl} to "${status}"${branchClause} using the set_item_workflow_status MCP tool. Put "done" in the "result" field on success, or an explanation in the "error" field on failure.`);
|
|
98
107
|
logger.success(`Workflow status updated to "${status}"`);
|
|
99
108
|
return true;
|
|
100
109
|
}
|
|
@@ -106,6 +115,32 @@ export async function setWorkflowStatus(itemUrl, status) {
|
|
|
106
115
|
return false;
|
|
107
116
|
}
|
|
108
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* Read the current workflow status of an idea1.ai project item. Returns null
|
|
120
|
+
* when the item has no status yet.
|
|
121
|
+
*/
|
|
122
|
+
export async function getWorkflowStatus(itemUrl) {
|
|
123
|
+
const hasClaude = await ensureClaudeCli();
|
|
124
|
+
if (!hasClaude) {
|
|
125
|
+
throw new Error('Claude CLI is required to read the project item workflow status');
|
|
126
|
+
}
|
|
127
|
+
logger.step('Reading workflow status from idea1.ai...');
|
|
128
|
+
const output = await runStructured(`Get the idea1 project item ${itemUrl} using the get_item MCP tool and put its workflowStatus value in the "workflowStatus" field. Use an empty string when the item has no workflow status.`, workflowStatusSchema, { effort: 'low' });
|
|
129
|
+
const status = typeof output.workflowStatus === 'string' ? output.workflowStatus.trim() : '';
|
|
130
|
+
logger.dim(`Workflow status on idea1.ai: ${status || '(none)'}`);
|
|
131
|
+
return status || null;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* JSON schema for the get-workflow-status structured output.
|
|
135
|
+
*/
|
|
136
|
+
const workflowStatusSchema = {
|
|
137
|
+
type: 'object',
|
|
138
|
+
properties: {
|
|
139
|
+
workflowStatus: { type: 'string', description: 'The workflowStatus of the idea1 project item, or an empty string when it has none' }
|
|
140
|
+
},
|
|
141
|
+
required: ['workflowStatus'],
|
|
142
|
+
additionalProperties: false
|
|
143
|
+
};
|
|
109
144
|
/**
|
|
110
145
|
* Generate a branch name from a project item description
|
|
111
146
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/services/claude.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACvG,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/services/claude.ts"],"names":[],"mappings":"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"}
|
package/dist/services/git.d.ts
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import type { BranchMetadata } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Path of a branch's metadata JSON file relative to the repository root
|
|
4
|
+
*/
|
|
5
|
+
export declare function getBranchMetadataRelativePath(branchName: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* The on-disk form of a branch metadata file. The web client writes the same
|
|
8
|
+
* bytes through the GitHub API, so keep this exact (2-space indent, trailing newline).
|
|
9
|
+
*/
|
|
10
|
+
export declare function serializeBranchMetadata(metadata: BranchMetadata): string;
|
|
2
11
|
/**
|
|
3
12
|
* Read branch metadata from the JSON file in the current working tree.
|
|
4
13
|
* Returns null if the file doesn't exist.
|
|
@@ -242,4 +251,61 @@ export declare function checkoutBranch(branchName: string): Promise<void>;
|
|
|
242
251
|
* Throws if uncommitted changes, untracked files, or unpushed commits are found.
|
|
243
252
|
*/
|
|
244
253
|
export declare function ensureStackBranchReady(stackBranch: string): Promise<void>;
|
|
254
|
+
/**
|
|
255
|
+
* Where a branch is checked out locally: the current repository root when it is
|
|
256
|
+
* the current branch, otherwise the worktree (or main repository) holding it,
|
|
257
|
+
* or null when it has no local checkout.
|
|
258
|
+
*/
|
|
259
|
+
export declare function getCheckoutPathForBranch(branchName: string): Promise<string | null>;
|
|
260
|
+
/**
|
|
261
|
+
* A file to write (content) or delete (null) in a detached commit
|
|
262
|
+
*/
|
|
263
|
+
export interface DetachedFileChange {
|
|
264
|
+
path: string;
|
|
265
|
+
content: string | null;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Commit file changes on top of a ref without checking anything out, using a
|
|
269
|
+
* temporary index. Returns the new commit sha (not yet on any branch). Used for
|
|
270
|
+
* branches that have no local checkout, so the branch can carry its workflow
|
|
271
|
+
* metadata before anyone works on it.
|
|
272
|
+
*/
|
|
273
|
+
export declare function commitFilesDetached(parentRef: string, changes: DetachedFileChange[], message: string): Promise<string>;
|
|
274
|
+
/**
|
|
275
|
+
* Publish a commit as the tip of a branch on origin (creating the branch when it
|
|
276
|
+
* does not exist yet), refresh the remote-tracking ref, and move the local
|
|
277
|
+
* branch ref along when one exists. Only for branches without a local checkout.
|
|
278
|
+
*/
|
|
279
|
+
export declare function pushCommitToBranch(branchName: string, commitSha: string): Promise<void>;
|
|
280
|
+
/**
|
|
281
|
+
* Create a branch on origin from a source ref (e.g. `origin/working/release`) with
|
|
282
|
+
* its `.idea1/<branch>.json` metadata as the first commit. No checkout is needed.
|
|
283
|
+
*/
|
|
284
|
+
export declare function createBranchWithMetadataDetached(branchName: string, sourceRef: string, metadata: BranchMetadata): Promise<void>;
|
|
285
|
+
/**
|
|
286
|
+
* Update fields of the committed `.idea1/<branch>.json` on origin for a branch
|
|
287
|
+
* that has no local checkout. Returns true when a commit was pushed.
|
|
288
|
+
*/
|
|
289
|
+
export declare function updateBranchMetadataDetached(branchName: string, updates: Partial<BranchMetadata>): Promise<boolean>;
|
|
290
|
+
/**
|
|
291
|
+
* Create a branch on origin pointing at a source ref, without any local checkout.
|
|
292
|
+
*/
|
|
293
|
+
export declare function createRemoteBranchFrom(branchName: string, sourceRef: string): Promise<void>;
|
|
294
|
+
export type FastForwardResult = 'up-to-date' | 'fast-forwarded' | 'ahead' | 'diverged' | 'blocked';
|
|
295
|
+
/**
|
|
296
|
+
* Fast-forward a local checkout of a branch to `origin/<branch>` when it is
|
|
297
|
+
* strictly behind. Never rewrites local commits: reports 'ahead' or 'diverged'
|
|
298
|
+
* instead, and 'blocked' when local changes prevent the fast-forward.
|
|
299
|
+
*/
|
|
300
|
+
export declare function fastForwardCheckoutToOrigin(branchName: string, checkoutPath: string): Promise<FastForwardResult>;
|
|
301
|
+
/**
|
|
302
|
+
* Whether a branch exists on origin (refreshing the remote-tracking ref first).
|
|
303
|
+
* Returns false quietly when the remote branch is gone.
|
|
304
|
+
*/
|
|
305
|
+
export declare function fetchRemoteBranch(branchName: string): Promise<boolean>;
|
|
306
|
+
/**
|
|
307
|
+
* Remove the committed `.idea1/<branch>.json` from a branch that has no local
|
|
308
|
+
* checkout, so the file does not leak into the target branch when the PR merges.
|
|
309
|
+
*/
|
|
310
|
+
export declare function removeBranchMetadataDetached(branchName: string): Promise<void>;
|
|
245
311
|
//# sourceMappingURL=git.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/services/git.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/services/git.ts"],"names":[],"mappings":"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"}
|
package/dist/services/git.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { exec, execOrThrow } from '../lib/shell.js';
|
|
2
2
|
import { logger } from '../lib/logger.js';
|
|
3
|
-
import { dirname, basename, join } from 'path';
|
|
4
|
-
import {
|
|
3
|
+
import { dirname, basename, join, resolve } from 'path';
|
|
4
|
+
import { tmpdir } from 'os';
|
|
5
|
+
import { mkdir, mkdtemp, writeFile, readFile, readdir, unlink, rm } from 'fs/promises';
|
|
5
6
|
import { access } from 'fs/promises';
|
|
6
7
|
import { SETTINGS_FILES } from '../lib/settings.js';
|
|
7
8
|
/**
|
|
@@ -28,11 +29,24 @@ function sanitizeBranchNameForFilename(branchName) {
|
|
|
28
29
|
function branchNameFromFilename(filename) {
|
|
29
30
|
return filename.replace(/\.json$/, '').replace(/--/g, '/');
|
|
30
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Path of a branch's metadata JSON file relative to the repository root
|
|
34
|
+
*/
|
|
35
|
+
export function getBranchMetadataRelativePath(branchName) {
|
|
36
|
+
return `.idea1/${sanitizeBranchNameForFilename(branchName)}.json`;
|
|
37
|
+
}
|
|
31
38
|
/**
|
|
32
39
|
* Get the path to a branch's metadata JSON file inside `.idea1/`
|
|
33
40
|
*/
|
|
34
41
|
function getBranchMetadataPath(worktreePath, branchName) {
|
|
35
|
-
return join(worktreePath,
|
|
42
|
+
return join(worktreePath, getBranchMetadataRelativePath(branchName));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The on-disk form of a branch metadata file. The web client writes the same
|
|
46
|
+
* bytes through the GitHub API, so keep this exact (2-space indent, trailing newline).
|
|
47
|
+
*/
|
|
48
|
+
export function serializeBranchMetadata(metadata) {
|
|
49
|
+
return JSON.stringify(metadata, null, 2) + '\n';
|
|
36
50
|
}
|
|
37
51
|
/**
|
|
38
52
|
* Read branch metadata from the JSON file in the current working tree.
|
|
@@ -77,7 +91,7 @@ export async function writeBranchMetadata(metadata, worktreePath) {
|
|
|
77
91
|
if (!await directoryExists(idea1Dir))
|
|
78
92
|
return false;
|
|
79
93
|
const metadataPath = getBranchMetadataPath(root, metadata.branchName);
|
|
80
|
-
await writeFile(metadataPath,
|
|
94
|
+
await writeFile(metadataPath, serializeBranchMetadata(metadata));
|
|
81
95
|
return true;
|
|
82
96
|
}
|
|
83
97
|
/**
|
|
@@ -91,7 +105,7 @@ async function updateBranchMetadataFile(branchName, updates) {
|
|
|
91
105
|
const content = await readFile(metadataPath, 'utf-8');
|
|
92
106
|
const metadata = JSON.parse(content);
|
|
93
107
|
Object.assign(metadata, updates);
|
|
94
|
-
await writeFile(metadataPath,
|
|
108
|
+
await writeFile(metadataPath, serializeBranchMetadata(metadata));
|
|
95
109
|
}
|
|
96
110
|
catch {
|
|
97
111
|
// File doesn't exist yet — silently skip
|
|
@@ -430,7 +444,7 @@ export async function commitBranchMetadata(worktreePath, branchName, projectItem
|
|
|
430
444
|
const idea1Dir = join(worktreePath, '.idea1');
|
|
431
445
|
await mkdir(idea1Dir, { recursive: true });
|
|
432
446
|
const filename = `${sanitizeBranchNameForFilename(branchName)}.json`;
|
|
433
|
-
await writeFile(join(idea1Dir, filename),
|
|
447
|
+
await writeFile(join(idea1Dir, filename), serializeBranchMetadata(metadata));
|
|
434
448
|
await execOrThrow('git', ['add', `.idea1/${filename}`], { cwd: worktreePath });
|
|
435
449
|
await execOrThrow('git', ['commit', '-m', `idea1: link to ${metadata.projectItemUrl ?? branchName}`], { cwd: worktreePath });
|
|
436
450
|
logger.dim('Committed branch metadata to branch');
|
|
@@ -906,4 +920,145 @@ export async function ensureStackBranchReady(stackBranch) {
|
|
|
906
920
|
}
|
|
907
921
|
logger.success(`Stack branch ${stackBranch} is clean and ready`);
|
|
908
922
|
}
|
|
923
|
+
/**
|
|
924
|
+
* Where a branch is checked out locally: the current repository root when it is
|
|
925
|
+
* the current branch, otherwise the worktree (or main repository) holding it,
|
|
926
|
+
* or null when it has no local checkout.
|
|
927
|
+
*/
|
|
928
|
+
export async function getCheckoutPathForBranch(branchName) {
|
|
929
|
+
const currentBranch = await getCurrentBranch();
|
|
930
|
+
if (currentBranch === branchName) {
|
|
931
|
+
return (await getRepoRoot()).trim();
|
|
932
|
+
}
|
|
933
|
+
return getWorktreePathForBranch(branchName);
|
|
934
|
+
}
|
|
935
|
+
/**
|
|
936
|
+
* Absolute path of the repository's common git directory (shared by all worktrees)
|
|
937
|
+
*/
|
|
938
|
+
async function getGitCommonDir() {
|
|
939
|
+
const commonDir = (await execOrThrow('git', ['rev-parse', '--git-common-dir'])).trim();
|
|
940
|
+
return resolve(process.cwd(), commonDir);
|
|
941
|
+
}
|
|
942
|
+
/**
|
|
943
|
+
* Commit file changes on top of a ref without checking anything out, using a
|
|
944
|
+
* temporary index. Returns the new commit sha (not yet on any branch). Used for
|
|
945
|
+
* branches that have no local checkout, so the branch can carry its workflow
|
|
946
|
+
* metadata before anyone works on it.
|
|
947
|
+
*/
|
|
948
|
+
export async function commitFilesDetached(parentRef, changes, message) {
|
|
949
|
+
const parentSha = (await execOrThrow('git', ['rev-parse', '--verify', `${parentRef}^{commit}`])).trim();
|
|
950
|
+
const indexFile = join(await getGitCommonDir(), `idea1-index-${process.pid}-${Date.now()}`);
|
|
951
|
+
const env = { ...process.env, GIT_INDEX_FILE: indexFile };
|
|
952
|
+
const tmpDir = await mkdtemp(join(tmpdir(), 'idea1-'));
|
|
953
|
+
try {
|
|
954
|
+
await execOrThrow('git', ['read-tree', parentSha], { env });
|
|
955
|
+
for (const change of changes) {
|
|
956
|
+
if (change.content === null) {
|
|
957
|
+
await execOrThrow('git', ['update-index', '--force-remove', change.path], { env });
|
|
958
|
+
continue;
|
|
959
|
+
}
|
|
960
|
+
const blobFile = join(tmpDir, 'blob');
|
|
961
|
+
await writeFile(blobFile, change.content);
|
|
962
|
+
const blobSha = (await execOrThrow('git', ['hash-object', '-w', blobFile])).trim();
|
|
963
|
+
await execOrThrow('git', ['update-index', '--add', '--cacheinfo', `100644,${blobSha},${change.path}`], { env });
|
|
964
|
+
}
|
|
965
|
+
const treeSha = (await execOrThrow('git', ['write-tree'], { env })).trim();
|
|
966
|
+
return (await execOrThrow('git', ['commit-tree', treeSha, '-p', parentSha, '-m', message])).trim();
|
|
967
|
+
}
|
|
968
|
+
finally {
|
|
969
|
+
await rm(indexFile, { force: true });
|
|
970
|
+
await rm(tmpDir, { recursive: true, force: true });
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
/**
|
|
974
|
+
* Publish a commit as the tip of a branch on origin (creating the branch when it
|
|
975
|
+
* does not exist yet), refresh the remote-tracking ref, and move the local
|
|
976
|
+
* branch ref along when one exists. Only for branches without a local checkout.
|
|
977
|
+
*/
|
|
978
|
+
export async function pushCommitToBranch(branchName, commitSha) {
|
|
979
|
+
await execOrThrow('git', ['push', 'origin', `${commitSha}:refs/heads/${branchName}`]);
|
|
980
|
+
await execOrThrow('git', ['fetch', 'origin', branchName]);
|
|
981
|
+
const localExists = await exec('git', ['rev-parse', '--verify', `refs/heads/${branchName}`]);
|
|
982
|
+
if (localExists.exitCode === 0) {
|
|
983
|
+
await execOrThrow('git', ['update-ref', `refs/heads/${branchName}`, commitSha]);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
/**
|
|
987
|
+
* Create a branch on origin from a source ref (e.g. `origin/working/release`) with
|
|
988
|
+
* its `.idea1/<branch>.json` metadata as the first commit. No checkout is needed.
|
|
989
|
+
*/
|
|
990
|
+
export async function createBranchWithMetadataDetached(branchName, sourceRef, metadata) {
|
|
991
|
+
logger.step(`Creating branch ${branchName} from ${sourceRef}...`);
|
|
992
|
+
const commitSha = await commitFilesDetached(sourceRef, [{ path: getBranchMetadataRelativePath(branchName), content: serializeBranchMetadata(metadata) }], `idea1: link to ${metadata.projectItemUrl ?? branchName}`);
|
|
993
|
+
await pushCommitToBranch(branchName, commitSha);
|
|
994
|
+
logger.success(`Branch ${branchName} created on origin with its workflow metadata`);
|
|
995
|
+
}
|
|
996
|
+
/**
|
|
997
|
+
* Update fields of the committed `.idea1/<branch>.json` on origin for a branch
|
|
998
|
+
* that has no local checkout. Returns true when a commit was pushed.
|
|
999
|
+
*/
|
|
1000
|
+
export async function updateBranchMetadataDetached(branchName, updates) {
|
|
1001
|
+
const remote = await readBranchMetadataFromRef(branchName);
|
|
1002
|
+
const merged = { ...(remote ?? { branchName }), ...updates, branchName };
|
|
1003
|
+
const unchanged = remote !== null && Object.keys(updates).every(key => remote[key] === merged[key]);
|
|
1004
|
+
if (unchanged) {
|
|
1005
|
+
return false;
|
|
1006
|
+
}
|
|
1007
|
+
const commitSha = await commitFilesDetached(`origin/${branchName}`, [{ path: getBranchMetadataRelativePath(branchName), content: serializeBranchMetadata(merged) }], `idea1: update metadata for ${merged.projectItemUrl ?? branchName}`);
|
|
1008
|
+
await pushCommitToBranch(branchName, commitSha);
|
|
1009
|
+
logger.dim('Committed branch metadata update on origin');
|
|
1010
|
+
return true;
|
|
1011
|
+
}
|
|
1012
|
+
/**
|
|
1013
|
+
* Create a branch on origin pointing at a source ref, without any local checkout.
|
|
1014
|
+
*/
|
|
1015
|
+
export async function createRemoteBranchFrom(branchName, sourceRef) {
|
|
1016
|
+
logger.step(`Creating branch ${branchName} from ${sourceRef}...`);
|
|
1017
|
+
await execOrThrow('git', ['push', 'origin', `${sourceRef}:refs/heads/${branchName}`]);
|
|
1018
|
+
await execOrThrow('git', ['fetch', 'origin', branchName]);
|
|
1019
|
+
logger.success(`Branch ${branchName} created on origin`);
|
|
1020
|
+
}
|
|
1021
|
+
/**
|
|
1022
|
+
* Fast-forward a local checkout of a branch to `origin/<branch>` when it is
|
|
1023
|
+
* strictly behind. Never rewrites local commits: reports 'ahead' or 'diverged'
|
|
1024
|
+
* instead, and 'blocked' when local changes prevent the fast-forward.
|
|
1025
|
+
*/
|
|
1026
|
+
export async function fastForwardCheckoutToOrigin(branchName, checkoutPath) {
|
|
1027
|
+
const local = (await execOrThrow('git', ['rev-parse', '--verify', `refs/heads/${branchName}`], { cwd: checkoutPath })).trim();
|
|
1028
|
+
const remote = (await execOrThrow('git', ['rev-parse', '--verify', `refs/remotes/origin/${branchName}`], { cwd: checkoutPath })).trim();
|
|
1029
|
+
if (local === remote) {
|
|
1030
|
+
return 'up-to-date';
|
|
1031
|
+
}
|
|
1032
|
+
const remoteIsAncestor = await exec('git', ['merge-base', '--is-ancestor', remote, local], { cwd: checkoutPath });
|
|
1033
|
+
if (remoteIsAncestor.exitCode === 0) {
|
|
1034
|
+
return 'ahead';
|
|
1035
|
+
}
|
|
1036
|
+
const localIsAncestor = await exec('git', ['merge-base', '--is-ancestor', local, remote], { cwd: checkoutPath });
|
|
1037
|
+
if (localIsAncestor.exitCode !== 0) {
|
|
1038
|
+
return 'diverged';
|
|
1039
|
+
}
|
|
1040
|
+
const fastForward = await exec('git', ['merge', '--ff-only', `origin/${branchName}`], { cwd: checkoutPath });
|
|
1041
|
+
return fastForward.exitCode === 0 ? 'fast-forwarded' : 'blocked';
|
|
1042
|
+
}
|
|
1043
|
+
/**
|
|
1044
|
+
* Whether a branch exists on origin (refreshing the remote-tracking ref first).
|
|
1045
|
+
* Returns false quietly when the remote branch is gone.
|
|
1046
|
+
*/
|
|
1047
|
+
export async function fetchRemoteBranch(branchName) {
|
|
1048
|
+
const result = await exec('git', ['fetch', 'origin', branchName]);
|
|
1049
|
+
return result.exitCode === 0;
|
|
1050
|
+
}
|
|
1051
|
+
/**
|
|
1052
|
+
* Remove the committed `.idea1/<branch>.json` from a branch that has no local
|
|
1053
|
+
* checkout, so the file does not leak into the target branch when the PR merges.
|
|
1054
|
+
*/
|
|
1055
|
+
export async function removeBranchMetadataDetached(branchName) {
|
|
1056
|
+
const remote = await readBranchMetadataFromRef(branchName);
|
|
1057
|
+
if (!remote) {
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
1060
|
+
const commitSha = await commitFilesDetached(`origin/${branchName}`, [{ path: getBranchMetadataRelativePath(branchName), content: null }], `idea1: remove branch metadata for ${branchName}`);
|
|
1061
|
+
await pushCommitToBranch(branchName, commitSha);
|
|
1062
|
+
logger.dim('Removed branch metadata file before merge');
|
|
1063
|
+
}
|
|
909
1064
|
//# sourceMappingURL=git.js.map
|