v0.3.0: rename app Daybook -> AgentFeed
Removes the "Daybook" name from everything user- and agent-facing, since no agents are configured yet and this is the cheap moment to do it. - UI brand, docs, README, CLAUDE.md -> AgentFeed. - Ingest env vars DAYBOOK_URL/TOKEN/SOURCE/DATA_DIR/BIND_ADDR/HOST_DATA_DIR/ KEY_PROVISIONING_API -> AGENTFEED_* (token *values* unchanged). - Skill: skills/daybook-posting -> skills/agentfeed-posting, daybook_post.py -> agentfeed_post.py (+ scripts/ wrapper and its test). - static/daybook.css -> static/agentfeed.css; localStorage daybook.* -> agentfeed.*; templatetag daybook_extras -> agentfeed_extras; multipart boundaries; json/csv viewer element ids; daybook_exception_handler -> agentfeed_exception_handler; compose service/container -> agentfeed. - Key-provisioning API now OFF by default (independent of DEBUG); enable with AGENTFEED_KEY_PROVISIONING_API=1 on test installs only. - Posting helper now points at Settings -> API Keys. Deferred on purpose (a later, separate step): the Django package `daybook_project`, the `/opt/daybook` install path, and the Forgejo repo name. The sibling AGENT_DAYBOOK__LLM_TEST name is intentionally untouched. Full suite: 129 passing; live server verified serving under the new name. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
4cacd8f64e
commit
d30e2436ab
39 changed files with 303 additions and 284 deletions
|
|
@ -1,13 +1,13 @@
|
|||
---
|
||||
name: daybook-posting
|
||||
description: Use when you have produced a finished deliverable such as a report, summary, brief, diagram, generated HTML, PDF, deck, or status update that a human should review later outside this chat. Publishes the artifact to a Daybook instance and returns a URL.
|
||||
name: agentfeed-posting
|
||||
description: Use when you have produced a finished deliverable such as a report, summary, brief, diagram, generated HTML, PDF, deck, or status update that a human should review later outside this chat. Publishes the artifact to a AgentFeed instance and returns a URL.
|
||||
---
|
||||
|
||||
# Daybook Posting
|
||||
# AgentFeed Posting
|
||||
|
||||
Daybook is a private artifact journal for completed agent outputs. It stores, indexes, and displays artifacts for human review. It does not execute commands, run workflows, or continue conversations.
|
||||
AgentFeed is a private artifact journal for completed agent outputs. It stores, indexes, and displays artifacts for human review. It does not execute commands, run workflows, or continue conversations.
|
||||
|
||||
You post to a **running Daybook server**, which may be anywhere — a cloud VM, a container, or a workstation. You do **not** need a checkout of Daybook's source. The only things that tie you to a particular instance are two environment variables: `DAYBOOK_URL` (where the server is) and `DAYBOOK_TOKEN` (who you are). Set those and the rest of this skill works unchanged regardless of where you or the server run.
|
||||
You post to a **running AgentFeed server**, which may be anywhere — a cloud VM, a container, or a workstation. You do **not** need a checkout of AgentFeed's source. The only things that tie you to a particular instance are two environment variables: `AGENTFEED_URL` (where the server is) and `AGENTFEED_TOKEN` (who you are). Set those and the rest of this skill works unchanged regardless of where you or the server run.
|
||||
|
||||
## Configuration
|
||||
|
||||
|
|
@ -17,20 +17,20 @@ config) — the helper reads `os.environ` directly. There is no `.env` file
|
|||
support; a `.env` file in the working directory is not read automatically.
|
||||
|
||||
```text
|
||||
DAYBOOK_URL=https://your-daybook-instance.example.com # your server's base URL
|
||||
DAYBOOK_TOKEN=your-personal-api-key # from Settings -> API Keys
|
||||
DAYBOOK_SOURCE=agent # a stable label for what's posting
|
||||
AGENTFEED_URL=https://your-agentfeed-instance.example.com # your server's base URL
|
||||
AGENTFEED_TOKEN=your-personal-api-key # from Settings -> API Keys
|
||||
AGENTFEED_SOURCE=agent # a stable label for what's posting
|
||||
```
|
||||
|
||||
- **`DAYBOOK_URL`** — the base URL of the Daybook instance you're posting to.
|
||||
- **`AGENTFEED_URL`** — the base URL of the AgentFeed instance you're posting to.
|
||||
Set it to your server. If it's unset, the helper falls back to
|
||||
`http://127.0.0.1:8001`, which is only correct when Daybook is running
|
||||
`http://127.0.0.1:8001`, which is only correct when AgentFeed is running
|
||||
locally on the same machine (its development default). For any remote or
|
||||
deployed instance you **must** set this.
|
||||
- **`DAYBOOK_TOKEN`** — a personal API key, created in the app under Settings →
|
||||
- **`AGENTFEED_TOKEN`** — a personal API key, created in the app under Settings →
|
||||
API Keys (name one per agent so you can revoke them individually). Not a key
|
||||
shared by everyone; artifacts posted with it land only in your feed.
|
||||
- **`DAYBOOK_SOURCE`** — a free-text label for whatever is posting
|
||||
- **`AGENTFEED_SOURCE`** — a free-text label for whatever is posting
|
||||
(agent-profile, script, or person name). Optional; can also be passed per
|
||||
call with `--source`.
|
||||
|
||||
|
|
@ -41,29 +41,29 @@ PowerShell multipart, or inline shell content (a `curl` fallback for
|
|||
environments without the helper is documented at the end — the script is
|
||||
still preferred everywhere it's available).
|
||||
|
||||
The helper lives at **`scripts/daybook_post.py` inside this skill's own
|
||||
The helper lives at **`scripts/agentfeed_post.py` inside this skill's own
|
||||
directory** — not in any project you happen to be working in. Invoke it by
|
||||
its absolute path. For brevity, the examples below assume you've captured
|
||||
that path once:
|
||||
|
||||
```bash
|
||||
# Point this at the helper inside THIS skill directory (absolute path).
|
||||
DAYBOOK_POST=/abs/path/to/this/skill/scripts/daybook_post.py
|
||||
AGENTFEED_POST=/abs/path/to/this/skill/scripts/agentfeed_post.py
|
||||
```
|
||||
|
||||
Then:
|
||||
|
||||
```bash
|
||||
python "$DAYBOOK_POST" --check
|
||||
python "$DAYBOOK_POST" --kind markdown --title "Build Report" --content-file report.md
|
||||
cat report.md | python "$DAYBOOK_POST" --kind markdown --title "Build Report"
|
||||
python "$DAYBOOK_POST" --file diagram.svg --title "Architecture Diagram"
|
||||
python "$AGENTFEED_POST" --check
|
||||
python "$AGENTFEED_POST" --kind markdown --title "Build Report" --content-file report.md
|
||||
cat report.md | python "$AGENTFEED_POST" --kind markdown --title "Build Report"
|
||||
python "$AGENTFEED_POST" --file diagram.svg --title "Architecture Diagram"
|
||||
```
|
||||
|
||||
The artifact URL is printed as the final stdout line.
|
||||
|
||||
(If you *are* working inside a Daybook source checkout, a compatibility
|
||||
wrapper also exists at `scripts/daybook_post.py` in the repo root, but the
|
||||
(If you *are* working inside a AgentFeed source checkout, a compatibility
|
||||
wrapper also exists at `scripts/agentfeed_post.py` in the repo root, but the
|
||||
canonical helper is the one bundled in this skill.)
|
||||
|
||||
## Kind Cheat Sheet
|
||||
|
|
@ -100,7 +100,7 @@ with no API equivalent at all yet.
|
|||
|
||||
## CDN Snippets For `html_full`
|
||||
|
||||
`html_full` is Daybook's escape hatch for custom pages — nothing is
|
||||
`html_full` is AgentFeed's escape hatch for custom pages — nothing is
|
||||
injected into it, so a poster wanting Tailwind or a charting library has to
|
||||
supply its own `<link>`/`<script>` tags. Known-good ones:
|
||||
|
||||
|
|
@ -113,13 +113,13 @@ supply its own `<link>`/`<script>` tags. Known-good ones:
|
|||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
```
|
||||
|
||||
**Offline caveat:** Daybook can run fully self-hosted/air-gapped. Any
|
||||
**Offline caveat:** AgentFeed can run fully self-hosted/air-gapped. Any
|
||||
artifact that links a CDN script won't render fully (or at all, for
|
||||
Tailwind's in-browser compiler) without internet access. If the deployment
|
||||
target is offline, don't reach for these — use `markdown`/`html_fragment`
|
||||
instead, which are styled entirely server-side with no external requests.
|
||||
|
||||
**Self-hosted alternative for tables/JSON — no CDN needed:** Daybook already
|
||||
**Self-hosted alternative for tables/JSON — no CDN needed:** AgentFeed already
|
||||
vendors Grid.js and renderjson locally (used to render `csv`/`json`
|
||||
artifacts), and they're reachable as plain static files from any artifact,
|
||||
including `html_full`:
|
||||
|
|
@ -138,7 +138,7 @@ tables/JSON; there's no vendored equivalent for Tailwind/Chart.js, so the
|
|||
CDN snippets above are still the only option for those.
|
||||
|
||||
Only use this for `html_full` specifically — never add CDN references to
|
||||
`markdown`/`html_fragment`/`deck`. Those kinds exist so Daybook, not the
|
||||
`markdown`/`html_fragment`/`deck`. Those kinds exist so AgentFeed, not the
|
||||
poster, owns styling; injecting a default CDN habit into them would
|
||||
undermine that.
|
||||
|
||||
|
|
@ -149,12 +149,12 @@ artifact), upload it first and reference the returned URL:
|
|||
|
||||
```bash
|
||||
# 1. Upload -> prints the URL as the last line
|
||||
python "$DAYBOOK_POST" --upload-image chart.png
|
||||
python "$AGENTFEED_POST" --upload-image chart.png
|
||||
|
||||
# 2. Reference that URL in your markdown, then post as usual.
|
||||
# The printed URL is absolute against your DAYBOOK_URL, e.g.
|
||||
# 
|
||||
python "$DAYBOOK_POST" report.md
|
||||
# The printed URL is absolute against your AGENTFEED_URL, e.g.
|
||||
# 
|
||||
python "$AGENTFEED_POST" report.md
|
||||
```
|
||||
|
||||
The image is linked to the artifact that references it and is deleted along with it.
|
||||
|
|
@ -167,15 +167,15 @@ just post the file positionally; auto-mode detects `.csv`/`.json` and picks
|
|||
the right kind automatically:
|
||||
|
||||
```bash
|
||||
python "$DAYBOOK_POST" results.csv
|
||||
python "$DAYBOOK_POST" --kind json --title "Run Summary" --content-file summary.json
|
||||
python "$AGENTFEED_POST" results.csv
|
||||
python "$AGENTFEED_POST" --kind json --title "Run Summary" --content-file summary.json
|
||||
```
|
||||
|
||||
`.xlsx` spreadsheets work too, with no special flag needed — just `--file`
|
||||
(or post it positionally, same as any other file):
|
||||
|
||||
```bash
|
||||
python "$DAYBOOK_POST" balance_sheet.xlsx
|
||||
python "$AGENTFEED_POST" balance_sheet.xlsx
|
||||
```
|
||||
|
||||
The server converts it to a `csv` artifact automatically. Known
|
||||
|
|
@ -196,7 +196,7 @@ as a binary, use `--file path --as-markdown` to wrap it in a Markdown
|
|||
fenced code block (still gets syntax highlighting):
|
||||
|
||||
```bash
|
||||
python "$DAYBOOK_POST" --file script.py --as-markdown --title "Generated Script"
|
||||
python "$AGENTFEED_POST" --file script.py --as-markdown --title "Generated Script"
|
||||
```
|
||||
|
||||
Without `--as-markdown`, it uploads as a downloadable binary file instead.
|
||||
|
|
@ -208,7 +208,7 @@ All optional, all default to something reasonable if omitted:
|
|||
| Flag | Default | Notes |
|
||||
|---|---|---|
|
||||
| `--source-type` | `agent` | One of `agent`, `person`, `system`. |
|
||||
| `--source-name` | Same as the effective source (`--source`, or `DAYBOOK_SOURCE` if `--source` wasn't given) | Human-readable name, e.g. "Hermes Agent". |
|
||||
| `--source-name` | Same as the effective source (`--source`, or `AGENTFEED_SOURCE` if `--source` wasn't given) | Human-readable name, e.g. "Hermes Agent". |
|
||||
| `--source-id` | Empty string | A stable external ID, if the poster has one. |
|
||||
| `--source-prompt` | Empty string | The prompt/instruction that produced this artifact — useful for later tracing why something was posted. |
|
||||
|
||||
|
|
@ -219,9 +219,9 @@ context like `run_id` or `model` — these end up in the artifact's
|
|||
|
||||
## Rules
|
||||
|
||||
- Run `--check` first if unsure Daybook is reachable.
|
||||
- Make sure `DAYBOOK_URL` points at the right instance and `DAYBOOK_TOKEN` is set before posting anything real.
|
||||
- Use a stable `DAYBOOK_SOURCE` or pass `--source` (the agent-profile, script, or person name that produced this artifact).
|
||||
- Run `--check` first if unsure AgentFeed is reachable.
|
||||
- Make sure `AGENTFEED_URL` points at the right instance and `AGENTFEED_TOKEN` is set before posting anything real.
|
||||
- Use a stable `AGENTFEED_SOURCE` or pass `--source` (the agent-profile, script, or person name that produced this artifact).
|
||||
- Use `--tags a,b,c` for filtering.
|
||||
- Use `--meta run_id=... --meta model=...` for machine-readable context.
|
||||
- Never inline multiline content into the shell command; use a file or stdin.
|
||||
|
|
@ -236,8 +236,8 @@ with no Python). Text artifacts post as JSON to `POST /api/artifacts` with
|
|||
bearer-token auth:
|
||||
|
||||
```bash
|
||||
curl -sS -X POST "$DAYBOOK_URL/api/artifacts" \
|
||||
-H "Authorization: Bearer $DAYBOOK_TOKEN" \
|
||||
curl -sS -X POST "$AGENTFEED_URL/api/artifacts" \
|
||||
-H "Authorization: Bearer $AGENTFEED_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"kind":"markdown","title":"Build Report","source":"agent","content":"# Hello\n\nBody text."}'
|
||||
```
|
||||
|
|
@ -245,12 +245,12 @@ curl -sS -X POST "$DAYBOOK_URL/api/artifacts" \
|
|||
File/image artifacts use multipart instead:
|
||||
|
||||
```bash
|
||||
curl -sS -X POST "$DAYBOOK_URL/api/artifacts" \
|
||||
-H "Authorization: Bearer $DAYBOOK_TOKEN" \
|
||||
curl -sS -X POST "$AGENTFEED_URL/api/artifacts" \
|
||||
-H "Authorization: Bearer $AGENTFEED_TOKEN" \
|
||||
-F "kind=image" -F "title=Architecture Diagram" -F "source=agent" \
|
||||
-F "file=@diagram.png"
|
||||
```
|
||||
|
||||
`GET $DAYBOOK_URL/api/capabilities` (no auth needed beyond a login/token per
|
||||
`GET $AGENTFEED_URL/api/capabilities` (no auth needed beyond a login/token per
|
||||
that instance's config) lists supported kinds, methods, and the server
|
||||
version if you need to confirm the contract before posting.
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Post artifacts to Daybook without shell-specific JSON or multipart quoting.
|
||||
"""Post artifacts to AgentFeed without shell-specific JSON or multipart quoting.
|
||||
|
||||
Zero third-party dependencies. Content comes from a file or stdin so agents do not
|
||||
need to inline multiline JSON/HTML/Markdown in shell commands.
|
||||
|
|
@ -26,11 +26,11 @@ DEFAULT_SOURCE = "agent"
|
|||
|
||||
def main():
|
||||
args = parse_args()
|
||||
base_url = os.environ.get("DAYBOOK_URL", DEFAULT_URL).rstrip("/")
|
||||
# DAYBOOK_TOKEN is your personal per-user token (Settings -> Account in the app);
|
||||
base_url = os.environ.get("AGENTFEED_URL", DEFAULT_URL).rstrip("/")
|
||||
# AGENTFEED_TOKEN is your personal per-user token (Settings -> API Keys in the app);
|
||||
# there is no shared fallback token, so posting without it cannot work.
|
||||
token = os.environ.get("DAYBOOK_TOKEN", "")
|
||||
source = args.source or os.environ.get("DAYBOOK_SOURCE", DEFAULT_SOURCE)
|
||||
token = os.environ.get("AGENTFEED_TOKEN", "")
|
||||
source = args.source or os.environ.get("AGENTFEED_SOURCE", DEFAULT_SOURCE)
|
||||
|
||||
if args.check:
|
||||
try:
|
||||
|
|
@ -43,8 +43,8 @@ def main():
|
|||
|
||||
if not token:
|
||||
print(
|
||||
"error: DAYBOOK_TOKEN is not set. Get your personal API token from "
|
||||
f"{base_url}/settings/account/ and set DAYBOOK_TOKEN.",
|
||||
"error: AGENTFEED_TOKEN is not set. Get your personal API token from "
|
||||
f"{base_url}/settings/api-keys/ and set AGENTFEED_TOKEN.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 2
|
||||
|
|
@ -84,11 +84,11 @@ def main():
|
|||
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(description="Publish an artifact to Daybook.")
|
||||
parser = argparse.ArgumentParser(description="Publish an artifact to AgentFeed.")
|
||||
parser.add_argument("path", nargs="?", help="Auto mode: one file path. Kind, content-type, and title are inferred. The simplest way to post.")
|
||||
parser.add_argument("--kind", choices=sorted(TEXT_KINDS), help="Text artifact kind. Omit when using --file or a positional path.")
|
||||
parser.add_argument("--title", help="Artifact title. Required unless --check is used.")
|
||||
parser.add_argument("--source", help="Artifact source (agent-profile, script, or person name). Defaults to DAYBOOK_SOURCE or 'agent'.")
|
||||
parser.add_argument("--source", help="Artifact source (agent-profile, script, or person name). Defaults to AGENTFEED_SOURCE or 'agent'.")
|
||||
parser.add_argument("--content-file", help="Read text artifact content from this file.")
|
||||
parser.add_argument("--file", help="Upload this file as image/pdf/binary, or render as markdown with --as-markdown.")
|
||||
parser.add_argument("--tags", help="Comma-separated tags.")
|
||||
|
|
@ -352,7 +352,7 @@ def post_payload(base_url, token, payload, args):
|
|||
|
||||
|
||||
def multipart_body(payload):
|
||||
boundary = f"----daybook-{uuid.uuid4().hex}"
|
||||
boundary = f"----agentfeed-{uuid.uuid4().hex}"
|
||||
chunks = []
|
||||
upload_path = payload["upload_path"]
|
||||
for key, value in payload.items():
|
||||
|
|
@ -394,11 +394,11 @@ def content_type_for(path):
|
|||
|
||||
|
||||
def upload_asset(base_url, token, path):
|
||||
"""Upload an image and return its Daybook URL for embedding in content."""
|
||||
"""Upload an image and return its AgentFeed URL for embedding in content."""
|
||||
if not path.is_file():
|
||||
raise ValueError(f"image file does not exist: {path}")
|
||||
|
||||
boundary = f"----daybook-{uuid.uuid4().hex}"
|
||||
boundary = f"----agentfeed-{uuid.uuid4().hex}"
|
||||
chunks = [
|
||||
f"--{boundary}\r\n".encode("utf-8"),
|
||||
f'Content-Disposition: form-data; name="file"; filename="{path.name}"\r\n'.encode("utf-8"),
|
||||
Loading…
Add table
Add a link
Reference in a new issue