diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..5fe568f --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +# SynapseNetwork does not currently publish a public sponsorship endpoint for this SDK. +# Keep this file so open-source tooling can discover the funding policy explicitly. diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..246b1f6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,40 @@ +--- +name: Bug report +about: Report an SDK bug or staging integration issue +title: "[Bug]: " +labels: bug +--- + +## Summary + +## SDK Surface + +- [ ] Python +- [ ] TypeScript +- [ ] Docs / examples + +## Invocation Mode + +- [ ] Fixed-price API invoke +- [ ] Token-metered LLM invoke +- [ ] Owner/provider control API + +## Environment + +- Gateway: staging (`https://api-staging.synapse-network.ai`) +- Chain: Arbitrum Sepolia +- Asset: MockUSDC + +## Reproduction + +```text +Steps, redacted code, request id, and idempotency key. +``` + +## Expected Behavior + +## Actual Behavior + +## Notes + +Do not include private keys, seed phrases, real credentials, or production tokens. diff --git a/.github/ISSUE_TEMPLATE/docs_request.md b/.github/ISSUE_TEMPLATE/docs_request.md new file mode 100644 index 0000000..2962847 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/docs_request.md @@ -0,0 +1,16 @@ +--- +name: Docs request +about: Request a README, docs, or AI-agent instruction improvement +title: "[Docs]: " +labels: documentation +--- + +## What is unclear? + +## Which page or file? + +## Expected developer outcome + +## Notes + +Public docs should remain staging-first until production docs are officially live. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..aef881e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,33 @@ +--- +name: Feature request +about: Propose an SDK capability, docs improvement, or staging integration helper +title: "[Feature]: " +labels: enhancement +--- + +## Summary + +## SDK Surface + +- [ ] Python +- [ ] TypeScript +- [ ] Docs / examples +- [ ] Agent / MCP usage + +## Use Case + +Describe the staging integration or developer workflow this would improve. + +## Proposed Behavior + +## Alternatives Considered + +## Environment + +- Gateway: staging (`https://api-staging.synapse-network.ai`) +- Chain: Arbitrum Sepolia +- Asset: MockUSDC for integration testing + +## Notes + +Do not include private keys, seed phrases, real credentials, or production tokens. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..5ed3058 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,16 @@ +## Summary + +- + +## Validation + +- [ ] `bash scripts/ci/pr_checks.sh` + +## Public SDK Contract Checklist + +- [ ] Public examples use `SYNAPSE_AGENT_KEY`. +- [ ] Public docs/examples point to staging, Arbitrum Sepolia, and MockUSDC where environment details are needed. +- [ ] Fixed-price examples pass discovered prices as strings. +- [ ] Token-metered LLM examples use `invoke_llm()` / `invokeLlm()` without `cost_usdc` / `costUsdc`. +- [ ] Public `SynapseAuth` / `SynapseProvider` returns use named models/interfaces, not raw maps. +- [ ] No private keys, seed phrases, credentials, or production tokens are committed. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..ea04f54 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,28 @@ +name: CI + +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + quality-gates: + name: SDK PR quality gates + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: Run PR quality gates + run: bash scripts/ci/pr_checks.sh diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e4a760d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +All notable public SDK changes should be recorded here. + +## 0.1.0 - Public Preview + +- Published staging-first Python and TypeScript SDK guidance. +- Standardized agent runtime credentials on `SYNAPSE_AGENT_KEY`. +- Documented two invocation modes: fixed-price API invoke and token-metered LLM invoke. +- Added typed owner/provider SDK return objects. +- Removed local gateway environment from public SDK presets and examples. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..4235c73 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,25 @@ +# Code of Conduct + +## Our Pledge + +We want the SynapseNetwork SDK community to be useful, respectful, and safe for developers building agent payment integrations. Be direct, kind, and professional. + +## Expected Behavior + +- Use welcoming and inclusive language. +- Respect different experience levels and time zones. +- Give constructive feedback focused on the work. +- Handle security, credentials, and financial-flow topics with care. + +## Unacceptable Behavior + +- Harassment, insults, threats, or discriminatory language. +- Publishing another person's private information. +- Sharing credentials, private keys, seed phrases, or other sensitive material. +- Deliberately misleading users about staging, testnet assets, or production readiness. + +## Enforcement + +Maintainers may edit, hide, or remove comments, issues, pull requests, or contributions that violate this code of conduct. Serious or repeated violations may result in a ban from project spaces. + +Report concerns through the support or security channels listed in `SUPPORT.md` and `SECURITY.md`. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..e582af9 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,52 @@ +# Contributing + +Thanks for improving the SynapseNetwork SDK. This repository is public-facing, so every change should keep the developer and AI-agent onboarding path clear, staging-first, and safe. + +## Before You Start + +1. Read `llms.txt`. +2. Use `SYNAPSE_AGENT_KEY` for agent runtime examples. +3. Treat `staging` as the only public preview environment. +4. Use Arbitrum Sepolia and MockUSDC in staging docs; do not document local gateway setup as the public integration path. +5. Never commit private keys, seed phrases, real credentials, or production tokens. + +## Development + +Python: + +```bash +cd python +python3 -m venv .venv +source .venv/bin/activate +python -m pip install -e ".[dev]" +``` + +TypeScript: + +```bash +cd typescript +npm install +``` + +## Quality Gates + +Run the full PR gate before opening or updating a pull request: + +```bash +bash scripts/ci/pr_checks.sh +``` + +Focused checks: + +```bash +bash scripts/ci/repo_hygiene_checks.sh +bash scripts/ci/python_checks.sh +bash scripts/ci/typescript_checks.sh +``` + +## SDK Contract Rules + +- Public `SynapseAuth` and `SynapseProvider` methods must return named SDK models/interfaces, not raw maps. +- Fixed-price API examples must pass discovered prices as strings, for example `cost_usdc="0.05"` or `costUsdc: "0.05"`. +- Token-metered LLM examples must use `invoke_llm()` / `invokeLlm()` and must not pass `cost_usdc` / `costUsdc`. +- New public behavior needs tests and docs in the same change. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d446b63 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Synapse Network Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..5ed3058 --- /dev/null +++ b/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,16 @@ +## Summary + +- + +## Validation + +- [ ] `bash scripts/ci/pr_checks.sh` + +## Public SDK Contract Checklist + +- [ ] Public examples use `SYNAPSE_AGENT_KEY`. +- [ ] Public docs/examples point to staging, Arbitrum Sepolia, and MockUSDC where environment details are needed. +- [ ] Fixed-price examples pass discovered prices as strings. +- [ ] Token-metered LLM examples use `invoke_llm()` / `invokeLlm()` without `cost_usdc` / `costUsdc`. +- [ ] Public `SynapseAuth` / `SynapseProvider` returns use named models/interfaces, not raw maps. +- [ ] No private keys, seed phrases, credentials, or production tokens are committed. diff --git a/README.md b/README.md index 0c1b462..e3091f4 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,26 @@ SynapseNetwork lets an agent discover services, invoke them through a gateway, a > Public Preview default: SDK examples use `staging`, backed by `https://api-staging.synapse-network.ai`. > After production launch, replace the public examples and tests with the `prod` environment. +## Staging Public Preview + +Today, public developer onboarding runs on staging: + +- Gateway: `https://api-staging.synapse-network.ai` +- App docs: [staging.synapse-network.ai/docs/sdk](https://staging.synapse-network.ai/docs/sdk) +- Chain: Arbitrum Sepolia testnet +- Asset: MockUSDC for integration testing, not production USDC + +Recommended path: + +1. Connect a wallet in the staging Gateway Dashboard. +2. Get or issue an Agent Key and export it as `SYNAPSE_AGENT_KEY`. +3. Set `SYNAPSE_ENV=staging`. +4. Use free services first, or fund staging balance with MockUSDC before paid test calls. +5. Run one fixed-price API invoke and one token-metered LLM invoke. +6. Read the invocation receipt and verify settlement metadata. + +Developers should pass staging before any future production migration. Production docs and examples stay reserved until production DNS, contracts, gateway health, and docs deployment are verified. + ## Choose Your Integration Path | Goal | Use | @@ -272,7 +292,7 @@ Credential handling and vulnerability reporting live in [SECURITY.md](./SECURITY The Python examples are staging-first and live under `python/examples`. ```bash -cd /Users/cliff/workspace/agent/Synapse-Network-Sdk/python +cd python ``` Register a provider service on staging: diff --git a/README.zh-CN.md b/README.zh-CN.md index 6d59ff5..6f214e0 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -26,6 +26,26 @@ SynapseNetwork 让 Agent 可以发现服务、通过 gateway 调用服务,并 > Public Preview 默认使用 `staging`,对应 `https://api-staging.synapse-network.ai`。 > 生产环境上线后,再把公开示例和测试统一切换到 `prod`。 +## Staging Public Preview + +当前公开开发者接入统一走 staging: + +- Gateway:`https://api-staging.synapse-network.ai` +- App docs:[staging.synapse-network.ai/docs/sdk](https://staging.synapse-network.ai/docs/sdk) +- 链:Arbitrum Sepolia 测试网 +- 资产:MockUSDC,用于接入测试,不是生产 USDC + +推荐路径: + +1. 在 staging Gateway Dashboard 连接钱包。 +2. 获取或签发 Agent Key,并设置为 `SYNAPSE_AGENT_KEY`。 +3. 设置 `SYNAPSE_ENV=staging`。 +4. 先调用免费服务;如需付费测试,先准备 MockUSDC 测试余额。 +5. 跑通一次 fixed-price API invoke 和一次 token-metered LLM invoke。 +6. 读取 invocation receipt,确认结算元数据。 + +开发者应先在 staging 验证通过。Production docs 与示例会在生产 DNS、合约、gateway health 和 docs deployment 验证后再统一切换。 + ## 选择你的接入路径 | 目标 | 使用 | diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 0000000..4f8563a --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,28 @@ +# Support + +## Public Preview Support + +The SDK is currently documented for staging public preview: + +- Gateway: `https://api-staging.synapse-network.ai` +- App docs: `https://staging.synapse-network.ai/docs/sdk` +- Chain: Arbitrum Sepolia +- Asset: MockUSDC, not production USDC + +Developers should validate integrations on staging before any future production migration. + +## Before Opening an Issue + +Please include: + +- SDK language and version. +- Whether you are using fixed-price `invoke()` / `invoke` or token-metered `invoke_llm()` / `invokeLlm()`. +- Gateway environment, normally `staging`. +- Request ID and idempotency key if an invocation failed. +- Redacted error payloads and stack traces. + +Never paste private keys, seed phrases, real credentials, or production tokens. + +## Security Reports + +Use `SECURITY.md` for vulnerability reports or credential exposure concerns. diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..77bf161 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,29 @@ +# SynapseNetwork SDK Documentation + +This directory is the public documentation source for the SynapseNetwork SDK repository. + +## Start Here + +1. [Getting Started](./guides/getting-started.md) +2. [SDK Docs Hub](./sdk/README.md) +3. [SDK/API Parity Matrix](./sdk/api-parity-matrix.md) +4. [Quality Gates](./quality-gates.md) +5. [Agent Map](./agent-map/README.md) + +## Public Preview Environment + +Public developer onboarding uses staging: + +- Gateway: `https://api-staging.synapse-network.ai` +- Chain: Arbitrum Sepolia testnet +- Asset: MockUSDC for integration testing, not production USDC + +Production docs and examples will be switched after production DNS, gateway health, contracts, and docs deployment are verified. + +## Contributor Notes + +Run the SDK PR gate before opening a pull request: + +```bash +bash scripts/ci/pr_checks.sh +``` diff --git a/docs/agent-map/README.md b/docs/agent-map/README.md index b499e19..a8bbde3 100644 --- a/docs/agent-map/README.md +++ b/docs/agent-map/README.md @@ -80,6 +80,7 @@ Update [index.json](./index.json) in the same change when: 3. A validation command changes. 4. A gateway endpoint contract changes. 5. The public preview environment or staging/prod guidance changes. +6. Public SDK examples change credential names, money handling, or invocation mode guidance. Do not put secrets, real tokens, private deployment URLs, or one-off incident notes in this map. @@ -97,6 +98,14 @@ Describe the product as a platform where agents call APIs and make small USDC pa 产品描述应表达:Agent 通过平台调用 API,并通过区块链支持的 USDC 结算完成小额付款。 +## Public Preview Constraint + +公开预览约束。 + +Public SDK docs should target staging on Arbitrum Sepolia with MockUSDC test assets until production docs are live. Do not present private local gateway setup as the public developer onboarding path. + +公开 SDK 文档在 production docs 上线前应指向 staging、Arbitrum Sepolia 和 MockUSDC 测试资产。不要把私有本地 gateway 设置作为公开开发者接入路径。 + ## Validation 验证。 diff --git a/docs/agent-map/index.json b/docs/agent-map/index.json index 3522d8a..75a5c08 100644 --- a/docs/agent-map/index.json +++ b/docs/agent-map/index.json @@ -44,6 +44,7 @@ "notes": [ "Canonical runtime flow is discovery/search plus one of two invoke modes: fixed-price invoke with costUsdc/cost_usdc, or token-metered LLM invoke with maxCostUsdc/max_cost_usdc.", "Public examples should use SYNAPSE_AGENT_KEY for agent runtime credentials; SYNAPSE_API_KEY is only a Python legacy fallback.", + "Public preview examples target staging on Arbitrum Sepolia with MockUSDC test assets.", "Do not restore old quote-first gateway calls." ] }, @@ -133,6 +134,7 @@ ], "notes": [ "Default environment is staging.", + "Public docs must describe staging as Arbitrum Sepolia plus MockUSDC until production docs are live.", "Do not reintroduce removed non-staging gateway presets or gateway setup docs.", "Do not reintroduce the retired gateway domain from the old .network namespace.", "Explicit gateway URL always wins over environment preset." @@ -230,6 +232,7 @@ ], "notes": [ "Provider staging examples require a public HTTPS endpoint reachable by the staging gateway.", + "Public SDK examples should pass discovered money values as strings and should not use float or Number conversions in quickstarts.", "Consumer wallet-to-invoke examples default to free services unless --allow-paid is explicit.", "E2E flows may require real staging credentials; PR CI should keep e2e out of the default gate unless explicitly configured." ] diff --git a/docs/guides/getting-started.md b/docs/guides/getting-started.md new file mode 100644 index 0000000..b8f390e --- /dev/null +++ b/docs/guides/getting-started.md @@ -0,0 +1,73 @@ +# Getting Started + +Use this guide to test the SDK in the staging public preview. + +## Environment + +Staging is the only public preview integration path: + +- Gateway: `https://api-staging.synapse-network.ai` +- Chain: Arbitrum Sepolia testnet +- Asset: MockUSDC for integration testing, not production USDC + +Set: + +```bash +export SYNAPSE_ENV=staging +export SYNAPSE_AGENT_KEY=agt_xxx +``` + +## Choose an Integration Path + +| Goal | Use | +|---|---| +| Connect an agent framework such as Cursor, Claude Desktop, or LangChain | `@synapse-network/mcp-server` | +| Write application code that invokes services directly | `SynapseClient` | +| Issue agent credentials or manage provider services | `SynapseAuth` and `auth.provider()` | + +## Fixed-Price API Invoke + +Use fixed-price invoke for normal API services. Pass the latest discovery price through as a string. + +```python +from synapse_client import SynapseClient + +client = SynapseClient() +service = client.search("sentiment", limit=1)[0] + +result = client.invoke( + service.service_id, + {"target": "Ethereum"}, + cost_usdc=str(service.price_usdc), + idempotency_key="agent-job-001", +) + +print(result.invocation_id, result.charged_usdc) +``` + +## Token-Metered LLM Invoke + +Use LLM invoke for services registered as token-metered LLMs. Do not send `cost_usdc` / `costUsdc`; pass an optional maximum spend cap instead. + +```python +from synapse_client import SynapseClient + +client = SynapseClient() + +result = client.invoke_llm( + "svc_provider_deepseek_chat", + {"messages": [{"role": "user", "content": "Hello"}]}, + max_cost_usdc="0.10", + idempotency_key="agent-job-002", +) + +print(result.usage, result.synapse) +``` + +## Validation + +Before contributing SDK changes, run: + +```bash +bash scripts/ci/pr_checks.sh +``` diff --git a/docs/ops/README.md b/docs/ops/README.md index 97be11a..7b9ab19 100644 --- a/docs/ops/README.md +++ b/docs/ops/README.md @@ -58,7 +58,7 @@ 根 `docs/03_Projects/sdk-python/` 当前集中维护: -1. [SDK_Python_Local_Development.md](./SDK_Python_Local_Development.md) +1. [SDK_Python_Staging_Development.md](./SDK_Python_Staging_Development.md) 项目目录内保留: diff --git a/docs/ops/SDK_Python_Local_Development.md b/docs/ops/SDK_Python_Staging_Development.md similarity index 100% rename from docs/ops/SDK_Python_Local_Development.md rename to docs/ops/SDK_Python_Staging_Development.md diff --git a/docs/ops/release-checklist.md b/docs/ops/release-checklist.md new file mode 100644 index 0000000..167e431 --- /dev/null +++ b/docs/ops/release-checklist.md @@ -0,0 +1,31 @@ +# Release Checklist + +Use this checklist for SDK releases and public documentation updates. + +## Preflight + +- [ ] `bash scripts/ci/pr_checks.sh` passes. +- [ ] `.github/workflows/ci.yml` and `.github/workflows/pr-ci.yml` are current. +- [ ] 更新 CHANGELOG.md with the release date and developer-visible changes. +- [ ] Public examples use `SYNAPSE_AGENT_KEY`. +- [ ] Public examples use `SYNAPSE_ENV=staging` until production launch. +- [ ] Fixed-price examples pass string money from discovery. +- [ ] Token-metered LLM examples use `invoke_llm()` / `invokeLlm()` without fixed `cost_usdc` / `costUsdc`. +- [ ] Public owner/provider returns are named SDK models/interfaces, not raw maps. + +## Staging Verification + +- [ ] Staging gateway health is verified. +- [ ] Arbitrum Sepolia and MockUSDC language is current. +- [ ] One fixed-price staging invoke is verified. +- [ ] One token-metered LLM staging invoke is verified when a staging LLM service is available. +- [ ] Receipt lookup is verified. + +## Production Switch + +Do not switch public examples from staging to production until production DNS, gateway health, contracts, docs deployment, and release notes are verified together. + +## Publish + +- [ ] Create and push the Git tag. +- [ ] Publish the GitHub Release with install notes and staging/prod status. diff --git a/docs/quality-gates.md b/docs/quality-gates.md index 4cbd604..a2ef44d 100644 --- a/docs/quality-gates.md +++ b/docs/quality-gates.md @@ -10,7 +10,7 @@ This repository uses `bash scripts/ci/pr_checks.sh` as the single PR quality gat ## Required Checks -- Repo hygiene: retired gateway domains, deprecated brand wording, README language split, staging defaults, and sensitive tracked filenames. +- Repo hygiene: retired gateway domains, deprecated brand wording, README language split, staging defaults, public example credential names, string money examples, removed local gateway guidance, and sensitive tracked filenames. - Python: Ruff format, Ruff lint, Mypy, unit tests with coverage, source size checks, Radon cyclomatic complexity, and package build. - TypeScript: Prettier, ESLint, `tsc --noEmit`, package build, unit tests, coverage, and duplicate-code scanning. - Security: Bandit for Python source and `npm audit --omit=dev --audit-level=high` for production npm dependencies. @@ -27,6 +27,7 @@ This repository uses `bash scripts/ci/pr_checks.sh` as the single PR quality gat - TypeScript global lines, branches, functions, and statements coverage must each be at least `80%`. - Duplicate code across `python/synapse_client` and `typescript/src` must stay at or below `3%` with a `50` token minimum clone size. - Public `SynapseAuth` and `SynapseProvider` methods must return named SDK models/interfaces, never raw Python `dict` or TypeScript `Record`. Internal HTTP payloads, schemas, and patch inputs may remain map-shaped. +- Public examples must use `SYNAPSE_AGENT_KEY`, staging, Arbitrum Sepolia, MockUSDC, and string money values until production docs are live. ## Refactor Rules diff --git a/docs/sdk/README.md b/docs/sdk/README.md index 294a513..1c336b7 100644 --- a/docs/sdk/README.md +++ b/docs/sdk/README.md @@ -9,17 +9,18 @@ This directory is the SDK-side source of truth for capabilities, integration gui ## Docs Index 1. [SDK Capability Inventory](./capability_inventory.md) -2. [Agent Map](../agent-map/README.md) -3. [Agent Map JSON](../agent-map/index.json) -4. [TypeScript Integration Guide](./typescript_integration.md) -5. [TypeScript Provider Integration Guide](./typescript_provider_integration.md) -6. [Python Integration Guide](./python_integration.md) -7. [Python Provider Integration Guide](./python_provider_integration.md) -8. [Python Staging Development](../ops/SDK_Python_Local_Development.md) -9. [TypeScript Consumer E2E Plan](../test/consumer-e2e-plan.md) -10. [TypeScript Provider Onboarding E2E Plan](../test/typescript-provider-onboarding-e2e-plan.md) -11. [Python Consumer Cold-Start E2E Plan](../test/python-consumer-cold-start-e2e-plan.md) -12. [Python Provider Onboarding E2E Plan](../test/python-provider-onboarding-e2e-plan.md) +2. [SDK/API Parity Matrix](./api-parity-matrix.md) +3. [Agent Map](../agent-map/README.md) +4. [Agent Map JSON](../agent-map/index.json) +5. [TypeScript Integration Guide](./typescript_integration.md) +6. [TypeScript Provider Integration Guide](./typescript_provider_integration.md) +7. [Python Integration Guide](./python_integration.md) +8. [Python Provider Integration Guide](./python_provider_integration.md) +9. [Python Staging Development](../ops/SDK_Python_Staging_Development.md) +10. [TypeScript Consumer E2E Plan](../test/consumer-e2e-plan.md) +11. [TypeScript Provider Onboarding E2E Plan](../test/typescript-provider-onboarding-e2e-plan.md) +12. [Python Consumer Cold-Start E2E Plan](../test/python-consumer-cold-start-e2e-plan.md) +13. [Python Provider Onboarding E2E Plan](../test/python-provider-onboarding-e2e-plan.md) ## Current Position @@ -84,6 +85,8 @@ Provider publishing is a separate owner-authenticated flow: Default environment is public preview/staging: - `staging`: `https://api-staging.synapse-network.ai` +- Chain: Arbitrum Sepolia testnet +- Asset: MockUSDC for integration testing, not production USDC Production launch will switch public examples and tests from `staging` to `prod`. @@ -136,14 +139,16 @@ The SDK maps `402` to balance, budget, or credential credit limit errors. Check ## Shortest Verification Path +From the repository root: + ```bash -cd /Users/cliff/workspace/agent/Synapse-Network-Sdk/python +cd python PYTHONPATH="$PWD" .venv/bin/python -m pytest synapse_client/test/test_client_unit.py -q export SYNAPSE_AGENT_KEY='agt_xxx_your_real_key' PYTHONPATH="$PWD" .venv/bin/python examples/smoke_test.py --query 'quotes' ``` ```bash -cd /Users/cliff/workspace/agent/Synapse-Network-Sdk/typescript +cd typescript npm run test:unit ``` diff --git a/docs/sdk/README.zh-CN.md b/docs/sdk/README.zh-CN.md index d0d9874..635e672 100644 --- a/docs/sdk/README.zh-CN.md +++ b/docs/sdk/README.zh-CN.md @@ -9,17 +9,18 @@ ## 文档入口 1. [SDK Capability Inventory](./capability_inventory.md) -2. [Agent Map](../agent-map/README.md) -3. [Agent Map JSON](../agent-map/index.json) -4. [TypeScript Integration Guide](./typescript_integration.md) -5. [TypeScript Provider Integration Guide](./typescript_provider_integration.md) -6. [Python Integration Guide](./python_integration.md) -7. [Python Provider Integration Guide](./python_provider_integration.md) -8. [Python Staging Development](../ops/SDK_Python_Local_Development.md) -9. [TypeScript Consumer E2E Plan](../test/consumer-e2e-plan.md) -10. [TypeScript Provider Onboarding E2E Plan](../test/typescript-provider-onboarding-e2e-plan.md) -11. [Python Consumer Cold-Start E2E Plan](../test/python-consumer-cold-start-e2e-plan.md) -12. [Python Provider Onboarding E2E Plan](../test/python-provider-onboarding-e2e-plan.md) +2. [SDK/API Parity Matrix](./api-parity-matrix.md) +3. [Agent Map](../agent-map/README.md) +4. [Agent Map JSON](../agent-map/index.json) +5. [TypeScript Integration Guide](./typescript_integration.md) +6. [TypeScript Provider Integration Guide](./typescript_provider_integration.md) +7. [Python Integration Guide](./python_integration.md) +8. [Python Provider Integration Guide](./python_provider_integration.md) +9. [Python Staging Development](../ops/SDK_Python_Staging_Development.md) +10. [TypeScript Consumer E2E Plan](../test/consumer-e2e-plan.md) +11. [TypeScript Provider Onboarding E2E Plan](../test/typescript-provider-onboarding-e2e-plan.md) +12. [Python Consumer Cold-Start E2E Plan](../test/python-consumer-cold-start-e2e-plan.md) +13. [Python Provider Onboarding E2E Plan](../test/python-provider-onboarding-e2e-plan.md) ## 当前结论 @@ -84,6 +85,8 @@ Provider publishing 是另一条 owner-authenticated flow: 默认环境是 public preview/staging: - `staging`: `https://api-staging.synapse-network.ai`,用于 public preview、测试资产和接入试跑。 +- 链:Arbitrum Sepolia 测试网。 +- 资产:MockUSDC,用于接入测试,不是生产 USDC。 生产环境上线后,再把公开示例和测试从 `staging` 统一切到 `prod`。 diff --git a/docs/sdk/api-parity-matrix.md b/docs/sdk/api-parity-matrix.md new file mode 100644 index 0000000..da4d2dc --- /dev/null +++ b/docs/sdk/api-parity-matrix.md @@ -0,0 +1,40 @@ +# SDK/API Parity Matrix + +This matrix keeps the SDK repo aligned with the Gateway and product docs in `Synapse-Network`. Public examples should describe these SDK surfaces first; raw Gateway routes remain implementation detail unless a developer is integrating without the SDK. + +Current public environment: staging on Arbitrum Sepolia with MockUSDC test assets. + +## Agent Runtime + +| Capability | Python SDK | TypeScript SDK | Gateway route | Notes | +|---|---|---|---|---| +| Discover services | `discover()`, `search()` | `discover()`, `search()` | `GET /api/v1/services/discover`, `POST /api/v1/agent/discovery/search` | Use before paid fixed-price calls to capture current price. | +| Fixed-price invoke | `invoke(..., cost_usdc="0.05")` | `invoke(..., { costUsdc: "0.05" })` | `POST /api/v1/agent/invoke` | Pass string amount from discovery; do not recompute with floats. | +| Token-metered LLM invoke | `invoke_llm(..., max_cost_usdc="0.10")` | `invokeLlm(..., { maxCostUsdc: "0.10" })` | `POST /api/v1/agent/invoke` | Do not send `cost_usdc` / `costUsdc`; Gateway bills final provider usage. | +| Invocation receipt | `get_invocation()` / `get_invocation_receipt()` | `getInvocation()` / `getInvocationReceipt()` | `GET /api/v1/agent/invocations/{id}` | Always read receipts after invoke. | + +## Owner Control Plane + +| Capability | Python SDK | TypeScript SDK | Gateway route | +|---|---|---|---| +| Wallet auth | `SynapseAuth.from_private_key()`, `get_token()` | `SynapseAuth.fromWallet()`, `getToken()` | `/api/v1/auth/challenge`, `/api/v1/auth/verify` | +| Agent credentials | `issue_credential()`, `list_credentials()`, `revoke_credential()`, `update_credential_quota()` | `issueCredential()`, `listCredentials()`, `revokeCredential()`, `updateCredentialQuota()` | `/api/v1/credentials/agent/*` | +| Balance and deposit | `get_balance()`, `register_deposit_intent()`, `confirm_deposit()` | `getBalance()`, `registerDepositIntent()`, `confirmDeposit()` | `/api/v1/balance*` | +| Usage and limits | `get_usage_logs()`, `set_spending_limit()` | `getUsageLogs()`, `setSpendingLimit()` | `/api/v1/usage/logs`, `/api/v1/balance/spending-limit` | + +## Provider Publishing + +| Capability | Python SDK | TypeScript SDK | Gateway route | +|---|---|---|---| +| Provider facade | `auth.provider()` / `SynapseProvider` | `auth.provider()` / `SynapseProvider` | Owner JWT scoped | +| Registration guide | `get_registration_guide()` | `getRegistrationGuide()` | `GET /api/v1/services/registration-guide` | +| Service lifecycle | `register_service()`, `list_services()`, `update_service()`, `delete_service()`, `ping_service()` | `registerService()`, `listServices()`, `updateService()`, `deleteService()`, `pingService()` | `/api/v1/services*` | +| Health and earnings | `get_service_status()`, `get_service_health_history()`, `get_earnings_summary()` | `getServiceStatus()`, `getServiceHealthHistory()`, `getEarningsSummary()` | `/api/v1/services/*`, `/api/v1/providers/earnings/summary` | +| Provider withdrawals | `get_withdrawal_capability()`, `create_withdrawal_intent()`, `list_withdrawals()` | `getWithdrawalCapability()`, `createWithdrawalIntent()`, `listWithdrawals()` | `/api/v1/providers/withdrawals*` | + +## Documentation Rules + +1. Public docs should point developers to SDK methods before raw REST routes. +2. Public docs should say staging, Arbitrum Sepolia, and MockUSDC until production launch. +3. Public docs must not show private local gateway setup as the public SDK onboarding path. +4. Public SDK examples should use `SYNAPSE_AGENT_KEY`, string money values, and named result objects. diff --git a/docs/sdk/capability_inventory.md b/docs/sdk/capability_inventory.md index 0e304bd..065b80b 100644 --- a/docs/sdk/capability_inventory.md +++ b/docs/sdk/capability_inventory.md @@ -12,7 +12,7 @@ Consumer runtime is: 4. token-metered LLM invoke through `invoke_llm()` / `invokeLlm()` with optional `max_cost_usdc` / `maxCostUsdc` 5. `GET /api/v1/agent/invocations/{id}` -Agent runtime examples use `SYNAPSE_AGENT_KEY=agt_xxx`. Python keeps `SYNAPSE_API_KEY` only as a legacy fallback. +Agent runtime examples use `SYNAPSE_AGENT_KEY=agt_xxx`. Python keeps `SYNAPSE_API_KEY` only as a legacy fallback. Public preview examples target staging on Arbitrum Sepolia with MockUSDC test assets. The old quote-first flow is not a current SDK main path. Python keeps deprecated compatibility methods that raise a clear error instead of calling removed endpoints. diff --git a/docs/sdk/python_integration.md b/docs/sdk/python_integration.md index 9a287e1..362750e 100644 --- a/docs/sdk/python_integration.md +++ b/docs/sdk/python_integration.md @@ -54,6 +54,8 @@ python -m pip install -e ".[dev]" 1. `staging`: `https://api-staging.synapse-network.ai` +当前 staging 使用 Arbitrum Sepolia 测试网和 MockUSDC 测试资产。MockUSDC 只用于接入验证,不是生产 USDC。 + 生产环境上线后,公开示例和测试再统一切换到 `prod`。 `AgentWallet.connect()` 不再使用 `demo_key` fallback。没有真实 credential 时会失败。 @@ -71,6 +73,15 @@ Fresh setup 不应从硬编码 credential 开始。`SYNAPSE_AGENT_KEY` 是 owner 如果 owner wallet 还没有余额,可以先选择 `price_usdc == 0` 的免费服务做 smoke path;`price_usdc > 0` 的服务需要先有可用余额、credits 或足够的 credential credit limit。 +Staging 接入建议先完成: + +1. `SYNAPSE_ENV=staging` +2. `SYNAPSE_AGENT_KEY=agt_xxx` +3. 免费 fixed-price API invoke +4. MockUSDC 余额准备后的付费 fixed-price API invoke +5. token-metered LLM invoke +6. receipt 查询和结算字段核对 + ## Owner 钱包登录 ```python diff --git a/docs/sdk/typescript_integration.md b/docs/sdk/typescript_integration.md index fdcbf01..9a0728c 100644 --- a/docs/sdk/typescript_integration.md +++ b/docs/sdk/typescript_integration.md @@ -50,6 +50,8 @@ SDK 库内部不隐式读取环境变量;Node、browser、worker runtime 都 1. `staging`: `https://api-staging.synapse-network.ai` +当前 staging 使用 Arbitrum Sepolia 测试网和 MockUSDC 测试资产。MockUSDC 只用于接入验证,不是生产 USDC。 + 生产环境上线后,公开示例和测试再统一切换到 `prod`。 显式 `gatewayUrl` 会覆盖 `environment`。 @@ -74,6 +76,15 @@ Fresh setup 不应从 `credential: "agt_xxx"` 开始。agent credential 必须 如果 owner wallet 还没有余额,可以先选择 `price_usdc == 0` 的免费服务做 smoke path;`price_usdc > 0` 的服务需要先有可用余额、credits 或足够的 credential credit limit。 +Staging 接入建议先完成: + +1. `SYNAPSE_ENV=staging` +2. `SYNAPSE_AGENT_KEY=agt_xxx` +3. 免费 fixed-price API invoke +4. MockUSDC 余额准备后的付费 fixed-price API invoke +5. token-metered LLM invoke +6. receipt 查询和结算字段核对 + ## Owner 钱包登录 ```ts diff --git a/llm-instructions.md b/llm-instructions.md index 701e334..d8e89fa 100644 --- a/llm-instructions.md +++ b/llm-instructions.md @@ -17,6 +17,8 @@ CRITICAL RULES FOR AI AGENTS: 9. ALWAYS fetch and read the receipt after invocation to verify settlement. 10. IF the user asks to publish/register/manage a provider API, initialize `SynapseAuth` and use `auth.provider()`. 11. Provider setup is owner-scoped. Do not treat Provider as a separate root account. +12. PUBLIC SDK EXAMPLES MUST TARGET STAGING: `SYNAPSE_ENV=staging`, Arbitrum Sepolia, and MockUSDC test assets. +13. DO NOT generate private local gateway onboarding instructions for public SDK users. @@ -32,6 +34,8 @@ AI Agent 中文规则: 9. 调用后必须读取 receipt,确认结算状态。 10. 如果用户要求发布、注册或管理 provider API,才初始化 `SynapseAuth` 并使用 `auth.provider()`。 11. Provider 是 owner scope 下的角色,不是第二套根账户体系。 +12. 公开 SDK 示例必须指向 staging:`SYNAPSE_ENV=staging`、Arbitrum Sepolia 和 MockUSDC 测试资产。 +13. 不要为公开 SDK 用户生成私有本地 gateway 接入说明。 Additional runtime preferences: diff --git a/llms.txt b/llms.txt index cac7a04..46d1cc0 100644 --- a/llms.txt +++ b/llms.txt @@ -9,8 +9,21 @@ This repository contains the official SynapseNetwork SDKs for TypeScript and Pyt - **Agent Key (`agt_xxx`)**: Runtime credential used by consumer agents to invoke services and pay. - **Service ID**: Unique identifier for a provider API. - **Staging URL**: `https://api-staging.synapse-network.ai`; staging is the default development environment. +- **Staging Chain**: Arbitrum Sepolia testnet with MockUSDC. MockUSDC is for integration testing only and is not production USDC. - **Money Rule**: Never recompute prices with floating-point math. Pass discovered prices and spend limits through exactly; use string amounts, for example `"0.05"`. +## Staging Public Preview + +Use staging for every public developer example until production launch. A correct staging integration has: + +1. `SYNAPSE_ENV=staging` +2. `SYNAPSE_AGENT_KEY=agt_xxx` +3. Fixed-price API invoke with string `cost_usdc` / `costUsdc` from discovery +4. Token-metered LLM invoke with optional string `max_cost_usdc` / `maxCostUsdc` +5. Receipt verification after invocation + +Do not generate private local gateway setup instructions for public SDK users. + ## Easiest Way: MCP Server If you are integrating SynapseNetwork into an agent framework such as Cursor, Claude Desktop, or LangChain, prefer the official MCP server instead of writing direct SDK code. diff --git a/python/README.md b/python/README.md index fc65a83..c9a6c32 100644 --- a/python/README.md +++ b/python/README.md @@ -8,7 +8,7 @@ 2. Python 接入:`docs/sdk/python_integration.md` 3. Python Provider 接入:`docs/sdk/python_provider_integration.md` 4. TypeScript 接入:`docs/sdk/typescript_integration.md` -5. 本地开发:`docs/ops/SDK_Python_Local_Development.md` +5. Staging 开发与验证:`docs/ops/SDK_Python_Staging_Development.md` 6. Python 冷启动 E2E:`docs/test/python-consumer-cold-start-e2e-plan.md` 7. Python Provider Onboarding E2E:`docs/test/python-provider-onboarding-e2e-plan.md` 8. Python bugfix:`docs/bugfix/python/bugs.md` diff --git a/python/examples/consumer_call_provider.py b/python/examples/consumer_call_provider.py index 32e3fd5..11616c9 100644 --- a/python/examples/consumer_call_provider.py +++ b/python/examples/consumer_call_provider.py @@ -21,8 +21,8 @@ def parse_args() -> argparse.Namespace: ) parser.add_argument( "--api-key", - default=os.getenv("SYNAPSE_API_KEY", "").strip(), - help="Agent credential. Defaults to SYNAPSE_API_KEY.", + default=os.getenv("SYNAPSE_AGENT_KEY", "").strip(), + help="Agent runtime credential. Defaults to SYNAPSE_AGENT_KEY.", ) parser.add_argument( "--environment", @@ -52,7 +52,6 @@ def parse_args() -> argparse.Namespace: ) parser.add_argument( "--cost-usdc", - type=float, default=None, help="Price assertion. Required only when --service-id skips discovery.", ) @@ -85,12 +84,12 @@ def parse_payload(raw: str) -> dict: return payload -def resolve_service(client: SynapseClient, args: argparse.Namespace, request_id: str) -> tuple[str, float]: +def resolve_service(client: SynapseClient, args: argparse.Namespace, request_id: str) -> tuple[str, str]: service_id = args.service_id.strip() if service_id: if args.cost_usdc is None: raise ValueError("--cost-usdc is required when --service-id skips discovery") - return service_id, float(args.cost_usdc) + return service_id, str(args.cost_usdc) discovery = client.search_services( query=args.query, @@ -110,13 +109,13 @@ def resolve_service(client: SynapseClient, args: argparse.Namespace, request_id: selected = discovery.services[0] if selected.price_usdc is None: raise RuntimeError(f"Selected service has no parseable price: {selected.service_id}") - return selected.service_id, float(selected.price_usdc) + return selected.service_id, str(selected.price_usdc) def main() -> int: args = parse_args() if not args.api_key: - print("SYNAPSE_API_KEY or --api-key is required.", file=sys.stderr) + print("SYNAPSE_AGENT_KEY or --api-key is required.", file=sys.stderr) return 2 try: payload = parse_payload(args.payload_json) @@ -137,7 +136,7 @@ def main() -> int: try: service_id, cost_usdc = resolve_service(client, args, request_id) print(f"Selected service id: {service_id}") - print(f"Price assertion: {cost_usdc:.6f} USDC") + print(f"Price assertion: {cost_usdc} USDC") invocation = client.invoke( service_id, diff --git a/python/examples/consumer_wallet_to_invoke.py b/python/examples/consumer_wallet_to_invoke.py index fb7818c..c51810b 100644 --- a/python/examples/consumer_wallet_to_invoke.py +++ b/python/examples/consumer_wallet_to_invoke.py @@ -6,6 +6,7 @@ import json import os import sys +from decimal import Decimal, InvalidOperation from uuid import uuid4 from synapse_client import SynapseAuth, SynapseClient, resolve_gateway_url @@ -71,6 +72,17 @@ def parse_payload(raw: str) -> dict: return payload +def price_string(service_price: object) -> str: + return str(service_price if service_price is not None else "0") + + +def is_zero_usdc(amount: str) -> bool: + try: + return Decimal(amount) == Decimal("0") + except (InvalidOperation, TypeError): + return False + + def main() -> int: if Account is None: print("eth-account is required. Install dev extras: python -m pip install -e '.[dev]'", file=sys.stderr) @@ -126,9 +138,9 @@ def main() -> int: selected = None for service in discovery.services: - price = float(service.price_usdc or 0) - print(f"- {service.service_id} | {service.service_name} | {price:.6f} USDC") - if selected is None and (args.allow_paid or price == 0): + price = price_string(service.price_usdc) + print(f"- {service.service_id} | {service.service_name} | {price} USDC") + if selected is None and (args.allow_paid or is_zero_usdc(price)): selected = service if selected is None: @@ -138,7 +150,7 @@ def main() -> int: ) return 1 - cost_usdc = float(selected.price_usdc or 0) + cost_usdc = price_string(selected.price_usdc) idempotency_key = f"{request_id}-invoke" invocation = client.invoke( selected.service_id, diff --git a/python/examples/smoke_test.py b/python/examples/smoke_test.py index e636218..3021f55 100755 --- a/python/examples/smoke_test.py +++ b/python/examples/smoke_test.py @@ -30,8 +30,8 @@ def parse_args() -> argparse.Namespace: ) parser.add_argument( "--api-key", - default=os.getenv("SYNAPSE_API_KEY", "").strip(), - help="Agent credential. Defaults to SYNAPSE_API_KEY.", + default=os.getenv("SYNAPSE_AGENT_KEY", "").strip(), + help="Agent runtime credential. Defaults to SYNAPSE_AGENT_KEY.", ) parser.add_argument( "--gateway-url", @@ -41,7 +41,7 @@ def parse_args() -> argparse.Namespace: parser.add_argument( "--environment", default=os.getenv("SYNAPSE_ENV", "").strip(), - help="Gateway environment preset: local, staging, or prod. Defaults to staging.", + help="Gateway environment preset. Defaults to staging.", ) parser.add_argument( "--query", @@ -61,7 +61,6 @@ def parse_args() -> argparse.Namespace: ) parser.add_argument( "--cost-usdc", - type=float, default=None, help="Required with --service-id. Price assertion sent to /api/v1/agent/invoke.", ) @@ -133,7 +132,7 @@ def format_curl( request_id: str, body: dict, ) -> str: - env_api_key = "${SYNAPSE_API_KEY:-REPLACE_ME}" + env_api_key = "${SYNAPSE_AGENT_KEY:-REPLACE_ME}" return shell_join( [ "curl", @@ -165,7 +164,7 @@ def print_stage_curl( return print_section("replay with curl") - print("export SYNAPSE_API_KEY='agt_xxx_your_real_key'") + print("export SYNAPSE_AGENT_KEY='agt_xxx_your_real_key'") if discovery_body is not None: print("discovery:") print(format_curl( @@ -200,7 +199,7 @@ def print_failure_diagnosis( print(f"service_id: {service_id}", file=sys.stderr) if isinstance(exc, AuthenticationError): - print("hint: verify SYNAPSE_API_KEY is valid, not revoked, and accepted by the target gateway.", file=sys.stderr) + print("hint: verify SYNAPSE_AGENT_KEY is valid, not revoked, and accepted by the target gateway.", file=sys.stderr) return if isinstance(exc, InsufficientFundsError): print("hint: owner treasury or credential credit limit is exhausted; top up balance or widen budget policy.", file=sys.stderr) @@ -229,11 +228,11 @@ def build_discovery_body(args: argparse.Namespace) -> dict: return body -def build_invoke_body(service_id: str, cost_usdc: float, idempotency_key: str, payload: dict) -> dict: +def build_invoke_body(service_id: str, cost_usdc: str, idempotency_key: str, payload: dict) -> dict: return { "serviceId": service_id, "idempotencyKey": idempotency_key, - "costUsdc": round(float(cost_usdc), 6), + "costUsdc": cost_usdc, "payload": {"body": payload}, "responseMode": "sync", } @@ -252,12 +251,12 @@ def resolve_service_id( service_id: str, request_id: str, discovery_body: dict | None, -) -> tuple[str, float, int]: +) -> tuple[str, str, int]: if service_id: if args.cost_usdc is None: print("--cost-usdc is required when --service-id is provided.", file=sys.stderr) - return service_id, 0.0, 2 - return service_id, float(args.cost_usdc), 0 + return service_id, "0", 2 + return service_id, str(args.cost_usdc), 0 print_section("discovery") print_json("Discovery request", discovery_body) @@ -274,12 +273,12 @@ def resolve_service_id( if not discovery.results: print("No discoverable services matched the current query.", file=sys.stderr) - return "", 0.0, 1 + return "", "0", 1 resolved_service_id = discovery.results[0].service_id - price_usdc = float(discovery.results[0].pricing.amount) + price_usdc = str(discovery.results[0].pricing.amount) print(f"Selected service: {resolved_service_id}") - print(f"Selected price: {price_usdc:.6f} USDC") + print(f"Selected price: {price_usdc} USDC") return resolved_service_id, price_usdc, 0 @@ -313,7 +312,7 @@ def run_price_asserted_invoke( *, client: SynapseClient, service_id: str, - cost_usdc: float, + cost_usdc: str, payload: dict, request_id: str, idempotency_key: str, @@ -345,7 +344,7 @@ def run_price_asserted_invoke( def main() -> int: args = parse_args() if not args.api_key: - print("SYNAPSE_API_KEY or --api-key is required", file=sys.stderr) + print("SYNAPSE_AGENT_KEY or --api-key is required", file=sys.stderr) return 2 try: diff --git a/scripts/ci/python_checks.sh b/scripts/ci/python_checks.sh index c33b500..61cdc21 100755 --- a/scripts/ci/python_checks.sh +++ b/scripts/ci/python_checks.sh @@ -4,6 +4,9 @@ set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" cd "$ROOT_DIR" +export SYNAPSE_ENV=staging +unset SYNAPSE_GATEWAY + PYTHON_BIN="${PYTHON_BIN:-python}" if [[ -z "${VIRTUAL_ENV:-}" ]]; then VENV_DIR="${PYTHON_VENV_DIR:-$ROOT_DIR/python/.venv}" diff --git a/scripts/ci/repo_hygiene_checks.sh b/scripts/ci/repo_hygiene_checks.sh index 10903b2..881ae1e 100755 --- a/scripts/ci/repo_hygiene_checks.sh +++ b/scripts/ci/repo_hygiene_checks.sh @@ -28,6 +28,21 @@ if grep -RInE --exclude-dir=.git --exclude-dir=node_modules --exclude-dir=.venv exit 1 fi +echo "[ci:hygiene] checking public SDK examples use staging agent credentials" +if grep -RInF --exclude-dir=.git --exclude-dir=__pycache__ --exclude-dir=.pytest_cache \ + "SYNAPSE_API_KEY" python/examples; then + echo "[ci:hygiene] public examples must use SYNAPSE_AGENT_KEY, not SYNAPSE_API_KEY" >&2 + exit 1 +fi + +echo "[ci:hygiene] checking public money examples preserve string amounts" +if grep -RInE --exclude-dir=.git --exclude-dir=node_modules --exclude-dir=.venv --exclude-dir=dist --exclude-dir=build --exclude-dir=coverage --exclude-dir=.pytest_cache \ + '(cost_usdc=float|costUsdc: Number|Number\([^)]*(price|cost)|float\([^)]*(price|cost|service\.price_usdc)|round\(float\(cost_usdc)' \ + README.md README.zh-CN.md docs/sdk llms.txt llm-instructions.md python/examples; then + echo "[ci:hygiene] public SDK examples must pass discovered money values as strings" >&2 + exit 1 +fi + echo "[ci:hygiene] checking deprecated product brand wording" OLD_AGENT_PAY="Agent""Pay" OLD_SYNAPSE_AGENT_PAY="Synapse Agent""Pay"