mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix: default optional Swift protocol fields (#103493)
This commit is contained in:
committed by
GitHub
parent
ed74d8dc7d
commit
e169bfed7c
@@ -25,6 +25,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
### Fixes
|
||||
|
||||
- **Swift protocol initializers:** default every schema-optional generated initializer parameter to `nil` so additive protocol fields no longer break SDK construction call sites.
|
||||
- **OpenCode Go MiMo catalog:** stop exposing the deprecated `mimo-v2-omni` and `mimo-v2-pro` aliases that reject agent requests, and keep release validation on the active MiMo V2.5 routes. (#103311, #103329) Thanks @krissding.
|
||||
- **OpenAI-compatible streamed tool calls:** execute complete native tool calls from streams that end with SSE `data: [DONE]` but omit `finish_reason`, while keeping transport EOF and visible-text cases fail-closed. (#98124, #97994) Thanks @SunnyShu0925.
|
||||
- **xAI provider aliases:** preserve Grok 4.3 and Grok 4.5 thinking profiles, fast-model routing, and encrypted reasoning replay when models use the shipped `x-ai` provider alias instead of clamping valid thinking requests to `minimal`. (#103315)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+30
-21
@@ -3,40 +3,49 @@ import Testing
|
||||
|
||||
struct GatewayModelsCompatibilityTests {
|
||||
@Test
|
||||
func `plugin approval request params keeps reviewer devices additive`() {
|
||||
func `optional fields stay additive around required fields`() {
|
||||
let params = PluginApprovalRequestParams(
|
||||
pluginid: nil,
|
||||
title: "Install plugin",
|
||||
description: "Review requested",
|
||||
severity: nil,
|
||||
toolname: nil,
|
||||
toolcallid: nil,
|
||||
alloweddecisions: nil,
|
||||
sessionkey: nil,
|
||||
turnsourcechannel: nil,
|
||||
turnsourceto: nil,
|
||||
turnsourceaccountid: nil,
|
||||
turnsourcethreadid: nil,
|
||||
timeoutms: nil,
|
||||
twophase: nil)
|
||||
description: "Review requested")
|
||||
|
||||
#expect(params.pluginid == nil)
|
||||
#expect(params.approvalreviewerdeviceids == nil)
|
||||
}
|
||||
|
||||
@Test
|
||||
func `message action params keeps requester account additive`() {
|
||||
func `optional fields stay additive before trailing required fields`() {
|
||||
let params = MessageActionParams(
|
||||
channel: "slack",
|
||||
action: "member-info",
|
||||
params: [:],
|
||||
accountid: "default",
|
||||
requestersenderid: "U123",
|
||||
senderisowner: true,
|
||||
sessionkey: nil,
|
||||
sessionid: nil,
|
||||
toolcontext: nil,
|
||||
idempotencykey: "test")
|
||||
|
||||
#expect(params.accountid == nil)
|
||||
#expect(params.requesteraccountid == nil)
|
||||
}
|
||||
|
||||
@Test
|
||||
func `strict literal model optional fields default to nil`() {
|
||||
let result = PluginsSessionActionSuccessResult()
|
||||
|
||||
#expect(result.ok)
|
||||
#expect(result.result == nil)
|
||||
}
|
||||
|
||||
@Test
|
||||
func `chat send canonical initializer stays unambiguous`() {
|
||||
let params = ChatSendParams(
|
||||
sessionkey: "main",
|
||||
message: "hello",
|
||||
idempotencykey: "test")
|
||||
let legacyParams = ChatSendParams(
|
||||
sessionkey: "main",
|
||||
message: "hello",
|
||||
fastmode: true,
|
||||
idempotencykey: "test")
|
||||
|
||||
#expect(params.agentid == nil)
|
||||
#expect(params.fastmodevalue == nil)
|
||||
#expect(legacyParams.fastmode == true)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1733,7 +1733,7 @@
|
||||
"prompt:snapshots:check": "node --import tsx scripts/generate-prompt-snapshots.ts --check",
|
||||
"prompt:snapshots:gen": "node --import tsx scripts/generate-prompt-snapshots.ts --write",
|
||||
"prompt:snapshots:sync-codex-model": "node --import tsx scripts/sync-codex-model-prompt-fixture.ts",
|
||||
"protocol:check": "pnpm protocol:gen && pnpm protocol:gen:swift && git diff --exit-code -- dist/protocol.schema.json apps/macos/Sources/OpenClawProtocol/GatewayModels.swift apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift",
|
||||
"protocol:check": "pnpm protocol:gen && pnpm protocol:gen:swift && git diff --exit-code -- dist/protocol.schema.json apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift",
|
||||
"protocol:gen": "node --import tsx scripts/protocol-gen.ts",
|
||||
"protocol:gen:swift": "node --import tsx scripts/protocol-gen-swift.ts",
|
||||
"proxy:coverage": "node scripts/run-node.mjs proxy coverage",
|
||||
|
||||
@@ -41,73 +41,6 @@ const STRICT_LITERAL_STRUCTS = new Set([
|
||||
"PluginsSessionActionFailureResult",
|
||||
]);
|
||||
|
||||
const DEFAULTED_OPTIONAL_INIT_PARAM_ENTRIES: readonly [string, readonly string[]][] = [
|
||||
["CrestodianChatResult", ["sensitive"]],
|
||||
["SendParams", ["buffer", "filename", "contentType"]],
|
||||
["SessionOperationEvent", ["agentId"]],
|
||||
["SessionsCompactionListParams", ["agentId"]],
|
||||
["SessionsCompactionGetParams", ["agentId"]],
|
||||
["SessionsCompactionBranchParams", ["agentId"]],
|
||||
["SessionsCompactionRestoreParams", ["agentId"]],
|
||||
["SessionsSendParams", ["agentId"]],
|
||||
["SessionsMessagesSubscribeParams", ["agentId"]],
|
||||
["SessionsMessagesUnsubscribeParams", ["agentId"]],
|
||||
["SessionsAbortParams", ["agentId"]],
|
||||
["SessionsListParams", ["archived"]],
|
||||
["SessionsPatchParams", ["agentId", "category", "archived", "pinned"]],
|
||||
["SessionsResetParams", ["agentId"]],
|
||||
[
|
||||
"SessionsDeleteParams",
|
||||
["agentId", "expectedSessionId", "expectedLifecycleRevision", "expectedSessionUpdatedAt"],
|
||||
],
|
||||
["SessionsCompactParams", ["agentId"]],
|
||||
["SessionsResolveParams", ["allowMissing"]],
|
||||
["SessionsUsageParams", ["agentId", "agentScope", "timeZone"]],
|
||||
["ChatHistoryParams", ["agentId", "offset"]],
|
||||
["ChatSendParams", ["agentId"]],
|
||||
["ChatAbortParams", ["agentId", "preserveSideRuns"]],
|
||||
["ChatInjectParams", ["agentId"]],
|
||||
["ChatDeltaEvent", ["agentId"]],
|
||||
["ChatFinalEvent", ["agentId"]],
|
||||
["ChatAbortedEvent", ["agentId", "errorMessage"]],
|
||||
["ChatErrorEvent", ["agentId"]],
|
||||
["ArtifactsListParams", ["agentId"]],
|
||||
["ArtifactsGetParams", ["agentId"]],
|
||||
["ArtifactsDownloadParams", ["agentId"]],
|
||||
["MessageActionParams", ["inboundTurnKind", "requesterAccountId"]],
|
||||
["CronListParams", ["compact"]],
|
||||
[
|
||||
"CronJob",
|
||||
[
|
||||
"declarationKey",
|
||||
"displayName",
|
||||
"owner",
|
||||
"configRevision",
|
||||
"nextRunAtMs",
|
||||
"lastRunAtMs",
|
||||
"lastRunStatus",
|
||||
"lastRunError",
|
||||
"lastDelivered",
|
||||
"lastDeliveryStatus",
|
||||
"lastDeliveryError",
|
||||
"lastFailureNotificationDelivered",
|
||||
"lastFailureNotificationDeliveryStatus",
|
||||
"lastFailureNotificationDeliveryError",
|
||||
],
|
||||
],
|
||||
["CronAddParams", ["declarationKey", "displayName", "owner"]],
|
||||
["CronRunLogEntry", ["errorReason", "failureNotificationDelivery"]],
|
||||
["ExecApprovalRequestParams", ["requireDeliveryRoute", "suppressDelivery"]],
|
||||
["PluginApprovalRequestParams", ["approvalReviewerDeviceIds"]],
|
||||
["DevicePairSetupCodeResult", ["gatewayUrls"]],
|
||||
["AgentSummary", ["thinkingLevels", "thinkingOptions", "thinkingDefault"]],
|
||||
["ModelChoice", ["available"]],
|
||||
];
|
||||
|
||||
const DEFAULTED_OPTIONAL_INIT_PARAMS: Record<string, Set<string>> = Object.fromEntries(
|
||||
DEFAULTED_OPTIONAL_INIT_PARAM_ENTRIES.map(([name, params]) => [name, new Set(params)]),
|
||||
);
|
||||
|
||||
const header = `// Generated by scripts/protocol-gen-swift.ts — do not edit by hand\n// swiftlint:disable file_length\nimport Foundation\n\npublic let GATEWAY_PROTOCOL_VERSION = ${PROTOCOL_VERSION}\npublic let GATEWAY_MIN_PROTOCOL_VERSION = ${MIN_CLIENT_PROTOCOL_VERSION}\n\nprivate struct GatewayAnyCodingKey: CodingKey, Hashable {\n let stringValue: String\n let intValue: Int?\n\n init?(stringValue: String) {\n self.stringValue = stringValue\n self.intValue = nil\n }\n\n init?(intValue: Int) {\n self.stringValue = String(intValue)\n self.intValue = intValue\n }\n}\n\npublic enum ErrorCode: String, Codable, Sendable {\n${Object.values(
|
||||
ErrorCodes,
|
||||
)
|
||||
@@ -280,21 +213,13 @@ function stringEnumCases(schema: JsonSchema): string[] | undefined {
|
||||
}
|
||||
|
||||
function swiftInitializerParam(params: {
|
||||
structName: string;
|
||||
key: string;
|
||||
name: string;
|
||||
schema: JsonSchema;
|
||||
required: boolean;
|
||||
allowStructuralNamed?: boolean;
|
||||
}): string {
|
||||
const type = swiftType(params.schema, true, params.allowStructuralNamed ?? true);
|
||||
if (params.required) {
|
||||
return `${params.name}: ${type}`;
|
||||
}
|
||||
const defaultNil =
|
||||
params.key === "agentId" ||
|
||||
(DEFAULTED_OPTIONAL_INIT_PARAMS[params.structName]?.has(params.key) ?? false);
|
||||
return `${params.name}: ${type}?${defaultNil ? " = nil" : ""}`;
|
||||
return params.required ? `${params.name}: ${type}` : `${params.name}: ${type}? = nil`;
|
||||
}
|
||||
|
||||
function emitEnum(name: string, schema: JsonSchema): string {
|
||||
@@ -362,8 +287,6 @@ function emitStruct(name: string, schema: JsonSchema): string {
|
||||
const propName = safeName(key);
|
||||
const req = required.has(key);
|
||||
return ` ${swiftInitializerParam({
|
||||
structName: name,
|
||||
key,
|
||||
name: propName,
|
||||
schema: prop,
|
||||
required: req,
|
||||
@@ -454,8 +377,6 @@ function emitStruct(name: string, schema: JsonSchema): string {
|
||||
const propName = swiftInitializerName(name, key);
|
||||
const req = required.has(key);
|
||||
return ` ${swiftInitializerParam({
|
||||
structName: name,
|
||||
key,
|
||||
name: propName,
|
||||
schema: prop,
|
||||
required: req,
|
||||
@@ -503,8 +424,6 @@ function emitStructCompatibilityInitializer(
|
||||
return " fastmode: Bool?";
|
||||
}
|
||||
return ` ${swiftInitializerParam({
|
||||
structName: name,
|
||||
key,
|
||||
name: propName,
|
||||
schema: prop,
|
||||
required: required.has(key),
|
||||
|
||||
Reference in New Issue
Block a user