Something went wrong. Try again.
small gleam coding and persistent agent daemon with a detachable cli and a canvas ui forked from okami.mom/albedo
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322//// Encoder-level checks for foreign replay and omitted Copilot fields.//// Foreign replay items are internal typed values; these assertions also//// distinguish omitted fields from fields the permissive fake server accepts.
import albedo/harness/extensions/github_copilot/modelsimport albedo/harness/extensions/github_copilot/wireimport albedo/openai_api as openaiimport albedo/openai_api/request as openai_requestimport albedo/openai_api/typesimport gleam/dynamic/decodeimport gleam/jsonimport gleam/listimport gleam/option.{type Option, Some}import gleam/resultimport gleam/string_treeimport gleeunit/should
const endpoint = "https://api.githubcopilot.com"
/// The account client the extension builds, without a sign-in: the wire never/// resolves a credential itself, so a fixed key is all it takes.fn client() -> types.Client { let base = openai.client(types.ChatCompletions, endpoint, "test-token") types.Client(..base, policy: types.GitHubCopilot)}
fn encode( route: models.Route, request: types.Request,) -> Result(openai.Exchange, types.Error) { wire.encode(client(), route, request)}
fn body(exchange: openai.Exchange) -> String { string_tree.to_string(exchange.body)}
fn read( encoded: String, decoder: decode.Decoder(a),) -> Result(a, json.DecodeError) { json.parse(encoded, decoder)}
/// Whether `path` is missing from `encoded` altogether, which is what Copilot/// needs of a field it does not document.fn absent(encoded: String, path: List(String)) -> Bool { read(encoded, decode.at(path, decode.dynamic)) |> result.is_error}
/// The `strict` key of every tool schema, refused by Copilot, so a body that/// carries one for any tool does not decode.fn tool_strict(encoded: String) -> Result(List(Bool), json.DecodeError) { read( encoded, decode.at( ["tools"], decode.list(decode.at(["function", "strict"], decode.bool)), ), )}
fn header(exchange: openai.Exchange, name: String) -> Option(String) { exchange.headers |> list.find(fn(pair) { pair.0 == name }) |> result.map(fn(pair) { pair.1 }) |> option.from_result}
fn chat_item(raw: String) -> types.ReplayItem { let assert Ok(item) = json.parse(raw, types.replay_decoder(types.ChatCompletions)) item}
fn responses_item(raw: String) -> types.ReplayItem { let assert Ok(item) = json.parse(raw, types.replay_decoder(types.Responses)) item}
fn picture() -> types.Image { let assert Ok(image) = types.image("image/png", "aGVsbG8=", 2, 3, 5) image}
/// One message of an encoded Chat Completions body, with the two foreign/// reasoning fields reported as presence: Copilot must see neither.type WireMessage { WireMessage( role: String, content: String, tool_call_id: String, calls: List(types.ToolCall), reasoning_content: Bool, reasoning_details: Bool, )}
fn wire_message() -> decode.Decoder(WireMessage) { use role <- decode.field("role", decode.string) // A turn that was only a tool call carries `null` content. use content <- decode.optional_field( "content", "", decode.map(decode.optional(decode.string), option.unwrap(_, "")), ) use tool_call_id <- decode.optional_field("tool_call_id", "", decode.string) use calls <- decode.optional_field("tool_calls", [], decode.list(chat_call())) use reasoning_content <- decode.optional_field( "reasoning_content", False, decode.map(decode.dynamic, fn(_) { True }), ) use reasoning_details <- decode.optional_field( "reasoning_details", False, decode.map(decode.dynamic, fn(_) { True }), ) decode.success(WireMessage( role, content, tool_call_id, calls, reasoning_content, reasoning_details, ))}
fn chat_call() -> decode.Decoder(types.ToolCall) { use id <- decode.field("id", decode.string) use name <- decode.subfield(["function", "name"], decode.string) use arguments <- decode.subfield(["function", "arguments"], decode.string) decode.success(types.ToolCall(id, name, arguments))}
fn messages(encoded: String) -> Result(List(WireMessage), json.DecodeError) { read(encoded, decode.at(["messages"], decode.list(wire_message())))}
pub fn chat_replay_drops_foreign_reasoning_and_keeps_text_and_calls_test() -> Nil { let assistant = chat_item( "{\"role\":\"assistant\",\"content\":\"reading\",\"reasoning_content\":\"hm\"," <> "\"reasoning_details\":[{\"type\":\"text\",\"text\":\"hm\"}]," <> "\"tool_calls\":[{\"id\":\"call_1\",\"type\":\"function\"," <> "\"function\":{\"name\":\"read\",\"arguments\":\"{\\\"path\\\":\\\"a\\\"}\"}}," <> "{\"id\":\"call_2\",\"type\":\"function\"," <> "\"function\":{\"name\":\"write\",\"arguments\":\"{}\"}}]}", ) let request = openai.request("gpt-5.1", [ types.User("go"), types.Replay(assistant), types.ToolOutput("call_1", "file text", []), types.ToolOutput("call_2", "written", []), ]) let assert Ok(exchange) = encode(models.ChatRoute, request) let assert Ok([ask, reply, first, second]) = messages(body(exchange)) should.equal(ask.role, "user") should.equal(reply.role, "assistant") should.equal(reply.content, "reading") should.equal(reply.calls, [ types.ToolCall("call_1", "read", "{\"path\":\"a\"}"), types.ToolCall("call_2", "write", "{}"), ]) should.be_false(reply.reasoning_content) should.be_false(reply.reasoning_details) should.equal(#(first.role, first.tool_call_id, first.content), #( "tool", "call_1", "file text", )) should.equal(#(second.role, second.tool_call_id, second.content), #( "tool", "call_2", "written", )) // A refused turn's words are the only text it has; dropping them would send // an empty assistant message where the model refused to answer. let refused = chat_item( "{\"role\":\"assistant\",\"content\":\"\",\"refusal\":\"not doing that\"}", ) let assert Ok(refused_exchange) = encode( models.ChatRoute, openai.request("gpt-5.1", [types.User("go"), types.Replay(refused)]), ) let assert Ok([_, refusal]) = messages(body(refused_exchange)) should.equal(refusal.content, "not doing that")}
pub fn native_responses_replay_is_refused_on_every_route_test() -> Nil { let native = responses_item( "{\"type\":\"reasoning\",\"id\":\"rs_1\",\"encrypted_content\":\"opaque\"}", ) let request = openai.request("gpt-5.1", [types.User("hi"), types.Replay(native)]) let assert Error(types.InvalidRequest(_)) = encode(models.ChatRoute, request) let assert Error(types.InvalidRequest(_)) = encode(models.ResponsesRoute, request) let assert Error(types.InvalidRequest(_)) = encode(models.MessagesRoute, request) // The same history as portable chat replay is what every route takes instead. let portable = chat_item( "{\"role\":\"assistant\",\"content\":\"hi\"," <> "\"tool_calls\":[{\"id\":\"c\",\"type\":\"function\"," <> "\"function\":{\"name\":\"read\",\"arguments\":\"{}\"}}]}", ) let portable_request = openai.request("gpt-5.1", [types.User("hi"), types.Replay(portable)]) let assert Ok(_) = encode(models.ChatRoute, portable_request) let assert Ok(_) = encode(models.ResponsesRoute, portable_request) let assert Ok(_) = encode(models.MessagesRoute, portable_request) Nil}
pub fn chat_body_keeps_copilot_field_names_and_omits_strict_test() -> Nil { let request = types.Request( ..openai.request("gpt-5.1", [types.User("hi")]), tools: [types.Tool("read", "read a file", json.object([]), True)], max_output_tokens: Some(128), options: types.Options( ..types.defaults, effort: Some("high"), service_tier: Some("priority"), ), ) let assert Ok(exchange) = encode(models.ChatRoute, request) let encoded = body(exchange) // Copilot limits and bills on `max_tokens`; `max_completion_tokens` is not a // field it documents. should.equal(read(encoded, decode.at(["max_tokens"], decode.int)), Ok(128)) should.be_true(absent(encoded, ["max_completion_tokens"])) // A sampling control and a tier it does not document stay off the body // rather than travelling empty. should.be_true(absent(encoded, ["reasoning_effort"])) should.be_true(absent(encoded, ["service_tier"])) // Copilot rejects the `strict` key outright, so it is missing, not false. should.be_true(result.is_error(tool_strict(encoded))) // The shared OpenAI policy carries both: the policy above is what removes // them, not the shape of this request. let assert Ok(plain) = openai_request.encode_with_policy( types.ChatCompletions, types.OpenAI, request, ) let plain = string_tree.to_string(plain) should.equal(tool_strict(plain), Ok([True])) should.equal( read(plain, decode.at(["service_tier"], decode.string)), Ok("priority"), ) should.equal( read(plain, decode.at(["reasoning_effort"], decode.string)), Ok("high"), )}
pub fn initiator_headers_follow_the_last_input_and_vision_follows_images_test() -> Nil { let assert Ok(person) = encode(models.ChatRoute, openai.request("gpt-5.1", [types.User("hi")])) should.equal(header(person, "x-initiator"), Some("user")) should.equal(header(person, "x-interaction-type"), Some("conversation-user")) should.be_none(header(person, "copilot-vision-request")) // A tool result is the agent's follow-up, not the person's turn. let assert Ok(agent) = encode( models.ChatRoute, openai.request("gpt-5.1", [ types.User("hi"), types.ToolOutput("call_1", "out", []), ]), ) should.equal(header(agent, "x-initiator"), Some("agent")) should.equal(header(agent, "x-interaction-type"), Some("conversation-agent")) should.be_none(header(agent, "copilot-vision-request")) // An image anywhere in the request asks for the vision channel, and the // person who attached it is still the initiator. let assert Ok(vision) = encode( models.ChatRoute, openai.request("gpt-5.1", [types.UserImage("look", [picture()])]), ) should.equal(header(vision, "x-initiator"), Some("user")) should.equal(header(vision, "copilot-vision-request"), Some("true")) let assert Ok(tool_image) = encode( models.ChatRoute, openai.request("gpt-5.1", [ types.User("hi"), types.ToolOutput("call_1", "", [picture()]), ]), ) should.equal(header(tool_image, "x-initiator"), Some("agent")) should.equal(header(tool_image, "copilot-vision-request"), Some("true"))}
pub fn routes_are_copilot_endpoints_and_the_account_key_is_the_only_credential_test() -> Nil { let request = openai.request("gpt-5.1", [types.User("hi")]) let assert Ok(chat) = encode(models.ChatRoute, request) should.equal(chat.url, endpoint <> "/chat/completions") should.be_none(header(chat, "anthropic-version")) let assert Ok(responses) = encode(models.ResponsesRoute, request) should.equal(responses.url, endpoint <> "/responses") should.be_none(header(responses, "anthropic-version")) let assert Ok(messages) = encode(models.MessagesRoute, request) should.equal(messages.url, endpoint <> "/v1/messages") should.equal(header(messages, "anthropic-version"), Some("2023-06-01")) // The wire sends the account's own key once and invents no other credential; // resolving it belongs to the extension, not the encoder. should.equal( list.filter(chat.headers, fn(pair) { pair.0 == "authorization" }), [#("authorization", "Bearer test-token")], ) should.equal(header(chat, "x-initiator"), Some("user"))}