@nexrall/code-core 1.4.46 → 1.4.47
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/agent/agentTypes.d.ts.map +1 -1
- package/dist/agent/agentTypes.js +6 -2
- package/dist/agent/loop.d.ts.map +1 -1
- package/dist/agent/loop.js +14 -1
- package/dist/agent/memory.d.ts +38 -10
- package/dist/agent/memory.d.ts.map +1 -1
- package/dist/agent/memory.js +223 -67
- package/dist/agent/skills.d.ts.map +1 -1
- package/dist/agent/skills.js +3 -14
- package/dist/agent/trust.d.ts +7 -0
- package/dist/agent/trust.d.ts.map +1 -0
- package/dist/agent/trust.js +151 -0
- package/dist/api/client.d.ts +30 -0
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +52 -0
- package/dist/checkpoint/manager.d.ts.map +1 -1
- package/dist/checkpoint/manager.js +6 -0
- package/dist/commands/loader.d.ts.map +1 -1
- package/dist/commands/loader.js +2 -13
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/permissions/modePolicy.d.ts.map +1 -1
- package/dist/permissions/modePolicy.js +1 -0
- package/dist/permissions/rules.js +1 -1
- package/dist/plugins/index.d.ts +31 -4
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/index.js +72 -5
- package/dist/plugins/installer.d.ts +47 -0
- package/dist/plugins/installer.d.ts.map +1 -1
- package/dist/plugins/installer.js +173 -0
- package/dist/tools/executor.d.ts.map +1 -1
- package/dist/tools/executor.js +196 -5
- package/dist/util/frontmatter.d.ts +22 -0
- package/dist/util/frontmatter.d.ts.map +1 -0
- package/dist/util/frontmatter.js +33 -0
- package/package.json +5 -2
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which trust-sensitive files actually exist in `dir`, so a confirmation
|
|
3
|
+
* prompt can tell the user what THIS folder will do rather than describing
|
|
4
|
+
* risks in the abstract. Ordered most- to least-dangerous.
|
|
5
|
+
*/
|
|
6
|
+
export declare function detectTrustSignals(dir: string): string[];
|
|
7
|
+
//# sourceMappingURL=trust.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trust.d.ts","sourceRoot":"","sources":["../../src/agent/trust.ts"],"names":[],"mappings":"AAiDA;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CA0DxD"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.detectTrustSignals = detectTrustSignals;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
// ─── Workspace Trust Signals (shared) ─────────────────────────────────────
|
|
40
|
+
//
|
|
41
|
+
// Opening a folder for an agent to work in is not a passive act. Before the
|
|
42
|
+
// user types anything, a session can already read and act on files found in
|
|
43
|
+
// that folder:
|
|
44
|
+
//
|
|
45
|
+
// • `.nexrall/mcp.json` declares MCP servers, and connecting to a stdio
|
|
46
|
+
// server runs `spawn(server.command, server.args)` — arbitrary command
|
|
47
|
+
// execution, straight from a file in the repo (see mcp/manager.ts /
|
|
48
|
+
// mcp/client.ts).
|
|
49
|
+
// • `.nexrall/plugins/` may contribute their OWN `mcp.json`/`hooks.json`
|
|
50
|
+
// (see plugins/index.ts's pluginMcpServers/pluginHooks) — same risk
|
|
51
|
+
// class as a bare mcp.json, just one hop further away.
|
|
52
|
+
// • `nexrall.md` is injected into the system prompt as trusted project
|
|
53
|
+
// instructions, so its contents steer the agent for the whole session.
|
|
54
|
+
// • `.nexrall/{skills,commands}` define playbooks the agent will follow,
|
|
55
|
+
// and `.nexrall/permissions.json` can pre-approve tool calls that would
|
|
56
|
+
// otherwise prompt.
|
|
57
|
+
//
|
|
58
|
+
// So `git clone` of a hostile repo followed by pointing an agent at it is
|
|
59
|
+
// enough to execute attacker-chosen commands before a human reviews anything.
|
|
60
|
+
//
|
|
61
|
+
// This module is the shared, pure "what would this folder do" detector. The
|
|
62
|
+
// CLI has its own longstanding copy (packages/cli/src/trust.ts) — kept
|
|
63
|
+
// independent there rather than migrated onto this one, so a change here
|
|
64
|
+
// can never silently alter the CLI's own trust-prompt wording/behaviour or
|
|
65
|
+
// its own dedicated test suite. Any NEW client (e.g. the desktop app) should
|
|
66
|
+
// use this shared copy instead of hand-rolling a third one.
|
|
67
|
+
//
|
|
68
|
+
// Deliberately stateless: nothing here reads or writes any trust STORE.
|
|
69
|
+
// Whether/how a client remembers "already confirmed this session" is the
|
|
70
|
+
// caller's job (see e.g. desktop's main/trustGate.ts) — this function only
|
|
71
|
+
// ever reports what is true of the folder RIGHT NOW.
|
|
72
|
+
/** Does the project settings file bind plugin aliases to remote repos? */
|
|
73
|
+
function declaresPluginSources(dir) {
|
|
74
|
+
try {
|
|
75
|
+
const raw = fs.readFileSync(path.join(dir, '.nexrall', 'settings.json'), 'utf-8');
|
|
76
|
+
const obj = JSON.parse(raw);
|
|
77
|
+
const s = obj.pluginSources;
|
|
78
|
+
return Boolean(s && typeof s === 'object' && !Array.isArray(s) && Object.keys(s).length > 0);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Which trust-sensitive files actually exist in `dir`, so a confirmation
|
|
86
|
+
* prompt can tell the user what THIS folder will do rather than describing
|
|
87
|
+
* risks in the abstract. Ordered most- to least-dangerous.
|
|
88
|
+
*/
|
|
89
|
+
function detectTrustSignals(dir) {
|
|
90
|
+
const signals = [];
|
|
91
|
+
const exists = (...p) => {
|
|
92
|
+
try {
|
|
93
|
+
return fs.existsSync(path.join(dir, ...p));
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
// Code-executing first — these can run local commands before the user
|
|
100
|
+
// types anything, so they are what the decision really hinges on.
|
|
101
|
+
if (exists('.nexrall', 'mcp.json')) {
|
|
102
|
+
signals.push('.nexrall/mcp.json — can start MCP servers (runs local commands)');
|
|
103
|
+
}
|
|
104
|
+
if (exists('.nexrall', 'plugins')) {
|
|
105
|
+
// Plugins are scanned from the workspace and may contribute their own MCP
|
|
106
|
+
// servers/hooks (see plugins/index.ts → pluginMcpServers/pluginHooks), so
|
|
107
|
+
// this is in the same risk class as mcp.json rather than a cosmetic add-on.
|
|
108
|
+
signals.push('.nexrall/plugins/ — project plugins (may add MCP servers or hooks)');
|
|
109
|
+
}
|
|
110
|
+
// Then things that widen what the agent may do without asking.
|
|
111
|
+
if (exists('.nexrall', 'permissions.json')) {
|
|
112
|
+
signals.push('.nexrall/permissions.json — pre-approved tool permissions');
|
|
113
|
+
}
|
|
114
|
+
if (exists('.nexrall', 'settings.json')) {
|
|
115
|
+
// Called out separately when the file declares plugin sources: those bind
|
|
116
|
+
// a short alias to a remote repo, so installing that alias would fetch
|
|
117
|
+
// whatever the REPOSITORY chose. Installing still needs a human and its
|
|
118
|
+
// own confirmation — nothing is fetched from a declaration alone — but the
|
|
119
|
+
// user should know the repo is trying to name what they install. A
|
|
120
|
+
// settings.json can also carry a project's own `hooks` config, which runs
|
|
121
|
+
// shell commands automatically around tool calls — worth flagging here too.
|
|
122
|
+
let hasHooks = false;
|
|
123
|
+
try {
|
|
124
|
+
const raw = fs.readFileSync(path.join(dir, '.nexrall', 'settings.json'), 'utf-8');
|
|
125
|
+
const obj = JSON.parse(raw);
|
|
126
|
+
hasHooks = Boolean(obj.hooks && typeof obj.hooks === 'object' && Object.keys(obj.hooks).length > 0);
|
|
127
|
+
}
|
|
128
|
+
catch { /* absent or malformed — treated as no hooks declared */ }
|
|
129
|
+
const bits = ['.nexrall/settings.json — project settings and permission rules'];
|
|
130
|
+
if (declaresPluginSources(dir))
|
|
131
|
+
bits.push('declares plugin sources (aliases for remote plugin repos)');
|
|
132
|
+
if (hasHooks)
|
|
133
|
+
bits.push('runs hooks (shell commands) automatically around tool calls');
|
|
134
|
+
signals.push(bits.join(', '));
|
|
135
|
+
}
|
|
136
|
+
// Then things that steer the agent's behaviour.
|
|
137
|
+
if (exists('nexrall.md')) {
|
|
138
|
+
signals.push('nexrall.md — project instructions added to the agent\u2019s prompt');
|
|
139
|
+
}
|
|
140
|
+
if (exists('.nexrall', 'skills')) {
|
|
141
|
+
signals.push('.nexrall/skills/ — custom agent playbooks');
|
|
142
|
+
}
|
|
143
|
+
if (exists('.nexrall', 'commands')) {
|
|
144
|
+
signals.push('.nexrall/commands/ — custom slash commands');
|
|
145
|
+
}
|
|
146
|
+
if (exists('.nexrall', 'agents')) {
|
|
147
|
+
signals.push('.nexrall/agents/ — custom sub-agent definitions');
|
|
148
|
+
}
|
|
149
|
+
return signals;
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=trust.js.map
|
package/dist/api/client.d.ts
CHANGED
|
@@ -131,6 +131,36 @@ export interface DescribeAttachmentResult {
|
|
|
131
131
|
}
|
|
132
132
|
export declare function describeAttachment(kind: 'image' | 'pdf', data: string, mediaType?: string, name?: string): Promise<DescribeAttachmentResult>;
|
|
133
133
|
export declare function getBalance(): Promise<number>;
|
|
134
|
+
export interface UsageDailyDay {
|
|
135
|
+
date: string;
|
|
136
|
+
total: number;
|
|
137
|
+
byType: Record<string, number>;
|
|
138
|
+
}
|
|
139
|
+
export interface UsageDailyResult {
|
|
140
|
+
days: UsageDailyDay[];
|
|
141
|
+
totalSpent: number;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Day-by-day spend breakdown, same endpoint the web app's Settings > Usage
|
|
145
|
+
* chart reads (backend/routes/user.js's /usage-daily). Used by Nexrall Work's
|
|
146
|
+
* own Settings > Usage panel so both surfaces show the identical numbers.
|
|
147
|
+
*/
|
|
148
|
+
export declare function getUsageDaily(days?: number): Promise<UsageDailyResult>;
|
|
134
149
|
export declare function exchangeVscodeCode(code: string): Promise<AuthConfig>;
|
|
135
150
|
export declare function login(email: string, password: string): Promise<AuthConfig>;
|
|
151
|
+
export interface UserProfile {
|
|
152
|
+
id: string | number;
|
|
153
|
+
email: string;
|
|
154
|
+
name?: string;
|
|
155
|
+
phone?: string;
|
|
156
|
+
avatar_url?: string;
|
|
157
|
+
username?: string;
|
|
158
|
+
bio?: string;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Same GET /api/user/profile the web app's Settings > Profile section reads.
|
|
162
|
+
* Used by Nexrall Work's own Settings > Profile panel so both surfaces show
|
|
163
|
+
* identical account data.
|
|
164
|
+
*/
|
|
165
|
+
export declare function getUserProfile(): Promise<UserProfile>;
|
|
136
166
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/api/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAA8B,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAiErH,eAAO,MAAM,QAAQ,QAAmB,CAAC;AAIzC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EAC5D,OAAO,EAAE,CAAC,EAAE,EACZ,UAAU,EAAE,KAAK,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,IAAI,GAAG,SAAS,GACtD,CAAC,EAAE,CAeL;AAiGD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IACnC,oFAAoF;IACpF,UAAU,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IACjG,6EAA6E;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6IAA6I;IAC7I,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;OAOG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,yFAAyF;IACzF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;;;;;OASG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;;;;;;;;;;OAeG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AA8ID,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,CAAC,CAAC,EAAE,QAAQ,KAAK,IAAI,GAC7B,OAAO,CAAC,OAAO,CAAC,CAkmClB;AAID;;;;;;;;;;;GAWG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAU9D;AAID;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAYxD;AAeD,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,OAAO,GAAG,KAAK,EACrB,IAAI,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,MAAM,EAClB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,wBAAwB,CAAC,CAmCnC;AAID,wBAAsB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CA0BlD;AAID,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CA+B1E;AAID,wBAAsB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CA0BhF"}
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAA8B,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAiErH,eAAO,MAAM,QAAQ,QAAmB,CAAC;AAIzC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EAC5D,OAAO,EAAE,CAAC,EAAE,EACZ,UAAU,EAAE,KAAK,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,IAAI,GAAG,SAAS,GACtD,CAAC,EAAE,CAeL;AAiGD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IACnC,oFAAoF;IACpF,UAAU,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IACjG,6EAA6E;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6IAA6I;IAC7I,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;OAOG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,yFAAyF;IACzF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;;;;;OASG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;;;;;;;;;;OAeG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AA8ID,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,CAAC,CAAC,EAAE,QAAQ,KAAK,IAAI,GAC7B,OAAO,CAAC,OAAO,CAAC,CAkmClB;AAID;;;;;;;;;;;GAWG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAU9D;AAID;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAYxD;AAeD,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,OAAO,GAAG,KAAK,EACrB,IAAI,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,MAAM,EAClB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,wBAAwB,CAAC,CAmCnC;AAID,wBAAsB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CA0BlD;AAID,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,aAAa,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,IAAI,SAAK,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAyBxE;AAID,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CA+B1E;AAID,wBAAsB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CA0BhF;AAID,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC,CAqB3D"}
|
package/dist/api/client.js
CHANGED
|
@@ -10,8 +10,10 @@ exports.cancelTurn = cancelTurn;
|
|
|
10
10
|
exports.revokeRefreshToken = revokeRefreshToken;
|
|
11
11
|
exports.describeAttachment = describeAttachment;
|
|
12
12
|
exports.getBalance = getBalance;
|
|
13
|
+
exports.getUsageDaily = getUsageDaily;
|
|
13
14
|
exports.exchangeVscodeCode = exchangeVscodeCode;
|
|
14
15
|
exports.login = login;
|
|
16
|
+
exports.getUserProfile = getUserProfile;
|
|
15
17
|
const eventsource_parser_1 = require("eventsource-parser");
|
|
16
18
|
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
17
19
|
const crypto_1 = require("crypto");
|
|
@@ -1544,6 +1546,33 @@ async function getBalance() {
|
|
|
1544
1546
|
const data = (await response.json());
|
|
1545
1547
|
return typeof data.balance === 'number' ? data.balance : 0;
|
|
1546
1548
|
}
|
|
1549
|
+
/**
|
|
1550
|
+
* Day-by-day spend breakdown, same endpoint the web app's Settings > Usage
|
|
1551
|
+
* chart reads (backend/routes/user.js's /usage-daily). Used by Nexrall Work's
|
|
1552
|
+
* own Settings > Usage panel so both surfaces show the identical numbers.
|
|
1553
|
+
*/
|
|
1554
|
+
async function getUsageDaily(days = 30) {
|
|
1555
|
+
const fetchOnce = () => (0, node_fetch_1.default)(`${exports.API_BASE}/api/user/usage-daily?days=${days}`, { method: 'GET', headers: authHeaders() });
|
|
1556
|
+
let response = await fetchOnce();
|
|
1557
|
+
if (response.status === 401 || response.status === 403) {
|
|
1558
|
+
const body = await response.text().catch(() => '');
|
|
1559
|
+
if (isExpiredTokenResponse(response.status, body) && await refreshAccessToken()) {
|
|
1560
|
+
response = await fetchOnce();
|
|
1561
|
+
}
|
|
1562
|
+
else {
|
|
1563
|
+
throw new Error(`API error ${response.status}: ${body}`);
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
if (!response.ok) {
|
|
1567
|
+
const errText = await response.text();
|
|
1568
|
+
throw new Error(`API error ${response.status}: ${errText}`);
|
|
1569
|
+
}
|
|
1570
|
+
const data = (await response.json());
|
|
1571
|
+
return {
|
|
1572
|
+
days: Array.isArray(data.days) ? data.days : [],
|
|
1573
|
+
totalSpent: typeof data.totalSpent === 'number' ? data.totalSpent : 0,
|
|
1574
|
+
};
|
|
1575
|
+
}
|
|
1547
1576
|
// ─── VSCode OAuth ─────────────────────────────────────────────────────────────
|
|
1548
1577
|
async function exchangeVscodeCode(code) {
|
|
1549
1578
|
const response = await (0, node_fetch_1.default)(`${exports.API_BASE}/api/auth/vscode-exchange`, {
|
|
@@ -1596,4 +1625,27 @@ async function login(email, password) {
|
|
|
1596
1625
|
email: data.email ?? email,
|
|
1597
1626
|
};
|
|
1598
1627
|
}
|
|
1628
|
+
/**
|
|
1629
|
+
* Same GET /api/user/profile the web app's Settings > Profile section reads.
|
|
1630
|
+
* Used by Nexrall Work's own Settings > Profile panel so both surfaces show
|
|
1631
|
+
* identical account data.
|
|
1632
|
+
*/
|
|
1633
|
+
async function getUserProfile() {
|
|
1634
|
+
const fetchOnce = () => (0, node_fetch_1.default)(`${exports.API_BASE}/api/user/profile`, { method: 'GET', headers: authHeaders() });
|
|
1635
|
+
let response = await fetchOnce();
|
|
1636
|
+
if (response.status === 401 || response.status === 403) {
|
|
1637
|
+
const body = await response.text().catch(() => '');
|
|
1638
|
+
if (isExpiredTokenResponse(response.status, body) && await refreshAccessToken()) {
|
|
1639
|
+
response = await fetchOnce();
|
|
1640
|
+
}
|
|
1641
|
+
else {
|
|
1642
|
+
throw new Error(`API error ${response.status}: ${body}`);
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
if (!response.ok) {
|
|
1646
|
+
const errText = await response.text();
|
|
1647
|
+
throw new Error(`API error ${response.status}: ${errText}`);
|
|
1648
|
+
}
|
|
1649
|
+
return (await response.json());
|
|
1650
|
+
}
|
|
1599
1651
|
//# sourceMappingURL=client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/checkpoint/manager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/checkpoint/manager.ts"],"names":[],"mappings":"AA+CA,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AAQD,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAMlE;AA4BD,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,OAAO,EAAE,OAAO,CAAC;IACjB,8FAA8F;IAC9F,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,sFAAsF;IACtF,SAAS,EAAE,MAAM,CAAC;IAClB,sGAAsG;IACtG,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAMD,MAAM,WAAW,aAAa;IAC5B,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,kFAAkF;IAClF,YAAY,EAAE,MAAM,CAAC;IACrB,6FAA6F;IAC7F,SAAS,EAAE,MAAM,CAAC;IAClB,6FAA6F;IAC7F,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AA6BD,qBAAa,iBAAiB;IAWhB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAVpC,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAElC;;;;OAIG;gBAC0B,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM;IAa5D,OAAO,CAAC,OAAO;IAIf;;;OAGG;IACH,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAcpD;;;;;OAKG;IACH,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IA8BxE;;;;;;;OAOG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQxC,OAAO,CAAC,iBAAiB;IAiBzB,0FAA0F;IAC1F,UAAU,IAAI,IAAI;IAWlB,IAAI,IAAI,iBAAiB,EAAE;IAY3B,cAAc,IAAI,OAAO;IAIzB;;;;;OAKG;IACH,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IA0BnD,OAAO,CAAC,aAAa;IAsBrB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,WAAW;IAuBnB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,KAAK;IAOb,OAAO,CAAC,YAAY;CAkCrB"}
|
|
@@ -68,6 +68,9 @@ const MAX_SNAPSHOT_BYTES = 2 * 1024 * 1024; // 2 MB/file — larger files are no
|
|
|
68
68
|
const MAX_PERSISTED_TURNS = 50; // pruned oldest-first on commit
|
|
69
69
|
const MUTATING_TOOLS = new Set([
|
|
70
70
|
'write_file',
|
|
71
|
+
'write_docx',
|
|
72
|
+
'write_xlsx',
|
|
73
|
+
'write_pptx',
|
|
71
74
|
'edit_file',
|
|
72
75
|
'multi_edit',
|
|
73
76
|
'delete_file',
|
|
@@ -99,6 +102,9 @@ function str(v) {
|
|
|
99
102
|
function affectedPaths(name, input) {
|
|
100
103
|
switch (name) {
|
|
101
104
|
case 'write_file':
|
|
105
|
+
case 'write_docx':
|
|
106
|
+
case 'write_xlsx':
|
|
107
|
+
case 'write_pptx':
|
|
102
108
|
case 'edit_file':
|
|
103
109
|
case 'multi_edit':
|
|
104
110
|
case 'delete_file':
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/commands/loader.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/commands/loader.ts"],"names":[],"mappings":"AA8BA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;CACrD;AAsED,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE,CASjE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAG7F;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAuCnF;AAED,4FAA4F;AAC5F,wBAAgB,aAAa,CAAC,GAAG,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE3F"}
|
package/dist/commands/loader.js
CHANGED
|
@@ -42,6 +42,7 @@ const path = __importStar(require("path"));
|
|
|
42
42
|
const os = __importStar(require("os"));
|
|
43
43
|
const child_process_1 = require("child_process");
|
|
44
44
|
const index_1 = require("../plugins/index");
|
|
45
|
+
const frontmatter_1 = require("../util/frontmatter");
|
|
45
46
|
// ── Built-in commands ─────────────────────────────────────────────────────────
|
|
46
47
|
// Shipped with the product; lowest precedence (project > global > builtin), so
|
|
47
48
|
// a user can override any of them by creating a file with the same name.
|
|
@@ -79,18 +80,6 @@ const BUILTIN_COMMANDS = [
|
|
|
79
80
|
].join('\n'),
|
|
80
81
|
},
|
|
81
82
|
];
|
|
82
|
-
function parseFrontmatter(raw) {
|
|
83
|
-
const m = /^\s*---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/.exec(raw);
|
|
84
|
-
if (!m)
|
|
85
|
-
return { meta: {}, body: raw.trim() };
|
|
86
|
-
const meta = {};
|
|
87
|
-
for (const line of m[1].split(/\r?\n/)) {
|
|
88
|
-
const kv = /^([A-Za-z0-9_-]+)\s*:\s*(.*)$/.exec(line.trim());
|
|
89
|
-
if (kv)
|
|
90
|
-
meta[kv[1].toLowerCase()] = kv[2].trim().replace(/^["']|["']$/g, '');
|
|
91
|
-
}
|
|
92
|
-
return { meta, body: (m[2] ?? '').trim() };
|
|
93
|
-
}
|
|
94
83
|
function loadDir(dir, source, into) {
|
|
95
84
|
let files;
|
|
96
85
|
try {
|
|
@@ -102,7 +91,7 @@ function loadDir(dir, source, into) {
|
|
|
102
91
|
for (const file of files) {
|
|
103
92
|
try {
|
|
104
93
|
const raw = fs.readFileSync(path.join(dir, file), 'utf-8');
|
|
105
|
-
const { meta, body } = parseFrontmatter(raw);
|
|
94
|
+
const { meta, body } = (0, frontmatter_1.parseFrontmatter)(raw);
|
|
106
95
|
const name = (meta.name || path.basename(file, '.md')).trim().toLowerCase();
|
|
107
96
|
if (!name)
|
|
108
97
|
continue;
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -42,4 +42,5 @@ __exportStar(require("./permissions/destructive"), exports);
|
|
|
42
42
|
__exportStar(require("./plugins/index"), exports);
|
|
43
43
|
__exportStar(require("./plugins/installer"), exports);
|
|
44
44
|
__exportStar(require("./plugins/sources"), exports);
|
|
45
|
+
__exportStar(require("./agent/trust"), exports);
|
|
45
46
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modePolicy.d.ts","sourceRoot":"","sources":["../../src/permissions/modePolicy.ts"],"names":[],"mappings":"AAsBA,yDAAyD;AACzD,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAE9D,kDAAkD;AAClD,MAAM,MAAM,cAAc,GACtB,OAAO,GACP,KAAK,GACL,MAAM,GACN,SAAS,CAAC;AAEd,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,IAAI,EAAE,cAAc,CAAC;IACrB,oFAAoF;IACpF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,aAU1B,CAAC;AAEH,0CAA0C;AAC1C,eAAO,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"modePolicy.d.ts","sourceRoot":"","sources":["../../src/permissions/modePolicy.ts"],"names":[],"mappings":"AAsBA,yDAAyD;AACzD,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAE9D,kDAAkD;AAClD,MAAM,MAAM,cAAc,GACtB,OAAO,GACP,KAAK,GACL,MAAM,GACN,SAAS,CAAC;AAEd,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,IAAI,EAAE,cAAc,CAAC;IACrB,oFAAoF;IACpF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,aAU1B,CAAC;AAEH,0CAA0C;AAC1C,eAAO,MAAM,gBAAgB,aAG3B,CAAC;AAEH,oEAAoE;AACpE,eAAO,MAAM,iBAAiB,aAE5B,CAAC;AAEH,sCAAsC;AACtC,eAAO,MAAM,UAAU,aAAsD,CAAC;AAE9E;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;;;;;GAOG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,WAAW,GAAG,cAAc,CAwDvD;AAED,4DAA4D;AAC5D,wBAAgB,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CAOzD;AAED,gFAAgF;AAChF,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,CAGtD"}
|
|
@@ -28,6 +28,7 @@ exports.READ_ONLY_TOOLS = new Set([
|
|
|
28
28
|
/** Tools that write to the filesystem. */
|
|
29
29
|
exports.FILE_WRITE_TOOLS = new Set([
|
|
30
30
|
'write_file', 'create_file', 'edit_file', 'multi_edit', 'notebook_edit',
|
|
31
|
+
'write_docx', 'write_xlsx', 'write_pptx',
|
|
31
32
|
]);
|
|
32
33
|
/** Tools that move/delete files — riskier than an in-place edit. */
|
|
33
34
|
exports.FILE_MUTATE_TOOLS = new Set([
|
|
@@ -200,7 +200,7 @@ function ruleMatches(rule, tool, input, workDir, opts) {
|
|
|
200
200
|
const aliases = {
|
|
201
201
|
Read: ['read_file', 'list_directory', 'search_files', 'glob', 'notebook_read'],
|
|
202
202
|
Edit: ['edit_file', 'multi_edit', 'write_file', 'notebook_edit'],
|
|
203
|
-
Write: ['write_file'],
|
|
203
|
+
Write: ['write_file', 'write_docx', 'write_xlsx', 'write_pptx'],
|
|
204
204
|
Bash: ['bash'],
|
|
205
205
|
WebFetch: ['fetch_url'],
|
|
206
206
|
Image: ['generate_image', 'stock_photo'],
|
package/dist/plugins/index.d.ts
CHANGED
|
@@ -6,7 +6,13 @@ export interface PluginInfo {
|
|
|
6
6
|
/** Absolute path to the plugin directory. */
|
|
7
7
|
dir: string;
|
|
8
8
|
scope: 'project' | 'global';
|
|
9
|
+
/** True when the user has toggled this plugin off (see isPluginDisabled). */
|
|
10
|
+
disabled: boolean;
|
|
9
11
|
}
|
|
12
|
+
/** True if this installed plugin directory has been toggled off. */
|
|
13
|
+
export declare function isPluginDisabled(dir: string): boolean;
|
|
14
|
+
/** Toggle a plugin on/off. Idempotent — enabling an already-enabled plugin is a no-op. */
|
|
15
|
+
export declare function setPluginDisabled(dir: string, disabled: boolean): void;
|
|
10
16
|
/**
|
|
11
17
|
* Where each single-file component may live, in priority order.
|
|
12
18
|
*
|
|
@@ -27,12 +33,33 @@ export declare const FILE_CANDIDATES: {
|
|
|
27
33
|
};
|
|
28
34
|
/** First existing candidate path for a component, or null. */
|
|
29
35
|
export declare function resolvePluginFile(dir: string, kind: keyof typeof FILE_CANDIDATES): string | null;
|
|
30
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* Discover installed plugins (project scope shadows global on name clash).
|
|
38
|
+
*
|
|
39
|
+
* Includes disabled plugins — callers that manage the install (the desktop
|
|
40
|
+
* UI's list, `nex plugin list`) need to show and re-enable them. Everything
|
|
41
|
+
* that actually LOADS a plugin's contents at runtime (pluginAssetDirs,
|
|
42
|
+
* pluginHooks, pluginMcpServers below) filters `disabled` out itself, which is
|
|
43
|
+
* what makes toggling a plugin off actually take effect instead of only
|
|
44
|
+
* hiding it from a list.
|
|
45
|
+
*/
|
|
31
46
|
export declare function loadPlugins(workDir: string): PluginInfo[];
|
|
32
|
-
/**
|
|
47
|
+
/**
|
|
48
|
+
* Find one installed plugin by name AND scope. Looking this up through
|
|
49
|
+
* loadPlugins() (rather than re-deriving `<scopeRoot>/<name>` the way
|
|
50
|
+
* removePlugin/updatePlugin in installer.ts do) is deliberate: a plugin's
|
|
51
|
+
* effective name can come from plugin.json's "name" field rather than its
|
|
52
|
+
* directory name (see scanRoot/readMeta above), so a caller that needs the
|
|
53
|
+
* plugin's actual `dir` for a specific scope — not just "some plugin with
|
|
54
|
+
* this name, whichever scope loadPlugins()'s single merged map preferred" —
|
|
55
|
+
* has to re-scan that one scope directly to avoid resolving to the wrong
|
|
56
|
+
* directory or silently matching the other scope's plugin of the same name.
|
|
57
|
+
*/
|
|
58
|
+
export declare function findPlugin(workDir: string, name: string, scope: 'project' | 'global'): PluginInfo | undefined;
|
|
59
|
+
/** Subdirectories of every ENABLED installed plugin that hold `kind` assets (existing only). */
|
|
33
60
|
export declare function pluginAssetDirs(workDir: string, kind: 'commands' | 'agents' | 'skills'): string[];
|
|
34
|
-
/** Merge hooks.json from every plugin into a single hooks config (arrays concatenated). */
|
|
61
|
+
/** Merge hooks.json from every ENABLED plugin into a single hooks config (arrays concatenated). */
|
|
35
62
|
export declare function pluginHooks(workDir: string): Record<string, unknown[]>;
|
|
36
|
-
/** MCP server maps declared by plugins: { serverName → config } (first plugin wins on clash). */
|
|
63
|
+
/** MCP server maps declared by ENABLED plugins: { serverName → config } (first plugin wins on clash). */
|
|
37
64
|
export declare function pluginMcpServers(workDir: string): Record<string, unknown>;
|
|
38
65
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugins/index.ts"],"names":[],"mappings":"AAsCA,MAAM,WAAW,UAAU;IACzB,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6CAA6C;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,SAAS,GAAG,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugins/index.ts"],"names":[],"mappings":"AAsCA,MAAM,WAAW,UAAU;IACzB,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6CAA6C;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC5B,6EAA6E;IAC7E,QAAQ,EAAE,OAAO,CAAC;CACnB;AAYD,oEAAoE;AACpE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAMrD;AAED,0FAA0F;AAC1F,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI,CAWtE;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe;;;;CAIlB,CAAC;AAEX,8DAA8D;AAC9D,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,eAAe,GAAG,MAAM,GAAG,IAAI,CAQhG;AAwCD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,EAAE,CAKzD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CAK7G;AAED,gGAAgG;AAChG,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,EAAE,CAOjG;AAED,mGAAmG;AACnG,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAkBtE;AAED,yGAAyG;AACzG,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAgBzE"}
|
package/dist/plugins/index.js
CHANGED
|
@@ -34,14 +34,50 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.FILE_CANDIDATES = void 0;
|
|
37
|
+
exports.isPluginDisabled = isPluginDisabled;
|
|
38
|
+
exports.setPluginDisabled = setPluginDisabled;
|
|
37
39
|
exports.resolvePluginFile = resolvePluginFile;
|
|
38
40
|
exports.loadPlugins = loadPlugins;
|
|
41
|
+
exports.findPlugin = findPlugin;
|
|
39
42
|
exports.pluginAssetDirs = pluginAssetDirs;
|
|
40
43
|
exports.pluginHooks = pluginHooks;
|
|
41
44
|
exports.pluginMcpServers = pluginMcpServers;
|
|
42
45
|
const fs = __importStar(require("fs"));
|
|
43
46
|
const path = __importStar(require("path"));
|
|
44
47
|
const os = __importStar(require("os"));
|
|
48
|
+
// ─── Enable / disable ──────────────────────────────────────────────────────────
|
|
49
|
+
//
|
|
50
|
+
// A marker file rather than a registry list, so the on/off state travels WITH
|
|
51
|
+
// the plugin directory itself: it survives a rename of the parent folder, and
|
|
52
|
+
// (deliberately, see installPlugin's preservation logic in installer.ts) it
|
|
53
|
+
// must survive `nex plugin update` re-copying the directory's contents — a
|
|
54
|
+
// user who turned a plugin off should not have it silently turn back on the
|
|
55
|
+
// next time it updates.
|
|
56
|
+
const DISABLED_MARKER = '.disabled';
|
|
57
|
+
/** True if this installed plugin directory has been toggled off. */
|
|
58
|
+
function isPluginDisabled(dir) {
|
|
59
|
+
try {
|
|
60
|
+
return fs.statSync(path.join(dir, DISABLED_MARKER)).isFile();
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Toggle a plugin on/off. Idempotent — enabling an already-enabled plugin is a no-op. */
|
|
67
|
+
function setPluginDisabled(dir, disabled) {
|
|
68
|
+
const marker = path.join(dir, DISABLED_MARKER);
|
|
69
|
+
if (disabled) {
|
|
70
|
+
fs.writeFileSync(marker, '');
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
try {
|
|
74
|
+
fs.unlinkSync(marker);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
/* already absent */
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
45
81
|
/**
|
|
46
82
|
* Where each single-file component may live, in priority order.
|
|
47
83
|
*
|
|
@@ -112,19 +148,46 @@ function scanRoot(root, scope, into) {
|
|
|
112
148
|
const name = meta.name || entry.name;
|
|
113
149
|
if (into.has(name))
|
|
114
150
|
continue; // project scope scanned first — it wins
|
|
115
|
-
into.set(name, { name, version: meta.version, description: meta.description, dir, scope });
|
|
151
|
+
into.set(name, { name, version: meta.version, description: meta.description, dir, scope, disabled: isPluginDisabled(dir) });
|
|
116
152
|
}
|
|
117
153
|
}
|
|
118
|
-
/**
|
|
154
|
+
/**
|
|
155
|
+
* Discover installed plugins (project scope shadows global on name clash).
|
|
156
|
+
*
|
|
157
|
+
* Includes disabled plugins — callers that manage the install (the desktop
|
|
158
|
+
* UI's list, `nex plugin list`) need to show and re-enable them. Everything
|
|
159
|
+
* that actually LOADS a plugin's contents at runtime (pluginAssetDirs,
|
|
160
|
+
* pluginHooks, pluginMcpServers below) filters `disabled` out itself, which is
|
|
161
|
+
* what makes toggling a plugin off actually take effect instead of only
|
|
162
|
+
* hiding it from a list.
|
|
163
|
+
*/
|
|
119
164
|
function loadPlugins(workDir) {
|
|
120
165
|
const out = new Map();
|
|
121
166
|
scanRoot(path.join(workDir, '.nexrall', 'plugins'), 'project', out);
|
|
122
167
|
scanRoot(path.join(os.homedir(), '.nexrall', 'plugins'), 'global', out);
|
|
123
168
|
return [...out.values()];
|
|
124
169
|
}
|
|
125
|
-
/**
|
|
170
|
+
/**
|
|
171
|
+
* Find one installed plugin by name AND scope. Looking this up through
|
|
172
|
+
* loadPlugins() (rather than re-deriving `<scopeRoot>/<name>` the way
|
|
173
|
+
* removePlugin/updatePlugin in installer.ts do) is deliberate: a plugin's
|
|
174
|
+
* effective name can come from plugin.json's "name" field rather than its
|
|
175
|
+
* directory name (see scanRoot/readMeta above), so a caller that needs the
|
|
176
|
+
* plugin's actual `dir` for a specific scope — not just "some plugin with
|
|
177
|
+
* this name, whichever scope loadPlugins()'s single merged map preferred" —
|
|
178
|
+
* has to re-scan that one scope directly to avoid resolving to the wrong
|
|
179
|
+
* directory or silently matching the other scope's plugin of the same name.
|
|
180
|
+
*/
|
|
181
|
+
function findPlugin(workDir, name, scope) {
|
|
182
|
+
const out = new Map();
|
|
183
|
+
const root = scope === 'project' ? path.join(workDir, '.nexrall', 'plugins') : path.join(os.homedir(), '.nexrall', 'plugins');
|
|
184
|
+
scanRoot(root, scope, out);
|
|
185
|
+
return out.get(name);
|
|
186
|
+
}
|
|
187
|
+
/** Subdirectories of every ENABLED installed plugin that hold `kind` assets (existing only). */
|
|
126
188
|
function pluginAssetDirs(workDir, kind) {
|
|
127
189
|
return loadPlugins(workDir)
|
|
190
|
+
.filter((p) => !p.disabled)
|
|
128
191
|
.map((p) => path.join(p.dir, kind))
|
|
129
192
|
.filter((d) => {
|
|
130
193
|
try {
|
|
@@ -135,10 +198,12 @@ function pluginAssetDirs(workDir, kind) {
|
|
|
135
198
|
}
|
|
136
199
|
});
|
|
137
200
|
}
|
|
138
|
-
/** Merge hooks.json from every plugin into a single hooks config (arrays concatenated). */
|
|
201
|
+
/** Merge hooks.json from every ENABLED plugin into a single hooks config (arrays concatenated). */
|
|
139
202
|
function pluginHooks(workDir) {
|
|
140
203
|
const merged = {};
|
|
141
204
|
for (const p of loadPlugins(workDir)) {
|
|
205
|
+
if (p.disabled)
|
|
206
|
+
continue;
|
|
142
207
|
const file = resolvePluginFile(p.dir, 'hooks');
|
|
143
208
|
if (!file)
|
|
144
209
|
continue;
|
|
@@ -157,10 +222,12 @@ function pluginHooks(workDir) {
|
|
|
157
222
|
}
|
|
158
223
|
return merged;
|
|
159
224
|
}
|
|
160
|
-
/** MCP server maps declared by plugins: { serverName → config } (first plugin wins on clash). */
|
|
225
|
+
/** MCP server maps declared by ENABLED plugins: { serverName → config } (first plugin wins on clash). */
|
|
161
226
|
function pluginMcpServers(workDir) {
|
|
162
227
|
const merged = {};
|
|
163
228
|
for (const p of loadPlugins(workDir)) {
|
|
229
|
+
if (p.disabled)
|
|
230
|
+
continue;
|
|
164
231
|
const file = resolvePluginFile(p.dir, 'mcp');
|
|
165
232
|
if (!file)
|
|
166
233
|
continue;
|