mirror of
https://github.com/Ryder-Sun/Meldwork.git
synced 2026-11-07 06:56:03 -10:00
feat: sync license and agent runtime updates
This commit is contained in:
1 parent
da0108abb1
commit
782f839d4f
26 files changed
+535
-145
No files matched your search
@@ -0,0 +1,51 @@
|
||||
# Code of Conduct
|
||||
|
||||
Meldwork is a workspace for people and Agents to build together. We want issues,
|
||||
pull requests, discussions, and community spaces to stay useful, direct, and
|
||||
respectful.
|
||||
|
||||
## Expected Behavior
|
||||
|
||||
- Be clear, constructive, and respectful when giving feedback.
|
||||
- Assume good intent while keeping discussions focused on facts, tradeoffs, and outcomes.
|
||||
- Respect different experience levels, backgrounds, languages, and working styles.
|
||||
- Keep disagreements technical, specific, and connected to the project.
|
||||
- Help maintainers keep issues and pull requests focused.
|
||||
- Protect private prompts, credentials, customer information, and other sensitive data.
|
||||
|
||||
## Unacceptable Behavior
|
||||
|
||||
The following behavior is not acceptable in Meldwork project spaces:
|
||||
|
||||
- Personal attacks, insults, harassment, or sustained disruption.
|
||||
- Demeaning comments about identity, background, language, ability, or experience.
|
||||
- Threats, intimidation, stalking, or unwanted contact.
|
||||
- Publishing another person's private information without consent.
|
||||
- Spam, trolling, discrimination, or repeated off-topic posting.
|
||||
- Submitting malicious code, secrets, private data, or intentionally misleading reports.
|
||||
- Any behavior maintainers reasonably judge to make the project unsafe or unproductive.
|
||||
|
||||
## Maintainer Responsibilities
|
||||
|
||||
Maintainers may edit or remove comments, close issues, limit participation, or
|
||||
block participants when needed to protect the project community. Enforcement
|
||||
should be proportional, documented when practical, and focused on keeping
|
||||
collaboration healthy.
|
||||
|
||||
## Reporting
|
||||
|
||||
Report conduct concerns privately through the repository's GitHub contact or
|
||||
security reporting channel. Do not open a public issue for sensitive reports.
|
||||
|
||||
Please include:
|
||||
|
||||
- a short description of what happened;
|
||||
- links, screenshots, or message references when available;
|
||||
- whether you want follow-up, confidentiality, or no direct reply.
|
||||
|
||||
Reports will be reviewed by project maintainers. We will handle reports with
|
||||
care and limit access to people who need the information to respond.
|
||||
|
||||
This Code of Conduct applies wherever the project or its maintainers represent
|
||||
the Meldwork community. It is adapted from the Contributor Covenant and the
|
||||
community standards used by comparable open-source projects.
|
||||
+10
-13
@@ -1,17 +1,14 @@
|
||||
# Commercial Use And Licensing
|
||||
|
||||
Meldwork is source-available under the [Meldwork Non-Commercial Source License](LICENSE). The public repository can be inspected, evaluated, run, and modified for non-commercial purposes, but it is not licensed for commercial use.
|
||||
Meldwork is licensed under the [Apache License 2.0](LICENSE). Commercial use,
|
||||
private use, modification, redistribution, and use inside a paid service are
|
||||
permitted under the license terms.
|
||||
|
||||
Any commercial use requires prior written permission from the copyright holder. This includes monetizing Meldwork, reselling or hosting it, embedding it in a proprietary product, using it to provide paid services, or using it as part of a for-profit organization's business operations.
|
||||
This page is a practical summary and does not replace the license text. Apache
|
||||
License 2.0 does not grant trademark rights to the Meldwork name, logo,
|
||||
screenshots, or other brand assets. Third-party software, Agent products,
|
||||
models, names, logos, and other materials remain subject to their own licenses
|
||||
and terms.
|
||||
|
||||
The copyright holder may offer a separate commercial license for organizations that need permission for:
|
||||
|
||||
- proprietary redistribution or resale of Meldwork or a modified version;
|
||||
- embedding Meldwork code in a closed-source product;
|
||||
- offering a hosted, managed, or network-accessible version;
|
||||
- internal business operations at a for-profit organization;
|
||||
- separately licensed commercial features, enterprise integrations, support, or managed deployment.
|
||||
|
||||
A commercial license does not change the licenses of third-party dependencies, Agent products, names, models, or logos. The repository license also does not grant trademark rights to the Meldwork name, logo, screenshots, or other brand assets.
|
||||
|
||||
This page is a practical summary and does not replace the license text or legal advice. When a planned use may be commercial, contact the repository owner through GitHub before using, distributing, hosting, reselling, or integrating the product.
|
||||
Before distributing a product that includes third-party materials, review the
|
||||
relevant notices and preserve the required attribution and license information.
|
||||
+6
-5
@@ -1,8 +1,8 @@
|
||||
# Contributing
|
||||
|
||||
Meldwork is source-available under the [Meldwork Non-Commercial Source License](LICENSE). Contributions are welcome when they improve the local-first desktop product, documentation, tests, or security posture.
|
||||
Meldwork is licensed under the [Apache License 2.0](LICENSE). Contributions are welcome when they improve the local-first desktop product, documentation, tests, or security posture.
|
||||
|
||||
Unless a separate written agreement applies, a contribution accepted into this repository is available under the repository license. The project may also offer separately licensed commercial editions. Before external code is incorporated into a separately licensed commercial build, the maintainer may require a reviewed contributor-license agreement that grants the necessary relicensing rights. Opening a pull request by itself does not transfer copyright or silently grant those additional rights.
|
||||
Unless a separate written agreement applies, a contribution accepted into this repository is available under the repository license. Opening a pull request does not transfer copyright beyond the rights granted by the Apache License 2.0.
|
||||
|
||||
## Ground Rules
|
||||
|
||||
@@ -11,8 +11,9 @@ Unless a separate written agreement applies, a contribution accepted into this r
|
||||
- Do not add remote services, telemetry, credential collection, or server dependencies without explicit project approval.
|
||||
- Preserve the local-first boundary: renderer code must not gain unrestricted filesystem, shell, Provider credential, or executable-path access.
|
||||
- Include focused tests for behavior, security boundary, storage, or IPC changes.
|
||||
- Confirm that all submitted code and assets are yours to license and do not introduce incompatible license obligations.
|
||||
- Confirm that all submitted code and assets are yours to contribute and do not introduce incompatible license obligations.
|
||||
|
||||
## Commercial Editions
|
||||
## Community Standards
|
||||
|
||||
Commercial use of Meldwork requires prior written permission. Commercial editions, proprietary integrations, support, and other paid offerings may use separate terms; see [COMMERCIAL_USE.md](COMMERCIAL_USE.md).
|
||||
Please follow the [Code of Conduct](CODE_OF_CONDUCT.md) in issues, pull
|
||||
requests, discussions, and other project spaces.
|
||||
@@ -1,82 +1,201 @@
|
||||
Meldwork Non-Commercial Source License 1.0
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
Copyright (c) 2026 Ryder-MHumble.
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
This license applies to Meldwork and the source code, documentation, assets, and
|
||||
other materials in this repository, except where a file or third-party notice
|
||||
states a different license.
|
||||
1. Definitions.
|
||||
|
||||
Meldwork is source-available, not open source in the OSI sense. Commercial use is
|
||||
not permitted without prior written permission from the copyright holder.
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
1. Allowed non-commercial use
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
You may download, inspect, run, copy, and modify Meldwork for personal learning,
|
||||
research, evaluation, security review, and other non-commercial purposes.
|
||||
"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 may share unmodified or modified copies for non-commercial purposes if you:
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
- keep this license and all copyright, attribution, and trademark notices;
|
||||
- clearly mark your changes when you distribute a modified copy;
|
||||
- do not remove or obscure third-party notices; and
|
||||
- do not imply that the copyright holder endorses your copy or service.
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
2. Commercial use requires permission
|
||||
"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.
|
||||
|
||||
You may not use Meldwork for a commercial purpose without a separate written
|
||||
license or other written permission from the copyright holder.
|
||||
"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).
|
||||
|
||||
Commercial purpose includes, without limitation:
|
||||
"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.
|
||||
|
||||
- selling, renting, sublicensing, or otherwise monetizing Meldwork or a modified
|
||||
version;
|
||||
- offering Meldwork or a modified version as a hosted, managed, consulting,
|
||||
outsourcing, integration, or support service;
|
||||
- embedding Meldwork code, UI, workflow, or packaged binaries in a proprietary,
|
||||
paid, or revenue-generating product;
|
||||
- using Meldwork to provide paid deliverables, paid automation, paid Agent
|
||||
operations, or other business services to a customer; and
|
||||
- use by or for a for-profit company, commercial product team, or revenue-driven
|
||||
organization as part of its business operations.
|
||||
"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."
|
||||
|
||||
If you want to use Meldwork commercially, contact the repository owner and obtain
|
||||
written permission before using, distributing, hosting, reselling, or integrating
|
||||
the product.
|
||||
"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.
|
||||
|
||||
3. No trademark license
|
||||
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.
|
||||
|
||||
This license does not grant rights to use the Meldwork name, logo, product
|
||||
identity, screenshots, or other brand assets except as needed to describe an
|
||||
unaltered copy of the software in a truthful, non-confusing way.
|
||||
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. Third-party materials
|
||||
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:
|
||||
|
||||
Third-party software, Agent products, models, names, logos, dependencies, and
|
||||
other materials remain subject to their own licenses and terms. This license does
|
||||
not give you rights that the copyright holder does not own.
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
5. Contributions
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
Unless a separate written agreement says otherwise, contributions submitted to
|
||||
this repository may be used under this license. The copyright holder may require
|
||||
a separate contributor agreement before accepting contributions intended for a
|
||||
commercially licensed edition.
|
||||
(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
|
||||
|
||||
6. Termination
|
||||
(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.
|
||||
|
||||
If you violate this license, your rights under it terminate automatically. The
|
||||
copyright holder may reinstate rights in writing after the violation is cured.
|
||||
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.
|
||||
|
||||
7. No warranty
|
||||
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.
|
||||
|
||||
Meldwork is provided "as is", without warranties or conditions of any kind,
|
||||
including implied warranties of merchantability, fitness for a particular
|
||||
purpose, title, and non-infringement. You are responsible for evaluating whether
|
||||
the software is suitable and lawful for your use.
|
||||
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.
|
||||
|
||||
8. Limitation of liability
|
||||
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.
|
||||
|
||||
To the maximum extent permitted by law, the copyright holder and contributors
|
||||
will not be liable for any damages arising from or related to the software or
|
||||
this license, including direct, indirect, incidental, consequential, special,
|
||||
exemplary, punitive, or business-interruption damages.
|
||||
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.
|
||||
@@ -1,9 +1,7 @@
|
||||
Meldwork
|
||||
Copyright 2026 Ryder-MHumble and Meldwork contributors.
|
||||
|
||||
Meldwork is licensed under the Meldwork Non-Commercial Source License. See
|
||||
LICENSE. Commercial use requires separate written permission from the copyright
|
||||
holder.
|
||||
Meldwork is licensed under the Apache License 2.0. See LICENSE.
|
||||
|
||||
Third-party Agent names, product names, and logos remain the property of their
|
||||
respective owners. They are used only to identify compatible integrations and
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
<!-- <p align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="frontend/public/logos/meldwork-wordmark-v3-dark.svg">
|
||||
<source media="(prefers-color-scheme: light)" srcset="frontend/public/logos/meldwork-wordmark-v3.svg">
|
||||
<img src="frontend/public/logos/meldwork-wordmark-v3.svg" alt="Meldwork" width="360">
|
||||
</picture>
|
||||
</p> -->
|
||||
<div align="center">
|
||||
|
||||
<p align="center">
|
||||
<img src="frontend/public/logos/meldwork-readme-banner-en.png" alt="Meldwork README banner" width="100%">
|
||||
</p>
|
||||
<img src="frontend/public/logos/meldwork-readme-banner-en.png" alt="Meldwork" width="100%" />
|
||||
|
||||
<p align="center">
|
||||
<strong>English</strong> · <a href="README.zh-CN.md">简体中文</a>
|
||||
</p>
|
||||
[Architecture](architecture.md) · [Agent Connector Contract](docs/agent-connector-sdk.md) · [Contributing](CONTRIBUTING.md) · [Code of Conduct](CODE_OF_CONDUCT.md)
|
||||
|
||||
[English](README.md) | [简体中文](README.zh-CN.md)
|
||||
|
||||
[](LICENSE)
|
||||
[](https://github.com/Ryder-MHumble/Meldwork/releases)
|
||||
|
||||
</div>
|
||||
|
||||
# Meldwork builds the organization layer for AI agents.
|
||||
|
||||
|
||||
+10
-13
@@ -1,18 +1,15 @@
|
||||
<!-- <p align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="frontend/public/logos/meldwork-wordmark-v3-dark.svg">
|
||||
<source media="(prefers-color-scheme: light)" srcset="frontend/public/logos/meldwork-wordmark-v3.svg">
|
||||
<img src="frontend/public/logos/meldwork-wordmark-v3.svg" alt="Meldwork" width="360">
|
||||
</picture>
|
||||
</p> -->
|
||||
<div align="center">
|
||||
|
||||
<p align="center">
|
||||
<img src="frontend/public/logos/meldwork-readme-banner-cn.png" alt="Meldwork README banner" width="100%">
|
||||
</p>
|
||||
<img src="frontend/public/logos/meldwork-readme-banner-en.png" alt="Meldwork" width="100%" />
|
||||
|
||||
<p align="center">
|
||||
<a href="README.md">English</a> · <strong>简体中文</strong>
|
||||
</p>
|
||||
[Architecture](architecture.md) · [Agent Connector Contract](docs/agent-connector-sdk.md) · [Contributing](CONTRIBUTING.md) · [Code of Conduct](CODE_OF_CONDUCT.md)
|
||||
|
||||
[English](README.md) | [简体中文](README.zh-CN.md)
|
||||
|
||||
[](LICENSE)
|
||||
[](https://github.com/Ryder-MHumble/Meldwork/releases)
|
||||
|
||||
</div>
|
||||
|
||||
# Meldwork 为 AI Agent 构建组织层
|
||||
|
||||
|
||||
Generated
+1
-1
@@ -7,7 +7,7 @@
|
||||
"": {
|
||||
"name": "meldwork-desktop",
|
||||
"version": "0.1.3",
|
||||
"license": "SEE LICENSE IN LICENSE",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@agentclientprotocol/sdk": "0.23.0",
|
||||
"@streamparser/json": "0.0.22",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"private": true,
|
||||
"description": "A local-first desktop workspace for multi-Agent collaboration",
|
||||
"author": "Ryder-MHumble",
|
||||
"license": "SEE LICENSE IN LICENSE",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
},
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"manifest":{"connectorId":"external.local-echo-sample","connectorVersion":"1.0.0","credentials":{"mode":"none","slots":[]},"description":"Local SDK sample that returns text without delegating to a built-in Agent.","domains":["general"],"eventProtocolVersion":1,"eventTypes":["Completed","Failed","Cancelled"],"inputTypes":["text"],"invocation":{"recipeId":"sdk.local-echo.v1"},"kind":"agent","label":"Local Echo Connector Sample","license":"LicenseRef-Meldwork-NC","manifestId":"connector-manifest-6ce79bf9cbe282e9f537a1b45d742cc507e21ade5ea2859dff9e007bd4f850db","outboundDestinations":[],"permissionModes":["read-only"],"recordType":"agent-connector-manifest","schemaVersion":1,"session":{"cancel":true,"checkpoint":false,"resume":true,"supported":true},"transport":{"protocol":"json","type":"cli"},"upstream":{"id":"meldwork-sdk","maxVersion":"1.0.0","minVersion":"1.0.0"},"usage":{"costMicros":false,"elapsedMs":false,"inputTokens":false,"outboundBytes":false,"outputTokens":false,"toolCalls":false}},"packageId":"connector-package-f4908cee8fa7acf5d17a403b39bd58cb8d4a1dfec3fbfb43c62c5727ee793cd4","provider":{"config":{},"id":"sdk.local-echo.v1"},"publisher":{"id":"meldwork","name":"Meldwork"},"recordType":"agent-connector-package","schemaVersion":1}
|
||||
{"manifest":{"connectorId":"external.local-echo-sample","connectorVersion":"1.0.0","credentials":{"mode":"none","slots":[]},"description":"Local SDK sample that returns text without delegating to a built-in Agent.","domains":["general"],"eventProtocolVersion":1,"eventTypes":["Completed","Failed","Cancelled"],"inputTypes":["text"],"invocation":{"recipeId":"sdk.local-echo.v1"},"kind":"agent","label":"Local Echo Connector Sample","license":"Apache-2.0","manifestId":"connector-manifest-6ce79bf9cbe282e9f537a1b45d742cc507e21ade5ea2859dff9e007bd4f850db","outboundDestinations":[],"permissionModes":["read-only"],"recordType":"agent-connector-manifest","schemaVersion":1,"session":{"cancel":true,"checkpoint":false,"resume":true,"supported":true},"transport":{"protocol":"json","type":"cli"},"upstream":{"id":"meldwork-sdk","maxVersion":"1.0.0","minVersion":"1.0.0"},"usage":{"costMicros":false,"elapsedMs":false,"inputTokens":false,"outboundBytes":false,"outputTokens":false,"toolCalls":false}},"packageId":"connector-package-f4908cee8fa7acf5d17a403b39bd58cb8d4a1dfec3fbfb43c62c5727ee793cd4","provider":{"config":{},"id":"sdk.local-echo.v1"},"publisher":{"id":"meldwork","name":"Meldwork"},"recordType":"agent-connector-package","schemaVersion":1}
|
||||
@@ -15,6 +15,7 @@ const {
|
||||
parseMimoOutput,
|
||||
parseOpenCodeOutput,
|
||||
parseOpenCodeReviewOutput,
|
||||
parsePiOutput,
|
||||
parseWorkBuddyOutput,
|
||||
readHermesFinalResponse,
|
||||
readHermesMessageWatermark,
|
||||
@@ -463,6 +464,7 @@ module.exports = {
|
||||
parseMimoOutput,
|
||||
parseOpenCodeOutput,
|
||||
parseOpenCodeReviewOutput,
|
||||
parsePiOutput,
|
||||
parseWorkBuddyOutput,
|
||||
prepareCommand,
|
||||
readHermesFinalResponse,
|
||||
|
||||
@@ -14,6 +14,7 @@ const {
|
||||
parseMimoOutput,
|
||||
parseOpenCodeOutput,
|
||||
parseOpenCodeReviewOutput,
|
||||
parsePiOutput,
|
||||
parseWorkBuddyOutput,
|
||||
readHermesFinalResponse,
|
||||
readHermesMessageWatermark,
|
||||
@@ -31,6 +32,7 @@ const {
|
||||
kimiStreamJsonRuntimeEvents,
|
||||
mimoJsonRuntimeEvents,
|
||||
openCodeJsonRuntimeEvents,
|
||||
piJsonRuntimeEvents,
|
||||
} = require('./cli-runtime-event-mappers.cjs')
|
||||
|
||||
function createStatelessRuntimeState() {
|
||||
@@ -75,7 +77,7 @@ const FINAL_OUTPUT_PARSERS = Object.freeze({
|
||||
codex: parseCodexOutput,
|
||||
openclaw: stdout => ({ text: normalizeOpenClawOutput(stdout), sessionRef: '' }),
|
||||
workbuddy: parseWorkBuddyOutput,
|
||||
pi: parseOpenCodeOutput,
|
||||
pi: parsePiOutput,
|
||||
kimi: parseKimiOutput,
|
||||
mimo: parseMimoOutput,
|
||||
claude: parseClaudeQwenOutput,
|
||||
@@ -365,7 +367,7 @@ const PI_JSON_EVENTS_PROFILE = profile({
|
||||
},
|
||||
createDecoder: createJsonLineParser,
|
||||
createState: createStatelessRuntimeState,
|
||||
mapEvent: openCodeJsonRuntimeEvents,
|
||||
mapEvent: piJsonRuntimeEvents,
|
||||
createFinalOutputAccumulator: createFinalOutputAccumulator('pi'),
|
||||
})
|
||||
|
||||
@@ -467,7 +469,6 @@ const TRANSPORT_EVENT_PROFILES = Object.freeze({
|
||||
openclaw: Object.freeze({ legacy: OPENCLAW_TERMINAL_DOCUMENT_PROFILE }),
|
||||
kimi: Object.freeze({ 'stream-json': KIMI_STREAM_JSON_PROFILE }),
|
||||
mimo: Object.freeze({ acp: ACP_JSONRPC_PROFILE }),
|
||||
pi: Object.freeze({ acp: ACP_JSONRPC_PROFILE }),
|
||||
opencode: Object.freeze({ acp: ACP_JSONRPC_PROFILE }),
|
||||
workbuddy: Object.freeze({ 'stream-json': ANTHROPIC_STREAM_JSON_PROFILE }),
|
||||
})
|
||||
|
||||
@@ -140,24 +140,20 @@ function invocation(kind, executable, workdir, sessionRef = '', options = {}) {
|
||||
}
|
||||
}
|
||||
if (kind === 'pi') {
|
||||
if (options.invocationTransport !== 'json') {
|
||||
return {
|
||||
command: executable,
|
||||
args: ['acp', '--pure', '--cwd', workdir],
|
||||
acpMode: options.sandbox === 'workspace-write' ? 'build' : 'plan',
|
||||
eventTransport: 'acp',
|
||||
fallbackTransport: 'json',
|
||||
fallbackSessionPolicy: 'preserve',
|
||||
}
|
||||
}
|
||||
return {
|
||||
command: executable,
|
||||
args: [
|
||||
'run', '--format', 'json',
|
||||
'--agent', options.sandbox === 'workspace-write' ? 'build' : 'plan',
|
||||
...(sessionRef ? ['--session', sessionRef] : []),
|
||||
'--mode', 'json',
|
||||
...(options.sandbox === 'workspace-write'
|
||||
? []
|
||||
: ['--tools', 'read,grep,find,ls']),
|
||||
...(options.provider?.id ? ['--provider', options.provider.id] : []),
|
||||
...(options.provider?.model ? ['--model', options.provider.model] : []),
|
||||
...(sessionRef ? ['--session-id', sessionRef] : []),
|
||||
'-p',
|
||||
],
|
||||
promptArg: true,
|
||||
eventTransport: 'pi-json-events',
|
||||
}
|
||||
}
|
||||
if (kind === 'kimi') {
|
||||
|
||||
@@ -154,7 +154,29 @@ function ingestStructuredEvent(state, event) {
|
||||
return
|
||||
}
|
||||
|
||||
if (['pi', 'mimo', 'opencode'].includes(state.kind)) {
|
||||
if (state.kind === 'pi') {
|
||||
if (event.type === 'session' && typeof event.id === 'string') state.sessionRef = event.id
|
||||
if (event.type === 'message_update'
|
||||
&& event.assistantMessageEvent?.type === 'text_delta'
|
||||
&& typeof event.assistantMessageEvent.delta === 'string') {
|
||||
appendStructuredText(state, event.assistantMessageEvent.delta, '')
|
||||
}
|
||||
if (event.type === 'message_end'
|
||||
&& event.message?.role === 'assistant'
|
||||
&& Array.isArray(event.message.content)
|
||||
&& !state.text.trim()) {
|
||||
appendStructuredText(state, piMessageContentText(event.message.content), '')
|
||||
}
|
||||
if (event.type === 'agent_settled') state.outcome = 'completed'
|
||||
if (event.type === 'turn_end') {
|
||||
const reason = String(event.message?.stopReason || event.message?.rawStopReason || '')
|
||||
state.outcome = reason === 'stop' ? 'completed' : (reason ? stepFinishOutcome(reason) : 'completed')
|
||||
if (state.outcome === 'failed') markStructuredFailure(state)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (['mimo', 'opencode'].includes(state.kind)) {
|
||||
if (typeof event.sessionID === 'string') state.sessionRef = event.sessionID
|
||||
if (event.type === 'text' && event.part?.type === 'text'
|
||||
&& typeof event.part.text === 'string') {
|
||||
@@ -437,6 +459,45 @@ function parseMimoOutput(stdout) {
|
||||
return { text: texts.join('\n').trim(), sessionRef, error: errors.join('\n').trim() }
|
||||
}
|
||||
|
||||
function piMessageContentText(content) {
|
||||
return (Array.isArray(content) ? content : [])
|
||||
.map(part => (part?.type === 'text' && typeof part.text === 'string' ? part.text : ''))
|
||||
.filter(Boolean)
|
||||
.join('\n')
|
||||
}
|
||||
|
||||
function parsePiOutput(stdout) {
|
||||
const raw = String(stdout || '').trim()
|
||||
if (!raw) return { text: '', sessionRef: '' }
|
||||
let sessionRef = ''
|
||||
const deltas = []
|
||||
let finalText = ''
|
||||
let parsedLine = false
|
||||
for (const line of raw.split(/\r?\n/)) {
|
||||
if (!line.trim()) continue
|
||||
try {
|
||||
const event = JSON.parse(line)
|
||||
parsedLine = true
|
||||
if (event?.type === 'session' && typeof event.id === 'string') sessionRef = event.id
|
||||
if (event?.type === 'message_update'
|
||||
&& event.assistantMessageEvent?.type === 'text_delta'
|
||||
&& typeof event.assistantMessageEvent.delta === 'string') {
|
||||
deltas.push(event.assistantMessageEvent.delta)
|
||||
}
|
||||
if (event?.type === 'message_end'
|
||||
&& event.message?.role === 'assistant'
|
||||
&& Array.isArray(event.message.content)) {
|
||||
const text = piMessageContentText(event.message.content)
|
||||
if (text) finalText = text
|
||||
}
|
||||
} catch { /* fall back to raw output when the CLI did not emit JSONL */ }
|
||||
}
|
||||
return {
|
||||
text: finalText.trim() || deltas.join('').trim() || (parsedLine ? '' : raw),
|
||||
sessionRef,
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeOpenClawOutput(stdout) {
|
||||
const raw = String(stdout || '').trim()
|
||||
if (!raw) return ''
|
||||
@@ -718,7 +779,15 @@ function classifyCliOutcome(kind, stdout) {
|
||||
: 'partial',
|
||||
}
|
||||
}
|
||||
if (['pi', 'mimo', 'opencode'].includes(kind)) {
|
||||
if (kind === 'pi') {
|
||||
const turn = events.findLast(event => event?.type === 'turn_end')
|
||||
if (turn) {
|
||||
const reason = String(turn.message?.stopReason || turn.message?.rawStopReason || '')
|
||||
return { outcome: reason === 'stop' || !reason ? 'completed' : stepFinishOutcome(reason) }
|
||||
}
|
||||
return { outcome: events.some(event => event?.type === 'agent_settled') ? 'completed' : 'partial' }
|
||||
}
|
||||
if (['mimo', 'opencode'].includes(kind)) {
|
||||
const finish = events.findLast(event => (
|
||||
event?.type === 'step_finish' || event?.part?.type === 'step-finish'
|
||||
))
|
||||
@@ -832,6 +901,7 @@ module.exports = {
|
||||
parseJsonOutputEvents,
|
||||
parseKimiOutput,
|
||||
parseMimoOutput,
|
||||
parsePiOutput,
|
||||
parseOpenCodeOutput,
|
||||
parseOpenCodeReviewOutput,
|
||||
parseWorkBuddyOutput,
|
||||
|
||||
@@ -345,6 +345,20 @@ function openCodeJsonRuntimeEvents(event) {
|
||||
return []
|
||||
}
|
||||
|
||||
function piJsonRuntimeEvents(event) {
|
||||
if (!event || typeof event !== 'object') return []
|
||||
if (event.type === 'message_update'
|
||||
&& event.assistantMessageEvent?.type === 'text_delta'
|
||||
&& typeof event.assistantMessageEvent.delta === 'string') {
|
||||
return [{
|
||||
type: 'answer_delta',
|
||||
status: 'running',
|
||||
delta: event.assistantMessageEvent.delta,
|
||||
}]
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
function finalOnlyRuntimeEvents() {
|
||||
return []
|
||||
}
|
||||
@@ -432,4 +446,5 @@ module.exports = {
|
||||
kimiStreamJsonRuntimeEvents,
|
||||
mimoJsonRuntimeEvents,
|
||||
openCodeJsonRuntimeEvents,
|
||||
piJsonRuntimeEvents,
|
||||
}
|
||||
@@ -13,6 +13,7 @@ const {
|
||||
parseMimoOutput,
|
||||
parseOpenCodeOutput,
|
||||
parseOpenCodeReviewOutput,
|
||||
parsePiOutput,
|
||||
parseWorkBuddyOutput,
|
||||
readHermesFinalResponse,
|
||||
readHermesMessageWatermark,
|
||||
@@ -53,6 +54,7 @@ module.exports = {
|
||||
parseMimoOutput,
|
||||
parseOpenCodeOutput,
|
||||
parseOpenCodeReviewOutput,
|
||||
parsePiOutput,
|
||||
parseWorkBuddyOutput,
|
||||
readHermesFinalResponse,
|
||||
readHermesMessageWatermark,
|
||||
|
||||
@@ -48,7 +48,7 @@ const SAMPLE_AGENT_CONNECTOR_MANIFEST = createAgentConnectorManifest({
|
||||
},
|
||||
outboundDestinations: [],
|
||||
credentials: { mode: 'none', slots: [] },
|
||||
license: 'LicenseRef-Meldwork-NC',
|
||||
license: 'Apache-2.0',
|
||||
})
|
||||
const SAMPLE_CREDENTIAL_AGENT_CONNECTOR_MANIFEST = createAgentConnectorManifest({
|
||||
connectorId: 'external.codex-provider-sample',
|
||||
@@ -81,7 +81,7 @@ const SAMPLE_CREDENTIAL_AGENT_CONNECTOR_MANIFEST = createAgentConnectorManifest(
|
||||
mode: 'credential-ref',
|
||||
slots: [{ slotId: 'openai-api-key', type: 'api-key', required: true }],
|
||||
},
|
||||
license: 'LicenseRef-Meldwork-NC',
|
||||
license: 'Apache-2.0',
|
||||
})
|
||||
const APPROVED_AGENT_CONNECTOR_MANIFESTS = Object.freeze([
|
||||
SAMPLE_AGENT_CONNECTOR_MANIFEST,
|
||||
@@ -116,7 +116,7 @@ const SAMPLE_LOCAL_ECHO_AGENT_CONNECTOR_MANIFEST = createAgentConnectorManifest(
|
||||
},
|
||||
outboundDestinations: [],
|
||||
credentials: { mode: 'none', slots: [] },
|
||||
license: 'LicenseRef-Meldwork-NC',
|
||||
license: 'Apache-2.0',
|
||||
})
|
||||
const SAMPLE_LOCAL_ECHO_AGENT_CONNECTOR_PACKAGE = createAgentConnectorPackage({
|
||||
publisher: { id: 'meldwork', name: 'Meldwork' },
|
||||
|
||||
@@ -19,6 +19,7 @@ const {
|
||||
parseMimoOutput,
|
||||
parseOpenCodeOutput,
|
||||
parseOpenCodeReviewOutput,
|
||||
parsePiOutput,
|
||||
parseWorkBuddyOutput,
|
||||
prepareCommand,
|
||||
readHermesFinalResponse,
|
||||
@@ -1062,6 +1063,67 @@ test('MiMo JSON output returns final text and session id', () => {
|
||||
})
|
||||
})
|
||||
|
||||
test('Pi uses the current non-interactive JSON mode and resumes by session id', () => {
|
||||
const readOnly = invocation('pi', '/tmp/pi', '/tmp/work', 'pi-session', {
|
||||
provider: { id: 'zgci', model: 'glm' },
|
||||
})
|
||||
assert.deepEqual(readOnly.args, [
|
||||
'--mode', 'json',
|
||||
'--tools', 'read,grep,find,ls',
|
||||
'--provider', 'zgci',
|
||||
'--model', 'glm',
|
||||
'--session-id', 'pi-session',
|
||||
'-p',
|
||||
])
|
||||
assert.equal(readOnly.promptArg, true)
|
||||
assert.equal(readOnly.eventTransport, 'pi-json-events')
|
||||
|
||||
const writable = invocation('pi', '/tmp/pi', '/tmp/work', '', {
|
||||
sandbox: 'workspace-write',
|
||||
})
|
||||
assert.deepEqual(writable.args, ['--mode', 'json', '-p'])
|
||||
})
|
||||
|
||||
test('Pi JSON output returns final text and session id from current CLI events', () => {
|
||||
const raw = [
|
||||
JSON.stringify({
|
||||
type: 'session',
|
||||
id: '01a03794-ae3f-72ea-9efd-cd2cd16d88a1',
|
||||
cwd: '/tmp/work',
|
||||
}),
|
||||
JSON.stringify({
|
||||
type: 'message_update',
|
||||
assistantMessageEvent: { type: 'text_delta', contentIndex: 0, delta: 'Pi ' },
|
||||
}),
|
||||
JSON.stringify({
|
||||
type: 'message_update',
|
||||
assistantMessageEvent: { type: 'text_delta', contentIndex: 0, delta: 'reply' },
|
||||
}),
|
||||
JSON.stringify({
|
||||
type: 'message_end',
|
||||
message: {
|
||||
role: 'assistant',
|
||||
content: [{ type: 'text', text: 'Pi reply' }],
|
||||
stopReason: 'stop',
|
||||
},
|
||||
}),
|
||||
JSON.stringify({
|
||||
type: 'turn_end',
|
||||
message: { role: 'assistant', stopReason: 'stop' },
|
||||
}),
|
||||
JSON.stringify({ type: 'agent_settled' }),
|
||||
].join('\n')
|
||||
assert.deepEqual(parsePiOutput(raw), {
|
||||
text: 'Pi reply',
|
||||
sessionRef: '01a03794-ae3f-72ea-9efd-cd2cd16d88a1',
|
||||
})
|
||||
assert.deepEqual(profileOutput('pi', raw), {
|
||||
text: 'Pi reply',
|
||||
sessionRef: '01a03794-ae3f-72ea-9efd-cd2cd16d88a1',
|
||||
outcome: 'completed',
|
||||
})
|
||||
})
|
||||
|
||||
test('Claude and Qwen stream JSON output returns the final reply and session id', () => {
|
||||
for (const kind of ['claude', 'qwen']) {
|
||||
const raw = [
|
||||
@@ -1598,12 +1660,19 @@ test('every supported built-in Agent produces an explicit completion outcome', (
|
||||
].join('\n'),
|
||||
pi: [
|
||||
JSON.stringify({
|
||||
type: 'text', sessionID: 'pi-session',
|
||||
part: { type: 'text', text: 'Pi Agent reply' },
|
||||
type: 'session', id: 'pi-session', version: 3,
|
||||
}),
|
||||
JSON.stringify({
|
||||
type: 'step_finish', sessionID: 'pi-session',
|
||||
part: { type: 'step-finish', reason: 'stop' },
|
||||
type: 'message_update',
|
||||
assistantMessageEvent: { type: 'text_delta', contentIndex: 0, delta: 'Pi Agent reply' },
|
||||
}),
|
||||
JSON.stringify({
|
||||
type: 'message_end',
|
||||
message: { role: 'assistant', content: [{ type: 'text', text: 'Pi Agent reply' }] },
|
||||
}),
|
||||
JSON.stringify({
|
||||
type: 'turn_end',
|
||||
message: { role: 'assistant', stopReason: 'stop', rawStopReason: 'stop' },
|
||||
}),
|
||||
].join('\n'),
|
||||
claude: JSON.stringify({
|
||||
|
||||
@@ -15,6 +15,7 @@ const {
|
||||
parseKimiOutput,
|
||||
parseMimoOutput,
|
||||
parseOpenCodeOutput,
|
||||
parsePiOutput,
|
||||
parseWorkBuddyOutput,
|
||||
prepareCommand,
|
||||
readHermesFinalResponse,
|
||||
@@ -1521,6 +1522,23 @@ test('Hermes receives selected Skill snapshots through the prompt without native
|
||||
assert.deepEqual(acpSpec.args, ['acp'])
|
||||
})
|
||||
|
||||
test('Pi receives provider settings through supported top-level JSON flags', () => {
|
||||
const spec = invocation('pi', '/tmp/pi', '/tmp', 'pi-session-123', {
|
||||
provider: { id: 'zgci', model: 'glm' },
|
||||
})
|
||||
assert.deepEqual(spec.args, [
|
||||
'--mode', 'json',
|
||||
'--tools', 'read,grep,find,ls',
|
||||
'--provider', 'zgci',
|
||||
'--model', 'glm',
|
||||
'--session-id', 'pi-session-123',
|
||||
'-p',
|
||||
])
|
||||
assert.equal(spec.promptArg, true)
|
||||
assert.equal(spec.eventTransport, 'pi-json-events')
|
||||
assert.equal(typeof parsePiOutput, 'function')
|
||||
})
|
||||
|
||||
test('Hermes forwards one image and rejects additional images instead of dropping them', () => {
|
||||
const first = path.resolve('diagram-one.png')
|
||||
const second = path.resolve('diagram-two.png')
|
||||
|
||||
@@ -133,11 +133,7 @@ test('every built-in invocation transport resolves its reusable profile and capa
|
||||
kind: 'mimo', options: { invocationTransport: 'json' },
|
||||
profileId: 'mimo-json-events-v1', limited: true,
|
||||
},
|
||||
{ kind: 'pi', profileId: 'acp-jsonrpc-v1', limited: false },
|
||||
{
|
||||
kind: 'pi', options: { invocationTransport: 'json' },
|
||||
profileId: 'pi-json-events-v1', limited: true,
|
||||
},
|
||||
{ kind: 'pi', profileId: 'pi-json-events-v1', limited: true },
|
||||
{ kind: 'claude', profileId: 'anthropic-stream-json-v1', limited: false },
|
||||
{ kind: 'gemini', profileId: 'gemini-stream-json-v1', limited: false },
|
||||
{ kind: 'opencode', profileId: 'acp-jsonrpc-v1', limited: false },
|
||||
|
||||
@@ -54,9 +54,9 @@ const STREAMING_FIXTURES = [
|
||||
{
|
||||
kind: 'pi',
|
||||
agent: 'Pi Agent',
|
||||
version: '0.1.0',
|
||||
version: '0.84.2',
|
||||
protocol: 'pi-json-events',
|
||||
evidence: 'source-derived',
|
||||
evidence: 'captured-fixture',
|
||||
file: 'pi.jsonl',
|
||||
expectedTypes: ['answer_delta'],
|
||||
},
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
{ "kind": "hermes", "agent": "Hermes", "version": "0.19.1", "protocol": "terminal-text", "evidence": "captured-fixture", "file": "hermes.txt" },
|
||||
{ "kind": "openclaw", "transport": "legacy", "agent": "OpenClaw", "version": "2026.7.1-2", "protocol": "openclaw-terminal-document", "evidence": "captured-fixture", "file": "openclaw.json" },
|
||||
{ "kind": "workbuddy", "agent": "WorkBuddy", "version": "2.115.0", "protocol": "workbuddy-terminal-result-json", "evidence": "source-derived", "file": "workbuddy.jsonl", "variants": [{ "transport": "stream-json", "agent": "WorkBuddy", "version": "2.115.0", "protocol": "anthropic-stream-json", "evidence": "source-derived", "file": "workbuddy-stream-json.jsonl" }] },
|
||||
{ "kind": "pi", "agent": "Pi Agent", "version": "0.1.0", "protocol": "pi-json-events", "evidence": "source-derived", "file": "pi.jsonl" },
|
||||
{ "kind": "pi", "agent": "Pi Agent", "version": "0.84.2", "protocol": "pi-json-events", "evidence": "captured-fixture", "file": "pi.jsonl" },
|
||||
{ "kind": "kimi", "transport": "stream-json", "agent": "Kimi", "version": "0.19.2", "protocol": "assistant-jsonl", "evidence": "captured-fixture", "file": "kimi.jsonl" },
|
||||
{ "kind": "mimo", "agent": "MiMo", "version": "0.1.0", "protocol": "mimo-json-events", "evidence": "captured-fixture", "file": "mimo.jsonl" },
|
||||
{ "kind": "claude", "agent": "Claude", "version": "2.1.165", "protocol": "anthropic-stream-json", "evidence": "captured-fixture", "file": "claude.jsonl" },
|
||||
|
||||
+8
-2
@@ -1,2 +1,8 @@
|
||||
{"type":"text","sessionID":"pi-fixture-session","part":{"type":"text","text":"Pi Agent fixture reply"}}
|
||||
{"type":"step_finish","sessionID":"pi-fixture-session","part":{"type":"step-finish","reason":"stop"}}
|
||||
{"type":"session","version":3,"id":"pi-fixture-session","cwd":"/tmp/work"}
|
||||
{"type":"agent_start"}
|
||||
{"type":"turn_start"}
|
||||
{"type":"message_update","assistantMessageEvent":{"type":"text_delta","contentIndex":0,"delta":"Pi Agent fixture reply"}}
|
||||
{"type":"message_end","message":{"role":"assistant","content":[{"type":"text","text":"Pi Agent fixture reply"}],"stopReason":"stop","rawStopReason":"stop"}}
|
||||
{"type":"turn_end","message":{"role":"assistant","content":[{"type":"text","text":"Pi Agent fixture reply"}],"stopReason":"stop","rawStopReason":"stop"}}
|
||||
{"type":"agent_end"}
|
||||
{"type":"agent_settled"}
|
||||
@@ -39,6 +39,61 @@ test('direct Hermes conversations reuse one persistent ACP runtime key across me
|
||||
assert.equal(calls[1].runOptions.acpPersistenceKey, calls[0].runOptions.acpPersistenceKey)
|
||||
})
|
||||
|
||||
test('direct Pi conversations reuse the native JSON session across messages', async (t) => {
|
||||
const { directory, calls, options } = fixture()
|
||||
t.after(() => fs.rmSync(directory, { recursive: true, force: true }))
|
||||
options.detectAgents = async () => [{
|
||||
kind: 'pi', name: 'Pi Agent', executable: '/tmp/pi', version: '0.84.2',
|
||||
}]
|
||||
options.runAgent = async (agent, prompt, workdir, runOptions) => {
|
||||
calls.push({ agent, prompt, workdir, runOptions })
|
||||
const sessionRef = runOptions.sessionRef || 'pi-json-session'
|
||||
await runOptions.onSessionRef(sessionRef)
|
||||
return { text: `pi reply ${calls.length}`, sessionRef, outcome: 'completed' }
|
||||
}
|
||||
const workspace = new LocalWorkspace(options)
|
||||
await workspace.refreshAgents()
|
||||
const group = workspace.createGroup({
|
||||
name: 'Pi direct', agentKinds: ['pi'], workdir: directory,
|
||||
conversationType: 'direct', directAgentKind: 'pi',
|
||||
})
|
||||
|
||||
await workspace.sendMessage({ groupId: group.id, text: 'first' })
|
||||
await workspace.sendMessage({ groupId: group.id, text: 'second' })
|
||||
|
||||
assert.deepEqual(calls.map(call => call.agent.kind), ['pi', 'pi'])
|
||||
assert.deepEqual(calls.map(call => call.runOptions.sessionRef), ['', 'pi-json-session'])
|
||||
assert.deepEqual(calls.map(call => call.runOptions.sessionTransport), ['', ''])
|
||||
})
|
||||
|
||||
test('group conversations dispatch Pi alongside other available Agents', async (t) => {
|
||||
const { directory, calls, options } = fixture()
|
||||
t.after(() => fs.rmSync(directory, { recursive: true, force: true }))
|
||||
options.detectAgents = async () => [
|
||||
{ kind: 'pi', name: 'Pi Agent', executable: '/tmp/pi', version: '0.84.2' },
|
||||
{ kind: 'codex', name: 'Codex', executable: '/tmp/codex', version: '0.144.0' },
|
||||
]
|
||||
options.runAgent = async (agent, prompt, workdir, runOptions) => {
|
||||
calls.push({ agent, prompt, workdir, runOptions })
|
||||
const sessionRef = runOptions.sessionRef || `${agent.kind}-session`
|
||||
await runOptions.onSessionRef(sessionRef)
|
||||
return { text: `${agent.kind} reply`, sessionRef, outcome: 'completed' }
|
||||
}
|
||||
const workspace = new LocalWorkspace(options)
|
||||
await workspace.refreshAgents()
|
||||
const group = workspace.createGroup({
|
||||
name: 'Pi group', agentKinds: ['pi', 'codex'], workdir: directory,
|
||||
})
|
||||
|
||||
await workspace.sendMessage({
|
||||
groupId: group.id, text: 'ask the group', targetKinds: ['pi', 'codex'],
|
||||
})
|
||||
|
||||
assert.deepEqual(calls.map(call => call.agent.kind).sort(), ['codex', 'pi'])
|
||||
const messages = workspace.snapshot().messages.filter(item => item.role === 'agent')
|
||||
assert.deepEqual(messages.map(item => item.agentKind).sort(), ['codex', 'pi'])
|
||||
})
|
||||
|
||||
test('Workspace stream bridge redacts split credentials and paths while preserving tools', async (t) => {
|
||||
const { directory, options } = fixture()
|
||||
t.after(() => fs.rmSync(directory, { recursive: true, force: true }))
|
||||
|
||||
Generated
+1
-1
@@ -7,7 +7,7 @@
|
||||
"": {
|
||||
"name": "meldwork-frontend",
|
||||
"version": "0.1.3",
|
||||
"license": "SEE LICENSE IN LICENSE",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@vicons/ionicons5": "^0.12.0",
|
||||
"dompurify": "^3.4.13",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"private": true,
|
||||
"description": "Meldwork local-first multi-Agent collaboration workspace",
|
||||
"author": "Ryder-MHumble",
|
||||
"license": "SEE LICENSE IN LICENSE",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user