mirror of
https://github.com/blamouche/obsidian-any-ai-code.git
synced 2026-07-22 06:53:38 +00:00
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>
64 lines
2 KiB
TypeScript
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;
|
|
}
|