@aitne-sh/aitne 0.1.13 → 0.1.14

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.
@@ -22,8 +22,8 @@ is the way to register repeating autonomous **work** — creating a recurring
22
22
  | A recurring scheduled **DM / briefing** ("DM me a summary every morning") | `schedule` skill → `POST /api/recurring-schedules` `taskType:dm_session` |
23
23
  | A background fetch of app data on a cadence (managed-task fetch windows) | `managed-tasks` skill |
24
24
 
25
- If the request is one-time, STOP and use the `schedule` skill. If it just sends a
26
- recurring DM with no autonomous work, use `dm_session` (above), not an Agent.
25
+ One-time? STOP `schedule` skill. Just a recurring DM with no autonomous work?
26
+ Use `dm_session` (above), not an Agent.
27
27
 
28
28
  ## Before creating — dedup (mandatory)
29
29
 
@@ -52,6 +52,7 @@ curl -s -X POST http://localhost:8321/api/agents \
52
52
  "timezone": "Asia/Tokyo"
53
53
  },
54
54
  "backend": { "tier": "medium" },
55
+ "limits": { "max_turns": 30, "max_budget_usd": 1.0, "timeout_minutes": 15 },
55
56
  "success_criteria": [
56
57
  { "id": "triage-note", "kind": "file_exists", "target": "notes/inbox-triage-{date}.md" }
57
58
  ],
@@ -69,15 +70,13 @@ Fields:
69
70
  - **`schedule.kind`** — `"recurring"` (structured, preferred) or `"cron"` (raw
70
71
  expression). A `one_shot`/`event` schedule is rejected with
71
72
  `one_shot_not_supported` (use `/schedule` for one-time work). Note:
72
- `"recurring"` is an **API-input convenience only** — the daemon converts the
73
- `recurrence` object to a cron expression and persists it as `kind: "cron"`.
74
- The Agent's on-disk `agent.md` frontmatter (and the dashboard editor) therefore
75
- only ever show `schedule.kind ∈ { cron, one_shot, event }`; there is no stored
76
- `"recurring"` kind to read back or PATCH.
73
+ `"recurring"` is an **API-input convenience only** — the daemon converts it to a
74
+ cron expression and persists `kind: "cron"`, so the stored `agent.md` (and the
75
+ dashboard editor) only ever show `cron`; there is no `"recurring"` to read back.
77
76
  - **`schedule.recurrence`** (when `kind:"recurring"`) — a structured recurrence:
78
77
  - `{ "frequency": "hourly", "intervalHours": 1, "minuteOfHour": 0 }` — every hour
79
- at :00 (`intervalHours` 1–23 for every-N-hours). **Sub-hourly (e.g. every
80
- 30 min) is not supported** for user Agents.
78
+ at :00 (`intervalHours` 1–23 for every-N-hours). **Sub-hourly is not
79
+ supported** for user Agents.
81
80
  - `{ "frequency": "daily", "time": "09:00" }`
82
81
  - `{ "frequency": "weekly", "time": "08:00", "daysOfWeek": [1] }` — 0=Sun…6=Sat.
83
82
  - `{ "frequency": "monthly", "time": "18:00", "daysOfMonth": [1] }`
@@ -85,24 +84,27 @@ Fields:
85
84
  them and fix the named field.
86
85
  - **`schedule.expression`** (when `kind:"cron"`) — a standard 5-field cron string
87
86
  in the resolved timezone (`min hour day-of-month month day-of-week`). Examples:
88
- `0 9 * * *` (daily 09:00), `0 8 * * 1` (Mondays 08:00), `0 * * * *` (hourly at
89
- :00), `0 */2 * * *` (every 2 hours), `0 18 1 * *` (1st of each month 18:00).
90
- A syntactically-valid cron is accepted at create (`201`, valid row) even if it
91
- cannot be mapped to a recurrence but a non-mappable shape (sub-hourly steps
92
- like `*/30`, hour ranges/lists like `9-17`) is never paired and silently never
93
- fires. Only shapes that map are actually run: minute a single value; hour a
94
- single value or `*` / `*/N`. Pick one explicit, mappable cadence.
87
+ `0 9 * * *` (daily 09:00), `0 8 * * 1` (Mondays 08:00), `0 */2 * * *` (every 2h),
88
+ `0 18 1 * *` (1st of month 18:00). Only mappable shapes actually fire: minute a
89
+ single value; hour a single value or `*` / `*/N`. A non-mappable shape (`*/30`,
90
+ ranges like `9-17`) is accepted at create but silently never fires pick one
91
+ explicit, mappable cadence.
95
92
  - **`schedule.timezone`** — IANA zone; omit to inherit the daemon default.
