Commit graph

3 commits

Author SHA1 Message Date
42b1516bc3 clients/php: v0.2 multi-turn Session API
- Session class with try/finally pattern + Client::session(callable) block helper
- Idempotent Session::close (in-memory + server idempotent)
- __destruct best-effort close fallback (errors logged via error_log, never raised)
- Client::createSession / ::session / ::listSessions / ::getSession
- TurnResult::text() helper concatenating text events
- TurnEvent value object preserves tool_call / thinking / text uniformly
- SessionState value object for list/get responses
- ClosedSessionException for use-after-close guard
- Session::__debugInfo redacts forge back-reference (no bearer in var_dump)
- tests/SessionTest.php: 15 tests covering create/close/turn/idempotency/exception/list/state/text/destruct/regression
- README "Multi-turn / Sessions (v0.2)" section + try/finally + block-form
  + __destruct + __debugInfo notes; exception tree updated

v0.1 surface unchanged — 44 existing ClientTest tests still green, +15 new
v0.2 tests in SessionTest. Client.php diff is purely additive (285 lines
appended, zero v0.1 lines touched).

Naming follows the existing PHP SDK convention: Clawdforge\Client (not the
spec's generic Sulkta\Clawdforge\Forge), with the new types living in the
same Clawdforge\ namespace and Exception\ClosedSessionException slotted
under the existing ForgeException tree.

Spec: memory/spec-clawdforge-v0.2.md
Server core: 940861f
2026-04-29 06:51:17 -07:00
7745c5eb5c clients/php: apply audit findings — token redaction + uploadStream + tests (1cff9b8 → next)
HIGH:
- H1: __debugInfo() redacts token on Client + AppToken; #[\SensitiveParameter]
  on Client constructor's $token param so PHP scrubs it from stack traces.

MEDIUM:
- M1: uploadStream(StreamInterface, filename, ttl) overload so callers
  handling form uploads have a non-path entry point. README warning above
  the API table on uploadFile path-trust.
- M2: RunRequest now rejects empty-string model/system in the constructor
  (callers should pass null/omit rather than '' to use defaults).
- M3: new MalformedResponseException extends ForgeException for
  "transport succeeded, body unparseable as expected JSON object". Decoupled
  from ApiException so callers can distinguish "server told me no" from
  "server replied 200 with garbage". README + ApiException docstring updated.
- M4: non-UTF-8 / malformed JSON now flows through M3's new exception.
- M5: ApiException error-message extraction falls back to json_encode
  (capped at 200 chars) when the error field is an object/array, so
  callers don't get empty messages on {"error":{"code":...,"msg":...}}.

LOW:
- L2: revokeToken now requires server response ok === true, raises
  MalformedResponseException on missing/false ok rather than silently
  returning true.
- L5: README WordPress snippet uses bare Client (matches the use line above).
- L7: 29 new tests — token redaction (3), uploadStream (2), empty
  model/system (2), MalformedResponseException across 7 scenarios incl.
  non-UTF-8, ApiException object-error formatting + 200-char cap, revoke
  ok=true requirement + ok=false + empty-name, RunRequest timeout bounds
  (3) + non-string/empty files entries (2), uploadFile unreadable-path
  + 4xx + 5xx, healthz 500, Authorization header asserted on every
  endpoint.

README polish: TLS verify=false caveat under "Custom HTTP client".

Audit memo: memory/clawdforge-audits/php-1cff9b8.md
2026-04-28 23:12:34 -07:00
1cff9b89d2 clients/php: initial PHP SDK for clawdforge
PHP 8.2+ Guzzle-based client mirroring the Python SDK surface:

- Client::healthz / run / uploadFile / createToken / listTokens / revokeToken
- Readonly value objects: RunRequest, RunResult, FileToken, AppToken
- Exception hierarchy: ForgeException (abstract) -> ApiException ->
  AuthException, plus TransportException
- camelCase PHP <-> snake_case wire conversion at the boundary
- Streamed multipart uploads via fopen($path, 'r')
- Injectable GuzzleHttp\ClientInterface (MockHandler-friendly)
- HTTP timeout = subprocess timeout + 30s margin
- 15 PHPUnit tests, 61 assertions, no live network
- README with Laravel + WordPress integration snippets
- MIT license, no Sulkta-specific assumptions
2026-04-28 22:41:02 -07:00