Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ jobs:
license "MIT"

on_macos do
# RemoteUI popup helper (own repo/formula): A3S-Lab/WebView. Pulled
# in automatically so the inline OS popup works out of the box.
depends_on "a3s-lab/tap/a3s-webview"
on_arm do
url "${base}/a3s-${tag}-aarch64-apple-darwin.tar.gz"
sha256 "${mac_arm}"
Expand Down
29 changes: 12 additions & 17 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "a3s"
version = "0.5.12"
version = "0.5.13"
edition = "2021"
description = "a3s — A3S coding agent CLI; `a3s code` launches the interactive TUI"
license = "MIT"
Expand All @@ -15,11 +15,12 @@ path = "src/main.rs"

[dependencies]
a3s-code-core = { git = "https://github.com/AI45Lab/Code.git", rev = "e1b65e8fd5dc3cf392d073173c37213669d0f782" }
a3s-tui = { git = "https://github.com/A3S-Lab/TUI.git", rev = "be0ed1864a9a9f27ecf9999a98e731e51e7fa569" }
a3s-tui = { git = "https://github.com/A3S-Lab/TUI.git", rev = "091f6ba172bf47a9c38c57d96f19a53cbb74c6a3" }
tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "time", "process", "io-util", "net"] }
anyhow = "1"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
chrono = { version = "0.4", features = ["serde"] }
similar = "2"
image = { version = "0.25", default-features = false, features = ["png", "jpeg", "gif", "webp"] }
# Codex account client (custom LlmClient over the ChatGPT backend).
Expand Down
282 changes: 282 additions & 0 deletions docs/knowledge-base-design.md

Large diffs are not rendered by default.

135 changes: 135 additions & 0 deletions docs/knowledge-compilation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# a3s code TUI — Knowledge Compilation ("LLM Wiki")

> Status: design + shipped capability (the `okf` skill, invoked as `/okf`). Audience: a3s maintainers.
> Companion to [knowledge-base-design.md](./knowledge-base-design.md). The KB is the *store*; this is how it gets *populated* from the codebase.

## What it is

