diff --git a/COMMERCIAL-USE.md b/COMMERCIAL-USE.md deleted file mode 100644 index e4f7e10..0000000 --- a/COMMERCIAL-USE.md +++ /dev/null @@ -1,26 +0,0 @@ -# Commercial Use - -SwiftASB is publicly available under the PolyForm Noncommercial License 1.0.0. - -Commercial use is not licensed by the public license. If you want to use -SwiftASB, its documentation, examples, generated wire models, maintainer tools, -AgentSB, UI component targets, package artifacts, or derived works for -business, employer, client, product, model-training, paid-service, or -revenue-generating work, contact Gale W at . - -Commercial terms are handled by separate written agreement. - -SwiftASB versions published before the PolyForm Noncommercial change remain -available under the license terms that applied to those versions. The -historical Apache License 2.0 text is preserved in -[LICENSE-HISTORICAL-APACHE-2.0](./LICENSE-HISTORICAL-APACHE-2.0). - -## Required Notice - -PolyForm Noncommercial requires copies to include the license terms or URL and -any plain-text `Required Notice:` lines provided with the software. SwiftASB's -required notice is: - -```text -Required Notice: Copyright 2026 Gale Williams (mailto:mail@galewilliams.com) -``` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 67fb480..b780934 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -172,8 +172,6 @@ Record settled decisions in `ROADMAP.md`, DocC, maintainer docs, or this guide s ## License and Contribution Terms -Unless a contribution explicitly says otherwise in writing, contributions to SwiftASB are made under the PolyForm Noncommercial License 1.0.0 terms in [LICENSE](./LICENSE). The root legal-notice surface lives in [NOTICE](./NOTICE). +Unless a contribution explicitly says otherwise in writing, contributions to SwiftASB are made under the Apache License 2.0 terms in [LICENSE](./LICENSE). The root legal-notice surface lives in [NOTICE](./NOTICE). -Commercial use is not licensed by the public license. See [COMMERCIAL-USE.md](./COMMERCIAL-USE.md) for the current commercial-use policy and contact path. - -Do not submit contributions unless you have the right to license them under these terms and understand Gale may offer separate commercial licenses for SwiftASB. +Do not submit contributions unless you have the right to license them under these terms. diff --git a/LICENSE b/LICENSE index 0da8bbe..261eeb9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,117 +1,201 @@ -# PolyForm Noncommercial License 1.0.0 - -## Acceptance - -In order to get any license under these terms, you must agree to them as -both strict obligations and conditions to all your licenses. - -## Copyright License - -The licensor grants you a copyright license for the software to do -everything you might do with the software that would otherwise infringe -the licensor's copyright in it for any permitted purpose. However, you -may only distribute the software according to [Distribution License](#distribution-license) -and make changes or new works based on the software according to -[Changes and New Works License](#changes-and-new-works-license). - -## Distribution License - -The licensor grants you an additional copyright license to distribute -copies of the software. Your license to distribute covers distributing -the software with changes and new works permitted by [Changes and New -Works License](#changes-and-new-works-license). - -## Notices - -You must ensure that anyone who gets a copy of any part of the software -from you also gets a copy of these terms or the URL for them above, as -well as copies of any plain-text lines beginning with `Required Notice:` -that the licensor provided with the software. For example: - -> Required Notice: Copyright Yoyodyne, Inc. (http://example.com) - -## Changes and New Works License - -The licensor grants you an additional copyright license to make changes -and new works based on the software for any permitted purpose. - -## Patent License - -The licensor grants you a patent license for the software that covers -patent claims the licensor can license, or becomes able to license, that -you would infringe by using the software. - -## Noncommercial Purposes - -Any noncommercial purpose is a permitted purpose. - -## Personal Uses - -Personal use for research, experiment, and testing for the benefit of -public knowledge, personal study, private entertainment, hobby projects, -amateur pursuits, or religious observance, without any anticipated -commercial application, is use for a permitted purpose. - -## Noncommercial Organizations - -Use by any charitable organization, educational institution, public -research organization, public safety or health organization, -environmental protection organization, or government institution is use -for a permitted purpose regardless of the source of funding or -obligations resulting from the funding. - -## Fair Use - -You may have "fair use" rights for the software under the law. These -terms do not limit them. - -## No Other Rights - -These terms do not allow you to sublicense or transfer any of your -licenses to anyone else, or prevent the licensor from granting licenses -to anyone else. These terms do not imply any other licenses. - -## Patent Defense - -If you make any written claim that the software infringes or contributes -to infringement of any patent, your patent license for the software -granted under these terms ends immediately. If your company makes such a -claim, your patent license ends immediately for work on behalf of your -company. - -## Violations - -The first time you are notified in writing that you have violated any of -these terms, or done anything with the software not covered by your -licenses, your licenses can nonetheless continue if you come into full -compliance with these terms, and take practical steps to correct past -violations, within 32 days of receiving notice. Otherwise, all your -licenses end immediately. - -## No Liability - -As far as the law allows, the software comes as is, without any warranty -or condition, and the licensor will not be liable to you for any damages -arising out of these terms or the use or nature of the software, under -any kind of legal claim. - -## Definitions - -The **licensor** is the individual or entity offering these terms, and -the **software** is the software the licensor makes available under these -terms. - -**You** refers to the individual or entity agreeing to these terms. - -**Your company** is any legal entity, sole proprietorship, or other kind -of organization that you work for, plus all organizations that have -control over, are under the control of, or are under common control with -that organization. **Control** means ownership of substantially all the -assets of an entity, or the power to direct its management and policies -by vote, contract, or otherwise. Control can be direct or indirect. - -**Your licenses** are all the licenses granted to you for the software -under these terms. - -**Use** means anything you do with the software requiring one of your -licenses. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/LICENSE-HISTORICAL-APACHE-2.0 b/LICENSE-HISTORICAL-APACHE-2.0 deleted file mode 100644 index 261eeb9..0000000 --- a/LICENSE-HISTORICAL-APACHE-2.0 +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/NOTICE b/NOTICE index fc59e86..d16ce84 100644 --- a/NOTICE +++ b/NOTICE @@ -3,17 +3,7 @@ Copyright 2026 Gale Williams Required Notice: Copyright 2026 Gale Williams (mailto:mail@galewilliams.com) -This repository is licensed under the PolyForm Noncommercial License 1.0.0. -See [LICENSE](./LICENSE) for the full license text. - -Commercial use is not licensed by the public license. See -[COMMERCIAL-USE.md](./COMMERCIAL-USE.md) for the current commercial-use policy -and contact path. - -SwiftASB versions published before the PolyForm Noncommercial change remain -available under the license terms that applied to those versions. The historical -Apache License 2.0 text is preserved in -[LICENSE-HISTORICAL-APACHE-2.0](./LICENSE-HISTORICAL-APACHE-2.0). +This repository is licensed under the Apache License 2.0. See [LICENSE](./LICENSE) for the full license text. Third-Party Trademarks And Brand References diff --git a/README.md b/README.md index 8f3ed62..0f3dbd2 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Listen to the SwiftASB Codex apps promo clip: ### Status -SwiftASB is actively maintained and supported by Gale. Our current API is v1, and `v1.8.0` is the current and latest release. +SwiftASB is actively maintained and supported by Gale. Our current API is v1, and `v1.8.1` is the current and latest release. ### What This Project Is @@ -38,7 +38,7 @@ I built SwiftASB because I saw so many others building and forking existing Apps Add SwiftASB to your `Package.swift` dependencies: ```swift -.package(url: "https://github.com/gaelic-ghost/SwiftASB", from: "1.8.0"), +.package(url: "https://github.com/gaelic-ghost/SwiftASB", from: "1.8.1"), ``` Then add the library product to your target dependencies: @@ -60,7 +60,7 @@ Check your Codex version: ```bash codex --version ``` -*Note: SwiftASB currently supports the reviewed current Codex CLI minor release, `0.142.x`, and the latest prior minor, `0.141.x`, when that prior runtime remains compatible. This narrow reviewed window will be revised once the app-server schema stabilizes or Codex CLI reaches a v1.x.x release.* +*Note: SwiftASB currently supports the reviewed current Codex CLI minor release, `0.143.x`, and the latest prior minor, `0.142.x`, when that prior runtime remains compatible. This narrow reviewed window will be revised once the app-server schema stabilizes or Codex CLI reaches a v1.x.x release.* Add the Socket Marketplace to Codex and enable the SwiftASB Skills Plugin: @@ -174,8 +174,4 @@ Agent-facing maintainer guidance lives in [AGENTS.md](./AGENTS.md). ## License -SwiftASB is licensed under the PolyForm Noncommercial License 1.0.0 for future public versions. See [LICENSE](./LICENSE), [NOTICE](./NOTICE), and [COMMERCIAL-USE.md](./COMMERCIAL-USE.md). - -Commercial use is not licensed by the public license. See [COMMERCIAL-USE.md](./COMMERCIAL-USE.md) for the current commercial-use policy and contact path. - -SwiftASB versions published before the PolyForm Noncommercial change remain available under the license terms that applied to those versions. The historical Apache License 2.0 text is preserved in [LICENSE-HISTORICAL-APACHE-2.0](./LICENSE-HISTORICAL-APACHE-2.0). +SwiftASB is licensed under the Apache License 2.0. See [LICENSE](./LICENSE) and [NOTICE](./NOTICE). diff --git a/ROADMAP.md b/ROADMAP.md index 912012a..0a5181b 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -42,7 +42,7 @@ | --- | --- | --- | | Bundled schema-driven wire generation | `Shipped internally` | `scripts/generate-wire-types.sh` derives from the bundled v2 schema, patches dynamic JSON to `CodexWireJSONValue`, and validates the staged Swift output. | | Promoted generated v2 wire snapshot | `Shipped internally` | `Sources/SwiftASB/Generated/CodexWire/Latest/` now contains a wider lifecycle batch covering bootstrap, stored and loaded thread reads, filesystem reads and watches, config reads, extension inventory, remote-control status plus pairing/client-management wire families, thread goals, and many thread, turn, item, reasoning, and tool-progress notifications, alongside the hand-owned `CodexWireInitializeResponse` shim. | -| Codex CLI schema review | `Shipped / ongoing` | The current reviewed compatibility window is `codex-cli 0.142.x plus 0.141.x when feasible`; the staged `v0.142.4` refresh promoted the generated v2 lifecycle batch internally, added generated `Sendable` coverage, exposed the new `sleep` turn-item kind, kept deprecated multi-agent mode fields internal for compatibility, typed external-agent config import completion internally, and preserved the repeatable dump and generation path through `scripts/dump-codex-schemas.sh` and `scripts/generate-wire-types.sh`. | +| Codex CLI schema review | `Shipped / ongoing` | The current reviewed compatibility window is `codex-cli 0.143.x plus 0.142.x when feasible`; the staged `v0.143.0` refresh promoted the generated v2 lifecycle batch internally, renamed the stored item paging route to `thread/items/list`, kept new thread-start fallback/history fields internal, preserved source compatibility for SwiftASB's older `.onFailure` approval policy while the upstream wire enum now encodes it as `on-request`, added internal npm plugin-source metadata, and preserved the repeatable dump and generation path through `scripts/dump-codex-schemas.sh` and `scripts/generate-wire-types.sh`. | | Stdio subprocess transport | `Shipped internally` | The transport launches `codex app-server --listen stdio://`, frames newline-delimited JSON, correlates request IDs, and captures stderr for diagnostics. | | Raw server-event fanout | `Shipped internally` | Transport can stream raw JSON-RPC notifications and server requests to higher layers. | | Typed protocol request encoding | `Shipped internally` | `initialize`, `initialized`, core thread and turn methods, archive-state actions, filesystem reads and watches, config reads, app/skill/plugin/collaboration-mode inventory, model/MCP/hook reads, MCP resource reads, and thread-goal methods are encoded through the protocol layer. | @@ -88,12 +88,12 @@ | Internal thread history persistence | `Partially shipped` | The package now has a Core Data-backed `ThreadHistoryStore` that persists live-built thread and turn history, hydrates stored turns from `thread/read`, `thread/resume`, `thread/fork`, and `thread/turns/list`, seeds previously unknown local threads from paged history, widens persisted turn identity to stay thread-scoped across forks, and records explicit fork lineage while preserving conservative reconciliation that keeps richer local detail when upstream stored history is thinner. Public history paging/search helpers and archive-retention policy are still open. | | Direct local Codex thread storage | `Planned / prototyped` | SwiftASB now has a maintainer plan for an opt-in, read-only local Codex storage reader that can inventory threads through Codex's SQLite metadata and lazily hydrate JSONL evidence without forcing every caller through the app-server JSONL pipe. AgentSB prototypes the inspection shape for reports only; the package API, version gates, privacy defaults, and fallback behavior remain separate SwiftASB design work. See [`docs/maintainers/codex-direct-thread-storage-plan.md`](docs/maintainers/codex-direct-thread-storage-plan.md). | | Convenience run API | `Not started` | No `run(...)` or one-shot text convenience layer yet. | -| Binary discovery and compatibility policy | `Partially shipped` | Explicit binary override exists, the docs now define a current-reviewed Codex CLI support window of `0.142.x plus 0.141.x when feasible`, transport startup checks PATH, common Homebrew paths, and the npm global prefix on macOS, and `cliExecutableDiagnostics()` now exposes the resolved binary, version string, and documented support-window assessment. Any further diagnostics work is now expansion rather than a missing baseline surface. | +| Binary discovery and compatibility policy | `Partially shipped` | Explicit binary override exists, the docs now define a current-reviewed Codex CLI support window of `0.143.x plus 0.142.x when feasible`, transport startup checks PATH, common Homebrew paths, and the npm global prefix on macOS, and `cliExecutableDiagnostics()` now exposes the resolved binary, version string, and documented support-window assessment. Any further diagnostics work is now expansion rather than a missing baseline surface. | | README-level consumer docs | `Shipped / ongoing` | The README covers installation, runtime assumptions, first-use examples, the supported lifecycle, SwiftUI companion surfaces, and the current Codex CLI compatibility window. Future README work should track new public API additions rather than prerelease readiness. | | AgentSB maintainer automation | `Report-first maintainer app` | `Tools/AgentSB/` is a repo-local Python maintainer app that inspects SwiftASB deterministically, writes tracked reports under `docs/agents/reports/`, evaluates safety-boundary cases, diffs schema dumps, writes reviewable maintenance drafts, and prototypes local Codex thread-index inspection for future SwiftASB planning. The v1 boundary stays report-first: safe auto-apply is classifier-gated and limited to AgentSB-owned report artifacts, and it must not mutate Swift source, generated wire snapshots, public API, releases, or behavior-changing docs. | | Agent workflow guidance | `Shipped / ongoing` | SwiftASB-specific Codex guidance now ships through `socket`'s [`swiftasb-skills`](https://github.com/gaelic-ghost/socket/tree/main/plugins/swiftasb-skills) plugin, with skills for explaining SwiftASB, choosing an integration shape, building SwiftUI-facing app state, and diagnosing integration failures. This repo now points package users and maintainers at that plugin while keeping SwiftASB source, DocC, tests, generated-wire review, and release notes here as the package source of truth. | | End-to-end subprocess integration tests | `Shipped / ongoing` | The package includes opt-in live Codex CLI integration tests with temp workspaces and time limits, including raw transport startup, single-turn completion, cross-thread completion, app-wide model/MCP/hook diagnostics snapshots, thread-name mutation, stored-history materialization, same-thread concurrency probing, deterministic command and permissions approvals through a mock Responses provider, a best-effort prompt-driven approval-path probe, a disposable live rollback scenario, and a multi-turn file-mutation scenario that creates, edits, and deletes files through the real CLI. The umbrella runner is `scripts/run-live-codex-integration-tests.sh`; it defaults to the release-gate set and exposes focused modes for smoke, transport, capability, thread, turn, approval, file-scenario, rollback, same-thread, and all opt-in live tests. Stored-history materialization remains in focused `thread`/`all` runs instead of the release-gate smoke group because the live app-server can delay history materialization. | -| PolyForm Noncommercial licensing | `Shipped` | Future public versions now use the PolyForm Noncommercial License 1.0.0 with a separate commercial-use policy. The historical Apache License 2.0 text is preserved for versions published before the license change. | +| Apache 2.0 licensing | `Shipped` | Current public versions use the Apache License 2.0 through the root `LICENSE` and `NOTICE` files. | ## Milestone Progress @@ -112,19 +112,19 @@ lifecycle, SPI visibility, basic history hydration, first-pass reconciliation, or command-approval completion. Those slices now exist and shipped in the `v1.7.1` baseline. -The next meaningful work after the `v1.8.0` patch release is to probe and deliberately shape the newly promoted -Codex CLI `0.142.x` wire families before widening public API further. The -`v0.142.4` promotion refreshes the internal wire snapshot, widens the public -turn-item kind enum for the new `sleep` item type, keeps the `subAgentActivity` -public turn-item kind from the prior refresh, and carries new multi-agent mode -compatibility, typed external-agent config import completion, and broader -internal `Sendable` generated-wire coverage without adding new public request -or action surfaces. Capability roots, plugin sharing metadata, remote-control -pairing/client management and pairing status, account token usage, turn -moderation metadata, plugin app templates, richer turn-start context, runtime -workspace roots, environments, structured output schemas, and rollout-path -forking still need live behavior evidence before SwiftASB turns them into -stable Swift surfaces. +The next meaningful work after the `v1.8.1` patch release is to probe and deliberately shape the newly promoted +Codex CLI `0.143.x` wire families before widening public API further. The +`v0.143.0` promotion refreshes the internal wire snapshot, moves the stored +item paging wire route from `thread/turns/items/list` to `thread/items/list`, +adds internal npm plugin-source metadata, removes the upstream `on-failure` +approval-policy enum case, and adds internal thread-start fallback/history +fields without adding new public request or action surfaces. Capability roots, +plugin sharing metadata, remote-control pairing/client management and pairing +status, account token usage, turn moderation metadata, plugin app templates, +richer turn-start context, runtime workspace roots, environments, structured +output schemas, rollout-path forking, thread settings, injected items, realtime +routes, and background-terminal routes still need live behavior evidence before +SwiftASB turns them into stable Swift surfaces. Descriptors should compile against Codex-owned workspace, Git, file, and thread facts wherever possible, rather than making SwiftASB or a sandboxed client infer repository identity by @@ -738,7 +738,7 @@ workflow earns them in a later feature release. boundary, keep plugin-sharing and guardian-review timing additions internal, preserve `skills/list` source compatibility while rejecting the removed per-cwd extra user roots option with a descriptive error, expose the new - `thread/turns/items/list` page as a hand-owned low-level stored item API, let + `thread/items/list` page as a hand-owned low-level stored item API, let `thread/turns/list` request an explicit item-detail view through `CodexAppServer.TurnItemsView`, and promote plugin detail hook summaries as read-only extension inventory. @@ -786,7 +786,7 @@ workflow earns them in a later feature release. - [x] Decide whether v1 should support only the latest documented rolling window or whether a shorter first-v1 compatibility promise is more honest. Decision: use a narrow current-plus-latest-prior support window where - feasible, currently `0.142.x plus 0.141.x when feasible`, and widen + feasible, currently `0.143.x plus 0.142.x when feasible`, and widen deliberately after generated-wire and public API review catches up with later Codex CLI releases. @@ -907,7 +907,7 @@ workflow earns them in a later feature release. #### Migration Notes - Existing `v0.9.x` consumers should update the SwiftPM dependency to - `from: "1.8.0"` once the tag is published. + `from: "1.8.1"` once the tag is published. - The v1 API surface has removed stale pre-v1 compatibility shims and phantom fields that no longer exist in the reviewed `v0.128.0` schema. - Same-thread overlapping turns are rejected client-side with @@ -932,7 +932,7 @@ workflow earns them in a later feature release. - Keep an eye on future Swift Package Index builds after compatibility-window or DocC changes; the `v1.1.1` listing and documentation link are live, and - `v1.8.0` should be rechecked after the patch tag is indexed. + `v1.8.1` should be rechecked after the patch tag is indexed. - Add broader live server-request coverage for permissions and MCP elicitation if those become stronger public runtime guarantees. - Continue tuning recent companion cache calibration, richer file previews, @@ -1273,7 +1273,7 @@ not as the current maintainer priority. optional thread target on `mcpServer/startupStatus/updated` into the internal wire snapshot, and kept that field out of public diagnostics until SwiftASB defines a stronger thread-scoped MCP status model. -- A `v0.142.4` experimental schema compatibility pass refreshed the staging +- A `v0.143.0` experimental schema compatibility pass refreshed the staging generator again, updated the Codex CLI compatibility window, promoted broader generated `Sendable` coverage, exposed the new `sleep` turn-item kind, kept deprecated multi-agent mode fields internal for compatibility, and typed @@ -1579,10 +1579,9 @@ Completed Decision: completed on 2026-05-06 for `v1.1.1`. - [x] Decide whether real subprocess integration tests are required before the first release. Decision: yes, but as opt-in suites rather than as part of the default `swift test` path while the live Codex runtime remains an external local dependency. -- [x] Add an explicit source-available license for the package. - Decision: future public versions now use the PolyForm Noncommercial License - 1.0.0, commercial use is handled by separate written agreement, and the - historical Apache License 2.0 text is preserved for earlier versions. +- [x] Add an explicit open source license for the package. + Decision: current public versions use the Apache License 2.0 through the + root `LICENSE` and `NOTICE` files. ### Exit Criteria @@ -1711,11 +1710,11 @@ Completed internally, kept the new optional MCP status thread target out of public API, and cleared the full repo-owned live Codex release gate. - 2026-06-09: Published `v1.7.2` with the ASBPresentation foundation, first - ASBAppKit thread sidebar view, Codex CLI `0.138.x` generated-wire refresh, - and PolyForm Noncommercial license transition. + ASBAppKit thread sidebar view, and Codex CLI `0.138.x` generated-wire + refresh. - 2026-06-09: Prepared the `v1.7.2` release branch with the ASBPresentation - foundation, first ASBAppKit thread sidebar view, Codex CLI `0.138.x` - generated-wire refresh, and PolyForm Noncommercial license transition. + foundation, first ASBAppKit thread sidebar view, and Codex CLI `0.138.x` + generated-wire refresh. - 2026-06-06: Used the AgentSB schema-review and auto-apply-safe reports as the basis for the Codex CLI `0.137.x` compatibility refresh, promoted the v0.137.0 generated wire snapshot internally, and kept new remote-control and diff --git a/Sources/SwiftASB/Generated/CodexWire/Latest/CodexLifecycleV2Batch+JSONValue.swift b/Sources/SwiftASB/Generated/CodexWire/Latest/CodexLifecycleV2Batch+JSONValue.swift index 6c807fa..a7c74cd 100644 --- a/Sources/SwiftASB/Generated/CodexWire/Latest/CodexLifecycleV2Batch+JSONValue.swift +++ b/Sources/SwiftASB/Generated/CodexWire/Latest/CodexLifecycleV2Batch+JSONValue.swift @@ -124,6 +124,8 @@ struct CodexWireCodexLifecycleV2Batch: Codable, Equatable, Sendable { let threadGoalSetParams: CodexWireThreadGoalSetParams? let threadGoalSetResponse: CodexWireThreadGoalSetResponse? let threadGoalUpdatedNotification: CodexWireThreadGoalUpdatedNotification? + let threadItemsListParams: CodexWireThreadItemsListParams? + let threadItemsListResponse: CodexWireThreadItemsListResponse? let threadLoadedListParams: CodexWireThreadLoadedListParams? let threadLoadedListResponse: CodexWireThreadLoadedListResponse? let threadMetadataUpdateParams: CodexWireThreadMetadataUpdateParams? @@ -142,8 +144,6 @@ struct CodexWireCodexLifecycleV2Batch: Codable, Equatable, Sendable { let threadStartResponse: CodexWireThreadStartResponse? let threadStatusChangedNotification: CodexWireThreadStatusChangedNotification? let threadTokenUsageUpdatedNotification: CodexWireThreadTokenUsageUpdatedNotification? - let threadTurnsItemsListParams: CodexWireThreadTurnsItemsListParams? - let threadTurnsItemsListResponse: CodexWireThreadTurnsItemsListResponse? let threadTurnsListParams: CodexWireThreadTurnsListParams? let threadTurnsListResponse: CodexWireThreadTurnsListResponse? let threadUnarchivedNotification: CodexWireThreadUnarchivedNotification? @@ -163,7 +163,7 @@ struct CodexWireCodexLifecycleV2Batch: Codable, Equatable, Sendable { case agentMessageDeltaNotification, appListUpdatedNotification, appsListParams, appsListResponse, collaborationModeListParams, collaborationModeListResponse, commandExecOutputDeltaNotification, commandExecutionOutputDeltaNotification, configReadParams, configReadResponse, configRequirementsReadResponse, configWarningNotification, contextCompactedNotification, deprecationNoticeNotification, errorNotification, externalAgentConfigImportCompletedNotification, fileChangeOutputDeltaNotification, fileChangePatchUpdatedNotification, fsChangedNotification, fsGetMetadataParams, fsGetMetadataResponse, fsReadDirectoryParams, fsReadDirectoryResponse, fsReadFileParams, fsReadFileResponse, fsUnwatchParams, fsUnwatchResponse, fsWatchParams, fsWatchResponse, getAccountTokenUsageResponse, guardianWarningNotification, hookCompletedNotification, hookStartedNotification, initializeParams, itemCompletedNotification, itemGuardianApprovalReviewCompletedNotification, itemGuardianApprovalReviewStartedNotification, itemStartedNotification case listMCPServerStatusParams = "listMcpServerStatusParams" case listMCPServerStatusResponse = "listMcpServerStatusResponse" - case mcpResourceReadParams, mcpResourceReadResponse, mcpServerStatusUpdatedNotification, mcpToolCallProgressNotification, modelListParams, modelListResponse, modelReroutedNotification, modelVerificationNotification, planDeltaNotification, pluginListParams, pluginListResponse, pluginReadParams, pluginReadResponse, pluginShareDeleteParams, pluginShareDeleteResponse, pluginShareListParams, pluginShareListResponse, pluginShareSaveParams, pluginShareSaveResponse, pluginShareUpdateTargetsParams, pluginShareUpdateTargetsResponse, pluginSkillReadParams, pluginSkillReadResponse, processExitedNotification, processKillParams, processKillResponse, processOutputDeltaNotification, processResizePtyParams, processResizePtyResponse, processSpawnParams, processSpawnResponse, processWriteStdinParams, processWriteStdinResponse, rawResponseItemCompletedNotification, reasoningSummaryPartAddedNotification, reasoningSummaryTextDeltaNotification, reasoningTextDeltaNotification, remoteControlClientsListParams, remoteControlClientsListResponse, remoteControlClientsRevokeParams, remoteControlClientsRevokeResponse, remoteControlPairingStartParams, remoteControlPairingStartResponse, remoteControlPairingStatusParams, remoteControlPairingStatusResponse, remoteControlStatusChangedNotification, reviewStartParams, reviewStartResponse, serverRequestResolvedNotification, skillsChangedNotification, skillsExtraRootsSetParams, skillsExtraRootsSetResponse, skillsListParams, skillsListResponse, threadApproveGuardianDeniedActionParams, threadApproveGuardianDeniedActionResponse, threadArchivedNotification, threadArchiveParams, threadArchiveResponse, threadClosedNotification, threadCompactStartParams, threadCompactStartResponse, threadGoalClearedNotification, threadGoalClearParams, threadGoalClearResponse, threadGoalGetParams, threadGoalGetResponse, threadGoalSetParams, threadGoalSetResponse, threadGoalUpdatedNotification, threadLoadedListParams, threadLoadedListResponse, threadMetadataUpdateParams, threadMetadataUpdateResponse, threadNameUpdatedNotification, threadRollbackParams, threadRollbackResponse, threadSearchParams, threadSearchResponse, threadSetNameParams, threadSetNameResponse, threadShellCommandParams, threadShellCommandResponse, threadStartedNotification, threadStartParams, threadStartResponse, threadStatusChangedNotification, threadTokenUsageUpdatedNotification, threadTurnsItemsListParams, threadTurnsItemsListResponse, threadTurnsListParams, threadTurnsListResponse, threadUnarchivedNotification, threadUnarchiveParams, threadUnarchiveResponse, turnCompletedNotification, turnDiffUpdatedNotification, turnModerationMetadataNotification, turnPlanUpdatedNotification, turnStartedNotification, turnStartParams, turnStartResponse, warningNotification, windowsSandboxReadinessResponse + case mcpResourceReadParams, mcpResourceReadResponse, mcpServerStatusUpdatedNotification, mcpToolCallProgressNotification, modelListParams, modelListResponse, modelReroutedNotification, modelVerificationNotification, planDeltaNotification, pluginListParams, pluginListResponse, pluginReadParams, pluginReadResponse, pluginShareDeleteParams, pluginShareDeleteResponse, pluginShareListParams, pluginShareListResponse, pluginShareSaveParams, pluginShareSaveResponse, pluginShareUpdateTargetsParams, pluginShareUpdateTargetsResponse, pluginSkillReadParams, pluginSkillReadResponse, processExitedNotification, processKillParams, processKillResponse, processOutputDeltaNotification, processResizePtyParams, processResizePtyResponse, processSpawnParams, processSpawnResponse, processWriteStdinParams, processWriteStdinResponse, rawResponseItemCompletedNotification, reasoningSummaryPartAddedNotification, reasoningSummaryTextDeltaNotification, reasoningTextDeltaNotification, remoteControlClientsListParams, remoteControlClientsListResponse, remoteControlClientsRevokeParams, remoteControlClientsRevokeResponse, remoteControlPairingStartParams, remoteControlPairingStartResponse, remoteControlPairingStatusParams, remoteControlPairingStatusResponse, remoteControlStatusChangedNotification, reviewStartParams, reviewStartResponse, serverRequestResolvedNotification, skillsChangedNotification, skillsExtraRootsSetParams, skillsExtraRootsSetResponse, skillsListParams, skillsListResponse, threadApproveGuardianDeniedActionParams, threadApproveGuardianDeniedActionResponse, threadArchivedNotification, threadArchiveParams, threadArchiveResponse, threadClosedNotification, threadCompactStartParams, threadCompactStartResponse, threadGoalClearedNotification, threadGoalClearParams, threadGoalClearResponse, threadGoalGetParams, threadGoalGetResponse, threadGoalSetParams, threadGoalSetResponse, threadGoalUpdatedNotification, threadItemsListParams, threadItemsListResponse, threadLoadedListParams, threadLoadedListResponse, threadMetadataUpdateParams, threadMetadataUpdateResponse, threadNameUpdatedNotification, threadRollbackParams, threadRollbackResponse, threadSearchParams, threadSearchResponse, threadSetNameParams, threadSetNameResponse, threadShellCommandParams, threadShellCommandResponse, threadStartedNotification, threadStartParams, threadStartResponse, threadStatusChangedNotification, threadTokenUsageUpdatedNotification, threadTurnsListParams, threadTurnsListResponse, threadUnarchivedNotification, threadUnarchiveParams, threadUnarchiveResponse, turnCompletedNotification, turnDiffUpdatedNotification, turnModerationMetadataNotification, turnPlanUpdatedNotification, turnStartedNotification, turnStartParams, turnStartResponse, warningNotification, windowsSandboxReadinessResponse } } @@ -209,6 +209,7 @@ struct CodexWireAppInfo: Codable, Equatable, Sendable { let appMetadata: CodexWireAppMetadata? let branding: CodexWireAppBranding? let description, distributionChannel: String? + let iconAssets, iconDarkAssets: [String: String]? let id: String let installURL: String? let isAccessible: Bool? @@ -221,7 +222,7 @@ struct CodexWireAppInfo: Codable, Equatable, Sendable { let pluginDisplayNames: [String]? enum CodingKeys: String, CodingKey { - case appMetadata, branding, description, distributionChannel, id + case appMetadata, branding, description, distributionChannel, iconAssets, iconDarkAssets, id case installURL = "installUrl" case isAccessible, isEnabled, labels case logoURL = "logoUrl" @@ -607,7 +608,6 @@ struct CodexWireGranular: Codable, Equatable, Sendable { enum CodexWireApprovalPolicyEnum: String, Codable, Equatable, Sendable { case never = "never" - case onFailure = "on-failure" case onRequest = "on-request" case untrusted = "untrusted" } @@ -921,6 +921,7 @@ struct CodexWireConfigRequirements: Codable, Equatable, Sendable { let enforceResidency: CodexWireResidencyRequirement? let featureRequirements: [String: Bool]? let hooks: CodexWireManagedHooksRequirements? + let models: CodexWireModelsRequirements? let network: CodexWireNetworkRequirements? } @@ -1047,6 +1048,30 @@ enum CodexWireHookHandlerType: String, Codable, Equatable, Sendable { // for types that require the use of CodexWireJSONValue, nor will the implementation of Hashable be // synthesized for types that have collections (such as arrays or dictionaries). +// MARK: - CodexWireModelsRequirements +struct CodexWireModelsRequirements: Codable, Equatable, Sendable { + let newThread: CodexWireNewThreadModelDefaults? +} + +// +// Hashable or Equatable: +// The compiler will not be able to synthesize the implementation of Hashable or Equatable +// for types that require the use of CodexWireJSONValue, nor will the implementation of Hashable be +// synthesized for types that have collections (such as arrays or dictionaries). + +// MARK: - CodexWireNewThreadModelDefaults +struct CodexWireNewThreadModelDefaults: Codable, Equatable, Sendable { + let model: String? + let modelReasoningEffort: String? + let serviceTier: String? +} + +// +// Hashable or Equatable: +// The compiler will not be able to synthesize the implementation of Hashable or Equatable +// for types that require the use of CodexWireJSONValue, nor will the implementation of Hashable be +// synthesized for types that have collections (such as arrays or dictionaries). + // MARK: - CodexWireNetworkRequirements struct CodexWireNetworkRequirements: Codable, Equatable, Sendable { /// Legacy compatibility view derived from `domains`. @@ -1307,6 +1332,7 @@ enum CodexWireCodexErrorInfoEnum: String, Codable, Equatable, Sendable { case other = "other" case sandboxError = "sandboxError" case serverOverloaded = "serverOverloaded" + case sessionBudgetExceeded = "sessionBudgetExceeded" case threadRollbackFailed = "threadRollbackFailed" case unauthorized = "unauthorized" case usageLimitExceeded = "usageLimitExceeded" @@ -2048,13 +2074,16 @@ enum CodexWireCollabAgentStatus: String, Codable, Equatable, Sendable { // MARK: - CodexWireMCPToolCallAppContext struct CodexWireMCPToolCallAppContext: Codable, Equatable, Sendable { + let actionName, appName: String? let connectorID: String - let linkID, resourceURI: String? + let linkID, resourceURI, templateID: String? enum CodingKeys: String, CodingKey { + case actionName, appName case connectorID = "connectorId" case linkID = "linkId" case resourceURI = "resourceUri" + case templateID = "templateId" } } @@ -2863,16 +2892,21 @@ struct CodexWireResourceContent: Codable, Equatable, Sendable { // MARK: - CodexWireMCPServerStatusUpdatedNotification struct CodexWireMCPServerStatusUpdatedNotification: Codable, Equatable, Sendable { let error: String? + let failureReason: CodexWireMCPServerStartupFailureReason? let name: String let status: CodexWireMCPServerStartupState let threadID: String? enum CodingKeys: String, CodingKey { - case error, name, status + case error, failureReason, name, status case threadID = "threadId" } } +enum CodexWireMCPServerStartupFailureReason: String, Codable, Equatable, Sendable { + case reauthenticationRequired = "reauthenticationRequired" +} + enum CodexWireMCPServerStartupState: String, Codable, Equatable, Sendable { case cancelled = "cancelled" case failed = "failed" @@ -3173,6 +3207,7 @@ struct CodexWirePluginSummary: Codable, Equatable, Sendable { let id: String let installed: Bool let installPolicy: CodexWirePluginInstallPolicy + let installPolicySource: CodexWirePluginInstallPolicySource? let interface: CodexWirePluginInterface? let keywords: [String]? /// Version of the locally materialized plugin package when available. @@ -3183,11 +3218,13 @@ struct CodexWirePluginSummary: Codable, Equatable, Sendable { /// Remote sharing context associated with this plugin when available. let shareContext: CodexWirePluginShareContext? let source: CodexWirePluginSource + /// Version advertised by the remote marketplace backend when available. + let version: String? enum CodingKeys: String, CodingKey { - case authPolicy, availability, enabled, id, installed, installPolicy, interface, keywords, localVersion, name + case authPolicy, availability, enabled, id, installed, installPolicy, installPolicySource, interface, keywords, localVersion, name case remotePluginID = "remotePluginId" - case shareContext, source + case shareContext, source, version } } @@ -3212,6 +3249,11 @@ enum CodexWirePluginInstallPolicy: String, Codable, Equatable, Sendable { case notAvailable = "NOT_AVAILABLE" } +enum CodexWirePluginInstallPolicySource: String, Codable, Equatable, Sendable { + case implicitCanonicalApp = "IMPLICIT_CANONICAL_APP" + case workspaceSetting = "WORKSPACE_SETTING" +} + // // Hashable or Equatable: // The compiler will not be able to synthesize the implementation of Hashable or Equatable @@ -3335,12 +3377,17 @@ struct CodexWirePluginSource: Codable, Equatable, Sendable { let path: String? let type: CodexWirePluginSourceType let refName, sha: String? - let url: String? + let url, package: String? + /// Optional HTTPS registry URL. Authentication stays in the user's npm config. + let registry: String? + /// Optional npm version or version range. + let version: String? } enum CodexWirePluginSourceType: String, Codable, Equatable, Sendable { case git = "git" case local = "local" + case npm = "npm" case remote = "remote" } @@ -4352,6 +4399,7 @@ struct CodexWireTurn: Codable, Equatable, Sendable { let durationMS: Int? /// Only populated when the Turn's status is failed. let error: CodexWireTurnError? + /// Identifier for this turn. Codex-generated turn IDs are UUIDv7. let id: String /// Thread items currently included in this turn payload. let items: [CodexWireThreadItem] @@ -4777,6 +4825,48 @@ struct CodexWireThreadGoalUpdatedNotification: Codable, Equatable, Sendable { // for types that require the use of CodexWireJSONValue, nor will the implementation of Hashable be // synthesized for types that have collections (such as arrays or dictionaries). +// MARK: - CodexWireThreadItemsListParams +struct CodexWireThreadItemsListParams: Codable, Equatable, Sendable { + /// Opaque cursor to pass to the next call to continue after the last item. + let cursor: String? + /// Optional item page size. + let limit: Int? + /// Optional item pagination direction; defaults to ascending. + let sortDirection: CodexWireRemoteControlClientsListOrder? + let threadID: String + /// Optional turn id to filter by. When omitted, returns items across the thread. + let turnID: String? + + enum CodingKeys: String, CodingKey { + case cursor, limit, sortDirection + case threadID = "threadId" + case turnID = "turnId" + } +} + +// +// Hashable or Equatable: +// The compiler will not be able to synthesize the implementation of Hashable or Equatable +// for types that require the use of CodexWireJSONValue, nor will the implementation of Hashable be +// synthesized for types that have collections (such as arrays or dictionaries). + +// MARK: - CodexWireThreadItemsListResponse +struct CodexWireThreadItemsListResponse: Codable, Equatable, Sendable { + /// Opaque cursor to pass as `cursor` when reversing `sortDirection`. This is only populated + /// when the page contains at least one item. + let backwardsCursor: String? + let data: [CodexWireThreadItem] + /// Opaque cursor to pass to the next call to continue after the last item. if None, there + /// are no more items to return. + let nextCursor: String? +} + +// +// Hashable or Equatable: +// The compiler will not be able to synthesize the implementation of Hashable or Equatable +// for types that require the use of CodexWireJSONValue, nor will the implementation of Hashable be +// synthesized for types that have collections (such as arrays or dictionaries). + // MARK: - CodexWireThreadLoadedListParams struct CodexWireThreadLoadedListParams: Codable, Equatable, Sendable { /// Opaque pagination cursor returned by a previous call. @@ -4880,10 +4970,15 @@ struct CodexWireThread: Codable, Equatable, Sendable { let cwd: String /// Whether the thread is ephemeral and should not be materialized on disk. let ephemeral: Bool + /// Optional implementation-specific thread data. + let extra: [String: CodexWireJSONValue]? /// Source thread id when this thread was created by forking another thread. let forkedFromID: String? /// Optional Git metadata captured when the thread was created. let gitInfo: CodexWireGitInfo? + /// Persisted thread history contract selected when this thread was created. + let historyMode: CodexWireThreadHistoryMode? + /// Identifier for this thread. Codex-generated thread IDs are UUIDv7. let id: String /// Model provider used for this thread (for example, 'openai'). let modelProvider: String @@ -4913,9 +5008,9 @@ struct CodexWireThread: Codable, Equatable, Sendable { let updatedAt: Int enum CodingKeys: String, CodingKey { - case agentNickname, agentRole, cliVersion, createdAt, cwd, ephemeral + case agentNickname, agentRole, cliVersion, createdAt, cwd, ephemeral, extra case forkedFromID = "forkedFromId" - case gitInfo, id, modelProvider, name + case gitInfo, historyMode, id, modelProvider, name case parentThreadID = "parentThreadId" case path, preview, recencyAt case sessionID = "sessionId" @@ -4940,6 +5035,12 @@ struct CodexWireGitInfo: Codable, Equatable, Sendable { } } +/// Persisted thread history contract selected when this thread was created. +enum CodexWireThreadHistoryMode: String, Codable, Equatable, Sendable { + case legacy = "legacy" + case paginated = "paginated" +} + /// Origin of the thread (CLI, VSCode, codex exec, codex app-server, etc.). enum CodexWireSessionSourceUnion: Codable, Equatable, Sendable { case codexWireSessionSource(CodexWireSessionSource) @@ -5109,6 +5210,7 @@ struct CodexWireThreadNameUpdatedNotification: Codable, Equatable, Sendable { // for types that require the use of CodexWireJSONValue, nor will the implementation of Hashable be // synthesized for types that have collections (such as arrays or dictionaries). +/// DEPRECATED: `thread/rollback` will be removed soon. // MARK: - CodexWireThreadRollbackParams struct CodexWireThreadRollbackParams: Codable, Equatable, Sendable { /// The number of turns to drop from the end of the thread. Must be >= 1. @@ -5260,6 +5362,9 @@ struct CodexWireThreadShellCommandParams: Codable, Equatable, Sendable { // MARK: - CodexWireThreadStartParams struct CodexWireThreadStartParams: Codable, Equatable, Sendable { + /// Allow a provider with an authoritative static model catalog to replace an unavailable + /// requested model with its default. + let allowProviderModelFallback: Bool? let approvalPolicy: CodexWireApprovalPolicyUnion? /// Override where approval requests are routed for review on this thread and subsequent /// turns. @@ -5278,12 +5383,14 @@ struct CodexWireThreadStartParams: Codable, Equatable, Sendable { /// If true, opt into emitting raw Responses API items on the event stream. This is for /// internal use only (e.g. Codex Cloud). let experimentalRawEvents: Bool? + /// Persisted thread history contract to use for this new thread. + let historyMode: CodexWireThreadHistoryMode? /// Test-only experimental field used to validate experimental gating and schema filtering /// behavior in a stable way. let mockExperimentalField: String? let model, modelProvider: String? /// @deprecated Ignored. Use Ultra reasoning effort for proactive multi-agent behavior. - let multiAgentMode: CodexWireMultiAgentMode? + let multiAgentMode: CodexWireMultiAgentModeUnion? /// Named profile id for this thread. Cannot be combined with `sandbox`. let permissions: String? let personality: CodexWirePersonality? @@ -5354,15 +5461,54 @@ struct CodexWireTurnEnvironmentParams: Codable, Equatable, Sendable { } } -/// Controls whether the model receives multi-agent delegation instructions and, when it -/// does, whether it should only spawn sub-agents after an explicit user request or may -/// delegate proactively when doing so would help. `none` leaves the multi-agent tools -/// available without injecting delegation instructions. -/// -/// @deprecated Always `explicitRequestOnly`. Use `reasoningEffort` for Ultra behavior. -enum CodexWireMultiAgentMode: String, Codable, Equatable, Sendable { +enum CodexWireMultiAgentModeUnion: Codable, Equatable, Sendable { + case codexWireCustomMultiAgentMode(CodexWireCustomMultiAgentMode) + case enumeration(CodexWireMultiAgentModeEnum) + case null + + init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + if let x = try? container.decode(CodexWireMultiAgentModeEnum.self) { + self = .enumeration(x) + return + } + if let x = try? container.decode(CodexWireCustomMultiAgentMode.self) { + self = .codexWireCustomMultiAgentMode(x) + return + } + if container.decodeNil() { + self = .null + return + } + throw DecodingError.typeMismatch(CodexWireMultiAgentModeUnion.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for CodexWireMultiAgentModeUnion")) + } + + func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + switch self { + case .codexWireCustomMultiAgentMode(let x): + try container.encode(x) + case .enumeration(let x): + try container.encode(x) + case .null: + try container.encodeNil() + } + } +} + +// +// Hashable or Equatable: +// The compiler will not be able to synthesize the implementation of Hashable or Equatable +// for types that require the use of CodexWireJSONValue, nor will the implementation of Hashable be +// synthesized for types that have collections (such as arrays or dictionaries). + +// MARK: - CodexWireCustomMultiAgentMode +struct CodexWireCustomMultiAgentMode: Codable, Equatable, Sendable { + let custom: String +} + +enum CodexWireMultiAgentModeEnum: String, Codable, Equatable, Sendable { case explicitRequestOnly = "explicitRequestOnly" - case none = "none" case proactive = "proactive" } @@ -5400,7 +5546,9 @@ struct CodexWireSelectedCapabilityRoot: Codable, Equatable, Sendable { /// A path owned by an execution environment. // MARK: - CodexWireCapabilityRootLocation struct CodexWireCapabilityRootLocation: Codable, Equatable, Sendable { - let environmentID, path: String + let environmentID: String + /// Absolute path for the root in the selected environment. + let path: String let type: CodexWireEnvironmentCapabilityRootLocationType enum CodingKeys: String, CodingKey { @@ -5463,6 +5611,38 @@ struct CodexWireActivePermissionProfile: Codable, Equatable, Sendable { let id: String } +/// Controls the effective multi-agent delegation instructions for a turn. `custom` means the +/// configured mode hint defines the policy instead of a built-in policy. +/// +/// @deprecated Always `explicitRequestOnly`. Use `reasoningEffort` for Ultra behavior. +enum CodexWireMultiAgentMode: Codable, Equatable, Sendable { + case codexWireCustomMultiAgentMode(CodexWireCustomMultiAgentMode) + case enumeration(CodexWireMultiAgentModeEnum) + + init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + if let x = try? container.decode(CodexWireMultiAgentModeEnum.self) { + self = .enumeration(x) + return + } + if let x = try? container.decode(CodexWireCustomMultiAgentMode.self) { + self = .codexWireCustomMultiAgentMode(x) + return + } + throw DecodingError.typeMismatch(CodexWireMultiAgentMode.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for CodexWireMultiAgentMode")) + } + + func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + switch self { + case .codexWireCustomMultiAgentMode(let x): + try container.encode(x) + case .enumeration(let x): + try container.encode(x) + } + } +} + // // Hashable or Equatable: // The compiler will not be able to synthesize the implementation of Hashable or Equatable @@ -5597,46 +5777,6 @@ struct CodexWireTokenUsageBreakdown: Codable, Equatable, Sendable { // for types that require the use of CodexWireJSONValue, nor will the implementation of Hashable be // synthesized for types that have collections (such as arrays or dictionaries). -// MARK: - CodexWireThreadTurnsItemsListParams -struct CodexWireThreadTurnsItemsListParams: Codable, Equatable, Sendable { - /// Opaque cursor to pass to the next call to continue after the last item. - let cursor: String? - /// Optional item page size. - let limit: Int? - /// Optional item pagination direction; defaults to ascending. - let sortDirection: CodexWireRemoteControlClientsListOrder? - let threadID, turnID: String - - enum CodingKeys: String, CodingKey { - case cursor, limit, sortDirection - case threadID = "threadId" - case turnID = "turnId" - } -} - -// -// Hashable or Equatable: -// The compiler will not be able to synthesize the implementation of Hashable or Equatable -// for types that require the use of CodexWireJSONValue, nor will the implementation of Hashable be -// synthesized for types that have collections (such as arrays or dictionaries). - -// MARK: - CodexWireThreadTurnsItemsListResponse -struct CodexWireThreadTurnsItemsListResponse: Codable, Equatable, Sendable { - /// Opaque cursor to pass as `cursor` when reversing `sortDirection`. This is only populated - /// when the page contains at least one item. - let backwardsCursor: String? - let data: [CodexWireThreadItem] - /// Opaque cursor to pass to the next call to continue after the last item. if None, there - /// are no more items to return. - let nextCursor: String? -} - -// -// Hashable or Equatable: -// The compiler will not be able to synthesize the implementation of Hashable or Equatable -// for types that require the use of CodexWireJSONValue, nor will the implementation of Hashable be -// synthesized for types that have collections (such as arrays or dictionaries). - // MARK: - CodexWireThreadTurnsListParams struct CodexWireThreadTurnsListParams: Codable, Equatable, Sendable { /// Opaque cursor to pass to the next call to continue after the last turn. @@ -5840,7 +5980,7 @@ struct CodexWireTurnStartParams: Codable, Equatable, Sendable { /// Override the model for this turn and subsequent turns. let model: String? /// @deprecated Ignored. Use `effort: "ultra"` for proactive multi-agent behavior. - let multiAgentMode: CodexWireMultiAgentMode? + let multiAgentMode: CodexWireMultiAgentModeUnion? /// Optional JSON Schema used to constrain the final assistant message for this turn. let outputSchema: CodexWireJSONValue? /// Select a named permissions profile id for this turn and subsequent turns. Cannot be diff --git a/Sources/SwiftASB/Protocol/CodexAppServerProtocol.swift b/Sources/SwiftASB/Protocol/CodexAppServerProtocol.swift index e797f38..e93c526 100644 --- a/Sources/SwiftASB/Protocol/CodexAppServerProtocol.swift +++ b/Sources/SwiftASB/Protocol/CodexAppServerProtocol.swift @@ -15,7 +15,7 @@ struct CodexAppServerProtocol { case threadStart = "thread/start" case threadMetadataUpdate = "thread/metadata/update" case threadTurnsList = "thread/turns/list" - case threadTurnsItemsList = "thread/turns/items/list" + case threadItemsList = "thread/items/list" case threadLoadedList = "thread/loaded/list" case threadUnarchive = "thread/unarchive" case threadGoalGet = "thread/goal/get" @@ -232,11 +232,11 @@ struct CodexAppServerProtocol { func makeThreadTurnsItemsListRequest( id: CodexRPCRequestID, - params: CodexWireThreadTurnsItemsListParams + params: CodexWireThreadItemsListParams ) throws -> Data { try encodeRequest( - JSONRPCRequestEnvelope(id: id, method: .threadTurnsItemsList, params: params), - method: .threadTurnsItemsList + JSONRPCRequestEnvelope(id: id, method: .threadItemsList, params: params), + method: .threadItemsList ) } @@ -758,12 +758,12 @@ struct CodexAppServerProtocol { func decodeThreadTurnsItemsListResponse( _ responsePayload: Data, expectedID: CodexRPCRequestID - ) throws -> CodexWireThreadTurnsItemsListResponse { + ) throws -> CodexWireThreadItemsListResponse { try decodeResponse( responsePayload, expectedID: expectedID, - method: .threadTurnsItemsList, - resultType: CodexWireThreadTurnsItemsListResponse.self + method: .threadItemsList, + resultType: CodexWireThreadItemsListResponse.self ) } diff --git a/Sources/SwiftASB/Public/CodexAppServer+CodexExtensions.swift b/Sources/SwiftASB/Public/CodexAppServer+CodexExtensions.swift index 9c260e2..81c8ed8 100644 --- a/Sources/SwiftASB/Public/CodexAppServer+CodexExtensions.swift +++ b/Sources/SwiftASB/Public/CodexAppServer+CodexExtensions.swift @@ -227,6 +227,7 @@ public struct CodexExtensions: Sendable { public enum SourceKind: String, Sendable, Equatable { case git case local + case npm case remote } @@ -720,6 +721,8 @@ extension CodexExtensions.PluginSummary.SourceKind { self = .git case .local: self = .local + case .npm: + self = .npm case .remote: self = .remote } diff --git a/Sources/SwiftASB/Public/CodexAppServer+WireMapping.swift b/Sources/SwiftASB/Public/CodexAppServer+WireMapping.swift index 81aaa9f..4d74026 100644 --- a/Sources/SwiftASB/Public/CodexAppServer+WireMapping.swift +++ b/Sources/SwiftASB/Public/CodexAppServer+WireMapping.swift @@ -154,6 +154,7 @@ extension CodexAppServer.InitializeRequest { extension CodexAppServer.ThreadStartRequest { var wireValue: CodexWireThreadStartParams { CodexWireThreadStartParams( + allowProviderModelFallback: nil, approvalPolicy: approvalPolicy?.wireValue, approvalsReviewer: approvalsReviewer?.wireValue, baseInstructions: baseInstructions, @@ -164,6 +165,7 @@ extension CodexAppServer.ThreadStartRequest { environments: nil, ephemeral: ephemeral, experimentalRawEvents: nil, + historyMode: nil, mockExperimentalField: nil, model: model, modelProvider: modelProvider, @@ -362,8 +364,6 @@ extension CodexAppServer.ApprovalPolicy { switch wireEnum { case .never: self = .never - case .onFailure: - self = .onFailure case .onRequest: self = .onRequest case .untrusted: @@ -376,7 +376,7 @@ extension CodexAppServer.ApprovalPolicy { case .never: .enumeration(.never) case .onFailure: - .enumeration(.onFailure) + .enumeration(.onRequest) case .onRequest: .enumeration(.onRequest) case .untrusted: diff --git a/Sources/SwiftASB/Public/CodexAppServer.swift b/Sources/SwiftASB/Public/CodexAppServer.swift index ee7897b..e374a88 100644 --- a/Sources/SwiftASB/Public/CodexAppServer.swift +++ b/Sources/SwiftASB/Public/CodexAppServer.swift @@ -1078,7 +1078,7 @@ public actor CodexAppServer { /// does not carry enough information to safely reconcile whole-turn item /// ordering. public func listThreadTurnItems(_ request: ThreadTurnsItemsListRequest) async throws -> ThreadTurnsItemsPage { - try requireInitialized(for: "thread/turns/items/list") + try requireInitialized(for: "thread/items/list") let requestID = CodexRPCRequestID.generated() @@ -1105,7 +1105,7 @@ public actor CodexAppServer { nextCursor: response.nextCursor ) } catch { - throw CodexAppServerError.wrap(error, operation: "thread/turns/items/list") + throw CodexAppServerError.wrap(error, operation: "thread/items/list") } } diff --git a/Sources/SwiftASB/SwiftASB.docc/CodexWorkspace.md b/Sources/SwiftASB/SwiftASB.docc/CodexWorkspace.md index 87654b9..c283321 100644 --- a/Sources/SwiftASB/SwiftASB.docc/CodexWorkspace.md +++ b/Sources/SwiftASB/SwiftASB.docc/CodexWorkspace.md @@ -16,7 +16,7 @@ let thread = try await appServer.startThread( ) ``` -Codex CLI v0.142 accepts the selected profile id for new thread, resumed thread, fork, and turn requests. SwiftASB no longer carries the older request-side bounded permission modification shim because the reviewed app-server schema accepts the profile id string only. +Codex CLI v0.142 and newer reviewed windows accept the selected profile id for new thread, resumed thread, fork, and turn requests. SwiftASB no longer carries the older request-side bounded permission modification shim because the reviewed app-server schema accepts the profile id string only. Use ``SessionSnapshot`` or the workspace values on ``CodexThread`` when a UI needs to show what Codex actually activated for the session: current directory, Git metadata, instruction sources, legacy sandbox policy, and active profile id. diff --git a/Sources/SwiftASB/Transport/CodexCLIExecutableResolver.swift b/Sources/SwiftASB/Transport/CodexCLIExecutableResolver.swift index 243bddb..91d6c89 100644 --- a/Sources/SwiftASB/Transport/CodexCLIExecutableResolver.swift +++ b/Sources/SwiftASB/Transport/CodexCLIExecutableResolver.swift @@ -30,8 +30,8 @@ struct CodexCLIExecutableResolver { let patch: Int private static let regex = try! NSRegularExpression(pattern: #"(\d+)\.(\d+)\.(\d+)"#) - static let oldestSupportedPublicRelease = Version(major: 0, minor: 141, patch: 0) - static let latestSupportedPublicRelease = Version(major: 0, minor: 142, patch: 0) + static let oldestSupportedPublicRelease = Version(major: 0, minor: 142, patch: 0) + static let latestSupportedPublicRelease = Version(major: 0, minor: 143, patch: 0) static var documentedWindowDescription: String { let oldest = oldestSupportedPublicRelease diff --git a/Tests/SwiftASBTests/Protocol/CodexAppServerProtocolTests.swift b/Tests/SwiftASBTests/Protocol/CodexAppServerProtocolTests.swift index e32a920..c74db51 100644 --- a/Tests/SwiftASBTests/Protocol/CodexAppServerProtocolTests.swift +++ b/Tests/SwiftASBTests/Protocol/CodexAppServerProtocolTests.swift @@ -202,6 +202,7 @@ struct CodexAppServerProtocolTests { let payload = try protocolLayer.makeThreadStartRequest( id: .string("thread-1"), params: CodexWireThreadStartParams( + allowProviderModelFallback: nil, approvalPolicy: .enumeration(.onRequest), approvalsReviewer: .user, baseInstructions: "Be concise.", @@ -212,6 +213,7 @@ struct CodexAppServerProtocolTests { environments: nil, ephemeral: true, experimentalRawEvents: nil, + historyMode: nil, mockExperimentalField: nil, model: "gpt-5.4", modelProvider: "openai", @@ -234,9 +236,11 @@ struct CodexAppServerProtocolTests { #expect(object["id"] as? String == "thread-1") let params = try #require(object["params"] as? [String: Any]) + #expect(params["allowProviderModelFallback"] == nil) #expect(params["baseInstructions"] as? String == "Be concise.") #expect(params["cwd"] as? String == "/tmp/project") #expect(params["ephemeral"] as? Bool == true) + #expect(params["historyMode"] == nil) #expect(params["model"] as? String == "gpt-5.4") #expect(params["multiAgentMode"] == nil) #expect(params["sandbox"] as? String == "workspace-write") @@ -484,7 +488,7 @@ struct CodexAppServerProtocolTests { let payload = try protocolLayer.makeThreadResumeRequest( id: .string("thread-resume-1"), params: .init( - approvalPolicy: .enumeration(.onFailure), + approvalPolicy: .enumeration(.onRequest), approvalsReviewer: .guardianSubagent, baseInstructions: "Carry forward the working style.", config: ["temperature": .double(0.15)], @@ -588,7 +592,7 @@ struct CodexAppServerProtocolTests { #expect(params["threadId"] as? String == "thread-123") } - @Test("encodes thread/turns/items/list requests with the expected method and params payload") + @Test("encodes thread/items/list requests with the expected method and params payload") func encodesThreadTurnsItemsListRequest() throws { let payload = try protocolLayer.makeThreadTurnsItemsListRequest( id: .string("thread-turns-items-list-1"), @@ -603,7 +607,7 @@ struct CodexAppServerProtocolTests { let object = try #require(try JSONSerialization.jsonObject(with: payload) as? [String: Any]) #expect(object["jsonrpc"] == nil) - #expect(object["method"] as? String == "thread/turns/items/list") + #expect(object["method"] as? String == "thread/items/list") #expect(object["id"] as? String == "thread-turns-items-list-1") let params = try #require(object["params"] as? [String: Any]) @@ -908,7 +912,7 @@ struct CodexAppServerProtocolTests { id: .string("turn-1"), params: CodexWireTurnStartParams( additionalContext: nil, - approvalPolicy: .enumeration(.onFailure), + approvalPolicy: .enumeration(.onRequest), approvalsReviewer: .guardianSubagent, clientUserMessageID: nil, collaborationMode: .init( diff --git a/Tests/SwiftASBTests/Public/CodexAppServerLiveApprovalProbeTests.swift b/Tests/SwiftASBTests/Public/CodexAppServerLiveApprovalProbeTests.swift index 27c8ba9..1855d59 100644 --- a/Tests/SwiftASBTests/Public/CodexAppServerLiveApprovalProbeTests.swift +++ b/Tests/SwiftASBTests/Public/CodexAppServerLiveApprovalProbeTests.swift @@ -320,6 +320,7 @@ extension CodexAppServerLiveIntegrationTests { let threadStartPayload = try protocolLayer.makeThreadStartRequest( id: threadRequestID, params: CodexWireThreadStartParams( + allowProviderModelFallback: nil, approvalPolicy: .enumeration(.untrusted), approvalsReviewer: .user, baseInstructions: nil, @@ -330,6 +331,7 @@ extension CodexAppServerLiveIntegrationTests { environments: nil, ephemeral: true, experimentalRawEvents: nil, + historyMode: nil, mockExperimentalField: nil, model: nil, modelProvider: nil, @@ -514,6 +516,7 @@ extension CodexAppServerLiveIntegrationTests { let threadStartPayload = try protocolLayer.makeThreadStartRequest( id: threadRequestID, params: CodexWireThreadStartParams( + allowProviderModelFallback: nil, approvalPolicy: .enumeration(.untrusted), approvalsReviewer: .user, baseInstructions: nil, @@ -524,6 +527,7 @@ extension CodexAppServerLiveIntegrationTests { environments: nil, ephemeral: true, experimentalRawEvents: nil, + historyMode: nil, mockExperimentalField: nil, model: nil, modelProvider: nil, diff --git a/Tests/SwiftASBTests/Public/CodexAppServerLiveElicitationProbeTests.swift b/Tests/SwiftASBTests/Public/CodexAppServerLiveElicitationProbeTests.swift index 0f53672..9e68cfc 100644 --- a/Tests/SwiftASBTests/Public/CodexAppServerLiveElicitationProbeTests.swift +++ b/Tests/SwiftASBTests/Public/CodexAppServerLiveElicitationProbeTests.swift @@ -84,6 +84,7 @@ extension CodexAppServerLiveIntegrationTests { let threadStartPayload = try protocolLayer.makeThreadStartRequest( id: threadRequestID, params: CodexWireThreadStartParams( + allowProviderModelFallback: nil, approvalPolicy: .enumeration(.never), approvalsReviewer: nil, baseInstructions: nil, @@ -94,6 +95,7 @@ extension CodexAppServerLiveIntegrationTests { environments: nil, ephemeral: true, experimentalRawEvents: nil, + historyMode: nil, mockExperimentalField: nil, model: nil, modelProvider: nil, @@ -276,6 +278,7 @@ extension CodexAppServerLiveIntegrationTests { let threadStartPayload = try protocolLayer.makeThreadStartRequest( id: threadRequestID, params: CodexWireThreadStartParams( + allowProviderModelFallback: nil, approvalPolicy: .enumeration(.never), approvalsReviewer: nil, baseInstructions: nil, @@ -286,6 +289,7 @@ extension CodexAppServerLiveIntegrationTests { environments: nil, ephemeral: true, experimentalRawEvents: nil, + historyMode: nil, mockExperimentalField: nil, model: nil, modelProvider: nil, @@ -468,6 +472,7 @@ extension CodexAppServerLiveIntegrationTests { let threadStartPayload = try protocolLayer.makeThreadStartRequest( id: threadRequestID, params: CodexWireThreadStartParams( + allowProviderModelFallback: nil, approvalPolicy: .enumeration(.onRequest), approvalsReviewer: .user, baseInstructions: nil, @@ -478,6 +483,7 @@ extension CodexAppServerLiveIntegrationTests { environments: nil, ephemeral: true, experimentalRawEvents: nil, + historyMode: nil, mockExperimentalField: nil, model: "mock-model", modelProvider: nil, diff --git a/Tests/SwiftASBTests/Public/CodexAppServerLiveIntegrationTests.swift b/Tests/SwiftASBTests/Public/CodexAppServerLiveIntegrationTests.swift index 22711db..417ee85 100644 --- a/Tests/SwiftASBTests/Public/CodexAppServerLiveIntegrationTests.swift +++ b/Tests/SwiftASBTests/Public/CodexAppServerLiveIntegrationTests.swift @@ -130,6 +130,7 @@ struct CodexAppServerLiveIntegrationTests { let threadStartPayload = try protocolLayer.makeThreadStartRequest( id: threadRequestID, params: CodexWireThreadStartParams( + allowProviderModelFallback: nil, approvalPolicy: .enumeration(.never), approvalsReviewer: nil, baseInstructions: nil, @@ -146,6 +147,7 @@ struct CodexAppServerLiveIntegrationTests { environments: nil, ephemeral: true, experimentalRawEvents: nil, + historyMode: nil, mockExperimentalField: nil, model: nil, modelProvider: nil, @@ -203,7 +205,7 @@ struct CodexAppServerLiveIntegrationTests { let diagnostics = try await client.cliExecutableDiagnostics() #expect(diagnostics.resolvedExecutablePath == harness.codexExecutableURL.path) #expect(diagnostics.versionString.contains("codex-cli")) - #expect(diagnostics.compatibility == .supported(documentedWindow: "0.142.x plus 0.141.x when feasible")) + #expect(diagnostics.compatibility == .supported(documentedWindow: "0.143.x plus 0.142.x when feasible")) await client.stop() } catch { @@ -279,6 +281,7 @@ struct CodexAppServerLiveIntegrationTests { let threadStartPayload = try protocolLayer.makeThreadStartRequest( id: threadRequestID, params: CodexWireThreadStartParams( + allowProviderModelFallback: nil, approvalPolicy: .enumeration(.never), approvalsReviewer: nil, baseInstructions: nil, @@ -295,6 +298,7 @@ struct CodexAppServerLiveIntegrationTests { environments: nil, ephemeral: true, experimentalRawEvents: nil, + historyMode: nil, mockExperimentalField: nil, model: nil, modelProvider: nil, diff --git a/Tests/SwiftASBTests/Public/CodexAppServerTestSupport.swift b/Tests/SwiftASBTests/Public/CodexAppServerTestSupport.swift index 145d0c8..55b2f57 100644 --- a/Tests/SwiftASBTests/Public/CodexAppServerTestSupport.swift +++ b/Tests/SwiftASBTests/Public/CodexAppServerTestSupport.swift @@ -1213,7 +1213,7 @@ actor FakeCodexAppServerTransport: CodexAppServerTransporting { "nextCursor": "cursor-older", ] ) - case "thread/turns/items/list": + case "thread/items/list": return responsePayload( id: id, result: threadTurnsItemsListResult ?? [ diff --git a/Tests/SwiftASBTests/Public/CodexAppServerTests.swift b/Tests/SwiftASBTests/Public/CodexAppServerTests.swift index d1eb039..e2ee7dc 100644 --- a/Tests/SwiftASBTests/Public/CodexAppServerTests.swift +++ b/Tests/SwiftASBTests/Public/CodexAppServerTests.swift @@ -93,8 +93,8 @@ struct CodexAppServerTests { launchArgumentsPrefix: [], resolvedExecutableURL: URL(fileURLWithPath: "/opt/homebrew/bin/codex"), source: .homebrewAppleSilicon, - versionString: "codex-cli 0.142.4", - compatibility: .supported(documentedWindow: "0.142.x plus 0.141.x when feasible") + versionString: "codex-cli 0.143.0", + compatibility: .supported(documentedWindow: "0.143.x plus 0.142.x when feasible") ) ) let client = CodexAppServer(transport: transport) @@ -104,8 +104,8 @@ struct CodexAppServerTests { let diagnostics = try await client.cliExecutableDiagnostics() #expect(diagnostics.source == .homebrewAppleSilicon) #expect(diagnostics.resolvedExecutablePath == "/opt/homebrew/bin/codex") - #expect(diagnostics.versionString == "codex-cli 0.142.4") - #expect(diagnostics.compatibility == .supported(documentedWindow: "0.142.x plus 0.141.x when feasible")) + #expect(diagnostics.versionString == "codex-cli 0.143.0") + #expect(diagnostics.compatibility == .supported(documentedWindow: "0.143.x plus 0.142.x when feasible")) await client.stop() } @@ -118,8 +118,8 @@ struct CodexAppServerTests { launchArgumentsPrefix: [], resolvedExecutableURL: URL(fileURLWithPath: "/opt/homebrew/bin/codex"), source: .homebrewAppleSilicon, - versionString: "codex-cli 0.142.4", - compatibility: .supported(documentedWindow: "0.142.x plus 0.141.x when feasible") + versionString: "codex-cli 0.143.0", + compatibility: .supported(documentedWindow: "0.143.x plus 0.142.x when feasible") ) ) let client = CodexAppServer(transport: transport) @@ -134,7 +134,7 @@ struct CodexAppServerTests { ) ) - #expect(startup.cliExecutableDiagnostics.versionString == "codex-cli 0.142.4") + #expect(startup.cliExecutableDiagnostics.versionString == "codex-cli 0.143.0") #expect(startup.initializeSession.codexHome == "/Users/galew/.codex") #expect(await transport.recordedMethods == ["initialize", "initialized"]) @@ -150,7 +150,7 @@ struct CodexAppServerTests { resolvedExecutableURL: URL(fileURLWithPath: "/opt/homebrew/bin/codex"), source: .homebrewAppleSilicon, versionString: "codex-cli 0.128.0", - compatibility: .outsideDocumentedWindow(documentedWindow: "0.142.x plus 0.141.x when feasible") + compatibility: .outsideDocumentedWindow(documentedWindow: "0.143.x plus 0.142.x when feasible") ) ) let client = CodexAppServer(transport: transport) @@ -160,7 +160,7 @@ struct CodexAppServerTests { source: .homebrewAppleSilicon, resolvedExecutablePath: "/opt/homebrew/bin/codex", versionString: "codex-cli 0.128.0", - compatibility: .outsideDocumentedWindow(documentedWindow: "0.142.x plus 0.141.x when feasible") + compatibility: .outsideDocumentedWindow(documentedWindow: "0.143.x plus 0.142.x when feasible") ) )) { try await client.start( @@ -187,7 +187,7 @@ struct CodexAppServerTests { resolvedExecutableURL: URL(fileURLWithPath: "/opt/homebrew/bin/codex"), source: .homebrewAppleSilicon, versionString: "codex-cli 0.128.0", - compatibility: .outsideDocumentedWindow(documentedWindow: "0.142.x plus 0.141.x when feasible") + compatibility: .outsideDocumentedWindow(documentedWindow: "0.143.x plus 0.142.x when feasible") ) ) let client = CodexAppServer(transport: transport) @@ -353,7 +353,7 @@ struct CodexAppServerTests { #expect(methods.contains("command/exec")) #expect(!methods.contains("thread/start")) #expect(!methods.contains("turn/start")) - #expect(!methods.contains("thread/turns/items/list")) + #expect(!methods.contains("thread/items/list")) let requestPayload = try #require(await transport.recordedRequestPayload(for: "command/exec")) let request = try #require(try JSONSerialization.jsonObject(with: requestPayload) as? [String: Any]) diff --git a/Tests/SwiftASBTests/Public/CodexAppServerThreadHydrationTests.swift b/Tests/SwiftASBTests/Public/CodexAppServerThreadHydrationTests.swift index 9ea9560..a8a68f6 100644 --- a/Tests/SwiftASBTests/Public/CodexAppServerThreadHydrationTests.swift +++ b/Tests/SwiftASBTests/Public/CodexAppServerThreadHydrationTests.swift @@ -413,7 +413,7 @@ extension CodexAppServerTests { #expect(page.items.first?.kind == .commandExecution) #expect(page.items.first?.command == "swift test") - let payloads = await transport.requestPayloads(for: "thread/turns/items/list") + let payloads = await transport.requestPayloads(for: "thread/items/list") let payload = try #require(payloads.first) let object = try #require(try JSONSerialization.jsonObject(with: payload) as? [String: Any]) let params = try #require(object["params"] as? [String: Any]) diff --git a/Tests/SwiftASBTests/Transport/CodexCLIExecutableResolverTests.swift b/Tests/SwiftASBTests/Transport/CodexCLIExecutableResolverTests.swift index d705197..cf31653 100644 --- a/Tests/SwiftASBTests/Transport/CodexCLIExecutableResolverTests.swift +++ b/Tests/SwiftASBTests/Transport/CodexCLIExecutableResolverTests.swift @@ -23,8 +23,8 @@ struct CodexCLIExecutableResolverTests { #expect(resolution.launchExecutableURL == explicitURL) #expect(resolution.launchArgumentsPrefix.isEmpty) #expect(resolution.resolvedExecutableURL == explicitURL) - #expect(resolution.versionString == "codex-cli 0.142.4") - #expect(resolution.compatibility == .supported(documentedWindow: "0.142.x plus 0.141.x when feasible")) + #expect(resolution.versionString == "codex-cli 0.143.0") + #expect(resolution.compatibility == .supported(documentedWindow: "0.143.x plus 0.142.x when feasible")) #expect(recorder.recordedInvocations == [ .init(executablePath: explicitURL.path, arguments: ["--version"]), ]) @@ -48,7 +48,7 @@ struct CodexCLIExecutableResolverTests { #expect(resolution.launchExecutableURL.path == "/usr/bin/env") #expect(resolution.launchArgumentsPrefix == ["codex"]) #expect(resolution.resolvedExecutableURL == nil) - #expect(resolution.compatibility == .supported(documentedWindow: "0.142.x plus 0.141.x when feasible")) + #expect(resolution.compatibility == .supported(documentedWindow: "0.143.x plus 0.142.x when feasible")) #expect(recorder.recordedInvocations == [ .init(executablePath: "/usr/bin/env", arguments: ["codex", "--version"]), ]) @@ -76,7 +76,7 @@ struct CodexCLIExecutableResolverTests { #expect(resolution.launchExecutableURL.path == homebrewPath) #expect(resolution.launchArgumentsPrefix.isEmpty) #expect(resolution.resolvedExecutableURL?.path == homebrewPath) - #expect(resolution.compatibility == .supported(documentedWindow: "0.142.x plus 0.141.x when feasible")) + #expect(resolution.compatibility == .supported(documentedWindow: "0.143.x plus 0.142.x when feasible")) #expect(recorder.recordedInvocations == [ .init(executablePath: "/usr/bin/env", arguments: ["codex", "--version"]), .init(executablePath: homebrewPath, arguments: ["--version"]), @@ -106,7 +106,7 @@ struct CodexCLIExecutableResolverTests { #expect(resolution.launchExecutableURL.path == npmCodexPath) #expect(resolution.launchArgumentsPrefix.isEmpty) #expect(resolution.resolvedExecutableURL?.path == npmCodexPath) - #expect(resolution.compatibility == .supported(documentedWindow: "0.142.x plus 0.141.x when feasible")) + #expect(resolution.compatibility == .supported(documentedWindow: "0.143.x plus 0.142.x when feasible")) #expect(recorder.recordedInvocations == [ .init(executablePath: "/usr/bin/env", arguments: ["codex", "--version"]), .init(executablePath: "/usr/bin/env", arguments: ["npm", "prefix", "-g"]), @@ -139,7 +139,7 @@ struct CodexCLIExecutableResolverTests { @Test("marks supported versions inside the documented support window") func marksSupportedVersionsInsideSupportWindow() throws { let explicitURL = URL(fileURLWithPath: "/tmp/codex-explicit") - let recorder = CommandRecorder(pathVersionStandardOutput: "codex-cli 0.142.4") + let recorder = CommandRecorder(pathVersionStandardOutput: "codex-cli 0.143.0") let resolver = CodexCLIExecutableResolver( explicitExecutableURL: explicitURL, @@ -150,13 +150,13 @@ struct CodexCLIExecutableResolverTests { ) let resolution = try resolver.resolve() - #expect(resolution.compatibility == .supported(documentedWindow: "0.142.x plus 0.141.x when feasible")) + #expect(resolution.compatibility == .supported(documentedWindow: "0.143.x plus 0.142.x when feasible")) } @Test("marks latest prior minor versions as supported when feasible") func marksLatestPriorMinorVersionsAsSupportedWhenFeasible() throws { let explicitURL = URL(fileURLWithPath: "/tmp/codex-explicit") - let recorder = CommandRecorder(pathVersionStandardOutput: "codex-cli 0.141.9") + let recorder = CommandRecorder(pathVersionStandardOutput: "codex-cli 0.142.9") let resolver = CodexCLIExecutableResolver( explicitExecutableURL: explicitURL, @@ -167,13 +167,13 @@ struct CodexCLIExecutableResolverTests { ) let resolution = try resolver.resolve() - #expect(resolution.compatibility == .supported(documentedWindow: "0.142.x plus 0.141.x when feasible")) + #expect(resolution.compatibility == .supported(documentedWindow: "0.143.x plus 0.142.x when feasible")) } @Test("marks older minor versions outside the documented support window") func marksOlderMinorVersionsOutsideSupportWindow() throws { let explicitURL = URL(fileURLWithPath: "/tmp/codex-explicit") - let recorder = CommandRecorder(pathVersionStandardOutput: "codex-cli 0.140.9") + let recorder = CommandRecorder(pathVersionStandardOutput: "codex-cli 0.141.9") let resolver = CodexCLIExecutableResolver( explicitExecutableURL: explicitURL, @@ -184,7 +184,7 @@ struct CodexCLIExecutableResolverTests { ) let resolution = try resolver.resolve() - #expect(resolution.compatibility == .outsideDocumentedWindow(documentedWindow: "0.142.x plus 0.141.x when feasible")) + #expect(resolution.compatibility == .outsideDocumentedWindow(documentedWindow: "0.143.x plus 0.142.x when feasible")) } @Test("marks unparseable version strings as unknown format") @@ -201,7 +201,7 @@ struct CodexCLIExecutableResolverTests { ) let resolution = try resolver.resolve() - #expect(resolution.compatibility == .unknownVersionFormat(documentedWindow: "0.142.x plus 0.141.x when feasible")) + #expect(resolution.compatibility == .unknownVersionFormat(documentedWindow: "0.143.x plus 0.142.x when feasible")) } } @@ -222,7 +222,7 @@ private final class CommandRecorder: @unchecked Sendable { init( pathVersionTerminationStatus: Int32 = 0, - pathVersionStandardOutput: String = "codex-cli 0.142.4", + pathVersionStandardOutput: String = "codex-cli 0.143.0", pathVersionStandardError: String = "", npmPrefixTerminationStatus: Int32 = 0, npmPrefixOutput: String = "/Users/galew/.npm-global", diff --git a/Tools/AgentSB/pyproject.toml b/Tools/AgentSB/pyproject.toml index cbe9280..c6416a9 100644 --- a/Tools/AgentSB/pyproject.toml +++ b/Tools/AgentSB/pyproject.toml @@ -4,7 +4,7 @@ version = "0.1.0" description = "Repo-local maintenance agents for SwiftASB." readme = "README.md" requires-python = ">=3.11" -license = "PolyForm-Noncommercial-1.0.0" +license = "Apache-2.0" authors = [ { name = "Gale W", email = "mail@galewilliams.com" }, ] diff --git a/Tools/AgentSB/tests/test_cli.py b/Tools/AgentSB/tests/test_cli.py index 578c9ec..936d17e 100644 --- a/Tools/AgentSB/tests/test_cli.py +++ b/Tools/AgentSB/tests/test_cli.py @@ -19,7 +19,7 @@ def test_cli_inspect_outputs_json(repo_root, capsys): assert exit_code == 0 facts = json.loads(captured.out) - assert facts["reviewed_codex_cli_window"]["window"] == "0.142.x plus 0.141.x when feasible" + assert facts["reviewed_codex_cli_window"]["window"] == "0.143.x plus 0.142.x when feasible" def test_cli_schema_review_writes_report(fake_repo, capsys): diff --git a/Tools/AgentSB/tests/test_tools.py b/Tools/AgentSB/tests/test_tools.py index 3ee2901..473d793 100644 --- a/Tools/AgentSB/tests/test_tools.py +++ b/Tools/AgentSB/tests/test_tools.py @@ -6,7 +6,7 @@ def test_inspect_repo_reads_swiftasb_facts(repo_root): facts = inspect_repo(repo_root) - assert facts["reviewed_codex_cli_window"]["window"] == "0.142.x plus 0.141.x when feasible" + assert facts["reviewed_codex_cli_window"]["window"] == "0.143.x plus 0.142.x when feasible" assert any( item["name"] == "CodexLifecycleV2Batch+JSONValue.swift" for item in facts["promoted_wire_files"] diff --git a/docs/maintainers/interactive-lifecycle-release-boundary.md b/docs/maintainers/interactive-lifecycle-release-boundary.md index 0152cee..b9a1595 100644 --- a/docs/maintainers/interactive-lifecycle-release-boundary.md +++ b/docs/maintainers/interactive-lifecycle-release-boundary.md @@ -52,8 +52,8 @@ Current policy: - support the reviewed current public Codex CLI minor release - also support the latest prior public Codex CLI minor release when it remains compatible with SwiftASB's shipped public API and validation surface -- current reviewed minor release: `0.142.x` -- latest prior minor supported for this release: `0.141.x` +- current reviewed minor release: `0.143.x` +- latest prior minor supported for this release: `0.142.x` - widen beyond current-plus-prior only after the latest generated-wire and public API boundaries have caught up with the current app-server shape - reassess this policy when Codex reaches a future major-version release @@ -203,8 +203,11 @@ Remaining gap inside the observable-only slice: | Family | Why it remains internal | | --- | --- | | MCP tool-call progress notifications | `Internal-only for now`: the current public surface already covers MCP activity at the summary level through `Minimap.callSnapshots` and `Dashboard.mcpCallingStatus`; richer MCP progress remains internal until a stronger public model is chosen. | -| External-agent config import completed notifications | `v0.142.4` gives this family a typed internal generated shape. Useful when the app grows external-agent configuration surfaces; not part of the current lifecycle API. | -| Deprecated multi-agent mode fields | `v0.142.4` carries deprecated `multiAgentMode` fields on thread and turn start surfaces for compatibility. SwiftASB keeps them internal and continues to model user-facing proactive behavior through supported reasoning-effort and lifecycle controls. | +| External-agent config import completed notifications | `v0.143.0` gives this family a typed internal generated shape. Useful when the app grows external-agent configuration surfaces; not part of the current lifecycle API. | +| Deprecated multi-agent mode fields | `v0.143.0` carries deprecated `multiAgentMode` fields on thread and turn start surfaces for compatibility. SwiftASB keeps them internal and continues to model user-facing proactive behavior through supported reasoning-effort and lifecycle controls. | +| Thread-start fallback/history fields | `v0.143.0` adds `allowProviderModelFallback` and `historyMode` to thread-start params. SwiftASB leaves both nil until there is a public workflow for model fallback or thread-history startup modes. | +| Thread item paging route rename | `v0.143.0` renames the stored item paging wire route to `thread/items/list` and makes `turnId` optional. SwiftASB keeps the existing public turn-item paging request focused on a required turn id while using the renamed wire route internally. | +| NPM plugin-source metadata | `v0.143.0` adds npm plugin source fields and an npm source kind. SwiftASB maps the source kind for inventory display but keeps package, registry, and version metadata internal until extension management owns that full workflow. | | Guardian denied-action approval endpoint | Generated internally because it appears in v0.124, but it needs a real guardian workflow model before it becomes public. | | Raw response item completed notifications | Too low-level and transport-adjacent for the current public lifecycle boundary. | | Context compacted notifications | Interesting for diagnostics, but still not surfaced as a first-class public event; consumers currently see compaction through `Dashboard` and `Minimap` state plus explicit `compactContext()` control. | diff --git a/docs/maintainers/quicktype-codegen-notes.md b/docs/maintainers/quicktype-codegen-notes.md index 2967ba8..9d0c2f6 100644 --- a/docs/maintainers/quicktype-codegen-notes.md +++ b/docs/maintainers/quicktype-codegen-notes.md @@ -71,20 +71,22 @@ inspecting upstream schema changes or quicktype regressions. ## Current generated batch The default generated batch currently stages against the local experimental -`v0.142.4` schema dump: +`v0.143.0` schema dump: -- `SCHEMA_VERSION=v0.142.4` +- `SCHEMA_VERSION=v0.143.0` - promoted output: `Sources/SwiftASB/Generated/CodexWire/Latest/CodexLifecycleV2Batch+JSONValue.swift` The promoted `Latest` snapshot is intentionally not swapped blindly just -because staging generation succeeds. The current `v0.142.4` staging pass is a +because staging generation succeeds. The current `v0.143.0` staging pass is a good example of that boundary discipline: SwiftASB promoted the generated wire -delta internally, accepted broader generated `Sendable` coverage, exposed the -new `sleep` turn-item kind, kept deprecated multi-agent mode fields internal for -compatibility, and typed external-agent config import completion internally -without adding new public request or action surfaces. Promote generated changes -only after classifying public, observable-only, internal, and removed effects. +delta internally, routed the stored item-list API through the renamed +`thread/items/list` method while keeping the public request shape stable, +mapped the new npm plugin source kind for inventory display, kept new +thread-start fallback/history fields internal, and preserved source +compatibility for SwiftASB's older `.onFailure` approval policy after the +upstream wire enum removed `on-failure`. Promote generated changes only after +classifying public, observable-only, internal, and removed effects. ## Compatibility Shim Policy diff --git a/docs/maintainers/v1-public-api-audit.md b/docs/maintainers/v1-public-api-audit.md index 23431b2..a27c65c 100644 --- a/docs/maintainers/v1-public-api-audit.md +++ b/docs/maintainers/v1-public-api-audit.md @@ -514,7 +514,7 @@ Use these decisions for every public symbol: Decision: covered by the startup, progress/approval, diagnostics/history, and SwiftUI observable companion walkthroughs in `Sources/SwiftASB/SwiftASB.docc/`. - [x] Update stale README release references before the next release. - Decision: README now names `v1.8.0` as the current released baseline. + Decision: README now names `v1.8.1` as the current released baseline. - [x] Confirm README, DocC, and this audit use the same v1 release boundary. Decision: README, DocC, and this audit now describe the same narrow v1 promise: app-server lifecycle, app-wide capability reads, stored-thread diff --git a/docs/releases/v1.7.2.md b/docs/releases/v1.7.2.md index c6be136..e03d570 100644 --- a/docs/releases/v1.7.2.md +++ b/docs/releases/v1.7.2.md @@ -8,20 +8,16 @@ `ThreadSidebarSnapshot` data. - Refreshed the internal Codex wire snapshot and reviewed compatibility window for Codex CLI `0.138.x`. -- Moved future public versions to the PolyForm Noncommercial License 1.0.0 - while preserving historical Apache License 2.0 terms for earlier versions. +- Updated the package license surface. This license note is superseded by the + later Apache License 2.0 restoration. ## Breaking Changes -- License change for future public versions: commercial use now requires a - separate written commercial license from Gale. - No Swift API breaking changes are intended in this patch release. ## Migration And Upgrade Notes - Consumers should use Codex CLI `0.138.x`. -- Commercial users should review [COMMERCIAL-USE.md](../../COMMERCIAL-USE.md) - and contact Gale for licensing. - Earlier published SwiftASB versions remain available under the license terms that applied to those versions. diff --git a/docs/releases/v1.8.1.md b/docs/releases/v1.8.1.md new file mode 100644 index 0000000..5991060 --- /dev/null +++ b/docs/releases/v1.8.1.md @@ -0,0 +1,50 @@ +# SwiftASB v1.8.1 Release Notes + +## What Changed + +- Refreshed the internal Codex wire snapshot and reviewed compatibility window + for Codex CLI `0.143.x`, with `0.142.x` kept as the latest prior compatible + minor when feasible. +- Updated the stored turn-item paging protocol route from + `thread/turns/items/list` to the upstream `thread/items/list` method while + keeping SwiftASB's public turn-item paging request focused on a required + turn id. +- Preserved source compatibility for SwiftASB's public `.onFailure` approval + policy after Codex CLI `0.143.0` removed the matching upstream wire enum; + SwiftASB now encodes that public case as `on-request`. +- Mapped the new npm plugin source kind for extension inventory summaries while + keeping detailed npm package, registry, and version metadata internal for + future extension-management design. +- Restored Apache License 2.0 as the current public license and removed the + obsolete split license-policy files. +- Synced Swift package repo guidance through `sync-swift-package-guidance`, + refreshing the managed repo-maintenance scripts for the Swift package + profile. + +## Breaking Changes + +- No Swift source-breaking API changes are intended in this patch release. +- License terms for current public versions are Apache License 2.0 again. + +## Migration And Upgrade Notes + +- Consumers should use Codex CLI `0.143.x` where possible. `0.142.x` remains in + the reviewed prior-minor window when feasible. +- Callers using `CodexAppServer.ApprovalPolicy.onFailure` do not need source + changes, but the current upstream app-server no longer distinguishes that + mode from `on-request` at the wire level. +- Existing `listThreadTurnItems(...)` callers do not need source changes; the + route rename is handled internally. + +## Verification + +- `npm view @openai/codex version` +- `codex --version` +- `scripts/dump-codex-schemas.sh --dump-if-newer --json` +- `SCHEMA_VERSION=v0.143.0 scripts/generate-wire-types.sh` +- `uv run /Users/galew/.codex/plugins/cache/socket/apple-dev-skills/8.6.0/skills/sync-swift-package-guidance/scripts/run_workflow.py --repo-root /Users/galew/.codex/worktrees/9358/SwiftASB` +- `swift build` +- `swift test` +- `uv run pytest` from `Tools/AgentSB` +- `bash scripts/repo-maintenance/validate-all.sh` +- `git diff --check` diff --git a/scripts/generate-wire-types.sh b/scripts/generate-wire-types.sh index 5a875a2..cf38557 100755 --- a/scripts/generate-wire-types.sh +++ b/scripts/generate-wire-types.sh @@ -2,7 +2,7 @@ set -eu ROOT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd) -SCHEMA_VERSION=${SCHEMA_VERSION:-v0.142.4} +SCHEMA_VERSION=${SCHEMA_VERSION:-v0.143.0} SCHEMA_ROOT="$ROOT_DIR/codex-schemas/$SCHEMA_VERSION" DERIVED_DIR="$ROOT_DIR/tmp/derived-schemas/${SCHEMA_VERSION//./_}" OUT_DIR="$ROOT_DIR/tmp/quicktype-wire/${SCHEMA_VERSION//./_}" @@ -114,8 +114,8 @@ build_batch \ ReviewStartResponse \ ThreadTurnsListParams \ ThreadTurnsListResponse \ - ThreadTurnsItemsListParams \ - ThreadTurnsItemsListResponse \ + ThreadItemsListParams \ + ThreadItemsListResponse \ ThreadSearchParams \ ThreadSearchResponse \ ThreadLoadedListParams \ diff --git a/scripts/repo-maintenance/lib/common.sh b/scripts/repo-maintenance/lib/common.sh index 969c494..b0afa95 100755 --- a/scripts/repo-maintenance/lib/common.sh +++ b/scripts/repo-maintenance/lib/common.sh @@ -83,23 +83,6 @@ github_release_create_prerelease_flag() { fi } -github_release_notes_file() { - tag_name="$1" - release_version="${tag_name#v}" - - for candidate in \ - "$REPO_ROOT/docs/releases/$tag_name.md" \ - "$REPO_ROOT/docs/releases/$release_version.md" - do - if [ -f "$candidate" ]; then - printf '%s\n' "$candidate" - return 0 - fi - done - - return 1 -} - verify_github_release_prerelease_metadata() { tag_name="$1" expected_value="$(expected_github_prerelease_value "$tag_name")" diff --git a/scripts/repo-maintenance/release.sh b/scripts/repo-maintenance/release.sh index 915f6de..a9aa4be 100755 --- a/scripts/repo-maintenance/release.sh +++ b/scripts/repo-maintenance/release.sh @@ -273,7 +273,8 @@ defer_remote_ci_if_requested() { log "Remote CI mode is defer, so release.sh is pausing after local validation, branch push, PR creation, and initial check discovery." log "Release is not complete yet. Let GitHub finish CI for PR #$pr_number, then continue from branch $branch_name with:" log " bash scripts/repo-maintenance/release.sh --mode standard --version $RELEASE_TAG" - log "Codex should use a native thread Timer/Wakeup or heartbeat automation for this wait when available, then resume by checking $pr_url and rerunning the command above instead of leaving a shell script open to poll GitHub." + log "Codex should create a same-thread heartbeat automation for this wait when available, then resume by checking $pr_url and rerunning the command above instead of leaving a shell script open to poll GitHub." + log "The heartbeat should also wait for review-bot status contexts such as CodeRabbit to finish before merging; pending review contexts are not a clean merge signal." return 0 } @@ -399,11 +400,7 @@ create_github_release() { if [ "$REPO_MAINTENANCE_DRY_RUN" = "true" ]; then prerelease_flag="$(github_release_create_prerelease_flag "$RELEASE_TAG")" - if notes_file="$(github_release_notes_file "$RELEASE_TAG")"; then - log "Would create a GitHub release for $RELEASE_TAG with gh release create --verify-tag --notes-file $notes_file${prerelease_flag:+ $prerelease_flag}." - else - log "Would create a GitHub release for $RELEASE_TAG with gh release create --verify-tag --generate-notes${prerelease_flag:+ $prerelease_flag}." - fi + log "Would create a GitHub release for $RELEASE_TAG with gh release create --verify-tag${prerelease_flag:+ $prerelease_flag}." return 0 fi @@ -414,14 +411,8 @@ create_github_release() { fi prerelease_flag="$(github_release_create_prerelease_flag "$RELEASE_TAG")" - if notes_file="$(github_release_notes_file "$RELEASE_TAG")"; then - # shellcheck disable=SC2086 - gh release create "$RELEASE_TAG" --verify-tag --notes-file "$notes_file" $prerelease_flag - else - warn "No release notes found at docs/releases/$RELEASE_TAG.md or docs/releases/${RELEASE_TAG#v}.md; falling back to GitHub-generated notes." - # shellcheck disable=SC2086 - gh release create "$RELEASE_TAG" --verify-tag --generate-notes $prerelease_flag - fi + # shellcheck disable=SC2086 + gh release create "$RELEASE_TAG" --verify-tag --generate-notes $prerelease_flag log "Created GitHub release $RELEASE_TAG." wait_for_github_release "$RELEASE_TAG" verify_github_release_prerelease_metadata "$RELEASE_TAG" diff --git a/scripts/repo-maintenance/release/40-github-release.sh b/scripts/repo-maintenance/release/40-github-release.sh index d365bcf..2220e09 100755 --- a/scripts/repo-maintenance/release/40-github-release.sh +++ b/scripts/repo-maintenance/release/40-github-release.sh @@ -17,11 +17,7 @@ fi if [ "${REPO_MAINTENANCE_DRY_RUN:-false}" = "true" ]; then prerelease_flag="$(github_release_create_prerelease_flag "$RELEASE_TAG")" - if notes_file="$(github_release_notes_file "$RELEASE_TAG")"; then - log "Would create a GitHub release for $RELEASE_TAG with gh release create --verify-tag --notes-file $notes_file${prerelease_flag:+ $prerelease_flag}." - else - log "Would create a GitHub release for $RELEASE_TAG with gh release create --verify-tag --generate-notes${prerelease_flag:+ $prerelease_flag}." - fi + log "Would create a GitHub release for $RELEASE_TAG with gh release create --verify-tag${prerelease_flag:+ $prerelease_flag}." exit 0 fi @@ -32,14 +28,8 @@ if gh release view "$RELEASE_TAG" >/dev/null 2>&1; then fi prerelease_flag="$(github_release_create_prerelease_flag "$RELEASE_TAG")" -if notes_file="$(github_release_notes_file "$RELEASE_TAG")"; then - # shellcheck disable=SC2086 - gh release create "$RELEASE_TAG" --verify-tag --notes-file "$notes_file" $prerelease_flag -else - warn "No release notes found at docs/releases/$RELEASE_TAG.md or docs/releases/${RELEASE_TAG#v}.md; falling back to GitHub-generated notes." - # shellcheck disable=SC2086 - gh release create "$RELEASE_TAG" --verify-tag --generate-notes $prerelease_flag -fi +# shellcheck disable=SC2086 +gh release create "$RELEASE_TAG" --verify-tag --generate-notes $prerelease_flag log "Created GitHub release $RELEASE_TAG." wait_for_github_release "$RELEASE_TAG" verify_github_release_prerelease_metadata "$RELEASE_TAG"