agent-once 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agent_once-0.1.0/.github/workflows/ci.yml +119 -0
- agent_once-0.1.0/.github/workflows/docs.yml +57 -0
- agent_once-0.1.0/.github/workflows/publish.yml +42 -0
- agent_once-0.1.0/.gitignore +17 -0
- agent_once-0.1.0/CHANGELOG.md +45 -0
- agent_once-0.1.0/CONTRIBUTING.md +36 -0
- agent_once-0.1.0/LICENSE +21 -0
- agent_once-0.1.0/PKG-INFO +421 -0
- agent_once-0.1.0/README.md +371 -0
- agent_once-0.1.0/SECURITY.md +9 -0
- agent_once-0.1.0/docs/backends.md +83 -0
- agent_once-0.1.0/docs/cli.md +36 -0
- agent_once-0.1.0/docs/concepts.md +128 -0
- agent_once-0.1.0/docs/hooks.md +70 -0
- agent_once-0.1.0/docs/index.md +49 -0
- agent_once-0.1.0/docs/integrations/crewai.md +50 -0
- agent_once-0.1.0/docs/integrations/index.md +20 -0
- agent_once-0.1.0/docs/integrations/langchain.md +55 -0
- agent_once-0.1.0/docs/integrations/mcp.md +57 -0
- agent_once-0.1.0/docs/integrations/openai-agents.md +71 -0
- agent_once-0.1.0/docs/integrations/pydantic-ai.md +61 -0
- agent_once-0.1.0/docs/quickstart.md +88 -0
- agent_once-0.1.0/docs/reference/integrations.md +21 -0
- agent_once-0.1.0/docs/reference/once.md +35 -0
- agent_once-0.1.0/docs/reference/stores.md +11 -0
- agent_once-0.1.0/docs/reference/verifiers.md +7 -0
- agent_once-0.1.0/docs/ttl.md +68 -0
- agent_once-0.1.0/docs/verifiers.md +110 -0
- agent_once-0.1.0/docs/why-not.md +34 -0
- agent_once-0.1.0/examples/crewai_example.py +40 -0
- agent_once-0.1.0/examples/langgraph_example.py +58 -0
- agent_once-0.1.0/examples/mcp_server.py +55 -0
- agent_once-0.1.0/examples/openai_agents_example.py +50 -0
- agent_once-0.1.0/examples/pydantic_ai_example.py +51 -0
- agent_once-0.1.0/examples/stripe_example.py +74 -0
- agent_once-0.1.0/mkdocs.yml +74 -0
- agent_once-0.1.0/pyproject.toml +79 -0
- agent_once-0.1.0/requirements-docs.txt +4 -0
- agent_once-0.1.0/src/once/__init__.py +38 -0
- agent_once-0.1.0/src/once/__main__.py +5 -0
- agent_once-0.1.0/src/once/_otel.py +57 -0
- agent_once-0.1.0/src/once/cli.py +172 -0
- agent_once-0.1.0/src/once/core.py +1088 -0
- agent_once-0.1.0/src/once/exceptions.py +53 -0
- agent_once-0.1.0/src/once/hooks.py +104 -0
- agent_once-0.1.0/src/once/integrations/__init__.py +1 -0
- agent_once-0.1.0/src/once/integrations/_wrap.py +81 -0
- agent_once-0.1.0/src/once/integrations/crewai.py +90 -0
- agent_once-0.1.0/src/once/integrations/langchain.py +102 -0
- agent_once-0.1.0/src/once/integrations/mcp.py +114 -0
- agent_once-0.1.0/src/once/integrations/openai_agents.py +118 -0
- agent_once-0.1.0/src/once/integrations/pydantic_ai.py +123 -0
- agent_once-0.1.0/src/once/key.py +32 -0
- agent_once-0.1.0/src/once/postgres.py +316 -0
- agent_once-0.1.0/src/once/py.typed +1 -0
- agent_once-0.1.0/src/once/store.py +405 -0
- agent_once-0.1.0/src/once/verifiers/__init__.py +11 -0
- agent_once-0.1.0/src/once/verifiers/_http.py +92 -0
- agent_once-0.1.0/src/once/verifiers/_stripe.py +237 -0
- agent_once-0.1.0/tests/conftest.py +48 -0
- agent_once-0.1.0/tests/test_async.py +382 -0
- agent_once-0.1.0/tests/test_basic.py +279 -0
- agent_once-0.1.0/tests/test_cli.py +145 -0
- agent_once-0.1.0/tests/test_concurrency.py +160 -0
- agent_once-0.1.0/tests/test_crash.py +116 -0
- agent_once-0.1.0/tests/test_edges.py +182 -0
- agent_once-0.1.0/tests/test_hooks.py +398 -0
- agent_once-0.1.0/tests/test_integrations.py +155 -0
- agent_once-0.1.0/tests/test_integrations_adapters.py +275 -0
- agent_once-0.1.0/tests/test_integrations_crewai.py +67 -0
- agent_once-0.1.0/tests/test_integrations_langchain.py +52 -0
- agent_once-0.1.0/tests/test_integrations_mcp.py +58 -0
- agent_once-0.1.0/tests/test_integrations_openai_agents.py +52 -0
- agent_once-0.1.0/tests/test_integrations_pydantic_ai.py +66 -0
- agent_once-0.1.0/tests/test_integrations_stripe.py +165 -0
- agent_once-0.1.0/tests/test_keys.py +79 -0
- agent_once-0.1.0/tests/test_otel.py +230 -0
- agent_once-0.1.0/tests/test_postgres.py +225 -0
- agent_once-0.1.0/tests/test_regressions.py +325 -0
- agent_once-0.1.0/tests/test_stateful.py +206 -0
- agent_once-0.1.0/tests/test_stress.py +89 -0
- agent_once-0.1.0/tests/test_timeout.py +108 -0
- agent_once-0.1.0/tests/test_ttl.py +513 -0
- agent_once-0.1.0/tests/test_verifiers_http.py +198 -0
- agent_once-0.1.0/tests/test_verifiers_stripe.py +450 -0
- agent_once-0.1.0/tests/test_verify.py +195 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
lint:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
timeout-minutes: 10
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
- uses: actions/setup-python@v5
|
|
14
|
+
with:
|
|
15
|
+
python-version: "3.12"
|
|
16
|
+
- run: pip install -e ".[dev,postgres,stripe]" mcp langchain-core langgraph
|
|
17
|
+
- run: ruff check .
|
|
18
|
+
- run: ruff format --check .
|
|
19
|
+
- run: mypy
|
|
20
|
+
|
|
21
|
+
# Linux runs every test against both SQLite and a Postgres service container.
|
|
22
|
+
test:
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
timeout-minutes: 15
|
|
25
|
+
strategy:
|
|
26
|
+
fail-fast: false
|
|
27
|
+
matrix:
|
|
28
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
29
|
+
services:
|
|
30
|
+
postgres:
|
|
31
|
+
image: postgres:17
|
|
32
|
+
env:
|
|
33
|
+
POSTGRES_PASSWORD: postgres
|
|
34
|
+
POSTGRES_DB: once_test
|
|
35
|
+
ports:
|
|
36
|
+
- 5432:5432
|
|
37
|
+
options: >-
|
|
38
|
+
--health-cmd "pg_isready -U postgres"
|
|
39
|
+
--health-interval 2s
|
|
40
|
+
--health-timeout 5s
|
|
41
|
+
--health-retries 30
|
|
42
|
+
env:
|
|
43
|
+
ONCE_TEST_POSTGRES_DSN: postgresql://postgres:postgres@localhost:5432/once_test
|
|
44
|
+
steps:
|
|
45
|
+
- uses: actions/checkout@v4
|
|
46
|
+
- uses: actions/setup-python@v5
|
|
47
|
+
with:
|
|
48
|
+
python-version: ${{ matrix.python-version }}
|
|
49
|
+
- run: pip install -e ".[dev,postgres]"
|
|
50
|
+
- run: pytest -q --cov=once --cov-report=term-missing
|
|
51
|
+
- if: matrix.python-version == '3.12'
|
|
52
|
+
run: pytest -q -m heavy tests/test_stress.py
|
|
53
|
+
|
|
54
|
+
# Service containers only run on Linux, so these skip the Postgres tests and
|
|
55
|
+
# leave postgres.py out of the coverage floor.
|
|
56
|
+
test-other:
|
|
57
|
+
runs-on: ${{ matrix.os }}
|
|
58
|
+
timeout-minutes: 15
|
|
59
|
+
strategy:
|
|
60
|
+
fail-fast: false
|
|
61
|
+
matrix:
|
|
62
|
+
os: [windows-latest, macos-latest]
|
|
63
|
+
steps:
|
|
64
|
+
- uses: actions/checkout@v4
|
|
65
|
+
- uses: actions/setup-python@v5
|
|
66
|
+
with:
|
|
67
|
+
python-version: "3.12"
|
|
68
|
+
- run: pip install -e ".[dev]"
|
|
69
|
+
- run: pytest -q --cov=once --cov-fail-under=0
|
|
70
|
+
- run: coverage report --omit="*postgres.py" --fail-under=95 --show-missing
|
|
71
|
+
|
|
72
|
+
integrations:
|
|
73
|
+
runs-on: ubuntu-latest
|
|
74
|
+
timeout-minutes: 15
|
|
75
|
+
strategy:
|
|
76
|
+
fail-fast: false
|
|
77
|
+
matrix:
|
|
78
|
+
mcp: ["mcp<2", "mcp>=2"]
|
|
79
|
+
steps:
|
|
80
|
+
- uses: actions/checkout@v4
|
|
81
|
+
- uses: actions/setup-python@v5
|
|
82
|
+
with:
|
|
83
|
+
python-version: "3.12"
|
|
84
|
+
- run: pip install -e ".[dev,stripe]" langchain-core langgraph "${{ matrix.mcp }}"
|
|
85
|
+
- run: pytest -q tests/test_integrations.py tests/test_integrations_mcp.py tests/test_integrations_langchain.py tests/test_integrations_stripe.py
|
|
86
|
+
- run: python examples/stripe_example.py
|
|
87
|
+
- run: python examples/langgraph_example.py
|
|
88
|
+
- run: python examples/mcp_server.py --demo
|
|
89
|
+
- run: pytest -q -m heavy tests/test_stress.py
|
|
90
|
+
|
|
91
|
+
# One environment per framework, since their pins conflict (crewai wants openai<3).
|
|
92
|
+
adapters:
|
|
93
|
+
runs-on: ubuntu-latest
|
|
94
|
+
timeout-minutes: 15
|
|
95
|
+
strategy:
|
|
96
|
+
fail-fast: false
|
|
97
|
+
matrix:
|
|
98
|
+
include:
|
|
99
|
+
- framework: openai_agents
|
|
100
|
+
extra: openai-agents
|
|
101
|
+
- framework: pydantic_ai
|
|
102
|
+
extra: pydantic-ai
|
|
103
|
+
- framework: crewai
|
|
104
|
+
extra: crewai
|
|
105
|
+
env:
|
|
106
|
+
CREWAI_DISABLE_TELEMETRY: "true"
|
|
107
|
+
OTEL_SDK_DISABLED: "true"
|
|
108
|
+
PYDANTIC_AI_NO_BANNER: "1"
|
|
109
|
+
steps:
|
|
110
|
+
- uses: actions/checkout@v4
|
|
111
|
+
- uses: actions/setup-python@v5
|
|
112
|
+
with:
|
|
113
|
+
python-version: "3.12"
|
|
114
|
+
- run: pip install -e ".[dev,${{ matrix.extra }}]"
|
|
115
|
+
- run: python examples/${{ matrix.framework }}_example.py
|
|
116
|
+
- run: pytest -q tests/test_integrations_${{ matrix.framework }}.py tests/test_integrations_adapters.py
|
|
117
|
+
- run: >-
|
|
118
|
+
mypy --python-version 3.12 src/once/integrations/${{ matrix.framework }}.py
|
|
119
|
+
tests/test_integrations_${{ matrix.framework }}.py examples/${{ matrix.framework }}_example.py
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: Docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: docs-${{ github.ref }}
|
|
14
|
+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
build:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
timeout-minutes: 10
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
- uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.12"
|
|
25
|
+
- run: pip install -r requirements-docs.txt
|
|
26
|
+
- run: mkdocs build --strict
|
|
27
|
+
- if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
|
|
28
|
+
uses: actions/upload-pages-artifact@v3
|
|
29
|
+
with:
|
|
30
|
+
path: site
|
|
31
|
+
|
|
32
|
+
deploy:
|
|
33
|
+
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
|
|
34
|
+
needs: build
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
timeout-minutes: 10
|
|
37
|
+
permissions:
|
|
38
|
+
pages: write
|
|
39
|
+
id-token: write
|
|
40
|
+
environment:
|
|
41
|
+
name: github-pages
|
|
42
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
43
|
+
steps:
|
|
44
|
+
# Skip, don't fail, until Settings > Pages > Source is set to GitHub Actions.
|
|
45
|
+
- id: pages
|
|
46
|
+
env:
|
|
47
|
+
GH_TOKEN: ${{ github.token }}
|
|
48
|
+
run: |
|
|
49
|
+
if gh api "repos/$GITHUB_REPOSITORY/pages" > /dev/null 2>&1; then
|
|
50
|
+
echo "enabled=true" >> "$GITHUB_OUTPUT"
|
|
51
|
+
else
|
|
52
|
+
echo "::notice::GitHub Pages is not enabled, skipping deploy"
|
|
53
|
+
echo "enabled=false" >> "$GITHUB_OUTPUT"
|
|
54
|
+
fi
|
|
55
|
+
- id: deployment
|
|
56
|
+
if: steps.pages.outputs.enabled == 'true'
|
|
57
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
timeout-minutes: 10
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.12"
|
|
20
|
+
- run: pip install build twine
|
|
21
|
+
- run: python -m build
|
|
22
|
+
- run: twine check --strict dist/*
|
|
23
|
+
- uses: actions/upload-artifact@v4
|
|
24
|
+
with:
|
|
25
|
+
name: dist
|
|
26
|
+
path: dist/
|
|
27
|
+
|
|
28
|
+
publish:
|
|
29
|
+
needs: build
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
timeout-minutes: 10
|
|
32
|
+
environment:
|
|
33
|
+
name: pypi
|
|
34
|
+
url: https://pypi.org/p/agent-once
|
|
35
|
+
permissions:
|
|
36
|
+
id-token: write
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/download-artifact@v4
|
|
39
|
+
with:
|
|
40
|
+
name: dist
|
|
41
|
+
path: dist/
|
|
42
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 (unreleased)
|
|
4
|
+
|
|
5
|
+
First release.
|
|
6
|
+
|
|
7
|
+
- `Once` with `@once.tool`, `execute` and `aexecute`, backed by SQLite.
|
|
8
|
+
- Records move through pending, done, failed and unknown. Failed and unknown are never re-run on their own.
|
|
9
|
+
- `verify` callbacks and `stale_after` to resolve unknown and abandoned pending records.
|
|
10
|
+
- Async tools, `timeout=`, cancellation marks unknown. Sync and async callers in one process wait for each other.
|
|
11
|
+
- `once` command line tool: `ls`, `show`, `reset`, `gc`. `Once.records()` and `Once.purge()`.
|
|
12
|
+
- `Once.close()`, and `Once` works as a context manager.
|
|
13
|
+
- `exclude=` on `once.tool` to leave parameters out of the key.
|
|
14
|
+
- `once.integrations.mcp` and `once.integrations.langchain` decorators, with examples.
|
|
15
|
+
- `once.integrations.openai_agents`, `once.integrations.pydantic_ai` and `once.integrations.crewai` decorators, with examples and extras. The `crewai` and `openai-agents` extras can't be installed together. Pydantic AI tools take their scope from `scope_arg`, then `scope_from(ctx)`, then the enclosing `once.scope()` (read with `current_scope()`), then `ctx.conversation_id`, or `ctx.run_id` with `scope="run"`.
|
|
16
|
+
- The framework helpers take `ttl=`.
|
|
17
|
+
- `PostgresStore` for workers on several machines, behind the `postgres` extra. Use `Once("postgresql://...")` or `Once(store=PostgresStore(dsn, table=...))`. The CLI accepts a Postgres URL for `--db` and has a `--table` option.
|
|
18
|
+
- `Store` protocol, so `Once(store=...)` takes any backend that implements it.
|
|
19
|
+
- `once.verifiers`: `stripe_verifier` and `stripe_params` for Stripe charges, PaymentIntents and refunds (`stripe` extra, or pass a client), and `http_verifier` for any API that can look an effect up by key. `stripe_verifier` falls back to listing when search isn't available to the account.
|
|
20
|
+
- `ttl=` on `Once`, `@once.tool`, `execute` and `aexecute`. Done records expire and the next call runs again; failed and unknown never expire. Stored in a new `expires_at` column, added to existing SQLite and Postgres tables on open. `once gc --expired` and `Once.purge(expired=True)` delete expired records.
|
|
21
|
+
- `current_scope()` returns the active `once.scope()` value. An `idempotency_key` parameter that gets `""` or `None` now means "no key", so one is computed. A `""` default used to become the key itself, so two tools with that default hit `KeyConflict`.
|
|
22
|
+
- `expires_at` is indexed in both stores, so `gc --expired` doesn't scan the whole table. The index is added to existing tables on open.
|
|
23
|
+
- `Once(hooks=Hooks(...))` with `on_claim`, `on_done`, `on_failed`, `on_unknown` and `on_replay`. Hooks get an `Event`, may be async under `aexecute`, and an error in one is logged, not raised.
|
|
24
|
+
- OpenTelemetry spans (`once <tool_name>`) behind the `otel` extra. No-op without a configured tracer.
|
|
25
|
+
|
|
26
|
+
Fixes from a review before the release:
|
|
27
|
+
|
|
28
|
+
- A sync call with `timeout=` runs in a thread that keeps the caller's context, so `once.scope()` and tracing still apply inside it.
|
|
29
|
+
- A `ttl` that would expire after year 9999 is treated as never expiring instead of raising `OverflowError`.
|
|
30
|
+
- A claim is given back if the call is interrupted (or an async store step is cancelled) before the tool starts, so the key isn't left pending.
|
|
31
|
+
- Storing the outcome is retried once after a store error, so a dropped connection doesn't leave a finished call pending.
|
|
32
|
+
- Calling the same key from inside its own call raises `OnceError` instead of deadlocking. This includes a sync call inside an async owner.
|
|
33
|
+
- `exclude=` names that are not parameters of the function raise an error.
|
|
34
|
+
- `EffectUnknown` is raised even if the record was reset while the call was finishing.
|
|
35
|
+
- `stripe_verifier` reads the status of the object it finds: failed or canceled counts as not happened, and a status still in flux raises `StripeInconclusive` so the record stays unknown. It also stays unknown when the list scan runs out before the end.
|
|
36
|
+
- `http_verifier` JSON-encodes non-string arguments in the URL, and rejects an argument named `key` that would clash with `{key}`.
|
|
37
|
+
- `PostgresStore` takes `statement_timeout` (30 seconds by default) and retries a statement once after a dropped connection. Postgres URLs are accepted in any case and with `+psycopg`.
|
|
38
|
+
- The CLI refuses SQLite files without an effects table and rejects a negative `--limit`.
|
|
39
|
+
- JSON errors name the argument or the verify function that couldn't be serialized.
|
|
40
|
+
- README and docs have a Gotchas section.
|
|
41
|
+
|
|
42
|
+
Changes made before the release that break keys from earlier development builds:
|
|
43
|
+
|
|
44
|
+
- `make_key` is now `sha256(canonical_json([tool_name, args, scope]))`. It used to concatenate the parts, which let some tool names and scopes collide.
|
|
45
|
+
- `canonical_json` now escapes non-ASCII characters (`ensure_ascii=True`), so strings with lone surrogates can be hashed.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Bug reports and pull requests are welcome. For anything bigger than a small fix, open an issue first so we can agree on the approach.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
python -m venv .venv
|
|
9
|
+
.venv/bin/pip install -e '.[dev,postgres,stripe]'
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Checks
|
|
13
|
+
|
|
14
|
+
CI runs these, so run them before opening a pull request:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
.venv/bin/ruff format --check .
|
|
18
|
+
.venv/bin/ruff check .
|
|
19
|
+
.venv/bin/mypy src tests
|
|
20
|
+
.venv/bin/python -m pytest
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The Postgres tests are skipped unless `ONCE_TEST_POSTGRES_DSN` points at a database they can create tables in, for example `postgresql://postgres:postgres@localhost:5432/once_test`. Slow stress tests are marked `heavy` and run with `pytest -m heavy`.
|
|
24
|
+
|
|
25
|
+
The docs site is MkDocs Material:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
pip install -r requirements-docs.txt
|
|
29
|
+
mkdocs serve
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Pull requests
|
|
33
|
+
|
|
34
|
+
- Add a test for a bug fix or new behavior.
|
|
35
|
+
- Update the README, the docs and `CHANGELOG.md` when behavior changes.
|
|
36
|
+
- Keep changes to stored keys and the table schema backward compatible, or say clearly in the changelog that they are not.
|
agent_once-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 frogscooper
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|