mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 06:20:43 +00:00
fix: session_status 'current' resolves to live run session instead of stale sandbox key (#76708) (#76995)
Summary:
- The PR threads a live `runSessionKey` through embedded tool construction, updates `session_status({sessionKey:"current"})` resolution, and adds unit, Telegram QA, workflow, and changelog coverage for #76708.
- Reproducibility: yes. Source inspection shows current main gives `session_status` only the sandbox/requester ... plus PR follow-up describe a focused Telegram Docker scenario that fails pre-fix and passes with this head.
Automerge notes:
- PR branch already contained follow-up commit before automerge: fix: preserve session visibility semantics for runSessionKey (#76708)
- PR branch already contained follow-up commit before automerge: fix: cover Telegram current session status
Validation:
- ClawSweeper review passed for head c3c964ecfd.
- Required merge gates passed before the squash merge.
Prepared head SHA: c3c964ecfd
Review: https://github.com/openclaw/openclaw/pull/76995#issuecomment-4367445187
Co-authored-by: Alex Knight <aknight@atlassian.com>
Co-authored-by: Alex Knight <15041791+amknight@users.noreply.github.com>
This commit is contained in:
@@ -462,7 +462,7 @@ jobs:
|
||||
published_upgrade_survivor_baselines: all-since-2026.4.23
|
||||
published_upgrade_survivor_scenarios: reported-issues
|
||||
telegram_mode: mock-openai
|
||||
telegram_scenarios: telegram-help-command,telegram-commands-command,telegram-tools-compact-command,telegram-whoami-command,telegram-context-command,telegram-mention-gating
|
||||
telegram_scenarios: telegram-help-command,telegram-commands-command,telegram-tools-compact-command,telegram-whoami-command,telegram-context-command,telegram-current-session-status-tool,telegram-mention-gating
|
||||
secrets:
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL }}
|
||||
|
||||
@@ -135,6 +135,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Channels/streaming: expose `streaming.progress.label`, `labels`, `maxLines`, and `toolProgress` in bundled channel config metadata so progress draft settings appear in config, docs, and control surfaces. Thanks @vincentkoc.
|
||||
- Channels/streaming: normalize whitespace and case for `streaming.progress.label: "auto"` so progress draft labels keep using the built-in label pool instead of rendering a literal `auto` title. Thanks @vincentkoc.
|
||||
- Plugins/Codex: preserve Codex-native OAuth routing for `/codex bind` app-server turns so bound sessions keep the selected Codex auth profile instead of falling back to public OpenAI credentials. (#76714) Thanks @keshavbotagent.
|
||||
- Telegram: keep status checks pointed at the active chat so asking for the current session no longer reports an old direct-message conversation. (#76708) Thanks @amknight.
|
||||
- Gateway/install: prefer supported system Node over nvm/fnm/volta/asdf/mise when regenerating managed gateway services, so `gateway install --force` no longer recreates service definitions that doctor immediately flags as version-manager-backed. Fixes #76339. Thanks @brokemac79.
|
||||
- Cron/status: render explicit `delivery.mode: "none"` jobs as no-delivery previews and label cron session history distinctly instead of showing fallback delivery or direct-session rows. Fixes #76945.
|
||||
- Gateway/usage: serve `usage.cost` and `sessions.usage` from a durable transcript aggregate cache with lock-safe background refreshes and localized stale-cache status, so large usage views avoid repeated full scans. (#76650) Thanks @Marvinthebored.
|
||||
|
||||
@@ -331,6 +331,7 @@ describe("telegram live qa runtime", () => {
|
||||
"telegram-tools-compact-command",
|
||||
"telegram-whoami-command",
|
||||
"telegram-context-command",
|
||||
"telegram-current-session-status-tool",
|
||||
"telegram-mentioned-message-reply",
|
||||
"telegram-mention-gating",
|
||||
]);
|
||||
@@ -340,9 +341,15 @@ describe("telegram live qa runtime", () => {
|
||||
"telegram-tools-compact-command",
|
||||
"telegram-whoami-command",
|
||||
"telegram-context-command",
|
||||
"telegram-current-session-status-tool",
|
||||
"telegram-mentioned-message-reply",
|
||||
"telegram-mention-gating",
|
||||
]);
|
||||
expect(
|
||||
scenarios
|
||||
.find((scenario) => scenario.id === "telegram-current-session-status-tool")
|
||||
?.buildRun("sut_bot").expectedTextIncludes,
|
||||
).toEqual(["QA-TELEGRAM-CURRENT-SESSION-OK", ":telegram:group:"]);
|
||||
expect(
|
||||
scenarios
|
||||
.find((scenario) => scenario.id === "telegram-mentioned-message-reply")
|
||||
|
||||
@@ -47,6 +47,7 @@ type TelegramQaScenarioId =
|
||||
| "telegram-tools-compact-command"
|
||||
| "telegram-whoami-command"
|
||||
| "telegram-context-command"
|
||||
| "telegram-current-session-status-tool"
|
||||
| "telegram-mentioned-message-reply"
|
||||
| "telegram-mention-gating";
|
||||
|
||||
@@ -208,6 +209,7 @@ type TelegramMessage = {
|
||||
|
||||
type TelegramUpdate = {
|
||||
update_id: number;
|
||||
edited_message?: TelegramMessage;
|
||||
message?: TelegramMessage;
|
||||
};
|
||||
|
||||
@@ -270,6 +272,17 @@ const TELEGRAM_QA_SCENARIOS: TelegramQaScenarioDefinition[] = [
|
||||
expectedTextIncludes: ["/context list", "Inline shortcut"],
|
||||
}),
|
||||
},
|
||||
{
|
||||
id: "telegram-current-session-status-tool",
|
||||
title: "Telegram current session_status tool call",
|
||||
defaultEnabled: false,
|
||||
timeoutMs: 60_000,
|
||||
buildRun: (sutUsername) => ({
|
||||
expectReply: true,
|
||||
input: `@${sutUsername} Telegram current session_status QA check. Call session_status with sessionKey set to current, then reply with the exact QA marker and resolved session key.`,
|
||||
expectedTextIncludes: ["QA-TELEGRAM-CURRENT-SESSION-OK", ":telegram:group:"],
|
||||
}),
|
||||
},
|
||||
{
|
||||
id: "telegram-mentioned-message-reply",
|
||||
title: "Telegram mentioned message gets a reply",
|
||||
@@ -471,7 +484,7 @@ function detectMediaKinds(message: TelegramMessage) {
|
||||
}
|
||||
|
||||
function normalizeTelegramObservedMessage(update: TelegramUpdate): TelegramObservedMessage | null {
|
||||
const message = update.message;
|
||||
const message = update.message ?? update.edited_message;
|
||||
if (!message?.from?.id) {
|
||||
return null;
|
||||
}
|
||||
@@ -608,7 +621,7 @@ async function flushTelegramUpdates(token: string) {
|
||||
{
|
||||
offset,
|
||||
timeout: 0,
|
||||
allowed_updates: ["message"],
|
||||
allowed_updates: ["message", "edited_message"],
|
||||
},
|
||||
15_000,
|
||||
);
|
||||
@@ -653,10 +666,12 @@ async function waitForObservedMessage(params: {
|
||||
observedMessages: TelegramObservedMessage[];
|
||||
observationScenarioId: string;
|
||||
observationScenarioTitle: string;
|
||||
expectedTextIncludes?: string[];
|
||||
}) {
|
||||
const startedAt = Date.now();
|
||||
let offset = params.initialOffset;
|
||||
let lastPollingError: unknown;
|
||||
let lastExpectedMismatch: Error | undefined;
|
||||
while (Date.now() - startedAt < params.timeoutMs) {
|
||||
const remainingMs = Math.max(
|
||||
1_000,
|
||||
@@ -671,7 +686,7 @@ async function waitForObservedMessage(params: {
|
||||
{
|
||||
offset,
|
||||
timeout: timeoutSeconds,
|
||||
allowed_updates: ["message"],
|
||||
allowed_updates: ["message", "edited_message"],
|
||||
},
|
||||
timeoutSeconds * 1000 + 5_000,
|
||||
);
|
||||
@@ -703,10 +718,23 @@ async function waitForObservedMessage(params: {
|
||||
};
|
||||
params.observedMessages.push(observedMessage);
|
||||
if (matchedScenario) {
|
||||
try {
|
||||
assertTelegramScenarioReply({
|
||||
expectedTextIncludes: params.expectedTextIncludes,
|
||||
message: observedMessage,
|
||||
});
|
||||
} catch (error) {
|
||||
lastExpectedMismatch =
|
||||
error instanceof Error ? error : new Error(formatErrorMessage(error));
|
||||
continue;
|
||||
}
|
||||
return { message: observedMessage, nextOffset: offset, observedAtMs: batchObservedAtMs };
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lastExpectedMismatch) {
|
||||
throw lastExpectedMismatch;
|
||||
}
|
||||
const timeoutMessage = `timed out after ${params.timeoutMs}ms waiting for Telegram message`;
|
||||
if (lastPollingError) {
|
||||
throw new Error(
|
||||
@@ -1332,6 +1360,9 @@ export async function runTelegramQaLive(params: {
|
||||
observedMessages,
|
||||
observationScenarioId: scenario.id,
|
||||
observationScenarioTitle: scenario.title,
|
||||
expectedTextIncludes: scenarioRun.expectReply
|
||||
? scenarioRun.expectedTextIncludes
|
||||
: undefined,
|
||||
predicate: (message) =>
|
||||
matchesTelegramScenarioReply({
|
||||
allowAnySutReply: scenarioRun.allowAnySutReply,
|
||||
|
||||
@@ -152,6 +152,7 @@ const QA_TOOL_PROGRESS_PROMPT_RE = /tool progress qa check/i;
|
||||
const QA_GROUP_VISIBLE_REPLY_TOOL_PROMPT_RE = /qa group visible reply tool check/i;
|
||||
const QA_GROUP_MESSAGE_UNAVAILABLE_FALLBACK_PROMPT_RE =
|
||||
/qa group message unavailable fallback check/i;
|
||||
const QA_TELEGRAM_CURRENT_SESSION_STATUS_PROMPT_RE = /telegram current session_status qa check/i;
|
||||
const QA_SUBAGENT_DIRECT_FALLBACK_PROMPT_RE = /subagent direct fallback qa check/i;
|
||||
const QA_SUBAGENT_DIRECT_FALLBACK_WORKER_RE = /subagent direct fallback worker/i;
|
||||
const QA_SUBAGENT_DIRECT_FALLBACK_MARKER = "QA-SUBAGENT-DIRECT-FALLBACK-OK";
|
||||
@@ -673,6 +674,28 @@ function hasToolErrorOutput(toolJson: Record<string, unknown> | null, toolOutput
|
||||
return /\b(?:error|failed|failure|not found|no such file|enoent)\b/i.test(toolOutput);
|
||||
}
|
||||
|
||||
function extractSessionStatusSessionKey(
|
||||
toolJson: Record<string, unknown> | null,
|
||||
toolOutput: string,
|
||||
) {
|
||||
const details = toolJson?.details;
|
||||
if (details && typeof details === "object") {
|
||||
const sessionKey = (details as { sessionKey?: unknown }).sessionKey;
|
||||
if (typeof sessionKey === "string" && sessionKey.trim()) {
|
||||
return sessionKey.trim();
|
||||
}
|
||||
}
|
||||
const topLevelSessionKey = toolJson?.sessionKey;
|
||||
if (typeof topLevelSessionKey === "string" && topLevelSessionKey.trim()) {
|
||||
return topLevelSessionKey.trim();
|
||||
}
|
||||
const statusLineSessionKey = /(?:^|\n)[^\n]*Session:\s*([^\s•\n]+)/u.exec(toolOutput)?.[1];
|
||||
if (statusLineSessionKey?.trim()) {
|
||||
return statusLineSessionKey.trim();
|
||||
}
|
||||
return /"sessionKey"\s*:\s*"([^"]+)"/.exec(toolOutput)?.[1]?.trim() ?? "";
|
||||
}
|
||||
|
||||
function isHeartbeatPrompt(text: string) {
|
||||
const trimmed = text.trim();
|
||||
if (!trimmed || /remember this fact/i.test(trimmed)) {
|
||||
@@ -1349,6 +1372,17 @@ async function buildResponsesPayload(
|
||||
exactMarkerDirective ?? exactReplyDirective ?? "QA-GROUP-FALLBACK-OK",
|
||||
);
|
||||
}
|
||||
if (QA_TELEGRAM_CURRENT_SESSION_STATUS_PROMPT_RE.test(allInputText)) {
|
||||
if (!toolOutput && hasDeclaredTool(body, "session_status")) {
|
||||
return buildToolCallEventsWithArgs("session_status", { sessionKey: "current" });
|
||||
}
|
||||
const sessionKey = extractSessionStatusSessionKey(toolJson, toolOutput);
|
||||
return buildAssistantEvents(
|
||||
sessionKey.includes(":telegram:group:")
|
||||
? `QA-TELEGRAM-CURRENT-SESSION-OK ${sessionKey}`
|
||||
: `QA-TELEGRAM-CURRENT-SESSION-BAD ${sessionKey || "missing-session-key"}`,
|
||||
);
|
||||
}
|
||||
if (/\bmarker\b/i.test(allInputText) && exactReplyDirective) {
|
||||
return buildAssistantEvents(exactReplyDirective);
|
||||
}
|
||||
|
||||
@@ -492,6 +492,61 @@ describe("session_status tool", () => {
|
||||
expect(details.sessionKey).toBe("main");
|
||||
});
|
||||
|
||||
it("resolves sessionKey=current to runSessionKey under default tree visibility (#76708)", async () => {
|
||||
resetSessionStore({
|
||||
"agent:main:telegram:default:direct:1234": {
|
||||
sessionId: "s-tg-direct",
|
||||
updatedAt: 5,
|
||||
status: "done",
|
||||
},
|
||||
"agent:main:main": {
|
||||
sessionId: "s-main",
|
||||
updatedAt: 10,
|
||||
status: "running",
|
||||
},
|
||||
});
|
||||
|
||||
// Default visibility is "tree". The tool is constructed with the Telegram
|
||||
// sandbox key as agentSessionKey but the live run session key as runSessionKey.
|
||||
// semantic-current must be treated as self for visibility purposes.
|
||||
const tool = createSessionStatusTool({
|
||||
agentSessionKey: "agent:main:telegram:default:direct:1234",
|
||||
runSessionKey: "agent:main:main",
|
||||
config: mockConfig as never,
|
||||
});
|
||||
|
||||
const result = await tool.execute("call-current-run-session", { sessionKey: "current" });
|
||||
const details = result.details as { ok?: boolean; sessionKey?: string };
|
||||
expect(details.ok).toBe(true);
|
||||
expect(details.sessionKey).toBe("agent:main:main");
|
||||
});
|
||||
|
||||
it("rejects explicit cross-session key under tree visibility even when it equals runSessionKey (#76708)", async () => {
|
||||
resetSessionStore({
|
||||
"agent:main:telegram:default:direct:1234": {
|
||||
sessionId: "s-tg-direct",
|
||||
updatedAt: 5,
|
||||
status: "done",
|
||||
},
|
||||
"agent:main:main": {
|
||||
sessionId: "s-main",
|
||||
updatedAt: 10,
|
||||
status: "running",
|
||||
},
|
||||
});
|
||||
|
||||
// Same setup but with an explicit key — should NOT bypass visibility.
|
||||
const tool = createSessionStatusTool({
|
||||
agentSessionKey: "agent:main:telegram:default:direct:1234",
|
||||
runSessionKey: "agent:main:main",
|
||||
config: mockConfig as never,
|
||||
});
|
||||
|
||||
await expect(
|
||||
tool.execute("call-explicit-key", { sessionKey: "agent:main:main" }),
|
||||
).rejects.toThrow(/visibility is restricted/);
|
||||
});
|
||||
|
||||
it("treats the TUI client label as the current requester session", async () => {
|
||||
resetSessionStore({
|
||||
"agent:main:main": {
|
||||
@@ -590,6 +645,29 @@ describe("session_status tool", () => {
|
||||
expect(details.statusText).toContain("🧠 Model:");
|
||||
});
|
||||
|
||||
it("resolves sandboxed sessionKey=current to the requester when no run session override exists", async () => {
|
||||
resetSessionStore({});
|
||||
|
||||
const tool = getSessionStatusTool("agent:main:telegram:group:-5096326138", {
|
||||
sandboxed: true,
|
||||
});
|
||||
|
||||
const result = await tool.execute("call-current-sandboxed-channel", {
|
||||
sessionKey: "current",
|
||||
});
|
||||
const details = result.details as { ok?: boolean; sessionKey?: string; statusText?: string };
|
||||
expect(details.ok).toBe(true);
|
||||
expect(details.sessionKey).toBe("agent:main:telegram:group:-5096326138");
|
||||
expect(details.statusText).toContain("OpenClaw");
|
||||
expect(details.statusText).toContain("🧠 Model:");
|
||||
expect(callGatewayMock).not.toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
method: "sessions.resolve",
|
||||
params: expect.objectContaining({ key: "current" }),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("resolves the default session_status lookup for a channel-plugin requester via implicit fallback", async () => {
|
||||
resetSessionStore({});
|
||||
|
||||
|
||||
@@ -260,6 +260,12 @@ export function createOpenClawTools(
|
||||
sandboxBrowserBridgeUrl?: string;
|
||||
allowHostBrowserControl?: boolean;
|
||||
agentSessionKey?: string;
|
||||
/**
|
||||
* The actual live run session key. When the tool is constructed with a sandbox/policy
|
||||
* session key, this allows `session_status({sessionKey:"current"})` to resolve to
|
||||
* the live run session instead of the stale sandbox key.
|
||||
*/
|
||||
runSessionKey?: string;
|
||||
agentChannel?: GatewayMessageChannel;
|
||||
agentAccountId?: string;
|
||||
/** Delivery target for topic/thread routing. */
|
||||
@@ -588,6 +594,7 @@ export function createOpenClawTools(
|
||||
}),
|
||||
createSessionStatusTool({
|
||||
agentSessionKey: options?.agentSessionKey,
|
||||
runSessionKey: options?.runSessionKey,
|
||||
config: resolvedConfig,
|
||||
sandboxed: options?.sandboxed,
|
||||
}),
|
||||
|
||||
@@ -664,6 +664,10 @@ async function compactEmbeddedPiSessionDirectOnce(
|
||||
messageProvider: resolvedMessageProvider,
|
||||
agentAccountId: params.agentAccountId,
|
||||
sessionKey: sandboxSessionKey,
|
||||
runSessionKey:
|
||||
params.sessionKey && params.sessionKey !== sandboxSessionKey
|
||||
? params.sessionKey
|
||||
: undefined,
|
||||
sessionId: params.sessionId,
|
||||
runId: params.runId,
|
||||
groupId: params.groupId,
|
||||
|
||||
@@ -885,6 +885,13 @@ export async function runEmbeddedAttempt(
|
||||
ownerOnlyToolAllowlist: params.ownerOnlyToolAllowlist,
|
||||
allowGatewaySubagentBinding: params.allowGatewaySubagentBinding,
|
||||
sessionKey: sandboxSessionKey,
|
||||
// When sandboxSessionKey differs from the real run session key (e.g. Telegram
|
||||
// direct peer key vs agent:main:main), pass the live key so session_status
|
||||
// "current" resolves to the active run session, not the stale sandbox key.
|
||||
runSessionKey:
|
||||
params.sessionKey && params.sessionKey !== sandboxSessionKey
|
||||
? params.sessionKey
|
||||
: undefined,
|
||||
sessionId: params.sessionId,
|
||||
runId: params.runId,
|
||||
agentDir,
|
||||
|
||||
@@ -274,6 +274,12 @@ export function createOpenClawCodingTools(options?: {
|
||||
messageThreadId?: string | number;
|
||||
sandbox?: SandboxContext | null;
|
||||
sessionKey?: string;
|
||||
/**
|
||||
* The actual live run session key. When the tool set is constructed with a
|
||||
* sandbox/policy session key, this allows `session_status({sessionKey:"current"})`
|
||||
* to resolve to the live run session instead of the stale sandbox key.
|
||||
*/
|
||||
runSessionKey?: string;
|
||||
/** Ephemeral session UUID — regenerated on /new and /reset. */
|
||||
sessionId?: string;
|
||||
/** Stable run identifier for this agent invocation. */
|
||||
@@ -698,6 +704,7 @@ export function createOpenClawCodingTools(options?: {
|
||||
sandboxBrowserBridgeUrl: sandbox?.browser?.bridgeUrl,
|
||||
allowHostBrowserControl: sandbox ? sandbox.browserAllowHostControl : true,
|
||||
agentSessionKey: options?.sessionKey,
|
||||
runSessionKey: options?.runSessionKey,
|
||||
agentChannel: resolveGatewayMessageChannel(options?.messageProvider),
|
||||
agentAccountId: options?.agentAccountId,
|
||||
agentTo: options?.messageTo,
|
||||
|
||||
@@ -276,6 +276,12 @@ async function resolveModelOverride(params: {
|
||||
|
||||
export function createSessionStatusTool(opts?: {
|
||||
agentSessionKey?: string;
|
||||
/**
|
||||
* The actual live run session key. When the tool is constructed with a sandbox/policy
|
||||
* session key (e.g. a Telegram direct peer key), this allows `session_status({sessionKey:
|
||||
* "current"})` to resolve to the live run session instead of the stale sandbox key.
|
||||
*/
|
||||
runSessionKey?: string;
|
||||
config?: OpenClawConfig;
|
||||
sandboxed?: boolean;
|
||||
}): AnyAgentTool {
|
||||
@@ -346,12 +352,31 @@ export function createSessionStatusTool(opts?: {
|
||||
|
||||
const requestedKeyParam = readStringParam(params, "sessionKey");
|
||||
let requestedKeyRaw = requestedKeyParam ?? opts?.agentSessionKey;
|
||||
|
||||
// Track whether this is a semantic-current request (literal "current" or a
|
||||
// current-client alias) BEFORE any rewrite, so visibility treats it as self.
|
||||
const isSemanticCurrentRequest =
|
||||
requestedKeyRaw === "current" ||
|
||||
Boolean(
|
||||
resolveCurrentSessionClientAlias({
|
||||
key: requestedKeyRaw ?? "",
|
||||
requesterInternalKey: effectiveRequesterKey,
|
||||
}),
|
||||
);
|
||||
|
||||
// Resolve semantic "current" to the live run session key for lookup purposes (#76708).
|
||||
// In sandboxed channel runs there may be no separate runSessionKey because the sandbox
|
||||
// key already is the live requester; avoid probing literal "current" through the gateway.
|
||||
if (requestedKeyRaw === "current" && (opts?.runSessionKey || opts?.sandboxed === true)) {
|
||||
requestedKeyRaw = opts.runSessionKey ?? effectiveRequesterKey;
|
||||
}
|
||||
|
||||
const currentSessionAlias = resolveCurrentSessionClientAlias({
|
||||
key: requestedKeyRaw ?? "",
|
||||
requesterInternalKey: effectiveRequesterKey,
|
||||
});
|
||||
if (currentSessionAlias) {
|
||||
requestedKeyRaw = currentSessionAlias;
|
||||
requestedKeyRaw = opts?.runSessionKey ?? currentSessionAlias;
|
||||
}
|
||||
const requestedKeyInput = requestedKeyRaw?.trim() ?? "";
|
||||
let resolvedViaSessionId = false;
|
||||
@@ -374,7 +399,7 @@ export function createSessionStatusTool(opts?: {
|
||||
}
|
||||
};
|
||||
|
||||
if (requestedKeyRaw.startsWith("agent:")) {
|
||||
if (requestedKeyRaw.startsWith("agent:") && !isSemanticCurrentRequest) {
|
||||
const requestedAgentId = resolveAgentIdFromSessionKey(requestedKeyRaw);
|
||||
ensureAgentAccess(requestedAgentId);
|
||||
const access = visibilityGuard.check(
|
||||
@@ -485,7 +510,7 @@ export function createSessionStatusTool(opts?: {
|
||||
|
||||
if (!resolved) {
|
||||
const fallback = resolveImplicitCurrentSessionFallback({
|
||||
allowFallback: requestedKeyRaw === "current" || requestedKeyParam === undefined,
|
||||
allowFallback: isSemanticCurrentRequest || requestedKeyParam === undefined,
|
||||
storeScopedRequesterKey,
|
||||
});
|
||||
if (fallback) {
|
||||
@@ -501,6 +526,7 @@ export function createSessionStatusTool(opts?: {
|
||||
|
||||
// Preserve caller-scoped raw-key/current lookups as "self" for visibility checks.
|
||||
const shouldTreatVisibilityTargetAsSelf =
|
||||
isSemanticCurrentRequest ||
|
||||
resolvedViaImplicitCurrentFallback ||
|
||||
(!resolvedViaSessionId &&
|
||||
(requestedKeyInput === "current" || resolved.key === requestedKeyInput));
|
||||
|
||||
@@ -522,7 +522,7 @@ describe("package artifact reuse", () => {
|
||||
expect(workflow).toContain("published_upgrade_survivor_scenarios: reported-issues");
|
||||
expect(workflow).toContain("telegram_mode: mock-openai");
|
||||
expect(workflow).toContain(
|
||||
"telegram_scenarios: telegram-help-command,telegram-commands-command,telegram-tools-compact-command,telegram-whoami-command,telegram-context-command,telegram-mention-gating",
|
||||
"telegram_scenarios: telegram-help-command,telegram-commands-command,telegram-tools-compact-command,telegram-whoami-command,telegram-context-command,telegram-current-session-status-tool,telegram-mention-gating",
|
||||
);
|
||||
expect(workflow).toContain("ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}");
|
||||
expect(workflow).toContain("ANTHROPIC_API_TOKEN: ${{ secrets.ANTHROPIC_API_TOKEN }}");
|
||||
|
||||
Reference in New Issue
Block a user