artisense 0.1.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 (2) hide show
  1. package/dist/index.js +304 -0
  2. package/package.json +17 -0
package/dist/index.js ADDED
@@ -0,0 +1,304 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/commands/skill.ts
4
+ import { mkdir, writeFile } from "node:fs/promises";
5
+ import { resolve as resolve2, dirname } from "node:path";
6
+
7
+ // src/config.ts
8
+ import { readFile } from "node:fs/promises";
9
+ import { resolve } from "node:path";
10
+ var DEFAULT_BASE_URL = "https://artisense.app";
11
+ function getApiKey() {
12
+ const key = process.env.ARTISENSE_API_KEY;
13
+ if (!key) {
14
+ console.error(`Error: ARTISENSE_API_KEY is not set.
15
+ Set it in your .env or shell environment.`);
16
+ process.exit(1);
17
+ }
18
+ return key;
19
+ }
20
+ async function getBaseUrl() {
21
+ if (process.env.ARTISENSE_BASE_URL) {
22
+ return process.env.ARTISENSE_BASE_URL.replace(/\/$/, "");
23
+ }
24
+ try {
25
+ const skillPath = resolve(process.cwd(), "SKILL.md");
26
+ const content = await readFile(skillPath, "utf-8");
27
+ const match = content.match(/^Base URL:\s*(.+)$/m);
28
+ if (match) {
29
+ return match[1].trim().replace(/\/$/, "");
30
+ }
31
+ } catch {}
32
+ return DEFAULT_BASE_URL;
33
+ }
34
+
35
+ // src/commands/skill.ts
36
+ var TARGETS = {
37
+ claude: {
38
+ path: ".claude/commands/artisense.md",
39
+ label: "Claude Code",
40
+ wrap: (c) => c
41
+ },
42
+ cursor: {
43
+ path: ".cursor/rules/artisense.mdc",
44
+ label: "Cursor",
45
+ wrap: (c) => `---
46
+ description: Artisense API skill for managing documents
47
+ globs:
48
+ alwaysApply: false
49
+ ---
50
+
51
+ ${c}`
52
+ },
53
+ copilot: {
54
+ path: ".github/copilot-instructions.md",
55
+ label: "GitHub Copilot",
56
+ wrap: (c) => c
57
+ }
58
+ };
59
+ var ALL_TARGET_KEYS = Object.keys(TARGETS);
60
+ async function skillCommand(args) {
61
+ const { baseUrl, targetKeys } = parseArgs(args);
62
+ const endpoint = `${baseUrl}/api/v1/skill`;
63
+ console.log(`Downloading SKILL.md from ${endpoint} ...`);
64
+ const res = await fetch(endpoint);
65
+ if (!res.ok) {
66
+ console.error(`Error: Failed to download (HTTP ${res.status})`);
67
+ process.exit(1);
68
+ }
69
+ const content = await res.text();
70
+ const cwd = process.cwd();
71
+ const rootPath = resolve2(cwd, "SKILL.md");
72
+ await writeFile(rootPath, content, "utf-8");
73
+ console.log(` Project root: ${rootPath}`);
74
+ for (const key of targetKeys) {
75
+ const target = TARGETS[key];
76
+ const fullPath = resolve2(cwd, target.path);
77
+ try {
78
+ await mkdir(dirname(fullPath), { recursive: true });
79
+ await writeFile(fullPath, target.wrap(content), "utf-8");
80
+ console.log(` ${target.label}: ${fullPath}`);
81
+ } catch {
82
+ console.warn(` ${target.label}: skipped (cannot write)`);
83
+ }
84
+ }
85
+ console.log(`
86
+ Next: set your API key:
87
+ ARTISENSE_API_KEY="ask_..."
88
+ `);
89
+ }
90
+ function parseArgs(args) {
91
+ let baseUrl = DEFAULT_BASE_URL;
92
+ const targetKeys = [];
93
+ for (const arg of args) {
94
+ if (arg === "--help" || arg === "-h") {
95
+ printUsage();
96
+ process.exit(0);
97
+ } else if (arg === "--all") {
98
+ targetKeys.push(...ALL_TARGET_KEYS);
99
+ } else if (arg.startsWith("--")) {
100
+ const key = arg.slice(2);
101
+ if (key in TARGETS) {
102
+ targetKeys.push(key);
103
+ } else {
104
+ console.error(`Unknown option: ${arg}`);
105
+ printUsage();
106
+ process.exit(1);
107
+ }
108
+ } else {
109
+ baseUrl = arg.replace(/\/$/, "");
110
+ }
111
+ }
112
+ return { baseUrl, targetKeys };
113
+ }
114
+ function printUsage() {
115
+ console.log(`
116
+ Usage: artisense skill [options]
117
+
118
+ Downloads SKILL.md to your project root.
119
+
120
+ Options:
121
+ --claude Also save to .claude/commands/artisense.md
122
+ --cursor Also save to .cursor/rules/artisense.mdc
123
+ --copilot Also save to .github/copilot-instructions.md
124
+ --all All of the above
125
+
126
+ Examples:
127
+ artisense skill
128
+ artisense skill --claude
129
+ artisense skill --claude --cursor
130
+ artisense skill --all
131
+ `);
132
+ }
133
+
134
+ // src/api.ts
135
+ async function request(baseUrl, path, apiKey, options = {}) {
136
+ const res = await fetch(`${baseUrl}${path}`, {
137
+ method: options.method ?? "GET",
138
+ headers: {
139
+ Authorization: `Bearer ${apiKey}`,
140
+ ...options.body ? { "Content-Type": "application/json" } : {}
141
+ },
142
+ body: options.body ? JSON.stringify(options.body) : undefined
143
+ });
144
+ const json = await res.json();
145
+ if (!res.ok) {
146
+ const message = json.error ?? `HTTP ${res.status}`;
147
+ console.error(`Error: ${message}`);
148
+ process.exit(1);
149
+ }
150
+ return json;
151
+ }
152
+
153
+ // src/commands/documents.ts
154
+ async function documentsCommand(args) {
155
+ const subcommand = args[0];
156
+ switch (subcommand) {
157
+ case "list":
158
+ case "ls":
159
+ case undefined:
160
+ return listDocuments();
161
+ case "get":
162
+ case "read":
163
+ return getDocument(args[1]);
164
+ case "create":
165
+ return createDocument(args.slice(1));
166
+ case "update":
167
+ return updateDocument(args[1], args.slice(2));
168
+ case "delete":
169
+ case "rm":
170
+ return deleteDocument(args[1]);
171
+ default:
172
+ console.error(`Unknown subcommand: ${subcommand}`);
173
+ printUsage2();
174
+ process.exit(1);
175
+ }
176
+ }
177
+ async function listDocuments() {
178
+ const [baseUrl, apiKey] = await Promise.all([getBaseUrl(), getApiKey()]);
179
+ const result = await request(baseUrl, "/api/v1/documents", apiKey);
180
+ if (result.data.length === 0) {
181
+ console.log("No documents found.");
182
+ return;
183
+ }
184
+ for (const doc of result.data) {
185
+ const title = doc.title || "(Untitled)";
186
+ console.log(`${doc.id} ${title} [${doc.type}] ${doc.updatedAt}`);
187
+ }
188
+ }
189
+ async function getDocument(id) {
190
+ if (!id) {
191
+ console.error("Usage: artisense docs get <document-id>");
192
+ process.exit(1);
193
+ }
194
+ const [baseUrl, apiKey] = await Promise.all([getBaseUrl(), getApiKey()]);
195
+ const result = await request(baseUrl, `/api/v1/documents/${id}`, apiKey);
196
+ console.log(JSON.stringify(result.data, null, 2));
197
+ }
198
+ async function createDocument(args) {
199
+ const body = parseFlags(args, ["title", "type", "parentId"]);
200
+ const [baseUrl, apiKey] = await Promise.all([getBaseUrl(), getApiKey()]);
201
+ const result = await request(baseUrl, "/api/v1/documents", apiKey, {
202
+ method: "POST",
203
+ body
204
+ });
205
+ console.log(`Created: ${result.data.id} ${result.data.title || "(Untitled)"}`);
206
+ }
207
+ async function updateDocument(id, args) {
208
+ if (!id) {
209
+ console.error("Usage: artisense docs update <document-id> --title '...' --content '...'");
210
+ process.exit(1);
211
+ }
212
+ const body = parseFlags(args, ["title", "content"]);
213
+ if (Object.keys(body).length === 0) {
214
+ console.error("Provide at least one of: --title, --content");
215
+ process.exit(1);
216
+ }
217
+ const [baseUrl, apiKey] = await Promise.all([getBaseUrl(), getApiKey()]);
218
+ const result = await request(baseUrl, `/api/v1/documents/${id}`, apiKey, { method: "PATCH", body });
219
+ console.log(`Updated: ${result.data.id} ${result.data.title || "(Untitled)"}`);
220
+ }
221
+ async function deleteDocument(id) {
222
+ if (!id) {
223
+ console.error("Usage: artisense docs delete <document-id>");
224
+ process.exit(1);
225
+ }
226
+ const [baseUrl, apiKey] = await Promise.all([getBaseUrl(), getApiKey()]);
227
+ await request(baseUrl, `/api/v1/documents/${id}`, apiKey, {
228
+ method: "DELETE"
229
+ });
230
+ console.log(`Deleted: ${id}`);
231
+ }
232
+ function parseFlags(args, allowedKeys) {
233
+ const result = {};
234
+ for (let i = 0;i < args.length; i++) {
235
+ const arg = args[i];
236
+ if (arg.startsWith("--")) {
237
+ const key = arg.slice(2);
238
+ if (allowedKeys.includes(key) && i + 1 < args.length) {
239
+ result[key] = args[++i];
240
+ }
241
+ }
242
+ }
243
+ return result;
244
+ }
245
+ function printUsage2() {
246
+ console.log(`
247
+ Usage: artisense docs <command>
248
+
249
+ Commands:
250
+ list List all documents
251
+ get <id> Get a document
252
+ create --title "..." [--type "..."] [--parentId "..."]
253
+ Create a document
254
+ update <id> --title "..." --content "..."
255
+ Update a document
256
+ delete <id> Delete a document
257
+ `);
258
+ }
259
+
260
+ // src/index.ts
261
+ var args = process.argv.slice(2);
262
+ var command = args[0];
263
+ switch (command) {
264
+ case "skill":
265
+ await skillCommand(args.slice(1));
266
+ break;
267
+ case "docs":
268
+ case "documents":
269
+ await documentsCommand(args.slice(1));
270
+ break;
271
+ case "help":
272
+ case "--help":
273
+ case "-h":
274
+ case undefined:
275
+ printHelp();
276
+ break;
277
+ default:
278
+ console.error(`Unknown command: ${command}`);
279
+ printHelp();
280
+ process.exit(1);
281
+ }
282
+ function printHelp() {
283
+ console.log(`
284
+ artisense — CLI for Artisense
285
+
286
+ Usage: artisense <command>
287
+
288
+ Commands:
289
+ skill Download SKILL.md for AI agents
290
+ docs Manage documents (list, get, create, update, delete)
291
+ help Show this help
292
+
293
+ Environment:
294
+ ARTISENSE_API_KEY Your API key (required for docs commands)
295
+
296
+ Examples:
297
+ artisense skill --claude
298
+ artisense docs list
299
+ artisense docs get <id>
300
+ artisense docs create --title "Meeting Notes"
301
+ artisense docs update <id> --content "Updated content"
302
+ artisense docs delete <id>
303
+ `);
304
+ }
package/package.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "artisense",
3
+ "version": "0.1.0",
4
+ "description": "CLI for Artisense — manage documents from your terminal or AI agent",
5
+ "license": "MIT",
6
+ "bin": {
7
+ "artisense": "dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "type": "module",
13
+ "scripts": {
14
+ "build": "bun build src/index.ts --outdir dist --target node",
15
+ "dev": "bun run src/index.ts"
16
+ }
17
+ }