@nomai/nomai 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.
- package/LICENSE +21 -0
- package/README.md +98 -0
- package/dist/cli.d.mts +912 -0
- package/dist/cli.mjs +3367 -0
- package/dist/dist-DQ6U1xGI.mjs +2462 -0
- package/dist/dist-DSXfsMP5.mjs +145 -0
- package/dist/index.d.mts +226 -0
- package/dist/index.mjs +2 -0
- package/dist/payload-DdBYzrl3.mjs +473 -0
- package/dist/rolldown-runtime-C7HZzL1F.mjs +26 -0
- package/package.json +52 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { n as __require, t as __commonJSMin } from "./rolldown-runtime-C7HZzL1F.mjs";
|
|
2
|
+
//#region node_modules/@vercel/detect-agent/dist/index.js
|
|
3
|
+
var require_dist = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all) __defProp(target, name, {
|
|
10
|
+
get: all[name],
|
|
11
|
+
enumerable: true
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
var __copyProps = (to, from, except, desc) => {
|
|
15
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
16
|
+
for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
17
|
+
get: () => from[key],
|
|
18
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
return to;
|
|
22
|
+
};
|
|
23
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
24
|
+
var src_exports = {};
|
|
25
|
+
__export(src_exports, {
|
|
26
|
+
KNOWN_AGENTS: () => KNOWN_AGENTS,
|
|
27
|
+
determineAgent: () => determineAgent
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(src_exports);
|
|
30
|
+
var import_promises = __require("node:fs/promises");
|
|
31
|
+
var import_node_fs = __require("node:fs");
|
|
32
|
+
const DEVIN_LOCAL_PATH = "/opt/.devin";
|
|
33
|
+
const CURSOR = "cursor";
|
|
34
|
+
const CURSOR_CLI = "cursor-cli";
|
|
35
|
+
const CLAUDE = "claude";
|
|
36
|
+
const COWORK = "cowork";
|
|
37
|
+
const DEVIN = "devin";
|
|
38
|
+
const REPLIT = "replit";
|
|
39
|
+
const GEMINI = "gemini";
|
|
40
|
+
const CODEX = "codex";
|
|
41
|
+
const ANTIGRAVITY = "antigravity";
|
|
42
|
+
const AUGMENT_CLI = "augment-cli";
|
|
43
|
+
const OPENCODE = "opencode";
|
|
44
|
+
const GITHUB_COPILOT = "github-copilot";
|
|
45
|
+
const GITHUB_COPILOT_CLI = "github-copilot-cli";
|
|
46
|
+
const V0 = "v0";
|
|
47
|
+
const KNOWN_AGENTS = {
|
|
48
|
+
CURSOR,
|
|
49
|
+
CURSOR_CLI,
|
|
50
|
+
CLAUDE,
|
|
51
|
+
COWORK,
|
|
52
|
+
DEVIN,
|
|
53
|
+
REPLIT,
|
|
54
|
+
GEMINI,
|
|
55
|
+
CODEX,
|
|
56
|
+
ANTIGRAVITY,
|
|
57
|
+
AUGMENT_CLI,
|
|
58
|
+
OPENCODE,
|
|
59
|
+
GITHUB_COPILOT,
|
|
60
|
+
V0
|
|
61
|
+
};
|
|
62
|
+
async function determineAgent() {
|
|
63
|
+
if (process.env.AI_AGENT) {
|
|
64
|
+
const name = process.env.AI_AGENT.trim();
|
|
65
|
+
if (name) {
|
|
66
|
+
if (name === GITHUB_COPILOT || name === GITHUB_COPILOT_CLI) return {
|
|
67
|
+
isAgent: true,
|
|
68
|
+
agent: { name: GITHUB_COPILOT }
|
|
69
|
+
};
|
|
70
|
+
if (name === V0) return {
|
|
71
|
+
isAgent: true,
|
|
72
|
+
agent: { name: V0 }
|
|
73
|
+
};
|
|
74
|
+
return {
|
|
75
|
+
isAgent: true,
|
|
76
|
+
agent: { name }
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (process.env.CURSOR_TRACE_ID) return {
|
|
81
|
+
isAgent: true,
|
|
82
|
+
agent: { name: CURSOR }
|
|
83
|
+
};
|
|
84
|
+
if (process.env.CURSOR_AGENT || process.env.CURSOR_EXTENSION_HOST_ROLE === "agent-exec") return {
|
|
85
|
+
isAgent: true,
|
|
86
|
+
agent: { name: CURSOR_CLI }
|
|
87
|
+
};
|
|
88
|
+
if (process.env.GEMINI_CLI) return {
|
|
89
|
+
isAgent: true,
|
|
90
|
+
agent: { name: GEMINI }
|
|
91
|
+
};
|
|
92
|
+
if (process.env.CODEX_SANDBOX || process.env.CODEX_CI || process.env.CODEX_THREAD_ID) return {
|
|
93
|
+
isAgent: true,
|
|
94
|
+
agent: { name: CODEX }
|
|
95
|
+
};
|
|
96
|
+
if (process.env.ANTIGRAVITY_AGENT) return {
|
|
97
|
+
isAgent: true,
|
|
98
|
+
agent: { name: ANTIGRAVITY }
|
|
99
|
+
};
|
|
100
|
+
if (process.env.AUGMENT_AGENT) return {
|
|
101
|
+
isAgent: true,
|
|
102
|
+
agent: { name: AUGMENT_CLI }
|
|
103
|
+
};
|
|
104
|
+
if (process.env.OPENCODE_CLIENT) return {
|
|
105
|
+
isAgent: true,
|
|
106
|
+
agent: { name: OPENCODE }
|
|
107
|
+
};
|
|
108
|
+
if (process.env.CLAUDECODE || process.env.CLAUDE_CODE) {
|
|
109
|
+
if (process.env.CLAUDE_CODE_IS_COWORK) return {
|
|
110
|
+
isAgent: true,
|
|
111
|
+
agent: { name: COWORK }
|
|
112
|
+
};
|
|
113
|
+
return {
|
|
114
|
+
isAgent: true,
|
|
115
|
+
agent: { name: CLAUDE }
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
if (process.env.REPL_ID) return {
|
|
119
|
+
isAgent: true,
|
|
120
|
+
agent: { name: REPLIT }
|
|
121
|
+
};
|
|
122
|
+
if (process.env.COPILOT_MODEL || process.env.COPILOT_ALLOW_ALL || process.env.COPILOT_GITHUB_TOKEN) return {
|
|
123
|
+
isAgent: true,
|
|
124
|
+
agent: { name: GITHUB_COPILOT }
|
|
125
|
+
};
|
|
126
|
+
try {
|
|
127
|
+
await (0, import_promises.access)(DEVIN_LOCAL_PATH, import_node_fs.constants.F_OK);
|
|
128
|
+
return {
|
|
129
|
+
isAgent: true,
|
|
130
|
+
agent: { name: DEVIN }
|
|
131
|
+
};
|
|
132
|
+
} catch (_error) {}
|
|
133
|
+
return {
|
|
134
|
+
isAgent: false,
|
|
135
|
+
agent: void 0
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
0 && (module.exports = {
|
|
139
|
+
KNOWN_AGENTS,
|
|
140
|
+
determineAgent
|
|
141
|
+
});
|
|
142
|
+
}));
|
|
143
|
+
//#endregion
|
|
144
|
+
export default require_dist();
|
|
145
|
+
export {};
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
//#region src/core/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Single source of truth for the types shared across the Nomai CLI.
|
|
4
|
+
*
|
|
5
|
+
* Design rule: ambient state (cwd, homedir) is injected through contexts and
|
|
6
|
+
* never read below the CLI layer, so every module is testable against temp dirs.
|
|
7
|
+
*/
|
|
8
|
+
type InstallScope = "project" | "global";
|
|
9
|
+
/** Ambient paths, resolved once at the CLI layer and passed down. */
|
|
10
|
+
interface ResolveContext {
|
|
11
|
+
/** The project the user runs nomai in (cwd or --dir override). */
|
|
12
|
+
projectDir: string;
|
|
13
|
+
/** os.homedir() in production, a temp dir in tests. */
|
|
14
|
+
homeDir: string;
|
|
15
|
+
}
|
|
16
|
+
/** One file of the payload, path relative to the harness install dir. */
|
|
17
|
+
interface PayloadFile {
|
|
18
|
+
/** e.g. "skills/nomai/SKILL.md" */
|
|
19
|
+
relPath: string;
|
|
20
|
+
contents: Buffer;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Where the installable payload comes from. The default implementation
|
|
24
|
+
* downloads the Nomai GitHub repo; a local checkout is used for dev/tests.
|
|
25
|
+
* A future remote registry plugs in here.
|
|
26
|
+
*/
|
|
27
|
+
interface PayloadSource {
|
|
28
|
+
/** Human-readable origin recorded in the manifest, e.g. "owner/nomai#main". */
|
|
29
|
+
readonly description: string;
|
|
30
|
+
/** Canonical shared payload (contents of payload/shared/). */
|
|
31
|
+
readSharedFiles(): Promise<PayloadFile[]>;
|
|
32
|
+
/** Per-harness overlay (contents of payload/<harnessId>/), [] if none. */
|
|
33
|
+
readHarnessOverlay(harnessId: string): Promise<PayloadFile[]>;
|
|
34
|
+
/** Release temp resources. Safe to call more than once. */
|
|
35
|
+
dispose(): Promise<void>;
|
|
36
|
+
}
|
|
37
|
+
interface TransformContext extends ResolveContext {
|
|
38
|
+
scope: InstallScope;
|
|
39
|
+
nomaiVersion: string;
|
|
40
|
+
}
|
|
41
|
+
interface OperationContext extends ResolveContext {
|
|
42
|
+
scope: InstallScope;
|
|
43
|
+
/** Required for install/update. Uninstall and status work offline from the manifest. */
|
|
44
|
+
payload?: PayloadSource;
|
|
45
|
+
nomaiVersion: string;
|
|
46
|
+
dryRun: boolean;
|
|
47
|
+
/** Overrides the keep-user-modified-files protection on delete paths. */
|
|
48
|
+
force: boolean;
|
|
49
|
+
}
|
|
50
|
+
interface InstallResult {
|
|
51
|
+
installDir: string;
|
|
52
|
+
filesWritten: string[];
|
|
53
|
+
filesRemoved: string[];
|
|
54
|
+
/** True when the install was already up to date and nothing changed. */
|
|
55
|
+
skipped: boolean;
|
|
56
|
+
}
|
|
57
|
+
interface UninstallResult {
|
|
58
|
+
installDir: string;
|
|
59
|
+
/** True when there was no nomai manifest at this target. */
|
|
60
|
+
notInstalled: boolean;
|
|
61
|
+
filesRemoved: string[];
|
|
62
|
+
/** User-modified files kept in place (pass --force to remove them too). */
|
|
63
|
+
filesKept: string[];
|
|
64
|
+
}
|
|
65
|
+
interface HarnessStatus {
|
|
66
|
+
harnessId: string;
|
|
67
|
+
scope: InstallScope;
|
|
68
|
+
installDir: string;
|
|
69
|
+
/** Harness present at this scope (its config dir exists). */
|
|
70
|
+
detected: boolean;
|
|
71
|
+
/** Nomai manifest found at this target. */
|
|
72
|
+
installed: boolean;
|
|
73
|
+
installedVersion?: string;
|
|
74
|
+
installedAt?: string;
|
|
75
|
+
/** Manifest-listed files whose on-disk content no longer matches. */
|
|
76
|
+
modifiedFiles: string[];
|
|
77
|
+
/** Manifest-listed files that no longer exist. */
|
|
78
|
+
missingFiles: string[];
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* One AI coding harness (Claude Code, Codex, Cursor, ...).
|
|
82
|
+
*
|
|
83
|
+
* Create adapters with defineHarness() — it fills every method with defaults
|
|
84
|
+
* that delegate to the generic engine, so a typical adapter is ~5 lines.
|
|
85
|
+
* Every method stays overridable for harnesses that need custom behavior
|
|
86
|
+
* (e.g. merging hooks into a settings.json instead of copying files).
|
|
87
|
+
*/
|
|
88
|
+
interface HarnessAdapter {
|
|
89
|
+
/** Stable machine id used in --harness, manifests, and payload/<id>/. */
|
|
90
|
+
readonly id: string;
|
|
91
|
+
/** Name shown in the wizard, e.g. "Claude Code". */
|
|
92
|
+
readonly displayName: string;
|
|
93
|
+
/** The harness config dir name, e.g. ".claude". */
|
|
94
|
+
readonly configDirName: string;
|
|
95
|
+
/** Is this harness in use in the project? Default: <projectDir>/<configDirName> exists. */
|
|
96
|
+
detectProject(projectDir: string): Promise<boolean>;
|
|
97
|
+
/** Is this harness installed for the user? Default: <homeDir>/<configDirName> exists. */
|
|
98
|
+
detectGlobal(homeDir: string): Promise<boolean>;
|
|
99
|
+
/** Directory nomai writes into for a scope, e.g. <projectDir>/.claude. */
|
|
100
|
+
resolveInstallDir(scope: InstallScope, ctx: ResolveContext): string;
|
|
101
|
+
/**
|
|
102
|
+
* Per-harness compilation hook. Receives the merged payload (shared +
|
|
103
|
+
* harness overlay, overlay wins) and returns the files to write.
|
|
104
|
+
* Default: identity.
|
|
105
|
+
*/
|
|
106
|
+
transformPayload(files: PayloadFile[], ctx: TransformContext): Promise<PayloadFile[]>;
|
|
107
|
+
install(ctx: OperationContext): Promise<InstallResult>;
|
|
108
|
+
uninstall(ctx: OperationContext): Promise<UninstallResult>;
|
|
109
|
+
status(ctx: OperationContext): Promise<HarnessStatus>;
|
|
110
|
+
}
|
|
111
|
+
interface DetectionResult {
|
|
112
|
+
harnessId: string;
|
|
113
|
+
project: boolean;
|
|
114
|
+
global: boolean;
|
|
115
|
+
}
|
|
116
|
+
interface DetectionReport {
|
|
117
|
+
results: DetectionResult[];
|
|
118
|
+
/** Ids detected at either scope — preseeds the wizard multiselect. */
|
|
119
|
+
detectedIds: string[];
|
|
120
|
+
/** Ids detected at project scope — drives the default scope answer. */
|
|
121
|
+
projectDetectedIds: string[];
|
|
122
|
+
}
|
|
123
|
+
/** Resolved answers of the install wizard (or of its flag-based bypass). */
|
|
124
|
+
interface InstallPlan {
|
|
125
|
+
harnessIds: string[];
|
|
126
|
+
scope: InstallScope;
|
|
127
|
+
}
|
|
128
|
+
interface ManifestFileEntry {
|
|
129
|
+
/** Relative to the install dir, posix separators. */
|
|
130
|
+
path: string;
|
|
131
|
+
sha256: string;
|
|
132
|
+
}
|
|
133
|
+
/** Receipt written next to the installed files; drives idempotency, update, and clean uninstall. */
|
|
134
|
+
interface Manifest {
|
|
135
|
+
schemaVersion: 1;
|
|
136
|
+
nomaiVersion: string;
|
|
137
|
+
/** PayloadSource description this install came from. */
|
|
138
|
+
source: string;
|
|
139
|
+
harness: string;
|
|
140
|
+
scope: InstallScope;
|
|
141
|
+
installedAt: string;
|
|
142
|
+
files: ManifestFileEntry[];
|
|
143
|
+
}
|
|
144
|
+
//#endregion
|
|
145
|
+
//#region src/harnesses/define.d.ts
|
|
146
|
+
interface HarnessConfig {
|
|
147
|
+
/** Stable machine id, e.g. "claude-code". */
|
|
148
|
+
id: string;
|
|
149
|
+
/** Name shown in the wizard, e.g. "Claude Code". */
|
|
150
|
+
displayName: string;
|
|
151
|
+
/** The harness config dir name, e.g. ".claude". */
|
|
152
|
+
configDirName: string;
|
|
153
|
+
/** Optional overrides — every default delegates to the generic engine. */
|
|
154
|
+
detectProject?: HarnessAdapter["detectProject"];
|
|
155
|
+
detectGlobal?: HarnessAdapter["detectGlobal"];
|
|
156
|
+
resolveInstallDir?: HarnessAdapter["resolveInstallDir"];
|
|
157
|
+
transformPayload?: HarnessAdapter["transformPayload"];
|
|
158
|
+
install?: HarnessAdapter["install"];
|
|
159
|
+
uninstall?: HarnessAdapter["uninstall"];
|
|
160
|
+
status?: HarnessAdapter["status"];
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Build a HarnessAdapter from declarative config. A typical adapter is:
|
|
164
|
+
*
|
|
165
|
+
* export const claudeCode = defineHarness({
|
|
166
|
+
* id: "claude-code",
|
|
167
|
+
* displayName: "Claude Code",
|
|
168
|
+
* configDirName: ".claude",
|
|
169
|
+
* });
|
|
170
|
+
*
|
|
171
|
+
* Harnesses that need per-harness compilation override transformPayload;
|
|
172
|
+
* harnesses with entirely custom mechanics (e.g. settings.json merges for
|
|
173
|
+
* hooks) can override install/uninstall/status wholesale.
|
|
174
|
+
*/
|
|
175
|
+
declare function defineHarness(config: HarnessConfig): HarnessAdapter;
|
|
176
|
+
//#endregion
|
|
177
|
+
//#region src/core/registry.d.ts
|
|
178
|
+
declare function listHarnesses(): HarnessAdapter[];
|
|
179
|
+
declare function getHarness(id: string): HarnessAdapter;
|
|
180
|
+
//#endregion
|
|
181
|
+
//#region src/core/detect.d.ts
|
|
182
|
+
/**
|
|
183
|
+
* Ask every registered harness whether it is present at project and global
|
|
184
|
+
* scope. The report preseeds the wizard's harness multiselect and drives
|
|
185
|
+
* the defaults used by --yes.
|
|
186
|
+
*/
|
|
187
|
+
declare function detectHarnesses(ctx: ResolveContext): Promise<DetectionReport>;
|
|
188
|
+
//#endregion
|
|
189
|
+
//#region src/core/installer.d.ts
|
|
190
|
+
/**
|
|
191
|
+
* Generic install/uninstall/status engine shared by all harness adapters.
|
|
192
|
+
* defineHarness() wires adapter methods to these functions by default;
|
|
193
|
+
* adapters with special needs override the methods instead.
|
|
194
|
+
*
|
|
195
|
+
* This module is the only place in the codebase that writes to disk.
|
|
196
|
+
*/
|
|
197
|
+
declare function installHarness(adapter: HarnessAdapter, ctx: OperationContext): Promise<InstallResult>;
|
|
198
|
+
declare function uninstallHarness(adapter: HarnessAdapter, ctx: OperationContext): Promise<UninstallResult>;
|
|
199
|
+
declare function statusHarness(adapter: HarnessAdapter, ctx: OperationContext): Promise<HarnessStatus>;
|
|
200
|
+
//#endregion
|
|
201
|
+
//#region src/core/payload.d.ts
|
|
202
|
+
/**
|
|
203
|
+
* Default payload source: the Nomai GitHub repo, fetched as a codeload
|
|
204
|
+
* tarball of `main` at install time (same model as BuilderIO's
|
|
205
|
+
* `npx @agent-native/skills`). The npm package itself ships no payload.
|
|
206
|
+
*/
|
|
207
|
+
declare const DEFAULT_SOURCE = "A-MCode/nomai-installer";
|
|
208
|
+
interface GitHubSourceRef {
|
|
209
|
+
owner: string;
|
|
210
|
+
repo: string;
|
|
211
|
+
ref?: string;
|
|
212
|
+
}
|
|
213
|
+
/** Accepts "owner/repo", "owner/repo#ref", or a github.com URL (optionally /tree/<ref>). */
|
|
214
|
+
declare function parseGitHubSource(input: string): GitHubSourceRef | null;
|
|
215
|
+
/**
|
|
216
|
+
* Turn a --source value (or the default) into a live PayloadSource:
|
|
217
|
+
* an existing local path wins, otherwise a GitHub download.
|
|
218
|
+
*/
|
|
219
|
+
declare function resolvePayloadSource(input?: string): Promise<PayloadSource>;
|
|
220
|
+
//#endregion
|
|
221
|
+
//#region src/core/manifest.d.ts
|
|
222
|
+
declare const MANIFEST_FILENAME = "nomai-manifest.json";
|
|
223
|
+
/** @returns null when no manifest exists; throws on a corrupt/foreign one. */
|
|
224
|
+
declare function readManifest(installDir: string): Promise<Manifest | null>;
|
|
225
|
+
//#endregion
|
|
226
|
+
export { DEFAULT_SOURCE, type DetectionReport, type DetectionResult, type HarnessAdapter, type HarnessConfig, type HarnessStatus, type InstallPlan, type InstallResult, type InstallScope, MANIFEST_FILENAME, type Manifest, type ManifestFileEntry, type OperationContext, type PayloadFile, type PayloadSource, type ResolveContext, type TransformContext, type UninstallResult, defineHarness, detectHarnesses, getHarness, installHarness, listHarnesses, parseGitHubSource, readManifest, resolvePayloadSource, statusHarness, uninstallHarness };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as getHarness, c as installHarness, d as MANIFEST_FILENAME, f as readManifest, i as detectHarnesses, l as statusHarness, n as parseGitHubSource, o as listHarnesses, r as resolvePayloadSource, s as defineHarness, t as DEFAULT_SOURCE, u as uninstallHarness } from "./payload-DdBYzrl3.mjs";
|
|
2
|
+
export { DEFAULT_SOURCE, MANIFEST_FILENAME, defineHarness, detectHarnesses, getHarness, installHarness, listHarnesses, parseGitHubSource, readManifest, resolvePayloadSource, statusHarness, uninstallHarness };
|