An **LLM-driven wiki compiler**, in the spirit of DeepWiki and conforming to
Google's **[Open Knowledge Format (OKF v0.1)](https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing)** —
which formalizes exactly this LLM-wiki pattern as "a directory of markdown files
with YAML frontmatter." The coding agent reads the project's code (and any
existing `.a3s/kb/` notes) and **compiles** an **OKF bundle** under
`.a3s/kb/wiki/`: one markdown *concept* file per module / decision / abstraction
(its file path is the concept's identity), each with a required `type` frontmatter
field, standard markdown links forming the concept graph, `[code](src/foo.rs#L42)`
links to the real source, and a per-directory `index.md` — every claim grounded in
a file the agent actually read.

It is a **compile**, not a one-shot dump: each concept records the source files
(and a digest of them) it was built from, so a re-run only regenerates concepts
whose sources changed — a dependency-tracked, incremental rebuild.

### Why OKF

OKF is the natural fit because it *is* the standardized form of what this feature
already produced: vendor-neutral, agent- and human-friendly markdown — "just
markdown, just files, just YAML frontmatter." Emitting OKF makes the compiled
bundle portable (shippable as a tarball / git repo, indexable by any tool) and
interoperable with other OKF consumers. The only hard OKF requirement is a `type`
field on every concept; everything else is convention. Spec + sample bundles:
`GoogleCloudPlatform/knowledge-catalog`.

## Why this serves a coding agent (first-principles)

- A fresh, navigable wiki of the codebase is exactly the durable project knowledge
the [KB design](./knowledge-base-design.md) wants — **auto-generated** instead of
hand-written, so the vault is useful on day one and stays current as code moves.
- It is dual-use: the human reads it (in `/kb` or any editor), and the agent reads
it back as context (via the KB's P2 `KbContextProvider`). The agent that wrote
the wiki works better because it has the wiki.
- The note↔code links (`[name](src/…#L…)`, standard markdown) are the
coding-specific edge no general wiki tool has.

## Architecture — the agent IS the compiler

There is **no new core subsystem**. Compilation is a structured agent task,
driven by a bundled skill, using the agent's existing tools. The cli only
provides the skill and a trigger.

| Piece | What | Where |
|---|---|---|
| **`okf` skill** | The compilation pipeline (survey → plan → generate → index → verify; incremental; anti-hallucination rules). A `kind: instruction` skill — this *is* the capability. | `crates/cli/skills/okf.md` |
| **Skill loader** | Always-materialized to `~/.a3s/cli-skills/okf/SKILL.md` and added to the session skill dirs — so the capability is available in every project (not login-gated, not project-local). | `src/tui/skills.rs` `ensure_builtin_skills_dir` → `skill_dirs()` (`mod.rs`) |
| **`/okf` trigger** | The skill itself surfaces in the `/` menu as **`/okf`** (selecting it asks the agent to apply the skill); it also auto-applies when the user asks for the wiki/docs in prose. *No separate slash command* — that would just duplicate the skill's menu entry. | the slash menu's skill listing (`panels/menu.rs`) |
| **Fan-out** | Pages generate concurrently via `parallel_task` when available, else sequentially. | the agent's existing `parallel_task`/`task` tools |
| **Output** | `.a3s/kb/wiki/*.md` — the KB vault's compiled subtree. | the agent's `write` tool, routed through `ctx.resolve_workspace_path` |

## Pipeline

1. **Survey** — map the repo (top-level dirs, manifests, module entry points,
existing `.a3s/kb/` notes). In a monorepo, each crate/package is a module concept.
2. **Plan the bundle** — a bounded concept set + directory layout (e.g. `modules/`,
`concepts/`, `decisions/`), each directory with an `index.md`, plus the root
`index.md`. Deterministic kebab-case slugs. The layout is shown to the user first.
3. **Generate** — per concept, read its sources then write an OKF file (required
`type`, the standard fields, an *explanation* with `[file](path#Lline)` code
links and `[name](/dir/other.md)` concept links), grounded entirely in what was
read. Fan out with `parallel_task`.
4. **Index** — each directory's `index.md` and the root `index.md` link every
concept (OKF's hierarchical navigation); concepts also link each other.
5. **Verify** — every markdown link must resolve; dangling links fixed or dropped.

### Concept file format (OKF)

```yaml
---
type: Architecture Decision # REQUIRED by OKF (exactly one type per concept)
title: Why microVM, not container
description: Rationale for libkrun MicroVMs over containers.
resource: crates/box/src/runtime.rs # the concept's canonical source (path or URL)
tags: [architecture, security]
timestamp: 2026-06-30T12:00:00Z # ISO 8601
# OKF permits extra fields; we keep these for incremental recompile + provenance:
source: compiled # agent-generated, NOT a human note
sources: [crates/box/src/runtime.rs, crates/box/README.md]
source_digest: <sha of the concatenated sources>
---
```

Body: synthesized prose + **standard markdown links** between concepts
(`[name](/dir/other.md)`) and to code (`[runtime.rs](crates/box/src/runtime.rs#L42)`)
+ a final `## Sources` list. Navigation is OKF's reserved `index.md` per directory;
an optional top-level `log.md` holds the chronological compile history.

### Incremental recompile

Before regenerating a concept, the skill recomputes the digest of its `sources`
and compares it to the stored `source_digest`. Unchanged ⇒ skip; changed ⇒ rebuild
(plus the affected `index.md`). This is the "compile" semantics — cheap re-runs, a
bundle that tracks the code.

## Guardrails

- **Anti-hallucination** — state only what the code says, cite file+line, mark
uncertainty, never invent APIs. A hallucinated page is worse than no page.
- **Provenance & boundaries** — `source: compiled` on every page; the agent owns
`.a3s/kb/wiki/`, the human owns `.a3s/kb/*.md`; neither clobbers the other; the
agent memory (`~/.a3s/memory/`) is untouched.
- **No secrets** — never copy tokens/keys/`.env` into a page.
- **Bounded** — document modules + concepts, not every file; compile large repos
by area and report coverage.
- **Reward-hacking** — the agent generates knowledge it is later fed. Provenance +
user review (in `/kb`) mitigate it, and the compiled wiki is kept **out of any
self-evolution fitness signal** (carried from the KB P2 caveat).

## Relation to the KB phases

- Works **today** as the `okf` skill — invoke it via **`/okf`** (the menu entry) or
by asking in prose; it writes plain `.md`, browsable with `/ide` or any editor —
independent of the KB panel.
- **One format, end to end:** both the compiled bundle (`.a3s/kb/wiki/`) and any
human-authored notes (`.a3s/kb/*.md`) are **OKF** — standard markdown links, a
required `type` field. There is no second link syntax to reconcile; the KB's P1
resolver follows OKF markdown links only.
- Gets better as the KB lands: P1 backlinks/search index the bundle's links so it
is navigable in `/kb`; P2 `KbContextProvider` feeds compiled concepts into the
agent's context.

## Open questions

- Bundle the skill always-on (current choice) vs. opt-in install?
- Should `/okf` recompile-all by default, or only stale pages? (Skill defaults to
incremental; ask in prose for a full rebuild.)
- A periodic/scheduled recompile via the agent's cron — later, once usage shows the
cadence.
47 changes: 38 additions & 9 deletions skills/a3s-os-capabilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ signed-in user may access.
| `list` | — | every module you can access (name, description, path, operationCount) |
| `search` | `query` | matching operations across modules |
| `describe` | `module` (+ optional `operation`) | the module's sub-modules + its operations; or, with `operation`, just that ONE operation's full input/output schema |
| `execute` | `module`, `operation`, `params` | the operation result (`data`), plus an optional `viewUrl` deep link and `ui` agent-ui directive |
| `execute` | `module`, `operation`, `params` | the operation result (`data`), plus an optional `view` object (a console deep link + suggested popup size) and `ui` agent-ui directive |

## Rules

Expand All @@ -89,17 +89,43 @@ signed-in user may access.
- Prefer read/`GET`-style operations for discovery; write operations (create /
update / delete) run with the user's real platform permissions — confirm intent
before mutating platform state.
- **Always surface `viewUrl`.** Many responses include a `viewUrl` — a deep link
to the console page for exactly what the user asked about. WHENEVER the response
contains one, extract it robustly (it may be top-level or nested, e.g.
`jq -r '.. | .viewUrl? // empty'` over the response) and present it to the user
as a clearly labeled, clickable link on its own line — e.g.
`🔗 在控制台查看: <viewUrl>` (write the label in the user's language). The TUI
renders bare URLs as clickable, so include the full URL. Never fabricate a
`viewUrl` that wasn't returned, and never drop one that was.
- **Offer the `view` as an inline link — never auto-open.** Some `execute`
responses include a `view` object — `{ "url": "…?embed=1", "width": N, "height":
N }` — a focused console page sized for a popup. Two things must happen:
1. **Keep `.view` in your command's JSON stdout** so the host can capture it —
do **not** narrow it away with `jq`; emit the full response or keep it in
your projection (e.g. `... | jq '{ data, view }'`). Never fabricate or drop
a returned `view`.
2. **End your reply with the link on its own line, exactly:** `🔗 打开渐进式UI`
— the host turns any reply line containing `打开渐进式UI` into a one-click
trigger that opens the view in the authenticated **渐进式UI** popup (the
user's current OS login is injected — no re-login). RemoteUI is
**user-triggered**: the popup is NOT opened automatically; the user clicks
that link (or runs `/view`). Do **not** print the raw URL yourself — the link
line is the affordance.
- The `ui` field (`protocol: "agent-ui"`) is a host-rendered remote component —
note that it exists if present, but don't try to render it yourself.

## Learned shortcuts — shorten the chain on repeat tasks

The `list → search → describe → execute` walk is for *discovering* an operation.
Once you've resolved one, remember it so the next similar task skips discovery.

- **Cache:** `~/.a3s/os-learned.md` (per-user). At the **start** of an OS task,
read it — `cat ~/.a3s/os-learned.md 2>/dev/null`. If it already maps a task like
the user's to a `module`/`operation`, **skip `list`/`search`**: go straight to
`describe` that operation (to confirm its current schema) → `execute`. That turns
a 4-step walk into 1–2 steps.
- **After** you successfully `execute` a NEWLY-resolved operation, append one terse
line so the next run is faster:
```bash
echo '- <short task intent> → {module}/{operation} (params: <key params>)' >> ~/.a3s/os-learned.md
```
Don't duplicate an existing entry; don't cache failed, ambiguous, or one-off calls.
- The cache is a **hint, not gospel**: if `describe` shows the schema changed or
`execute` errors with the cached operation, fall back to `list`/`search` to
re-discover and fix the stale entry.

## Examples

```bash
Expand All @@ -110,6 +136,9 @@ post() { curl -s -X POST "$API" -H "Authorization: Bearer $A3S_OS_TOKEN" -H 'Con
post '{"action":"list"}' # 1. what modules exist
post '{"action":"search","query":"ocr"}' # 2. find operations
post '{"action":"describe","module":"kernel","operation":"runOcr"}' # 3. exact schema

# execute: keep `.view` in the projection so the host can offer the 渐进式UI link
post '{"action":"execute","module":"assets","operation":"listAssets"}' | jq '{data, view}'
```

```json
Expand Down
Loading
Loading