





















@@ -14,6 +14,7 @@ import {
1414} from "@earendil-works/pi-tui";
1515import { resolveAgentIdByWorkspacePath, resolveDefaultAgentId } from "../agents/agent-scope.js";
1616import { getRuntimeConfig, type OpenClawConfig } from "../config/config.js";
17+import type { CommandEntry } from "../gateway/protocol/index.js";
1718import { registerUncaughtExceptionHandler } from "../infra/unhandled-rejections.js";
1819import { setConsoleSubsystemFilter } from "../logging/console.js";
1920import { loggingState } from "../logging/state.js";
@@ -475,6 +476,10 @@ export async function runTui(opts: RunTuiOptions): Promise<TuiResult> {
475476const autoMessage = opts.message?.trim();
476477let autoMessageSent = false;
477478let sessionInfo: SessionInfo = {};
479+let dynamicSlashCommands: CommandEntry[] = [];
480+let dynamicSlashCommandsKey: string | null = null;
481+let dynamicSlashCommandsInFlightKey: string | null = null;
482+let dynamicSlashCommandsRequestId = 0;
478483let lastCtrlCAt = 0;
479484let exitRequested = false;
480485let exitResult: TuiResult = { exitReason: "exit" };
@@ -699,7 +704,10 @@ export async function runTui(opts: RunTuiOptions): Promise<TuiResult> {
699704root.addChild(footer);
700705root.addChild(editor);
701706702-const updateAutocompleteProvider = () => {
707+const resolveDynamicSlashCommandsKey = () => currentAgentId;
708+709+const applyAutocompleteProvider = () => {
710+const dynamicKey = resolveDynamicSlashCommandsKey();
703711editor.setAutocompleteProvider(
704712new CombinedAutocompleteProvider(
705713getSlashCommands({
@@ -708,12 +716,56 @@ export async function runTui(opts: RunTuiOptions): Promise<TuiResult> {
708716provider: sessionInfo.modelProvider,
709717model: sessionInfo.model,
710718thinkingLevels: sessionInfo.thinkingLevels,
719+dynamicCommands: dynamicSlashCommandsKey === dynamicKey ? dynamicSlashCommands : [],
711720}),
712721process.cwd(),
713722),
714723);
715724};
716725726+const refreshDynamicSlashCommands = () => {
727+const key = resolveDynamicSlashCommandsKey();
728+if (
729+!isConnected ||
730+!client.listCommands ||
731+dynamicSlashCommandsKey === key ||
732+dynamicSlashCommandsInFlightKey === key
733+) {
734+return;
735+}
736+dynamicSlashCommandsInFlightKey = key;
737+const requestId = ++dynamicSlashCommandsRequestId;
738+const agentId = currentAgentId;
739+void client
740+.listCommands({
741+ agentId,
742+scope: "text",
743+includeArgs: false,
744+})
745+.then((commands) => {
746+if (
747+requestId !== dynamicSlashCommandsRequestId ||
748+key !== resolveDynamicSlashCommandsKey()
749+) {
750+return;
751+}
752+dynamicSlashCommands = commands;
753+dynamicSlashCommandsKey = key;
754+applyAutocompleteProvider();
755+})
756+.catch(() => undefined)
757+.finally(() => {
758+if (dynamicSlashCommandsInFlightKey === key) {
759+dynamicSlashCommandsInFlightKey = null;
760+}
761+});
762+};
763+764+const updateAutocompleteProvider = () => {
765+applyAutocompleteProvider();
766+refreshDynamicSlashCommands();
767+};
768+717769tui.addChild(root);
718770tui.setFocus(editor);
719771@@ -1339,6 +1391,7 @@ export async function runTui(opts: RunTuiOptions): Promise<TuiResult> {
13391391await refreshAgents();
13401392await restoreRememberedSession();
13411393updateHeader();
1394+updateAutocompleteProvider();
13421395await loadHistory();
13431396setConnectionStatus(
13441397isLocalMode ? "local ready" : reconnected ? "gateway reconnected" : "gateway connected",
@@ -1362,6 +1415,11 @@ export async function runTui(opts: RunTuiOptions): Promise<TuiResult> {
13621415isConnected = false;
13631416wasDisconnected = true;
13641417historyLoaded = false;
1418+dynamicSlashCommands = [];
1419+dynamicSlashCommandsKey = null;
1420+dynamicSlashCommandsInFlightKey = null;
1421+dynamicSlashCommandsRequestId += 1;
1422+updateAutocompleteProvider();
13651423pauseStreamingWatchdog();
13661424const disconnectState = isLocalMode
13671425 ? {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。