96
93
  - **`schedule.defer_in_quiet_hours`** — boolean, default `false`. When `true`, a
97
- firing that lands inside the user's quiet hours is pushed to the window's end
98
- instead of running — the whole run moves, so the data is fresh at delivery
99
- time. Mechanical rule: **set `true` whenever the Expected output includes
100
- DMing the user**; leave it `false` for silent file-writing work deliberately
101
- scheduled overnight.
94
+ firing inside the user's quiet hours is pushed to the window's end (the whole run
95
+ moves, so data is fresh at delivery). Mechanical rule: **set `true` whenever the
96
+ Expected output includes DMing the user**; `false` for silent overnight file work.
102
97
  - **`backend`** — optional. `tier` is `lite`/`medium`/`high` (cost/capability knob;
103
- the standalone control that works). `process_key` defaults to `agent.task`;
104
- omit unless you know you need another. (Pinning a backend *engine* without a
105
- `model` is a known no-op — prefer `tier`.)
98
+ the standalone control that works). `process_key` defaults to `agent.task`; omit
99
+ unless you know you need another. (Pinning an *engine* without a `model` is a
100
+ known no-op — prefer `tier`.)
101
+ - **`limits`** — optional per-firing caps: `max_turns` (default `20`),
102
+ `max_budget_usd` (soft cost cap, default `0.25`), `timeout_minutes` (default
103
+ `10`). Defaults are tight; a research/briefing Agent that runs several searches
104
+ and writes a note wants more, e.g. `{ "max_turns": 40, "max_budget_usd": 1.5,
105
+ "timeout_minutes": 20 }`. **Set them here at create time** — omitting the block
106
+ silently applies the defaults, and (like other user-Agent fields) limits are
107
+ changed afterward only by editing the `agent.md`, not via `PATCH /api/agents`.
106
108
  - **`playbooks`** — optional array of operating-playbook slugs to inject into the
107
109
  Agent's prompt at fire time: `research`, `markdown-note`, `monitoring`. Declaring
108
110
  one makes the daemon inject that playbook's full methodology into every run — a
@@ -155,17 +157,14 @@ a run-time autonomy boundary, and a verification receipt:
155
157
 
156
158
  {{> ref:prompt-frame-extended }}
157
159
 
158
- The `# Output` decision feeds one schedule field: if the output contract
159
- includes DMing the user, also set `schedule.defer_in_quiet_hours: true` so a
160
- firing inside quiet hours waits for the window's end instead of producing a
161
- message that would be held anyway.
160
+ Reminder: if the `# Output` includes DMing the user, set
161
+ `schedule.defer_in_quiet_hours: true` (see the schedule field above).
162
162
 
163
163
  ## Success criteria — derive them from `# Output`
164
164
 
165
- `success_criteria` are deterministic checks the daemon evaluates after every
166
- firing; their hit rate is the Agent's dashboard quality metric without them
167
- the Agent has **no quality signal**. Derive 1–3 mechanically from the `# Output`
168
- contract at creation time:
165
+ `success_criteria` are deterministic checks the daemon runs after every firing;
166
+ their hit rate is the Agent's dashboard quality metric (without them it has **no
167
+ quality signal**). Derive 1–3 mechanically from the `# Output` contract:
169
168
 
170
169
  - Writes a dated note → `{ "id": "note-exists", "kind": "file_exists",
171
170
  "target": "notes/<name>-{date}.md" }`. Targets are vault-relative; `{date}`
@@ -175,34 +174,38 @@ contract at creation time:
175
174
  counts headings of exactly `heading_level`.
176
175
  - DMs the user → `{ "id": "dm-delivered", "kind": "notification_log",
177
176
  "notification_type": "agent", "delivered_within_minutes": M }` — size `M` to
