@lumpcode/core 0.0.12 → 0.0.14
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 +2 -2
- package/dist/helpers/executeStepsForContextList/main.d.ts +3 -3
- package/dist/helpers/executeStepsForContextList/main.d.ts.map +1 -1
- package/dist/helpers/getContextStatus/main.d.ts +3 -3
- package/dist/helpers/getContextStatus/main.d.ts.map +1 -1
- package/dist/helpers/getToDoContextList/main.d.ts +4 -4
- package/dist/helpers/getToDoContextList/main.d.ts.map +1 -1
- package/dist/index.cjs +123 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +123 -7
- package/dist/index.js.map +1 -1
- package/dist/types/BranchFn.d.ts +2 -2
- package/dist/types/BranchFn.d.ts.map +1 -1
- package/dist/types/CommandFn.d.ts +3 -3
- package/dist/types/CommandFn.d.ts.map +1 -1
- package/dist/types/ContextStatus.d.ts +1 -7
- package/dist/types/ContextStatus.d.ts.map +1 -1
- package/dist/types/GetContextListFn.d.ts +3 -3
- package/dist/types/GetContextListFn.d.ts.map +1 -1
- package/dist/types/GitCommitMessageFn.d.ts +3 -3
- package/dist/types/GitCommitMessageFn.d.ts.map +1 -1
- package/dist/types/HistoryEntry.d.ts +3 -3
- package/dist/types/HistoryEntry.d.ts.map +1 -1
- package/dist/types/PostCommandExecFn.d.ts +5 -4
- package/dist/types/PostCommandExecFn.d.ts.map +1 -1
- package/dist/types/PromptFn.d.ts +4 -4
- package/dist/types/PromptFn.d.ts.map +1 -1
- package/dist/types/SetupFn.d.ts +2 -2
- package/dist/types/SetupFn.d.ts.map +1 -1
- package/dist/types/Step.d.ts +6 -5
- package/dist/types/Step.d.ts.map +1 -1
- package/dist/types/Steps.d.ts +3 -1
- package/dist/types/Steps.d.ts.map +1 -1
- package/dist/types/TeardownFn.d.ts +2 -2
- package/dist/types/TeardownFn.d.ts.map +1 -1
- package/dist/usages/runLump/main.d.ts +9 -9
- package/dist/usages/runLump/main.d.ts.map +1 -1
- package/dist/utils/resolveSpawnExecutable/index.d.ts +1 -0
- package/dist/utils/resolveSpawnExecutable/index.d.ts.map +1 -1
- package/dist/utils/resolveSpawnExecutable/main.d.ts +4 -0
- package/dist/utils/resolveSpawnExecutable/main.d.ts.map +1 -1
- package/dist/utils/resolveSpawnExecutable/npmCmdShimFixture.d.ts +6 -0
- package/dist/utils/resolveSpawnExecutable/npmCmdShimFixture.d.ts.map +1 -0
- package/dist/utils/resolveSpawnExecutable/windowsNpmCmdShimBody.d.ts +6 -0
- package/dist/utils/resolveSpawnExecutable/windowsNpmCmdShimBody.d.ts.map +1 -0
- package/dist/utils/resolveSpawnExecutable/windowsNpmCmdShimFixture.d.ts +6 -0
- package/dist/utils/resolveSpawnExecutable/windowsNpmCmdShimFixture.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,6 @@ import { extname, dirname } from 'node:path';
|
|
|
6
6
|
import * as fs$1 from 'node:fs/promises';
|
|
7
7
|
import { readFile, mkdir, writeFile } from 'node:fs/promises';
|
|
8
8
|
import ignore from 'ignore';
|
|
9
|
-
import z from 'zod';
|
|
10
9
|
|
|
11
10
|
function set(object, path, value) {
|
|
12
11
|
const keys = Array.isArray(path) ? path : [path];
|
|
@@ -65,6 +64,10 @@ const DEFAULT_WINDOWS_PATHEXT = [
|
|
|
65
64
|
'.WSH',
|
|
66
65
|
'.MSC',
|
|
67
66
|
];
|
|
67
|
+
/** Matches a quoted script path using %dp0% / %~dp0 relative to a Windows .cmd shim. */
|
|
68
|
+
const WINDOWS_DP0_SCRIPT_RE = /"(?:%dp0%|%~dp0)\\?((?:[^"\r\n])+?\.(?:js|mjs|cjs))"/i;
|
|
69
|
+
/** Absolute Windows path to a Node script in quotes. */
|
|
70
|
+
const WINDOWS_ABS_SCRIPT_RE = /"([A-Za-z]:\\[^"\r\n]+\.(?:js|mjs|cjs))"/i;
|
|
68
71
|
function windowsPathext() {
|
|
69
72
|
const fromEnv = process.env.PATHEXT?.split(';').map((entry) => entry.trim()).filter(Boolean);
|
|
70
73
|
return fromEnv?.length ? fromEnv : DEFAULT_WINDOWS_PATHEXT;
|
|
@@ -130,9 +133,83 @@ function wrapWindowsCmdShim(resolvedPath, args) {
|
|
|
130
133
|
args: ['/d', '/s', '/c', resolvedPath, ...args],
|
|
131
134
|
};
|
|
132
135
|
}
|
|
136
|
+
function resolveWindowsJsPathFromShim(shimDir, relativeOrAbsolute) {
|
|
137
|
+
if (/^[A-Za-z]:[\\/]/.test(relativeOrAbsolute)) {
|
|
138
|
+
return path.resolve(relativeOrAbsolute);
|
|
139
|
+
}
|
|
140
|
+
// Normalize Windows separators so stubbed-win32 tests on POSIX still resolve.
|
|
141
|
+
const parts = relativeOrAbsolute.replace(/^[\\/]+/, '').split(/[/\\]+/).filter(Boolean);
|
|
142
|
+
return path.resolve(shimDir, ...parts);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Prefer a real Node binary — never a .cmd/.bat shim (those reintroduce cmd.exe),
|
|
146
|
+
* and never the host SEA/`lumpcode` binary via process.execPath.
|
|
147
|
+
* Returns bare `"node"` as last resort so spawn fails with ENOENT instead of
|
|
148
|
+
* silently falling back to cmd.exe after a Node entry was identified.
|
|
149
|
+
*/
|
|
150
|
+
function resolveNodeExecutable(preferredDir) {
|
|
151
|
+
if (preferredDir != null) {
|
|
152
|
+
const bundledNode = path.join(preferredDir, 'node.exe');
|
|
153
|
+
if (fileExists(bundledNode)) {
|
|
154
|
+
return bundledNode;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
for (const name of ['node.exe', 'node']) {
|
|
158
|
+
const found = resolveOnPath(name);
|
|
159
|
+
if (!found)
|
|
160
|
+
continue;
|
|
161
|
+
const ext = path.extname(found).toLowerCase();
|
|
162
|
+
if (ext === '.cmd' || ext === '.bat')
|
|
163
|
+
continue;
|
|
164
|
+
return found;
|
|
165
|
+
}
|
|
166
|
+
const base = path.basename(process.execPath).toLowerCase();
|
|
167
|
+
if (base === 'node' || base === 'node.exe') {
|
|
168
|
+
return process.execPath;
|
|
169
|
+
}
|
|
170
|
+
return 'node';
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Parse an npm/yarn-style Windows `.cmd` shim to `node <script.js>`.
|
|
174
|
+
* Returns null only when the file is not a recognizable Node cmd-shim
|
|
175
|
+
* (caller may wrap with cmd.exe). Once a script path is found, never falls
|
|
176
|
+
* back to cmd.exe — missing Node uses bare `"node"` for a clear spawn failure.
|
|
177
|
+
*/
|
|
178
|
+
function tryUnwrapWindowsNpmCmdShim(cmdPath) {
|
|
179
|
+
let body;
|
|
180
|
+
try {
|
|
181
|
+
body = fs.readFileSync(cmdPath, 'utf8');
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
const shimDir = path.dirname(cmdPath);
|
|
187
|
+
const lines = body.split(/\r?\n/);
|
|
188
|
+
// Windows npm-cmd-shim ends with `%*` pass-through; prefer that line for the script path.
|
|
189
|
+
const passThroughLine = [...lines].reverse().find((line) => /%\*\s*$/.test(line));
|
|
190
|
+
const searchOrder = passThroughLine != null ? [passThroughLine, body] : [body];
|
|
191
|
+
for (const searchIn of searchOrder) {
|
|
192
|
+
const dp0Match = searchIn.match(WINDOWS_DP0_SCRIPT_RE);
|
|
193
|
+
if (dp0Match?.[1]) {
|
|
194
|
+
const candidate = resolveWindowsJsPathFromShim(shimDir, dp0Match[1]);
|
|
195
|
+
if (fileExists(candidate)) {
|
|
196
|
+
return { scriptPath: candidate };
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const absMatch = searchIn.match(WINDOWS_ABS_SCRIPT_RE);
|
|
200
|
+
if (absMatch?.[1] && fileExists(absMatch[1])) {
|
|
201
|
+
return { scriptPath: absMatch[1] };
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
133
206
|
/**
|
|
134
207
|
* Resolves bare executable names on Windows so npm-style `.cmd` shims and
|
|
135
208
|
* extensionless Node entrypoints work with `child_process.spawn` (no shell).
|
|
209
|
+
*
|
|
210
|
+
* For Node agent CLIs installed via npm (copilot.cmd, cursor-agent.cmd, …),
|
|
211
|
+
* unwraps the shim to `node <entry.js> …args` so prompt argv is not mangled by
|
|
212
|
+
* cmd.exe / `%*`. Unrecognized `.cmd`/`.bat` files still wrap through cmd.exe.
|
|
136
213
|
*/
|
|
137
214
|
function resolveSpawnExecutable(executable, args) {
|
|
138
215
|
if (process.platform !== 'win32') {
|
|
@@ -153,17 +230,52 @@ function resolveSpawnExecutable(executable, args) {
|
|
|
153
230
|
}
|
|
154
231
|
const ext = path.extname(resolved).toLowerCase();
|
|
155
232
|
if (ext === '.cmd' || ext === '.bat') {
|
|
233
|
+
const unwrapped = tryUnwrapWindowsNpmCmdShim(resolved);
|
|
234
|
+
if (unwrapped != null) {
|
|
235
|
+
return {
|
|
236
|
+
executable: resolveNodeExecutable(path.dirname(resolved)),
|
|
237
|
+
args: [unwrapped.scriptPath, ...args],
|
|
238
|
+
};
|
|
239
|
+
}
|
|
156
240
|
return wrapWindowsCmdShim(resolved, args);
|
|
157
241
|
}
|
|
158
242
|
if (isNodeScript(resolved)) {
|
|
159
243
|
return {
|
|
160
|
-
executable:
|
|
244
|
+
executable: resolveNodeExecutable(path.dirname(resolved)),
|
|
161
245
|
args: [resolved, ...args],
|
|
162
246
|
};
|
|
163
247
|
}
|
|
164
248
|
return { executable: resolved, args };
|
|
165
249
|
}
|
|
166
250
|
|
|
251
|
+
/**
|
|
252
|
+
* Minimal Windows npm-cmd-shim `.cmd` body (modern `"%_prog%"` + `"%dp0%\\…\\.js" %*` form).
|
|
253
|
+
* Shared by core spawn tests and CLI e2e path-agent install — do not duplicate.
|
|
254
|
+
*/
|
|
255
|
+
function windowsNpmCmdShimBody(relativeJsFromShimDir) {
|
|
256
|
+
const target = relativeJsFromShimDir.replace(/\//g, '\\');
|
|
257
|
+
return [
|
|
258
|
+
'@ECHO off',
|
|
259
|
+
'GOTO start',
|
|
260
|
+
':find_dp0',
|
|
261
|
+
'SET dp0=%~dp0',
|
|
262
|
+
'EXIT /b',
|
|
263
|
+
':start',
|
|
264
|
+
'SETLOCAL',
|
|
265
|
+
'CALL :find_dp0',
|
|
266
|
+
'',
|
|
267
|
+
'IF EXIST "%dp0%\\node.exe" (',
|
|
268
|
+
' SET "_prog=%dp0%\\node.exe"',
|
|
269
|
+
') ELSE (',
|
|
270
|
+
' SET "_prog=node"',
|
|
271
|
+
' SET PATHEXT=%PATHEXT:;.JS;=;%',
|
|
272
|
+
')',
|
|
273
|
+
'',
|
|
274
|
+
`endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & set PATHEXT=%PATHEXT:;.JS;=;% & "%_prog%" "%dp0%\\${target}" %*`,
|
|
275
|
+
'',
|
|
276
|
+
].join('\r\n');
|
|
277
|
+
}
|
|
278
|
+
|
|
167
279
|
function formatMessage(prefix, message) {
|
|
168
280
|
if (!prefix)
|
|
169
281
|
return message;
|
|
@@ -3591,7 +3703,10 @@ async function executeStepsForContextList({ baseBranch, branchFn, lumpVariables,
|
|
|
3591
3703
|
}
|
|
3592
3704
|
}
|
|
3593
3705
|
if (postCommandExecFn) {
|
|
3594
|
-
await postCommandExecFn(postCommandExecFnInput);
|
|
3706
|
+
const returnedSteps = await postCommandExecFn(postCommandExecFnInput);
|
|
3707
|
+
if (returnedSteps != null && returnedSteps.length > 0) {
|
|
3708
|
+
await walkAndExecuteSteps(returnedSteps, nextCallHeadIndex);
|
|
3709
|
+
}
|
|
3595
3710
|
}
|
|
3596
3711
|
}
|
|
3597
3712
|
}
|
|
@@ -3730,7 +3845,8 @@ async function scanDirectory({ dirPath, allPaths, gitignoresMap, projectRoot, lo
|
|
|
3730
3845
|
}
|
|
3731
3846
|
|
|
3732
3847
|
async function getContextStatus(params) {
|
|
3733
|
-
const { contextName, gitCommitMessageFn, projectRoot, baseBranch, lumpVariables
|
|
3848
|
+
const { contextName, gitCommitMessageFn, projectRoot, baseBranch, lumpVariables: lumpVariablesInput, contextVariables = {}, remoteName = "origin", logger, } = params;
|
|
3849
|
+
const lumpVariables = (lumpVariablesInput ?? {});
|
|
3734
3850
|
const commitMessage = gitCommitMessageFn({
|
|
3735
3851
|
context: { name: contextName, variables: contextVariables },
|
|
3736
3852
|
lumpVariables,
|
|
@@ -3850,7 +3966,6 @@ async function getToDoContextList(params) {
|
|
|
3850
3966
|
}
|
|
3851
3967
|
|
|
3852
3968
|
const contextStatus = ['toDo', 'branchPushed', 'finished'];
|
|
3853
|
-
const contextStatusSchema = z.enum(contextStatus);
|
|
3854
3969
|
|
|
3855
3970
|
const defaultGitCommitMessageFn = ({ context }) => {
|
|
3856
3971
|
return `LUMP:${context.name}`;
|
|
@@ -3900,7 +4015,8 @@ const defaultSetupWorkspaceFnWithWorktree = async (input) => {
|
|
|
3900
4015
|
};
|
|
3901
4016
|
|
|
3902
4017
|
async function runLump(input) {
|
|
3903
|
-
const { baseBranch, branchFn, lumpVariables
|
|
4018
|
+
const { baseBranch, branchFn, lumpVariables: lumpVariablesInput, getContextListFn, gitAddCommandFn = defaultGitAddCommandFn, gitCommitCommandFn = defaultGitCommitCommandFn, gitCommitMessageFn = defaultGitCommitMessageFn, gitPushCommandFn = defaultGitPushCommandFn, numberOfContextsPerBranch = 1, projectRoot, steps, setupFn = () => ({ contextRunState: {} }), setupWorkspaceFn = defaultSetupWorkspaceFn, teardownFn = () => undefined, teardownWorkspaceFn = defaultTeardownWorkspaceFn, getKeepHistoryFilePathFn = () => undefined, logger: loggerInput, } = input;
|
|
4019
|
+
const lumpVariables = (lumpVariablesInput ?? {});
|
|
3904
4020
|
const logger = loggerInput ?? createConsoleLogger({});
|
|
3905
4021
|
const contextListToDoResult = await getToDoContextList({
|
|
3906
4022
|
getContextListFn,
|
|
@@ -3954,5 +4070,5 @@ async function runLump(input) {
|
|
|
3954
4070
|
});
|
|
3955
4071
|
}
|
|
3956
4072
|
|
|
3957
|
-
export { appendHistoryEntry, collectStepsForContext, contextStatus,
|
|
4073
|
+
export { appendHistoryEntry, collectStepsForContext, contextStatus, createConsoleLogger, defaultGitAddCommandFn, defaultGitCommitCommandFn, defaultGitCommitMessageFn, defaultGitPushCommandFn, defaultSetupWorkspaceFn, defaultSetupWorkspaceFnWithWorktree, defaultTeardownWorkspaceFn, defaultTeardownWorkspaceFnWithWorktree, execAsync, execBinary, executeStepsForContextList, failure, formatExecFailureMessage, getCodeBasePaths, getContextStatus, getToDoContextList, historyFormatFromPath, parseGitLogHashSubjectLines, pathExists, readHistoryFile, resolveSpawnExecutable, runLump, set, shellSingleQuote, success, validateContextListNames, windowsNpmCmdShimBody, writeHistoryFile };
|
|
3958
4074
|
//# sourceMappingURL=index.js.map
|