@linzumi/cli 0.0.96-beta → 0.0.97-beta
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 +1 -1
- package/dist/index.js +575 -77
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -125,25 +125,31 @@ function discoverCurrentGitProject(args) {
|
|
|
125
125
|
const responsiveness = args.placeResponsiveness;
|
|
126
126
|
const candidates = /* @__PURE__ */ new Map();
|
|
127
127
|
const searchStats = [];
|
|
128
|
-
const
|
|
129
|
-
const
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
128
|
+
const selectedScanRoots = uniqueStrings(args.selectedScanRoots ?? []);
|
|
129
|
+
const selectedScanRootSet = new Set(selectedScanRoots);
|
|
130
|
+
const sourceRoots = args.sourceRoots ?? defaultLocalProjectSourceRoots({
|
|
131
|
+
cwd: args.cwd,
|
|
132
|
+
homeDir: args.homeDir,
|
|
133
|
+
selectedScanRoots
|
|
134
|
+
});
|
|
135
|
+
const sourceRootMaxDepth = normalizeSourceRootMaxDepth(
|
|
136
|
+
args.sourceRootMaxDepth
|
|
137
|
+
);
|
|
138
|
+
const sourceRootScanDeadlineMs = Date.now() + normalizeSourceRootScanBudgetMs(args.sourceRootScanBudgetMs);
|
|
139
|
+
const createSourceRootScanBudget = () => ({
|
|
140
|
+
deadlineMs: sourceRootScanDeadlineMs,
|
|
141
|
+
maxDirectoryVisits: normalizeSourceRootMaxDirectoryVisits(
|
|
142
|
+
args.sourceRootMaxDirectoryVisits
|
|
143
|
+
),
|
|
144
|
+
maxProjectEnrichments: normalizeSourceRootMaxProjectEnrichments(
|
|
145
|
+
args.sourceRootMaxProjectEnrichments
|
|
146
|
+
),
|
|
147
|
+
directoryVisits: 0,
|
|
148
|
+
projectEnrichments: 0,
|
|
149
|
+
exhausted: false
|
|
144
150
|
});
|
|
145
|
-
const
|
|
146
|
-
let placesSearched =
|
|
151
|
+
const defaultSourceRootScanBudget = createSourceRootScanBudget();
|
|
152
|
+
let placesSearched = 0;
|
|
147
153
|
const scanBudgetMs = projectScanBudgetMs();
|
|
148
154
|
for (const sourceRoot of sourceRoots) {
|
|
149
155
|
if (Date.now() - startedAtMs >= scanBudgetMs) {
|
|
@@ -158,6 +164,19 @@ function discoverCurrentGitProject(args) {
|
|
|
158
164
|
continue;
|
|
159
165
|
}
|
|
160
166
|
const sourceRootStartedAtMs = Date.now();
|
|
167
|
+
const isSelectedScanRoot = selectedScanRootSet.has(sourceRoot);
|
|
168
|
+
const sourceRootScanBudget = isSelectedScanRoot ? createSourceRootScanBudget() : defaultSourceRootScanBudget;
|
|
169
|
+
if (isSourceRootScanBudgetExhausted(sourceRootScanBudget)) {
|
|
170
|
+
searchStats.push({
|
|
171
|
+
place: sourceRoot,
|
|
172
|
+
source: "git",
|
|
173
|
+
duration_ms: Date.now() - sourceRootStartedAtMs,
|
|
174
|
+
result_count: 0,
|
|
175
|
+
scan_budget_exhausted: true
|
|
176
|
+
});
|
|
177
|
+
placesSearched += 1;
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
161
180
|
const rootResponsive = isPlaceResponsive(sourceRoot, responsiveness);
|
|
162
181
|
if (!rootResponsive) {
|
|
163
182
|
searchStats.push({
|
|
@@ -170,25 +189,60 @@ function discoverCurrentGitProject(args) {
|
|
|
170
189
|
placesSearched += 1;
|
|
171
190
|
continue;
|
|
172
191
|
}
|
|
173
|
-
|
|
192
|
+
const directoryExists2 = isDirectory(sourceRoot);
|
|
193
|
+
if (!directoryExists2) {
|
|
194
|
+
if (isSelectedScanRoot) {
|
|
195
|
+
searchStats.push({
|
|
196
|
+
place: sourceRoot,
|
|
197
|
+
source: "git",
|
|
198
|
+
duration_ms: Date.now() - sourceRootStartedAtMs,
|
|
199
|
+
result_count: 0,
|
|
200
|
+
missing_directory: true
|
|
201
|
+
});
|
|
202
|
+
placesSearched += 1;
|
|
203
|
+
}
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
const foundInRoot = discoverGitWorktreesInSourceRoot(
|
|
207
|
+
sourceRoot,
|
|
208
|
+
sourceRootMaxDepth,
|
|
209
|
+
responsiveness,
|
|
210
|
+
sourceRootScanBudget
|
|
211
|
+
);
|
|
212
|
+
const enrichedProjectCount = enrichSourceRootProjects(
|
|
213
|
+
candidates,
|
|
214
|
+
foundInRoot,
|
|
215
|
+
sourceRootScanBudget
|
|
216
|
+
);
|
|
217
|
+
searchStats.push({
|
|
218
|
+
place: sourceRoot,
|
|
219
|
+
source: "git",
|
|
220
|
+
duration_ms: Date.now() - sourceRootStartedAtMs,
|
|
221
|
+
result_count: enrichedProjectCount,
|
|
222
|
+
scan_budget_exhausted: sourceRootScanBudget.exhausted ? true : void 0
|
|
223
|
+
});
|
|
224
|
+
placesSearched += 1;
|
|
225
|
+
if (sourceRootScanBudget.exhausted) {
|
|
174
226
|
continue;
|
|
175
227
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
228
|
+
}
|
|
229
|
+
if (args.includeRuntimeCwdHint !== false) {
|
|
230
|
+
const cwdResponsive = isPlaceResponsive(args.cwd, responsiveness);
|
|
231
|
+
const gitStartedAtMs = Date.now();
|
|
232
|
+
const topLevel = cwdResponsive ? gitOutput(args.cwd, ["rev-parse", "--show-toplevel"]) : void 0;
|
|
233
|
+
const gitDurationMs = Date.now() - gitStartedAtMs;
|
|
234
|
+
if (topLevel !== void 0) {
|
|
235
|
+
mergeRuntimeCwdCandidate(
|
|
179
236
|
candidates,
|
|
180
|
-
projectCandidateFromWorktree(
|
|
181
|
-
worktreePath,
|
|
182
|
-
"local_source_root",
|
|
183
|
-
topLevel
|
|
184
|
-
)
|
|
237
|
+
projectCandidateFromWorktree(topLevel, "runtime_cwd_hint", topLevel)
|
|
185
238
|
);
|
|
186
239
|
}
|
|
187
240
|
searchStats.push({
|
|
188
|
-
place:
|
|
241
|
+
place: args.cwd,
|
|
189
242
|
source: "git",
|
|
190
|
-
duration_ms:
|
|
191
|
-
result_count:
|
|
243
|
+
duration_ms: gitDurationMs,
|
|
244
|
+
result_count: topLevel === void 0 ? 0 : 1,
|
|
245
|
+
skipped_unresponsive: cwdResponsive ? void 0 : true
|
|
192
246
|
});
|
|
193
247
|
placesSearched += 1;
|
|
194
248
|
}
|
|
@@ -261,16 +315,60 @@ function mergeCandidate(candidates, candidate) {
|
|
|
261
315
|
const existing = candidates.get(candidate.importKey);
|
|
262
316
|
if (existing === void 0 || shouldReplaceCandidate(existing, candidate)) {
|
|
263
317
|
candidates.set(candidate.importKey, candidate);
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
const currentWorktreePath = candidate.metadata.current_worktree_path;
|
|
321
|
+
if (existing.metadata.current_worktree_path === void 0 && typeof currentWorktreePath === "string") {
|
|
322
|
+
candidates.set(candidate.importKey, {
|
|
323
|
+
...existing,
|
|
324
|
+
metadata: {
|
|
325
|
+
...existing.metadata,
|
|
326
|
+
current_worktree_path: currentWorktreePath
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
function mergeRuntimeCwdCandidate(candidates, candidate) {
|
|
332
|
+
if (candidate === void 0) {
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
const existing = candidates.get(candidate.importKey);
|
|
336
|
+
if (existing !== void 0 && existing.metadata.discovery_method === "local_source_root" && existing.path !== candidate.path) {
|
|
337
|
+
candidates.set(candidate.importKey, {
|
|
338
|
+
...candidate,
|
|
339
|
+
metadata: {
|
|
340
|
+
...candidate.metadata,
|
|
341
|
+
discovery_method: "local_source_root"
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
return;
|
|
264
345
|
}
|
|
346
|
+
mergeCandidate(candidates, candidate);
|
|
347
|
+
}
|
|
348
|
+
function enrichSourceRootProjects(candidates, worktreePaths, scanBudget) {
|
|
349
|
+
return worktreePaths.reduce((enrichedCount, worktreePath) => {
|
|
350
|
+
if (!consumeSourceRootProjectEnrichmentBudget(scanBudget)) {
|
|
351
|
+
return enrichedCount;
|
|
352
|
+
}
|
|
353
|
+
const candidate = projectCandidateFromWorktree(
|
|
354
|
+
worktreePath,
|
|
355
|
+
"local_source_root"
|
|
356
|
+
);
|
|
357
|
+
if (candidate === void 0) {
|
|
358
|
+
return enrichedCount;
|
|
359
|
+
}
|
|
360
|
+
mergeCandidate(candidates, candidate);
|
|
361
|
+
return enrichedCount + 1;
|
|
362
|
+
}, 0);
|
|
265
363
|
}
|
|
266
364
|
function shouldReplaceCandidate(existing, candidate) {
|
|
267
365
|
const existingMethod = existing.metadata.discovery_method;
|
|
268
366
|
const candidateMethod = candidate.metadata.discovery_method;
|
|
269
|
-
if (existingMethod === "
|
|
270
|
-
return
|
|
367
|
+
if (existingMethod === "runtime_cwd_hint") {
|
|
368
|
+
return candidateMethod !== "runtime_cwd_hint";
|
|
271
369
|
}
|
|
272
|
-
if (candidateMethod === "
|
|
273
|
-
return
|
|
370
|
+
if (candidateMethod === "runtime_cwd_hint") {
|
|
371
|
+
return false;
|
|
274
372
|
}
|
|
275
373
|
const existingActivity = Date.parse(existing.activityAt ?? "");
|
|
276
374
|
const candidateActivity = Date.parse(candidate.activityAt ?? "");
|
|
@@ -296,32 +394,91 @@ function compareProjectCandidates(left, right) {
|
|
|
296
394
|
}
|
|
297
395
|
return left.displayName.localeCompare(right.displayName);
|
|
298
396
|
}
|
|
299
|
-
function discoverGitWorktreesInSourceRoot(sourceRoot) {
|
|
397
|
+
function discoverGitWorktreesInSourceRoot(sourceRoot, maxDepth, responsiveness, scanBudget) {
|
|
300
398
|
if (!isDirectory(sourceRoot)) {
|
|
301
399
|
return [];
|
|
302
400
|
}
|
|
401
|
+
return uniqueStrings(
|
|
402
|
+
discoverGitWorktreesBelow(sourceRoot, maxDepth, responsiveness, scanBudget)
|
|
403
|
+
).sort();
|
|
404
|
+
}
|
|
405
|
+
function discoverGitWorktreesBelow(directory, depthRemaining, responsiveness, scanBudget) {
|
|
406
|
+
if (!consumeSourceRootScanBudget(scanBudget)) {
|
|
407
|
+
return [];
|
|
408
|
+
}
|
|
409
|
+
if (depthRemaining < 0) {
|
|
410
|
+
return [];
|
|
411
|
+
}
|
|
412
|
+
if (isGitWorktreeRoot(directory)) {
|
|
413
|
+
return [directory];
|
|
414
|
+
}
|
|
415
|
+
if (depthRemaining === 0) {
|
|
416
|
+
return [];
|
|
417
|
+
}
|
|
418
|
+
let entries;
|
|
303
419
|
try {
|
|
304
|
-
|
|
305
|
-
if (!entry.isDirectory()) {
|
|
306
|
-
return [];
|
|
307
|
-
}
|
|
308
|
-
const candidatePath = join(sourceRoot, entry.name);
|
|
309
|
-
return isGitWorktreeRoot(candidatePath) ? [candidatePath] : [];
|
|
310
|
-
}).sort();
|
|
420
|
+
entries = readdirSync(directory, { withFileTypes: true });
|
|
311
421
|
} catch (_error) {
|
|
312
422
|
return [];
|
|
313
423
|
}
|
|
424
|
+
return entries.flatMap((entry) => {
|
|
425
|
+
if (!entry.isDirectory()) {
|
|
426
|
+
return [];
|
|
427
|
+
}
|
|
428
|
+
if (ignoredSourceRootDirectoryNames.has(entry.name)) {
|
|
429
|
+
return [];
|
|
430
|
+
}
|
|
431
|
+
const childPath = join(directory, entry.name);
|
|
432
|
+
if (isSourceRootScanBudgetExhausted(scanBudget)) {
|
|
433
|
+
return [];
|
|
434
|
+
}
|
|
435
|
+
if (!isPlaceResponsive(childPath, responsiveness)) {
|
|
436
|
+
return [];
|
|
437
|
+
}
|
|
438
|
+
return discoverGitWorktreesBelow(
|
|
439
|
+
childPath,
|
|
440
|
+
depthRemaining - 1,
|
|
441
|
+
responsiveness,
|
|
442
|
+
scanBudget
|
|
443
|
+
);
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
function consumeSourceRootScanBudget(scanBudget) {
|
|
447
|
+
if (isSourceRootScanBudgetExhausted(scanBudget)) {
|
|
448
|
+
return false;
|
|
449
|
+
}
|
|
450
|
+
scanBudget.directoryVisits += 1;
|
|
451
|
+
return true;
|
|
452
|
+
}
|
|
453
|
+
function consumeSourceRootProjectEnrichmentBudget(scanBudget) {
|
|
454
|
+
if (Date.now() >= scanBudget.deadlineMs || scanBudget.projectEnrichments >= scanBudget.maxProjectEnrichments) {
|
|
455
|
+
scanBudget.exhausted = true;
|
|
456
|
+
return false;
|
|
457
|
+
}
|
|
458
|
+
scanBudget.projectEnrichments += 1;
|
|
459
|
+
return true;
|
|
460
|
+
}
|
|
461
|
+
function isSourceRootScanBudgetExhausted(scanBudget) {
|
|
462
|
+
if (scanBudget.exhausted) {
|
|
463
|
+
return true;
|
|
464
|
+
}
|
|
465
|
+
if (Date.now() >= scanBudget.deadlineMs || scanBudget.directoryVisits >= scanBudget.maxDirectoryVisits || scanBudget.projectEnrichments >= scanBudget.maxProjectEnrichments) {
|
|
466
|
+
scanBudget.exhausted = true;
|
|
467
|
+
return true;
|
|
468
|
+
}
|
|
469
|
+
return false;
|
|
314
470
|
}
|
|
315
471
|
function isGitWorktreeRoot(path2) {
|
|
316
472
|
return existsSync(join(path2, ".git"));
|
|
317
473
|
}
|
|
318
|
-
function defaultLocalProjectSourceRoots(
|
|
319
|
-
if (cwd === dirname(cwd)) {
|
|
474
|
+
function defaultLocalProjectSourceRoots(args) {
|
|
475
|
+
if (args.cwd === dirname(args.cwd)) {
|
|
320
476
|
return [];
|
|
321
477
|
}
|
|
322
478
|
return uniqueStrings([
|
|
323
|
-
...
|
|
324
|
-
...
|
|
479
|
+
...homeSourceRoots(args.homeDir),
|
|
480
|
+
...args.selectedScanRoots ?? [],
|
|
481
|
+
...ancestorSourceRoots(args.cwd),
|
|
325
482
|
...externalVolumeSourceRoots()
|
|
326
483
|
]);
|
|
327
484
|
}
|
|
@@ -344,8 +501,8 @@ function ancestorSourceRoots(cwd) {
|
|
|
344
501
|
}
|
|
345
502
|
return roots;
|
|
346
503
|
}
|
|
347
|
-
function homeSourceRoots() {
|
|
348
|
-
const home = homedir();
|
|
504
|
+
function homeSourceRoots(homeDir) {
|
|
505
|
+
const home = homeDir ?? homedir();
|
|
349
506
|
return [
|
|
350
507
|
"code",
|
|
351
508
|
"src",
|
|
@@ -385,6 +542,42 @@ function isDirectory(path2) {
|
|
|
385
542
|
return false;
|
|
386
543
|
}
|
|
387
544
|
}
|
|
545
|
+
function normalizeSourceRootMaxDepth(value) {
|
|
546
|
+
if (value === void 0) {
|
|
547
|
+
return defaultSourceRootMaxDepth;
|
|
548
|
+
}
|
|
549
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
550
|
+
return defaultSourceRootMaxDepth;
|
|
551
|
+
}
|
|
552
|
+
return Math.floor(value);
|
|
553
|
+
}
|
|
554
|
+
function normalizeSourceRootScanBudgetMs(value) {
|
|
555
|
+
if (value === void 0) {
|
|
556
|
+
return defaultSourceRootScanBudgetMs;
|
|
557
|
+
}
|
|
558
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
559
|
+
return defaultSourceRootScanBudgetMs;
|
|
560
|
+
}
|
|
561
|
+
return Math.floor(value);
|
|
562
|
+
}
|
|
563
|
+
function normalizeSourceRootMaxDirectoryVisits(value) {
|
|
564
|
+
if (value === void 0) {
|
|
565
|
+
return defaultSourceRootMaxDirectoryVisits;
|
|
566
|
+
}
|
|
567
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
568
|
+
return defaultSourceRootMaxDirectoryVisits;
|
|
569
|
+
}
|
|
570
|
+
return Math.floor(value);
|
|
571
|
+
}
|
|
572
|
+
function normalizeSourceRootMaxProjectEnrichments(value) {
|
|
573
|
+
if (value === void 0) {
|
|
574
|
+
return defaultSourceRootMaxProjectEnrichments;
|
|
575
|
+
}
|
|
576
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
577
|
+
return defaultSourceRootMaxProjectEnrichments;
|
|
578
|
+
}
|
|
579
|
+
return Math.floor(value);
|
|
580
|
+
}
|
|
388
581
|
function uniqueStrings(values) {
|
|
389
582
|
return Array.from(new Set(values));
|
|
390
583
|
}
|
|
@@ -432,13 +625,29 @@ function compactJsonObject(value) {
|
|
|
432
625
|
})
|
|
433
626
|
);
|
|
434
627
|
}
|
|
435
|
-
var worktreePathSampleLimit, gitSpawnTimeoutMs, defaultProjectScanBudgetMs;
|
|
628
|
+
var worktreePathSampleLimit, gitSpawnTimeoutMs, defaultSourceRootMaxDepth, defaultSourceRootScanBudgetMs, defaultSourceRootMaxDirectoryVisits, defaultSourceRootMaxProjectEnrichments, ignoredSourceRootDirectoryNames, defaultProjectScanBudgetMs;
|
|
436
629
|
var init_onboardingProjectDiscovery = __esm({
|
|
437
630
|
"src/onboardingProjectDiscovery.ts"() {
|
|
438
631
|
"use strict";
|
|
439
632
|
init_onboardingPlaceResponsiveness();
|
|
440
633
|
worktreePathSampleLimit = 25;
|
|
441
634
|
gitSpawnTimeoutMs = 4e3;
|
|
635
|
+
defaultSourceRootMaxDepth = 4;
|
|
636
|
+
defaultSourceRootScanBudgetMs = 2e4;
|
|
637
|
+
defaultSourceRootMaxDirectoryVisits = 5e3;
|
|
638
|
+
defaultSourceRootMaxProjectEnrichments = 100;
|
|
639
|
+
ignoredSourceRootDirectoryNames = /* @__PURE__ */ new Set([
|
|
640
|
+
".cache",
|
|
641
|
+
".git",
|
|
642
|
+
".next",
|
|
643
|
+
".pnpm-store",
|
|
644
|
+
".turbo",
|
|
645
|
+
"build",
|
|
646
|
+
"dist",
|
|
647
|
+
"Library",
|
|
648
|
+
"node_modules",
|
|
649
|
+
"target"
|
|
650
|
+
]);
|
|
442
651
|
defaultProjectScanBudgetMs = 2e4;
|
|
443
652
|
}
|
|
444
653
|
});
|
|
@@ -1115,7 +1324,27 @@ async function runOnboardingDiscoveryChildRole(kind, stdin, stdout) {
|
|
|
1115
1324
|
if (kind === "projects") {
|
|
1116
1325
|
const { discoverCurrentGitProject: discoverCurrentGitProject2 } = await Promise.resolve().then(() => (init_onboardingProjectDiscovery(), onboardingProjectDiscovery_exports));
|
|
1117
1326
|
const cwd = typeof args.cwd === "string" ? args.cwd : process.cwd();
|
|
1118
|
-
|
|
1327
|
+
const homeDir = typeof args.homeDir === "string" ? args.homeDir : void 0;
|
|
1328
|
+
const sourceRoots = Array.isArray(args.sourceRoots) ? args.sourceRoots.filter(
|
|
1329
|
+
(path2) => typeof path2 === "string"
|
|
1330
|
+
) : void 0;
|
|
1331
|
+
const selectedScanRoots = Array.isArray(args.selectedScanRoots) ? args.selectedScanRoots.filter(
|
|
1332
|
+
(path2) => typeof path2 === "string"
|
|
1333
|
+
) : void 0;
|
|
1334
|
+
const sourceRootMaxDepth = typeof args.sourceRootMaxDepth === "number" ? args.sourceRootMaxDepth : void 0;
|
|
1335
|
+
const includeRuntimeCwdHint = typeof args.includeRuntimeCwdHint === "boolean" ? args.includeRuntimeCwdHint : void 0;
|
|
1336
|
+
stdout.write(
|
|
1337
|
+
JSON.stringify(
|
|
1338
|
+
discoverCurrentGitProject2({
|
|
1339
|
+
cwd,
|
|
1340
|
+
homeDir,
|
|
1341
|
+
sourceRoots,
|
|
1342
|
+
selectedScanRoots,
|
|
1343
|
+
includeRuntimeCwdHint,
|
|
1344
|
+
sourceRootMaxDepth
|
|
1345
|
+
})
|
|
1346
|
+
)
|
|
1347
|
+
);
|
|
1119
1348
|
return 0;
|
|
1120
1349
|
}
|
|
1121
1350
|
if (kind === "conversations") {
|
|
@@ -7269,6 +7498,18 @@ function dequeuePendingKandanMessage(queue) {
|
|
|
7269
7498
|
compactPendingKandanMessageQueue(queue);
|
|
7270
7499
|
return message;
|
|
7271
7500
|
}
|
|
7501
|
+
function drainAllPendingKandanMessages(queue) {
|
|
7502
|
+
const drained = [];
|
|
7503
|
+
for (let index = queue.head; index < queue.items.length; index += 1) {
|
|
7504
|
+
const message = queue.items[index];
|
|
7505
|
+
if (message !== void 0) {
|
|
7506
|
+
drained.push(message);
|
|
7507
|
+
}
|
|
7508
|
+
}
|
|
7509
|
+
queue.items = [];
|
|
7510
|
+
queue.head = 0;
|
|
7511
|
+
return drained;
|
|
7512
|
+
}
|
|
7272
7513
|
function requeuePendingKandanMessageFront(queue, message) {
|
|
7273
7514
|
if (queue.head > 0) {
|
|
7274
7515
|
queue.head = queue.head - 1;
|
|
@@ -7278,7 +7519,10 @@ function requeuePendingKandanMessageFront(queue, message) {
|
|
|
7278
7519
|
queue.items.unshift(message);
|
|
7279
7520
|
}
|
|
7280
7521
|
function interruptPendingKandanMessages(queue, throughSeq) {
|
|
7281
|
-
const result = interruptQueuedMessages(
|
|
7522
|
+
const result = interruptQueuedMessages(
|
|
7523
|
+
pendingKandanMessages(queue),
|
|
7524
|
+
throughSeq
|
|
7525
|
+
);
|
|
7282
7526
|
if (result.ok) {
|
|
7283
7527
|
replacePendingKandanMessages(queue, result.queue);
|
|
7284
7528
|
}
|
|
@@ -8997,6 +9241,7 @@ function initialChannelSessionState(cursor, rootSeq, kandanThreadId, codexThread
|
|
|
8997
9241
|
failedSeqs: /* @__PURE__ */ new Map(),
|
|
8998
9242
|
drainInFlight: false,
|
|
8999
9243
|
drainRequested: false,
|
|
9244
|
+
deadWorkerRebuildAttempts: 0,
|
|
9000
9245
|
boundStartTimeout: false,
|
|
9001
9246
|
fusedQueuedSeqs: /* @__PURE__ */ new Map(),
|
|
9002
9247
|
reconnectRetryTimer: void 0,
|
|
@@ -10568,6 +10813,9 @@ async function drainKandanMessageQueue(args, state, payloadContext) {
|
|
|
10568
10813
|
}
|
|
10569
10814
|
}
|
|
10570
10815
|
async function drainKandanMessageQueueOnce(args, state, payloadContext) {
|
|
10816
|
+
if (await rebuildIfCodexWorkerDead(args, state)) {
|
|
10817
|
+
return;
|
|
10818
|
+
}
|
|
10571
10819
|
if (drainKandanMessageQueueBlocked(args, state)) {
|
|
10572
10820
|
return;
|
|
10573
10821
|
}
|
|
@@ -10649,6 +10897,14 @@ async function drainKandanMessageQueueOnce(args, state, payloadContext) {
|
|
|
10649
10897
|
await drainKandanMessageQueue(args, state, payloadContext);
|
|
10650
10898
|
}
|
|
10651
10899
|
} catch (error) {
|
|
10900
|
+
if (codexWorkerIsDead(args)) {
|
|
10901
|
+
await stopCodexTyping(args, state);
|
|
10902
|
+
requeuePendingKandanMessageFront(state.queue, next);
|
|
10903
|
+
state.turn = { status: "idle" };
|
|
10904
|
+
clearActiveProcessingState(state, next.seq);
|
|
10905
|
+
await rebuildIfCodexWorkerDead(args, state);
|
|
10906
|
+
return;
|
|
10907
|
+
}
|
|
10652
10908
|
if (isRecoverableCodexThreadError(error) && state.kandanThreadId !== void 0) {
|
|
10653
10909
|
const oldCodexThreadId = state.codexThreadId;
|
|
10654
10910
|
try {
|
|
@@ -10709,6 +10965,83 @@ async function drainKandanMessageQueueOnce(args, state, payloadContext) {
|
|
|
10709
10965
|
}
|
|
10710
10966
|
}
|
|
10711
10967
|
}
|
|
10968
|
+
function codexWorkerIsDead(args) {
|
|
10969
|
+
return args.codex.isClosed?.() === true;
|
|
10970
|
+
}
|
|
10971
|
+
async function rebuildIfCodexWorkerDead(args, state) {
|
|
10972
|
+
if (!codexWorkerIsDead(args)) {
|
|
10973
|
+
return false;
|
|
10974
|
+
}
|
|
10975
|
+
const pending = drainAllPendingKandanMessages(state.queue);
|
|
10976
|
+
if (pending.length === 0) {
|
|
10977
|
+
return false;
|
|
10978
|
+
}
|
|
10979
|
+
const { codexThreadId, kandanThreadId } = state;
|
|
10980
|
+
const rebuild = args.options.rebuildOnDeadCodexWorker;
|
|
10981
|
+
args.log("kandan.queue_drain_dead_worker_rebuild", {
|
|
10982
|
+
codex_thread_id: codexThreadId ?? null,
|
|
10983
|
+
kandan_thread_id: kandanThreadId ?? null,
|
|
10984
|
+
pending_count: pending.length,
|
|
10985
|
+
attempt: state.deadWorkerRebuildAttempts + 1,
|
|
10986
|
+
rebuild_available: rebuild !== void 0
|
|
10987
|
+
});
|
|
10988
|
+
const failPending = async (reason) => {
|
|
10989
|
+
for (const message of pending) {
|
|
10990
|
+
try {
|
|
10991
|
+
await publishQueuedMessageState(args, state, message, {
|
|
10992
|
+
status: "failed",
|
|
10993
|
+
reason
|
|
10994
|
+
});
|
|
10995
|
+
} catch (error) {
|
|
10996
|
+
args.log("kandan.queue_drain_dead_worker_fail_publish_failed", {
|
|
10997
|
+
codex_thread_id: codexThreadId ?? null,
|
|
10998
|
+
seq: message.seq,
|
|
10999
|
+
message: error instanceof Error ? error.message : String(error)
|
|
11000
|
+
});
|
|
11001
|
+
}
|
|
11002
|
+
}
|
|
11003
|
+
};
|
|
11004
|
+
if (rebuild === void 0 || codexThreadId === void 0 || kandanThreadId === void 0) {
|
|
11005
|
+
await failPending(
|
|
11006
|
+
"Codex worker for this thread exited and could not be respawned to resume the conversation."
|
|
11007
|
+
);
|
|
11008
|
+
return true;
|
|
11009
|
+
}
|
|
11010
|
+
if (state.deadWorkerRebuildAttempts >= maxDeadWorkerRebuildAttempts) {
|
|
11011
|
+
args.log("kandan.queue_drain_dead_worker_rebuild_exhausted", {
|
|
11012
|
+
codex_thread_id: codexThreadId,
|
|
11013
|
+
kandan_thread_id: kandanThreadId,
|
|
11014
|
+
attempts: state.deadWorkerRebuildAttempts
|
|
11015
|
+
});
|
|
11016
|
+
await failPending(
|
|
11017
|
+
"Codex worker for this thread kept exiting on resume; giving up after several respawn attempts."
|
|
11018
|
+
);
|
|
11019
|
+
return true;
|
|
11020
|
+
}
|
|
11021
|
+
state.deadWorkerRebuildAttempts += 1;
|
|
11022
|
+
state.closed = true;
|
|
11023
|
+
let rebuilt = false;
|
|
11024
|
+
try {
|
|
11025
|
+
rebuilt = await rebuild({
|
|
11026
|
+
codexThreadId,
|
|
11027
|
+
kandanThreadId,
|
|
11028
|
+
pendingMessages: pending
|
|
11029
|
+
});
|
|
11030
|
+
} catch (error) {
|
|
11031
|
+
args.log("kandan.queue_drain_dead_worker_rebuild_failed", {
|
|
11032
|
+
codex_thread_id: codexThreadId,
|
|
11033
|
+
kandan_thread_id: kandanThreadId,
|
|
11034
|
+
message: error instanceof Error ? error.message : String(error)
|
|
11035
|
+
});
|
|
11036
|
+
rebuilt = false;
|
|
11037
|
+
}
|
|
11038
|
+
if (!rebuilt) {
|
|
11039
|
+
await failPending(
|
|
11040
|
+
"Codex worker for this thread exited and could not be respawned to resume the conversation."
|
|
11041
|
+
);
|
|
11042
|
+
}
|
|
11043
|
+
return true;
|
|
11044
|
+
}
|
|
10712
11045
|
function drainKandanMessageQueueBlocked(args, state) {
|
|
10713
11046
|
if (state.closed) {
|
|
10714
11047
|
logQueuedDrainBlocked(args, state, "session_closed");
|
|
@@ -11720,7 +12053,7 @@ async function pushOptional(kandan, topic, event, payload, log2) {
|
|
|
11720
12053
|
});
|
|
11721
12054
|
}
|
|
11722
12055
|
}
|
|
11723
|
-
var codexTypingHeartbeatMs, CODEX_START_REQUEST_TIMEOUT_MS, CodexStartRequestTimeoutError, maxTrackedFailedChatEventSeqs, maxChatEventFailureAttempts, maxForwardedTurnIds, maxClaimedKandanMessageKeys, claimedKandanMessageKeys, nextChatJoinRegistrationSerial, defaultReconnectHandlingRetryDelaysMs, defaultTuiInputMirrorRetryDelaysMs, pipelineCloseTimeoutMs;
|
|
12056
|
+
var codexTypingHeartbeatMs, CODEX_START_REQUEST_TIMEOUT_MS, CodexStartRequestTimeoutError, maxTrackedFailedChatEventSeqs, maxChatEventFailureAttempts, maxForwardedTurnIds, maxClaimedKandanMessageKeys, claimedKandanMessageKeys, nextChatJoinRegistrationSerial, defaultReconnectHandlingRetryDelaysMs, defaultTuiInputMirrorRetryDelaysMs, pipelineCloseTimeoutMs, maxDeadWorkerRebuildAttempts;
|
|
11724
12057
|
var init_channelSession = __esm({
|
|
11725
12058
|
"src/channelSession.ts"() {
|
|
11726
12059
|
"use strict";
|
|
@@ -11771,6 +12104,7 @@ var init_channelSession = __esm({
|
|
|
11771
12104
|
15e3
|
|
11772
12105
|
];
|
|
11773
12106
|
pipelineCloseTimeoutMs = 1e4;
|
|
12107
|
+
maxDeadWorkerRebuildAttempts = 3;
|
|
11774
12108
|
}
|
|
11775
12109
|
});
|
|
11776
12110
|
|
|
@@ -19451,7 +19785,7 @@ var linzumiCliVersion, linzumiCliVersionText;
|
|
|
19451
19785
|
var init_version = __esm({
|
|
19452
19786
|
"src/version.ts"() {
|
|
19453
19787
|
"use strict";
|
|
19454
|
-
linzumiCliVersion = "0.0.
|
|
19788
|
+
linzumiCliVersion = "0.0.97-beta";
|
|
19455
19789
|
linzumiCliVersionText = `linzumi ${linzumiCliVersion}`;
|
|
19456
19790
|
}
|
|
19457
19791
|
});
|
|
@@ -23211,6 +23545,7 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
|
|
|
23211
23545
|
const missingAllowedCwds = {
|
|
23212
23546
|
value: normalizeAllowedCwds(options.missingAllowedCwds ?? [])
|
|
23213
23547
|
};
|
|
23548
|
+
const projectDiscoveryCwdIsSelectedRootFromSyncedConfig = { value: false };
|
|
23214
23549
|
const applyRunnerConfigSync = (config, syncOptions) => {
|
|
23215
23550
|
const persistedAllowedCwds = replaceAllowedCwdsForLinzumiUrl(
|
|
23216
23551
|
config.allowedCwds,
|
|
@@ -23219,6 +23554,10 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
|
|
|
23219
23554
|
const updatedAllowedCwds = configuredAllowedCwds(persistedAllowedCwds, {
|
|
23220
23555
|
createMissing: true
|
|
23221
23556
|
});
|
|
23557
|
+
projectDiscoveryCwdIsSelectedRootFromSyncedConfig.value = projectDiscoveryCwdIsSelectedRootFromSyncedConfig.value || allowedCwdsContainAny(updatedAllowedCwds.allowedCwds, [
|
|
23558
|
+
options.cwd,
|
|
23559
|
+
...startupAllowedCwds
|
|
23560
|
+
]);
|
|
23222
23561
|
allowedCwds.value = normalizeAllowedCwds([
|
|
23223
23562
|
...syncOptions.includeStartupAllowedCwds ? startupAllowedCwds : [],
|
|
23224
23563
|
...updatedAllowedCwds.allowedCwds
|
|
@@ -23305,6 +23644,7 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
|
|
|
23305
23644
|
allowedCwds.value
|
|
23306
23645
|
),
|
|
23307
23646
|
allowedCwdProjects: allowedCwdProjects(allowedCwds.value),
|
|
23647
|
+
onboardingSelectedFolderScan: true,
|
|
23308
23648
|
portForwarding: liveForwardPorts.size > 0,
|
|
23309
23649
|
tcpForwarding: true,
|
|
23310
23650
|
linzumiMcp: true,
|
|
@@ -24386,6 +24726,53 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
|
|
|
24386
24726
|
);
|
|
24387
24727
|
}
|
|
24388
24728
|
const runtimeSettings = startInstanceRuntimeSettings(options, control);
|
|
24729
|
+
const rebuildOnDeadCodexWorker = shouldUseThreadProcesses(options) ? async (rebuildArgs) => {
|
|
24730
|
+
await evictStaleDynamicChannelSession(rebuildArgs.codexThreadId);
|
|
24731
|
+
let rebuilt = false;
|
|
24732
|
+
for (const message of rebuildArgs.pendingMessages) {
|
|
24733
|
+
const reconnectControl = {
|
|
24734
|
+
type: "reconnect_thread",
|
|
24735
|
+
workspace: workspaceSlug,
|
|
24736
|
+
channel: channelSlug,
|
|
24737
|
+
threadId: rebuildArgs.kandanThreadId,
|
|
24738
|
+
codexThreadId: rebuildArgs.codexThreadId,
|
|
24739
|
+
cwd,
|
|
24740
|
+
...integerValue(control.rootSeq) === void 0 ? {} : { rootSeq: integerValue(control.rootSeq) },
|
|
24741
|
+
sourceSeq: message.seq,
|
|
24742
|
+
workDescription: message.body,
|
|
24743
|
+
...runtimeSettings.model === void 0 ? {} : { model: runtimeSettings.model },
|
|
24744
|
+
...runtimeSettings.reasoningEffort === void 0 ? {} : { reasoningEffort: runtimeSettings.reasoningEffort },
|
|
24745
|
+
...runtimeSettings.sandbox === void 0 ? {} : { sandbox: runtimeSettings.sandbox },
|
|
24746
|
+
...runtimeSettings.approvalPolicy === void 0 ? {} : { approvalPolicy: runtimeSettings.approvalPolicy },
|
|
24747
|
+
...runtimeSettings.fast === void 0 ? {} : { fast: runtimeSettings.fast }
|
|
24748
|
+
};
|
|
24749
|
+
const liveSession = dynamicChannelSessions.get(
|
|
24750
|
+
rebuildArgs.codexThreadId
|
|
24751
|
+
);
|
|
24752
|
+
try {
|
|
24753
|
+
if (liveSession !== void 0 && rebuilt) {
|
|
24754
|
+
await liveSession.startThreadMessageTurn({
|
|
24755
|
+
seq: message.seq,
|
|
24756
|
+
body: message.body,
|
|
24757
|
+
actorSlug: message.actorSlug,
|
|
24758
|
+
actorUserId: message.actorUserId
|
|
24759
|
+
});
|
|
24760
|
+
} else {
|
|
24761
|
+
await startThreadRunnerProcess(reconnectControl, cwd);
|
|
24762
|
+
}
|
|
24763
|
+
rebuilt = true;
|
|
24764
|
+
} catch (error) {
|
|
24765
|
+
log2("runner.thread_dead_worker_rebuild_failed", {
|
|
24766
|
+
codex_thread_id: rebuildArgs.codexThreadId,
|
|
24767
|
+
kandan_thread_id: rebuildArgs.kandanThreadId,
|
|
24768
|
+
seq: message.seq,
|
|
24769
|
+
message: error instanceof Error ? error.message : String(error)
|
|
24770
|
+
});
|
|
24771
|
+
return false;
|
|
24772
|
+
}
|
|
24773
|
+
}
|
|
24774
|
+
return rebuilt;
|
|
24775
|
+
} : void 0;
|
|
24389
24776
|
const session = await attachChannelSession({
|
|
24390
24777
|
kandan,
|
|
24391
24778
|
codex: sessionCodex,
|
|
@@ -24400,6 +24787,7 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
|
|
|
24400
24787
|
fetch: options.fetch,
|
|
24401
24788
|
fast: control.fast ?? options.fast,
|
|
24402
24789
|
launchTui: false,
|
|
24790
|
+
rebuildOnDeadCodexWorker,
|
|
24403
24791
|
pipelinePersistDir: commanderOutboxPersistDir(),
|
|
24404
24792
|
enablePortForwardWatch: true,
|
|
24405
24793
|
initialForwardPorts: allowedForwardPorts,
|
|
@@ -25115,6 +25503,29 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
|
|
|
25115
25503
|
}
|
|
25116
25504
|
);
|
|
25117
25505
|
}
|
|
25506
|
+
if (control.type === "scan_onboarding_projects") {
|
|
25507
|
+
const selectedScanRoots = onboardingProjectScanRoots(control.paths);
|
|
25508
|
+
return runLocalOnboardingProjectDiscovery(options, log2, {
|
|
25509
|
+
workspaceSlug: stringValue(control.workspace),
|
|
25510
|
+
selectedScanRoots,
|
|
25511
|
+
sourceRoots: selectedScanRoots,
|
|
25512
|
+
workerId: "projects-selected-folders",
|
|
25513
|
+
workerLabel: "Selected folders",
|
|
25514
|
+
startingMessage: "Checking selected folders",
|
|
25515
|
+
emptyMessage: "No Git projects found in selected folders",
|
|
25516
|
+
foundMessage: "Selected folder projects found",
|
|
25517
|
+
failedMessage: "Selected folder project scan failed",
|
|
25518
|
+
currentPlace: selectedScanRoots[0] ?? options.cwd,
|
|
25519
|
+
requireTerminalStatusWrite: true,
|
|
25520
|
+
includeRuntimeCwdHint: false
|
|
25521
|
+
}).catch((error) => {
|
|
25522
|
+
log2("onboarding.project_scan_failed", {
|
|
25523
|
+
runnerId: options.runnerId,
|
|
25524
|
+
message: error instanceof Error ? error.message : String(error)
|
|
25525
|
+
});
|
|
25526
|
+
throw error;
|
|
25527
|
+
});
|
|
25528
|
+
}
|
|
25118
25529
|
if (control.type === "start_instance") {
|
|
25119
25530
|
const staleAgeMs = staleStartInstanceAgeMs(control, Date.now());
|
|
25120
25531
|
if (staleAgeMs !== void 0) {
|
|
@@ -25219,7 +25630,12 @@ async function openLocalCodexRunner(options, log2, cleanup, close) {
|
|
|
25219
25630
|
settleControlDispatch(control.type, () => handleControl(control), ack, log2);
|
|
25220
25631
|
};
|
|
25221
25632
|
finishRunnerStartup(
|
|
25222
|
-
|
|
25633
|
+
onboardingDiscoveryRunnerOptions(
|
|
25634
|
+
options,
|
|
25635
|
+
allowedCwds.value,
|
|
25636
|
+
missingAllowedCwds.value,
|
|
25637
|
+
projectDiscoveryCwdIsSelectedRootFromSyncedConfig.value
|
|
25638
|
+
),
|
|
25223
25639
|
log2,
|
|
25224
25640
|
pendingControls,
|
|
25225
25641
|
controlDispatcher,
|
|
@@ -29585,6 +30001,14 @@ function onboardingConversationImportSources(value) {
|
|
|
29585
30001
|
)
|
|
29586
30002
|
).sort();
|
|
29587
30003
|
}
|
|
30004
|
+
function onboardingProjectScanRoots(value) {
|
|
30005
|
+
return normalizeAllowedCwds(
|
|
30006
|
+
(arrayValue(value) ?? []).flatMap((path2) => {
|
|
30007
|
+
const normalizedPath = stringValue(path2)?.trim();
|
|
30008
|
+
return normalizedPath === void 0 || normalizedPath === "" ? [] : [normalizedPath];
|
|
30009
|
+
})
|
|
30010
|
+
);
|
|
30011
|
+
}
|
|
29588
30012
|
async function replayLocalOnboardingConversation(args) {
|
|
29589
30013
|
let replayedChunkCount = 0;
|
|
29590
30014
|
for (const message of args.messages) {
|
|
@@ -30011,27 +30435,42 @@ async function runLocalOnboardingConversationDiscovery(options, log2) {
|
|
|
30011
30435
|
);
|
|
30012
30436
|
}
|
|
30013
30437
|
}
|
|
30014
|
-
async function runLocalOnboardingProjectDiscovery(options, log2) {
|
|
30015
|
-
const workspaceSlug = runnerWorkspaceSlug(options);
|
|
30438
|
+
async function runLocalOnboardingProjectDiscovery(options, log2, args = {}) {
|
|
30439
|
+
const workspaceSlug = args.workspaceSlug ?? runnerWorkspaceSlug(options);
|
|
30440
|
+
const selectedScanRoots = args.selectedScanRoots ?? selectedProjectDiscoveryScanRoots(options);
|
|
30016
30441
|
if (workspaceSlug === void 0) {
|
|
30017
30442
|
return;
|
|
30018
30443
|
}
|
|
30444
|
+
const workerId = args.workerId ?? "projects-local-filesystem";
|
|
30445
|
+
const workerLabel = args.workerLabel ?? "Local Git projects";
|
|
30446
|
+
const currentPlace = args.currentPlace ?? selectedScanRoots[0] ?? options.cwd;
|
|
30019
30447
|
await reportOnboardingDiscoveryStatus(options, log2, {
|
|
30020
30448
|
phase: "projects",
|
|
30021
30449
|
status: "starting",
|
|
30022
30450
|
placesSearched: 0,
|
|
30023
|
-
message: "
|
|
30024
|
-
currentPlace
|
|
30451
|
+
message: args.startingMessage ?? "Searching local Git projects",
|
|
30452
|
+
currentPlace,
|
|
30025
30453
|
currentSource: "git",
|
|
30454
|
+
workspaceSlug,
|
|
30026
30455
|
metadata: {
|
|
30027
|
-
worker_id:
|
|
30028
|
-
worker_label:
|
|
30456
|
+
worker_id: workerId,
|
|
30457
|
+
worker_label: workerLabel,
|
|
30458
|
+
...selectedScanRoots.length === 0 ? {} : { selected_scan_roots: selectedScanRoots }
|
|
30029
30459
|
}
|
|
30030
30460
|
});
|
|
30031
30461
|
let successfulPostStartWriteCount = 0;
|
|
30032
30462
|
try {
|
|
30033
|
-
const summary = await options.localProjectDiscovery?.(
|
|
30034
|
-
|
|
30463
|
+
const summary = await options.localProjectDiscovery?.({
|
|
30464
|
+
selectedScanRoots,
|
|
30465
|
+
sourceRoots: args.sourceRoots,
|
|
30466
|
+
includeRuntimeCwdHint: args.includeRuntimeCwdHint
|
|
30467
|
+
}) ?? await discoverCurrentGitProjectInChildProcess(
|
|
30468
|
+
{
|
|
30469
|
+
cwd: options.cwd,
|
|
30470
|
+
selectedScanRoots,
|
|
30471
|
+
sourceRoots: args.sourceRoots,
|
|
30472
|
+
includeRuntimeCwdHint: args.includeRuntimeCwdHint
|
|
30473
|
+
},
|
|
30035
30474
|
{ log: (event, payload) => log2(event, payload) }
|
|
30036
30475
|
);
|
|
30037
30476
|
const client = createLinzumiMcpApiClient({
|
|
@@ -30061,22 +30500,31 @@ async function runLocalOnboardingProjectDiscovery(options, log2) {
|
|
|
30061
30500
|
phase: "projects",
|
|
30062
30501
|
status: "completed",
|
|
30063
30502
|
placesSearched: summary.placesSearched,
|
|
30064
|
-
message: summary.candidates.length === 0 ?
|
|
30065
|
-
currentPlace
|
|
30503
|
+
message: summary.candidates.length === 0 ? args.emptyMessage ?? "No local Git projects found" : args.foundMessage ?? "Local Git projects found",
|
|
30504
|
+
currentPlace,
|
|
30066
30505
|
currentSource: "git",
|
|
30506
|
+
workspaceSlug,
|
|
30067
30507
|
metadata: {
|
|
30068
|
-
worker_id:
|
|
30069
|
-
worker_label:
|
|
30508
|
+
worker_id: workerId,
|
|
30509
|
+
worker_label: workerLabel,
|
|
30070
30510
|
duration_ms: summary.durationMs,
|
|
30071
30511
|
reported_count: summary.candidates.length,
|
|
30072
30512
|
failed_report_count: failedReportCount,
|
|
30513
|
+
...selectedScanRoots.length === 0 ? {} : { selected_scan_roots: selectedScanRoots },
|
|
30073
30514
|
search_stats: summary.searchStats
|
|
30074
30515
|
}
|
|
30075
30516
|
};
|
|
30076
|
-
|
|
30077
|
-
|
|
30078
|
-
|
|
30517
|
+
const completedStatusWritten = await reportOnboardingDiscoveryStatus(
|
|
30518
|
+
options,
|
|
30519
|
+
log2,
|
|
30520
|
+
completedReport
|
|
30079
30521
|
);
|
|
30522
|
+
if (!completedStatusWritten && args.requireTerminalStatusWrite === true) {
|
|
30523
|
+
throw new Error(
|
|
30524
|
+
"onboarding project discovery terminal status write failed"
|
|
30525
|
+
);
|
|
30526
|
+
}
|
|
30527
|
+
successfulPostStartWriteCount = completedStatusWritten ? successfulPostStartWriteCount + 1 : successfulPostStartWriteCount;
|
|
30080
30528
|
log2("onboarding.local_project_discovery_completed", {
|
|
30081
30529
|
runnerId: options.runnerId,
|
|
30082
30530
|
workspace: workspaceSlug,
|
|
@@ -30094,19 +30542,26 @@ async function runLocalOnboardingProjectDiscovery(options, log2) {
|
|
|
30094
30542
|
phase: "projects",
|
|
30095
30543
|
status: "failed",
|
|
30096
30544
|
placesSearched: 0,
|
|
30097
|
-
message: "
|
|
30098
|
-
currentPlace
|
|
30545
|
+
message: args.failedMessage ?? "Local Git project scan failed",
|
|
30546
|
+
currentPlace,
|
|
30099
30547
|
currentSource: "git",
|
|
30100
30548
|
lastError: message,
|
|
30549
|
+
workspaceSlug,
|
|
30101
30550
|
metadata: {
|
|
30102
|
-
worker_id:
|
|
30103
|
-
worker_label:
|
|
30551
|
+
worker_id: workerId,
|
|
30552
|
+
worker_label: workerLabel,
|
|
30553
|
+
...selectedScanRoots.length === 0 ? {} : { selected_scan_roots: selectedScanRoots }
|
|
30104
30554
|
}
|
|
30105
30555
|
};
|
|
30106
|
-
|
|
30107
|
-
|
|
30108
|
-
|
|
30556
|
+
const failedStatusWritten = await reportOnboardingDiscoveryStatus(
|
|
30557
|
+
options,
|
|
30558
|
+
log2,
|
|
30559
|
+
failedReport
|
|
30109
30560
|
);
|
|
30561
|
+
if (!failedStatusWritten && args.requireTerminalStatusWrite === true) {
|
|
30562
|
+
throw error;
|
|
30563
|
+
}
|
|
30564
|
+
successfulPostStartWriteCount = failedStatusWritten ? successfulPostStartWriteCount + 1 : successfulPostStartWriteCount;
|
|
30110
30565
|
log2("onboarding.local_project_discovery_failed", {
|
|
30111
30566
|
runnerId: options.runnerId,
|
|
30112
30567
|
workspace: workspaceSlug,
|
|
@@ -30118,11 +30573,45 @@ async function runLocalOnboardingProjectDiscovery(options, log2) {
|
|
|
30118
30573
|
);
|
|
30119
30574
|
}
|
|
30120
30575
|
}
|
|
30576
|
+
function selectedProjectDiscoveryScanRoots(options) {
|
|
30577
|
+
const cwd = options.cwd.trim();
|
|
30578
|
+
const implicitCwdAliases = new Set(implicitCwdStringAliases(cwd));
|
|
30579
|
+
for (const alias of options.projectDiscoveryImplicitCwdAliases ?? []) {
|
|
30580
|
+
implicitCwdAliases.add(alias);
|
|
30581
|
+
}
|
|
30582
|
+
const allowedCwds = options.projectDiscoveryCwdIsSelectedRoot === true ? options.allowedCwds : options.allowedCwds.filter(
|
|
30583
|
+
(allowedCwd) => !implicitCwdAliases.has(allowedCwd)
|
|
30584
|
+
);
|
|
30585
|
+
return normalizeAllowedCwds([
|
|
30586
|
+
...allowedCwds,
|
|
30587
|
+
...options.missingAllowedCwds ?? []
|
|
30588
|
+
]);
|
|
30589
|
+
}
|
|
30590
|
+
function implicitCwdStringAliases(cwd) {
|
|
30591
|
+
if (cwd === "") {
|
|
30592
|
+
return [];
|
|
30593
|
+
}
|
|
30594
|
+
return normalizeAllowedCwds([cwd, resolve8(expandUserPath(cwd))]);
|
|
30595
|
+
}
|
|
30596
|
+
function onboardingDiscoveryRunnerOptions(options, allowedCwds, missingAllowedCwds, projectDiscoveryCwdIsSelectedRootFromSyncedConfig) {
|
|
30597
|
+
return {
|
|
30598
|
+
...options,
|
|
30599
|
+
allowedCwds,
|
|
30600
|
+
missingAllowedCwds,
|
|
30601
|
+
projectDiscoveryCwdIsSelectedRoot: options.projectDiscoveryCwdIsSelectedRoot === true || projectDiscoveryCwdIsSelectedRootFromSyncedConfig
|
|
30602
|
+
};
|
|
30603
|
+
}
|
|
30604
|
+
function allowedCwdsContainAny(allowedCwds, candidates) {
|
|
30605
|
+
const allowed = new Set(normalizeAllowedCwds(allowedCwds));
|
|
30606
|
+
return normalizeAllowedCwds(candidates).some(
|
|
30607
|
+
(candidate) => allowed.has(candidate)
|
|
30608
|
+
);
|
|
30609
|
+
}
|
|
30121
30610
|
function shouldStartOnboardingDiscoveryAgents(options, workspaceSlug = runnerWorkspaceSlug(options)) {
|
|
30122
30611
|
return workspaceSlug !== void 0 && options.threadProcess === void 0 && options.onboardingDiscovery === "start";
|
|
30123
30612
|
}
|
|
30124
30613
|
async function reportOnboardingDiscoveryStatus(options, log2, args) {
|
|
30125
|
-
const workspaceSlug = runnerWorkspaceSlug(options);
|
|
30614
|
+
const workspaceSlug = args.workspaceSlug ?? runnerWorkspaceSlug(options);
|
|
30126
30615
|
if (workspaceSlug === void 0) {
|
|
30127
30616
|
return false;
|
|
30128
30617
|
}
|
|
@@ -69207,6 +69696,7 @@ async function parseStartRunnerArgs(args, deps = {
|
|
|
69207
69696
|
fast: values.get("fast") === true,
|
|
69208
69697
|
logFile: stringValue8(values, "log-file"),
|
|
69209
69698
|
allowedCwds,
|
|
69699
|
+
projectDiscoveryCwdIsSelectedRoot: true,
|
|
69210
69700
|
allowedForwardPorts: parseAllowedPortList(
|
|
69211
69701
|
stringValue8(values, "forward-port")
|
|
69212
69702
|
),
|
|
@@ -69274,6 +69764,7 @@ async function parseAgentRunnerArgs(args, deps = {
|
|
|
69274
69764
|
parseAllowedCwdList(stringValue8(values, "allowed-cwd"))
|
|
69275
69765
|
) : requestedCwdValue === void 0 ? configuredAllowedCwds2.allowedCwds.length > 0 ? [...configuredAllowedCwds2.allowedCwds] : assertConfiguredAllowedCwds([requestedCwd]) : assertConfiguredAllowedCwds([requestedCwd]);
|
|
69276
69766
|
const cwd = allowedCwds[0] ?? requestedCwd;
|
|
69767
|
+
const projectDiscoveryCwdIsSelectedRoot = values.has("allowed-cwd") || requestedCwdValue === void 0 && configuredAllowedCwds2.allowedCwds.length > 0;
|
|
69277
69768
|
const requestedCodexBin = stringValue8(values, "codex-bin") ?? "codex";
|
|
69278
69769
|
const customCodeServerBin = stringValue8(values, "code-server-bin");
|
|
69279
69770
|
const initialDependencyStatus = await deps.buildDependencyStatus({
|
|
@@ -69313,6 +69804,8 @@ async function parseAgentRunnerArgs(args, deps = {
|
|
|
69313
69804
|
logFile: stringValue8(values, "log-file"),
|
|
69314
69805
|
allowedCwds,
|
|
69315
69806
|
missingAllowedCwds: configuredAllowedCwds2.missingAllowedCwds,
|
|
69807
|
+
projectDiscoveryCwdIsSelectedRoot,
|
|
69808
|
+
projectDiscoveryImplicitCwdAliases: projectDiscoveryCwdIsSelectedRoot ? void 0 : allowedCwds,
|
|
69316
69809
|
allowedForwardPorts: parseAllowedPortList(
|
|
69317
69810
|
stringValue8(values, "forward-port")
|
|
69318
69811
|
),
|
|
@@ -69436,6 +69929,9 @@ async function parseRunnerArgs(args, deps = {
|
|
|
69436
69929
|
const configuredAllowedCwds2 = values.has("allowed-cwd") ? assertConfiguredAllowedCwds(
|
|
69437
69930
|
parseAllowedCwdList(stringValue8(values, "allowed-cwd"))
|
|
69438
69931
|
) : [...localConfiguredAllowedCwds.allowedCwds];
|
|
69932
|
+
const projectDiscoveryCwdIsSelectedRoot = cwdAllowedCwds.some(
|
|
69933
|
+
(cwdAllowedCwd) => configuredAllowedCwds2.includes(cwdAllowedCwd)
|
|
69934
|
+
);
|
|
69439
69935
|
const requestedCodexBin = stringValue8(values, "codex-bin") ?? "codex";
|
|
69440
69936
|
const customCodeServerBin = stringValue8(values, "code-server-bin");
|
|
69441
69937
|
const onboardingDiscovery = values.get("no-onboarding-discovery") === true ? void 0 : "start";
|
|
@@ -69490,6 +69986,8 @@ async function parseRunnerArgs(args, deps = {
|
|
|
69490
69986
|
/* @__PURE__ */ new Set([...cwdAllowedCwds, ...configuredAllowedCwds2])
|
|
69491
69987
|
),
|
|
69492
69988
|
missingAllowedCwds: localConfiguredAllowedCwds.missingAllowedCwds,
|
|
69989
|
+
projectDiscoveryCwdIsSelectedRoot,
|
|
69990
|
+
projectDiscoveryImplicitCwdAliases: projectDiscoveryCwdIsSelectedRoot ? void 0 : cwdAllowedCwds,
|
|
69493
69991
|
allowedForwardPorts: parseAllowedPortList(
|
|
69494
69992
|
stringValue8(values, "forward-port")
|
|
69495
69993
|
),
|
package/package.json
CHANGED