@hasna/instructions 0.4.0 → 0.4.2
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/cli/index.js +75 -62
- package/dist/db/database.d.ts +1 -1
- package/dist/db/database.d.ts.map +1 -1
- package/dist/index.js +25 -38
- package/dist/mcp/index.js +22 -32
- package/dist/server/index.js +2 -2
- package/dist/status.d.ts +2 -3
- package/dist/status.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -2112,21 +2112,17 @@ var init_types = __esm(() => {
|
|
|
2112
2112
|
|
|
2113
2113
|
// src/db/database.ts
|
|
2114
2114
|
import { Database } from "bun:sqlite";
|
|
2115
|
-
import {
|
|
2115
|
+
import { existsSync as existsSync2, mkdirSync, rmSync } from "fs";
|
|
2116
2116
|
import { join as join2 } from "path";
|
|
2117
2117
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
2118
2118
|
function getDbPath() {
|
|
2119
|
-
if (process.env["
|
|
2120
|
-
return process.env["
|
|
2119
|
+
if (process.env["HASNA_INSTRUCTIONS_DB_PATH"]) {
|
|
2120
|
+
return process.env["HASNA_INSTRUCTIONS_DB_PATH"];
|
|
2121
2121
|
}
|
|
2122
|
-
if (process.env["CONFIGS_DB_PATH"]) {
|
|
2123
|
-
return process.env["CONFIGS_DB_PATH"];
|
|
2124
|
-
}
|
|
2125
|
-
migrateDotfile();
|
|
2126
2122
|
const home = process.env["HOME"] || process.env["USERPROFILE"] || "~";
|
|
2127
|
-
const dir = join2(home, ".hasna", "
|
|
2123
|
+
const dir = join2(home, ".hasna", "instructions");
|
|
2128
2124
|
mkdirSync(dir, { recursive: true });
|
|
2129
|
-
return join2(dir, "
|
|
2125
|
+
return join2(dir, "instructions.db");
|
|
2130
2126
|
}
|
|
2131
2127
|
function uuid() {
|
|
2132
2128
|
return randomUUID3();
|
|
@@ -2195,29 +2191,23 @@ function ensureFeedbackTable(db) {
|
|
|
2195
2191
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
2196
2192
|
)
|
|
2197
2193
|
`);
|
|
2194
|
+
const existing = new Set(db.query("PRAGMA table_info(feedback)").all().map((r) => r.name));
|
|
2195
|
+
const required = [
|
|
2196
|
+
["email", "TEXT"],
|
|
2197
|
+
["category", "TEXT DEFAULT 'general'"],
|
|
2198
|
+
["version", "TEXT"],
|
|
2199
|
+
["machine_id", "TEXT"],
|
|
2200
|
+
["created_at", "TEXT"]
|
|
2201
|
+
];
|
|
2202
|
+
for (const [name, def] of required) {
|
|
2203
|
+
if (!existing.has(name))
|
|
2204
|
+
db.exec(`ALTER TABLE feedback ADD COLUMN ${name} ${def}`);
|
|
2205
|
+
}
|
|
2198
2206
|
}
|
|
2199
2207
|
function insertFeedback(input, db) {
|
|
2200
2208
|
const d = db || getDatabase();
|
|
2201
2209
|
d.run("INSERT INTO feedback (message, email, category, version) VALUES (?, ?, ?, ?)", [input.message, input.email ?? null, input.category ?? "general", input.version ?? null]);
|
|
2202
2210
|
}
|
|
2203
|
-
function migrateDotfile() {
|
|
2204
|
-
const home = process.env["HOME"] || process.env["USERPROFILE"] || "~";
|
|
2205
|
-
const oldDirs = [join2(home, ".open-configs"), join2(home, ".configs")];
|
|
2206
|
-
const newDir = join2(home, ".hasna", "configs");
|
|
2207
|
-
if (existsSync2(newDir))
|
|
2208
|
-
return;
|
|
2209
|
-
for (const oldDir of oldDirs) {
|
|
2210
|
-
if (!existsSync2(oldDir))
|
|
2211
|
-
continue;
|
|
2212
|
-
try {
|
|
2213
|
-
if (!statSync(oldDir).isDirectory())
|
|
2214
|
-
continue;
|
|
2215
|
-
mkdirSync(join2(home, ".hasna"), { recursive: true });
|
|
2216
|
-
cpSync(oldDir, newDir, { recursive: true, force: false });
|
|
2217
|
-
return;
|
|
2218
|
-
} catch {}
|
|
2219
|
-
}
|
|
2220
|
-
}
|
|
2221
2211
|
var MIGRATIONS, _db = null;
|
|
2222
2212
|
var init_database = __esm(() => {
|
|
2223
2213
|
MIGRATIONS = [
|
|
@@ -3582,7 +3572,7 @@ var init_redact = __esm(() => {
|
|
|
3582
3572
|
});
|
|
3583
3573
|
|
|
3584
3574
|
// src/lib/sync-dir.ts
|
|
3585
|
-
import { existsSync as existsSync5, readdirSync, readFileSync as readFileSync2, statSync
|
|
3575
|
+
import { existsSync as existsSync5, readdirSync, readFileSync as readFileSync2, statSync } from "fs";
|
|
3586
3576
|
import { join as join4, relative } from "path";
|
|
3587
3577
|
import { homedir as homedir4 } from "os";
|
|
3588
3578
|
function shouldSkip(p) {
|
|
@@ -3593,7 +3583,7 @@ async function syncFromDir(dir, opts = {}) {
|
|
|
3593
3583
|
const absDir = expandPath(dir);
|
|
3594
3584
|
if (!existsSync5(absDir))
|
|
3595
3585
|
return { added: 0, updated: 0, unchanged: 0, skipped: [`Not found: ${absDir}`] };
|
|
3596
|
-
const files = opts.recursive !== false ? walkDir(absDir) : readdirSync(absDir).map((f) => join4(absDir, f)).filter((f) =>
|
|
3586
|
+
const files = opts.recursive !== false ? walkDir(absDir) : readdirSync(absDir).map((f) => join4(absDir, f)).filter((f) => statSync(f).isFile());
|
|
3597
3587
|
const result = { added: 0, updated: 0, unchanged: 0, skipped: [] };
|
|
3598
3588
|
const home = homedir4();
|
|
3599
3589
|
const allConfigs = await store.listConfigs();
|
|
@@ -5200,7 +5190,7 @@ init_apply();
|
|
|
5200
5190
|
init_sync();
|
|
5201
5191
|
init_redact();
|
|
5202
5192
|
import chalk from "chalk";
|
|
5203
|
-
import { existsSync as existsSync13, readFileSync as readFileSync9 } from "fs";
|
|
5193
|
+
import { existsSync as existsSync13, readFileSync as readFileSync9, writeSync } from "fs";
|
|
5204
5194
|
import { homedir as homedir7 } from "os";
|
|
5205
5195
|
import { basename as basename6, join as join11, resolve as resolve7 } from "path";
|
|
5206
5196
|
|
|
@@ -5333,7 +5323,7 @@ import { dirname as dirname3, isAbsolute as isAbsolute2, join as join9, parse as
|
|
|
5333
5323
|
|
|
5334
5324
|
// src/lib/session-render.ts
|
|
5335
5325
|
import { createHash } from "crypto";
|
|
5336
|
-
import { existsSync as existsSync9, readFileSync as readFileSync5, realpathSync as realpathSync2, statSync as
|
|
5326
|
+
import { existsSync as existsSync9, readFileSync as readFileSync5, realpathSync as realpathSync2, statSync as statSync2 } from "fs";
|
|
5337
5327
|
import { homedir as homedir5 } from "os";
|
|
5338
5328
|
import { basename as basename4, dirname as dirname2, extname as extname3, isAbsolute, join as join8, parse, posix, relative as relative2, resolve as resolve4 } from "path";
|
|
5339
5329
|
var CODEWITH_NATIVE_IMPORTS_ENV = "HASNA_CONFIGS_CODEWITH_NATIVE_IMPORTS";
|
|
@@ -6099,7 +6089,7 @@ function readIdentitySourcePath(sourcePath, baseDir, sourceId) {
|
|
|
6099
6089
|
}
|
|
6100
6090
|
return;
|
|
6101
6091
|
}
|
|
6102
|
-
const stat =
|
|
6092
|
+
const stat = statSync2(resolvedPath);
|
|
6103
6093
|
if (!stat.isFile()) {
|
|
6104
6094
|
throw new Error(`Identity instruction source path is not a file for ${sourceId}: ${sourcePath.path}`);
|
|
6105
6095
|
}
|
|
@@ -6736,14 +6726,12 @@ import { existsSync as existsSync11, readFileSync as readFileSync7 } from "fs";
|
|
|
6736
6726
|
var PACKAGE_NAME = "@hasna/instructions";
|
|
6737
6727
|
var PACKAGE_VERSION = "0.3.0";
|
|
6738
6728
|
function activeDatabaseEnv() {
|
|
6739
|
-
if (process.env["
|
|
6740
|
-
return "
|
|
6741
|
-
if (process.env["CONFIGS_DB_PATH"])
|
|
6742
|
-
return "CONFIGS_DB_PATH";
|
|
6729
|
+
if (process.env["HASNA_INSTRUCTIONS_DB_PATH"])
|
|
6730
|
+
return "HASNA_INSTRUCTIONS_DB_PATH";
|
|
6743
6731
|
return null;
|
|
6744
6732
|
}
|
|
6745
6733
|
function configuredDatabaseKind() {
|
|
6746
|
-
const value = process.env["
|
|
6734
|
+
const value = process.env["HASNA_INSTRUCTIONS_DB_PATH"] ?? "";
|
|
6747
6735
|
return value === ":memory:" || value.startsWith("file::memory:") ? "memory" : "file";
|
|
6748
6736
|
}
|
|
6749
6737
|
function countBy(items, getValue) {
|
|
@@ -6817,8 +6805,7 @@ async function getConfigsStatus(store = resolveConfigStore()) {
|
|
|
6817
6805
|
},
|
|
6818
6806
|
env: {
|
|
6819
6807
|
database: {
|
|
6820
|
-
primary: "
|
|
6821
|
-
fallback: "CONFIGS_DB_PATH",
|
|
6808
|
+
primary: "HASNA_INSTRUCTIONS_DB_PATH",
|
|
6822
6809
|
active: activeDatabaseEnv(),
|
|
6823
6810
|
kind: configuredDatabaseKind()
|
|
6824
6811
|
}
|
|
@@ -6913,6 +6900,32 @@ function truncateMiddle(value, max = 80) {
|
|
|
6913
6900
|
// src/cli/index.tsx
|
|
6914
6901
|
import { createRequire } from "module";
|
|
6915
6902
|
var pkg = createRequire(import.meta.url)("../../package.json");
|
|
6903
|
+
var EAGAIN_SLEEP = new Int32Array(new SharedArrayBuffer(4));
|
|
6904
|
+
function writeStdout(text) {
|
|
6905
|
+
const buf = Buffer.from(text, "utf8");
|
|
6906
|
+
let offset = 0;
|
|
6907
|
+
while (offset < buf.length) {
|
|
6908
|
+
try {
|
|
6909
|
+
offset += writeSync(1, buf, offset);
|
|
6910
|
+
} catch (e) {
|
|
6911
|
+
const code = e.code;
|
|
6912
|
+
if (code === "EAGAIN") {
|
|
6913
|
+
Atomics.wait(EAGAIN_SLEEP, 0, 0, 1);
|
|
6914
|
+
continue;
|
|
6915
|
+
}
|
|
6916
|
+
if (code === "EPIPE")
|
|
6917
|
+
return;
|
|
6918
|
+
throw e;
|
|
6919
|
+
}
|
|
6920
|
+
}
|
|
6921
|
+
}
|
|
6922
|
+
function printLine(text = "") {
|
|
6923
|
+
writeStdout(`${text}
|
|
6924
|
+
`);
|
|
6925
|
+
}
|
|
6926
|
+
function printJson(value) {
|
|
6927
|
+
printLine(JSON.stringify(value, null, 2));
|
|
6928
|
+
}
|
|
6916
6929
|
function fmtConfig(c, format) {
|
|
6917
6930
|
if (format === "json")
|
|
6918
6931
|
return JSON.stringify(c, null, 2);
|
|
@@ -7090,7 +7103,7 @@ program.command("list").alias("ls").description("List stored configs").option("-
|
|
|
7090
7103
|
return;
|
|
7091
7104
|
}
|
|
7092
7105
|
if (fmt === "json") {
|
|
7093
|
-
|
|
7106
|
+
printJson(configs);
|
|
7094
7107
|
return;
|
|
7095
7108
|
}
|
|
7096
7109
|
const page = paginate(configs, { limit: opts.limit, cursor: opts.cursor });
|
|
@@ -7108,18 +7121,18 @@ program.command("show <id>").alias("inspect").description("Show a config's conte
|
|
|
7108
7121
|
try {
|
|
7109
7122
|
const c = await resolveConfigStore().getConfig(id);
|
|
7110
7123
|
if (opts.format === "json") {
|
|
7111
|
-
|
|
7124
|
+
printJson(c);
|
|
7112
7125
|
return;
|
|
7113
7126
|
}
|
|
7114
7127
|
if (opts.format === "content") {
|
|
7115
|
-
|
|
7128
|
+
printLine(c.content);
|
|
7116
7129
|
return;
|
|
7117
7130
|
}
|
|
7118
7131
|
console.log(fmtConfig(c, "table"));
|
|
7119
7132
|
console.log();
|
|
7120
7133
|
console.log(chalk.bold("Content:"));
|
|
7121
7134
|
console.log(chalk.dim("\u2500".repeat(60)));
|
|
7122
|
-
|
|
7135
|
+
printLine(c.content);
|
|
7123
7136
|
} catch (e) {
|
|
7124
7137
|
console.error(chalk.red(e instanceof Error ? e.message : String(e)));
|
|
7125
7138
|
process.exit(1);
|
|
@@ -7160,7 +7173,7 @@ program.command("delete <id>").alias("rm").description("Delete a config record (
|
|
|
7160
7173
|
const config = await store.getConfig(id);
|
|
7161
7174
|
await store.deleteConfig(config.id);
|
|
7162
7175
|
if (opts.json) {
|
|
7163
|
-
|
|
7176
|
+
printJson({ deleted: true, id: config.id, slug: config.slug });
|
|
7164
7177
|
return;
|
|
7165
7178
|
}
|
|
7166
7179
|
console.log(chalk.green("\u2713") + ` Deleted: ${chalk.bold(config.name)} ${chalk.dim(`(${config.slug})`)}`);
|
|
@@ -7295,9 +7308,9 @@ program.command("import <file>").description("Import configs from a tar.gz bundl
|
|
|
7295
7308
|
});
|
|
7296
7309
|
program.command("whoami").description("Show setup summary").action(async () => {
|
|
7297
7310
|
const store = resolveConfigStore();
|
|
7298
|
-
const dbPath = isCloudMode() ? `${process.env["HASNA_INSTRUCTIONS_API_URL"]}/v1 (self_hosted)` : process.env["
|
|
7311
|
+
const dbPath = isCloudMode() ? `${process.env["HASNA_INSTRUCTIONS_API_URL"]}/v1 (self_hosted)` : process.env["HASNA_INSTRUCTIONS_DB_PATH"] || join11(homedir7(), ".hasna", "instructions", "instructions.db");
|
|
7299
7312
|
const stats = await store.getConfigStats();
|
|
7300
|
-
console.log(chalk.bold("@hasna/
|
|
7313
|
+
console.log(chalk.bold("@hasna/instructions") + chalk.dim(" v" + pkg.version));
|
|
7301
7314
|
console.log(chalk.cyan(isCloudMode() ? "API:" : "DB:") + " " + dbPath);
|
|
7302
7315
|
console.log(chalk.cyan("Total configs:") + " " + (stats["total"] || 0));
|
|
7303
7316
|
console.log();
|
|
@@ -7326,7 +7339,7 @@ profileCmd.command("list").description("List all profiles").option("--brief", "c
|
|
|
7326
7339
|
return;
|
|
7327
7340
|
}
|
|
7328
7341
|
if (fmt === "json") {
|
|
7329
|
-
|
|
7342
|
+
printJson(profiles);
|
|
7330
7343
|
return;
|
|
7331
7344
|
}
|
|
7332
7345
|
const page = paginate(profiles, { limit: opts.limit, cursor: opts.cursor });
|
|
@@ -7481,7 +7494,7 @@ sessionCmd.command("plan").description("Produce a dry-run render plan for profil
|
|
|
7481
7494
|
sources
|
|
7482
7495
|
});
|
|
7483
7496
|
if (opts.json) {
|
|
7484
|
-
|
|
7497
|
+
printJson(planJsonForOutput(plan));
|
|
7485
7498
|
return;
|
|
7486
7499
|
}
|
|
7487
7500
|
console.log(chalk.bold(`${plan.tool} session render plan`) + chalk.dim(` (${plan.adapter.mode})`));
|
|
@@ -7526,7 +7539,7 @@ sessionCmd.command("apply").description("Write a session render plan to its mana
|
|
|
7526
7539
|
});
|
|
7527
7540
|
const result = applySessionRender(plan, { dryRun: opts.dryRun, force: opts.force });
|
|
7528
7541
|
if (opts.json) {
|
|
7529
|
-
|
|
7542
|
+
printJson(result);
|
|
7530
7543
|
if (result.conflicts.length > 0)
|
|
7531
7544
|
process.exitCode = 1;
|
|
7532
7545
|
return;
|
|
@@ -7584,7 +7597,7 @@ snapshotCmd.command("show <id>").description("Show a snapshot's content").action
|
|
|
7584
7597
|
console.error(chalk.red("Snapshot not found: " + id));
|
|
7585
7598
|
process.exit(1);
|
|
7586
7599
|
}
|
|
7587
|
-
|
|
7600
|
+
printLine(snap.content);
|
|
7588
7601
|
});
|
|
7589
7602
|
snapshotCmd.command("restore <config> <snapshot-id>").description("Restore a config to a snapshot version").action(async (configId, snapId) => {
|
|
7590
7603
|
try {
|
|
@@ -7741,7 +7754,7 @@ program.command("package-manager-scan [paths...]").description("Scan package-man
|
|
|
7741
7754
|
const visible = result.findings.slice(0, maxPrinted);
|
|
7742
7755
|
const omitted = Math.max(0, result.findings.length - visible.length);
|
|
7743
7756
|
if (opts.json) {
|
|
7744
|
-
|
|
7757
|
+
printJson(result);
|
|
7745
7758
|
} else if (result.findings.length === 0) {
|
|
7746
7759
|
console.log(chalk.green("\u2713") + ` Package-manager scan clean (${result.scannedFiles} file(s)).`);
|
|
7747
7760
|
} else {
|
|
@@ -7760,7 +7773,7 @@ program.command("package-manager-scan [paths...]").description("Scan package-man
|
|
|
7760
7773
|
}
|
|
7761
7774
|
});
|
|
7762
7775
|
var mcpCmd = program.command("mcp").description("Install/remove MCP server for AI agents");
|
|
7763
|
-
mcpCmd.command("install").alias("add").description("Install configs MCP server into an agent").option("--claude", "install into Claude Code").option("--codex", "install into Codex").option("--gemini", "install into Gemini").option("--all", "install into all agents").option("--profile <level>", "set
|
|
7776
|
+
mcpCmd.command("install").alias("add").description("Install configs MCP server into an agent").option("--claude", "install into Claude Code").option("--codex", "install into Codex").option("--gemini", "install into Gemini").option("--all", "install into all agents").option("--profile <level>", "set INSTRUCTIONS_PROFILE (minimal|standard|full)", "standard").action(async (opts) => {
|
|
7764
7777
|
const targets = opts.all ? ["claude", "codex", "gemini"] : [
|
|
7765
7778
|
...opts.claude ? ["claude"] : [],
|
|
7766
7779
|
...opts.codex ? ["codex"] : [],
|
|
@@ -7775,7 +7788,7 @@ mcpCmd.command("install").alias("add").description("Install configs MCP server i
|
|
|
7775
7788
|
const { vars } = await getMachineProfileContext({}, resolveConfigStore());
|
|
7776
7789
|
const mcpBinary = `${vars["BUN_BIN_DIR"]}/configs-mcp`;
|
|
7777
7790
|
if (target === "claude") {
|
|
7778
|
-
const cmd = opts.profile && opts.profile !== "full" ? ["claude", "mcp", "add", "--transport", "stdio", "--scope", "user", "configs", "--", "env", `
|
|
7791
|
+
const cmd = opts.profile && opts.profile !== "full" ? ["claude", "mcp", "add", "--transport", "stdio", "--scope", "user", "configs", "--", "env", `INSTRUCTIONS_PROFILE=${opts.profile}`, mcpBinary] : ["claude", "mcp", "add", "--transport", "stdio", "--scope", "user", "configs", "--", mcpBinary];
|
|
7779
7792
|
const proc = Bun.spawn(cmd, { stdout: "inherit", stderr: "inherit" });
|
|
7780
7793
|
await proc.exited;
|
|
7781
7794
|
console.log(chalk.green("\u2713") + " Installed into Claude Code");
|
|
@@ -7832,7 +7845,7 @@ program.command("init").description("First-time setup: sync all known configs, c
|
|
|
7832
7845
|
await store.reset();
|
|
7833
7846
|
console.log(chalk.dim("Reset local store."));
|
|
7834
7847
|
}
|
|
7835
|
-
console.log(chalk.bold(`@hasna/
|
|
7848
|
+
console.log(chalk.bold(`@hasna/instructions \u2014 initializing
|
|
7836
7849
|
`));
|
|
7837
7850
|
const result = await syncKnown({ store });
|
|
7838
7851
|
console.log(chalk.green("\u2713") + ` Synced: +${result.added} updated:${result.updated} unchanged:${result.unchanged}`);
|
|
@@ -7876,17 +7889,17 @@ DB stats:`));
|
|
|
7876
7889
|
if (count > 0)
|
|
7877
7890
|
console.log(` ${key.padEnd(18)} ${count}`);
|
|
7878
7891
|
}
|
|
7879
|
-
const location = isCloudMode() ? `${process.env["HASNA_INSTRUCTIONS_API_URL"]}/v1 (self_hosted)` : process.env["
|
|
7892
|
+
const location = isCloudMode() ? `${process.env["HASNA_INSTRUCTIONS_API_URL"]}/v1 (self_hosted)` : process.env["HASNA_INSTRUCTIONS_DB_PATH"] || join11(homedir7(), ".hasna", "instructions", "instructions.db");
|
|
7880
7893
|
console.log(chalk.dim(`
|
|
7881
7894
|
${isCloudMode() ? "API" : "DB"}: ${location}`));
|
|
7882
7895
|
});
|
|
7883
7896
|
program.command("status").description("Health check: total configs, drift from disk, unredacted secrets").option("--json", "output metadata-only JSON").action(async (opts) => {
|
|
7884
7897
|
const status = await getConfigsStatus(resolveConfigStore());
|
|
7885
7898
|
if (opts.json) {
|
|
7886
|
-
|
|
7899
|
+
printJson(status);
|
|
7887
7900
|
return;
|
|
7888
7901
|
}
|
|
7889
|
-
console.log(chalk.bold("@hasna/
|
|
7902
|
+
console.log(chalk.bold("@hasna/instructions") + chalk.dim(` v${pkg.version}`));
|
|
7890
7903
|
console.log(chalk.cyan("Database:") + ` ${status.env.database.kind} (${status.env.database.active ?? "default"})`);
|
|
7891
7904
|
console.log(chalk.cyan("Total:") + ` ${status.counts.configs.total} configs
|
|
7892
7905
|
`);
|
|
@@ -7897,7 +7910,7 @@ program.command("status").description("Health check: total configs, drift from d
|
|
|
7897
7910
|
});
|
|
7898
7911
|
program.command("backup").description("Export configs to a timestamped backup file").action(async () => {
|
|
7899
7912
|
const { mkdirSync: mk } = await import("fs");
|
|
7900
|
-
const backupDir = join11(homedir7(), ".hasna", "
|
|
7913
|
+
const backupDir = join11(homedir7(), ".hasna", "instructions", "backups");
|
|
7901
7914
|
mk(backupDir, { recursive: true });
|
|
7902
7915
|
const ts = new Date().toISOString().replace(/[:.]/g, "-").replace("T", "-").slice(0, 19);
|
|
7903
7916
|
const outPath = join11(backupDir, `configs-${ts}.tar.gz`);
|
|
@@ -8048,7 +8061,7 @@ program.command("watch").description("Watch known config files for changes and a
|
|
|
8048
8061
|
const interval = Number(opts.interval);
|
|
8049
8062
|
const { statSync: st } = await import("fs");
|
|
8050
8063
|
const { expandPath: expandPath2 } = await Promise.resolve().then(() => (init_apply(), exports_apply));
|
|
8051
|
-
console.log(chalk.bold("@hasna/
|
|
8064
|
+
console.log(chalk.bold("@hasna/instructions watch") + chalk.dim(` \u2014 polling every ${interval}ms`));
|
|
8052
8065
|
console.log(chalk.dim(`Watching known config files for changes\u2026
|
|
8053
8066
|
`));
|
|
8054
8067
|
const mtimes = new Map;
|
|
@@ -8208,7 +8221,7 @@ program.command("bootstrap").description("Install the full @hasna ecosystem: CLI
|
|
|
8208
8221
|
{ name: "@hasna/assistants", bin: "assistants", mcp: "assistants-mcp" },
|
|
8209
8222
|
{ name: "@hasna/brains", bin: "brains", mcp: "brains-mcp" }
|
|
8210
8223
|
];
|
|
8211
|
-
console.log(chalk.bold("@hasna/
|
|
8224
|
+
console.log(chalk.bold("@hasna/instructions bootstrap") + chalk.dim(` \u2014 installing ${packages.length} ecosystem packages
|
|
8212
8225
|
`));
|
|
8213
8226
|
console.log(chalk.cyan("Installing CLI tools:"));
|
|
8214
8227
|
for (const pkg2 of packages) {
|
|
@@ -8268,7 +8281,7 @@ program.command("push").description("Alias for sync --to-disk (write DB configs
|
|
|
8268
8281
|
});
|
|
8269
8282
|
program.command("update").description("Check for updates and install latest version").option("--check", "only check, don't install").action(async (opts) => {
|
|
8270
8283
|
try {
|
|
8271
|
-
const proc = Bun.spawn(["npm", "view", "@hasna/
|
|
8284
|
+
const proc = Bun.spawn(["npm", "view", "@hasna/instructions", "version"], { stdout: "pipe", stderr: "pipe" });
|
|
8272
8285
|
const latest = (await new Response(proc.stdout).text()).trim();
|
|
8273
8286
|
await proc.exited;
|
|
8274
8287
|
if (latest === pkg.version) {
|
|
@@ -8277,7 +8290,7 @@ program.command("update").description("Check for updates and install latest vers
|
|
|
8277
8290
|
console.log(`Current: ${chalk.dim(pkg.version)} \u2192 Latest: ${chalk.green(latest)}`);
|
|
8278
8291
|
if (!opts.check) {
|
|
8279
8292
|
console.log(chalk.dim("Installing..."));
|
|
8280
|
-
const install = Bun.spawn(["bun", "install", "-g", `@hasna/
|
|
8293
|
+
const install = Bun.spawn(["bun", "install", "-g", `@hasna/instructions@${latest}`], { stdout: "inherit", stderr: "inherit" });
|
|
8281
8294
|
await install.exited;
|
|
8282
8295
|
console.log(chalk.green("\u2713") + ` Updated to ${latest}`);
|
|
8283
8296
|
}
|
package/dist/db/database.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export declare function resetDatabase(): void;
|
|
|
7
7
|
/**
|
|
8
8
|
* Destroy the on-disk local database: close the handle and delete the db file
|
|
9
9
|
* plus its WAL/SHM sidecars. Used by `init --force`. Resolves the path from the
|
|
10
|
-
* db module (honoring
|
|
10
|
+
* db module (honoring HASNA_INSTRUCTIONS_DB_PATH); a no-op for the
|
|
11
11
|
* in-memory (`:memory:`) database. Local-only — the CloudConfigStore never calls
|
|
12
12
|
* this (destroying the shared cloud store from a client is forbidden).
|
|
13
13
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAetC,wBAAgB,IAAI,IAAI,MAAM,CAE7B;AAED,wBAAgB,GAAG,IAAI,MAAM,CAE5B;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK5C;AAyED,wBAAgB,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,CAqBnD;AAED,wBAAgB,aAAa,IAAI,IAAI,CAKpC;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAOzC;AAsDD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,CAAC,EAAE,QAAQ,GAAG,IAAI,CAMxE"}
|
package/dist/index.js
CHANGED
|
@@ -73,21 +73,17 @@ import { randomUUID as randomUUID2 } from "crypto";
|
|
|
73
73
|
|
|
74
74
|
// src/db/database.ts
|
|
75
75
|
import { Database } from "bun:sqlite";
|
|
76
|
-
import {
|
|
76
|
+
import { existsSync, mkdirSync, rmSync } from "fs";
|
|
77
77
|
import { join } from "path";
|
|
78
78
|
import { randomUUID } from "crypto";
|
|
79
79
|
function getDbPath() {
|
|
80
|
-
if (process.env["
|
|
81
|
-
return process.env["
|
|
80
|
+
if (process.env["HASNA_INSTRUCTIONS_DB_PATH"]) {
|
|
81
|
+
return process.env["HASNA_INSTRUCTIONS_DB_PATH"];
|
|
82
82
|
}
|
|
83
|
-
if (process.env["CONFIGS_DB_PATH"]) {
|
|
84
|
-
return process.env["CONFIGS_DB_PATH"];
|
|
85
|
-
}
|
|
86
|
-
migrateDotfile();
|
|
87
83
|
const home = process.env["HOME"] || process.env["USERPROFILE"] || "~";
|
|
88
|
-
const dir = join(home, ".hasna", "
|
|
84
|
+
const dir = join(home, ".hasna", "instructions");
|
|
89
85
|
mkdirSync(dir, { recursive: true });
|
|
90
|
-
return join(dir, "
|
|
86
|
+
return join(dir, "instructions.db");
|
|
91
87
|
}
|
|
92
88
|
function uuid() {
|
|
93
89
|
return randomUUID();
|
|
@@ -225,29 +221,23 @@ function ensureFeedbackTable(db) {
|
|
|
225
221
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
226
222
|
)
|
|
227
223
|
`);
|
|
224
|
+
const existing = new Set(db.query("PRAGMA table_info(feedback)").all().map((r) => r.name));
|
|
225
|
+
const required = [
|
|
226
|
+
["email", "TEXT"],
|
|
227
|
+
["category", "TEXT DEFAULT 'general'"],
|
|
228
|
+
["version", "TEXT"],
|
|
229
|
+
["machine_id", "TEXT"],
|
|
230
|
+
["created_at", "TEXT"]
|
|
231
|
+
];
|
|
232
|
+
for (const [name, def] of required) {
|
|
233
|
+
if (!existing.has(name))
|
|
234
|
+
db.exec(`ALTER TABLE feedback ADD COLUMN ${name} ${def}`);
|
|
235
|
+
}
|
|
228
236
|
}
|
|
229
237
|
function insertFeedback(input, db) {
|
|
230
238
|
const d = db || getDatabase();
|
|
231
239
|
d.run("INSERT INTO feedback (message, email, category, version) VALUES (?, ?, ?, ?)", [input.message, input.email ?? null, input.category ?? "general", input.version ?? null]);
|
|
232
240
|
}
|
|
233
|
-
function migrateDotfile() {
|
|
234
|
-
const home = process.env["HOME"] || process.env["USERPROFILE"] || "~";
|
|
235
|
-
const oldDirs = [join(home, ".open-configs"), join(home, ".configs")];
|
|
236
|
-
const newDir = join(home, ".hasna", "configs");
|
|
237
|
-
if (existsSync(newDir))
|
|
238
|
-
return;
|
|
239
|
-
for (const oldDir of oldDirs) {
|
|
240
|
-
if (!existsSync(oldDir))
|
|
241
|
-
continue;
|
|
242
|
-
try {
|
|
243
|
-
if (!statSync(oldDir).isDirectory())
|
|
244
|
-
continue;
|
|
245
|
-
mkdirSync(join(home, ".hasna"), { recursive: true });
|
|
246
|
-
cpSync(oldDir, newDir, { recursive: true, force: false });
|
|
247
|
-
return;
|
|
248
|
-
} catch {}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
241
|
|
|
252
242
|
// src/db/configs.ts
|
|
253
243
|
function rowToConfig(row) {
|
|
@@ -1498,14 +1488,12 @@ function hasSecrets(content, format) {
|
|
|
1498
1488
|
var PACKAGE_NAME = "@hasna/instructions";
|
|
1499
1489
|
var PACKAGE_VERSION = "0.3.0";
|
|
1500
1490
|
function activeDatabaseEnv() {
|
|
1501
|
-
if (process.env["
|
|
1502
|
-
return "
|
|
1503
|
-
if (process.env["CONFIGS_DB_PATH"])
|
|
1504
|
-
return "CONFIGS_DB_PATH";
|
|
1491
|
+
if (process.env["HASNA_INSTRUCTIONS_DB_PATH"])
|
|
1492
|
+
return "HASNA_INSTRUCTIONS_DB_PATH";
|
|
1505
1493
|
return null;
|
|
1506
1494
|
}
|
|
1507
1495
|
function configuredDatabaseKind() {
|
|
1508
|
-
const value = process.env["
|
|
1496
|
+
const value = process.env["HASNA_INSTRUCTIONS_DB_PATH"] ?? "";
|
|
1509
1497
|
return value === ":memory:" || value.startsWith("file::memory:") ? "memory" : "file";
|
|
1510
1498
|
}
|
|
1511
1499
|
function countBy(items, getValue) {
|
|
@@ -1579,8 +1567,7 @@ async function getConfigsStatus(store = resolveConfigStore()) {
|
|
|
1579
1567
|
},
|
|
1580
1568
|
env: {
|
|
1581
1569
|
database: {
|
|
1582
|
-
primary: "
|
|
1583
|
-
fallback: "CONFIGS_DB_PATH",
|
|
1570
|
+
primary: "HASNA_INSTRUCTIONS_DB_PATH",
|
|
1584
1571
|
active: activeDatabaseEnv(),
|
|
1585
1572
|
kind: configuredDatabaseKind()
|
|
1586
1573
|
}
|
|
@@ -1685,7 +1672,7 @@ var PG_MIGRATIONS = [
|
|
|
1685
1672
|
];
|
|
1686
1673
|
// src/lib/session-render.ts
|
|
1687
1674
|
import { createHash } from "crypto";
|
|
1688
|
-
import { existsSync as existsSync5, readFileSync as readFileSync3, realpathSync as realpathSync2, statSync
|
|
1675
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3, realpathSync as realpathSync2, statSync } from "fs";
|
|
1689
1676
|
import { homedir as homedir3 } from "os";
|
|
1690
1677
|
import { basename as basename3, dirname as dirname2, extname as extname2, isAbsolute, join as join3, parse, posix, relative, resolve as resolve2 } from "path";
|
|
1691
1678
|
var CODEWITH_NATIVE_IMPORTS_ENV = "HASNA_CONFIGS_CODEWITH_NATIVE_IMPORTS";
|
|
@@ -2451,7 +2438,7 @@ function readIdentitySourcePath(sourcePath, baseDir, sourceId) {
|
|
|
2451
2438
|
}
|
|
2452
2439
|
return;
|
|
2453
2440
|
}
|
|
2454
|
-
const stat =
|
|
2441
|
+
const stat = statSync(resolvedPath);
|
|
2455
2442
|
if (!stat.isFile()) {
|
|
2456
2443
|
throw new Error(`Identity instruction source path is not a file for ${sourceId}: ${sourcePath.path}`);
|
|
2457
2444
|
}
|
|
@@ -3089,7 +3076,7 @@ import { existsSync as existsSync8, readdirSync as readdirSync2, readFileSync as
|
|
|
3089
3076
|
import { basename as basename4, extname as extname3, join as join6 } from "path";
|
|
3090
3077
|
|
|
3091
3078
|
// src/lib/sync-dir.ts
|
|
3092
|
-
import { existsSync as existsSync7, readdirSync, readFileSync as readFileSync5, statSync as
|
|
3079
|
+
import { existsSync as existsSync7, readdirSync, readFileSync as readFileSync5, statSync as statSync2 } from "fs";
|
|
3093
3080
|
import { join as join5, relative as relative3 } from "path";
|
|
3094
3081
|
import { homedir as homedir4 } from "os";
|
|
3095
3082
|
var SKIP = [".db", ".db-shm", ".db-wal", ".log", ".lock", ".DS_Store", "node_modules", ".git"];
|
|
@@ -3101,7 +3088,7 @@ async function syncFromDir(dir, opts = {}) {
|
|
|
3101
3088
|
const absDir = expandPath(dir);
|
|
3102
3089
|
if (!existsSync7(absDir))
|
|
3103
3090
|
return { added: 0, updated: 0, unchanged: 0, skipped: [`Not found: ${absDir}`] };
|
|
3104
|
-
const files = opts.recursive !== false ? walkDir(absDir) : readdirSync(absDir).map((f) => join5(absDir, f)).filter((f) =>
|
|
3091
|
+
const files = opts.recursive !== false ? walkDir(absDir) : readdirSync(absDir).map((f) => join5(absDir, f)).filter((f) => statSync2(f).isFile());
|
|
3105
3092
|
const result = { added: 0, updated: 0, unchanged: 0, skipped: [] };
|
|
3106
3093
|
const home = homedir4();
|
|
3107
3094
|
const allConfigs = await store.listConfigs();
|
package/dist/mcp/index.js
CHANGED
|
@@ -49,21 +49,17 @@ var init_types = __esm(() => {
|
|
|
49
49
|
|
|
50
50
|
// src/db/database.ts
|
|
51
51
|
import { Database } from "bun:sqlite";
|
|
52
|
-
import {
|
|
52
|
+
import { existsSync, mkdirSync, rmSync } from "fs";
|
|
53
53
|
import { join } from "path";
|
|
54
54
|
import { randomUUID } from "crypto";
|
|
55
55
|
function getDbPath() {
|
|
56
|
-
if (process.env["
|
|
57
|
-
return process.env["
|
|
56
|
+
if (process.env["HASNA_INSTRUCTIONS_DB_PATH"]) {
|
|
57
|
+
return process.env["HASNA_INSTRUCTIONS_DB_PATH"];
|
|
58
58
|
}
|
|
59
|
-
if (process.env["CONFIGS_DB_PATH"]) {
|
|
60
|
-
return process.env["CONFIGS_DB_PATH"];
|
|
61
|
-
}
|
|
62
|
-
migrateDotfile();
|
|
63
59
|
const home = process.env["HOME"] || process.env["USERPROFILE"] || "~";
|
|
64
|
-
const dir = join(home, ".hasna", "
|
|
60
|
+
const dir = join(home, ".hasna", "instructions");
|
|
65
61
|
mkdirSync(dir, { recursive: true });
|
|
66
|
-
return join(dir, "
|
|
62
|
+
return join(dir, "instructions.db");
|
|
67
63
|
}
|
|
68
64
|
function uuid() {
|
|
69
65
|
return randomUUID();
|
|
@@ -132,29 +128,23 @@ function ensureFeedbackTable(db) {
|
|
|
132
128
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
133
129
|
)
|
|
134
130
|
`);
|
|
131
|
+
const existing = new Set(db.query("PRAGMA table_info(feedback)").all().map((r) => r.name));
|
|
132
|
+
const required = [
|
|
133
|
+
["email", "TEXT"],
|
|
134
|
+
["category", "TEXT DEFAULT 'general'"],
|
|
135
|
+
["version", "TEXT"],
|
|
136
|
+
["machine_id", "TEXT"],
|
|
137
|
+
["created_at", "TEXT"]
|
|
138
|
+
];
|
|
139
|
+
for (const [name, def] of required) {
|
|
140
|
+
if (!existing.has(name))
|
|
141
|
+
db.exec(`ALTER TABLE feedback ADD COLUMN ${name} ${def}`);
|
|
142
|
+
}
|
|
135
143
|
}
|
|
136
144
|
function insertFeedback(input, db) {
|
|
137
145
|
const d = db || getDatabase();
|
|
138
146
|
d.run("INSERT INTO feedback (message, email, category, version) VALUES (?, ?, ?, ?)", [input.message, input.email ?? null, input.category ?? "general", input.version ?? null]);
|
|
139
147
|
}
|
|
140
|
-
function migrateDotfile() {
|
|
141
|
-
const home = process.env["HOME"] || process.env["USERPROFILE"] || "~";
|
|
142
|
-
const oldDirs = [join(home, ".open-configs"), join(home, ".configs")];
|
|
143
|
-
const newDir = join(home, ".hasna", "configs");
|
|
144
|
-
if (existsSync(newDir))
|
|
145
|
-
return;
|
|
146
|
-
for (const oldDir of oldDirs) {
|
|
147
|
-
if (!existsSync(oldDir))
|
|
148
|
-
continue;
|
|
149
|
-
try {
|
|
150
|
-
if (!statSync(oldDir).isDirectory())
|
|
151
|
-
continue;
|
|
152
|
-
mkdirSync(join(home, ".hasna"), { recursive: true });
|
|
153
|
-
cpSync(oldDir, newDir, { recursive: true, force: false });
|
|
154
|
-
return;
|
|
155
|
-
} catch {}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
148
|
var MIGRATIONS, _db = null;
|
|
159
149
|
var init_database = __esm(() => {
|
|
160
150
|
MIGRATIONS = [
|
|
@@ -1962,7 +1952,7 @@ var init_sync = __esm(() => {
|
|
|
1962
1952
|
});
|
|
1963
1953
|
|
|
1964
1954
|
// src/lib/sync-dir.ts
|
|
1965
|
-
import { existsSync as existsSync5, readdirSync as readdirSync2, readFileSync as readFileSync3, statSync
|
|
1955
|
+
import { existsSync as existsSync5, readdirSync as readdirSync2, readFileSync as readFileSync3, statSync } from "fs";
|
|
1966
1956
|
import { join as join4, relative } from "path";
|
|
1967
1957
|
import { homedir as homedir3 } from "os";
|
|
1968
1958
|
function shouldSkip(p) {
|
|
@@ -1973,7 +1963,7 @@ async function syncFromDir(dir, opts = {}) {
|
|
|
1973
1963
|
const absDir = expandPath(dir);
|
|
1974
1964
|
if (!existsSync5(absDir))
|
|
1975
1965
|
return { added: 0, updated: 0, unchanged: 0, skipped: [`Not found: ${absDir}`] };
|
|
1976
|
-
const files = opts.recursive !== false ? walkDir(absDir) : readdirSync2(absDir).map((f) => join4(absDir, f)).filter((f) =>
|
|
1966
|
+
const files = opts.recursive !== false ? walkDir(absDir) : readdirSync2(absDir).map((f) => join4(absDir, f)).filter((f) => statSync(f).isFile());
|
|
1977
1967
|
const result = { added: 0, updated: 0, unchanged: 0, skipped: [] };
|
|
1978
1968
|
const home = homedir3();
|
|
1979
1969
|
const allConfigs = await store.listConfigs();
|
|
@@ -2050,7 +2040,7 @@ var init_sync_dir = __esm(() => {
|
|
|
2050
2040
|
var require_package = __commonJS((exports, module) => {
|
|
2051
2041
|
module.exports = {
|
|
2052
2042
|
name: "@hasna/instructions",
|
|
2053
|
-
version: "0.4.
|
|
2043
|
+
version: "0.4.2",
|
|
2054
2044
|
description: "AI coding agent instruction & configuration manager \u2014 store, version, apply, and share all your AI coding configs. CLI + MCP + HTTP API (instructions-serve) + generated SDK + Dashboard.",
|
|
2055
2045
|
type: "module",
|
|
2056
2046
|
main: "dist/index.js",
|
|
@@ -2274,7 +2264,7 @@ var PROFILES = {
|
|
|
2274
2264
|
standard: ["list_configs", "get_config", "create_config", "update_config", "apply_config", "sync_known", "get_status", "render_template", "scan_secrets", "list_profiles", "apply_profile", "search_tools", "describe_tools"],
|
|
2275
2265
|
full: []
|
|
2276
2266
|
};
|
|
2277
|
-
var activeProfile = process.env["
|
|
2267
|
+
var activeProfile = process.env["INSTRUCTIONS_PROFILE"] || "full";
|
|
2278
2268
|
var profileFilter = PROFILES[activeProfile];
|
|
2279
2269
|
var ALL_LEAN_TOOLS = [
|
|
2280
2270
|
{ name: "list_configs", inputSchema: { type: "object", properties: { category: { type: "string" }, agent: { type: "string" }, kind: { type: "string" }, search: { type: "string" }, limit: { type: "number" }, cursor: { type: "number" }, verbose: { type: "boolean" } } } },
|
|
@@ -2454,7 +2444,7 @@ function buildServer() {
|
|
|
2454
2444
|
drifted,
|
|
2455
2445
|
drifted_configs: driftedSlugs.slice(0, 5),
|
|
2456
2446
|
missing,
|
|
2457
|
-
db_path: process.env["
|
|
2447
|
+
db_path: process.env["HASNA_INSTRUCTIONS_DB_PATH"] || "~/.hasna/instructions/instructions.db"
|
|
2458
2448
|
});
|
|
2459
2449
|
}
|
|
2460
2450
|
case "sync_known": {
|
package/dist/server/index.js
CHANGED
|
@@ -3199,7 +3199,7 @@ if (process.argv.includes("--version") || process.argv.includes("-V")) {
|
|
|
3199
3199
|
console.log(getPackageVersion());
|
|
3200
3200
|
process.exit(0);
|
|
3201
3201
|
}
|
|
3202
|
-
var PORT = Number(process.env["PORT"] ?? process.env["INSTRUCTIONS_PORT"] ??
|
|
3202
|
+
var PORT = Number(process.env["PORT"] ?? process.env["INSTRUCTIONS_PORT"] ?? 3457);
|
|
3203
3203
|
var app = new Hono2;
|
|
3204
3204
|
app.use("*", cors());
|
|
3205
3205
|
function serviceMode() {
|
|
@@ -3268,7 +3268,7 @@ if (dashDir) {
|
|
|
3268
3268
|
});
|
|
3269
3269
|
});
|
|
3270
3270
|
}
|
|
3271
|
-
var HOST = process.env["HOST"] ?? process.env["INSTRUCTIONS_HOST"] ??
|
|
3271
|
+
var HOST = process.env["HOST"] ?? process.env["INSTRUCTIONS_HOST"] ?? "localhost";
|
|
3272
3272
|
console.log(`instructions-serve listening on http://${HOST}:${PORT} (mode: ${serviceMode()})${dashDir ? " (dashboard: /)" : " (no dashboard)"}`);
|
|
3273
3273
|
var server_default = { port: PORT, hostname: HOST, fetch: app.fetch };
|
|
3274
3274
|
export {
|
package/dist/status.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ConfigStore } from "./data/config-store.js";
|
|
2
|
-
type ActiveDbEnv = "
|
|
2
|
+
type ActiveDbEnv = "HASNA_INSTRUCTIONS_DB_PATH" | null;
|
|
3
3
|
type DatabaseKind = "memory" | "file";
|
|
4
4
|
type ContractStatus = "ok" | "warn";
|
|
5
5
|
export interface ConfigsStatusContract {
|
|
@@ -11,8 +11,7 @@ export interface ConfigsStatusContract {
|
|
|
11
11
|
};
|
|
12
12
|
env: {
|
|
13
13
|
database: {
|
|
14
|
-
primary: "
|
|
15
|
-
fallback: "CONFIGS_DB_PATH";
|
|
14
|
+
primary: "HASNA_INSTRUCTIONS_DB_PATH";
|
|
16
15
|
active: ActiveDbEnv;
|
|
17
16
|
kind: DatabaseKind;
|
|
18
17
|
};
|
package/dist/status.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AACA,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAQ9E,KAAK,WAAW,GAAG,
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AACA,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAQ9E,KAAK,WAAW,GAAG,4BAA4B,GAAG,IAAI,CAAC;AACvD,KAAK,YAAY,GAAG,QAAQ,GAAG,MAAM,CAAC;AACtC,KAAK,cAAc,GAAG,IAAI,GAAG,MAAM,CAAC;AAEpC,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,SAAS,CAAC;IACnB,aAAa,EAAE,KAAK,CAAC;IACrB,OAAO,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,GAAG,EAAE;QACH,QAAQ,EAAE;YACR,OAAO,EAAE,4BAA4B,CAAC;YACtC,MAAM,EAAE,WAAW,CAAC;YACpB,IAAI,EAAE,YAAY,CAAC;SACpB,CAAC;KACH,CAAC;IACF,MAAM,EAAE;QACN,OAAO,EAAE;YACP,KAAK,EAAE,MAAM,CAAC;YACd,IAAI,EAAE,MAAM,CAAC;YACb,SAAS,EAAE,MAAM,CAAC;YAClB,SAAS,EAAE,MAAM,CAAC;SACnB,CAAC;QACF,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACnC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAChC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,MAAM,EAAE;QACN,MAAM,EAAE,cAAc,CAAC;QACvB,iBAAiB,EAAE,OAAO,CAAC;QAC3B,cAAc,EAAE,MAAM,CAAC;QACvB,cAAc,EAAE,MAAM,CAAC;QACvB,wBAAwB,EAAE,MAAM,CAAC;QACjC,QAAQ,EAAE,OAAO,CAAC;QAClB,iBAAiB,EAAE,OAAO,CAAC;QAC3B,oBAAoB,EAAE,OAAO,CAAC;KAC/B,CAAC;IACF,MAAM,EAAE;QACN,oBAAoB,EAAE,KAAK,CAAC;QAC5B,oBAAoB,EAAE,KAAK,CAAC;QAC5B,iBAAiB,EAAE,KAAK,CAAC;QACzB,oBAAoB,EAAE,KAAK,CAAC;QAC5B,0BAA0B,EAAE,IAAI,CAAC;KAClC,CAAC;CACH;AAsBD,wBAAsB,gBAAgB,CACpC,KAAK,GAAE,WAAkC,GACxC,OAAO,CAAC,qBAAqB,CAAC,CAiHhC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hasna/instructions",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "AI coding agent instruction & configuration manager — store, version, apply, and share all your AI coding configs. CLI + MCP + HTTP API (instructions-serve) + generated SDK + Dashboard.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|