@in-the-loop-labs/pair-review 3.2.3 → 3.3.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/README.md +7 -6
- package/package.json +5 -4
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin-code-critic/.claude-plugin/plugin.json +1 -1
- package/public/css/repo-settings.css +347 -0
- package/public/index.html +46 -9
- package/public/js/components/AIPanel.js +79 -37
- package/public/js/components/DiffOptionsDropdown.js +84 -1
- package/public/js/index.js +31 -6
- package/public/js/pr.js +22 -0
- package/public/js/repo-settings.js +334 -6
- package/public/repo-settings.html +29 -0
- package/src/ai/analyzer.js +28 -19
- package/src/ai/claude-cli.js +2 -0
- package/src/ai/claude-provider.js +4 -1
- package/src/ai/provider.js +7 -6
- package/src/chat/session-manager.js +6 -3
- package/src/config.js +230 -38
- package/src/database.js +766 -38
- package/src/git/worktree-pool-lifecycle.js +674 -0
- package/src/git/worktree-pool-usage.js +216 -0
- package/src/git/worktree.js +46 -13
- package/src/main.js +185 -26
- package/src/routes/analyses.js +48 -26
- package/src/routes/chat.js +27 -3
- package/src/routes/config.js +17 -5
- package/src/routes/executable-analysis.js +38 -19
- package/src/routes/local.js +19 -6
- package/src/routes/mcp.js +13 -2
- package/src/routes/pr.js +72 -29
- package/src/routes/setup.js +41 -4
- package/src/routes/stack-analysis.js +29 -10
- package/src/routes/worktrees.js +294 -9
- package/src/server.js +20 -3
- package/src/setup/pr-setup.js +161 -27
- package/src/ws/server.js +51 -1
|
@@ -198,6 +198,22 @@ Examples:
|
|
|
198
198
|
</div>
|
|
199
199
|
</section>
|
|
200
200
|
|
|
201
|
+
<!-- Provider Skill Discovery Section -->
|
|
202
|
+
<section class="settings-section">
|
|
203
|
+
<div class="section-header">
|
|
204
|
+
<h2>Provider Skill Discovery</h2>
|
|
205
|
+
<p class="section-description">Controls whether AI providers load environment-level skills automatically. Currently applies to Pi's skill auto-discovery. When disabled, Pi runs with <code>--no-skills</code>.</p>
|
|
206
|
+
</div>
|
|
207
|
+
<div class="form-group" style="max-width: 300px;">
|
|
208
|
+
<label for="load-skills-select" class="settings-label">Load Skills</label>
|
|
209
|
+
<select class="settings-select" id="load-skills-select">
|
|
210
|
+
<option value="">Default (inherit from config)</option>
|
|
211
|
+
<option value="1">Enabled</option>
|
|
212
|
+
<option value="0">Disabled</option>
|
|
213
|
+
</select>
|
|
214
|
+
</div>
|
|
215
|
+
</section>
|
|
216
|
+
|
|
201
217
|
<!-- Repository Location Section -->
|
|
202
218
|
<section class="settings-section" id="local-path-section">
|
|
203
219
|
<div class="section-header">
|
|
@@ -227,6 +243,19 @@ Examples:
|
|
|
227
243
|
</div>
|
|
228
244
|
</section>
|
|
229
245
|
|
|
246
|
+
<!-- Worktrees Section -->
|
|
247
|
+
<section class="settings-section" id="worktrees-section" style="display: none;">
|
|
248
|
+
<div class="section-header">
|
|
249
|
+
<h2>Worktrees</h2>
|
|
250
|
+
<p class="section-description">
|
|
251
|
+
Manage worktree directories used for reviewing pull requests in this repository.
|
|
252
|
+
</p>
|
|
253
|
+
</div>
|
|
254
|
+
<div id="worktrees-content">
|
|
255
|
+
<!-- Rendered dynamically by JS -->
|
|
256
|
+
</div>
|
|
257
|
+
</section>
|
|
258
|
+
|
|
230
259
|
<!-- Danger Zone -->
|
|
231
260
|
<section class="settings-section danger-zone">
|
|
232
261
|
<div class="section-header">
|
package/src/ai/analyzer.js
CHANGED
|
@@ -73,9 +73,10 @@ async function captureDiffSnapshot(analyzer, worktreePath, prMetadata, logPrefix
|
|
|
73
73
|
* @param {Object|null} instructions - Instructions object { repoInstructions, requestInstructions }
|
|
74
74
|
* @param {Function|null} progressCallback - Parent progress callback to wrap
|
|
75
75
|
* @param {Object} db - Database instance
|
|
76
|
+
* @param {Object} providerOverrides - Per-call config overrides passed to createProvider (optional)
|
|
76
77
|
* @returns {Object} { voiceAnalyzer, voiceKey, reviewerLabel, voiceRequestInstructions, voiceProgressCallback, voiceTier, voiceTimeout }
|
|
77
78
|
*/
|
|
78
|
-
function buildVoiceContext(voice, idx, instructions, progressCallback, db) {
|
|
79
|
+
function buildVoiceContext(voice, idx, instructions, progressCallback, db, providerOverrides = {}, providerOverridesMap = null) {
|
|
79
80
|
const voiceKey = `${voice.provider}-${voice.model}${idx > 0 ? `-${idx}` : ''}`;
|
|
80
81
|
const reviewerLabel = buildReviewerLabel(idx, voice);
|
|
81
82
|
|
|
@@ -87,13 +88,16 @@ function buildVoiceContext(voice, idx, instructions, progressCallback, db) {
|
|
|
87
88
|
: voice.customInstructions;
|
|
88
89
|
}
|
|
89
90
|
|
|
91
|
+
// Resolve per-voice overrides: prefer provider-specific from map, fall back to shared overrides
|
|
92
|
+
const effectiveOverrides = providerOverridesMap?.[voice.provider] || providerOverrides;
|
|
93
|
+
|
|
90
94
|
const ProviderClass = getProviderClass(voice.provider);
|
|
91
95
|
const isExecutable = ProviderClass?.isExecutable || false;
|
|
92
96
|
|
|
93
97
|
// Only create Analyzer for native voices
|
|
94
|
-
const voiceAnalyzer = isExecutable ? null : new Analyzer(db, voice.model, voice.provider);
|
|
98
|
+
const voiceAnalyzer = isExecutable ? null : new Analyzer(db, voice.model, voice.provider, effectiveOverrides);
|
|
95
99
|
// Create provider instance for executable voices (used directly)
|
|
96
|
-
const voiceProvider = isExecutable ? createProvider(voice.provider, voice.model) : null;
|
|
100
|
+
const voiceProvider = isExecutable ? createProvider(voice.provider, voice.model, effectiveOverrides) : null;
|
|
97
101
|
|
|
98
102
|
const voiceTier = voice.tier || 'balanced';
|
|
99
103
|
const voiceTimeout = voice.timeout || ProviderClass?.defaultTimeout || 600000;
|
|
@@ -272,12 +276,16 @@ class Analyzer {
|
|
|
272
276
|
* @param {Object} database - Database instance
|
|
273
277
|
* @param {string} model - Model to use (e.g., 'opus', 'gemini-2.5-pro')
|
|
274
278
|
* @param {string} provider - Provider ID (e.g., 'claude', 'gemini'). Defaults to 'claude'.
|
|
279
|
+
* @param {Object} providerOverrides - Per-call config overrides passed to createProvider (optional)
|
|
280
|
+
* @param {Object|null} providerOverridesMap - Per-provider overrides map for council mode (provider ID → overrides)
|
|
275
281
|
*/
|
|
276
|
-
constructor(database, model = 'opus', provider = 'claude') {
|
|
282
|
+
constructor(database, model = 'opus', provider = 'claude', providerOverrides = {}, providerOverridesMap = null) {
|
|
277
283
|
// Store model and provider for creating provider instances per level
|
|
278
284
|
this.model = model;
|
|
279
285
|
this.provider = provider;
|
|
280
286
|
this.db = database;
|
|
287
|
+
this.providerOverrides = providerOverrides;
|
|
288
|
+
this.providerOverridesMap = providerOverridesMap;
|
|
281
289
|
this.testContextCache = new Map(); // Cache test detection results per worktree
|
|
282
290
|
this._worktreeManager = null; // Lazy-initialized for sparse-checkout queries
|
|
283
291
|
}
|
|
@@ -1015,7 +1023,7 @@ Or simply ignore any changes to files matching these patterns in your analysis.
|
|
|
1015
1023
|
}
|
|
1016
1024
|
|
|
1017
1025
|
// Create provider instance for this level
|
|
1018
|
-
const aiProvider = createProvider(this.provider, this.model);
|
|
1026
|
+
const aiProvider = createProvider(this.provider, this.model, this.providerOverrides);
|
|
1019
1027
|
|
|
1020
1028
|
const updateProgress = (step) => {
|
|
1021
1029
|
const progress = `${lp}[Level 1] ${step}...`;
|
|
@@ -1975,7 +1983,7 @@ If you are unsure, use "NEW" - it is correct for the vast majority of suggestion
|
|
|
1975
1983
|
}
|
|
1976
1984
|
|
|
1977
1985
|
// Create provider instance for this level
|
|
1978
|
-
const aiProvider = createProvider(this.provider, this.model);
|
|
1986
|
+
const aiProvider = createProvider(this.provider, this.model, this.providerOverrides);
|
|
1979
1987
|
|
|
1980
1988
|
const updateProgress = (step) => {
|
|
1981
1989
|
const progress = `${lp}[Level 2] ${step}...`;
|
|
@@ -2085,7 +2093,7 @@ If you are unsure, use "NEW" - it is correct for the vast majority of suggestion
|
|
|
2085
2093
|
}
|
|
2086
2094
|
|
|
2087
2095
|
// Create provider instance for this level
|
|
2088
|
-
const aiProvider = createProvider(this.provider, this.model);
|
|
2096
|
+
const aiProvider = createProvider(this.provider, this.model, this.providerOverrides);
|
|
2089
2097
|
|
|
2090
2098
|
const updateProgress = (step) => {
|
|
2091
2099
|
const progress = `${lp}[Level 3] ${step}...`;
|
|
@@ -2655,7 +2663,7 @@ File-level suggestions should NOT have a line number. They apply to the entire f
|
|
|
2655
2663
|
}
|
|
2656
2664
|
|
|
2657
2665
|
// Create provider instance for consolidation (use overrides if provided)
|
|
2658
|
-
const aiProvider = createProvider(providerOverride || this.provider, modelOverride || this.model);
|
|
2666
|
+
const aiProvider = createProvider(providerOverride || this.provider, modelOverride || this.model, this.providerOverrides);
|
|
2659
2667
|
|
|
2660
2668
|
// Build the consolidation prompt
|
|
2661
2669
|
const prompt = this.buildOrchestrationPrompt(allSuggestions, prMetadata, customInstructions, worktreePath, tier, lp, { excludePrevious, dedupContext });
|
|
@@ -2932,7 +2940,7 @@ File-level suggestions should NOT have a line number. They apply to the entire f
|
|
|
2932
2940
|
if (voices.length === 1) {
|
|
2933
2941
|
const voice = voices[0];
|
|
2934
2942
|
const { voiceAnalyzer, voiceProvider, isExecutable, voiceKey, reviewerLabel, voiceRequestInstructions, voiceProgressCallback, voiceTier, voiceTimeout } =
|
|
2935
|
-
buildVoiceContext(voice, 0, instructions, progressCallback, this.db);
|
|
2943
|
+
buildVoiceContext(voice, 0, instructions, progressCallback, this.db, this.providerOverrides, this.providerOverridesMap);
|
|
2936
2944
|
logger.info(`[ReviewerCouncil] Single reviewer (${reviewerLabel}) — running directly on parent run, no child run`);
|
|
2937
2945
|
|
|
2938
2946
|
// Report voice-centric progress structure
|
|
@@ -3034,7 +3042,7 @@ File-level suggestions should NOT have a line number. They apply to the entire f
|
|
|
3034
3042
|
const commentRepo = new CommentRepository(this.db);
|
|
3035
3043
|
const voicePromises = voices.map(async (voice, idx) => {
|
|
3036
3044
|
const { voiceAnalyzer, voiceProvider, isExecutable, voiceKey, reviewerLabel, voiceRequestInstructions, voiceProgressCallback, voiceTier, voiceTimeout } =
|
|
3037
|
-
buildVoiceContext(voice, idx, instructions, progressCallback, this.db);
|
|
3045
|
+
buildVoiceContext(voice, idx, instructions, progressCallback, this.db, this.providerOverrides, this.providerOverridesMap);
|
|
3038
3046
|
const childRunId = uuidv4();
|
|
3039
3047
|
|
|
3040
3048
|
// Create child analysis run record
|
|
@@ -3271,7 +3279,7 @@ File-level suggestions should NOT have a line number. They apply to the entire f
|
|
|
3271
3279
|
|
|
3272
3280
|
const consolidated = await this._crossVoiceConsolidate(
|
|
3273
3281
|
voiceReviews, prMetadata, consolInstructions, worktreePath,
|
|
3274
|
-
{ provider: consolProvider, model: consolModel, tier: consolTier, timeout: consolConfig.timeout, analysisId, progressCallback, excludePrevious, dedupContext }
|
|
3282
|
+
{ provider: consolProvider, model: consolModel, tier: consolTier, timeout: consolConfig.timeout, analysisId, progressCallback, excludePrevious, dedupContext, providerOverrides: this.providerOverrides }
|
|
3275
3283
|
);
|
|
3276
3284
|
|
|
3277
3285
|
const finalSuggestions = this.validateAndFinalizeSuggestions(
|
|
@@ -3410,7 +3418,8 @@ File-level suggestions should NOT have a line number. They apply to the entire f
|
|
|
3410
3418
|
tier,
|
|
3411
3419
|
timeout: voice.timeout || VoiceProviderClass?.defaultTimeout || 600000,
|
|
3412
3420
|
customInstructions: voiceInstructions,
|
|
3413
|
-
voiceCustomInstructions: voice.customInstructions || null
|
|
3421
|
+
voiceCustomInstructions: voice.customInstructions || null,
|
|
3422
|
+
providerOverrides: this.providerOverridesMap?.[voice.provider] || this.providerOverrides
|
|
3414
3423
|
});
|
|
3415
3424
|
}
|
|
3416
3425
|
}
|
|
@@ -3575,7 +3584,7 @@ File-level suggestions should NOT have a line number. They apply to the entire f
|
|
|
3575
3584
|
}));
|
|
3576
3585
|
const consolidated = await this._intraLevelConsolidate(
|
|
3577
3586
|
level, voiceGroups, prMetadata, orchInstructions, worktreePath,
|
|
3578
|
-
{ provider: orchProvider, model: orchModel, tier: orchTier, timeout: orchConfig.timeout, analysisId, progressCallback, reviewerCount: successfulVoicesForLevel.length }
|
|
3587
|
+
{ provider: orchProvider, model: orchModel, tier: orchTier, timeout: orchConfig.timeout, analysisId, progressCallback, reviewerCount: successfulVoicesForLevel.length, providerOverrides: this.providerOverrides }
|
|
3579
3588
|
);
|
|
3580
3589
|
consolidatedPerLevel[level] = consolidated;
|
|
3581
3590
|
// Report intra-level consolidation step as completed
|
|
@@ -3661,7 +3670,7 @@ File-level suggestions should NOT have a line number. They apply to the entire f
|
|
|
3661
3670
|
* @private
|
|
3662
3671
|
*/
|
|
3663
3672
|
async _executeCouncilVoice(task, context) {
|
|
3664
|
-
const { voiceId, reviewerLabel, reviewerLogPrefix, level, provider, model, tier, timeout = 600000, customInstructions } = task;
|
|
3673
|
+
const { voiceId, reviewerLabel, reviewerLogPrefix, level, provider, model, tier, timeout = 600000, customInstructions, providerOverrides } = task;
|
|
3665
3674
|
const { reviewId, runId, worktreePath, prMetadata, generatedPatterns, validFiles, analysisId, progressCallback } = context;
|
|
3666
3675
|
const displayLabel = reviewerLabel || voiceId;
|
|
3667
3676
|
|
|
@@ -3672,7 +3681,7 @@ File-level suggestions should NOT have a line number. They apply to the entire f
|
|
|
3672
3681
|
}
|
|
3673
3682
|
|
|
3674
3683
|
// Create provider instance for this voice
|
|
3675
|
-
const aiProvider = createProvider(provider, model);
|
|
3684
|
+
const aiProvider = createProvider(provider, model, providerOverrides || {});
|
|
3676
3685
|
|
|
3677
3686
|
// Build prompt based on level
|
|
3678
3687
|
let prompt;
|
|
@@ -3748,9 +3757,9 @@ File-level suggestions should NOT have a line number. They apply to the entire f
|
|
|
3748
3757
|
* @private
|
|
3749
3758
|
*/
|
|
3750
3759
|
async _intraLevelConsolidate(level, voiceGroups, prMetadata, customInstructions, worktreePath, orchConfig) {
|
|
3751
|
-
const { provider, model, tier, timeout, analysisId, progressCallback, reviewerCount } = orchConfig;
|
|
3760
|
+
const { provider, model, tier, timeout, analysisId, progressCallback, reviewerCount, providerOverrides } = orchConfig;
|
|
3752
3761
|
|
|
3753
|
-
const aiProvider = createProvider(provider, model);
|
|
3762
|
+
const aiProvider = createProvider(provider, model, providerOverrides || {});
|
|
3754
3763
|
|
|
3755
3764
|
const isLocal = prMetadata.reviewType === 'local';
|
|
3756
3765
|
const reviewDescription = isLocal
|
|
@@ -3916,9 +3925,9 @@ File-level suggestions should NOT have a line number. They apply to the entire f
|
|
|
3916
3925
|
* @private
|
|
3917
3926
|
*/
|
|
3918
3927
|
async _crossVoiceConsolidate(voiceReviews, prMetadata, customInstructions, worktreePath, config) {
|
|
3919
|
-
const { provider, model, tier, timeout, analysisId, progressCallback, excludePrevious, dedupContext } = config;
|
|
3928
|
+
const { provider, model, tier, timeout, analysisId, progressCallback, excludePrevious, dedupContext, providerOverrides } = config;
|
|
3920
3929
|
|
|
3921
|
-
const aiProvider = createProvider(provider, model);
|
|
3930
|
+
const aiProvider = createProvider(provider, model, providerOverrides || {});
|
|
3922
3931
|
|
|
3923
3932
|
const voiceDescriptions = voiceReviews.map(v => {
|
|
3924
3933
|
let desc = `### Reviewer: ${v.voiceKey}`;
|
package/src/ai/claude-cli.js
CHANGED
|
@@ -53,6 +53,8 @@ class ClaudeCLI {
|
|
|
53
53
|
});
|
|
54
54
|
|
|
55
55
|
const pid = claude.pid;
|
|
56
|
+
const fullCommand = this.useShell ? this.command : `${this.command} ${this.args.join(' ')}`;
|
|
57
|
+
logger.debug(`${levelPrefix} Claude CLI command: ${fullCommand}`);
|
|
56
58
|
logger.info(`${levelPrefix} Spawned Claude CLI process: PID ${pid}`);
|
|
57
59
|
|
|
58
60
|
let stdout = '';
|
|
@@ -257,7 +257,8 @@ class ClaudeProvider extends AIProvider {
|
|
|
257
257
|
logger.info(`${levelPrefix} Executing Claude CLI...`);
|
|
258
258
|
logger.info(`${levelPrefix} Writing prompt: ${prompt.length} bytes`);
|
|
259
259
|
|
|
260
|
-
const
|
|
260
|
+
const spawnArgs = [...this.args];
|
|
261
|
+
const claude = spawn(this.command, spawnArgs, {
|
|
261
262
|
cwd,
|
|
262
263
|
env: {
|
|
263
264
|
...process.env,
|
|
@@ -268,6 +269,8 @@ class ClaudeProvider extends AIProvider {
|
|
|
268
269
|
});
|
|
269
270
|
|
|
270
271
|
const pid = claude.pid;
|
|
272
|
+
const fullCommand = this.useShell ? this.command : `${this.command} ${spawnArgs.join(' ')}`;
|
|
273
|
+
logger.debug(`${levelPrefix} Claude CLI command: ${fullCommand}`);
|
|
271
274
|
logger.info(`${levelPrefix} Spawned Claude CLI process: PID ${pid}`);
|
|
272
275
|
|
|
273
276
|
// Register process for cancellation tracking if analysisId provided
|
package/src/ai/provider.js
CHANGED
|
@@ -671,10 +671,11 @@ function getAllProvidersInfo() {
|
|
|
671
671
|
* Create a provider instance
|
|
672
672
|
* @param {string} providerId - Provider ID (e.g., 'claude', 'gemini')
|
|
673
673
|
* @param {string} model - Model to use (optional, uses default if not specified)
|
|
674
|
+
* @param {Object} overrides - Per-call config overrides that supersede global providerConfigOverrides (optional)
|
|
674
675
|
* @returns {AIProvider}
|
|
675
676
|
* @throws {Error} If provider is not registered
|
|
676
677
|
*/
|
|
677
|
-
function createProvider(providerId, model = null) {
|
|
678
|
+
function createProvider(providerId, model = null, overrides = {}) {
|
|
678
679
|
const ProviderClass = providerRegistry.get(providerId);
|
|
679
680
|
|
|
680
681
|
if (!ProviderClass) {
|
|
@@ -683,7 +684,7 @@ function createProvider(providerId, model = null) {
|
|
|
683
684
|
}
|
|
684
685
|
|
|
685
686
|
// Get config overrides for this provider
|
|
686
|
-
const
|
|
687
|
+
const configOverrides = providerConfigOverrides.get(providerId);
|
|
687
688
|
|
|
688
689
|
// Determine the actual model to use
|
|
689
690
|
let actualModel = model;
|
|
@@ -691,8 +692,8 @@ function createProvider(providerId, model = null) {
|
|
|
691
692
|
// Resolve default from merged models (config + built-in).
|
|
692
693
|
// Checks both sources because some providers (e.g., Pi) define built-in
|
|
693
694
|
// modes with default:true that aren't in config overrides.
|
|
694
|
-
if (
|
|
695
|
-
actualModel = resolveDefaultModel(mergeModels(ProviderClass.getModels(),
|
|
695
|
+
if (configOverrides?.models || ProviderClass.getModels().length > 0) {
|
|
696
|
+
actualModel = resolveDefaultModel(mergeModels(ProviderClass.getModels(), configOverrides?.models));
|
|
696
697
|
}
|
|
697
698
|
// Fall back to provider's built-in default
|
|
698
699
|
if (!actualModel) {
|
|
@@ -700,8 +701,8 @@ function createProvider(providerId, model = null) {
|
|
|
700
701
|
}
|
|
701
702
|
}
|
|
702
703
|
|
|
703
|
-
// Create provider instance with config overrides
|
|
704
|
-
return new ProviderClass(actualModel, { ...(
|
|
704
|
+
// Create provider instance with config overrides, per-call overrides, and yolo mode
|
|
705
|
+
return new ProviderClass(actualModel, { ...(configOverrides || {}), ...overrides, yolo: yoloMode });
|
|
705
706
|
}
|
|
706
707
|
|
|
707
708
|
/**
|
|
@@ -43,7 +43,7 @@ class ChatSessionManager {
|
|
|
43
43
|
* @param {string} [options.initialContext] - Initial context to prepend to the first user message
|
|
44
44
|
* @returns {Promise<{id: number, status: string}>}
|
|
45
45
|
*/
|
|
46
|
-
async createSession({ provider, model, reviewId, contextCommentId, systemPrompt, cwd, initialContext }) {
|
|
46
|
+
async createSession({ provider, model, reviewId, contextCommentId, systemPrompt, cwd, initialContext, loadSkills }) {
|
|
47
47
|
// Resolve provider definition once — used for model fallback and bridge construction
|
|
48
48
|
const providerDef = getChatProvider(provider);
|
|
49
49
|
|
|
@@ -72,6 +72,7 @@ class ChatSessionManager {
|
|
|
72
72
|
model: resolvedModel,
|
|
73
73
|
cwd,
|
|
74
74
|
systemPrompt,
|
|
75
|
+
loadSkills,
|
|
75
76
|
}, providerDef);
|
|
76
77
|
|
|
77
78
|
const listeners = {
|
|
@@ -413,9 +414,10 @@ class ChatSessionManager {
|
|
|
413
414
|
* @param {Object} options
|
|
414
415
|
* @param {string} [options.systemPrompt] - System prompt text
|
|
415
416
|
* @param {string} [options.cwd] - Working directory for agent
|
|
417
|
+
* @param {boolean} [options.loadSkills] - Resolved load_skills override for the session
|
|
416
418
|
* @returns {Promise<{id: number, status: string}>}
|
|
417
419
|
*/
|
|
418
|
-
async resumeSession(sessionId, { systemPrompt, cwd } = {}) {
|
|
420
|
+
async resumeSession(sessionId, { systemPrompt, cwd, loadSkills } = {}) {
|
|
419
421
|
// Already active — return immediately
|
|
420
422
|
if (this._sessions.has(sessionId)) {
|
|
421
423
|
return { id: sessionId, status: 'active' };
|
|
@@ -459,6 +461,7 @@ class ChatSessionManager {
|
|
|
459
461
|
model: row.model,
|
|
460
462
|
cwd,
|
|
461
463
|
systemPrompt,
|
|
464
|
+
loadSkills,
|
|
462
465
|
...resumeOptions,
|
|
463
466
|
});
|
|
464
467
|
|
|
@@ -588,7 +591,7 @@ class ChatSessionManager {
|
|
|
588
591
|
useShell: def?.useShell,
|
|
589
592
|
tools: CHAT_TOOLS,
|
|
590
593
|
extensions: appExtensions ? [taskExtensionDir] : [],
|
|
591
|
-
loadSkills: def?.load_skills,
|
|
594
|
+
loadSkills: options.loadSkills ?? def?.load_skills,
|
|
592
595
|
});
|
|
593
596
|
}
|
|
594
597
|
|