suemo 0.0.7 → 0.0.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "suemo",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "Persistent semantic memory for AI agents — backed by SurrealDB.",
5
5
  "author": {
6
6
  "name": "Umar Alfarouk",
@@ -27,7 +27,7 @@
27
27
  "bin": {
28
28
  "suemo": "./src/cli/index.ts"
29
29
  },
30
- "files": ["src", "LICENSE", "README.md"],
30
+ "files": ["src", "skills", "LICENSE", "README.md", "tsconfig.json"],
31
31
  "exports": {
32
32
  ".": {
33
33
  "bun": "./src/index.ts",
@@ -0,0 +1,35 @@
1
+ ---
2
+ name: suemo
3
+ description: OpenCode-focused persistent memory workflow for suemo with CLI/MCP parity and versioned references.
4
+ version: 0.0.8
5
+ ---
6
+
7
+ # suemo skill
8
+
9
+ Use suemo to persist technical context across sessions with minimal, project-scoped memory.
10
+
11
+ ## Quick use
12
+
13
+ - CLI latest skill: `suemo skill`
14
+ - CLI specific reference: `suemo skill <reference-name>`
15
+ - MCP latest skill: `skill({})`
16
+ - MCP specific reference: `skill({ reference: "<reference-name>" })`
17
+
18
+ ## Reference names
19
+
20
+ - `agents-snippet`
21
+ - `cli-reference`
22
+ - `core-workflow`
23
+ - `manual-test-plan`
24
+ - `mcp-reference`
25
+ - `schema-retention-longevity`
26
+ - `sync-local-vps`
27
+
28
+ ## Operating model
29
+
30
+ 1. Query first: reuse prior knowledge before implementation.
31
+ 2. Observe/believe during work (not only at the end).
32
+ 3. Use episode + context for session continuity.
33
+ 4. Keep scope project-bound via inferred scope unless explicitly overridden.
34
+
35
+ For full details, read references via `suemo skill <reference-name>`.
@@ -0,0 +1,36 @@
1
+ ---
2
+ name: agents-snippet
3
+ description: AGENTS.md snippet optimized for suemo skill discovery and usage.
4
+ version: 0.0.8
5
+ ---
6
+
7
+ # AGENTS.md snippet
8
+
9
+ ```md
10
+ ## suemo-first memory workflow
11
+
12
+ Before significant work:
13
+
14
+ - query("what do I know about <topic>")
15
+
16
+ If you need latest usage docs:
17
+
18
+ - suemo skill
19
+ - suemo skill core-workflow
20
+ - suemo skill mcp-reference
21
+
22
+ During work:
23
+
24
+ - observe("...") for concrete facts
25
+ - believe("...") for conclusions
26
+ - goal_set("...") for long tasks
27
+
28
+ After completion:
29
+
30
+ - goal_resolve("...") if applicable
31
+ - episode_end(sessionId, summary="...")
32
+
33
+ After compaction/reset:
34
+
35
+ - context({ scope: "<project-id>", limit: 20 })
36
+ ```
@@ -0,0 +1,44 @@
1
+ ---
2
+ name: cli-reference
3
+ description: CLI command reference for suemo v0.0.6 including skill access.
4
+ version: 0.0.8
5
+ ---
6
+
7
+ # CLI reference
8
+
9
+ Core:
10
+
11
+ - `suemo init config`
12
+ - `suemo init schema`
13
+ - `suemo init opencode`
14
+ - `suemo serve [--stdio|--dev]`
15
+ - `suemo skill [reference]`
16
+
17
+ Memory:
18
+
19
+ - `suemo observe <content>`
20
+ - `suemo believe <content>`
21
+ - `suemo query <input>`
22
+ - `suemo recall <nodeId>`
23
+ - `suemo wander`
24
+ - `suemo timeline`
25
+ - `suemo consolidate [--nrem-only]`
26
+
27
+ Goals:
28
+
29
+ - `suemo goal set <content>`
30
+ - `suemo goal list`
31
+ - `suemo goal resolve <id>`
32
+
33
+ Ops:
34
+
35
+ - `suemo sync --direction push|pull|both [--remote <name>] [--dry-run]`
36
+ - `suemo export`
37
+ - `suemo import <file>`
38
+ - `suemo health|health vitals|health stats`
39
+
40
+ JSON modes:
41
+
42
+ - `--json`
43
+ - `--pretty`
44
+ - `--verbose-json` (implies `--json`, includes embeddings)
@@ -0,0 +1,40 @@
1
+ ---
2
+ name: core-workflow
3
+ description: Canonical suemo operating loop for OpenCode agents.
4
+ version: 0.0.8
5
+ ---
6
+
7
+ # Core workflow
8
+
9
+ 1. Start with memory lookup:
10
+
11
+ ```ts
12
+ query('what do I know about <topic>')
13
+ ```
14
+
15
+ 2. During work, persist concrete discoveries:
16
+
17
+ ```ts
18
+ observe('...')
19
+ believe('...')
20
+ ```
21
+
22
+ 3. For long tasks:
23
+
24
+ ```ts
25
+ goal_set('...')
26
+ ```
27
+
28
+ 4. If compaction/reset happened:
29
+
30
+ ```ts
31
+ context({ scope: '<project-id>', limit: 20 })
32
+ ```
33
+
34
+ 5. Close session:
35
+
36
+ ```ts
37
+ episode_end(sessionId, summary = '...')
38
+ ```
39
+
40
+ Prefer project-scoped memory. Let suemo infer scope from nearest `{projectDir}/suemo.json` (recommended `main.projectDir = '.ua'`).
@@ -0,0 +1,77 @@
1
+ ---
2
+ name: manual-test-plan
3
+ description: Comprehensive manual test matrix for suemo features and commands.
4
+ version: 0.0.8
5
+ ---
6
+
7
+ # Manual test plan
8
+
9
+ ## A. Setup and compatibility
10
+
11
+ 1. `suemo init config`
12
+ 2. `suemo init schema`
13
+ 3. `suemo health`
14
+ 4. `suemo doctor embed` (informational when embeddings unavailable)
15
+
16
+ Expected:
17
+
18
+ - clean startup, schema idempotent, health/stats readable
19
+
20
+ ## B. Scope inference
21
+
22
+ 1. Ensure `.ua/suemo.json` exists (or let suemo create)
23
+ 2. Run `observe`, `query`, `goal list` without `--scope`
24
+ 3. Verify records are in inferred scope
25
+
26
+ ## C. Memory lifecycle
27
+
28
+ 1. `observe`
29
+ 2. duplicate `observe` (dedup merge expected in same scope)
30
+ 3. `believe` then conflicting `believe` (invalidation + relation)
31
+ 4. `recall`, `timeline`, `wander`
32
+ 5. `update` by node id and re-query
33
+
34
+ ## D. Session/episode/context
35
+
36
+ 1. `episode_start`
37
+ 2. add observations with `sessionId`
38
+ 3. `session_context_set`
39
+ 4. `context`
40
+ 5. `episode_end` with structured fields
41
+ 6. verify episode fields persisted
42
+
43
+ ## E. Goals
44
+
45
+ 1. `goal set`
46
+ 2. `goal list`
47
+ 3. `goal resolve`
48
+ 4. `goal list --resolved`
49
+
50
+ ## F. Consolidation
51
+
52
+ 1. seed enough unconsolidated memories
53
+ 2. run `consolidate --nrem-only`
54
+ 3. run full `consolidate`
55
+ 4. verify derived nodes/relations and no cross-scope contamination
56
+
57
+ ## G. Sync/export/import
58
+
59
+ 1. `export` and `import` roundtrip (memory + relation + episode)
60
+ 2. `sync` push/pull/both with cursor sanity
61
+ 3. auto-sync with write trigger and timer
62
+
63
+ ## H. Skill docs access
64
+
65
+ 1. `suemo skill`
66
+ 2. `suemo skill core-workflow`
67
+ 3. MCP `skill({})`, `skill({ reference: "cli-reference" })`
68
+
69
+ ## I. Output modes
70
+
71
+ Repeat representative commands under:
72
+
73
+ - `--pretty`
74
+ - `--json`
75
+ - `--verbose-json`
76
+
77
+ Verify embeddings are hidden in `--json` and visible in `--verbose-json`.
@@ -0,0 +1,46 @@
1
+ ---
2
+ name: mcp-reference
3
+ description: MCP tool reference for suemo v0.0.6.
4
+ version: 0.0.8
5
+ ---
6
+
7
+ # MCP tools
8
+
9
+ Write/mutate:
10
+
11
+ - `observe`
12
+ - `believe`
13
+ - `invalidate`
14
+ - `upsert_by_key`
15
+ - `update`
16
+ - `capture_prompt`
17
+ - `goal_set`
18
+ - `goal_resolve`
19
+ - `episode_start`
20
+ - `episode_end`
21
+ - `session_context_set`
22
+
23
+ Read/retrieve:
24
+
25
+ - `query`
26
+ - `recall`
27
+ - `wander`
28
+ - `timeline`
29
+ - `context`
30
+ - `goal_list`
31
+ - `session_context_get`
32
+ - `health`
33
+ - `vitals`
34
+ - `stats`
35
+ - `suggest_topic_key`
36
+ - `skill`
37
+
38
+ Maintenance:
39
+
40
+ - `consolidate` (supports optional `scope`)
41
+
42
+ Notes:
43
+
44
+ - Optional `scope` defaults to inferred project id.
45
+ - `update` re-embeds when `content` changes.
46
+ - `episode_end` accepts structured fields (`goal`, `discoveries`, `accomplished`, `files_changed`).
@@ -0,0 +1,31 @@
1
+ ---
2
+ name: schema-retention-longevity
3
+ description: Long-term schema and retention design expectations for suemo.
4
+ version: 0.0.8
5
+ ---
6
+
7
+ # Schema + retention longevity
8
+
9
+ ## Required invariants
10
+
11
+ 1. Scope isolation for semantic operations (dedup, contradiction, upsert-by-key, consolidation).
12
+ 2. Retention checks fail closed when probe cannot prove ≥90d time-travel reach.
13
+ 3. Sync/export/import cover `memory`, `relates_to`, and `episode`.
14
+ 4. Cursor advancement only after successful sync batch completion.
15
+ 5. Additive schema changes preferred; idempotent `DEFINE ... OVERWRITE` remains stable.
16
+
17
+ ## Index baseline
18
+
19
+ - `memory(embedding)` HNSW
20
+ - `memory(content)` + `memory(summary)` fulltext
21
+ - `memory(scope, created_at)`, `memory(kind, valid_until)`, `memory(salience)`, `memory(topic_key)`
22
+ - `memory(updated_at)`
23
+ - `relates_to(updated_at)`
24
+ - `episode(session_id, ended_at, started_at)`
25
+ - `episode(updated_at)`
26
+
27
+ ## Operational checks
28
+
29
+ - Run schema repeatedly (idempotence check).
30
+ - Validate retention probe against deployed Surreal flags.
31
+ - Verify scoped operations do not mutate or merge cross-project data.
@@ -0,0 +1,26 @@
1
+ ---
2
+ name: sync-local-vps
3
+ description: Two-way sync manual scenario for local and VPS SurrealDB.
4
+ version: 0.0.8
5
+ ---
6
+
7
+ # Local ↔ VPS sync scenario
8
+
9
+ Use this as canonical two-way sync validation.
10
+
11
+ 1. Prepare isolated scope (`sync-smoke-<timestamp>`)
12
+ 2. Local write → `sync --direction push`
13
+ 3. VPS write → `sync --direction pull`
14
+ 4. Conflict smoke: update same memory both sides, run `sync --direction both`
15
+ 5. Invalidation propagation smoke
16
+ 6. Auto-sync smoke with `serve --stdio` and write-trigger
17
+ 7. Cursor sanity (two immediate sync runs)
18
+
19
+ Expected outcomes:
20
+
21
+ - no data loss
22
+ - LWW behavior consistent
23
+ - invalidation propagates
24
+ - cursor advances only on successful syncs
25
+
26
+ Detailed command walkthrough remains available at `data/scenarios/sync-local-vps.md`.
@@ -394,7 +394,7 @@ function extractEnvValue(content: string, key: string): string | null {
394
394
  }
395
395
 
396
396
  function readFastembedScriptSource(): string {
397
- const path = fileURLToPath(new URL('../../../data/fastembed-server.py', import.meta.url))
397
+ const path = fileURLToPath(new URL('../embedding/fastembed-server.py', import.meta.url))
398
398
  return readFileSync(path, 'utf-8')
399
399
  }
400
400
 
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env python3
2
+ # fastembed.py
3
+ # Run: pacman -S python-fastembed python-fastapi python-uvicorn
4
+ # Start: python fastembed.py
5
+
6
+ from contextlib import asynccontextmanager
7
+ import os
8
+ from pathlib import Path
9
+ from fastapi import FastAPI
10
+ from fastembed import TextEmbedding
11
+ from pydantic import BaseModel
12
+ import uvicorn
13
+
14
+ MODEL_NAME = os.getenv("FASTEMBED_MODEL", "sentence-transformers/all-MiniLM-L6-v2")
15
+ CACHE_DIR = Path(
16
+ os.getenv("FASTEMBED_CACHE_DIR", str(Path.home() / ".cache" / "fastembed"))
17
+ )
18
+ HOST = os.getenv("FASTEMBED_HOST", "127.0.0.1")
19
+ PORT = int(os.getenv("FASTEMBED_PORT", "8080"))
20
+ _model: TextEmbedding | None = None
21
+
22
+
23
+ @asynccontextmanager
24
+ async def lifespan(app: FastAPI):
25
+ global _model
26
+ CACHE_DIR.mkdir(parents=True, exist_ok=True)
27
+ print(f"Loading {MODEL_NAME} (cache: {CACHE_DIR})...")
28
+ _model = TextEmbedding(model_name=MODEL_NAME, cache_dir=str(CACHE_DIR))
29
+ print("Model ready.")
30
+ yield
31
+
32
+
33
+ app = FastAPI(lifespan=lifespan)
34
+
35
+
36
+ class EmbedRequest(BaseModel):
37
+ input: str | list[str] # OpenAI-compatible field name
38
+ model: str = MODEL_NAME
39
+
40
+
41
+ class EmbedResponse(BaseModel):
42
+ object: str = "list"
43
+ data: list[dict]
44
+ model: str
45
+ usage: dict
46
+
47
+
48
+ @app.post("/v1/embeddings")
49
+ def embed(req: EmbedRequest) -> EmbedResponse:
50
+ texts = [req.input] if isinstance(req.input, str) else req.input
51
+ vectors = list(_model.embed(texts)) # type: ignore
52
+ return EmbedResponse(
53
+ data=[
54
+ {"object": "embedding", "index": i, "embedding": v.tolist()}
55
+ for i, v in enumerate(vectors)
56
+ ],
57
+ model=MODEL_NAME,
58
+ usage={"prompt_tokens": sum(len(t.split()) for t in texts), "total_tokens": 0},
59
+ )
60
+
61
+
62
+ @app.get("/health")
63
+ def health():
64
+ return {"status": "ok", "model": MODEL_NAME, "dimension": 384}
65
+
66
+
67
+ if __name__ == "__main__":
68
+ uvicorn.run(app, host=HOST, port=PORT)
package/tsconfig.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "compilerOptions": {
3
+ "lib": ["ESNext"],
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "moduleDetection": "force",
7
+ "resolveJsonModule": true,
8
+
9
+ "target": "ESNext",
10
+ "noEmit": true,
11
+ "isolatedModules": true,
12
+
13
+ "rewriteRelativeImportExtensions": true,
14
+ "allowImportingTsExtensions": true,
15
+ "verbatimModuleSyntax": true,
16
+
17
+ "strict": true,
18
+ "noUncheckedIndexedAccess": true,
19
+ "exactOptionalPropertyTypes": true,
20
+ "noUnusedLocals": true,
21
+
22
+ "skipLibCheck": true,
23
+
24
+ "paths": {
25
+ "@/*": ["./*"]
26
+ }
27
+ },
28
+ "include": ["src/**/*", "suemo.config.ts"]
29
+ }