Skip to content

Commit 53f04af

Browse files
hyperpolymathclaude
andcommitted
fix(zig): two more Zig 0.15 API fixes — callconv(.C) + http response writer
- 22 FFI files: strip `callconv(.C)` from `pub export fn` signatures (in Zig 0.15 CallingConvention.C was removed; callconv is implicit on export) - 4 http FFI files: replace ArrayList.init + response_storage union with std.Io.Writer.Allocating + response_writer field (Zig 0.15 replaced FetchOptions.response_storage union with response_writer: ?*Writer; ArrayList is now unmanaged and has no init; use Io.Writer.Allocating.init instead) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 875bd3b commit 53f04af

26 files changed

Lines changed: 128 additions & 122 deletions

File tree

cartridges/aerie-mcp/ffi/aerie_ffi.zig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,24 @@
66
const std = @import("std");
77

88
/// List active environment count.
9-
export fn aerie_list_envs_count() callconv(.C) u32 {
9+
export fn aerie_list_envs_count() u32 {
1010
return 0; // Stub
1111
}
1212

1313
/// Create an environment. Returns env ID or 0 on failure.
14-
export fn aerie_create_env(name: [*c]const u8, mem_mb: u32) callconv(.C) u32 {
14+
export fn aerie_create_env(name: [*c]const u8, mem_mb: u32) u32 {
1515
if (name == null or mem_mb == 0) return 0;
1616
return 1; // Stub
1717
}
1818

1919
/// Destroy an environment. Returns 0 on success.
20-
export fn aerie_destroy_env(env_id: u32) callconv(.C) i32 {
20+
export fn aerie_destroy_env(env_id: u32) i32 {
2121
if (env_id == 0) return -1;
2222
return 0; // Stub
2323
}
2424

2525
/// Get env status: 0=provisioning, 1=ready, 2=destroying, 3=destroyed, 4=error.
26-
export fn aerie_get_status(env_id: u32) callconv(.C) u8 {
26+
export fn aerie_get_status(env_id: u32) u8 {
2727
if (env_id == 0) return 4; // Error
2828
return 1; // Stub — ready
2929
}

cartridges/burble-admin-mcp/ffi/burble_admin_ffi.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub const PermLevel = enum(i32) {
3232

3333
/// Returns the minimum permission level for an operation.
3434
/// Matches burble_min_perm in Protocol.idr exactly.
35-
pub export fn burble_admin_min_perm(op: i32) callconv(.C) i32 {
35+
pub export fn burble_admin_min_perm(op: i32) i32 {
3636
return switch (@as(Operation, @enumFromInt(op))) {
3737
.list_rooms => 0,
3838
.create_room => 1,
@@ -46,7 +46,7 @@ pub export fn burble_admin_min_perm(op: i32) callconv(.C) i32 {
4646

4747
/// Check if a user with the given permission level can perform the operation.
4848
/// Returns 1 if allowed, 0 if denied.
49-
pub export fn burble_admin_check_perm(op: i32, user_perm: i32) callconv(.C) i32 {
49+
pub export fn burble_admin_check_perm(op: i32, user_perm: i32) i32 {
5050
const required = burble_admin_min_perm(op);
5151
return if (user_perm >= required) 1 else 0;
5252
}
@@ -56,7 +56,7 @@ pub export fn burble_admin_check_perm(op: i32, user_perm: i32) callconv(.C) i32
5656
// ═══════════════════════════════════════════════════════════════════════
5757

5858
/// Validate room capacity (1-500). Returns clamped value.
59-
pub export fn burble_admin_clamp_capacity(requested: i32) callconv(.C) i32 {
59+
pub export fn burble_admin_clamp_capacity(requested: i32) i32 {
6060
if (requested < 1) return 1;
6161
if (requested > 500) return 500;
6262
return requested;

cartridges/civic-connect-mcp/ffi/civic_connect_ffi.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,18 @@
66
const std = @import("std");
77

88
/// List active channel count.
9-
export fn civic_connect_list_channels_count() callconv(.C) u32 {
9+
export fn civic_connect_list_channels_count() u32 {
1010
return 0; // Stub
1111
}
1212

1313
/// Send a message to a channel. Returns 0 on success, -1 on error.
14-
export fn civic_connect_send_message(channel_id: u32, body: [*c]const u8) callconv(.C) i32 {
14+
export fn civic_connect_send_message(channel_id: u32, body: [*c]const u8) i32 {
1515
if (channel_id == 0 or body == null) return -1;
1616
return 0; // Stub
1717
}
1818

1919
/// Get poll results. Returns total vote count, or 0 if poll not found.
20-
export fn civic_connect_get_poll(poll_id: u32) callconv(.C) u32 {
20+
export fn civic_connect_get_poll(poll_id: u32) u32 {
2121
if (poll_id == 0) return 0;
2222
return 0; // Stub
2323
}

cartridges/conflow-mcp/ffi/conflow_ffi.zig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,25 @@
66
const std = @import("std");
77

88
/// Get a config value by key. Returns 0 if found, -1 if missing.
9-
export fn conflow_get_config(key: [*c]const u8) callconv(.C) i32 {
9+
export fn conflow_get_config(key: [*c]const u8) i32 {
1010
if (key == null) return -1;
1111
return 0; // Stub
1212
}
1313

1414
/// Apply a config blob. Returns number of entries applied, or -1 on error.
15-
export fn conflow_apply_config(blob: [*c]const u8) callconv(.C) i32 {
15+
export fn conflow_apply_config(blob: [*c]const u8) i32 {
1616
if (blob == null) return -1;
1717
return 0; // Stub
1818
}
1919

2020
/// Validate a config blob. Returns 0 if valid, error count otherwise.
21-
export fn conflow_validate_config(blob: [*c]const u8) callconv(.C) i32 {
21+
export fn conflow_validate_config(blob: [*c]const u8) i32 {
2222
if (blob == null) return -1;
2323
return 0; // Stub — valid
2424
}
2525

2626
/// Diff two config blobs. Returns number of differences.
27-
export fn conflow_diff_config(a: [*c]const u8, b: [*c]const u8) callconv(.C) u32 {
27+
export fn conflow_diff_config(a: [*c]const u8, b: [*c]const u8) u32 {
2828
if (a == null or b == null) return 0;
2929
return 0; // Stub
3030
}

cartridges/dns-shield-mcp/ffi/dns_shield_ffi.zig

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export fn dns_shield_resolve_doq(
5757
domain: [*:0]const u8,
5858
record_type: RecordType,
5959
result: *DnsResult,
60-
) callconv(.C) i32 {
60+
) i32 {
6161
return resolve_encrypted(domain, record_type, .doq, result);
6262
}
6363

@@ -66,7 +66,7 @@ export fn dns_shield_resolve_doh(
6666
domain: [*:0]const u8,
6767
record_type: RecordType,
6868
result: *DnsResult,
69-
) callconv(.C) i32 {
69+
) i32 {
7070
return resolve_encrypted(domain, record_type, .doh, result);
7171
}
7272

@@ -75,7 +75,7 @@ export fn dns_shield_resolve_doh(
7575
export fn dns_shield_validate_dnssec(
7676
domain: [*:0]const u8,
7777
record_type: RecordType,
78-
) callconv(.C) DnssecState {
78+
) DnssecState {
7979
// DNSSEC validation requires checking RRSIG + DNSKEY chain.
8080
// For now, delegate to the system resolver's DNSSEC support
8181
// (most modern resolvers like systemd-resolved, Unbound, or
@@ -90,7 +90,7 @@ export fn dns_shield_validate_dnssec(
9090
export fn dns_shield_check_caa(
9191
domain: [*:0]const u8,
9292
ca_domain: [*:0]const u8,
93-
) callconv(.C) i32 {
93+
) i32 {
9494
_ = domain;
9595
_ = ca_domain;
9696
// CAA check: resolve CAA records, compare with ca_domain.
@@ -99,12 +99,12 @@ export fn dns_shield_check_caa(
9999
}
100100

101101
/// Flush the DNS cache for all encrypted resolvers.
102-
export fn dns_shield_flush_cache() callconv(.C) void {
102+
export fn dns_shield_flush_cache() void {
103103
// Clear any cached DoQ/DoH responses.
104104
}
105105

106106
/// Get the DNS Shield cartridge version.
107-
export fn dns_shield_version() callconv(.C) [*:0]const u8 {
107+
export fn dns_shield_version() [*:0]const u8 {
108108
return "0.5.0";
109109
}
110110

cartridges/game-admin-mcp/ffi/game_admin_ffi.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub const PermLevel = enum(i32) {
2222
admin = 2,
2323
};
2424

25-
pub export fn game_admin_min_perm(op: i32) callconv(.C) i32 {
25+
pub export fn game_admin_min_perm(op: i32) i32 {
2626
return switch (@as(Operation, @enumFromInt(op))) {
2727
.list_servers => 0,
2828
.get_server_status => 0,
@@ -35,12 +35,12 @@ pub export fn game_admin_min_perm(op: i32) callconv(.C) i32 {
3535
};
3636
}
3737

38-
pub export fn game_admin_check_perm(op: i32, user_perm: i32) callconv(.C) i32 {
38+
pub export fn game_admin_check_perm(op: i32, user_perm: i32) i32 {
3939
const required = game_admin_min_perm(op);
4040
return if (user_perm >= required) 1 else 0;
4141
}
4242

43-
pub export fn game_admin_is_readonly(op: i32) callconv(.C) i32 {
43+
pub export fn game_admin_is_readonly(op: i32) i32 {
4444
return switch (@as(Operation, @enumFromInt(op))) {
4545
.list_servers, .get_server_status, .get_logs, .probe_health => 1,
4646
else => 0,

cartridges/github-api-mcp/ffi/github_api_mcp_ffi.zig

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -377,15 +377,15 @@ fn doHttpRequest(
377377
const http_method = parseHttpMethod(method);
378378

379379
// Fetch the request (Zig 0.15 API — replaces open/send/wait)
380-
var response_storage = std.ArrayList(u8).init(allocator);
381-
defer response_storage.deinit();
380+
var aw: std.Io.Writer.Allocating = .init(allocator);
381+
defer aw.deinit();
382382

383383
const fetch_result = client.fetch(.{
384384
.method = http_method,
385385
.location = .{ .uri = uri },
386386
.extra_headers = &headers_buf,
387387
.payload = body,
388-
.response_storage = .{ .dynamic = &response_storage },
388+
.response_writer = &aw.writer,
389389
}) catch return -5;
390390

391391
// Handle rate limiting (HTTP 429 or 403 with depleted budget)
@@ -402,8 +402,9 @@ fn doHttpRequest(
402402
}
403403

404404
// Copy response body into the caller's output buffer
405-
const to_copy = @min(response_storage.items.len, out_cap);
406-
@memcpy(out_buf[0..to_copy], response_storage.items[0..to_copy]);
405+
const response_bytes = aw.writer.buffered();
406+
const to_copy = @min(response_bytes.len, out_cap);
407+
@memcpy(out_buf[0..to_copy], response_bytes[0..to_copy]);
407408
return @intCast(to_copy);
408409
}
409410

cartridges/gitlab-api-mcp/ffi/gitlab_api_mcp_ffi.zig

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -330,15 +330,15 @@ pub export fn gitlab_api_mcp_request(
330330
} else null;
331331

332332
// Fetch the request (Zig 0.15 API — replaces open/send/wait)
333-
var response_storage = std.ArrayList(u8).init(allocator);
334-
defer response_storage.deinit();
333+
var aw: std.Io.Writer.Allocating = .init(allocator);
334+
defer aw.deinit();
335335

336336
const fetch_result = client.fetch(.{
337337
.method = http_method,
338338
.location = .{ .uri = uri },
339339
.extra_headers = &headers_buf,
340340
.payload = body_slice,
341-
.response_storage = .{ .dynamic = &response_storage },
341+
.response_writer = &aw.writer,
342342
}) catch return -4;
343343

344344
// Handle rate limiting (HTTP 429)
@@ -350,8 +350,9 @@ pub export fn gitlab_api_mcp_request(
350350
}
351351

352352
// Handle server errors
353-
const bytes_read = @min(response_storage.items.len, cap);
354-
@memcpy(out_buf[0..bytes_read], response_storage.items[0..bytes_read]);
353+
const response_bytes = aw.writer.buffered();
354+
const bytes_read = @min(response_bytes.len, cap);
355+
@memcpy(out_buf[0..bytes_read], response_bytes[0..bytes_read]);
355356
out_len.* = @intCast(bytes_read);
356357

357358
if (status_code >= 500) {
@@ -436,15 +437,15 @@ pub export fn gitlab_api_mcp_graphql(
436437
};
437438

438439
// Fetch the request (Zig 0.15 API — replaces open/send/wait)
439-
var response_storage = std.ArrayList(u8).init(allocator);
440-
defer response_storage.deinit();
440+
var aw: std.Io.Writer.Allocating = .init(allocator);
441+
defer aw.deinit();
441442

442443
const fetch_result = client.fetch(.{
443444
.method = .POST,
444445
.location = .{ .uri = uri },
445446
.extra_headers = &headers_buf,
446447
.payload = gql_body,
447-
.response_storage = .{ .dynamic = &response_storage },
448+
.response_writer = &aw.writer,
448449
}) catch return -4;
449450

450451
const status_code = @intFromEnum(fetch_result.status);
@@ -454,8 +455,9 @@ pub export fn gitlab_api_mcp_graphql(
454455
return -3;
455456
}
456457

457-
const bytes_read = @min(response_storage.items.len, cap);
458-
@memcpy(out_buf[0..bytes_read], response_storage.items[0..bytes_read]);
458+
const response_bytes = aw.writer.buffered();
459+
const bytes_read = @min(response_bytes.len, cap);
460+
@memcpy(out_buf[0..bytes_read], response_bytes[0..bytes_read]);
459461
out_len.* = @intCast(bytes_read);
460462
return 0;
461463
}
@@ -528,15 +530,15 @@ pub export fn gitlab_api_mcp_setup_mirror(
528530
};
529531

530532
// Fetch the request (Zig 0.15 API — replaces open/send/wait)
531-
var response_storage = std.ArrayList(u8).init(allocator);
532-
defer response_storage.deinit();
533+
var aw: std.Io.Writer.Allocating = .init(allocator);
534+
defer aw.deinit();
533535

534536
const fetch_result = client.fetch(.{
535537
.method = .POST,
536538
.location = .{ .uri = uri },
537539
.extra_headers = &headers_buf_mirror,
538540
.payload = mirror_body,
539-
.response_storage = .{ .dynamic = &response_storage },
541+
.response_writer = &aw.writer,
540542
}) catch return -4;
541543

542544
const status_code = @intFromEnum(fetch_result.status);
@@ -546,8 +548,9 @@ pub export fn gitlab_api_mcp_setup_mirror(
546548
return -3;
547549
}
548550

549-
const bytes_read = @min(response_storage.items.len, cap);
550-
@memcpy(out_buf[0..bytes_read], response_storage.items[0..bytes_read]);
551+
const response_bytes = aw.writer.buffered();
552+
const bytes_read = @min(response_bytes.len, cap);
553+
@memcpy(out_buf[0..bytes_read], response_bytes[0..bytes_read]);
551554
out_len.* = @intCast(bytes_read);
552555
return 0;
553556
}

cartridges/gossamer-mcp/ffi/gossamer_ffi.zig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,26 @@ const std = @import("std");
99
pub const WindowHandle = u32;
1010

1111
/// Create a new webview window. Returns handle or 0 on failure.
12-
export fn gossamer_create_window(width: u32, height: u32) callconv(.C) WindowHandle {
12+
export fn gossamer_create_window(width: u32, height: u32) WindowHandle {
1313
if (width == 0 or height == 0) return 0;
1414
// Stub: real impl delegates to libgossamer
1515
return 1;
1616
}
1717

1818
/// Load a panel by URI into a window. Returns 0 on success, -1 on error.
19-
export fn gossamer_load_panel(handle: WindowHandle, uri: [*c]const u8) callconv(.C) i32 {
19+
export fn gossamer_load_panel(handle: WindowHandle, uri: [*c]const u8) i32 {
2020
if (handle == 0 or uri == null) return -1;
2121
return 0;
2222
}
2323

2424
/// Evaluate JavaScript in a window context. Returns 0 on success.
25-
export fn gossamer_eval_js(handle: WindowHandle, script: [*c]const u8) callconv(.C) i32 {
25+
export fn gossamer_eval_js(handle: WindowHandle, script: [*c]const u8) i32 {
2626
if (handle == 0 or script == null) return -1;
2727
return 0;
2828
}
2929

3030
/// Get runtime version. Returns packed major.minor.patch.
31-
export fn gossamer_get_version() callconv(.C) u32 {
31+
export fn gossamer_get_version() u32 {
3232
return (0 << 16) | (1 << 8) | 0; // 0.1.0
3333
}
3434

cartridges/hypatia-mcp/ffi/hypatia_ffi.zig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,25 @@
66
const std = @import("std");
77

88
/// Scan a repository path. Returns scan ID or 0 on failure.
9-
export fn hypatia_scan_repo(path: [*c]const u8) callconv(.C) u32 {
9+
export fn hypatia_scan_repo(path: [*c]const u8) u32 {
1010
if (path == null) return 0;
1111
return 1; // Stub
1212
}
1313

1414
/// Begin model training. Returns 0 on success.
15-
export fn hypatia_train_model(model_name: [*c]const u8) callconv(.C) i32 {
15+
export fn hypatia_train_model(model_name: [*c]const u8) i32 {
1616
if (model_name == null) return -1;
1717
return 0; // Stub
1818
}
1919

2020
/// Get the score for a completed scan (0-100).
21-
export fn hypatia_get_score(scan_id: u32) callconv(.C) u8 {
21+
export fn hypatia_get_score(scan_id: u32) u8 {
2222
if (scan_id == 0) return 0;
2323
return 85; // Stub
2424
}
2525

2626
/// Get active rule count.
27-
export fn hypatia_get_rule_count() callconv(.C) u32 {
27+
export fn hypatia_get_rule_count() u32 {
2828
return 17; // Stub — matches standard workflow set
2929
}
3030

0 commit comments

Comments
 (0)