@tpsdev-ai/flair 0.2.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.
Files changed (64) hide show
  1. package/LICENSE +19 -0
  2. package/README.md +246 -0
  3. package/SECURITY.md +116 -0
  4. package/config.yaml +16 -0
  5. package/dist/resources/A2AAdapter.js +474 -0
  6. package/dist/resources/Agent.js +9 -0
  7. package/dist/resources/AgentCard.js +45 -0
  8. package/dist/resources/AgentSeed.js +111 -0
  9. package/dist/resources/IngestEvents.js +149 -0
  10. package/dist/resources/Integration.js +13 -0
  11. package/dist/resources/IssueTokens.js +19 -0
  12. package/dist/resources/Memory.js +122 -0
  13. package/dist/resources/MemoryBootstrap.js +263 -0
  14. package/dist/resources/MemoryConsolidate.js +105 -0
  15. package/dist/resources/MemoryFeed.js +41 -0
  16. package/dist/resources/MemoryReflect.js +105 -0
  17. package/dist/resources/OrgEvent.js +43 -0
  18. package/dist/resources/OrgEventCatchup.js +65 -0
  19. package/dist/resources/OrgEventMaintenance.js +29 -0
  20. package/dist/resources/SemanticSearch.js +147 -0
  21. package/dist/resources/SkillScan.js +101 -0
  22. package/dist/resources/Soul.js +9 -0
  23. package/dist/resources/SoulFeed.js +12 -0
  24. package/dist/resources/WorkspaceLatest.js +45 -0
  25. package/dist/resources/WorkspaceState.js +76 -0
  26. package/dist/resources/auth-middleware.js +470 -0
  27. package/dist/resources/embeddings-provider.js +127 -0
  28. package/dist/resources/embeddings.js +42 -0
  29. package/dist/resources/health.js +6 -0
  30. package/dist/resources/memory-feed-lib.js +15 -0
  31. package/dist/resources/table-helpers.js +35 -0
  32. package/package.json +62 -0
  33. package/resources/A2AAdapter.ts +510 -0
  34. package/resources/Agent.ts +10 -0
  35. package/resources/AgentCard.ts +65 -0
  36. package/resources/AgentSeed.ts +119 -0
  37. package/resources/IngestEvents.ts +189 -0
  38. package/resources/Integration.ts +14 -0
  39. package/resources/IssueTokens.ts +29 -0
  40. package/resources/Memory.ts +138 -0
  41. package/resources/MemoryBootstrap.ts +283 -0
  42. package/resources/MemoryConsolidate.ts +121 -0
  43. package/resources/MemoryFeed.ts +48 -0
  44. package/resources/MemoryReflect.ts +122 -0
  45. package/resources/OrgEvent.ts +63 -0
  46. package/resources/OrgEventCatchup.ts +89 -0
  47. package/resources/OrgEventMaintenance.ts +37 -0
  48. package/resources/SemanticSearch.ts +157 -0
  49. package/resources/SkillScan.ts +146 -0
  50. package/resources/Soul.ts +10 -0
  51. package/resources/SoulFeed.ts +15 -0
  52. package/resources/WorkspaceLatest.ts +66 -0
  53. package/resources/WorkspaceState.ts +102 -0
  54. package/resources/auth-middleware.ts +502 -0
  55. package/resources/embeddings-provider.ts +144 -0
  56. package/resources/embeddings.ts +28 -0
  57. package/resources/health.ts +7 -0
  58. package/resources/memory-feed-lib.ts +22 -0
  59. package/resources/table-helpers.ts +46 -0
  60. package/schemas/agent.graphql +22 -0
  61. package/schemas/event.graphql +12 -0
  62. package/schemas/memory.graphql +50 -0
  63. package/schemas/schema.graphql +41 -0
  64. package/schemas/workspace.graphql +14 -0
