create-agentfs 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/LICENSE +21 -0
- package/README.md +238 -0
- package/dist/cli.d.ts +51 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +246 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/compile.d.ts +48 -0
- package/dist/commands/compile.d.ts.map +1 -0
- package/dist/commands/compile.js +228 -0
- package/dist/commands/compile.js.map +1 -0
- package/dist/commands/cron.d.ts +18 -0
- package/dist/commands/cron.d.ts.map +1 -0
- package/dist/commands/cron.js +95 -0
- package/dist/commands/cron.js.map +1 -0
- package/dist/commands/doctor.d.ts +11 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +199 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/memory.d.ts +19 -0
- package/dist/commands/memory.d.ts.map +1 -0
- package/dist/commands/memory.js +213 -0
- package/dist/commands/memory.js.map +1 -0
- package/dist/commands/onboard.d.ts +31 -0
- package/dist/commands/onboard.d.ts.map +1 -0
- package/dist/commands/onboard.js +362 -0
- package/dist/commands/onboard.js.map +1 -0
- package/dist/commands/secret.d.ts +13 -0
- package/dist/commands/secret.d.ts.map +1 -0
- package/dist/commands/secret.js +109 -0
- package/dist/commands/secret.js.map +1 -0
- package/dist/commands/security.d.ts +16 -0
- package/dist/commands/security.d.ts.map +1 -0
- package/dist/commands/security.js +203 -0
- package/dist/commands/security.js.map +1 -0
- package/dist/commands/sync.d.ts +14 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +84 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/compilers/agent-map.d.ts +34 -0
- package/dist/compilers/agent-map.d.ts.map +1 -0
- package/dist/compilers/agent-map.js +66 -0
- package/dist/compilers/agent-map.js.map +1 -0
- package/dist/compilers/base.d.ts +67 -0
- package/dist/compilers/base.d.ts.map +1 -0
- package/dist/compilers/base.js +183 -0
- package/dist/compilers/base.js.map +1 -0
- package/dist/compilers/claude.d.ts +26 -0
- package/dist/compilers/claude.d.ts.map +1 -0
- package/dist/compilers/claude.js +151 -0
- package/dist/compilers/claude.js.map +1 -0
- package/dist/compilers/cursor.d.ts +11 -0
- package/dist/compilers/cursor.d.ts.map +1 -0
- package/dist/compilers/cursor.js +52 -0
- package/dist/compilers/cursor.js.map +1 -0
- package/dist/compilers/index.d.ts +14 -0
- package/dist/compilers/index.d.ts.map +1 -0
- package/dist/compilers/index.js +14 -0
- package/dist/compilers/index.js.map +1 -0
- package/dist/compilers/openclaw.d.ts +12 -0
- package/dist/compilers/openclaw.d.ts.map +1 -0
- package/dist/compilers/openclaw.js +51 -0
- package/dist/compilers/openclaw.js.map +1 -0
- package/dist/cron/index.d.ts +10 -0
- package/dist/cron/index.d.ts.map +1 -0
- package/dist/cron/index.js +9 -0
- package/dist/cron/index.js.map +1 -0
- package/dist/cron/jobs/consolidate.d.ts +16 -0
- package/dist/cron/jobs/consolidate.d.ts.map +1 -0
- package/dist/cron/jobs/consolidate.js +61 -0
- package/dist/cron/jobs/consolidate.js.map +1 -0
- package/dist/cron/jobs/heartbeat.d.ts +11 -0
- package/dist/cron/jobs/heartbeat.d.ts.map +1 -0
- package/dist/cron/jobs/heartbeat.js +66 -0
- package/dist/cron/jobs/heartbeat.js.map +1 -0
- package/dist/cron/jobs/inbox-triage.d.ts +11 -0
- package/dist/cron/jobs/inbox-triage.d.ts.map +1 -0
- package/dist/cron/jobs/inbox-triage.js +85 -0
- package/dist/cron/jobs/inbox-triage.js.map +1 -0
- package/dist/cron/runner.d.ts +32 -0
- package/dist/cron/runner.d.ts.map +1 -0
- package/dist/cron/runner.js +69 -0
- package/dist/cron/runner.js.map +1 -0
- package/dist/cron/types.d.ts +21 -0
- package/dist/cron/types.d.ts.map +1 -0
- package/dist/cron/types.js +6 -0
- package/dist/cron/types.js.map +1 -0
- package/dist/generators/filesystem.d.ts +52 -0
- package/dist/generators/filesystem.d.ts.map +1 -0
- package/dist/generators/filesystem.js +155 -0
- package/dist/generators/filesystem.js.map +1 -0
- package/dist/generators/ignore.d.ts +38 -0
- package/dist/generators/ignore.d.ts.map +1 -0
- package/dist/generators/ignore.js +154 -0
- package/dist/generators/ignore.js.map +1 -0
- package/dist/generators/index.d.ts +14 -0
- package/dist/generators/index.d.ts.map +1 -0
- package/dist/generators/index.js +14 -0
- package/dist/generators/index.js.map +1 -0
- package/dist/generators/init.d.ts +37 -0
- package/dist/generators/init.d.ts.map +1 -0
- package/dist/generators/init.js +169 -0
- package/dist/generators/init.js.map +1 -0
- package/dist/generators/manifest.d.ts +31 -0
- package/dist/generators/manifest.d.ts.map +1 -0
- package/dist/generators/manifest.js +123 -0
- package/dist/generators/manifest.js.map +1 -0
- package/dist/generators/memory.d.ts +36 -0
- package/dist/generators/memory.d.ts.map +1 -0
- package/dist/generators/memory.js +106 -0
- package/dist/generators/memory.js.map +1 -0
- package/dist/generators/profiles.d.ts +22 -0
- package/dist/generators/profiles.d.ts.map +1 -0
- package/dist/generators/profiles.js +92 -0
- package/dist/generators/profiles.js.map +1 -0
- package/dist/generators/prompts.d.ts +24 -0
- package/dist/generators/prompts.d.ts.map +1 -0
- package/dist/generators/prompts.js +122 -0
- package/dist/generators/prompts.js.map +1 -0
- package/dist/generators/scaffold.d.ts +29 -0
- package/dist/generators/scaffold.d.ts.map +1 -0
- package/dist/generators/scaffold.js +90 -0
- package/dist/generators/scaffold.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/confidence.d.ts +69 -0
- package/dist/memory/confidence.d.ts.map +1 -0
- package/dist/memory/confidence.js +125 -0
- package/dist/memory/confidence.js.map +1 -0
- package/dist/memory/episodic.d.ts +40 -0
- package/dist/memory/episodic.d.ts.map +1 -0
- package/dist/memory/episodic.js +139 -0
- package/dist/memory/episodic.js.map +1 -0
- package/dist/memory/index.d.ts +17 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +17 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/parser.d.ts +73 -0
- package/dist/memory/parser.d.ts.map +1 -0
- package/dist/memory/parser.js +156 -0
- package/dist/memory/parser.js.map +1 -0
- package/dist/memory/procedural.d.ts +43 -0
- package/dist/memory/procedural.d.ts.map +1 -0
- package/dist/memory/procedural.js +126 -0
- package/dist/memory/procedural.js.map +1 -0
- package/dist/secrets/exfil-guard.d.ts +31 -0
- package/dist/secrets/exfil-guard.d.ts.map +1 -0
- package/dist/secrets/exfil-guard.js +51 -0
- package/dist/secrets/exfil-guard.js.map +1 -0
- package/dist/secrets/index.d.ts +8 -0
- package/dist/secrets/index.d.ts.map +1 -0
- package/dist/secrets/index.js +7 -0
- package/dist/secrets/index.js.map +1 -0
- package/dist/secrets/vault.d.ts +63 -0
- package/dist/secrets/vault.d.ts.map +1 -0
- package/dist/secrets/vault.js +163 -0
- package/dist/secrets/vault.js.map +1 -0
- package/dist/security/claude-compiler.d.ts +28 -0
- package/dist/security/claude-compiler.d.ts.map +1 -0
- package/dist/security/claude-compiler.js +66 -0
- package/dist/security/claude-compiler.js.map +1 -0
- package/dist/security/index.d.ts +7 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +7 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/parser.d.ts +47 -0
- package/dist/security/parser.d.ts.map +1 -0
- package/dist/security/parser.js +136 -0
- package/dist/security/parser.js.map +1 -0
- package/dist/sync/index.d.ts +7 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +6 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/sync.d.ts +46 -0
- package/dist/sync/sync.d.ts.map +1 -0
- package/dist/sync/sync.js +174 -0
- package/dist/sync/sync.js.map +1 -0
- package/dist/types/compiler.d.ts +81 -0
- package/dist/types/compiler.d.ts.map +1 -0
- package/dist/types/compiler.js +10 -0
- package/dist/types/compiler.js.map +1 -0
- package/dist/types/index.d.ts +15 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/manifest.d.ts +112 -0
- package/dist/types/manifest.d.ts.map +1 -0
- package/dist/types/manifest.js +10 -0
- package/dist/types/manifest.js.map +1 -0
- package/dist/types/memory.d.ts +85 -0
- package/dist/types/memory.d.ts.map +1 -0
- package/dist/types/memory.js +20 -0
- package/dist/types/memory.js.map +1 -0
- package/dist/types/security.d.ts +67 -0
- package/dist/types/security.d.ts.map +1 -0
- package/dist/types/security.js +10 -0
- package/dist/types/security.js.map +1 -0
- package/dist/types/setup.d.ts +54 -0
- package/dist/types/setup.d.ts.map +1 -0
- package/dist/types/setup.js +9 -0
- package/dist/types/setup.js.map +1 -0
- package/dist/utils/fhs-mapping.d.ts +76 -0
- package/dist/utils/fhs-mapping.d.ts.map +1 -0
- package/dist/utils/fhs-mapping.js +189 -0
- package/dist/utils/fhs-mapping.js.map +1 -0
- package/package.json +58 -0
- package/templates/compilers/agent-map.md.hbs +36 -0
- package/templates/compilers/claude.md.hbs +95 -0
- package/templates/procedural/code-review.md +54 -0
- package/templates/procedural/debugging.md +52 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consolidation cron job — Story 6.1.
|
|
3
|
+
*
|
|
4
|
+
* Runs at session end to snapshot memory state:
|
|
5
|
+
* - Reads semantic.md and reports active/superseded counts
|
|
6
|
+
* - Lists episodic entries
|
|
7
|
+
* - Lists procedural skills
|
|
8
|
+
*
|
|
9
|
+
* Future enhancement: auto-extract new facts from session transcript,
|
|
10
|
+
* detect contradictions, and trigger decay on stale patterns.
|
|
11
|
+
*
|
|
12
|
+
* @module cron/jobs/consolidate
|
|
13
|
+
*/
|
|
14
|
+
import fs from 'node:fs/promises';
|
|
15
|
+
import path from 'node:path';
|
|
16
|
+
import { parseSemanticMemory, isSuperseded } from '../../memory/index.js';
|
|
17
|
+
import { listEpisodicDates } from '../../memory/episodic.js';
|
|
18
|
+
import { listProceduralSkills } from '../../memory/procedural.js';
|
|
19
|
+
import { writeEpisodicEntry } from '../../memory/episodic.js';
|
|
20
|
+
export const consolidateJob = {
|
|
21
|
+
name: 'consolidate',
|
|
22
|
+
description: 'Snapshot memory state at session end',
|
|
23
|
+
async run(vaultRoot) {
|
|
24
|
+
const semanticPath = path.join(vaultRoot, '.agentos/memory/semantic.md');
|
|
25
|
+
let semanticContent;
|
|
26
|
+
try {
|
|
27
|
+
semanticContent = await fs.readFile(semanticPath, 'utf8');
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return {
|
|
31
|
+
success: false,
|
|
32
|
+
job: 'consolidate',
|
|
33
|
+
message: 'No semantic memory found. Run `agentfs onboard` first.',
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
const entries = parseSemanticMemory(semanticContent);
|
|
37
|
+
const active = entries.filter((e) => !isSuperseded(e));
|
|
38
|
+
const superseded = entries.filter((e) => isSuperseded(e));
|
|
39
|
+
const episodicDates = await listEpisodicDates(vaultRoot);
|
|
40
|
+
const proceduralSkills = await listProceduralSkills(vaultRoot);
|
|
41
|
+
// Write an episodic entry for today's consolidation
|
|
42
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
43
|
+
await writeEpisodicEntry(vaultRoot, {
|
|
44
|
+
date: today,
|
|
45
|
+
events: [`Memory consolidation ran`],
|
|
46
|
+
decisions: [],
|
|
47
|
+
lessons: [],
|
|
48
|
+
});
|
|
49
|
+
return {
|
|
50
|
+
success: true,
|
|
51
|
+
job: 'consolidate',
|
|
52
|
+
message: `Consolidation complete. Semantic: ${active.length} active, ${superseded.length} superseded. Episodic: ${episodicDates.length} days. Procedural: ${proceduralSkills.length} skills.`,
|
|
53
|
+
details: {
|
|
54
|
+
semantic: { active: active.length, superseded: superseded.length },
|
|
55
|
+
episodic: episodicDates.length,
|
|
56
|
+
procedural: proceduralSkills.length,
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=consolidate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consolidate.js","sourceRoot":"","sources":["../../../src/cron/jobs/consolidate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D,MAAM,CAAC,MAAM,cAAc,GAAY;IACrC,IAAI,EAAE,aAAa;IACnB,WAAW,EAAE,sCAAsC;IAEnD,KAAK,CAAC,GAAG,CAAC,SAAiB;QACzB,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,6BAA6B,CAAC,CAAC;QAEzE,IAAI,eAAuB,CAAC;QAC5B,IAAI,CAAC;YACH,eAAe,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,GAAG,EAAE,aAAa;gBAClB,OAAO,EAAE,wDAAwD;aAClE,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,GAAG,mBAAmB,CAAC,eAAe,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;QACvD,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;QAE1D,MAAM,aAAa,GAAG,MAAM,iBAAiB,CAAC,SAAS,CAAC,CAAC;QACzD,MAAM,gBAAgB,GAAG,MAAM,oBAAoB,CAAC,SAAS,CAAC,CAAC;QAE/D,oDAAoD;QACpD,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACpD,MAAM,kBAAkB,CAAC,SAAS,EAAE;YAClC,IAAI,EAAE,KAAK;YACX,MAAM,EAAE,CAAC,0BAA0B,CAAC;YACpC,SAAS,EAAE,EAAE;YACb,OAAO,EAAE,EAAE;SACZ,CAAC,CAAC;QAEH,OAAO;YACL,OAAO,EAAE,IAAI;YACb,GAAG,EAAE,aAAa;YAClB,OAAO,EAAE,qCAAqC,MAAM,CAAC,MAAM,YAAY,UAAU,CAAC,MAAM,0BAA0B,aAAa,CAAC,MAAM,sBAAsB,gBAAgB,CAAC,MAAM,UAAU;YAC7L,OAAO,EAAE;gBACP,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC,MAAM,EAAE;gBAClE,QAAQ,EAAE,aAAa,CAAC,MAAM;gBAC9B,UAAU,EAAE,gBAAgB,CAAC,MAAM;aACpC;SACF,CAAC;IACJ,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Heartbeat cron job — Story 6.4.
|
|
3
|
+
*
|
|
4
|
+
* Writes periodic status to `.agentos/proc/status.md` so that
|
|
5
|
+
* runtime state is observable.
|
|
6
|
+
*
|
|
7
|
+
* @module cron/jobs/heartbeat
|
|
8
|
+
*/
|
|
9
|
+
import type { CronJob } from '../types.js';
|
|
10
|
+
export declare const heartbeatJob: CronJob;
|
|
11
|
+
//# sourceMappingURL=heartbeat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heartbeat.d.ts","sourceRoot":"","sources":["../../../src/cron/jobs/heartbeat.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,aAAa,CAAC;AAEvD,eAAO,MAAM,YAAY,EAAE,OA4D1B,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Heartbeat cron job — Story 6.4.
|
|
3
|
+
*
|
|
4
|
+
* Writes periodic status to `.agentos/proc/status.md` so that
|
|
5
|
+
* runtime state is observable.
|
|
6
|
+
*
|
|
7
|
+
* @module cron/jobs/heartbeat
|
|
8
|
+
*/
|
|
9
|
+
import fs from 'node:fs/promises';
|
|
10
|
+
import path from 'node:path';
|
|
11
|
+
export const heartbeatJob = {
|
|
12
|
+
name: 'heartbeat',
|
|
13
|
+
description: 'Write runtime status to .agentos/proc/status.md',
|
|
14
|
+
async run(vaultRoot) {
|
|
15
|
+
const procDir = path.join(vaultRoot, '.agentos/proc');
|
|
16
|
+
await fs.mkdir(procDir, { recursive: true });
|
|
17
|
+
const statusPath = path.join(procDir, 'status.md');
|
|
18
|
+
const now = new Date();
|
|
19
|
+
const timestamp = now.toISOString();
|
|
20
|
+
// Check for overdue tasks in Tasks/ directory
|
|
21
|
+
let overdueTasks = [];
|
|
22
|
+
const tasksDir = path.join(vaultRoot, 'Tasks');
|
|
23
|
+
try {
|
|
24
|
+
const files = await fs.readdir(tasksDir);
|
|
25
|
+
const mdFiles = files.filter((f) => f.endsWith('.md'));
|
|
26
|
+
for (const file of mdFiles) {
|
|
27
|
+
const content = await fs.readFile(path.join(tasksDir, file), 'utf8');
|
|
28
|
+
const dueLine = content.split('\n').find((l) => l.startsWith('due:'));
|
|
29
|
+
if (dueLine) {
|
|
30
|
+
const dueDate = dueLine.replace('due:', '').trim();
|
|
31
|
+
if (dueDate <= now.toISOString().slice(0, 10)) {
|
|
32
|
+
overdueTasks.push(file.replace('.md', ''));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// No Tasks/ directory — that's fine
|
|
39
|
+
}
|
|
40
|
+
const lines = [
|
|
41
|
+
'# Agent Status',
|
|
42
|
+
'',
|
|
43
|
+
`**Last heartbeat:** ${timestamp}`,
|
|
44
|
+
`**Status:** active`,
|
|
45
|
+
'',
|
|
46
|
+
];
|
|
47
|
+
if (overdueTasks.length > 0) {
|
|
48
|
+
lines.push('## Overdue Tasks');
|
|
49
|
+
for (const task of overdueTasks) {
|
|
50
|
+
lines.push(`- ⚠️ ${task}`);
|
|
51
|
+
}
|
|
52
|
+
lines.push('');
|
|
53
|
+
}
|
|
54
|
+
await fs.writeFile(statusPath, lines.join('\n'), 'utf8');
|
|
55
|
+
return {
|
|
56
|
+
success: true,
|
|
57
|
+
job: 'heartbeat',
|
|
58
|
+
message: `Heartbeat written at ${timestamp}. ${overdueTasks.length} overdue task(s).`,
|
|
59
|
+
details: {
|
|
60
|
+
timestamp,
|
|
61
|
+
overdueTasks: overdueTasks.length,
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=heartbeat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../../../src/cron/jobs/heartbeat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inbox triage cron job — Story 6.3.
|
|
3
|
+
*
|
|
4
|
+
* Scans `Inbox/` for markdown files and suggests routing based on
|
|
5
|
+
* frontmatter tags. Does NOT automatically move files — suggestions only.
|
|
6
|
+
*
|
|
7
|
+
* @module cron/jobs/inbox-triage
|
|
8
|
+
*/
|
|
9
|
+
import type { CronJob } from '../types.js';
|
|
10
|
+
export declare const inboxTriageJob: CronJob;
|
|
11
|
+
//# sourceMappingURL=inbox-triage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox-triage.d.ts","sourceRoot":"","sources":["../../../src/cron/jobs/inbox-triage.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,aAAa,CAAC;AAkCvD,eAAO,MAAM,cAAc,EAAE,OA6C5B,CAAC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inbox triage cron job — Story 6.3.
|
|
3
|
+
*
|
|
4
|
+
* Scans `Inbox/` for markdown files and suggests routing based on
|
|
5
|
+
* frontmatter tags. Does NOT automatically move files — suggestions only.
|
|
6
|
+
*
|
|
7
|
+
* @module cron/jobs/inbox-triage
|
|
8
|
+
*/
|
|
9
|
+
import fs from 'node:fs/promises';
|
|
10
|
+
import path from 'node:path';
|
|
11
|
+
/** Simple frontmatter tag extraction. */
|
|
12
|
+
function extractTags(content) {
|
|
13
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
14
|
+
if (!match)
|
|
15
|
+
return [];
|
|
16
|
+
const frontmatter = match[1];
|
|
17
|
+
const tagLine = frontmatter.split('\n').find((l) => l.startsWith('tags:'));
|
|
18
|
+
if (!tagLine)
|
|
19
|
+
return [];
|
|
20
|
+
// Support `tags: [a, b]` or `tags: a, b`
|
|
21
|
+
const raw = tagLine.replace('tags:', '').trim();
|
|
22
|
+
return raw
|
|
23
|
+
.replace(/[\[\]]/g, '')
|
|
24
|
+
.split(',')
|
|
25
|
+
.map((t) => t.trim())
|
|
26
|
+
.filter(Boolean);
|
|
27
|
+
}
|
|
28
|
+
/** Suggest a target folder based on tags. */
|
|
29
|
+
function suggestFolder(tags) {
|
|
30
|
+
const tagSet = new Set(tags.map((t) => t.toLowerCase()));
|
|
31
|
+
if (tagSet.has('project') || tagSet.has('work'))
|
|
32
|
+
return 'Projects';
|
|
33
|
+
if (tagSet.has('daily') || tagSet.has('journal'))
|
|
34
|
+
return 'Daily';
|
|
35
|
+
if (tagSet.has('resource') || tagSet.has('reference'))
|
|
36
|
+
return 'Resources';
|
|
37
|
+
if (tagSet.has('person') || tagSet.has('contact'))
|
|
38
|
+
return 'People';
|
|
39
|
+
if (tagSet.has('engineering') || tagSet.has('devops'))
|
|
40
|
+
return 'Engineering';
|
|
41
|
+
if (tagSet.has('career') || tagSet.has('job'))
|
|
42
|
+
return 'Career';
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
export const inboxTriageJob = {
|
|
46
|
+
name: 'inbox-triage',
|
|
47
|
+
description: 'Scan Inbox/ and suggest file routing based on tags',
|
|
48
|
+
async run(vaultRoot) {
|
|
49
|
+
const inboxDir = path.join(vaultRoot, 'Inbox');
|
|
50
|
+
let files;
|
|
51
|
+
try {
|
|
52
|
+
const entries = await fs.readdir(inboxDir);
|
|
53
|
+
files = entries.filter((f) => f.endsWith('.md'));
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return {
|
|
57
|
+
success: true,
|
|
58
|
+
job: 'inbox-triage',
|
|
59
|
+
message: 'No Inbox/ directory found. Nothing to triage.',
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (files.length === 0) {
|
|
63
|
+
return {
|
|
64
|
+
success: true,
|
|
65
|
+
job: 'inbox-triage',
|
|
66
|
+
message: 'Inbox is empty. Nothing to triage.',
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
const suggestions = [];
|
|
70
|
+
for (const file of files) {
|
|
71
|
+
const content = await fs.readFile(path.join(inboxDir, file), 'utf8');
|
|
72
|
+
const tags = extractTags(content);
|
|
73
|
+
const suggestion = suggestFolder(tags);
|
|
74
|
+
suggestions.push({ file, tags, suggestion });
|
|
75
|
+
}
|
|
76
|
+
const withSuggestion = suggestions.filter((s) => s.suggestion !== null);
|
|
77
|
+
return {
|
|
78
|
+
success: true,
|
|
79
|
+
job: 'inbox-triage',
|
|
80
|
+
message: `Triaged ${files.length} file(s): ${withSuggestion.length} with suggestions, ${files.length - withSuggestion.length} unclassified.`,
|
|
81
|
+
details: { suggestions },
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
//# sourceMappingURL=inbox-triage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox-triage.js","sourceRoot":"","sources":["../../../src/cron/jobs/inbox-triage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cron job runner — scheduled tasks for memory maintenance.
|
|
3
|
+
*
|
|
4
|
+
* Provides a registry of cron jobs that can be triggered by:
|
|
5
|
+
* - Session end hooks (consolidation)
|
|
6
|
+
* - Manual CLI invocation (`agentfs cron run <job>`)
|
|
7
|
+
* - Future: actual cron scheduling via OS-level timers
|
|
8
|
+
*
|
|
9
|
+
* Each job implements the `CronJob` interface and is registered
|
|
10
|
+
* in the `CRON_REGISTRY`.
|
|
11
|
+
*
|
|
12
|
+
* @module cron/runner
|
|
13
|
+
*/
|
|
14
|
+
import type { CronJob, CronResult } from './types.js';
|
|
15
|
+
/** All available cron jobs, keyed by name. */
|
|
16
|
+
export declare const CRON_REGISTRY: Record<string, CronJob>;
|
|
17
|
+
/**
|
|
18
|
+
* Run a single cron job by name.
|
|
19
|
+
*
|
|
20
|
+
* @param name - Job name from the registry
|
|
21
|
+
* @param vaultRoot - Absolute path to vault root
|
|
22
|
+
* @returns CronResult with success flag, message, and optional details
|
|
23
|
+
*/
|
|
24
|
+
export declare function runCronJob(name: string, vaultRoot: string): Promise<CronResult>;
|
|
25
|
+
/**
|
|
26
|
+
* Run all registered cron jobs.
|
|
27
|
+
*
|
|
28
|
+
* @param vaultRoot - Absolute path to vault root
|
|
29
|
+
* @returns Array of CronResults, one per job
|
|
30
|
+
*/
|
|
31
|
+
export declare function runAllCronJobs(vaultRoot: string): Promise<CronResult[]>;
|
|
32
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/cron/runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAStD,8CAA8C;AAC9C,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAIjD,CAAC;AAMF;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,UAAU,CAAC,CAmBrB;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,UAAU,EAAE,CAAC,CAMvB"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cron job runner — scheduled tasks for memory maintenance.
|
|
3
|
+
*
|
|
4
|
+
* Provides a registry of cron jobs that can be triggered by:
|
|
5
|
+
* - Session end hooks (consolidation)
|
|
6
|
+
* - Manual CLI invocation (`agentfs cron run <job>`)
|
|
7
|
+
* - Future: actual cron scheduling via OS-level timers
|
|
8
|
+
*
|
|
9
|
+
* Each job implements the `CronJob` interface and is registered
|
|
10
|
+
* in the `CRON_REGISTRY`.
|
|
11
|
+
*
|
|
12
|
+
* @module cron/runner
|
|
13
|
+
*/
|
|
14
|
+
import { consolidateJob } from './jobs/consolidate.js';
|
|
15
|
+
import { heartbeatJob } from './jobs/heartbeat.js';
|
|
16
|
+
import { inboxTriageJob } from './jobs/inbox-triage.js';
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Registry
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
/** All available cron jobs, keyed by name. */
|
|
21
|
+
export const CRON_REGISTRY = {
|
|
22
|
+
consolidate: consolidateJob,
|
|
23
|
+
heartbeat: heartbeatJob,
|
|
24
|
+
'inbox-triage': inboxTriageJob,
|
|
25
|
+
};
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Runner
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
/**
|
|
30
|
+
* Run a single cron job by name.
|
|
31
|
+
*
|
|
32
|
+
* @param name - Job name from the registry
|
|
33
|
+
* @param vaultRoot - Absolute path to vault root
|
|
34
|
+
* @returns CronResult with success flag, message, and optional details
|
|
35
|
+
*/
|
|
36
|
+
export async function runCronJob(name, vaultRoot) {
|
|
37
|
+
const job = CRON_REGISTRY[name];
|
|
38
|
+
if (!job) {
|
|
39
|
+
return {
|
|
40
|
+
success: false,
|
|
41
|
+
job: name,
|
|
42
|
+
message: `Unknown cron job: '${name}'`,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
return await job.run(vaultRoot);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
return {
|
|
50
|
+
success: false,
|
|
51
|
+
job: name,
|
|
52
|
+
message: `Job '${name}' failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Run all registered cron jobs.
|
|
58
|
+
*
|
|
59
|
+
* @param vaultRoot - Absolute path to vault root
|
|
60
|
+
* @returns Array of CronResults, one per job
|
|
61
|
+
*/
|
|
62
|
+
export async function runAllCronJobs(vaultRoot) {
|
|
63
|
+
const results = [];
|
|
64
|
+
for (const [name] of Object.entries(CRON_REGISTRY)) {
|
|
65
|
+
results.push(await runCronJob(name, vaultRoot));
|
|
66
|
+
}
|
|
67
|
+
return results;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/cron/runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,8EAA8E;AAC9E,WAAW;AACX,8EAA8E;AAE9E,8CAA8C;AAC9C,MAAM,CAAC,MAAM,aAAa,GAA4B;IACpD,WAAW,EAAE,cAAc;IAC3B,SAAS,EAAE,YAAY;IACvB,cAAc,EAAE,cAAc;CAC/B,CAAC;AAEF,8EAA8E;AAC9E,SAAS;AACT,8EAA8E;AAE9E;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,IAAY,EACZ,SAAiB;IAEjB,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO;YACL,OAAO,EAAE,KAAK;YACd,GAAG,EAAE,IAAI;YACT,OAAO,EAAE,sBAAsB,IAAI,GAAG;SACvC,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,OAAO,MAAM,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,OAAO,EAAE,KAAK;YACd,GAAG,EAAE,IAAI;YACT,OAAO,EAAE,QAAQ,IAAI,aAAa,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;SACrF,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,SAAiB;IAEjB,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC,MAAM,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cron job types.
|
|
3
|
+
* @module cron/types
|
|
4
|
+
*/
|
|
5
|
+
/** Result returned by every cron job execution. */
|
|
6
|
+
export interface CronResult {
|
|
7
|
+
success: boolean;
|
|
8
|
+
job: string;
|
|
9
|
+
message: string;
|
|
10
|
+
details?: Record<string, unknown>;
|
|
11
|
+
}
|
|
12
|
+
/** A cron job that can be run against a vault. */
|
|
13
|
+
export interface CronJob {
|
|
14
|
+
/** Human-readable job name. */
|
|
15
|
+
name: string;
|
|
16
|
+
/** Short description of what this job does. */
|
|
17
|
+
description: string;
|
|
18
|
+
/** Execute the job. */
|
|
19
|
+
run(vaultRoot: string): Promise<CronResult>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/cron/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,mDAAmD;AACnD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,kDAAkD;AAClD,MAAM,WAAW,OAAO;IACtB,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,uBAAuB;IACvB,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC7C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/cron/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filesystem Generator — creates the vault directory structure for AgentFS.
|
|
3
|
+
*
|
|
4
|
+
* Produces all FHS-mapped user space directories (profile-dependent) plus the
|
|
5
|
+
* fixed kernel space tree under `.agentos/`. Directories that already exist
|
|
6
|
+
* are counted as skipped rather than overwritten, ensuring idempotent behaviour.
|
|
7
|
+
*
|
|
8
|
+
* @module generators/filesystem
|
|
9
|
+
* @see docs/architecture.md Section 1 "Three-layer architecture"
|
|
10
|
+
* @see docs/architecture.md Section 11 "FHS Mapping"
|
|
11
|
+
*/
|
|
12
|
+
import type { SetupAnswers, GeneratorResult } from '../types/index.js';
|
|
13
|
+
/**
|
|
14
|
+
* Generates the complete vault directory structure for a new AgentFS vault.
|
|
15
|
+
*
|
|
16
|
+
* Creates two categories of directories under `answers.targetDir`:
|
|
17
|
+
*
|
|
18
|
+
* 1. **User space** — FHS-mapped directories derived from `answers.profile`
|
|
19
|
+
* via `getDefaultPaths()`. These vary per profile (e.g. `personal` gets
|
|
20
|
+
* `Work/`, `Career/`, `Engineering/`; `company` gets `Teams/`, `Clients/`).
|
|
21
|
+
*
|
|
22
|
+
* 2. **Kernel space** — The fixed `.agentos/` subtree required by every vault:
|
|
23
|
+
* `init.d/`, `compile.d/`, `security/profiles/`, `security/audit/`,
|
|
24
|
+
* `cron.d/`, `proc/signals/`, `proc/locks/`, `memory/episodic/`,
|
|
25
|
+
* `memory/procedural/`, `hooks/`, and `bin/`.
|
|
26
|
+
*
|
|
27
|
+
* All directories are created with `mkdir({ recursive: true })`, making the
|
|
28
|
+
* operation safe to re-run on an existing vault. Already-present directories
|
|
29
|
+
* are recorded in `result.skipped`; newly created ones in `result.created`.
|
|
30
|
+
* Both lists contain absolute paths.
|
|
31
|
+
*
|
|
32
|
+
* @param answers - Collected setup wizard answers. `answers.targetDir` is the
|
|
33
|
+
* vault root; `answers.profile` drives the user-space layout.
|
|
34
|
+
* @returns A `GeneratorResult` with absolute paths split into `created` and
|
|
35
|
+
* `skipped` lists.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* const result = await generateFilesystem({
|
|
40
|
+
* vaultName: 'my-notes',
|
|
41
|
+
* ownerName: 'Alice',
|
|
42
|
+
* profile: 'personal',
|
|
43
|
+
* primaryAgent: 'claude',
|
|
44
|
+
* supportedAgents: ['claude'],
|
|
45
|
+
* modules: [],
|
|
46
|
+
* targetDir: '/home/alice/my-notes',
|
|
47
|
+
* });
|
|
48
|
+
* console.log(result.created.length); // number of newly created dirs
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare function generateFilesystem(answers: SetupAnswers): Promise<GeneratorResult>;
|
|
52
|
+
//# sourceMappingURL=filesystem.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filesystem.d.ts","sourceRoot":"","sources":["../../src/generators/filesystem.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAY,MAAM,mBAAmB,CAAC;AA+FjF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC,CAyBxF"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filesystem Generator — creates the vault directory structure for AgentFS.
|
|
3
|
+
*
|
|
4
|
+
* Produces all FHS-mapped user space directories (profile-dependent) plus the
|
|
5
|
+
* fixed kernel space tree under `.agentos/`. Directories that already exist
|
|
6
|
+
* are counted as skipped rather than overwritten, ensuring idempotent behaviour.
|
|
7
|
+
*
|
|
8
|
+
* @module generators/filesystem
|
|
9
|
+
* @see docs/architecture.md Section 1 "Three-layer architecture"
|
|
10
|
+
* @see docs/architecture.md Section 11 "FHS Mapping"
|
|
11
|
+
*/
|
|
12
|
+
import { mkdir, stat } from 'node:fs/promises';
|
|
13
|
+
import { join } from 'node:path';
|
|
14
|
+
import { getDefaultPaths } from '../utils/fhs-mapping.js';
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Kernel space directories — fixed for every vault regardless of profile.
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
/**
|
|
19
|
+
* Relative paths (from vault root) for every kernel space directory that must
|
|
20
|
+
* exist under `.agentos/`. Order is irrelevant — all are created with
|
|
21
|
+
* `recursive: true`.
|
|
22
|
+
*/
|
|
23
|
+
const KERNEL_DIRS = [
|
|
24
|
+
'.agentos/init.d',
|
|
25
|
+
'.agentos/compile.d',
|
|
26
|
+
'.agentos/security/profiles',
|
|
27
|
+
'.agentos/security/audit',
|
|
28
|
+
'.agentos/cron.d',
|
|
29
|
+
'.agentos/proc/signals',
|
|
30
|
+
'.agentos/proc/locks',
|
|
31
|
+
'.agentos/memory/episodic',
|
|
32
|
+
'.agentos/memory/procedural',
|
|
33
|
+
'.agentos/hooks',
|
|
34
|
+
'.agentos/bin',
|
|
35
|
+
];
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// Helpers
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
/**
|
|
40
|
+
* Returns `true` when the filesystem entry at `absPath` already exists
|
|
41
|
+
* (whether a directory or a file). Returns `false` on ENOENT; re-throws any
|
|
42
|
+
* other OS error to avoid silently masking permission problems.
|
|
43
|
+
*/
|
|
44
|
+
async function pathExists(absPath) {
|
|
45
|
+
try {
|
|
46
|
+
await stat(absPath);
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
if (err.code === 'ENOENT') {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
throw err;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Attempts to create a single directory (and any missing ancestors via
|
|
58
|
+
* `recursive: true`). Resolves with `'created'` when the directory was new,
|
|
59
|
+
* or `'skipped'` when it already existed before the call.
|
|
60
|
+
*
|
|
61
|
+
* @param absPath - Absolute path to the directory to create.
|
|
62
|
+
* @returns Whether the directory was freshly created or already present.
|
|
63
|
+
*/
|
|
64
|
+
async function ensureDir(absPath) {
|
|
65
|
+
const existed = await pathExists(absPath);
|
|
66
|
+
await mkdir(absPath, { recursive: true });
|
|
67
|
+
return existed ? 'skipped' : 'created';
|
|
68
|
+
}
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
// User-space path derivation
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
/**
|
|
73
|
+
* Derives the set of unique vault-relative directory strings from an
|
|
74
|
+
* `FhsPaths` instance, filtering out any `undefined` optional paths.
|
|
75
|
+
*
|
|
76
|
+
* `FhsPaths` values are vault-relative strings (e.g. `'Inbox'`, `'Projects'`).
|
|
77
|
+
* De-duplication is applied because some profiles (e.g. `shared`) collapse
|
|
78
|
+
* two FHS keys onto the same vault directory (e.g. `srv` and `usr_share`
|
|
79
|
+
* both resolve to `'Shared'`).
|
|
80
|
+
*
|
|
81
|
+
* @param paths - Resolved FHS paths for the chosen profile.
|
|
82
|
+
* @returns Array of unique vault-relative directory paths to create.
|
|
83
|
+
*/
|
|
84
|
+
function userSpaceDirs(paths) {
|
|
85
|
+
const seen = new Set();
|
|
86
|
+
const result = [];
|
|
87
|
+
for (const value of Object.values(paths)) {
|
|
88
|
+
if (typeof value === 'string' && !seen.has(value)) {
|
|
89
|
+
seen.add(value);
|
|
90
|
+
result.push(value);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
// Main export
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
/**
|
|
99
|
+
* Generates the complete vault directory structure for a new AgentFS vault.
|
|
100
|
+
*
|
|
101
|
+
* Creates two categories of directories under `answers.targetDir`:
|
|
102
|
+
*
|
|
103
|
+
* 1. **User space** — FHS-mapped directories derived from `answers.profile`
|
|
104
|
+
* via `getDefaultPaths()`. These vary per profile (e.g. `personal` gets
|
|
105
|
+
* `Work/`, `Career/`, `Engineering/`; `company` gets `Teams/`, `Clients/`).
|
|
106
|
+
*
|
|
107
|
+
* 2. **Kernel space** — The fixed `.agentos/` subtree required by every vault:
|
|
108
|
+
* `init.d/`, `compile.d/`, `security/profiles/`, `security/audit/`,
|
|
109
|
+
* `cron.d/`, `proc/signals/`, `proc/locks/`, `memory/episodic/`,
|
|
110
|
+
* `memory/procedural/`, `hooks/`, and `bin/`.
|
|
111
|
+
*
|
|
112
|
+
* All directories are created with `mkdir({ recursive: true })`, making the
|
|
113
|
+
* operation safe to re-run on an existing vault. Already-present directories
|
|
114
|
+
* are recorded in `result.skipped`; newly created ones in `result.created`.
|
|
115
|
+
* Both lists contain absolute paths.
|
|
116
|
+
*
|
|
117
|
+
* @param answers - Collected setup wizard answers. `answers.targetDir` is the
|
|
118
|
+
* vault root; `answers.profile` drives the user-space layout.
|
|
119
|
+
* @returns A `GeneratorResult` with absolute paths split into `created` and
|
|
120
|
+
* `skipped` lists.
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```ts
|
|
124
|
+
* const result = await generateFilesystem({
|
|
125
|
+
* vaultName: 'my-notes',
|
|
126
|
+
* ownerName: 'Alice',
|
|
127
|
+
* profile: 'personal',
|
|
128
|
+
* primaryAgent: 'claude',
|
|
129
|
+
* supportedAgents: ['claude'],
|
|
130
|
+
* modules: [],
|
|
131
|
+
* targetDir: '/home/alice/my-notes',
|
|
132
|
+
* });
|
|
133
|
+
* console.log(result.created.length); // number of newly created dirs
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
export async function generateFilesystem(answers) {
|
|
137
|
+
const { targetDir, profile } = answers;
|
|
138
|
+
const fhsPaths = getDefaultPaths(profile);
|
|
139
|
+
const userDirs = userSpaceDirs(fhsPaths);
|
|
140
|
+
// Combine user-space relative paths with kernel-space relative paths.
|
|
141
|
+
const allRelativeDirs = [...userDirs, ...KERNEL_DIRS];
|
|
142
|
+
const result = {
|
|
143
|
+
created: [],
|
|
144
|
+
skipped: [],
|
|
145
|
+
};
|
|
146
|
+
// Process all directories concurrently — mkdir with recursive:true is safe
|
|
147
|
+
// to run in parallel because parent creation races are handled by the OS.
|
|
148
|
+
await Promise.all(allRelativeDirs.map(async (relPath) => {
|
|
149
|
+
const absPath = join(targetDir, relPath);
|
|
150
|
+
const outcome = await ensureDir(absPath);
|
|
151
|
+
result[outcome].push(absPath);
|
|
152
|
+
}));
|
|
153
|
+
return result;
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=filesystem.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filesystem.js","sourceRoot":"","sources":["../../src/generators/filesystem.ts"],"names":[],"mappings":"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"}
|