@tpsdev-ai/flair 0.45.0 → 0.47.0
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.
- package/config.yaml +35 -2
- package/dist/build-info.json +6 -0
- package/dist/cli.js +847 -168
- package/dist/doctor-client.js +358 -11
- package/dist/federation/scheduler.js +114 -9
- package/dist/hook-install.js +150 -1
- package/dist/install/global-bin-path.js +234 -0
- package/dist/lib/entity-vocab-cli.js +113 -0
- package/dist/lib/mcp-enable.js +71 -21
- package/dist/lib/scheduler-platform.js +363 -1
- package/dist/postinstall.cjs +88 -0
- package/dist/rem/runner.js +177 -10
- package/dist/rem/scheduler.js +126 -20
- package/dist/resources/AttentionQuery.js +5 -3
- package/dist/resources/AutoPromoteCandidates.js +18 -12
- package/dist/resources/Federation.js +49 -5
- package/dist/resources/Memory.js +36 -2
- package/dist/resources/MemoryBootstrap.js +118 -7
- package/dist/resources/MemoryMaintenance.js +8 -2
- package/dist/resources/MemoryReflect.js +70 -5
- package/dist/resources/auto-promote-lib.js +46 -0
- package/dist/resources/build-info.js +50 -0
- package/dist/resources/entity-vocab.js +25 -1
- package/dist/resources/health.js +25 -5
- package/dist/resources/mcp-oauth-flag.js +20 -0
- package/dist/resources/mcp-oauth.js +6 -1
- package/dist/resources/mcp-tools.js +53 -3
- package/dist/resources/memory-reflect-lib.js +201 -4
- package/dist/src/lib/scheduler-platform.js +363 -1
- package/dist/src/rem/scheduler.js +126 -20
- package/docs/deepseek-harness.md +110 -0
- package/docs/entity-vocabulary.md +15 -0
- package/docs/integrations.md +1 -0
- package/docs/mcp-clients.md +4 -0
- package/docs/notes/mcp-oauth-model2.md +52 -3
- package/package.json +5 -4
- package/schemas/memory.graphql +12 -0
- package/templates/bin/flair-federation-sync.sh.tmpl +8 -1
- package/templates/bin/flair-rem-nightly.sh.tmpl +8 -1
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Flair + DeepSeek Harness (zero-code MCP bridge)
|
|
2
|
+
|
|
3
|
+
Give DeepSeek Harness (DSH) sessions persistent, portable memory — no plugin code, just one Cordis overlay wiring [`@tpsdev-ai/flair-mcp`](../packages/flair-mcp) through DSH's first-party MCP bridge, [`@deepseek-ai/dsh-mcp-client`](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/mcp/mcp-client).
|
|
4
|
+
|
|
5
|
+
> **Verified against DSH as of 2026-08-20** (`deepseek-ai/deepseek-harness`, branch `master`). DSH is a developer preview and its own README promises compatibility-breaking changes. If wiring fails after a DSH upgrade, re-check the config field names against [their MCP client README](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/mcp/mcp-client/README.md) before suspecting Flair.
|
|
6
|
+
|
|
7
|
+
The same eleven tools every other MCP client gets ([full table in mcp-clients.md](mcp-clients.md#what-the-mcp-server-exposes)) appear to the model under DSH's server-qualified names: `mcp__flair__memory_search`, `mcp__flair__memory_store`, `mcp__flair__bootstrap`, and so on — the same `mcp__<server>__<tool>` convention Claude Code uses.
|
|
8
|
+
|
|
9
|
+
Two caveats up front, both structural to DSH's bridge (details below):
|
|
10
|
+
|
|
11
|
+
1. **DSH scrubs the ambient environment before spawning MCP servers.** Flair's env vars must be declared in the overlay's `config.env` — exported shell vars will not reliably reach the server.
|
|
12
|
+
2. **Recall on this path is reactive.** The model must *choose* to call the memory tools; DSH's MCP bridge cannot inject Flair context at session start. There is a documented mitigation (a persona nudge), but real auto-inject requires a native DSH plugin — planned as phase 2 of [flair#1289](https://github.com/tpsdev-ai/flair/issues/1289).
|
|
13
|
+
|
|
14
|
+
## Prerequisites
|
|
15
|
+
|
|
16
|
+
Same as every MCP client — a running Flair and an agent identity. Follow [Step 1 of mcp-clients.md](mcp-clients.md#step-1--install-flair-do-once) (install, `flair init`, `flair agent add <id>`, `flair status`). If DSH runs on a machine that cannot see your Flair instance's loopback address, you need a reachable `FLAIR_URL` — see [quickstart-fabric.md](quickstart-fabric.md).
|
|
17
|
+
|
|
18
|
+
DSH spawns the server with `npx`, so the machine running DSH needs Node.js 22+ (Flair's own floor).
|
|
19
|
+
|
|
20
|
+
## The overlay
|
|
21
|
+
|
|
22
|
+
A ready-to-use copy of this file ships in the repo at [`examples/deepseek-harness/flair.cordis.yml`](../examples/deepseek-harness/flair.cordis.yml):
|
|
23
|
+
|
|
24
|
+
```yaml
|
|
25
|
+
- insert:
|
|
26
|
+
- id: memory-flair
|
|
27
|
+
name: '@deepseek-ai/dsh-mcp-client'
|
|
28
|
+
config:
|
|
29
|
+
serverName: flair
|
|
30
|
+
transport: stdio
|
|
31
|
+
command: npx
|
|
32
|
+
args: ['-y', '@tpsdev-ai/flair-mcp@<version>']
|
|
33
|
+
env:
|
|
34
|
+
FLAIR_AGENT_ID: <agent-id>
|
|
35
|
+
FLAIR_URL: http://127.0.0.1:19926
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Replace the two placeholders before use:
|
|
39
|
+
|
|
40
|
+
- `<version>` — pin the flair-mcp version you intend to run (the one you already have is `flair --version`). The [pinning rationale from mcp-clients.md](mcp-clients.md#step-2--wire-the-mcp-server-into-your-cli) applies with extra force here: DSH re-spawns the command per session, so an unpinned spec re-resolves to whatever is currently on npm every time. Leaving the literal `<version>` in place fails loudly at `npx` — intended.
|
|
41
|
+
- `<agent-id>` — the identity you created with `flair agent add`.
|
|
42
|
+
|
|
43
|
+
`FLAIR_URL` as shown is the local default; point it at your Fabric URL for a remote instance.
|
|
44
|
+
|
|
45
|
+
Apply it for one run:
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
dsh web --patch "$PWD/examples/deepseek-harness/flair.cordis.yml"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
To keep it across runs, merge the single `insert` patch into a user patch layer — `$DSH_HOME/profiles/<name>/cordis.patch.yml` for one profile, or `$DSH_HOME/cordis.patch.yml` machine-wide. Merge into an existing file rather than copying over it; it may already carry unrelated patches.
|
|
52
|
+
|
|
53
|
+
DSH's own reference memory overlays prefer a preinstalled binary over a package runner ("DSH starts it but does not run a package manager"). If you want that shape: `npm install -g @tpsdev-ai/flair-mcp@<version>`, then `command: flair-mcp` with no `args`.
|
|
54
|
+
|
|
55
|
+
## Caveat 1 — the bridge scrubs ambient env; declare Flair's env explicitly
|
|
56
|
+
|
|
57
|
+
Before spawning a stdio MCP server, DSH's bridge builds the child environment from a **scrubbed** copy of the parent env: every variable whose name matches `KEY`, `PASSWORD`, `SECRET`, or `TOKEN` (case-insensitive) is dropped, and so is every `DSH_*` variable. The overlay's `config.env` is merged **after** the scrub, so it is the one reliable channel.
|
|
58
|
+
|
|
59
|
+
Concretely for Flair:
|
|
60
|
+
|
|
61
|
+
- `FLAIR_KEY_PATH` contains `KEY` — an exported value is **silently dropped**. If your Ed25519 key is not at the default `~/.flair/keys/<agent>.key`, you must set `FLAIR_KEY_PATH` in `config.env`.
|
|
62
|
+
- `FLAIR_AGENT_ID` and `FLAIR_URL` happen to survive today's scrub pattern, but the pattern is DSH's to change. Declare all three in `config.env` and depend on none of the ambient env.
|
|
63
|
+
|
|
64
|
+
This mirrors the general rule from [mcp-clients.md troubleshooting](mcp-clients.md#troubleshooting) — a client's own env does not propagate to the spawned MCP subprocess unless declared — DSH just enforces it deliberately.
|
|
65
|
+
|
|
66
|
+
## Caveat 2 — recall is reactive on this path
|
|
67
|
+
|
|
68
|
+
DSH's MCP bridge registers **tools** on the model's tool list. That is all it can do: DSH has no first-class memory seam, and the bridge has no way to run `bootstrap` at session start and inject the result into context. Whether memory gets consulted is the model's per-turn decision — identical to the behavior DSH documents for its own reference memory servers.
|
|
69
|
+
|
|
70
|
+
The documented mitigation is a standing prompt nudge. DSH's deployment persona is the `persona` config key on its `system-prompt` row (agent presets can shadow it with a persona row of their own; there is no end-user prompt-editing API — prompt text is config/composition only). Add something like:
|
|
71
|
+
|
|
72
|
+
> At the start of a task, call `mcp__flair__bootstrap` or `mcp__flair__memory_search` to load relevant memory before planning. When you make a decision worth keeping, or the user asks you to remember something, record it with `mcp__flair__memory_store`.
|
|
73
|
+
|
|
74
|
+
This is additive guidance in the shape DSH's own memory examples recommend, and it works — but it is a nudge, not a guarantee. **Honest limitation:** automatic session-start injection (what Flair's Claude Code `SessionStart` hook does) requires a native DSH plugin using their per-turn system-prompt context seam. That is phase 2 of [flair#1289](https://github.com/tpsdev-ai/flair/issues/1289); until it ships, this wiring gives pull-based memory only.
|
|
75
|
+
|
|
76
|
+
## Tools-only bridging
|
|
77
|
+
|
|
78
|
+
DSH bridges MCP **tools** only — Resources and Prompts are explicitly not bridged (a documented DSH limitation, not a Flair one). This costs nothing here: `flair-mcp` is a tools-only server, so its entire surface crosses the bridge.
|
|
79
|
+
|
|
80
|
+
## Verify your wiring
|
|
81
|
+
|
|
82
|
+
Initial tool discovery is asynchronous — wait until the `mcp__flair__*` tools appear in the session's tool list before the first prompt. Then run the write → fresh-session → recall check (the same protocol shape DSH uses to validate its own reference memory servers):
|
|
83
|
+
|
|
84
|
+
1. In DSH session A, ask: *"Remember that my validation drink is lapsang-`<unique suffix>`."* Confirm the model calls `mcp__flair__memory_store` and the tool reports success.
|
|
85
|
+
2. Open DSH session B in the same running Host — do not copy session A's conversation. Ask: *"What is my validation drink? Check memory."* Confirm the model calls `mcp__flair__memory_search` and returns the value.
|
|
86
|
+
3. Still in session B, ask it to *use* the recalled value ("suggest one drink for the meeting"). Confirm the answer builds on it.
|
|
87
|
+
|
|
88
|
+
A new DSH session is enough; a Host restart is not. Because the memory now lives in Flair rather than a local file, the same check also passes *across harnesses*: store in DSH, then `memory_search` from Claude Code or any other [MCP client](mcp-clients.md) pointed at the same Flair instance and agent.
|
|
89
|
+
|
|
90
|
+
## Config reference (the fields this wiring uses)
|
|
91
|
+
|
|
92
|
+
Field names verified against DSH `master` 2026-08-20; [their table](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/mcp/mcp-client/README.md) is authoritative.
|
|
93
|
+
|
|
94
|
+
| Field | Value here | Notes |
|
|
95
|
+
|---|---|---|
|
|
96
|
+
| `serverName` | `flair` | Namespace for tool names (`mcp__flair__*`); must be unique across live instances |
|
|
97
|
+
| `transport` | `stdio` | flair-mcp is a stdio server |
|
|
98
|
+
| `command` / `args` | `npx` / `['-y', '@tpsdev-ai/flair-mcp@<version>']` | Or a preinstalled `flair-mcp` binary |
|
|
99
|
+
| `env` | `FLAIR_AGENT_ID`, `FLAIR_URL`, optionally `FLAIR_KEY_PATH` | Merged after DSH's env scrub — the only reliable channel (see caveat 1) |
|
|
100
|
+
| `toolCallTimeoutMs` | (default 60000) | Per-tool-call timeout; raise it only if slow remote searches genuinely exceed a minute |
|
|
101
|
+
|
|
102
|
+
## Troubleshooting
|
|
103
|
+
|
|
104
|
+
**"FLAIR_AGENT_ID is required" on startup.** The env block is missing or ambient-only — declare it in `config.env` (caveat 1).
|
|
105
|
+
|
|
106
|
+
**Tools never appear.** DSH logs initial connection and discovery failures; by default a failed startup registers no tools rather than failing the plugin. Check `flair status` on the Flair side, and check the DSH logs for the `flair` server's connect errors. A duplicate `serverName: flair` across live instances fails the later instance at load.
|
|
107
|
+
|
|
108
|
+
**`auth_error` on every call.** Identity/key mismatch — and remember that an exported `FLAIR_KEY_PATH` never reaches the server (caveat 1). Re-run `flair agent add <id>` (idempotent) or set `FLAIR_KEY_PATH` in `config.env`.
|
|
109
|
+
|
|
110
|
+
For everything else: [troubleshooting.md](troubleshooting.md).
|
|
@@ -89,6 +89,21 @@ Per the attention-plane spec's K&S-approved refinements, `entities: [String] @in
|
|
|
89
89
|
Existing rows on all three tables simply carry no `entities` — readers must tolerate absence,
|
|
90
90
|
the same pattern already used for `Presence.activityUpdatedAt`. No migration, no backfill.
|
|
91
91
|
|
|
92
|
+
All three fields are reachable from the CLI (flair#1288): `flair memory add`,
|
|
93
|
+
`flair workspace set`, and `flair orgevent` take `--entities <csv>`, a comma-separated list of
|
|
94
|
+
vocabulary strings:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
flair memory add --agent flint --entities "repo:tpsdev-ai/flair,issue:tpsdev-ai/flair#1288" "shipped the entities CLI surface"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The CLI validates each value before writing (a malformed value is rejected with the
|
|
101
|
+
`type:value` format and the valid type list); the server re-validates on every write path
|
|
102
|
+
regardless. The CLI's validator is an inlined copy of this module
|
|
103
|
+
(`src/lib/entity-vocab-cli.ts` — `src/` can't import across the packaging boundary into
|
|
104
|
+
`resources/`), pinned to it by `test/unit/cli-entities-option.test.ts`; the server-side gate
|
|
105
|
+
remains this module alone.
|
|
106
|
+
|
|
92
107
|
`Relationship` gets **no** `entities` field: its `subject`/`object` columns already carry
|
|
93
108
|
free-form entity-reference strings and are already indexed — they're the vocabulary carrier
|
|
94
109
|
for that table. They are lowercased on write today but not yet validated against this
|
package/docs/integrations.md
CHANGED
|
@@ -17,6 +17,7 @@ Where Flair already runs. Each integration shown here is a working surface — t
|
|
|
17
17
|
| **Gemini CLI** | [`flair-mcp`](#claude-code-cursor-codex-gemini-cli-continuedev-via-flair-mcp) | MCP config | Standard MCP server |
|
|
18
18
|
| **Antigravity CLI** (`agy`) | [`flair-mcp`](#claude-code-cursor-codex-gemini-cli-continuedev-via-flair-mcp) | MCP config | `~/.gemini/config/mcp_config.json`; pickup by a live `agy` pending verification |
|
|
19
19
|
| **Goose** (block/goose) | [`flair-mcp`](#claude-code-cursor-codex-gemini-cli-continuedev-via-flair-mcp) | MCP config | Goose ships native MCP support |
|
|
20
|
+
| **DeepSeek Harness** (`dsh`) | [`flair-mcp`](deepseek-harness.md) | Cordis overlay | First-party MCP bridge; tools-only, reactive recall — [dedicated page](deepseek-harness.md) |
|
|
20
21
|
| **LangGraph (TS)** | [`langgraph-flair`](#langgraph-typescript) | FlairClient | Drop-in `BaseStore` |
|
|
21
22
|
| **OpenClaw** | [`openclaw-flair`](#openclaw) | Ed25519 | Native plugin + context engine |
|
|
22
23
|
| **n8n** | [`n8n-nodes-flair`](#n8n) | FlairApi credential | Three nodes (chat memory, search, store) |
|
package/docs/mcp-clients.md
CHANGED
|
@@ -30,6 +30,8 @@ flair agent add my-project
|
|
|
30
30
|
flair status
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
+
> **`flair: command not found` right after installing?** Your npm global prefix's bin dir isn't on PATH (common with a user prefix like `~/.npm-global`) — run `export PATH="$(npm prefix -g)/bin:$PATH"`, persist that line in your shell profile, and `flair doctor` will print the exact line for your shell any time.
|
|
34
|
+
|
|
33
35
|
Flair runs as a local server at `http://127.0.0.1:19926` by default. The MCP server connects to it on demand via Ed25519-signed requests; nothing leaves your machine unless you explicitly route to a remote Flair instance.
|
|
34
36
|
|
|
35
37
|
---
|
|
@@ -244,6 +246,8 @@ Which memories are non-private is decided at write time, and the default is not
|
|
|
244
246
|
|
|
245
247
|
`bootstrap` returns the canonical structured containers — `soul`, `memories`, `predicted`, `teammateFindings`, `events` — plus counts and a `tokenEstimate`. The containers are **always present** (empty `[]`/`{}` when there's nothing), so an empty container is distinguishable from an unsupported one.
|
|
246
248
|
|
|
249
|
+
**The token ledger reconciles `tokenEstimate` from the payload alone (flair#1270).** Every token-charged content class carries a counter — `soulTokens`, `memoryTokens`, `trustTokens`, `eventsTokens` — plus a measured `scaffoldTokens` for the fixed JSON frame, and `tokenEstimate ≈ scaffoldTokens + soulTokens + memoryTokens + trustTokens + eventsTokens`. The remaining ≈ gap is the bounded per-item difference between the prose lines the memory counters measure and the heavier structured objects the containers ship. A payload whose estimate an agent can't decompose from the reported figures is a bug, not an accounting convention.
|
|
250
|
+
|
|
247
251
|
**Empty containers say why they're empty (flair#1182).** When a structured container ships empty, the payload carries a short hint naming the reason and what fills it — `eventsHint`, `teammateFindingsHint`, `predictedHint`. This is present *only* when the container is empty, so a deliberately-empty container is never confused with a silent drop (a connector never has to diff against a previous payload to tell the two apart).
|
|
248
252
|
|
|
249
253
|
**`matchQuality` is null on lifecycle sections — by design (flair#1225).** With `includeTrust: true`, each included memory carries a per-memory trust block, section-tagged, whose `matchQuality` is a `strong`/`moderate`/`breadcrumb` confidence band. On the **lifecycle sections** (`permanent`, `recent`, `predicted`) `matchQuality` is `null`: those are a lifecycle-window *load*, not a retrieval surface, so there is no relevance score to band. This is **correct, not a scoring failure** — an own-recent `null` next to a teammate's band does not mean your own records "scored worse". A retrieval band is only meaningful on the retrieval sections (`relevant`, `teammate`). The entry's `section` field makes this legible, and a `matchQualityNote` on any null entry states the reason inline.
|
|
@@ -46,6 +46,48 @@ context, so the wrapped handler scopes to the verified agent exactly as an
|
|
|
46
46
|
Ed25519-signed REST call would. Identity always comes from the resolved agent,
|
|
47
47
|
never from the tool arguments (no forging of agentId / authorId).
|
|
48
48
|
|
|
49
|
+
### Which Agent is my connector? (distinct-by-default — flair#1280)
|
|
50
|
+
|
|
51
|
+
**The connector's Agent is whatever the `Credential(kind:"idp")` mapping says
|
|
52
|
+
— and that is NOT constrained to be your CLI agent.** Distinct identities are
|
|
53
|
+
the ruled default (flair#1280): per-purpose connector identities are the
|
|
54
|
+
product pattern for org/service installs, and same-identity is a deliberate
|
|
55
|
+
opt-in, never something the server infers. The practical consequences:
|
|
56
|
+
|
|
57
|
+
- **Where the mapping is decided.** `flair mcp enable --principal <agent-id>
|
|
58
|
+
--idp-subject <sub>` (the identity-mapping step, backed by
|
|
59
|
+
`provisionIdpIdentityMapping`) writes the mapping. The `--principal` you pass
|
|
60
|
+
is the Agent every `/mcp` call will read and write as. Pass an EXISTING
|
|
61
|
+
agent id to attach the sub to it; the step's output states the resulting
|
|
62
|
+
`sub → Agent` mapping in as many words.
|
|
63
|
+
- **Linking a sub to an existing Agent (the same-identity opt-in).** Re-run
|
|
64
|
+
`flair mcp enable` with the SAME `--idp-provider`/`--idp-subject` and
|
|
65
|
+
`--principal <your-cli-agent-id>`. The existing `(provider, subject)`
|
|
66
|
+
Credential is RE-POINTED to that principal — one Credential row per subject,
|
|
67
|
+
so resolution stays deterministic. The link *replaces* the mapping; it does
|
|
68
|
+
not merge the two agents' memories.
|
|
69
|
+
- **First diagnostic: ask the server who you are.** The `bootstrap` tool's
|
|
70
|
+
response always carries the resolved `agentId` and a `scope` descriptor
|
|
71
|
+
(`scope.agentId` / `scope.isAdmin` / `scope.reads`, flair#1182). "My memory
|
|
72
|
+
is empty over the connector" + a `bootstrap.agentId` you don't recognize =
|
|
73
|
+
the sub resolved to a different (often JIT-provisioned) Agent — link it as
|
|
74
|
+
above.
|
|
75
|
+
- **JIT caveat.** A JIT-provisioned mapping (`FLAIR_MCP_JIT_PROVISION=1`)
|
|
76
|
+
stamps `idpProvider: "mcp-oauth"`. Runtime resolution matches on
|
|
77
|
+
`(kind, idpSubject)` only, but the *linking* upsert matches on
|
|
78
|
+
`(kind, idpProvider, idpSubject)` — so when re-linking a JIT-provisioned
|
|
79
|
+
sub, pass `--idp-provider mcp-oauth` (matching the JIT stamp), or first
|
|
80
|
+
revoke the JIT credential (`status: "revoked"`). Linking under a different
|
|
81
|
+
provider name creates a SECOND active credential for the same subject, and
|
|
82
|
+
which one wins resolution is unspecified.
|
|
83
|
+
|
|
84
|
+
The two-identity contract (a distinct connector agent sees other agents'
|
|
85
|
+
org-non-private rows, never their private rows, 404-never-403 by id; a linked
|
|
86
|
+
connector sees exactly what the linked agent sees) is pinned end-to-end by
|
|
87
|
+
`test/integration/mcp-connector-principal-mapping.test.ts`, which drives the
|
|
88
|
+
real `mcpHandler`/`resolveAgentFromSub` against a real store with two
|
|
89
|
+
registered identities.
|
|
90
|
+
|
|
49
91
|
## Enabling (operator checklist)
|
|
50
92
|
|
|
51
93
|
1. **Install the AS plugin** — add `@harperfast/oauth` (already an exact-pinned
|
|
@@ -59,9 +101,12 @@ never from the tool arguments (no forging of agentId / authorId).
|
|
|
59
101
|
clientId: ${OAUTH_GITHUB_CLIENT_ID}
|
|
60
102
|
clientSecret: ${OAUTH_GITHUB_CLIENT_SECRET}
|
|
61
103
|
mcp:
|
|
62
|
-
enabled:
|
|
104
|
+
enabled: ${FLAIR_MCP_OAUTH} # whole-token env reference (flair#1152) — the choice lives in the ENVIRONMENT, so a re-packed deploy can't revert it
|
|
63
105
|
issuer: ${FLAIR_MCP_ISSUER} # pin to your public origin — REQUIRED
|
|
64
|
-
resource
|
|
106
|
+
# NO resource key (flair#1180): the plugin derives <issuer>/mcp when it is
|
|
107
|
+
# absent. A composite like ${FLAIR_MCP_ISSUER}/mcp never interpolates
|
|
108
|
+
# (whole-token-only expansion) and fails every connect with
|
|
109
|
+
# invalid_target. Non-standard resource: set an explicit LITERAL URL.
|
|
65
110
|
accessTokenTtl: 900 # 5–15 min (Sherlock req 1) — short-lived
|
|
66
111
|
dynamicClientRegistration:
|
|
67
112
|
enabled: false # DCR is NOT SUPPORTED (flair#756) — explicit, not omitted (an absent block leaves DCR OPEN by the plugin's own default)
|
|
@@ -82,7 +127,11 @@ never from the tool arguments (no forging of agentId / authorId).
|
|
|
82
127
|
turning the surface on.
|
|
83
128
|
|
|
84
129
|
2. **Set the env:**
|
|
85
|
-
- `FLAIR_MCP_OAUTH=
|
|
130
|
+
- `FLAIR_MCP_OAUTH=true` — turns on the `/mcp` route registration AND the
|
|
131
|
+
component AS (flair#1152: `true` is the ONE value both readers accept —
|
|
132
|
+
flair's flag takes 1/true/yes/on, but the component's config read of the
|
|
133
|
+
same var accepts only "true"/"false" and deletes anything else, so `1`
|
|
134
|
+
gives you a guarded `/mcp` with no authorization server behind it).
|
|
86
135
|
- `FLAIR_MCP_ISSUER=https://your-public-origin` (or `FLAIR_PUBLIC_URL`).
|
|
87
136
|
- `FLAIR_MCP_JIT_PROVISION=1` — ONLY if you want unknown subjects
|
|
88
137
|
auto-provisioned (default OFF; pre-provision Agent+Credential otherwise).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tpsdev-ai/flair",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.47.0",
|
|
4
4
|
"packageManager": "bun@1.3.10",
|
|
5
5
|
"description": "Identity, memory, and soul for AI agents. Cryptographic identity (Ed25519), semantic memory with local embeddings, and persistent personality — all in a single process.",
|
|
6
6
|
"type": "module",
|
|
@@ -47,12 +47,13 @@
|
|
|
47
47
|
"scripts": {
|
|
48
48
|
"clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
49
49
|
"prebuild": "npm run clean",
|
|
50
|
-
"build": "tsc -p tsconfig.json --noCheck",
|
|
51
|
-
"build:cli": "tsc -p tsconfig.cli.json --noCheck",
|
|
50
|
+
"build": "tsc -p tsconfig.json --noCheck && node scripts/write-build-info.mjs",
|
|
51
|
+
"build:cli": "tsc -p tsconfig.cli.json --noCheck && node scripts/write-build-info.mjs",
|
|
52
52
|
"prepublishOnly": "npm run build && npm run build:cli",
|
|
53
53
|
"test": "bun test",
|
|
54
54
|
"test:e2e": "playwright test",
|
|
55
|
-
"release": "./scripts/release.sh"
|
|
55
|
+
"release": "./scripts/release.sh",
|
|
56
|
+
"postinstall": "node -e \"try{require('./dist/postinstall.cjs')}catch(e){}\""
|
|
56
57
|
},
|
|
57
58
|
"publishConfig": {
|
|
58
59
|
"access": "public"
|
package/schemas/memory.graphql
CHANGED
|
@@ -219,4 +219,16 @@ type MemoryCandidate @table(database: "flair") @export {
|
|
|
219
219
|
# evidence and would promote tagless (a cross-user leak). Nullable/additive —
|
|
220
220
|
# pre-#1205b candidates and non-tagged (scope:"recent"/"all") distillations
|
|
221
221
|
# read null, unchanged behavior (clean-upgrade-path gate).
|
|
222
|
+
visibilityRuling: String # flair#1257 slice 3: the distiller's AFFIRMATIVE visibility ruling for the
|
|
223
|
+
# promoted row — only ever "shared", and only stamped (resources/memory-
|
|
224
|
+
# reflect-lib.ts buildStagedCandidateRow) when the ruling arrived WITH a
|
|
225
|
+
# non-empty team-relevance justification. Promotion (resources/auto-promote-
|
|
226
|
+
# lib.ts decidePromotedVisibility) re-verifies all three conditions
|
|
227
|
+
# (continuity scopeTag + this ruling + visibilityRationale) and defaults
|
|
228
|
+
# "private" otherwise — default-private-unless (Sherlock): a shared promoted
|
|
229
|
+
# row must always trace to a recorded justification, never to a default.
|
|
230
|
+
# Nullable/additive — pre-slice-3 candidates read null ⇒ private, unchanged.
|
|
231
|
+
visibilityRationale: String # flair#1257 slice 3: the team-relevance justification paired with
|
|
232
|
+
# visibilityRuling — the auditable "why shared" recorded on the candidate.
|
|
233
|
+
# Nullable/additive, same clean-upgrade contract as scopeTag above.
|
|
222
234
|
}
|
|
@@ -25,4 +25,11 @@ if [ -n "${FLAIR_ADMIN_PASS_FILE:-}" ] && [ -f "${FLAIR_ADMIN_PASS_FILE}" ]; the
|
|
|
25
25
|
set -- "$@" --admin-pass-file "${FLAIR_ADMIN_PASS_FILE}"
|
|
26
26
|
fi
|
|
27
27
|
|
|
28
|
-
exec
|
|
28
|
+
# Run the CLI under node rather than exec-ing it directly: `node <script>`
|
|
29
|
+
# needs READ permission only, so the shim keeps working when a deploy method
|
|
30
|
+
# (npm-pack tarball extraction) strips the exec bit from the script (#1231).
|
|
31
|
+
# NODE_BIN is an ABSOLUTE path resolved at enable time — the shim performs
|
|
32
|
+
# zero PATH lookups at run time, exactly like the old absolute-FLAIR_BIN
|
|
33
|
+
# form. Do not replace it with a bare `node`: that would hand binary
|
|
34
|
+
# selection to whatever PATH the service manager happens to carry.
|
|
35
|
+
exec "{{NODE_BIN}}" "{{FLAIR_BIN}}" federation sync "$@"
|
|
@@ -5,5 +5,12 @@
|
|
|
5
5
|
#
|
|
6
6
|
# Single line that invokes the CLI's run-once subcommand — the runner module
|
|
7
7
|
# does all the work. Logs land in {{HOME}}/.flair/logs/.
|
|
8
|
+
#
|
|
9
|
+
# Run the CLI under node rather than exec-ing it directly: `node <script>`
|
|
10
|
+
# needs READ permission only, so the shim keeps working when a deploy method
|
|
11
|
+
# (npm-pack tarball extraction) strips the exec bit from the script (#1231).
|
|
12
|
+
# NODE_BIN is an ABSOLUTE path resolved at enable time — the shim performs
|
|
13
|
+
# zero PATH lookups at run time. Do not replace it with a bare `node`: that
|
|
14
|
+
# would hand binary selection to whatever PATH the service manager carries.
|
|
8
15
|
set -e
|
|
9
|
-
exec {{FLAIR_BIN}} rem nightly run-once
|
|
16
|
+
exec "{{NODE_BIN}}" "{{FLAIR_BIN}}" rem nightly run-once
|