@schift-io/memory 0.1.0 → 0.1.1
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/hooks/session-start +1 -1
- package/mcp-server.js +7 -3
- package/package.json +4 -1
- package/scripts/auto-ingest-url.sh +16 -8
- package/scripts/init.sh +4 -4
- package/scripts/login.sh +3 -3
package/hooks/session-start
CHANGED
|
@@ -18,7 +18,7 @@ ENDJSON
|
|
|
18
18
|
fi
|
|
19
19
|
|
|
20
20
|
# Validate key is not empty/expired
|
|
21
|
-
api_key=$(
|
|
21
|
+
api_key=$(node -e "try{const d=JSON.parse(require('fs').readFileSync('${AUTH_FILE}','utf-8'));process.stdout.write(d.api_key||'')}catch{}" 2>/dev/null || echo "")
|
|
22
22
|
if [ -z "$api_key" ]; then
|
|
23
23
|
cat <<ENDJSON
|
|
24
24
|
{
|
package/mcp-server.js
CHANGED
|
@@ -92,7 +92,9 @@ const TOOLS = [
|
|
|
92
92
|
|
|
93
93
|
async function handleToolCall(name, args) {
|
|
94
94
|
switch (name) {
|
|
95
|
-
case 'save_url':
|
|
95
|
+
case 'save_url': {
|
|
96
|
+
try { new URL(args.url); } catch { throw new Error(`Invalid URL: ${args.url}`); }
|
|
97
|
+
if (!/^https?:$/.test(new URL(args.url).protocol)) throw new Error('Only http/https URLs are supported');
|
|
96
98
|
return apiCall('/v1/memory/ingest-url', {
|
|
97
99
|
url: args.url,
|
|
98
100
|
domain: args.domain || 'ops',
|
|
@@ -100,7 +102,7 @@ async function handleToolCall(name, args) {
|
|
|
100
102
|
summary: args.summary,
|
|
101
103
|
context: args.context,
|
|
102
104
|
findings: args.findings,
|
|
103
|
-
});
|
|
105
|
+
});}
|
|
104
106
|
|
|
105
107
|
case 'save_note':
|
|
106
108
|
return apiCall('/v1/memory/compact', {
|
|
@@ -122,7 +124,9 @@ async function handleToolCall(name, args) {
|
|
|
122
124
|
const auth = loadAuth();
|
|
123
125
|
if (!auth) return { status: 'not_authenticated', message: 'Run: npx @schift-io/memory login' };
|
|
124
126
|
try {
|
|
125
|
-
const resp = await fetch(`${auth.url}/
|
|
127
|
+
const resp = await fetch(`${auth.url}/v1/organizations/me`, {
|
|
128
|
+
headers: { 'Authorization': `Bearer ${auth.key}` },
|
|
129
|
+
});
|
|
126
130
|
return { status: 'connected', cloud_url: auth.url, healthy: resp.ok };
|
|
127
131
|
} catch (e) {
|
|
128
132
|
return { status: 'error', message: e.message };
|
package/package.json
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@schift-io/memory",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Second brain for Claude Code - saves conversations and web content to Schift Cloud",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=18"
|
|
9
|
+
},
|
|
7
10
|
"bin": {
|
|
8
11
|
"schift-memory-mcp": "./mcp-server.js"
|
|
9
12
|
},
|
|
@@ -1,22 +1,30 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# Post-WebFetch hook:
|
|
3
|
-
# This runs async after WebFetch calls - it queues the URL for next prompt
|
|
2
|
+
# Post-WebFetch hook: queues URLs for save prompt
|
|
4
3
|
set -euo pipefail
|
|
5
4
|
|
|
6
|
-
SCHIFT_API="${SCHIFT_API_URL:-http://localhost:8787}"
|
|
7
|
-
SCHIFT_KEY="${SCHIFT_API_KEY:-local}"
|
|
8
5
|
QUEUE_FILE="$HOME/.schift/memory/queue/pending-urls.jsonl"
|
|
9
6
|
|
|
10
7
|
# Read tool input from stdin (Claude Code passes hook context)
|
|
11
8
|
input=$(cat 2>/dev/null || echo "{}")
|
|
12
|
-
url=$(echo "$input" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('tool_input',{}).get('url',''))" 2>/dev/null || echo "")
|
|
13
9
|
|
|
14
|
-
|
|
10
|
+
# Use node (guaranteed in Claude Code) instead of python3
|
|
11
|
+
url=$(node -e "
|
|
12
|
+
try {
|
|
13
|
+
const d = JSON.parse(process.argv[1]);
|
|
14
|
+
const u = (d.tool_input || {}).url || '';
|
|
15
|
+
if (u) process.stdout.write(u);
|
|
16
|
+
} catch {}
|
|
17
|
+
" "$input" 2>/dev/null || echo "")
|
|
18
|
+
|
|
19
|
+
if [ -z "$url" ]; then
|
|
15
20
|
exit 0
|
|
16
21
|
fi
|
|
17
22
|
|
|
18
|
-
#
|
|
23
|
+
# Safe JSON serialization via node
|
|
19
24
|
mkdir -p "$(dirname "$QUEUE_FILE")"
|
|
20
|
-
|
|
25
|
+
node -e "
|
|
26
|
+
const line = JSON.stringify({ url: process.argv[1], timestamp: new Date().toISOString() });
|
|
27
|
+
process.stdout.write(line + '\n');
|
|
28
|
+
" "$url" >> "$QUEUE_FILE"
|
|
21
29
|
|
|
22
30
|
exit 0
|
package/scripts/init.sh
CHANGED
|
@@ -21,7 +21,7 @@ if [ ! -f "$AUTH_FILE" ]; then
|
|
|
21
21
|
exit 1
|
|
22
22
|
fi
|
|
23
23
|
|
|
24
|
-
api_key=$(
|
|
24
|
+
api_key=$(node -e "try{process.stdout.write(JSON.parse(require('fs').readFileSync('${AUTH_FILE}','utf-8')).api_key||'')}catch{}" 2>/dev/null || echo "")
|
|
25
25
|
if [ -z "$api_key" ]; then
|
|
26
26
|
echo " Auth file exists but API key is missing."
|
|
27
27
|
echo " Run: npx @schift-io/memory login"
|
|
@@ -30,10 +30,10 @@ fi
|
|
|
30
30
|
|
|
31
31
|
# --- Step 2: Validate key against Schift Cloud ---
|
|
32
32
|
echo " Validating Schift account..."
|
|
33
|
-
cloud_url=$(
|
|
33
|
+
cloud_url=$(node -e "try{process.stdout.write(JSON.parse(require('fs').readFileSync('${AUTH_FILE}','utf-8')).cloud_url||'${SCHIFT_CLOUD}')}catch{process.stdout.write('${SCHIFT_CLOUD}')}" 2>/dev/null || echo "${SCHIFT_CLOUD}")
|
|
34
34
|
validate=$(curl -sf -o /dev/null -w "%{http_code}" \
|
|
35
35
|
-H "Authorization: Bearer ${api_key}" \
|
|
36
|
-
"${cloud_url}/v1/me" 2>/dev/null || echo "000")
|
|
36
|
+
"${cloud_url}/v1/organizations/me" 2>/dev/null || echo "000")
|
|
37
37
|
|
|
38
38
|
if [ "$validate" != "200" ]; then
|
|
39
39
|
echo " API key is invalid or expired."
|
|
@@ -49,7 +49,7 @@ mkdir -p "$HOME/.schift/memory"/{config,sources/web,compact/session,compact/topi
|
|
|
49
49
|
|
|
50
50
|
# --- Step 4: Bootstrap bucket on Schift Cloud ---
|
|
51
51
|
echo " Creating knowledge bucket on Schift Cloud..."
|
|
52
|
-
curl -sf -X POST "${cloud_url}/v1/
|
|
52
|
+
curl -sf -X POST "${cloud_url}/v1/memory/bootstrap" \
|
|
53
53
|
-H "Content-Type: application/json" \
|
|
54
54
|
-H "Authorization: Bearer ${api_key}" > /dev/null 2>&1 || true
|
|
55
55
|
|
package/scripts/login.sh
CHANGED
|
@@ -13,11 +13,11 @@ echo ""
|
|
|
13
13
|
|
|
14
14
|
# Check if already logged in
|
|
15
15
|
if [ -f "$AUTH_FILE" ]; then
|
|
16
|
-
existing_key=$(
|
|
16
|
+
existing_key=$(node -e "try{process.stdout.write(JSON.parse(require('fs').readFileSync('${AUTH_FILE}','utf-8')).api_key||'')}catch{}" 2>/dev/null || echo "")
|
|
17
17
|
if [ -n "$existing_key" ]; then
|
|
18
18
|
validate=$(curl -sf -o /dev/null -w "%{http_code}" \
|
|
19
19
|
-H "Authorization: Bearer ${existing_key}" \
|
|
20
|
-
"${SCHIFT_CLOUD}/v1/me" 2>/dev/null || echo "000")
|
|
20
|
+
"${SCHIFT_CLOUD}/v1/organizations/me" 2>/dev/null || echo "000")
|
|
21
21
|
if [ "$validate" = "200" ]; then
|
|
22
22
|
echo " Already logged in. Account is valid."
|
|
23
23
|
echo " To re-login, delete: ${AUTH_FILE}"
|
|
@@ -41,7 +41,7 @@ fi
|
|
|
41
41
|
echo " Validating..."
|
|
42
42
|
validate=$(curl -sf -o /dev/null -w "%{http_code}" \
|
|
43
43
|
-H "Authorization: Bearer ${api_key}" \
|
|
44
|
-
"${SCHIFT_CLOUD}/v1/me" 2>/dev/null || echo "000")
|
|
44
|
+
"${SCHIFT_CLOUD}/v1/organizations/me" 2>/dev/null || echo "000")
|
|
45
45
|
|
|
46
46
|
if [ "$validate" != "200" ]; then
|
|
47
47
|
echo " Invalid API key. Check your key and try again."
|