refactor: streamline logging and context handling in team services
- Replaced logger.info calls with console.log in TeamMemberLogsFinder for performance logging. - Simplified environment variable handling in TeamProvisioningService by removing unnecessary context settings. - Updated stopTeam method to accept a signal parameter for improved process termination control. - Enhanced model handling in team dialogs to support new context management logic, ensuring consistent behavior across components. - Adjusted teamSlice to reflect changes in model parsing and context handling, improving overall state management.
This commit is contained in:
parent
1073a51039
commit
e6b7a6fe53
11 changed files with 70 additions and 74 deletions
|
|
@ -151,7 +151,7 @@ export class TeamMemberLogsFinder {
|
||||||
const tDiscovery = performance.now();
|
const tDiscovery = performance.now();
|
||||||
|
|
||||||
if (!discovery) {
|
if (!discovery) {
|
||||||
logger.info(
|
console.log(
|
||||||
`[perf] findLogsForTask(${taskId}) discovery=null ${(tDiscovery - t0).toFixed(0)}ms`
|
`[perf] findLogsForTask(${taskId}) discovery=null ${(tDiscovery - t0).toFixed(0)}ms`
|
||||||
);
|
);
|
||||||
return [];
|
return [];
|
||||||
|
|
@ -310,7 +310,7 @@ export class TeamMemberLogsFinder {
|
||||||
);
|
);
|
||||||
const tTotal = performance.now();
|
const tTotal = performance.now();
|
||||||
|
|
||||||
logger.info(
|
console.log(
|
||||||
`[perf] findLogsForTask(${taskId}@${teamName}) ` +
|
`[perf] findLogsForTask(${taskId}@${teamName}) ` +
|
||||||
`total=${(tTotal - t0).toFixed(0)}ms | ` +
|
`total=${(tTotal - t0).toFixed(0)}ms | ` +
|
||||||
`discovery=${(tDiscovery - t0).toFixed(0)}ms | ` +
|
`discovery=${(tDiscovery - t0).toFixed(0)}ms | ` +
|
||||||
|
|
@ -344,7 +344,7 @@ export class TeamMemberLogsFinder {
|
||||||
const tDiscovery = performance.now();
|
const tDiscovery = performance.now();
|
||||||
|
|
||||||
if (!discovery) {
|
if (!discovery) {
|
||||||
logger.info(
|
console.log(
|
||||||
`[perf] findLogFileRefsForTask(${taskId}) discovery=null ${(tDiscovery - t0).toFixed(0)}ms`
|
`[perf] findLogFileRefsForTask(${taskId}) discovery=null ${(tDiscovery - t0).toFixed(0)}ms`
|
||||||
);
|
);
|
||||||
return [];
|
return [];
|
||||||
|
|
@ -490,7 +490,7 @@ export class TeamMemberLogsFinder {
|
||||||
const sortedRefs = [...refs].sort((a, b) => b.sortTime - a.sortTime);
|
const sortedRefs = [...refs].sort((a, b) => b.sortTime - a.sortTime);
|
||||||
const tTotal = performance.now();
|
const tTotal = performance.now();
|
||||||
|
|
||||||
logger.info(
|
console.log(
|
||||||
`[perf] findLogFileRefsForTask(${taskId}@${teamName}) ` +
|
`[perf] findLogFileRefsForTask(${taskId}@${teamName}) ` +
|
||||||
`total=${(tTotal - t0).toFixed(0)}ms | ` +
|
`total=${(tTotal - t0).toFixed(0)}ms | ` +
|
||||||
`discovery=${(tDiscovery - t0).toFixed(0)}ms | ` +
|
`discovery=${(tDiscovery - t0).toFixed(0)}ms | ` +
|
||||||
|
|
|
||||||
|
|
@ -2779,10 +2779,7 @@ export class TeamProvisioningService {
|
||||||
try {
|
try {
|
||||||
child = spawnCli(claudePath, spawnArgs, {
|
child = spawnCli(claudePath, spawnArgs, {
|
||||||
cwd: request.cwd,
|
cwd: request.cwd,
|
||||||
env: {
|
env: { ...shellEnv },
|
||||||
...shellEnv,
|
|
||||||
...(request.limitContext ? { CLAUDE_CODE_DISABLE_1M_CONTEXT: '1' } : {}),
|
|
||||||
},
|
|
||||||
stdio: ['pipe', 'pipe', 'pipe'],
|
stdio: ['pipe', 'pipe', 'pipe'],
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -2800,10 +2797,7 @@ export class TeamProvisioningService {
|
||||||
claudePath,
|
claudePath,
|
||||||
args: spawnArgs,
|
args: spawnArgs,
|
||||||
cwd: request.cwd,
|
cwd: request.cwd,
|
||||||
env: {
|
env: { ...shellEnv },
|
||||||
...shellEnv,
|
|
||||||
...(request.limitContext ? { CLAUDE_CODE_DISABLE_1M_CONTEXT: '1' } : {}),
|
|
||||||
},
|
|
||||||
prompt,
|
prompt,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -3186,10 +3180,7 @@ export class TeamProvisioningService {
|
||||||
try {
|
try {
|
||||||
child = spawnCli(claudePath, launchArgs, {
|
child = spawnCli(claudePath, launchArgs, {
|
||||||
cwd: request.cwd,
|
cwd: request.cwd,
|
||||||
env: {
|
env: { ...shellEnv },
|
||||||
...shellEnv,
|
|
||||||
...(request.limitContext ? { CLAUDE_CODE_DISABLE_1M_CONTEXT: '1' } : {}),
|
|
||||||
},
|
|
||||||
stdio: ['pipe', 'pipe', 'pipe'],
|
stdio: ['pipe', 'pipe', 'pipe'],
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -3209,10 +3200,7 @@ export class TeamProvisioningService {
|
||||||
claudePath,
|
claudePath,
|
||||||
args: launchArgs,
|
args: launchArgs,
|
||||||
cwd: request.cwd,
|
cwd: request.cwd,
|
||||||
env: {
|
env: { ...shellEnv },
|
||||||
...shellEnv,
|
|
||||||
...(request.limitContext ? { CLAUDE_CODE_DISABLE_1M_CONTEXT: '1' } : {}),
|
|
||||||
},
|
|
||||||
prompt,
|
prompt,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -4360,7 +4348,7 @@ export class TeamProvisioningService {
|
||||||
/**
|
/**
|
||||||
* Stop the running process for a team. No-op if team is not running.
|
* Stop the running process for a team. No-op if team is not running.
|
||||||
*/
|
*/
|
||||||
stopTeam(teamName: string): void {
|
stopTeam(teamName: string, signal?: NodeJS.Signals): void {
|
||||||
const runId = this.getTrackedRunId(teamName);
|
const runId = this.getTrackedRunId(teamName);
|
||||||
if (!runId) {
|
if (!runId) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -4378,25 +4366,25 @@ export class TeamProvisioningService {
|
||||||
run.cancelRequested = true;
|
run.cancelRequested = true;
|
||||||
// Note: do NOT call stdin.end() before kill — EOF triggers CLI's graceful
|
// Note: do NOT call stdin.end() before kill — EOF triggers CLI's graceful
|
||||||
// shutdown which deletes team files (config.json, inboxes/, tasks/).
|
// shutdown which deletes team files (config.json, inboxes/, tasks/).
|
||||||
// SIGTERM alone kills the process before cleanup runs, preserving files.
|
// SIGTERM/SIGKILL kills the process before cleanup runs, preserving files.
|
||||||
killProcessTree(run.child);
|
killProcessTree(run.child, signal);
|
||||||
const progress = updateProgress(run, 'disconnected', 'Team stopped by user');
|
const progress = updateProgress(run, 'disconnected', 'Team stopped by user');
|
||||||
run.onProgress(progress);
|
run.onProgress(progress);
|
||||||
this.cleanupRun(run);
|
this.cleanupRun(run);
|
||||||
logger.info(`[${teamName}] Process stopped by user`);
|
logger.info(`[${teamName}] Process stopped (signal=${signal ?? 'SIGTERM'})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop all running team processes. Called during app shutdown to kill
|
* Stop all running team processes. Called during app shutdown.
|
||||||
* processes via SIGTERM before the OS closes stdin (which would trigger
|
* Uses SIGKILL (uncatchable) to guarantee the process dies instantly
|
||||||
* CLI's graceful cleanup and delete team files).
|
* without any cleanup — prevents CLI from deleting team files on exit.
|
||||||
*/
|
*/
|
||||||
stopAllTeams(): void {
|
stopAllTeams(): void {
|
||||||
const alive = this.getAliveTeams();
|
const alive = this.getAliveTeams();
|
||||||
if (alive.length === 0) return;
|
if (alive.length === 0) return;
|
||||||
logger.info(`Stopping all team processes on shutdown: ${alive.join(', ')}`);
|
logger.info(`Killing all team processes on shutdown (SIGKILL): ${alive.join(', ')}`);
|
||||||
for (const teamName of alive) {
|
for (const teamName of alive) {
|
||||||
this.stopTeam(teamName);
|
this.stopTeam(teamName, 'SIGKILL');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1168,7 +1168,7 @@ export const TeamDetailView = ({ teamName }: TeamDetailViewProps): React.JSX.Ele
|
||||||
const MODEL_LABELS: Record<string, string> = {
|
const MODEL_LABELS: Record<string, string> = {
|
||||||
default: 'Default',
|
default: 'Default',
|
||||||
opus: 'Opus 4.6',
|
opus: 'Opus 4.6',
|
||||||
sonnet: 'Sonnet 4.5',
|
sonnet: 'Sonnet 4.6',
|
||||||
haiku: 'Haiku 4.5',
|
haiku: 'Haiku 4.5',
|
||||||
};
|
};
|
||||||
const modelLabel = MODEL_LABELS[launchParams.model] ?? launchParams.model;
|
const modelLabel = MODEL_LABELS[launchParams.model] ?? launchParams.model;
|
||||||
|
|
|
||||||
|
|
@ -546,7 +546,10 @@ export const CreateTeamDialog = ({
|
||||||
[memberColorMap, members, soloTeam]
|
[memberColorMap, members, soloTeam]
|
||||||
);
|
);
|
||||||
|
|
||||||
const effectiveModel = useMemo(() => computeEffectiveTeamModel(selectedModel), [selectedModel]);
|
const effectiveModel = useMemo(
|
||||||
|
() => computeEffectiveTeamModel(selectedModel, limitContext),
|
||||||
|
[selectedModel, limitContext]
|
||||||
|
);
|
||||||
|
|
||||||
const sanitizedTeamName = sanitizeTeamName(teamName.trim());
|
const sanitizedTeamName = sanitizeTeamName(teamName.trim());
|
||||||
|
|
||||||
|
|
@ -561,7 +564,6 @@ export const CreateTeamDialog = ({
|
||||||
model: effectiveModel,
|
model: effectiveModel,
|
||||||
effort: (selectedEffort as EffortLevel) || undefined,
|
effort: (selectedEffort as EffortLevel) || undefined,
|
||||||
skipPermissions,
|
skipPermissions,
|
||||||
limitContext: limitContext || undefined,
|
|
||||||
worktree: worktreeEnabled && worktreeName.trim() ? worktreeName.trim() : undefined,
|
worktree: worktreeEnabled && worktreeName.trim() ? worktreeName.trim() : undefined,
|
||||||
extraCliArgs: customArgs.trim() || undefined,
|
extraCliArgs: customArgs.trim() || undefined,
|
||||||
}),
|
}),
|
||||||
|
|
@ -576,7 +578,6 @@ export const CreateTeamDialog = ({
|
||||||
effectiveModel,
|
effectiveModel,
|
||||||
selectedEffort,
|
selectedEffort,
|
||||||
skipPermissions,
|
skipPermissions,
|
||||||
limitContext,
|
|
||||||
worktreeEnabled,
|
worktreeEnabled,
|
||||||
worktreeName,
|
worktreeName,
|
||||||
customArgs,
|
customArgs,
|
||||||
|
|
@ -985,6 +986,7 @@ export const CreateTeamDialog = ({
|
||||||
id="create-limit-context"
|
id="create-limit-context"
|
||||||
checked={limitContext}
|
checked={limitContext}
|
||||||
onCheckedChange={setLimitContext}
|
onCheckedChange={setLimitContext}
|
||||||
|
disabled={selectedModel === 'haiku'}
|
||||||
/>
|
/>
|
||||||
<SkipPermissionsCheckbox
|
<SkipPermissionsCheckbox
|
||||||
id="create-skip-permissions"
|
id="create-skip-permissions"
|
||||||
|
|
|
||||||
|
|
@ -512,12 +512,12 @@ export const LaunchTeamDialog = (props: LaunchTeamDialogProps): React.JSX.Elemen
|
||||||
args.push('--verbose', '--setting-sources', 'user,project,local');
|
args.push('--verbose', '--setting-sources', 'user,project,local');
|
||||||
args.push('--mcp-config', '<auto>', '--disallowedTools', 'TeamDelete,TodoWrite');
|
args.push('--mcp-config', '<auto>', '--disallowedTools', 'TeamDelete,TodoWrite');
|
||||||
if (skipPermissions) args.push('--dangerously-skip-permissions');
|
if (skipPermissions) args.push('--dangerously-skip-permissions');
|
||||||
const model = computeEffectiveTeamModel(selectedModel);
|
const model = computeEffectiveTeamModel(selectedModel, limitContext);
|
||||||
if (model) args.push('--model', model);
|
if (model) args.push('--model', model);
|
||||||
if (selectedEffort) args.push('--effort', selectedEffort);
|
if (selectedEffort) args.push('--effort', selectedEffort);
|
||||||
if (!clearContext) args.push('--resume', '<previous>');
|
if (!clearContext) args.push('--resume', '<previous>');
|
||||||
return args;
|
return args;
|
||||||
}, [isLaunch, skipPermissions, selectedModel, selectedEffort, clearContext]);
|
}, [isLaunch, skipPermissions, selectedModel, limitContext, selectedEffort, clearContext]);
|
||||||
|
|
||||||
const launchOptionalSummary = useMemo(() => {
|
const launchOptionalSummary = useMemo(() => {
|
||||||
if (!isLaunch) return [];
|
if (!isLaunch) return [];
|
||||||
|
|
@ -590,10 +590,9 @@ export const LaunchTeamDialog = (props: LaunchTeamDialogProps): React.JSX.Elemen
|
||||||
teamName: effectiveTeamName,
|
teamName: effectiveTeamName,
|
||||||
cwd: effectiveCwd,
|
cwd: effectiveCwd,
|
||||||
prompt: promptDraft.value.trim() || undefined,
|
prompt: promptDraft.value.trim() || undefined,
|
||||||
model: computeEffectiveTeamModel(selectedModel),
|
model: computeEffectiveTeamModel(selectedModel, limitContext),
|
||||||
effort: (selectedEffort as EffortLevel) || undefined,
|
effort: (selectedEffort as EffortLevel) || undefined,
|
||||||
clearContext: clearContext || undefined,
|
clearContext: clearContext || undefined,
|
||||||
limitContext: limitContext || undefined,
|
|
||||||
skipPermissions,
|
skipPermissions,
|
||||||
worktree: worktreeEnabled && worktreeName.trim() ? worktreeName.trim() : undefined,
|
worktree: worktreeEnabled && worktreeName.trim() ? worktreeName.trim() : undefined,
|
||||||
extraCliArgs: customArgs.trim() || undefined,
|
extraCliArgs: customArgs.trim() || undefined,
|
||||||
|
|
@ -958,6 +957,7 @@ export const LaunchTeamDialog = (props: LaunchTeamDialogProps): React.JSX.Elemen
|
||||||
id="launch-limit-context"
|
id="launch-limit-context"
|
||||||
checked={limitContext}
|
checked={limitContext}
|
||||||
onCheckedChange={setLimitContext}
|
onCheckedChange={setLimitContext}
|
||||||
|
disabled={selectedModel === 'haiku'}
|
||||||
/>
|
/>
|
||||||
<SkipPermissionsCheckbox
|
<SkipPermissionsCheckbox
|
||||||
id="dialog-skip-permissions"
|
id="dialog-skip-permissions"
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ export const LimitContextCheckbox: React.FC<LimitContextCheckboxProps> = ({
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
Limit context to 200K tokens
|
Limit context to 200K tokens
|
||||||
|
{disabled && <span className="text-[10px] italic">(always 200K for this model)</span>}
|
||||||
</Label>
|
</Label>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -78,16 +78,24 @@ const ACTIVE_PROVIDER = PROVIDERS[0];
|
||||||
const MODEL_OPTIONS = [
|
const MODEL_OPTIONS = [
|
||||||
{ value: '', label: 'Default' },
|
{ value: '', label: 'Default' },
|
||||||
{ value: 'opus', label: 'Opus 4.6' },
|
{ value: 'opus', label: 'Opus 4.6' },
|
||||||
{ value: 'sonnet', label: 'Sonnet 4.5' },
|
{ value: 'sonnet', label: 'Sonnet 4.6' },
|
||||||
{ value: 'haiku', label: 'Haiku 4.5' },
|
{ value: 'haiku', label: 'Haiku 4.5' },
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the effective model string for team provisioning.
|
* Computes the effective model string for team provisioning.
|
||||||
* Simply maps empty selection to undefined.
|
* By default adds [1m] suffix for 1M context (Opus/Sonnet).
|
||||||
|
* When limitContext=true, returns base model without [1m] (200K context).
|
||||||
|
* Haiku does not support 1M — always returned as-is.
|
||||||
*/
|
*/
|
||||||
export function computeEffectiveTeamModel(selectedModel: string): string | undefined {
|
export function computeEffectiveTeamModel(
|
||||||
return selectedModel || undefined;
|
selectedModel: string,
|
||||||
|
limitContext: boolean
|
||||||
|
): string | undefined {
|
||||||
|
const base = selectedModel || undefined;
|
||||||
|
if (limitContext) return base;
|
||||||
|
if (base === 'haiku') return base;
|
||||||
|
return base ? `${base}[1m]` : 'sonnet[1m]';
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TeamModelSelectorProps {
|
export interface TeamModelSelectorProps {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ interface KanbanColumnProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
headerClassName?: string;
|
headerClassName?: string;
|
||||||
bodyClassName?: string;
|
bodyClassName?: string;
|
||||||
|
headerDragClassName?: string;
|
||||||
headerAccessory?: React.ReactNode;
|
headerAccessory?: React.ReactNode;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
@ -23,6 +24,7 @@ export const KanbanColumn = ({
|
||||||
className,
|
className,
|
||||||
headerClassName,
|
headerClassName,
|
||||||
bodyClassName,
|
bodyClassName,
|
||||||
|
headerDragClassName,
|
||||||
headerAccessory,
|
headerAccessory,
|
||||||
children,
|
children,
|
||||||
}: KanbanColumnProps): React.JSX.Element => {
|
}: KanbanColumnProps): React.JSX.Element => {
|
||||||
|
|
@ -35,20 +37,27 @@ export const KanbanColumn = ({
|
||||||
)}
|
)}
|
||||||
style={bodyBg ? { backgroundColor: bodyBg } : undefined}
|
style={bodyBg ? { backgroundColor: bodyBg } : undefined}
|
||||||
>
|
>
|
||||||
|
{count > 0 && (
|
||||||
|
<Badge
|
||||||
|
variant="secondary"
|
||||||
|
className="absolute -right-2 -top-2 z-10 min-w-5 px-1.5 py-0 text-[10px] font-medium leading-5"
|
||||||
|
>
|
||||||
|
{count}
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
<header
|
<header
|
||||||
className={cn('border-b border-[var(--color-border)] px-3 py-2 pr-14', headerClassName)}
|
className={cn(
|
||||||
|
'border-b border-[var(--color-border)] px-3 py-2',
|
||||||
|
headerClassName,
|
||||||
|
headerDragClassName
|
||||||
|
)}
|
||||||
style={headerBg ? { backgroundColor: headerBg } : undefined}
|
style={headerBg ? { backgroundColor: headerBg } : undefined}
|
||||||
>
|
>
|
||||||
<h4 className="flex items-center gap-2 text-xs font-semibold uppercase tracking-wide text-[var(--color-text)]">
|
<h4 className="flex items-center gap-2 text-xs font-semibold uppercase tracking-wide text-[var(--color-text)]">
|
||||||
{icon}
|
{icon}
|
||||||
{title}
|
{title}
|
||||||
</h4>
|
</h4>
|
||||||
<div className="absolute right-2 top-2 z-10 flex items-center gap-2">
|
{headerAccessory && <div className="absolute right-2 top-2 z-10">{headerAccessory}</div>}
|
||||||
{headerAccessory}
|
|
||||||
<Badge variant="secondary" className="px-2 py-0.5 text-[10px] font-normal">
|
|
||||||
{count}
|
|
||||||
</Badge>
|
|
||||||
</div>
|
|
||||||
</header>
|
</header>
|
||||||
<div className={cn('flex max-h-[480px] flex-col gap-1.5 overflow-auto p-2', bodyClassName)}>
|
<div className={cn('flex max-h-[480px] flex-col gap-1.5 overflow-auto p-2', bodyClassName)}>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import ReactGridLayout, { WidthProvider } from 'react-grid-layout/legacy';
|
||||||
|
|
||||||
import { usePersistedGridLayout } from '@renderer/hooks/usePersistedGridLayout';
|
import { usePersistedGridLayout } from '@renderer/hooks/usePersistedGridLayout';
|
||||||
import { browserGridLayoutRepository } from '@renderer/services/layout-system/BrowserGridLayoutRepository';
|
import { browserGridLayoutRepository } from '@renderer/services/layout-system/BrowserGridLayoutRepository';
|
||||||
import { GripVertical } from 'lucide-react';
|
|
||||||
|
|
||||||
import { KanbanColumn } from './KanbanColumn';
|
import { KanbanColumn } from './KanbanColumn';
|
||||||
|
|
||||||
|
|
@ -213,15 +212,7 @@ const LoadedKanbanGridLayout = ({
|
||||||
className="flex h-full min-h-0 flex-col"
|
className="flex h-full min-h-0 flex-col"
|
||||||
headerClassName="shrink-0"
|
headerClassName="shrink-0"
|
||||||
bodyClassName="kanban-grid-no-drag min-h-0 max-h-none flex-1"
|
bodyClassName="kanban-grid-no-drag min-h-0 max-h-none flex-1"
|
||||||
headerAccessory={
|
headerDragClassName="kanban-grid-drag-handle cursor-grab active:cursor-grabbing"
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="kanban-grid-drag-handle inline-flex cursor-grab items-center justify-center rounded-sm p-1 text-[var(--color-text-muted)] transition-colors hover:text-[var(--color-text)] active:cursor-grabbing"
|
|
||||||
aria-label={`Drag ${column.title} column`}
|
|
||||||
>
|
|
||||||
<GripVertical size={14} />
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{column.content}
|
{column.content}
|
||||||
</KanbanColumn>
|
</KanbanColumn>
|
||||||
|
|
|
||||||
|
|
@ -542,15 +542,16 @@ function saveLaunchParams(teamName: string, params: TeamLaunchParams): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse raw model string — simply returns the base model name.
|
* Parse raw model string from TeamCreateRequest/TeamLaunchRequest.
|
||||||
* The [1m] suffix is no longer used; context limiting is handled via env var.
|
* E.g. 'opus[1m]' → { model: 'opus', limitContext: false }
|
||||||
|
* 'sonnet' → { model: 'sonnet', limitContext: true }
|
||||||
|
* Models without [1m] suffix mean context is limited to 200K.
|
||||||
*/
|
*/
|
||||||
function parseModelString(raw?: string): { model?: string } {
|
function parseModelString(raw?: string): { model?: string; limitContext: boolean } {
|
||||||
if (!raw) return {};
|
if (!raw) return { limitContext: true };
|
||||||
// Strip legacy [1m] suffix if present in saved data
|
|
||||||
const match = raw.match(/^(\w+)\[1m\]$/);
|
const match = raw.match(/^(\w+)\[1m\]$/);
|
||||||
if (match) return { model: match[1] };
|
if (match) return { model: match[1], limitContext: false };
|
||||||
return { model: raw };
|
return { model: raw, limitContext: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadToolApprovalSettings(): ToolApprovalSettings {
|
function loadToolApprovalSettings(): ToolApprovalSettings {
|
||||||
|
|
@ -1422,11 +1423,11 @@ export const createTeamSlice: StateCreator<AppState, [], [], TeamSlice> = (set,
|
||||||
const response = await unwrapIpc('team:create', () => api.teams.createTeam(request));
|
const response = await unwrapIpc('team:create', () => api.teams.createTeam(request));
|
||||||
|
|
||||||
// Persist per-team launch params (model, effort, limit context)
|
// Persist per-team launch params (model, effort, limit context)
|
||||||
const { model: baseModel } = parseModelString(request.model);
|
const { model: baseModel, limitContext } = parseModelString(request.model);
|
||||||
const params: TeamLaunchParams = {
|
const params: TeamLaunchParams = {
|
||||||
model: baseModel || 'default',
|
model: baseModel || 'default',
|
||||||
effort: request.effort,
|
effort: request.effort,
|
||||||
limitContext: request.limitContext,
|
limitContext,
|
||||||
};
|
};
|
||||||
saveLaunchParams(request.teamName, params);
|
saveLaunchParams(request.teamName, params);
|
||||||
set((state) => ({
|
set((state) => ({
|
||||||
|
|
@ -1559,11 +1560,11 @@ export const createTeamSlice: StateCreator<AppState, [], [], TeamSlice> = (set,
|
||||||
const response = await unwrapIpc('team:launch', () => api.teams.launchTeam(request));
|
const response = await unwrapIpc('team:launch', () => api.teams.launchTeam(request));
|
||||||
|
|
||||||
// Persist per-team launch params (model, effort, limit context)
|
// Persist per-team launch params (model, effort, limit context)
|
||||||
const { model: baseModel } = parseModelString(request.model);
|
const { model: baseModel, limitContext } = parseModelString(request.model);
|
||||||
const params: TeamLaunchParams = {
|
const params: TeamLaunchParams = {
|
||||||
model: baseModel || 'default',
|
model: baseModel || 'default',
|
||||||
effort: request.effort,
|
effort: request.effort,
|
||||||
limitContext: request.limitContext,
|
limitContext,
|
||||||
};
|
};
|
||||||
saveLaunchParams(request.teamName, params);
|
saveLaunchParams(request.teamName, params);
|
||||||
set((state) => ({
|
set((state) => ({
|
||||||
|
|
|
||||||
|
|
@ -401,8 +401,6 @@ export interface TeamLaunchRequest {
|
||||||
effort?: EffortLevel;
|
effort?: EffortLevel;
|
||||||
/** When true, skip --resume and start a fresh session (clears context memory). */
|
/** When true, skip --resume and start a fresh session (clears context memory). */
|
||||||
clearContext?: boolean;
|
clearContext?: boolean;
|
||||||
/** When true, set CLAUDE_CODE_DISABLE_1M_CONTEXT=1 to limit context to 200K tokens. */
|
|
||||||
limitContext?: boolean;
|
|
||||||
/** When false, run WITHOUT --dangerously-skip-permissions (manual tool approval). Default: true. */
|
/** When false, run WITHOUT --dangerously-skip-permissions (manual tool approval). Default: true. */
|
||||||
skipPermissions?: boolean;
|
skipPermissions?: boolean;
|
||||||
/** Worktree name — CLI: --worktree <name>. */
|
/** Worktree name — CLI: --worktree <name>. */
|
||||||
|
|
@ -525,8 +523,6 @@ export interface TeamCreateRequest {
|
||||||
prompt?: string;
|
prompt?: string;
|
||||||
model?: string;
|
model?: string;
|
||||||
effort?: EffortLevel;
|
effort?: EffortLevel;
|
||||||
/** When true, set CLAUDE_CODE_DISABLE_1M_CONTEXT=1 to limit context to 200K tokens. */
|
|
||||||
limitContext?: boolean;
|
|
||||||
/** When false, run WITHOUT --dangerously-skip-permissions (manual tool approval). Default: true. */
|
/** When false, run WITHOUT --dangerously-skip-permissions (manual tool approval). Default: true. */
|
||||||
skipPermissions?: boolean;
|
skipPermissions?: boolean;
|
||||||
/** Worktree name — CLI: --worktree <name>. */
|
/** Worktree name — CLI: --worktree <name>. */
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue