graphjin 3.20.71 → 3.20.73

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.
Files changed (2) hide show
  1. package/README.md +92 -2
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -20,7 +20,8 @@ Works with PostgreSQL, MySQL, MongoDB, SQLite, Oracle, MSSQL, Snowflake, Redshif
20
20
  - **Smart discovery before action** - Agents start with `query_catalog(search: "<user instruction>")`, `graphql_help`, relationship evidence, examples, config recipes, and safety notes before writing or running queries.
21
21
  - **Guarded action, not raw access** - Source-mode access, query allow-lists, read-only boundaries, policy-aware MCP tools, local encrypted secrets, and `gj_config` preview/apply keep changes auditable.
22
22
  - **Operational awareness** - `gj_security`, `gj_runtime`, and the built-in console expose policy and bounded runtime status so agents can check what is safe before they act.
23
- - **Durable memory and standing questions** - Saved queries, fragments, and workflows live in the owner-scoped `gj_artifacts` store; cursor-backed watches (`gj_watch`) run standing questions under the owner's permissions, resume from persisted subscription cursors, and deliver fired events to a durable inbox (`gj_watch_event`), webhooks, or workflows. Normal watches are durable by default; explicit ephemeral watches use TTL leases.
23
+ - **Standing questions, not just answers** - Hand a cursor-paginated subscription to `gj_watch` and GraphJin keeps answering it under the owner's permissions, resumes from persisted cursors across restarts, treats absence as a first-class event, and files what it finds in a durable inbox (`gj_watch_event`), a webhook, or a workflow. Evaluation runs on database polls, not model calls - a model writes the watch once, and nothing calls one again unless you turn on optional per-watch triage. See [Watches](#watches-and-standing-questions).
24
+ - **Durable memory** - Saved queries, fragments, and workflows live in the owner-scoped `gj_artifacts` store. Normal watches are durable by default; explicit ephemeral watches use TTL leases.
24
25
 
25
26
  ## Installation
26
27
 
@@ -49,6 +50,23 @@ Download .deb/.rpm from [releases](https://github.com/dosco/graphjin/releases)
49
50
  docker pull dosco/graphjin
50
51
  ```
51
52
 
53
+ **Docker — as an agent environment**
54
+
55
+ The same binary also ships as a graded environment for training and evaluating
56
+ agents. It boots ready with nothing mounted: the demo world and a 113-task
57
+ verified suite are built in.
58
+
59
+ ```bash
60
+ docker run -d -p 8090:8090 --tmpfs /tmp:size=1g dosco/graphjin:env-latest
61
+ ```
62
+
63
+ `/health` says what it is — build, suite fingerprint, dataset fingerprint,
64
+ reward contract, and whether the suite matches the world it is served on.
65
+ `/tmp` must be writable: each world provisions its own database there.
66
+
67
+ See [the environment docs](https://graphjin.com/environment/quickstart/) for
68
+ the full story.
69
+
52
70
  ## Try It Now
53
71
 
54
72
  One command, no clone, no Docker. The binary ships with a built-in demo — a
@@ -608,7 +626,77 @@ Instead of your client chaining `query_catalog` → `validate_where_clause` →
608
626
  - **Machine-actionable refusals:** blocked responses carry a structured `refusal` (code, reasons, unblock steps, `policy_final`/`retryable`) so a calling agent can course-correct in one step instead of guessing.
609
627
  - **Server-owned model:** `ask_graphjin_agent` always uses the provider, model, and credential environment variable configured under `agent`. Without server credentials it fails closed with `model_credentials_required`.
610
628
 
611
- It is an RLM loop — the model writes JavaScript that calls the discovery tools, and the typed result is parsed from `key: value` output. It needs strong **code generation**, not provider tool-calling. Ax requests structured JSON for typed stages, choosing the mechanism from the named deployment profile (`agent.provider`) and its rules for the selected model; `agent.structured_output_mode: auto` is the default, with `native`, `function`, and `json_object` available as overrides. See [AGENTIC.md](AGENTIC.md#server-side-agent) and [CONFIG.md](CONFIG.md#agent-configuration).
629
+ It is an RLM loop — the model writes JavaScript that calls the discovery tools, and the typed result is parsed from `key: value` output. It needs strong **code generation**, not provider tool-calling. Ax requests structured JSON for typed stages, choosing the mechanism from the named deployment profile (`agent.provider`) and its rules for the selected model; `agent.structured_output_mode: auto` is the default, with `native`, `function`, and `json_object` available as overrides. `agent.service_tier` similarly defaults to provider-delegated `auto`, with portable `standard`, `flex`, and `priority` requests available when the profile/model supports them. See [AGENTIC.md](AGENTIC.md#server-side-agent) and [CONFIG.md](CONFIG.md#agent-configuration).
630
+
631
+ ## Watches And Standing Questions
632
+
633
+ Asking is a pull: it only produces value when someone thinks to ask. A watch is the
634
+ push direction. You hand `gj_watch` a cursor-paginated subscription once, and GraphJin
635
+ keeps answering it against live data, under the owner's stored identity and role.
636
+
637
+ ```graphql
638
+ mutation {
639
+ gj_watch(insert: {
640
+ name: "failed_invoices"
641
+ description: "Alert when a failed invoice changes."
642
+ query: "subscription failed_invoices { invoices(where: {status: {eq: \"failed\"}}, first: 25, after: $cursor) { id account_id status attempts } invoices_cursor }"
643
+ }) { id name status enabled }
644
+ }
645
+ ```
646
+
647
+ - **It costs database polls, not model calls.** The runner rides GraphJin's existing
648
+ cursor-backed subscriptions, compares a hash of each result, and writes a cursor
649
+ checkpoint even when nothing changed. No model is consulted to decide whether
650
+ something happened. A model writes the watch once; after that the only optional model
651
+ cost is per-watch triage in `enrich_json`, which is off by default and capped per day.
652
+ - **Absence is a first-class event.** A watch with `absence_json` fires when the
653
+ expected thing *does not* arrive, so silence stops being indistinguishable from
654
+ health.
655
+ - **It survives restarts.** Cursors are persisted, so a watch resumes where it left off
656
+ rather than replaying or skipping.
657
+ - **It cannot outrun its owner.** A watch only ever sees what its owner could already
658
+ query, and both `gj_watch` and `gj_watch_event` are owner-scoped.
659
+ - **Waking you and acting are different permissions.** Inbox delivery is immediate;
660
+ autonomous webhook or workflow delivery stays paused until the exact current
661
+ `action_hash` is approved. Alerts fail open, actions fail closed.
662
+
663
+ The built-in demo registers four standing questions on a first run (declared in
664
+ `examples/saas-ops/seed/watches.yml`), three of which have already fired by the time the
665
+ console opens. Management, review, cleanup, and MCP resource subscriptions are covered
666
+ under [MCP Tools](#mcp-tools); the full model is in
667
+ [AGENTIC.md](AGENTIC.md#watches-standing-questions-with-a-durable-inbox).
668
+
669
+ ## Train And Measure Agents On Your Own Graph
670
+
671
+ The same machinery that grades GraphJin's public benchmark grades agents on
672
+ *your* data, and runs as a reinforcement-learning environment for tuning small
673
+ models on it.
674
+
675
+ ```bash
676
+ # Generate a verified task suite from your catalog, with a train/eval split
677
+ graphjin eval create --demo --writable --scale 500 --composition coverage --split 0.8
678
+
679
+ # Serve it: pooled isolated worlds, one graded episode per request
680
+ graphjin env serve --path ./graphjin-demo --suite eval/suite.yml --pool 4 \
681
+ --split eval/suite.split.json --side train --freeze-time 2026-08-01T12:00:00Z
682
+ ```
683
+
684
+ - **Tasks come from your schema, and the reward comes from the database.** Each
685
+ task carries a hidden oracle — a read-only query that computes the answer —
686
+ so being plausible earns nothing. Writes are graded by the state the database
687
+ ended in *and* by every other row staying put.
688
+ - **Worlds are isolated and resettable.** An episode leases one, so a task that
689
+ writes changes only the world it was given.
690
+ - **Your real schema, without your real data.** `graphjin env clone` learns a
691
+ running server's schema from its catalog and writes a local synthetic copy.
692
+ No rows are read; the only real values that cross over are the closed sets
693
+ the catalog already publishes.
694
+
695
+ Three ways to drive an episode — GraphJin calls your endpoint, you supply each
696
+ completion, or you bring the whole agent over MCP — all grading through the same
697
+ contract.
698
+
699
+ **→ [The GraphJin Agent Environment](https://graphjin.com/environment/)**
612
700
 
613
701
  ## JS Workflows (GraphQL + REST)
614
702
 
@@ -837,6 +925,8 @@ Built-in web UI at `http://localhost:8080` for query development.
837
925
 
838
926
  - [Configuration Reference](CONFIG.md)
839
927
  - [Feature Reference](FEATURES.md)
928
+ - [Agent Environment](https://graphjin.com/environment/) — train and measure agents
929
+ - [Agent Evaluation](https://graphjin.com/agentic/evaluation/) — gate a release
840
930
  - [Go Examples](https://pkg.go.dev/github.com/dosco/graphjin/core#pkg-examples)
841
931
 
842
932
  ## Get in Touch
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "graphjin",
3
- "version": "3.20.71",
3
+ "version": "3.20.73",
4
4
  "description": "GraphJin — one governed graph for AI agents: GraphQL + MCP over your databases, files, APIs, and code",
5
5
  "bin": {
6
6
  "graphjin": "bin/graphjin.js"