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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ SynapseNetwork lets an agent discover services, invoke them through a gateway, a
2. Create a `SynapseClient`.
3. Search, invoke, and read the receipt.

This README is the 5-minute SDK quickstart path for public preview. It gives agents one primary agent demo flow: choose Python or TypeScript, use `staging`, search for a service, invoke it, then verify the receipt.

> Public Preview default: SDK examples use `staging`, backed by `https://api-staging.synapse-network.ai`.
> The `prod` preset points to `https://api.synapse-network.ai`, but production should only be used after official DNS and `/health` are live.

Expand Down Expand Up @@ -138,6 +140,28 @@ console.log(receipt.invocationId, receipt.status, receipt.chargedUsdc);

TypeScript does not read environment variables by itself. Read them in your app and pass `environment` or `gatewayUrl` explicitly.

### LLM token-metered calls

LLM services registered with `serviceKind=llm` and `priceModel=token_metered` use `invoke_llm()` / `invokeLlm()`. Do not pass `cost_usdc` / `costUsdc`; pass optional `max_cost_usdc` / `maxCostUsdc` or let Gateway compute the automatic hold. Streaming is rejected in V1 so Gateway can capture final usage safely.

```python
result = client.invoke_llm(
"svc_deepseek_chat",
{"messages": [{"role": "user", "content": "hello"}], "max_tokens": 512},
max_cost_usdc="0.010000",
)
print(result.usage.input_tokens, result.synapse.charged_usdc, result.synapse.released_usdc)
```

```ts
const result = await client.invokeLlm(
"svc_deepseek_chat",
{ messages: [{ role: "user", content: "hello" }], max_tokens: 512 },
{ maxCostUsdc: "0.010000" }
);
console.log(result.usage?.inputTokens, result.synapse?.chargedUsdc, result.synapse?.releasedUsdc);
```

## Advanced: Programmatic Credential Issuance

Use `SynapseAuth` only when an owner/backend service needs to issue credentials or register provider services programmatically. Ordinary agent runtime code should use `SynapseClient` with an existing `agt_xxx` key.
Expand Down Expand Up @@ -274,6 +298,8 @@ Supported today:
- Provider service register/list/get/status/update/delete/ping/registration guide/health history
- Provider earnings and withdrawal intent/list/capability helpers

Public owner/provider helpers return named SDK objects such as `UsageLogList`, `ProviderRegistrationGuide`, and `ProviderWithdrawalIntentResult`, not raw maps.

Not yet wrapped:

- Refunds, notifications, community, and event APIs
Expand Down
24 changes: 24 additions & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,28 @@ console.log(receipt.invocationId, receipt.status, receipt.chargedUsdc);

TypeScript SDK 不会自动读取环境变量。请在你的应用中读取环境变量,然后显式传入 `environment` 或 `gatewayUrl`。

### LLM 按 token 计费调用

使用 `serviceKind=llm` 和 `priceModel=token_metered` 注册的 LLM 服务,需要调用 `invoke_llm()` / `invokeLlm()`。不要传 `cost_usdc` / `costUsdc`;可以传可选的 `max_cost_usdc` / `maxCostUsdc`,也可以交给 Gateway 自动冻结。V1 会拒绝 streaming,确保 Gateway 能拿到 final usage 后再扣费。

```python
result = client.invoke_llm(
"svc_deepseek_chat",
{"messages": [{"role": "user", "content": "hello"}], "max_tokens": 512},
max_cost_usdc="0.010000",
)
print(result.usage.input_tokens, result.synapse.charged_usdc, result.synapse.released_usdc)
```

```ts
const result = await client.invokeLlm(
"svc_deepseek_chat",
{ messages: [{ role: "user", content: "hello" }], max_tokens: 512 },
{ maxCostUsdc: "0.010000" }
);
console.log(result.usage?.inputTokens, result.synapse?.chargedUsdc, result.synapse?.releasedUsdc);
```

## 高级用法:以代码方式签发凭据

