@howlil/ez-agents 3.4.1 → 3.5.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/LICENSE +21 -21
- package/README.md +84 -20
- package/agents/ez-observer-agent.md +260 -0
- package/agents/ez-release-agent.md +333 -0
- package/agents/ez-requirements-agent.md +377 -0
- package/agents/ez-scrum-master-agent.md +242 -0
- package/agents/ez-tech-lead-agent.md +267 -0
- package/bin/install.js +3221 -3230
- package/commands/ez/arch-review.md +102 -0
- package/commands/ez/execute-phase.md +11 -0
- package/commands/ez/export-session.md +79 -0
- package/commands/ez/gather-requirements.md +117 -0
- package/commands/ez/git-workflow.md +72 -0
- package/commands/ez/hotfix.md +120 -0
- package/commands/ez/import-session.md +82 -0
- package/commands/ez/join-discord.md +18 -18
- package/commands/ez/list-sessions.md +96 -0
- package/commands/ez/package-manager.md +316 -0
- package/commands/ez/plan-phase.md +9 -1
- package/commands/ez/preflight.md +79 -0
- package/commands/ez/progress.md +13 -1
- package/commands/ez/release.md +153 -0
- package/commands/ez/resume.md +107 -0
- package/commands/ez/standup.md +85 -0
- package/ez-agents/bin/ez-tools.cjs +1095 -716
- package/ez-agents/bin/lib/assistant-adapter.cjs +264 -264
- package/ez-agents/bin/lib/audit-exec.cjs +7 -2
- package/ez-agents/bin/lib/bdd-validator.cjs +622 -0
- package/ez-agents/bin/lib/circuit-breaker.cjs +118 -118
- package/ez-agents/bin/lib/config.cjs +190 -190
- package/ez-agents/bin/lib/content-scanner.cjs +238 -0
- package/ez-agents/bin/lib/context-cache.cjs +154 -0
- package/ez-agents/bin/lib/context-errors.cjs +71 -0
- package/ez-agents/bin/lib/context-manager.cjs +220 -0
- package/ez-agents/bin/lib/discussion-synthesizer.cjs +458 -0
- package/ez-agents/bin/lib/file-access.cjs +207 -0
- package/ez-agents/bin/lib/file-lock.cjs +236 -236
- package/ez-agents/bin/lib/frontmatter.cjs +299 -299
- package/ez-agents/bin/lib/fs-utils.cjs +153 -153
- package/ez-agents/bin/lib/git-errors.cjs +83 -0
- package/ez-agents/bin/lib/git-utils.cjs +118 -0
- package/ez-agents/bin/lib/git-workflow-engine.cjs +1157 -0
- package/ez-agents/bin/lib/index.cjs +157 -113
- package/ez-agents/bin/lib/init.cjs +757 -757
- package/ez-agents/bin/lib/lockfile-validator.cjs +227 -0
- package/ez-agents/bin/lib/logger.cjs +124 -124
- package/ez-agents/bin/lib/memory-compression.cjs +256 -0
- package/ez-agents/bin/lib/metrics-tracker.cjs +406 -0
- package/ez-agents/bin/lib/milestone.cjs +241 -241
- package/ez-agents/bin/lib/model-provider.cjs +241 -241
- package/ez-agents/bin/lib/package-manager-detector.cjs +203 -0
- package/ez-agents/bin/lib/package-manager-executor.cjs +385 -0
- package/ez-agents/bin/lib/package-manager-service.cjs +216 -0
- package/ez-agents/bin/lib/phase.cjs +925 -925
- package/ez-agents/bin/lib/planning-write.cjs +107 -107
- package/ez-agents/bin/lib/release-validator.cjs +614 -0
- package/ez-agents/bin/lib/retry.cjs +119 -119
- package/ez-agents/bin/lib/roadmap.cjs +306 -306
- package/ez-agents/bin/lib/safe-exec.cjs +128 -128
- package/ez-agents/bin/lib/safe-path.cjs +130 -130
- package/ez-agents/bin/lib/session-chain.cjs +304 -0
- package/ez-agents/bin/lib/session-errors.cjs +81 -0
- package/ez-agents/bin/lib/session-export.cjs +251 -0
- package/ez-agents/bin/lib/session-import.cjs +262 -0
- package/ez-agents/bin/lib/session-manager.cjs +280 -0
- package/ez-agents/bin/lib/state.cjs +736 -736
- package/ez-agents/bin/lib/temp-file.cjs +239 -239
- package/ez-agents/bin/lib/template.cjs +223 -223
- package/ez-agents/bin/lib/test-file-lock.cjs +112 -112
- package/ez-agents/bin/lib/test-graceful.cjs +93 -93
- package/ez-agents/bin/lib/test-logger.cjs +60 -60
- package/ez-agents/bin/lib/test-safe-exec.cjs +38 -38
- package/ez-agents/bin/lib/test-safe-path.cjs +33 -33
- package/ez-agents/bin/lib/test-temp-file.cjs +125 -125
- package/ez-agents/bin/lib/tier-manager.cjs +428 -0
- package/ez-agents/bin/lib/timeout-exec.cjs +63 -63
- package/ez-agents/bin/lib/url-fetch.cjs +170 -0
- package/ez-agents/bin/lib/verify.cjs +15 -1
- package/ez-agents/references/checkpoints.md +776 -776
- package/ez-agents/references/continuation-format.md +249 -249
- package/ez-agents/references/metrics-schema.md +118 -0
- package/ez-agents/references/planning-config.md +140 -0
- package/ez-agents/references/questioning.md +162 -162
- package/ez-agents/references/tdd.md +263 -263
- package/ez-agents/references/tier-strategy.md +103 -0
- package/ez-agents/templates/bdd-feature.md +173 -0
- package/ez-agents/templates/codebase/concerns.md +310 -310
- package/ez-agents/templates/codebase/conventions.md +307 -307
- package/ez-agents/templates/codebase/integrations.md +280 -280
- package/ez-agents/templates/codebase/stack.md +186 -186
- package/ez-agents/templates/codebase/testing.md +480 -480
- package/ez-agents/templates/config.json +37 -37
- package/ez-agents/templates/continue-here.md +78 -78
- package/ez-agents/templates/discussion.md +68 -0
- package/ez-agents/templates/incident-runbook.md +205 -0
- package/ez-agents/templates/milestone-archive.md +123 -123
- package/ez-agents/templates/milestone.md +115 -115
- package/ez-agents/templates/release-checklist.md +133 -0
- package/ez-agents/templates/requirements.md +231 -231
- package/ez-agents/templates/research-project/ARCHITECTURE.md +204 -204
- package/ez-agents/templates/research-project/FEATURES.md +147 -147
- package/ez-agents/templates/research-project/PITFALLS.md +200 -200
- package/ez-agents/templates/research-project/STACK.md +120 -120
- package/ez-agents/templates/research-project/SUMMARY.md +170 -170
- package/ez-agents/templates/retrospective.md +54 -54
- package/ez-agents/templates/roadmap.md +202 -202
- package/ez-agents/templates/rollback-plan.md +201 -0
- package/ez-agents/templates/summary-minimal.md +41 -41
- package/ez-agents/templates/summary-standard.md +48 -48
- package/ez-agents/templates/summary.md +248 -248
- package/ez-agents/templates/user-setup.md +311 -311
- package/ez-agents/templates/verification-report.md +322 -322
- package/ez-agents/workflows/add-phase.md +112 -112
- package/ez-agents/workflows/add-tests.md +351 -351
- package/ez-agents/workflows/add-todo.md +158 -158
- package/ez-agents/workflows/arch-review.md +54 -0
- package/ez-agents/workflows/audit-milestone.md +332 -332
- package/ez-agents/workflows/autonomous.md +131 -30
- package/ez-agents/workflows/check-todos.md +177 -177
- package/ez-agents/workflows/cleanup.md +152 -152
- package/ez-agents/workflows/complete-milestone.md +766 -766
- package/ez-agents/workflows/diagnose-issues.md +219 -219
- package/ez-agents/workflows/discovery-phase.md +289 -289
- package/ez-agents/workflows/discuss-phase.md +762 -762
- package/ez-agents/workflows/execute-phase.md +513 -468
- package/ez-agents/workflows/execute-plan.md +483 -483
- package/ez-agents/workflows/export-session.md +255 -0
- package/ez-agents/workflows/gather-requirements.md +206 -0
- package/ez-agents/workflows/health.md +159 -159
- package/ez-agents/workflows/help.md +584 -492
- package/ez-agents/workflows/hotfix.md +291 -0
- package/ez-agents/workflows/import-session.md +303 -0
- package/ez-agents/workflows/insert-phase.md +130 -130
- package/ez-agents/workflows/list-phase-assumptions.md +178 -178
- package/ez-agents/workflows/map-codebase.md +316 -316
- package/ez-agents/workflows/new-milestone.md +339 -10
- package/ez-agents/workflows/new-project.md +293 -299
- package/ez-agents/workflows/node-repair.md +92 -92
- package/ez-agents/workflows/pause-work.md +122 -122
- package/ez-agents/workflows/plan-milestone-gaps.md +274 -274
- package/ez-agents/workflows/plan-phase.md +673 -651
- package/ez-agents/workflows/progress.md +372 -382
- package/ez-agents/workflows/quick.md +610 -610
- package/ez-agents/workflows/release.md +253 -0
- package/ez-agents/workflows/remove-phase.md +155 -155
- package/ez-agents/workflows/research-phase.md +74 -74
- package/ez-agents/workflows/resume-project.md +307 -307
- package/ez-agents/workflows/resume-session.md +215 -0
- package/ez-agents/workflows/set-profile.md +81 -81
- package/ez-agents/workflows/settings.md +242 -242
- package/ez-agents/workflows/standup.md +64 -0
- package/ez-agents/workflows/stats.md +57 -57
- package/ez-agents/workflows/transition.md +544 -544
- package/ez-agents/workflows/ui-phase.md +290 -290
- package/ez-agents/workflows/ui-review.md +157 -157
- package/ez-agents/workflows/update.md +320 -320
- package/ez-agents/workflows/validate-phase.md +167 -167
- package/ez-agents/workflows/verify-phase.md +243 -243
- package/ez-agents/workflows/verify-work.md +584 -584
- package/package.json +10 -4
- package/scripts/build-hooks.js +43 -43
- package/scripts/run-tests.cjs +29 -29
|
@@ -1,63 +1,63 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* EZ Timeout Exec — Command execution with timeout and fallback
|
|
5
|
-
*
|
|
6
|
-
* Provides safe command execution with configurable timeout
|
|
7
|
-
* Logs errors and supports fallback values
|
|
8
|
-
*
|
|
9
|
-
* Usage:
|
|
10
|
-
* const { execWithTimeout } = require('./timeout-exec.cjs');
|
|
11
|
-
* const result = await execWithTimeout('node', ['script.js'], { timeout: 5000, fallback: 'default' });
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
const { execFile } = require('child_process');
|
|
15
|
-
const { promisify } = require('util');
|
|
16
|
-
const execFileAsync = promisify(execFile);
|
|
17
|
-
const Logger = require('./logger.cjs');
|
|
18
|
-
const logger = new Logger();
|
|
19
|
-
|
|
20
|
-
const DEFAULT_TIMEOUT = 5000; // 5 seconds
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Execute a command with timeout
|
|
24
|
-
* @param {string} cmd - Command to execute
|
|
25
|
-
* @param {string[]} args - Command arguments
|
|
26
|
-
* @param {Object} options - Execution options
|
|
27
|
-
* @param {number} options.timeout - Timeout in milliseconds (default: 5000)
|
|
28
|
-
* @param {any} options.fallback - Fallback value if command fails or times out
|
|
29
|
-
* @returns {Promise<string>} - Command stdout or fallback value
|
|
30
|
-
*/
|
|
31
|
-
async function execWithTimeout(cmd, args, options = {}) {
|
|
32
|
-
const { timeout = DEFAULT_TIMEOUT, fallback = null } = options;
|
|
33
|
-
const hasFallback = Object.prototype.hasOwnProperty.call(options, 'fallback');
|
|
34
|
-
|
|
35
|
-
return new Promise(async (resolve, reject) => {
|
|
36
|
-
const timeoutId = setTimeout(() => {
|
|
37
|
-
logger.error(`Command timed out: ${cmd} ${args.join(' ')}`, { timeout });
|
|
38
|
-
if (hasFallback) {
|
|
39
|
-
logger.info('Using fallback value', { fallback });
|
|
40
|
-
resolve(fallback);
|
|
41
|
-
} else {
|
|
42
|
-
reject(new Error(`Command timed out after ${timeout}ms: ${cmd}`));
|
|
43
|
-
}
|
|
44
|
-
}, timeout);
|
|
45
|
-
|
|
46
|
-
try {
|
|
47
|
-
const result = await execFileAsync(cmd, args, { timeout });
|
|
48
|
-
clearTimeout(timeoutId);
|
|
49
|
-
resolve(result.stdout.trim());
|
|
50
|
-
} catch (err) {
|
|
51
|
-
clearTimeout(timeoutId);
|
|
52
|
-
logger.error(`Command failed: ${cmd}`, { error: err.message, args });
|
|
53
|
-
if (hasFallback) {
|
|
54
|
-
logger.info('Using fallback value', { fallback });
|
|
55
|
-
resolve(fallback);
|
|
56
|
-
} else {
|
|
57
|
-
reject(err);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
module.exports = { execWithTimeout };
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* EZ Timeout Exec — Command execution with timeout and fallback
|
|
5
|
+
*
|
|
6
|
+
* Provides safe command execution with configurable timeout
|
|
7
|
+
* Logs errors and supports fallback values
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* const { execWithTimeout } = require('./timeout-exec.cjs');
|
|
11
|
+
* const result = await execWithTimeout('node', ['script.js'], { timeout: 5000, fallback: 'default' });
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const { execFile } = require('child_process');
|
|
15
|
+
const { promisify } = require('util');
|
|
16
|
+
const execFileAsync = promisify(execFile);
|
|
17
|
+
const Logger = require('./logger.cjs');
|
|
18
|
+
const logger = new Logger();
|
|
19
|
+
|
|
20
|
+
const DEFAULT_TIMEOUT = 5000; // 5 seconds
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Execute a command with timeout
|
|
24
|
+
* @param {string} cmd - Command to execute
|
|
25
|
+
* @param {string[]} args - Command arguments
|
|
26
|
+
* @param {Object} options - Execution options
|
|
27
|
+
* @param {number} options.timeout - Timeout in milliseconds (default: 5000)
|
|
28
|
+
* @param {any} options.fallback - Fallback value if command fails or times out
|
|
29
|
+
* @returns {Promise<string>} - Command stdout or fallback value
|
|
30
|
+
*/
|
|
31
|
+
async function execWithTimeout(cmd, args, options = {}) {
|
|
32
|
+
const { timeout = DEFAULT_TIMEOUT, fallback = null } = options;
|
|
33
|
+
const hasFallback = Object.prototype.hasOwnProperty.call(options, 'fallback');
|
|
34
|
+
|
|
35
|
+
return new Promise(async (resolve, reject) => {
|
|
36
|
+
const timeoutId = setTimeout(() => {
|
|
37
|
+
logger.error(`Command timed out: ${cmd} ${args.join(' ')}`, { timeout });
|
|
38
|
+
if (hasFallback) {
|
|
39
|
+
logger.info('Using fallback value', { fallback });
|
|
40
|
+
resolve(fallback);
|
|
41
|
+
} else {
|
|
42
|
+
reject(new Error(`Command timed out after ${timeout}ms: ${cmd}`));
|
|
43
|
+
}
|
|
44
|
+
}, timeout);
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const result = await execFileAsync(cmd, args, { timeout });
|
|
48
|
+
clearTimeout(timeoutId);
|
|
49
|
+
resolve(result.stdout.trim());
|
|
50
|
+
} catch (err) {
|
|
51
|
+
clearTimeout(timeoutId);
|
|
52
|
+
logger.error(`Command failed: ${cmd}`, { error: err.message, args });
|
|
53
|
+
if (hasFallback) {
|
|
54
|
+
logger.info('Using fallback value', { fallback });
|
|
55
|
+
resolve(fallback);
|
|
56
|
+
} else {
|
|
57
|
+
reject(err);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
module.exports = { execWithTimeout };
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* URL Fetch Service
|
|
5
|
+
*
|
|
6
|
+
* Provides secure URL fetching with HTTPS validation and user confirmation.
|
|
7
|
+
* Only HTTPS URLs are allowed. HTTP, file, data, javascript, and vbscript protocols are blocked.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { URL } = require('url');
|
|
11
|
+
const { URLFetchError } = require('./context-errors.cjs');
|
|
12
|
+
|
|
13
|
+
const DEFAULT_TIMEOUT = 30000; // 30 seconds
|
|
14
|
+
const BLOCKED_PROTOCOLS = ['http:', 'file:', 'data:', 'javascript:', 'vbscript:'];
|
|
15
|
+
|
|
16
|
+
class URLValidator {
|
|
17
|
+
/**
|
|
18
|
+
* Validate a URL string
|
|
19
|
+
* @param {string} urlString - The URL to validate
|
|
20
|
+
* @returns {{valid: boolean, error?: string}} - Validation result
|
|
21
|
+
*/
|
|
22
|
+
static validate(urlString) {
|
|
23
|
+
if (!urlString || typeof urlString !== 'string') {
|
|
24
|
+
return { valid: false, error: 'URL is required' };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
const url = new URL(urlString);
|
|
29
|
+
|
|
30
|
+
// Check protocol
|
|
31
|
+
if (url.protocol !== 'https:') {
|
|
32
|
+
if (BLOCKED_PROTOCOLS.includes(url.protocol)) {
|
|
33
|
+
return {
|
|
34
|
+
valid: false,
|
|
35
|
+
error: `Protocol '${url.protocol}' is not allowed. Only HTTPS is permitted.`
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
valid: false,
|
|
40
|
+
error: `Invalid protocol '${url.protocol}'. Only HTTPS is allowed.`
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Check hostname exists
|
|
45
|
+
if (!url.hostname || url.hostname.trim() === '') {
|
|
46
|
+
return { valid: false, error: 'Invalid URL: missing hostname' };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Reject localhost URLs
|
|
50
|
+
if (url.hostname === 'localhost' ||
|
|
51
|
+
url.hostname === '127.0.0.1' ||
|
|
52
|
+
url.hostname === '::1' ||
|
|
53
|
+
url.hostname.endsWith('.localhost')) {
|
|
54
|
+
return {
|
|
55
|
+
valid: false,
|
|
56
|
+
error: 'Localhost URLs are not allowed. Use a publicly accessible HTTPS URL.'
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return { valid: true };
|
|
61
|
+
} catch (err) {
|
|
62
|
+
return {
|
|
63
|
+
valid: false,
|
|
64
|
+
error: `Invalid URL format: ${err.message}`
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
class URLFetchService {
|
|
71
|
+
/**
|
|
72
|
+
* Create a new URLFetchService instance
|
|
73
|
+
* @param {number} timeout - Request timeout in milliseconds (default: 30000)
|
|
74
|
+
*/
|
|
75
|
+
constructor(timeout = DEFAULT_TIMEOUT) {
|
|
76
|
+
this.timeout = timeout;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Validate a URL
|
|
81
|
+
* @param {string} urlString - The URL to validate
|
|
82
|
+
* @returns {{valid: boolean, error?: string}} - Validation result
|
|
83
|
+
*/
|
|
84
|
+
validateUrl(urlString) {
|
|
85
|
+
return URLValidator.validate(urlString);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Fetch content from a URL
|
|
90
|
+
* @param {string} url - The URL to fetch
|
|
91
|
+
* @returns {{content: string, contentType: string}} - Fetched content
|
|
92
|
+
* @throws {URLFetchError} - On fetch errors
|
|
93
|
+
*/
|
|
94
|
+
async fetchUrl(url) {
|
|
95
|
+
// Validate URL first
|
|
96
|
+
const validation = this.validateUrl(url);
|
|
97
|
+
if (!validation.valid) {
|
|
98
|
+
throw new URLFetchError(url, validation.error);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
// Create abort controller for timeout
|
|
103
|
+
const controller = new AbortController();
|
|
104
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
105
|
+
|
|
106
|
+
const response = await fetch(url, {
|
|
107
|
+
headers: {
|
|
108
|
+
'User-Agent': 'ez-agents/1.0'
|
|
109
|
+
},
|
|
110
|
+
signal: controller.signal,
|
|
111
|
+
redirect: 'follow'
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
clearTimeout(timeoutId);
|
|
115
|
+
|
|
116
|
+
// Check for HTTP errors
|
|
117
|
+
if (!response.ok) {
|
|
118
|
+
throw new URLFetchError(
|
|
119
|
+
url,
|
|
120
|
+
`HTTP ${response.status}: ${response.statusText}`
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Get content type
|
|
125
|
+
const contentType = response.headers.get('content-type') || 'text/plain';
|
|
126
|
+
|
|
127
|
+
// Get content
|
|
128
|
+
const content = await response.text();
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
content,
|
|
132
|
+
contentType
|
|
133
|
+
};
|
|
134
|
+
} catch (err) {
|
|
135
|
+
if (err.name === 'AbortError') {
|
|
136
|
+
throw new URLFetchError(url, `Request timeout after ${this.timeout}ms`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (err.name === 'URLFetchError') {
|
|
140
|
+
throw err;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
throw new URLFetchError(url, `Network error: ${err.message}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Prompt user for confirmation before fetching a URL
|
|
149
|
+
* @param {string} url - The URL to fetch
|
|
150
|
+
* @returns {Promise<boolean>} - True if user confirmed
|
|
151
|
+
*/
|
|
152
|
+
static async confirmUrlFetch(url) {
|
|
153
|
+
const readline = require('readline');
|
|
154
|
+
|
|
155
|
+
return new Promise((resolve) => {
|
|
156
|
+
const rl = readline.createInterface({
|
|
157
|
+
input: process.stdin,
|
|
158
|
+
output: process.stdout
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
rl.question(`Fetch ${url}? (y/n): `, (answer) => {
|
|
162
|
+
rl.close();
|
|
163
|
+
resolve(answer.toLowerCase() === 'y');
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
module.exports = URLFetchService;
|
|
170
|
+
module.exports.URLValidator = URLValidator;
|
|
@@ -270,11 +270,25 @@ async function cmdVerifyCommits(cwd, hashes, raw) {
|
|
|
270
270
|
const valid = [];
|
|
271
271
|
const invalid = [];
|
|
272
272
|
for (const hash of hashes) {
|
|
273
|
+
// Use git cat-file -t which supports both short and full hashes
|
|
274
|
+
// First try with the hash as-is (works for both short and full)
|
|
273
275
|
const result = await execGit(cwd, ['cat-file', '-t', hash]);
|
|
274
276
|
if (result.exitCode === 0 && result.stdout.trim() === 'commit') {
|
|
275
277
|
valid.push(hash);
|
|
276
278
|
} else {
|
|
277
|
-
|
|
279
|
+
// If that fails, try to resolve to full hash first
|
|
280
|
+
const resolveResult = await execGit(cwd, ['rev-parse', hash]);
|
|
281
|
+
if (resolveResult.exitCode === 0) {
|
|
282
|
+
const fullHash = resolveResult.stdout.trim();
|
|
283
|
+
const result2 = await execGit(cwd, ['cat-file', '-t', fullHash]);
|
|
284
|
+
if (result2.exitCode === 0 && result2.stdout.trim() === 'commit') {
|
|
285
|
+
valid.push(hash);
|
|
286
|
+
} else {
|
|
287
|
+
invalid.push(hash);
|
|
288
|
+
}
|
|
289
|
+
} else {
|
|
290
|
+
invalid.push(hash);
|
|
291
|
+
}
|
|
278
292
|
}
|
|
279
293
|
}
|
|
280
294
|
|