Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ jobs:
- name: Publish drift guard — self-test
run: node --test scripts/check-publish-drift.test.mjs

# A package naming @codespar/sdk in BOTH dependencies and
# peerDependencies must name the same range in each. @codespar/mcp
# names both, and 0.5.6 shipped with them disagreeing — a release step
# widened one and left the other, which is what happens to a fact
# written down twice. Hermetic, and it carries its own control.
- name: SDK range agreement
run: node --test scripts/check-sdk-range-agreement.test.mjs

# core#129: @codespar/types carried 15 meta-tool definitions in main
# while the published 0.10.15 tarball carried 3, for two months, with
# CI green throughout. npm versions are immutable, so that number can
Expand Down
64 changes: 32 additions & 32 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions packages/autogen/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@codespar/autogen",
"version": "0.4.4",
"version": "0.4.5",
"description": "Microsoft AutoGen adapter for CodeSpar — convert session tools to AutoGen function tool format",
"type": "module",
"main": "./dist/index.js",
Expand Down Expand Up @@ -38,7 +38,7 @@
"directory": "packages/autogen"
},
"peerDependencies": {
"@codespar/sdk": "^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^0.14.0"
"@codespar/sdk": "^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^0.14.0 || ^0.15.0"
},
"devDependencies": {
"@codespar/sdk": "*",
Expand Down
4 changes: 2 additions & 2 deletions packages/camel/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@codespar/camel",
"version": "0.4.4",
"version": "0.4.5",
"description": "CAMEL-AI adapter for CodeSpar — convert session tools to CAMEL function format",
"type": "module",
"main": "./dist/index.js",
Expand Down Expand Up @@ -38,7 +38,7 @@
"directory": "packages/camel"
},
"peerDependencies": {
"@codespar/sdk": "^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^0.14.0"
"@codespar/sdk": "^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^0.14.0 || ^0.15.0"
},
"devDependencies": {
"@codespar/sdk": "*",
Expand Down
4 changes: 2 additions & 2 deletions packages/claude/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@codespar/claude",
"version": "0.4.4",
"version": "0.4.5",
"description": "Claude Agent SDK adapter for CodeSpar — convert MCP tools to Claude tool format",
"type": "module",
"main": "./dist/index.js",
Expand Down Expand Up @@ -37,7 +37,7 @@
"directory": "packages/claude"
},
"peerDependencies": {
"@codespar/sdk": "^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^0.14.0"
"@codespar/sdk": "^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^0.14.0 || ^0.15.0"
},
"devDependencies": {
"@codespar/sdk": "*",
Expand Down
11 changes: 11 additions & 0 deletions packages/cli/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# @codespar/cli — changelog

## 0.10.0 — 2026-09-14

### Changed

- `--arg` accepts either form of a property that publishes a union of
shapes. `codespar pay --arg recipient=pix@example.com` sends the Pix
key as text and `--arg recipient={"bank":...}` sends the bank-account
object, from the same flag (codespar-core#128). A key that is all
digits stays text: the parse is taken only when it lands on a
structured branch, so a CPF does not become a number.

## 0.9.0 — 2026-09-14

### Added
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@codespar/cli",
"version": "0.9.0",
"version": "0.10.0",
"description": "CodeSpar CLI. The agentic OS for money movement in Latin America, from your terminal: authenticate, browse servers, mint mandates, execute tools, manage sessions, stream logs.",
"type": "module",
"bin": {
Expand Down Expand Up @@ -46,7 +46,7 @@
"node": ">=20"
},
"dependencies": {
"@codespar/sdk": "^0.12.0 || ^0.13.0 || ^0.14.0",
"@codespar/sdk": "^0.12.0 || ^0.13.0 || ^0.14.0 || ^0.15.0",
"commander": "^13.0.0"
},
"devDependencies": {
Expand Down
48 changes: 48 additions & 0 deletions packages/cli/src/__tests__/meta-tool-args.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,51 @@ describe("required input", () => {
}
});
});

describe("a property that publishes a union of shapes (core#128)", () => {
// `codespar_pay.recipient` takes either a Pix key string or a bank-account
// object. It used to be published as `type: "string"` with a description
// telling the caller to pass an object, so a client that enforced the schema
// rejected the correct call. The union is now in the schema, and the CLI has
// to accept both forms through the same flag.
const recipient = pay.input_schema.properties.recipient!;

it("is published as a union and not as one type", () => {
expect(recipient.type).toBeUndefined();
expect(recipient.anyOf?.map((b) => b.type).sort()).toEqual(["object", "string"]);
});

it("keeps a Pix key as the string it is", () => {
// A CPF key is all digits and must not become a number, and an EVP is not
// JSON. Both stay text.
expect(coerceArg(pay, "recipient", "pix@example.com")).toBe("pix@example.com");
expect(coerceArg(pay, "recipient", "12345678901")).toBe("12345678901");
expect(coerceArg(pay, "recipient", "b5b8e0f4-0000-4000-8000-000000000000")).toBe(
"b5b8e0f4-0000-4000-8000-000000000000",
);
});

it("parses the bank-account object the other branch declares", () => {
const account = {
bank: "60701190",
account: "12345678",
branch: "0001",
tax_id: "12345678901",
name: "Fulana de Tal",
account_type: "CACC",
};
expect(coerceArg(pay, "recipient", JSON.stringify(account))).toEqual(account);
});

it("builds the whole call with either form", () => {
const viaKey = buildArgs(pay, undefined, ["recipient=pix@example.com"], "pay");
expect(viaKey.recipient).toBe("pix@example.com");
const viaAccount = buildArgs(
pay,
undefined,
['recipient={"bank":"60701190","account":"12345678","branch":"0001"}'],
"pay",
);
expect(viaAccount.recipient).toMatchObject({ bank: "60701190" });
});
});
Loading
Loading