178
- the run (30–60 typical). Caveat: matching is install-wide within the window
179
- (ANY delivered `"agent"` notification counts, not just this Agent's), so
180
- prefer the file-based kinds whenever the output also lands in a file.
177
+ the run (30–60 typical). Caveat: matching is install-wide (ANY delivered
178
+ `"agent"` notification in the window counts) prefer file-based kinds when the
179
+ output also lands in a file.
180
+ - Mutates state (no file) → `{ "id": "acted", "kind": "agent_action_count",
181
+ "action_type": "…", "min": N }` — ≥ N logged actions of `action_type`; the
182
+ signal for **operational Agents**.
181
183
 
182
184
  `id` values must be unique within the Agent (duplicates are rejected as
183
185
  `invalid_definition` on `success_criteria[i].id`).
184
186
 
185
187
  ## Responses & errors
186
188
 
187
- - `201 { "status": "created", "slug": "…" }` the Agent is live; its recurring
188
- schedule is paired and it will fire on the next matching tick. The response may
189
- also carry `warnings[]` (non-blocking authoring lint e.g. a missing
190
- `# Instruction` section, a playbook you named but didn't declare, or an
191
- `# Output` contract with no `success_criteria`); the Agent is still created,
192
- but fix the flagged issues and re-save its `agent.md`.
193
- - `400 one_shot_not_supported` the schedule was not `cron`/`recurring`. Use the
194
- `schedule` skill for one-time tasks.
195
- - `400 invalid_recurrence` — a `kind:"recurring"` schedule carried a malformed
196
- `recurrence`. Read `issues[]` (each `{ field, message }`), fix the named field,
197
- and resubmit.
198
- - `409 slug_collision` — pick a different slug.
199
- - `400 invalid_definition` — the assembled definition failed validation. Two
200
- shapes share this error: pre-write schema validation returns `hint` +
201
- `issues[]` (each `{ field, message }`); the post-write cross-check (loader
202
- rejects the freshly written file) returns `slug` + a single `detail` string
203
- (or `null`). Read `issues[]` if present, else fall back to `detail`, fix the
204
- reported field(s), and resubmit. An empty/placeholder `prompt` also lands
205
- here — get the real task from the user, never retry with another stub.
189
+ Every error is `{ "error": "<code>", "hint"?: "…", "field"?: "…", "issues"?:
190
+ [{ field, message }] }`. **Read `hint` (what to do), `field` / `issues` (what to
191
+ fix), then resubmit** almost every failure is a one-field fix the response
192
+ spells out, so retry after correcting rather than giving up.
193
+
194
+ - `201 { "status": "created", "slug": "…" }` — live; the recurring schedule is
195
+ paired and fires on the next tick. May carry `warnings[]` (non-blocking lint:
196
+ missing `# Instruction`, an undeclared playbook, or `# Output` with no
197
+ `success_criteria`)created anyway, but fix + re-save the `agent.md`.
198
+ - `400 slug_required` / `name_required` / `schedule_required` a required field
199
+ was missing/empty; `field` + `hint` name the one to add.
200
+ - `400 one_shot_not_supported` — schedule wasn't `cron`/`recurring`; one-time work
201
+ goes to the `schedule` skill.
202
+ - `400 invalid_recurrence` malformed `recurrence`; fix each `issues[]` field.
203
+ - `409 slug_collision` that slug exists (`GET /api/agents` to inspect); pick
204
+ another, or edit the existing Agent rather than recreating it.
205
+ - `400 invalid_definition` — schema or loader cross-check failure. Read `issues[]`
206
+ if present, else the single `detail` string (also mirrored into `hint`). An
207
+ empty/placeholder `prompt` lands here too — get the real task from the user,
208
+ never retry with a stub.
206
209
 
207
210
  Read `Read`-only files you reference in the prompt to confirm they exist before
208
211
  creating the Agent.
@@ -38,8 +38,11 @@ curl -s http://localhost:8321/api/context/list/plans/projects
38
38
 
39
39
  Response: `{ "files": [{ "name", "lastModified" }, …] }`. Use this to
40
40
  enumerate `plans/projects/`, `journal/weekly/`, `journal/monthly/`,
41
- `identity/`, `policies/`, `policies/routines/`, `state/inbox/` before
42
- deciding a write target.
41
+ `identity/`, `policies/`, `policies/routines/`, `state/inbox/`,
42
+ `knowledge/sources/` before deciding a write target.
43
+ For `plans/projects` each project entry additionally carries
44
+ `meta: { "title", "state" }` (frontmatter/H1 summary; `_`-prefixed
45
+ files omit it).
43
46
 
44
47
  ### GET /api/context/today/reconciliation
45
48
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aitne-sh/aitne",
3
- "version": "0.1.13",
3
+ "version": "0.1.14",
4
4
  "description": "Aitne — a local-first, proactive personal AI agent. A long-running TypeScript daemon is the nervous system; Claude Code (or Codex / Gemini CLI) is the brain. All persistent memory lives in local Markdown files.",
5
5
  "keywords": [
6
6
  "ai",
@@ -43,9 +43,9 @@
43
43
  "README.md"
44
44
  ],
45
45
  "dependencies": {
46
- "@aitne/daemon": "0.1.13",
47
- "@aitne/dashboard": "0.1.13",
48
- "@aitne/shared": "0.1.13"
46
+ "@aitne/dashboard": "0.1.14",
47
+ "@aitne/shared": "0.1.14",
48
+ "@aitne/daemon": "0.1.14"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@typescript-eslint/eslint-plugin": "^8.58.1",