@hasna/files 0.1.3 → 0.1.5
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/db/pg-migrations.d.ts +4 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +109 -0
- package/dist/mcp/index.js +40 -1
- package/package.json +5 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { getDb, DB_PATH } from "./db/database.js";
|
|
2
|
+
export { PG_MIGRATIONS } from "./db/pg-migrations.js";
|
|
2
3
|
export { getCurrentMachine, listMachines, getMachine, upsertMachine } from "./db/machines.js";
|
|
3
4
|
export { createSource, getSource, listSources, updateSource, deleteSource, markSourceIndexed } from "./db/sources.js";
|
|
4
5
|
export { upsertFile, getFile, listFiles, searchFiles as searchFilesDb, markFileDeleted, deleteFile, getFileByPath, refreshAllFts } from "./db/files.js";
|
package/dist/index.js
CHANGED
|
@@ -40073,6 +40073,114 @@ var migration_v3 = `
|
|
|
40073
40073
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
40074
40074
|
);
|
|
40075
40075
|
`;
|
|
40076
|
+
// src/db/pg-migrations.ts
|
|
40077
|
+
var PG_MIGRATIONS = [
|
|
40078
|
+
`CREATE TABLE IF NOT EXISTS machines (
|
|
40079
|
+
id TEXT PRIMARY KEY,
|
|
40080
|
+
name TEXT NOT NULL,
|
|
40081
|
+
hostname TEXT NOT NULL,
|
|
40082
|
+
platform TEXT NOT NULL,
|
|
40083
|
+
arch TEXT NOT NULL,
|
|
40084
|
+
is_current BOOLEAN NOT NULL DEFAULT FALSE,
|
|
40085
|
+
last_seen TEXT NOT NULL DEFAULT NOW()::text,
|
|
40086
|
+
created_at TEXT NOT NULL DEFAULT NOW()::text
|
|
40087
|
+
)`,
|
|
40088
|
+
`CREATE TABLE IF NOT EXISTS sources (
|
|
40089
|
+
id TEXT PRIMARY KEY,
|
|
40090
|
+
name TEXT NOT NULL,
|
|
40091
|
+
type TEXT NOT NULL CHECK(type IN ('local', 's3')),
|
|
40092
|
+
path TEXT,
|
|
40093
|
+
bucket TEXT,
|
|
40094
|
+
prefix TEXT,
|
|
40095
|
+
region TEXT,
|
|
40096
|
+
config TEXT NOT NULL DEFAULT '{}',
|
|
40097
|
+
machine_id TEXT NOT NULL REFERENCES machines(id) ON DELETE CASCADE,
|
|
40098
|
+
enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
|
40099
|
+
last_indexed_at TEXT,
|
|
40100
|
+
file_count INTEGER NOT NULL DEFAULT 0,
|
|
40101
|
+
created_at TEXT NOT NULL DEFAULT NOW()::text,
|
|
40102
|
+
updated_at TEXT NOT NULL DEFAULT NOW()::text
|
|
40103
|
+
)`,
|
|
40104
|
+
`CREATE TABLE IF NOT EXISTS files (
|
|
40105
|
+
id TEXT PRIMARY KEY,
|
|
40106
|
+
source_id TEXT NOT NULL REFERENCES sources(id) ON DELETE CASCADE,
|
|
40107
|
+
machine_id TEXT NOT NULL REFERENCES machines(id) ON DELETE CASCADE,
|
|
40108
|
+
path TEXT NOT NULL,
|
|
40109
|
+
name TEXT NOT NULL,
|
|
40110
|
+
ext TEXT NOT NULL DEFAULT '',
|
|
40111
|
+
size INTEGER NOT NULL DEFAULT 0,
|
|
40112
|
+
mime TEXT NOT NULL DEFAULT 'application/octet-stream',
|
|
40113
|
+
hash TEXT,
|
|
40114
|
+
status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active', 'deleted', 'moved')),
|
|
40115
|
+
indexed_at TEXT NOT NULL DEFAULT NOW()::text,
|
|
40116
|
+
modified_at TEXT,
|
|
40117
|
+
created_at TEXT NOT NULL DEFAULT NOW()::text,
|
|
40118
|
+
UNIQUE(source_id, path)
|
|
40119
|
+
)`,
|
|
40120
|
+
`CREATE TABLE IF NOT EXISTS tags (
|
|
40121
|
+
id TEXT PRIMARY KEY,
|
|
40122
|
+
name TEXT NOT NULL UNIQUE,
|
|
40123
|
+
color TEXT NOT NULL DEFAULT '#6366f1',
|
|
40124
|
+
created_at TEXT NOT NULL DEFAULT NOW()::text
|
|
40125
|
+
)`,
|
|
40126
|
+
`CREATE TABLE IF NOT EXISTS file_tags (
|
|
40127
|
+
file_id TEXT NOT NULL REFERENCES files(id) ON DELETE CASCADE,
|
|
40128
|
+
tag_id TEXT NOT NULL REFERENCES tags(id) ON DELETE CASCADE,
|
|
40129
|
+
created_at TEXT NOT NULL DEFAULT NOW()::text,
|
|
40130
|
+
PRIMARY KEY (file_id, tag_id)
|
|
40131
|
+
)`,
|
|
40132
|
+
`CREATE TABLE IF NOT EXISTS collections (
|
|
40133
|
+
id TEXT PRIMARY KEY,
|
|
40134
|
+
name TEXT NOT NULL,
|
|
40135
|
+
description TEXT NOT NULL DEFAULT '',
|
|
40136
|
+
created_at TEXT NOT NULL DEFAULT NOW()::text,
|
|
40137
|
+
updated_at TEXT NOT NULL DEFAULT NOW()::text
|
|
40138
|
+
)`,
|
|
40139
|
+
`CREATE TABLE IF NOT EXISTS collection_files (
|
|
40140
|
+
collection_id TEXT NOT NULL REFERENCES collections(id) ON DELETE CASCADE,
|
|
40141
|
+
file_id TEXT NOT NULL REFERENCES files(id) ON DELETE CASCADE,
|
|
40142
|
+
added_at TEXT NOT NULL DEFAULT NOW()::text,
|
|
40143
|
+
PRIMARY KEY (collection_id, file_id)
|
|
40144
|
+
)`,
|
|
40145
|
+
`CREATE TABLE IF NOT EXISTS projects (
|
|
40146
|
+
id TEXT PRIMARY KEY,
|
|
40147
|
+
name TEXT NOT NULL,
|
|
40148
|
+
description TEXT NOT NULL DEFAULT '',
|
|
40149
|
+
created_at TEXT NOT NULL DEFAULT NOW()::text,
|
|
40150
|
+
updated_at TEXT NOT NULL DEFAULT NOW()::text
|
|
40151
|
+
)`,
|
|
40152
|
+
`CREATE TABLE IF NOT EXISTS project_files (
|
|
40153
|
+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
40154
|
+
file_id TEXT NOT NULL REFERENCES files(id) ON DELETE CASCADE,
|
|
40155
|
+
added_at TEXT NOT NULL DEFAULT NOW()::text,
|
|
40156
|
+
PRIMARY KEY (project_id, file_id)
|
|
40157
|
+
)`,
|
|
40158
|
+
`CREATE INDEX IF NOT EXISTS idx_files_source ON files(source_id)`,
|
|
40159
|
+
`CREATE INDEX IF NOT EXISTS idx_files_machine ON files(machine_id)`,
|
|
40160
|
+
`CREATE INDEX IF NOT EXISTS idx_files_ext ON files(ext)`,
|
|
40161
|
+
`CREATE INDEX IF NOT EXISTS idx_files_status ON files(status)`,
|
|
40162
|
+
`CREATE INDEX IF NOT EXISTS idx_files_hash ON files(hash)`,
|
|
40163
|
+
`CREATE INDEX IF NOT EXISTS idx_sources_machine ON sources(machine_id)`,
|
|
40164
|
+
`CREATE INDEX IF NOT EXISTS idx_sources_type ON sources(type)`,
|
|
40165
|
+
`CREATE TABLE IF NOT EXISTS peers (
|
|
40166
|
+
id TEXT PRIMARY KEY,
|
|
40167
|
+
url TEXT NOT NULL UNIQUE,
|
|
40168
|
+
name TEXT NOT NULL DEFAULT '',
|
|
40169
|
+
last_synced_at TEXT,
|
|
40170
|
+
auto_sync BOOLEAN NOT NULL DEFAULT FALSE,
|
|
40171
|
+
sync_interval_minutes INTEGER NOT NULL DEFAULT 30,
|
|
40172
|
+
created_at TEXT NOT NULL DEFAULT NOW()::text
|
|
40173
|
+
)`,
|
|
40174
|
+
`CREATE TABLE IF NOT EXISTS feedback (
|
|
40175
|
+
id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
|
|
40176
|
+
message TEXT NOT NULL,
|
|
40177
|
+
email TEXT,
|
|
40178
|
+
category TEXT DEFAULT 'general',
|
|
40179
|
+
version TEXT,
|
|
40180
|
+
machine_id TEXT,
|
|
40181
|
+
created_at TEXT NOT NULL DEFAULT NOW()::text
|
|
40182
|
+
)`
|
|
40183
|
+
];
|
|
40076
40184
|
// node_modules/nanoid/index.js
|
|
40077
40185
|
import { webcrypto as crypto2 } from "crypto";
|
|
40078
40186
|
|
|
@@ -52645,5 +52753,6 @@ export {
|
|
|
52645
52753
|
createCollection,
|
|
52646
52754
|
addToProject,
|
|
52647
52755
|
addToCollection,
|
|
52756
|
+
PG_MIGRATIONS,
|
|
52648
52757
|
DB_PATH
|
|
52649
52758
|
};
|
package/dist/mcp/index.js
CHANGED
|
@@ -40027,7 +40027,7 @@ var init_dist_es9 = __esm(() => {
|
|
|
40027
40027
|
var require_package2 = __commonJS((exports, module) => {
|
|
40028
40028
|
module.exports = {
|
|
40029
40029
|
name: "@hasna/files",
|
|
40030
|
-
version: "0.1.
|
|
40030
|
+
version: "0.1.5",
|
|
40031
40031
|
description: "Agent-first file management \u2014 index local folders and S3 buckets, tag, search, and retrieve files via CLI + MCP",
|
|
40032
40032
|
type: "module",
|
|
40033
40033
|
main: "dist/index.js",
|
|
@@ -54955,6 +54955,7 @@ async function getPresignedUrl(source, filePath, expiresIn = 3600) {
|
|
|
54955
54955
|
import { join as join8 } from "path";
|
|
54956
54956
|
import { existsSync as existsSync4 } from "fs";
|
|
54957
54957
|
import { homedir as homedir6 } from "os";
|
|
54958
|
+
var _filesAgents = new Map;
|
|
54958
54959
|
var server = new McpServer({
|
|
54959
54960
|
name: "files",
|
|
54960
54961
|
version: "0.1.0"
|
|
@@ -55286,6 +55287,44 @@ server.tool("send_feedback", "Send feedback about this service", {
|
|
|
55286
55287
|
return { content: [{ type: "text", text: String(e2) }], isError: true };
|
|
55287
55288
|
}
|
|
55288
55289
|
});
|
|
55290
|
+
server.tool("register_agent", "Register an agent session. Returns agent_id. Auto-triggers a heartbeat.", {
|
|
55291
|
+
name: exports_external.string(),
|
|
55292
|
+
session_id: exports_external.string().optional()
|
|
55293
|
+
}, async (params) => {
|
|
55294
|
+
const existing = [..._filesAgents.values()].find((a2) => a2.name === params.name);
|
|
55295
|
+
if (existing) {
|
|
55296
|
+
existing.last_seen_at = new Date().toISOString();
|
|
55297
|
+
if (params.session_id)
|
|
55298
|
+
existing.session_id = params.session_id;
|
|
55299
|
+
return { content: [{ type: "text", text: JSON.stringify(existing) }] };
|
|
55300
|
+
}
|
|
55301
|
+
const id = Math.random().toString(36).slice(2, 10);
|
|
55302
|
+
const ag2 = { id, name: params.name, session_id: params.session_id, last_seen_at: new Date().toISOString() };
|
|
55303
|
+
_filesAgents.set(id, ag2);
|
|
55304
|
+
return { content: [{ type: "text", text: JSON.stringify(ag2) }] };
|
|
55305
|
+
});
|
|
55306
|
+
server.tool("heartbeat", "Update last_seen_at to signal agent is active.", {
|
|
55307
|
+
agent_id: exports_external.string()
|
|
55308
|
+
}, async (params) => {
|
|
55309
|
+
const ag2 = _filesAgents.get(params.agent_id);
|
|
55310
|
+
if (!ag2)
|
|
55311
|
+
return { content: [{ type: "text", text: `Agent not found: ${params.agent_id}` }], isError: true };
|
|
55312
|
+
ag2.last_seen_at = new Date().toISOString();
|
|
55313
|
+
return { content: [{ type: "text", text: JSON.stringify({ agent_id: ag2.id, last_seen_at: ag2.last_seen_at }) }] };
|
|
55314
|
+
});
|
|
55315
|
+
server.tool("set_focus", "Set active project context for this agent session.", {
|
|
55316
|
+
agent_id: exports_external.string(),
|
|
55317
|
+
project_id: exports_external.string().optional()
|
|
55318
|
+
}, async (params) => {
|
|
55319
|
+
const ag2 = _filesAgents.get(params.agent_id);
|
|
55320
|
+
if (!ag2)
|
|
55321
|
+
return { content: [{ type: "text", text: `Agent not found: ${params.agent_id}` }], isError: true };
|
|
55322
|
+
ag2.project_id = params.project_id;
|
|
55323
|
+
return { content: [{ type: "text", text: JSON.stringify({ agent_id: ag2.id, project_id: ag2.project_id ?? null }) }] };
|
|
55324
|
+
});
|
|
55325
|
+
server.tool("list_agents", "List all registered agents.", {}, async () => {
|
|
55326
|
+
return { content: [{ type: "text", text: JSON.stringify([..._filesAgents.values()]) }] };
|
|
55327
|
+
});
|
|
55289
55328
|
var machine = getCurrentMachine();
|
|
55290
55329
|
var allSources = listSources(machine.id).filter((s2) => s2.enabled);
|
|
55291
55330
|
for (const source of allSources) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hasna/files",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Agent-first file management
|
|
3
|
+
"version": "0.1.5",
|
|
4
|
+
"description": "Agent-first file management \u2014 index local folders and S3 buckets, tag, search, and retrieve files via CLI + MCP",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
"test": "bun test",
|
|
34
34
|
"dev:cli": "bun run src/cli/index.tsx",
|
|
35
35
|
"dev:mcp": "bun run src/mcp/index.ts",
|
|
36
|
-
"dev:serve": "bun run src/server/index.ts"
|
|
36
|
+
"dev:serve": "bun run src/server/index.ts",
|
|
37
|
+
"postinstall": "mkdir -p $HOME/.hasna/files 2>/dev/null || true"
|
|
37
38
|
},
|
|
38
39
|
"keywords": [
|
|
39
40
|
"files",
|
|
@@ -75,4 +76,4 @@
|
|
|
75
76
|
"bun-types": "latest",
|
|
76
77
|
"typescript": "^5.8.2"
|
|
77
78
|
}
|
|
78
|
-
}
|
|
79
|
+
}
|