packetdial: add gated call-queue + time-frame edit wrappers (live-verified)

Added write wrappers, each tested create→update→delete on the arizonacomputerguru test
domain (sanctioned, non-production):
- call queues: create-callqueue, update-callqueue, delete-callqueue + add-agent /
  update-agent / remove-agent
- time frames: create-timeframe, update-timeframe, delete-timeframe (body-discriminated —
  same path, server selects the op from the body; wrappers pass --body verbatim)

All behind --confirm (gate verified: DRY RUN refuses without it). SKILL.md documents the
bodies + the days-of-week-needs-array gotcha + names ACG as the test bed; capability map
+ api.md history updated. No production objects touched; no test leftovers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-22 07:44:30 -07:00
parent 25b2ff45bf
commit f42f9c2419
4 changed files with 139 additions and 2 deletions

View File

@@ -84,6 +84,39 @@ bash "$CLAUDETOOLS_ROOT/.claude/scripts/py.sh" ns.py update-user acme 101 --body
bash "$CLAUDETOOLS_ROOT/.claude/scripts/py.sh" ns.py delete-user acme 101 --confirm
```
### Call queue edits (live-verified create→update→delete, 2026-06-22)
```bash
# create — body MUST include synchronous + callqueue (the queue extension/id)
ns.py create-callqueue acme --body '{"synchronous":"yes","callqueue":"8000","description":"Support"}' --confirm
ns.py update-callqueue acme 8000 --body '{"description":"Support (2nd shift)","callqueue-dispatch-type":"Round-robin"}' --confirm
ns.py delete-callqueue acme 8000 --confirm
# agents on a queue
ns.py add-agent acme 8000 --body '{"callqueue-agent-id":"101@acme"}' --confirm
ns.py update-agent acme 8000 101@acme --body '{"callqueue-agent-dispatch-order-ordinal":1}' --confirm
ns.py remove-agent acme 8000 101@acme --confirm
```
### Time frame edits (live-verified create→update→delete, 2026-06-22)
Timeframes are **body-discriminated** — same path, the server picks the operation from the
body. The id arg is the `timeframe-id` (from `ns.py timeframes <domain>`).
```bash
# create: timeframe-type = always | days-of-week | specific-dates | holiday | custom
ns.py create-timeframe acme --body '{"synchronous":"yes","timeframe-name":"After Hours","timeframe-type":"always"}' --confirm
# update: the body carries the type-specific array OR a type-convert:
ns.py update-timeframe acme <timeframe-id> --body '{"update-only":"yes","timeframe-days-of-week-array":[...]}' --confirm
ns.py update-timeframe acme <timeframe-id> --body '{"type":"days-of-week"}' --confirm # convert type
# delete: no body = delete the whole timeframe; {"child_id":N} = delete one entry
ns.py delete-timeframe acme <timeframe-id> --confirm
```
**Gotcha:** a `days-of-week` (or other entry-bearing) timeframe rejects creation without its
entry array (`HTTP 400 "...should have at most 1 days of week entry"`) — create `always` first
and convert, or include the array in the create body. The **`arizonacomputerguru` domain is the
sanctioned test bed** (not in production use) for exercising these writes safely.
## Raw escape hatch (any of the 239 v2 paths)
The named commands cover the common surface; for anything else, hit the path
@@ -105,8 +138,8 @@ The live OpenAPI spec is **NetSapiens API v2 v44.4.10** — **239 paths / 354 op
| `users` (+ `/devices`, answerrules, voicemail, contacts under a user) | R/W, biggest surface | `users`, `user`, `devices`, `create/update/delete-user` | per-user devices live at `users/{u}/devices` |
| `phonenumbers` (DIDs + dial-rule routing) | R/W | `dids`, `create-did` | |
| `phones` (SIP devices, MAC provisioning) | R/W | `phones`, `create-phone` | |
| `callqueues` (ACD: agents, dispatch, live stats) | R/W + PATCH | `callqueues` (read) | writes via `raw` |
| `timeframes` (business-hours / holiday schedules) | R/W | `timeframes` (read) | writes via `raw` |
| `callqueues` (ACD: agents, dispatch, live stats) | R/W + PATCH | `callqueues` + `create/update/delete-callqueue`, `add/update/remove-agent` | full CRUD wrapped (verified) |
| `timeframes` (business-hours / holiday schedules) | R/W | `timeframes` + `create/update/delete-timeframe` | body-discriminated; CRUD wrapped (verified) |
| `autoattendants` (IVR menus) | R/W | `autoattendants` (read) | |
| `sites` (multi-site) | R/W | `sites` (read) | |
| `contacts` (domain address book) | R/W | `contacts` (read) | |