只有当 owner/backend service 需要以代码方式签发凭据或注册 provider service 时,才使用 `SynapseAuth`。普通 Agent 运行时代码应使用已有 `agt_xxx` key 和 `SynapseClient`。
Expand Down Expand Up @@ -274,6 +296,8 @@ PYTHONPATH="$PWD" .venv/bin/python examples/consumer_wallet_to_invoke.py \
- Provider service register/list/get/status/update/delete/ping/registration guide/health history
- Provider earnings and withdrawal intent/list/capability helpers

公开 owner/provider helper 返回 `UsageLogList`、`ProviderRegistrationGuide`、`ProviderWithdrawalIntentResult` 等命名 SDK 对象,而不是 raw map。

尚未封装:

- Refunds、notifications、community、event APIs
Expand Down
13 changes: 10 additions & 3 deletions docs/agent-map/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"SECURITY.md",
"docs/sdk/README.md",
"docs/sdk/capability_inventory.md",
"docs/quality-gates.md",
"scripts/ci/pr_checks.sh"
],
"domains": [
Expand Down Expand Up @@ -70,7 +71,8 @@
],
"notes": [
"Credential and finance-adjacent helpers must not log real tokens or secrets.",
"High-impact finance helpers may wrap API calls, but should not auto-execute irreversible user actions."
"High-impact finance helpers may wrap API calls, but should not auto-execute irreversible user actions.",
"Public owner-auth returns must use named SDK models/interfaces, not raw dict or Record."
]
},
{
Expand Down Expand Up @@ -98,7 +100,8 @@
],
"notes": [
"Provider onboarding success is measured through owner control-plane service records, not public discovery alone.",
"Provider is an owner-scoped supply-side role; use auth.provider() / SynapseProvider rather than a separate root identity."
"Provider is an owner-scoped supply-side role; use auth.provider() / SynapseProvider rather than a separate root identity.",
"Public provider facade returns must use named SDK models/interfaces, not raw dict or Record."
]
},
{
Expand Down Expand Up @@ -179,6 +182,9 @@
"scripts/ci/python_checks.sh",
"scripts/ci/typescript_checks.sh",
"scripts/ci/repo_hygiene_checks.sh",
"scripts/ci/security_checks.sh",
"scripts/ci/source_quality_checks.py",
"docs/quality-gates.md",
"typescript/package.json"
],
"supporting_files": [
Expand All @@ -189,7 +195,8 @@
"bash scripts/ci/pr_checks.sh"
],
"notes": [
"Local scripts and GitHub Actions must share the same entrypoint."
"Local scripts and GitHub Actions must share the same entrypoint.",
"Source files over 500 lines, high complexity, and duplicate code above threshold must fail PR CI."
]
},
{
Expand Down
37 changes: 26 additions & 11 deletions docs/plans/bootstrap-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,42 @@

- Project: `synapse-network-sdk`
- Root: `/Users/cliff/workspace/agent/Synapse-Network-Sdk`
- Overall: `READY`
- Overall: `PARTIAL`

## Checklist
- [x] Core - Core status=HEALTHY (ok=7, warn=0, fail=0, info=0)
- [ ] Core - Core status=ATTENTION (ok=6, warn=0, fail=1, info=0)
- [x] Planning - Planning status=HEALTHY (ok=2, warn=0, fail=0, info=0)
- [x] Integration - Integration status=HEALTHY (ok=2, warn=0, fail=0, info=0)
- [ ] Optional - Optional status=WATCH (ok=2, warn=5, fail=0, info=0)
- [x] Final verification - latest `amem doctor .` already reflects the current healthy state
- [ ] Final verification - re-run `amem doctor .` and confirm no remaining WARN / FAIL steps

## Action Sequence
1. Optional (recommended): Refactor flagged functions before adding more behavior, and add a short guiding comment when complex logic must remain in place.
1. Core (required): Re-run `amem profile-check .` and repair the missing profile-managed files.
2. Optional (recommended): Refactor flagged functions before adding more behavior, and add a short guiding comment when complex logic must remain in place.

## Onboarding Runbook
### Step 1: Core / profile_consistency
- Priority: `required`
- Trigger: missing required file: tests
- Action: Repair missing or drifted profile-managed files before continuing onboarding.
- Command: `amem profile-check .`
- Verify with: `amem profile-check .`
- Next command: `amem doctor .`
- Safe To Auto Execute: `False`
- Approval Required: `True`
- Approval Reason: this step diagnoses drift but manual repair choices still require a human decision
- Done when: `amem doctor .` shows `[OK] profile_consistency`.

## Group Health
### Core
- Summary: Core status=HEALTHY (ok=7, warn=0, fail=0, info=0)
- Summary: Core status=ATTENTION (ok=6, warn=0, fail=1, info=0)
- [OK] `registry` registered as 'synapse-network-sdk'
- [OK] `active` active=true
- [OK] `root` /Users/cliff/workspace/agent/Synapse-Network-Sdk
- [OK] `python3.12` /opt/homebrew/bin/python3.12
- [OK] `mcp_package` mcp import OK
- [OK] `profile_manifest` applied profile 'python-service'
- [OK] `profile_consistency` profile 'python-service' consistency OK
- [FAIL] `profile_consistency` missing required file: tests

### Planning
- Summary: Planning status=HEALTHY (ok=2, warn=0, fail=0, info=0)
Expand All @@ -38,8 +53,8 @@
- Summary: Optional status=WATCH (ok=2, warn=5, fail=0, info=0)
- [OK] `copilot_activation` Agents-Memory activation block present -> /Users/cliff/workspace/agent/Synapse-Network-Sdk/.github/copilot-instructions.md
- [OK] `agents_read_order` AGENTS.md references current bridge and 8 managed standard(s)
- [WARN] `refactor_watch` python/examples/smoke_test.py::main high complexity (lines=101>40, locals=12>8, branches=5, missing_guiding_comment)
- [WARN] `refactor_watch` python/synapse_client/test/test_consumer_e2e.py::test_python_sdk_consumer_cold_start_e2e high complexity (lines=134>40, locals=30>8, missing_guiding_comment)
- [WARN] `refactor_watch` python/synapse_client/test/test_consumer_e2e.py::_fund_and_deposit high complexity (lines=57>40, locals=15>8, missing_guiding_comment)
- [WARN] `refactor_watch` python/synapse_client/test/test_consumer_e2e.py::test_python_sdk_credential_management_e2e high complexity (lines=75>40, locals=25>8)
- [WARN] `refactor_watch` python/synapse_client/auth.py::SynapseAuth.issue_credential high complexity (branches=7>5, lines=38, locals=8, missing_guiding_comment)
- [WARN] `refactor_watch` python/examples/consumer_wallet_to_invoke.py::main high complexity (lines=78>40, branches=7>5, locals=18>8, nesting=3, missing_guiding_comment)
- [WARN] `refactor_watch` python/examples/smoke_test.py::main high complexity (lines=104>40, branches=6>5, locals=13>8, missing_guiding_comment)
- [WARN] `refactor_watch` python/examples/consumer_call_provider.py::main high complexity (lines=42>40, locals=10>8, branches=4, missing_guiding_comment)
- [WARN] `refactor_watch` python/synapse_client/test/test_consumer_e2e.py::test_python_sdk_consumer_cold_start_e2e high complexity (lines=135>40, locals=30>8, missing_guiding_comment)
- [WARN] `refactor_watch` python/examples/provider_staging_onboarding.py::main high complexity (lines=46>40, locals=9>8, missing_guiding_comment)
32 changes: 16 additions & 16 deletions docs/plans/refactor-watch.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,26 @@ Track Python functions that are already high-complexity or are approaching the c

## Hotspots

1. [WARN] `python/examples/smoke_test.py::main` line=376 metrics=(lines=101, branches=5, nesting=2, locals=12)
1. [WARN] `python/examples/consumer_wallet_to_invoke.py::main` line=74 metrics=(lines=78, branches=7, nesting=3, locals=18)
- token: `hotspot-664c48761084`
- issues: `lines=78>40, branches=7>5, locals=18>8, nesting=3, missing_guiding_comment`
- bundle command: `amem refactor-bundle . --token hotspot-664c48761084`
2. [WARN] `python/examples/smoke_test.py::main` line=345 metrics=(lines=104, branches=6, nesting=2, locals=13)
- token: `hotspot-8ec9b16a0f08`
- issues: `lines=101>40, locals=12>8, branches=5, missing_guiding_comment`
- issues: `lines=104>40, branches=6>5, locals=13>8, missing_guiding_comment`
- bundle command: `amem refactor-bundle . --token hotspot-8ec9b16a0f08`
2. [WARN] `python/synapse_client/test/test_consumer_e2e.py::test_python_sdk_consumer_cold_start_e2e` line=175 metrics=(lines=134, branches=0, nesting=0, locals=30)
3. [WARN] `python/examples/consumer_call_provider.py::main` line=116 metrics=(lines=42, branches=4, nesting=2, locals=10)
- token: `hotspot-c6270384bbbf`
- issues: `lines=42>40, locals=10>8, branches=4, missing_guiding_comment`
- bundle command: `amem refactor-bundle . --token hotspot-c6270384bbbf`
4. [WARN] `python/synapse_client/test/test_consumer_e2e.py::test_python_sdk_consumer_cold_start_e2e` line=174 metrics=(lines=135, branches=0, nesting=0, locals=30)
- token: `hotspot-402833792f1b`
- issues: `lines=134>40, locals=30>8, missing_guiding_comment`
- issues: `lines=135>40, locals=30>8, missing_guiding_comment`
- bundle command: `amem refactor-bundle . --token hotspot-402833792f1b`
3. [WARN] `python/synapse_client/test/test_consumer_e2e.py::_fund_and_deposit` line=77 metrics=(lines=57, branches=0, nesting=0, locals=15)
- token: `hotspot-7f5cb8d7d075`
- issues: `lines=57>40, locals=15>8, missing_guiding_comment`
- bundle command: `amem refactor-bundle . --token hotspot-7f5cb8d7d075`
4. [WARN] `python/synapse_client/test/test_consumer_e2e.py::test_python_sdk_credential_management_e2e` line=327 metrics=(lines=75, branches=1, nesting=1, locals=25)
- token: `hotspot-26c3a2e1a320`
- issues: `lines=75>40, locals=25>8`
- bundle command: `amem refactor-bundle . --token hotspot-26c3a2e1a320`
5. [WARN] `python/synapse_client/auth.py::SynapseAuth.issue_credential` line=198 metrics=(lines=38, branches=7, nesting=2, locals=8)
- token: `hotspot-4ede4034d9f9`
- issues: `branches=7>5, lines=38, locals=8, missing_guiding_comment`
- bundle command: `amem refactor-bundle . --token hotspot-4ede4034d9f9`
5. [WARN] `python/examples/provider_staging_onboarding.py::main` line=91 metrics=(lines=46, branches=2, nesting=1, locals=9)
- token: `hotspot-41fb390a7399`
- issues: `lines=46>40, locals=9>8, missing_guiding_comment`
- bundle command: `amem refactor-bundle . --token hotspot-41fb390a7399`

## Suggested Action

Expand Down
42 changes: 42 additions & 0 deletions docs/quality-gates.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
created_at: 2026-04-28
updated_at: 2026-04-28
doc_status: active
---

# SDK Quality Gates

This repository uses `bash scripts/ci/pr_checks.sh` as the single PR quality gate entrypoint. GitHub Actions and local validation must keep using that same script so PR behavior matches developer machines.

## Required Checks

- Repo hygiene: retired gateway domains, deprecated brand wording, README language split, staging defaults, 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.

## Thresholds

- Source files must be `500` lines or fewer.
- Test files may be up to `700` lines while the suite is being decomposed.
- Python functions may have at most `40` effective logic lines.
- Python Radon complexity must stay at grade `A` or `B`; grade `C` or worse fails CI.
- TypeScript ESLint complexity must be `8` or lower.
- TypeScript functions may have at most `60` effective lines.
- Python coverage must be at least `80%`.
- 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 `SynapseClient`, `SynapseAuth`, and `SynapseProvider` methods must return named SDK models/interfaces, never raw Python `dict` or TypeScript `Record<string, unknown>`. Internal HTTP payloads, schemas, and patch inputs may remain map-shaped.

## Refactor Rules

- If a source file exceeds `500` lines, split it before adding more behavior.
- If logic appears in three places, extract a shared helper or module.
- If a function exceeds `40` Python effective lines, `60` TypeScript lines, or the complexity threshold, split pure decisions from I/O and orchestration.
- Bug fixes need regression tests. New observable behavior needs unit tests.
- New consumer/owner/provider SDK methods need a named result model/interface before they are exposed publicly.
- Public SDK API changes must update docs and `docs/sdk/capability_inventory.md` when the implementation state changes.

## GitHub Enforcement

The `main` branch must require the PR CI status check named `SDK PR quality gates`, require the branch to be up to date, block direct pushes, and require at least one approving review before merge.
13 changes: 11 additions & 2 deletions docs/sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ The SDK currently has three explicit public surfaces:

Provider remains an owner-scoped supply-side role. `SynapseProvider` improves discoverability but does not introduce a second provider root identity.

Python quote-first methods `create_quote()`, `create_invocation()`, and `invoke_service()` are deprecated. They no longer call old endpoints and instead tell users to use discovery/search + `invoke(..., cost_usdc=...)`.
Owner/provider helper returns are typed SDK objects. Do not document or add public `SynapseAuth` / `SynapseProvider` methods that return raw Python `dict` or TypeScript `Record<string, unknown>`; add a named result model/interface instead.

Python quote-first methods `create_quote()`, `create_invocation()`, and `invoke_service()` are deprecated. They no longer call old endpoints and instead tell users to use discovery/search + `invoke(..., cost_usdc=...)` for fixed-price APIs.

LLM services use `serviceKind=llm` + `priceModel=token_metered`. Runtime code should call `invoke_llm()` / `invokeLlm()` and read `usage` plus `synapse` billing metadata. Do not pass `cost_usdc` / `costUsdc` for LLM calls; pass optional `max_cost_usdc` / `maxCostUsdc` or let Gateway compute the automatic hold. Streaming is disabled in V1.

## Staging Docs

Expand All @@ -51,6 +55,8 @@ The top README prioritizes the shortest TTFC path:
2. Generate Agent Key.
3. Agent runtime uses `SynapseClient` for discovery / invoke / receipt.

For public preview, treat the top README as the 5-minute SDK agent demo: Python and TypeScript both default to `staging`, then walk through discovery/search, invoke, receipt verification, and first-run troubleshooting.

Programmatic credential issuance is an advanced owner flow:

1. Owner wallet signs in.
Expand Down Expand Up @@ -95,7 +101,8 @@ Runtime calls should include:

1. `request_id` / request header for gateway log correlation.
2. `idempotency_key` / `idempotencyKey` to avoid duplicate charges or duplicate execution.
3. `cost_usdc` / `costUsdc` from latest discovery price. If price changes, the gateway rejects the call and the caller should rediscover.
3. For fixed-price APIs, pass `cost_usdc` / `costUsdc` from latest discovery price. If price changes, the gateway rejects the call and the caller should rediscover.
4. For token-metered LLM services, call `invoke_llm()` / `invokeLlm()` with optional `max_cost_usdc` / `maxCostUsdc`; final Provider `usage` drives the actual charge.

## Common Failures

Expand All @@ -122,6 +129,8 @@ Check:

The SDK maps `402` to balance, budget, or credential credit limit errors. Check account balance, credential budget, and daily cap rather than blindly retrying.

Plain-language marker for quickstart checks: 402 or budget errors mean the agent request reached billing guardrails and should be fixed by funding, credits, or credential budget changes before retrying.

## Shortest Verification Path

```bash
Expand Down
Loading
Loading