@analyticscli/growth-engineer 0.1.0-preview.10 → 0.1.0-preview.12
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/dist/runtime/openclaw-growth-runner.mjs +64 -20
- package/dist/runtime/openclaw-growth-runner.mjs.map +1 -1
- package/dist/runtime/openclaw-growth-shared.d.mts +2 -1
- package/dist/runtime/openclaw-growth-shared.mjs +32 -2
- package/dist/runtime/openclaw-growth-shared.mjs.map +1 -1
- package/dist/runtime/openclaw-growth-wizard.mjs +263 -35
- package/dist/runtime/openclaw-growth-wizard.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -462,6 +462,170 @@ async function askMenuChoice(rl, { title, subtitle = 'Use Up/Down to move, Enter
|
|
|
462
462
|
}
|
|
463
463
|
}
|
|
464
464
|
}
|
|
465
|
+
async function askMultiChoice(rl, { title, subtitle = 'Use Up/Down to move, Space to toggle, Enter to continue.', options, defaultValues, requiredValues = [], minSelections = 1, renderHeader, }) {
|
|
466
|
+
const required = new Set(requiredValues);
|
|
467
|
+
const normalizeSelection = (values) => {
|
|
468
|
+
const selected = new Set(values);
|
|
469
|
+
requiredValues.forEach((value) => selected.add(value));
|
|
470
|
+
return options.map((option) => option.value).filter((value) => selected.has(value));
|
|
471
|
+
};
|
|
472
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY || !process.stdin.setRawMode) {
|
|
473
|
+
process.stdout.write(`\n${title}\n`);
|
|
474
|
+
options.forEach((option, index) => {
|
|
475
|
+
const checked = defaultValues.includes(option.value) || required.has(option.value) ? 'x' : ' ';
|
|
476
|
+
const requiredLabel = required.has(option.value) ? ' required' : '';
|
|
477
|
+
process.stdout.write(` ${index + 1}) [${checked}] ${option.label}${requiredLabel}: ${option.detail}\n`);
|
|
478
|
+
});
|
|
479
|
+
const answer = await ask(rl, `Select one or more (comma-separated 1-${options.length})`, normalizeSelection(defaultValues).map((value) => String(options.findIndex((option) => option.value === value) + 1)).join(','));
|
|
480
|
+
const selected = answer
|
|
481
|
+
.split(',')
|
|
482
|
+
.map((value) => Number.parseInt(value.trim(), 10) - 1)
|
|
483
|
+
.filter((index) => options[index])
|
|
484
|
+
.map((index) => options[index].value);
|
|
485
|
+
const normalized = normalizeSelection(selected);
|
|
486
|
+
return normalized.length >= minSelections ? normalized : normalizeSelection(defaultValues);
|
|
487
|
+
}
|
|
488
|
+
rl.pause();
|
|
489
|
+
let completed = false;
|
|
490
|
+
try {
|
|
491
|
+
const selected = await askMultiChoiceByKeys({
|
|
492
|
+
title,
|
|
493
|
+
subtitle,
|
|
494
|
+
options,
|
|
495
|
+
defaultValues: normalizeSelection(defaultValues),
|
|
496
|
+
requiredValues,
|
|
497
|
+
minSelections,
|
|
498
|
+
renderHeader,
|
|
499
|
+
});
|
|
500
|
+
completed = true;
|
|
501
|
+
return selected;
|
|
502
|
+
}
|
|
503
|
+
finally {
|
|
504
|
+
if (completed) {
|
|
505
|
+
rl.resume();
|
|
506
|
+
}
|
|
507
|
+
else {
|
|
508
|
+
process.stdin.pause();
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
async function askMultiChoiceByKeys({ title, subtitle, options, defaultValues, requiredValues, minSelections, renderHeader, }) {
|
|
513
|
+
emitKeypressEvents(process.stdin);
|
|
514
|
+
const wasRaw = process.stdin.isRaw;
|
|
515
|
+
const wasPaused = process.stdin.isPaused();
|
|
516
|
+
process.stdin.setRawMode(true);
|
|
517
|
+
process.stdin.resume();
|
|
518
|
+
const required = new Set(requiredValues);
|
|
519
|
+
const selected = new Set(defaultValues);
|
|
520
|
+
requiredValues.forEach((value) => selected.add(value));
|
|
521
|
+
let cursorIndex = 0;
|
|
522
|
+
let warning = '';
|
|
523
|
+
return await new Promise((resolve, reject) => {
|
|
524
|
+
const cleanup = () => {
|
|
525
|
+
process.stdin.off('keypress', onKeypress);
|
|
526
|
+
process.stdin.setRawMode(Boolean(wasRaw));
|
|
527
|
+
if (wasPaused) {
|
|
528
|
+
process.stdin.pause();
|
|
529
|
+
}
|
|
530
|
+
process.stdout.write(ANSI.showCursor);
|
|
531
|
+
};
|
|
532
|
+
const selectedValues = () => options.map((option) => option.value).filter((value) => selected.has(value));
|
|
533
|
+
const render = () => {
|
|
534
|
+
process.stdout.write('\x1b[2J\x1b[H');
|
|
535
|
+
renderHeader?.();
|
|
536
|
+
process.stdout.write(`\n${ANSI.bold}${title}${ANSI.reset}\n`);
|
|
537
|
+
process.stdout.write(`${ANSI.dim}${subtitle}${ANSI.reset}\n\n`);
|
|
538
|
+
if (warning) {
|
|
539
|
+
process.stdout.write(`${ANSI.cyan}${warning}${ANSI.reset}\n\n`);
|
|
540
|
+
}
|
|
541
|
+
for (let index = 0; index < options.length; index += 1) {
|
|
542
|
+
const option = options[index];
|
|
543
|
+
const pointer = index === cursorIndex ? `${ANSI.cyan}>${ANSI.reset}` : ' ';
|
|
544
|
+
const checkbox = selected.has(option.value) ? '[x]' : '[ ]';
|
|
545
|
+
const requiredLabel = required.has(option.value) ? ` ${ANSI.dim}(required)${ANSI.reset}` : '';
|
|
546
|
+
process.stdout.write(`${pointer} ${checkbox} ${index + 1}) ${ANSI.bold}${option.label}${ANSI.reset}${requiredLabel}\n`);
|
|
547
|
+
writeWrapped(option.detail, ' ', ANSI.dim);
|
|
548
|
+
}
|
|
549
|
+
process.stdout.write(`\n${ANSI.dim}Esc/Q cancels. Space toggles, A toggles all optional items, Enter continues. Number keys 1-${options.length} toggle items.${ANSI.reset}\n`);
|
|
550
|
+
};
|
|
551
|
+
const cancel = () => {
|
|
552
|
+
cleanup();
|
|
553
|
+
process.stdout.write('\n');
|
|
554
|
+
reject(new WizardAbortError('Setup cancelled.'));
|
|
555
|
+
};
|
|
556
|
+
const finish = () => {
|
|
557
|
+
const values = selectedValues();
|
|
558
|
+
if (values.length < minSelections) {
|
|
559
|
+
warning = `Select at least ${minSelections} item${minSelections === 1 ? '' : 's'} to continue.`;
|
|
560
|
+
render();
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
cleanup();
|
|
564
|
+
process.stdout.write('\x1b[2J\x1b[H');
|
|
565
|
+
resolve(values);
|
|
566
|
+
};
|
|
567
|
+
const toggleIndex = (index) => {
|
|
568
|
+
const option = options[index];
|
|
569
|
+
if (!option)
|
|
570
|
+
return;
|
|
571
|
+
warning = '';
|
|
572
|
+
if (required.has(option.value)) {
|
|
573
|
+
selected.add(option.value);
|
|
574
|
+
warning = `${option.label} is required.`;
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
577
|
+
if (selected.has(option.value))
|
|
578
|
+
selected.delete(option.value);
|
|
579
|
+
else
|
|
580
|
+
selected.add(option.value);
|
|
581
|
+
requiredValues.forEach((value) => selected.add(value));
|
|
582
|
+
};
|
|
583
|
+
const onKeypress = (_text, key) => {
|
|
584
|
+
if (key?.ctrl && key?.name === 'c') {
|
|
585
|
+
cancel();
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
if (key?.name === 'escape' || key?.name === 'q') {
|
|
589
|
+
cancel();
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
if (key?.name === 'up' || key?.name === 'k') {
|
|
593
|
+
cursorIndex = (cursorIndex - 1 + options.length) % options.length;
|
|
594
|
+
warning = '';
|
|
595
|
+
}
|
|
596
|
+
else if (key?.name === 'down' || key?.name === 'j') {
|
|
597
|
+
cursorIndex = (cursorIndex + 1) % options.length;
|
|
598
|
+
warning = '';
|
|
599
|
+
}
|
|
600
|
+
else if (key?.name === 'space') {
|
|
601
|
+
toggleIndex(cursorIndex);
|
|
602
|
+
}
|
|
603
|
+
else if (String(_text || '').toLowerCase() === 'a') {
|
|
604
|
+
const optional = options.filter((option) => !required.has(option.value));
|
|
605
|
+
const allSelected = optional.every((option) => selected.has(option.value));
|
|
606
|
+
optional.forEach((option) => {
|
|
607
|
+
if (allSelected)
|
|
608
|
+
selected.delete(option.value);
|
|
609
|
+
else
|
|
610
|
+
selected.add(option.value);
|
|
611
|
+
});
|
|
612
|
+
requiredValues.forEach((value) => selected.add(value));
|
|
613
|
+
warning = '';
|
|
614
|
+
}
|
|
615
|
+
else if (key?.name === 'return' || key?.name === 'enter') {
|
|
616
|
+
finish();
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
else if (/^[1-9]$/.test(String(_text || ''))) {
|
|
620
|
+
toggleIndex(Number(_text) - 1);
|
|
621
|
+
}
|
|
622
|
+
render();
|
|
623
|
+
};
|
|
624
|
+
process.stdin.on('keypress', onKeypress);
|
|
625
|
+
process.stdout.write(ANSI.hideCursor);
|
|
626
|
+
render();
|
|
627
|
+
});
|
|
628
|
+
}
|
|
465
629
|
async function askMenuChoiceByKeys({ title, subtitle, options, defaultValue, renderHeader, }) {
|
|
466
630
|
emitKeypressEvents(process.stdin);
|
|
467
631
|
const wasRaw = process.stdin.isRaw;
|
|
@@ -2885,12 +3049,32 @@ async function askYesNo(rl, label, defaultYes = true) {
|
|
|
2885
3049
|
}
|
|
2886
3050
|
}
|
|
2887
3051
|
}
|
|
3052
|
+
function truncateTableCell(value, width) {
|
|
3053
|
+
const text = String(value || '').replace(/\s+/g, ' ').trim();
|
|
3054
|
+
if (text.length <= width)
|
|
3055
|
+
return text.padEnd(width, ' ');
|
|
3056
|
+
return `${text.slice(0, Math.max(0, width - 3))}...`.padEnd(width, ' ');
|
|
3057
|
+
}
|
|
3058
|
+
function printAsciiTable(headers, rows, widths) {
|
|
3059
|
+
const border = `+${widths.map((width) => '-'.repeat(width + 2)).join('+')}+`;
|
|
3060
|
+
const renderRow = (cells) => `| ${cells.map((cell, index) => truncateTableCell(cell, widths[index])).join(' | ')} |`;
|
|
3061
|
+
process.stdout.write(`${border}\n`);
|
|
3062
|
+
process.stdout.write(`${renderRow(headers)}\n`);
|
|
3063
|
+
process.stdout.write(`${border}\n`);
|
|
3064
|
+
for (const row of rows) {
|
|
3065
|
+
process.stdout.write(`${renderRow(row)}\n`);
|
|
3066
|
+
}
|
|
3067
|
+
process.stdout.write(`${border}\n`);
|
|
3068
|
+
}
|
|
2888
3069
|
function printCadencePlan(cadences) {
|
|
2889
3070
|
process.stdout.write('\nDefault growth cadence:\n');
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
3071
|
+
printAsciiTable(['Cadence', 'Every', 'Mode', 'Primary focus', 'What it decides'], cadences.map((cadence) => [
|
|
3072
|
+
cadence.key,
|
|
3073
|
+
`${cadence.intervalDays}d`,
|
|
3074
|
+
cadence.criticalOnly ? 'critical only' : 'full review',
|
|
3075
|
+
Array.isArray(cadence.focusAreas) ? cadence.focusAreas.slice(0, 4).join(', ') : '',
|
|
3076
|
+
cadence.objective,
|
|
3077
|
+
]), [12, 7, 13, 30, 42]);
|
|
2894
3078
|
process.stdout.write('\n');
|
|
2895
3079
|
}
|
|
2896
3080
|
async function askToolUsage(rl) {
|
|
@@ -2917,18 +3101,37 @@ async function askToolUsage(rl) {
|
|
|
2917
3101
|
],
|
|
2918
3102
|
});
|
|
2919
3103
|
}
|
|
2920
|
-
async function askCadencePlan(rl) {
|
|
2921
|
-
const
|
|
3104
|
+
async function askCadencePlan(rl, existingCadences = []) {
|
|
3105
|
+
const existingByKey = new Map((Array.isArray(existingCadences) ? existingCadences : [])
|
|
3106
|
+
.filter((cadence) => cadence?.key)
|
|
3107
|
+
.map((cadence) => [String(cadence.key), cadence]));
|
|
3108
|
+
const cadences = DEFAULT_CADENCE_PLAN.map((cadence) => ({
|
|
3109
|
+
...cadence,
|
|
3110
|
+
...(existingByKey.get(cadence.key) || {}),
|
|
3111
|
+
}));
|
|
2922
3112
|
printCadencePlan(cadences);
|
|
2923
|
-
const
|
|
2924
|
-
|
|
3113
|
+
const selectedCadences = await askMultiChoice(rl, {
|
|
3114
|
+
title: 'Scheduled review cadences',
|
|
3115
|
+
subtitle: 'Use Up/Down to move, Space to toggle cadences, A to toggle all, Enter to continue.',
|
|
3116
|
+
defaultValues: cadences.filter((cadence) => cadence.enabled !== false).map((cadence) => cadence.key),
|
|
3117
|
+
minSelections: 1,
|
|
3118
|
+
options: cadences.map((cadence) => ({
|
|
3119
|
+
value: cadence.key,
|
|
3120
|
+
label: cadence.title,
|
|
3121
|
+
detail: `${cadence.intervalDays}d, ${cadence.criticalOnly ? 'critical only' : 'full review'} - ${cadence.objective}`,
|
|
3122
|
+
})),
|
|
3123
|
+
});
|
|
3124
|
+
const selected = new Set(selectedCadences);
|
|
3125
|
+
cadences.forEach((cadence) => {
|
|
3126
|
+
cadence.enabled = selected.has(cadence.key);
|
|
3127
|
+
});
|
|
3128
|
+
const customize = await askYesNo(rl, 'Customize objectives, instructions, focus areas, or source priorities for enabled cadences?', false);
|
|
3129
|
+
if (!customize)
|
|
2925
3130
|
return cadences;
|
|
2926
3131
|
for (const cadence of cadences) {
|
|
2927
|
-
|
|
2928
|
-
const enabled = await askYesNo(rl, `Enable ${cadence.key}?`, true);
|
|
2929
|
-
cadence.enabled = enabled;
|
|
2930
|
-
if (!enabled)
|
|
3132
|
+
if (cadence.enabled === false)
|
|
2931
3133
|
continue;
|
|
3134
|
+
process.stdout.write(`\n${cadence.title}\n`);
|
|
2932
3135
|
cadence.objective = await ask(rl, `${cadence.key} objective`, cadence.objective);
|
|
2933
3136
|
cadence.instructions = await ask(rl, `${cadence.key} instructions`, cadence.instructions);
|
|
2934
3137
|
const focusAreas = await ask(rl, `${cadence.key} focus areas (comma-separated)`, cadence.focusAreas.join(','));
|
|
@@ -2992,7 +3195,7 @@ async function buildDefaultWizardConfig() {
|
|
|
2992
3195
|
command: getWizardDefaultSourceCommand('analytics'),
|
|
2993
3196
|
},
|
|
2994
3197
|
revenuecat: {
|
|
2995
|
-
enabled:
|
|
3198
|
+
enabled: true,
|
|
2996
3199
|
mode: 'command',
|
|
2997
3200
|
command: getWizardDefaultSourceCommand('revenuecat'),
|
|
2998
3201
|
},
|
|
@@ -3009,7 +3212,7 @@ async function buildDefaultWizardConfig() {
|
|
|
3009
3212
|
initialLookback: '30d',
|
|
3010
3213
|
},
|
|
3011
3214
|
extra: [
|
|
3012
|
-
buildExtraSourceConfig('asc-cli', { enabled:
|
|
3215
|
+
buildExtraSourceConfig('asc-cli', { enabled: true, mode: 'command', command: getWizardDefaultSourceCommand('asc') }),
|
|
3013
3216
|
],
|
|
3014
3217
|
},
|
|
3015
3218
|
schedule: {
|
|
@@ -3025,6 +3228,7 @@ async function buildDefaultWizardConfig() {
|
|
|
3025
3228
|
autoCreateWhenGitHubWriteAccess: true,
|
|
3026
3229
|
disableAutoCreateGitHubArtifacts: false,
|
|
3027
3230
|
mode: 'issue',
|
|
3231
|
+
outputDestinations: ['openclaw_chat', 'github_issue', 'github_pull_request'],
|
|
3028
3232
|
usageMode: 'production_autopilot',
|
|
3029
3233
|
draftPullRequests: true,
|
|
3030
3234
|
proposalBranchPrefix: 'openclaw/proposals',
|
|
@@ -3058,7 +3262,7 @@ async function buildDefaultWizardConfig() {
|
|
|
3058
3262
|
},
|
|
3059
3263
|
},
|
|
3060
3264
|
charting: {
|
|
3061
|
-
enabled:
|
|
3265
|
+
enabled: true,
|
|
3062
3266
|
command: null,
|
|
3063
3267
|
},
|
|
3064
3268
|
notifications: {
|
|
@@ -3105,7 +3309,7 @@ function buildRecommendedSourceConfig() {
|
|
|
3105
3309
|
command: getWizardDefaultSourceCommand('analytics'),
|
|
3106
3310
|
},
|
|
3107
3311
|
revenuecat: {
|
|
3108
|
-
enabled:
|
|
3312
|
+
enabled: true,
|
|
3109
3313
|
mode: 'command',
|
|
3110
3314
|
command: getWizardDefaultSourceCommand('revenuecat'),
|
|
3111
3315
|
},
|
|
@@ -3122,7 +3326,7 @@ function buildRecommendedSourceConfig() {
|
|
|
3122
3326
|
initialLookback: '30d',
|
|
3123
3327
|
},
|
|
3124
3328
|
extra: [
|
|
3125
|
-
buildExtraSourceConfig('asc-cli', { enabled:
|
|
3329
|
+
buildExtraSourceConfig('asc-cli', { enabled: true, mode: 'command', command: getWizardDefaultSourceCommand('asc') }),
|
|
3126
3330
|
],
|
|
3127
3331
|
};
|
|
3128
3332
|
}
|
|
@@ -3131,6 +3335,8 @@ function getInputChannelInitialSelection(config) {
|
|
|
3131
3335
|
const extraSources = Array.isArray(sources.extra) ? sources.extra : [];
|
|
3132
3336
|
const selected = new Set();
|
|
3133
3337
|
const hasExplicitSources = Boolean(config?.sources);
|
|
3338
|
+
if (!hasExplicitSources)
|
|
3339
|
+
return orderConnectors([...CONNECTOR_KEYS]);
|
|
3134
3340
|
if (!hasExplicitSources || sources.analytics?.enabled !== false)
|
|
3135
3341
|
selected.add('analytics');
|
|
3136
3342
|
if (sources.revenuecat?.enabled === true || isConnectorLocallyConfigured('revenuecat'))
|
|
@@ -3142,12 +3348,9 @@ function getInputChannelInitialSelection(config) {
|
|
|
3142
3348
|
isConnectorLocallyConfigured('asc')) {
|
|
3143
3349
|
selected.add('asc');
|
|
3144
3350
|
}
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
isConnectorLocallyConfigured('github')) {
|
|
3149
|
-
selected.add('github');
|
|
3150
|
-
}
|
|
3351
|
+
selected.add('github');
|
|
3352
|
+
if (selected.size === 0)
|
|
3353
|
+
return orderConnectors([...CONNECTOR_KEYS]);
|
|
3151
3354
|
return orderConnectors([...selected]);
|
|
3152
3355
|
}
|
|
3153
3356
|
function buildSourceConfigFromInputChannels(selectedConnectors, existingSources = {}) {
|
|
@@ -3266,11 +3469,25 @@ async function askOutputConfig(rl, config) {
|
|
|
3266
3469
|
'GitHub issues or draft PRs are optional and only run when a token plus an inferred repo are available.',
|
|
3267
3470
|
]);
|
|
3268
3471
|
const currentMode = config?.actions?.mode || config?.deliveries?.github?.mode || 'issue';
|
|
3269
|
-
const
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3472
|
+
const configuredDestinations = Array.isArray(config?.actions?.outputDestinations)
|
|
3473
|
+
? config.actions.outputDestinations
|
|
3474
|
+
: [];
|
|
3475
|
+
const currentAutoCreateIssue = Boolean(config?.actions?.autoCreateIssues ||
|
|
3476
|
+
configuredDestinations.includes('github_issue') ||
|
|
3477
|
+
(config?.deliveries?.github?.autoCreate && currentMode !== 'pull_request'));
|
|
3478
|
+
const currentAutoCreatePullRequest = Boolean(config?.actions?.autoCreatePullRequests ||
|
|
3479
|
+
configuredDestinations.includes('github_pull_request') ||
|
|
3480
|
+
(config?.deliveries?.github?.autoCreate && currentMode === 'pull_request'));
|
|
3481
|
+
const outputChoices = await askMultiChoice(rl, {
|
|
3482
|
+
title: 'Output destinations',
|
|
3483
|
+
subtitle: 'Use Up/Down to move, Space to toggle outputs, A to toggle all optional outputs, Enter to continue.',
|
|
3484
|
+
defaultValues: [
|
|
3485
|
+
'chat',
|
|
3486
|
+
...(currentAutoCreateIssue ? ['issue'] : []),
|
|
3487
|
+
...(currentAutoCreatePullRequest ? ['pull_request'] : []),
|
|
3488
|
+
],
|
|
3489
|
+
requiredValues: ['chat'],
|
|
3490
|
+
minSelections: 1,
|
|
3274
3491
|
options: [
|
|
3275
3492
|
{
|
|
3276
3493
|
value: 'chat',
|
|
@@ -3289,9 +3506,11 @@ async function askOutputConfig(rl, config) {
|
|
|
3289
3506
|
},
|
|
3290
3507
|
],
|
|
3291
3508
|
});
|
|
3292
|
-
const
|
|
3293
|
-
const
|
|
3294
|
-
const
|
|
3509
|
+
const wantsIssue = outputChoices.includes('issue');
|
|
3510
|
+
const wantsPullRequest = outputChoices.includes('pull_request');
|
|
3511
|
+
const summaryOnly = !wantsIssue && !wantsPullRequest;
|
|
3512
|
+
const mode = wantsPullRequest ? 'pull_request' : 'issue';
|
|
3513
|
+
const autoCreate = wantsIssue || wantsPullRequest;
|
|
3295
3514
|
if (!summaryOnly) {
|
|
3296
3515
|
process.stdout.write('GitHub repo scope is not pinned by the wizard; OpenClaw/Hermes will infer it from OPENCLAW_GITHUB_REPO, the local git remote, or runtime context when creating issues/PRs.\n');
|
|
3297
3516
|
}
|
|
@@ -3308,8 +3527,13 @@ async function askOutputConfig(rl, config) {
|
|
|
3308
3527
|
config.actions = {
|
|
3309
3528
|
...(config.actions || {}),
|
|
3310
3529
|
mode,
|
|
3311
|
-
|
|
3312
|
-
|
|
3530
|
+
outputDestinations: [
|
|
3531
|
+
'openclaw_chat',
|
|
3532
|
+
...(wantsIssue ? ['github_issue'] : []),
|
|
3533
|
+
...(wantsPullRequest ? ['github_pull_request'] : []),
|
|
3534
|
+
],
|
|
3535
|
+
autoCreateIssues: wantsIssue,
|
|
3536
|
+
autoCreatePullRequests: wantsPullRequest,
|
|
3313
3537
|
autoCreateWhenGitHubWriteAccess: config.actions?.autoCreateWhenGitHubWriteAccess !== false,
|
|
3314
3538
|
disableAutoCreateGitHubArtifacts: config.actions?.disableAutoCreateGitHubArtifacts === true,
|
|
3315
3539
|
draftPullRequests: true,
|
|
@@ -3327,6 +3551,10 @@ async function askOutputConfig(rl, config) {
|
|
|
3327
3551
|
...(config.deliveries?.github || {}),
|
|
3328
3552
|
enabled: !summaryOnly,
|
|
3329
3553
|
mode,
|
|
3554
|
+
modes: [
|
|
3555
|
+
...(wantsIssue ? ['issue'] : []),
|
|
3556
|
+
...(wantsPullRequest ? ['pull_request'] : []),
|
|
3557
|
+
],
|
|
3330
3558
|
autoCreate,
|
|
3331
3559
|
draftPullRequests: true,
|
|
3332
3560
|
proposalBranchPrefix: config?.actions?.proposalBranchPrefix || 'openclaw/proposals',
|
|
@@ -3388,7 +3616,7 @@ async function askGitHubArtifactDetails(rl, config) {
|
|
|
3388
3616
|
if (!customize) {
|
|
3389
3617
|
config.charting = {
|
|
3390
3618
|
...(config.charting || {}),
|
|
3391
|
-
enabled: config.charting?.enabled
|
|
3619
|
+
enabled: config.charting?.enabled !== false,
|
|
3392
3620
|
command: config.charting?.command || null,
|
|
3393
3621
|
};
|
|
3394
3622
|
return config;
|
|
@@ -3419,7 +3647,7 @@ async function askIntervalConfig(rl, config) {
|
|
|
3419
3647
|
const usageMode = await askToolUsage(rl);
|
|
3420
3648
|
const intervalMinutes = Number.parseInt(await ask(rl, 'Growth runner wake-up interval in minutes', String(currentSchedule.intervalMinutes || DEFAULT_GROWTH_INTERVAL_MINUTES)), 10) || DEFAULT_GROWTH_INTERVAL_MINUTES;
|
|
3421
3649
|
const connectorHealthCheckIntervalMinutes = Number.parseInt(await ask(rl, 'Connector health check interval in minutes', String(currentSchedule.connectorHealthCheckIntervalMinutes || DEFAULT_CONNECTOR_HEALTH_INTERVAL_MINUTES)), 10) || DEFAULT_CONNECTOR_HEALTH_INTERVAL_MINUTES;
|
|
3422
|
-
const cadences = await askCadencePlan(rl);
|
|
3650
|
+
const cadences = await askCadencePlan(rl, currentSchedule.cadences);
|
|
3423
3651
|
config.schedule = {
|
|
3424
3652
|
...currentSchedule,
|
|
3425
3653
|
intervalMinutes,
|