@@ -0,0 +1,22 @@
1
+ import { createHash } from "node:crypto";
2
+
3
+ export function computeContentHash(agentId: string, content: string): string {
4
+ return createHash("sha256")
5
+ .update(`${agentId}${content}`)
6
+ .digest("hex")
7
+ .slice(0, 16);
8
+ }
9
+
10
+ export async function findExistingMemoryByContentHash(
11
+ records: AsyncIterable<any> | Iterable<any>,
12
+ agentId: string,
13
+ contentHash: string,
14
+ ): Promise<any | null> {
15
+ for await (const record of records) {
16
+ if (record?.agentId === agentId && record?.contentHash === contentHash) {
17
+ return record;
18
+ }
19
+ }
20
+
21
+ return null;
22
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Safe read-modify-write helper for Harper tables.
3
+ *
4
+ * Harper's `put()` is FULL RECORD REPLACEMENT. If you pass a partial
5
+ * object, all missing fields (including embeddings!) are permanently
6
+ * deleted. This helper ensures you always read the full record first.
7
+ *
8
+ * Usage:
9
+ * import { patchRecord } from "./table-helpers.js";
10
+ * await patchRecord(tables.Memory, id, { lastReflected: now });
11
+ */
12
+
13
+ export async function patchRecord(
14
+ table: any,
15
+ id: string,
16
+ patch: Record<string, unknown>,
17
+ ): Promise<void> {
18
+ const existing = await table.get(id);
19
+ if (!existing) throw new Error(`Record ${id} not found`);
20
+ await table.put({ ...existing, ...patch });
21
+ }
22
+
23
+ /**
24
+ * Fire-and-forget variant — swallows errors silently.
25
+ * Use for best-effort metadata updates (lastReflected, lastRetrieved, etc.)
26
+ * where a failure should never break the calling request.
27
+ */
28
+ export function patchRecordSilent(
29
+ table: any,
30
+ id: string,
31
+ patch: Record<string, unknown>,
32
+ ): void {
33
+ patchRecord(table, id, patch).catch(() => {});
34
+ }
35
+
36
+ // ── RULE ──────────────────────────────────────────────────────────────────────
37
+ // Never call `tables.X.put(partial)` directly anywhere in Flair resources.
38
+ // Harper put() = FULL RECORD REPLACEMENT. Missing fields are deleted permanently.
39
+ // Always use patchRecord() or patchRecordSilent().
40
+ // ─────────────────────────────────────────────────────────────────────────────
41
+
42
+ // ── RULE ──────────────────────────────────────────────────────────────────────
43
+ // Never call `tables.X.put(partial)` directly anywhere in Flair resources.
44
+ // Harper put() = FULL RECORD REPLACEMENT. Missing fields are deleted permanently.
45
+ // Always use patchRecord() or patchRecordSilent().
46
+ // ─────────────────────────────────────────────────────────────────────────────
@@ -0,0 +1,22 @@
1
+ type Agent @table(database: "flair") @export {
2
+ id: ID @primaryKey
3
+ name: String!
4
+ role: String
5
+ type: String @indexed
6
+ publicKey: String!
7
+ createdAt: String!
8
+ updatedAt: String
9
+ }
10
+
11
+ type Integration @table(database: "flair") @export {
12
+ id: ID @primaryKey
13
+ agentId: String! @indexed
14
+ platform: String! @indexed
15
+ username: String
16
+ userId: String
17
+ email: String
18
+ encryptedCredential: String
19
+ metadata: String
20
+ createdAt: String!
21
+ updatedAt: String
22
+ }
@@ -0,0 +1,12 @@
1
+ type OrgEvent @table(database: "flair") @export {
2
+ id: ID @primaryKey
3
+ authorId: String! @indexed
4
+ kind: String! @indexed
5
+ scope: String @indexed
6
+ summary: String!
7
+ detail: String
8
+ targetIds: [String] @indexed
9
+ refId: String @indexed
10
+ createdAt: String! @indexed
11
+ expiresAt: String @indexed
12
+ }
@@ -0,0 +1,50 @@
1
+ type Memory @table(database: "flair") {
2
+ id: ID @primaryKey
3
+ agentId: String! @indexed
4
+ content: String!
5
+ contentHash: String @indexed
6
+ visibility: String
7
+ embedding: [Float] @indexed(type: "HNSW")
8
+ tags: [String] @indexed
9
+ durability: String @indexed
10
+ source: String
11
+ createdAt: String! @indexed
12
+ updatedAt: String
13
+ expiresAt: String @indexed
14
+ retrievalCount: Int
15
+ lastRetrieved: String
16
+ promotionStatus: String # null | "pending" | "approved" | "rejected"
17
+ promotedAt: String
18
+ promotedBy: String # authenticated agentId who approved
19
+ archived: Boolean @indexed
20
+ archivedAt: String
21
+ archivedBy: String # authenticated agentId who archived
22
+ # Learning pipeline fields
23
+ parentId: String # link to related memory
24
+ derivedFrom: [String] # source memory IDs this was reflected from
25
+ sessionId: String @indexed # originating session
26
+ lastReflected: String # ISO timestamp of last reflection pass
27
+ supersedes: String @indexed # ID of memory this one replaces (version chain)
28
+ subject: String @indexed # entity this memory is about (person, service, project)
29
+ }
30
+
31
+ type Soul @table(database: "flair") {
32
+ id: ID @primaryKey
33
+ agentId: String! @indexed
34
+ key: String! @indexed
35
+ value: String!
36
+ priority: String # critical | high | standard | low (skill governance)
37
+ metadata: String # JSON blob (skill governance: source, version, hash, etc.)
38
+ durability: String @indexed
39
+ createdAt: String!
40
+ updatedAt: String
41
+ }
42
+
43
+ type MemoryGrant @table(database: "flair") @export {
44
+ id: ID @primaryKey
45
+ ownerId: String!
46
+ granteeId: String!
47
+ scope: String!
48
+ filter: String
49
+ createdAt: String
50
+ }
@@ -0,0 +1,41 @@
1
+
2
+ # ─── Observatory tables ───────────────────────────────────────────────────────
3
+
4
+ type ObsOffice @table(database: "flair") @export {
5
+ id: ID @primaryKey # e.g. "rockit"
6
+ name: String!
7
+ publicKey: String! # Ed25519 hex public key for auth verification
8
+ status: String @indexed # "online" | "offline" | "degraded"
9
+ lastSeen: String
10
+ agentCount: Int
11
+ createdAt: String!
12
+ updatedAt: String
13
+ }
14
+
15
+ type ObsAgentSnapshot @table(database: "flair") @export {
16
+ id: ID @primaryKey # "{officeId}:{agentId}"
17
+ officeId: String! @indexed
18
+ agentId: String! @indexed
19
+ name: String
20
+ role: String
21
+ type: String # "agent" | "human"
22
+ model: String
23
+ status: String @indexed # "active" | "idle" | "offline"
24
+ currentTask: String
25
+ lastActivity: String
26
+ lastHeartbeat: String
27
+ updatedAt: String!
28
+ }
29
+
30
+ type ObsEventFeed @table(database: "flair") @export {
31
+ id: ID @primaryKey # "{officeId}:{eventId}"
32
+ officeId: String! @indexed
33
+ kind: String! @indexed
34
+ authorId: String! @indexed
35
+ summary: String!
36
+ refId: String @indexed
37
+ scope: String @indexed
38
+ createdAt: String! @indexed
39
+ receivedAt: String!
40
+ expiresAt: String @indexed
41
+ }
@@ -0,0 +1,14 @@
1
+ type WorkspaceState @table(database: "flair") @export {
2
+ id: ID @primaryKey
3
+ agentId: String! @indexed
4
+ ref: String!
5
+ label: String @indexed
6
+ provider: String!
7
+ timestamp: String! @indexed
8
+ metadata: String
9
+ taskId: String @indexed
10
+ phase: String @indexed
11
+ summary: String
12
+ filesChanged: [String]
13
+ createdAt: String!
14
+ }