blamouche_obsidian-any-ai-code/session-utils.ts
blamouche 073efef75c Run multiple runtimes in parallel via session tabs
Refactor the sidebar panel from a single-process view into a tabbed
multi-session view: each tab is an independent CliSession with its own
PTY process and xterm terminal. A New session / + control opens a session
from any configured runtime; multiple sessions of the same runtime are
allowed and labels are disambiguated. Stop/Restart/Clear and the @file/
@folder buttons act on the active tab; a single ResizeObserver refits only
the visible terminal and re-fits on tab activation.

Automations now spawn their own session tab for the declared runtime (or
the default when none is declared), await CLI readiness, then send the
prompt — replacing the old skip-if-not-running/runtime-mismatch logic.
Add settings autoCloseAutomationSessions and maxConcurrentSessions; the
Automations modal "Run now" button is always enabled.

Extract pure helpers to session-utils.ts (resolveRuntimeForAutomation,
runtimeMatches, nextSessionLabel, canOpenSession) with unit tests. Update
README and the generated example automation. Bump to 0.2.9 (manifest,
versions.json, package.json, prompt-hub version).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 10:12:26 +02:00

64 lines
2 KiB
TypeScript

import type { CliRuntimeConfig } from "./runtime-utils";
/**
* True when `target` (an automation's declared runtime) refers to `runtime`,
* matched either by id or by display name (case-insensitive). Mirrors the rule
* the sidebar view used before sessions existed.
*/
export function runtimeMatches(runtime: CliRuntimeConfig, target: string): boolean {
const wanted = target.trim().toLowerCase();
if (!wanted) {
return false;
}
if (runtime.id.trim().toLowerCase() === wanted) {
return true;
}
return runtime.name.trim().toLowerCase() === wanted;
}
/**
* Resolve which runtime an automation should spawn.
* - If `declared` is set, find the runtime matching it (id or name); returns
* `null` when none matches (the automation is then skipped).
* - If `declared` is empty/null, fall back to the default runtime
* (`defaultId`), then to the first configured runtime.
*/
export function resolveRuntimeForAutomation(
runtimes: CliRuntimeConfig[],
declared: string | null | undefined,
defaultId: string
): CliRuntimeConfig | null {
const wanted = (declared ?? "").trim();
if (wanted) {
return runtimes.find((runtime) => runtimeMatches(runtime, wanted)) ?? null;
}
return runtimes.find((runtime) => runtime.id === defaultId) ?? runtimes[0] ?? null;
}
/**
* Build a tab label for a new session, disambiguating duplicates of the same
* runtime: "Claude", "Claude (2)", "Claude (3)", ...
*/
export function nextSessionLabel(existingLabels: string[], runtimeName: string): string {
const base = runtimeName.trim() || "(Unnamed)";
const taken = new Set(existingLabels);
if (!taken.has(base)) {
return base;
}
let counter = 2;
while (taken.has(`${base} (${counter})`)) {
counter += 1;
}
return `${base} (${counter})`;
}
/**
* Whether another session may be opened given the current count and the
* configured cap. `max <= 0` means unlimited.
*/
export function canOpenSession(currentCount: number, max: number): boolean {
if (!Number.isFinite(max) || max <= 0) {
return true;
}
return currentCount < max;
}