@tpsdev-ai/flair 0.46.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/dist/build-info.json +6 -0
- package/dist/cli.js +479 -163
- package/dist/doctor-client.js +92 -11
- package/dist/install/global-bin-path.js +234 -0
- package/dist/lib/entity-vocab-cli.js +113 -0
- package/dist/lib/mcp-enable.js +12 -2
- package/dist/lib/scheduler-platform.js +153 -0
- package/dist/postinstall.cjs +88 -0
- package/dist/rem/runner.js +177 -10
- package/dist/rem/scheduler.js +15 -9
- 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/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-tools.js +53 -3
- package/dist/resources/memory-reflect-lib.js +201 -4
- package/dist/src/lib/scheduler-platform.js +153 -0
- package/dist/src/rem/scheduler.js +15 -9
- 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 +42 -0
- package/package.json +5 -4
- package/schemas/memory.graphql +12 -0
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
|
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
|
}
|