--- name: daniel-calendar-assistant description: Operate Daniel Calendar through its authenticated REST API. Use this guide for reliable calendar queries, creation, batch writes, edits, and verification. --- # Daniel Calendar Agent Skill ## Connection - API base: `https://calendar.hdaniel.studio/api/v1` - Send every request with `Authorization: Bearer `. - First call `GET /token/me`. Read `username`, `timezone`, and `scopes`. - Then call `GET /calendars`. Keep the returned calendar IDs and names for this conversation. **Every write must use the returned `id`, never a display name.** - Never expose the token in a reply, URL, event description, or log. ## Time and queries - Interpret dates and times in the account timezone returned by `/token/me`; if missing, use `Asia/Shanghai`. - “This week” means Monday through Sunday in that timezone. - Query event ranges with `YYYY-MM-DD`. The `end` date is exclusive. - Use `GET /events?start=YYYY-MM-DD&end=YYYY-MM-DD` before scheduling when conflicts or duplicate events matter. ## Creating events `POST /events` requires exactly these business fields: ```json { "calendar": "calendar_id_from_GET_calendars", "title": "Event title", "start": "2026-09-07T21:00:00+08:00", "end": "2026-09-08T05:30:00+08:00", "all_day": false, "location": "", "description": "", "reminder_minutes": 40 } ``` - The JSON field is named `calendar`, but its value **must be a calendar ID** returned by `GET /calendars`; never send a display name such as `课程` or `日常`. - `reminder_minutes` is optional; omit it if the user did not request a reminder. - A successful response is not enough for important writes: make one range query afterwards and verify title, time, calendar, description, all-day state, and reminder. ## Batch creation For multiple independent events, prefer `POST /events/batch`: ```json { "events": [{"calendar":"calendar_id_from_GET_calendars","title":"睡觉","start":"2026-09-07T23:00:00+08:00","end":"2026-09-08T07:00:00+08:00","all_day":false,"location":"","description":""}], "duplicate_policy": "skip", "atomic": true, "dry_run": false } ``` - First make a single range query spanning the whole import to detect duplicates. - Use `dry_run: true` for a preview only when the user asks for one. - `duplicate_policy: "skip"` avoids repeat imports. - Report `created`, `skipped`, and `failed` separately. Never count a validation failure as a created event. - If `atomic: true` returns a failure, state that the batch did not complete and inspect the response before retrying. ## Editing and deletion - Read the event first and preserve fields the user did not ask to change. - Update with `PATCH /api/v1/events/{event_id}`. Send the changed fields using the same names as event creation (`calendar`, `title`, `start`, `end`, `all_day`, `location`, `description`, `reminder_minutes`). ```json {"title":"更新后的标题","start":"2026-09-07T21:30:00+08:00","end":"2026-09-07T22:30:00+08:00"} ``` - Delete with `DELETE /api/v1/events/{event_id}`. - Confirm the target event unambiguously before edits or deletions, especially when titles repeat or deletion is requested. - Re-query the affected range after the operation. ## General interaction rules - Ask the user which calendar to use when it cannot be inferred. Resolve their chosen calendar name to its ID with `GET /calendars` before writing. - For a potentially ambiguous conversion, show a compact preview first. Once the user explicitly confirms, execute the confirmed version without asking the same question again. - Use neutral examples only. Do not invent personal schedules, calendar names, preferences, or recurring rules. ## Common pitfalls - Do not infer a token is write-capable from a successful read; use `scopes` from `/token/me`. - Do not use server UTC to decide “today” or “this week”. - Do not send undocumented field names such as `calendar_id`. - Do not blindly repeat slow per-event requests when `/events/batch` is available. - If the API returns `422`, explain that nothing was created, correct the invalid fields, then retry. ## Transport compatibility and resilient interaction - For direct command-line or code requests, prefer HTTPS over HTTP/1.1 (for example, add `--http1.1` when using curl). HTTP/2 is also supported. Never use plaintext HTTP for authenticated API requests. - A protocol choice does not bypass the Work environment's network-approval or outbound-network policy. - When a safe, bounded retry can resolve a transient transport or service error, retry quietly and do not burden the user with intermediate diagnostics. - If the operation still cannot be completed after appropriate checks, provide the actionable outcome without inventing a server fault. For ChatGPT Work failures that occur before an HTTP response is received, treat the user's local Work network permissions, workspace policy, or execution environment as the first troubleshooting direction.