@jackwener/opencli 1.7.7 → 1.7.9
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/README.md +49 -14
- package/README.zh-CN.md +30 -10
- package/cli-manifest.json +782 -55
- package/clis/36kr/news.js +1 -1
- package/clis/amazon/discussion.js +37 -6
- package/clis/amazon/discussion.test.js +147 -32
- package/clis/apple-podcasts/commands.test.js +4 -4
- package/clis/apple-podcasts/episodes.js +1 -1
- package/clis/apple-podcasts/search.js +1 -1
- package/clis/apple-podcasts/top.js +1 -1
- package/clis/arxiv/paper.js +1 -1
- package/clis/arxiv/search.js +1 -1
- package/clis/band/mentions.js +3 -3
- package/clis/bbc/news.js +1 -1
- package/clis/bilibili/subtitle.js +2 -2
- package/clis/bloomberg/businessweek.js +1 -1
- package/clis/bloomberg/economics.js +1 -1
- package/clis/bloomberg/industries.js +1 -1
- package/clis/bloomberg/main.js +1 -1
- package/clis/bloomberg/markets.js +1 -1
- package/clis/bloomberg/opinions.js +1 -1
- package/clis/bloomberg/politics.js +1 -1
- package/clis/bloomberg/tech.js +1 -1
- package/clis/boss/search.js +49 -8
- package/clis/boss/search.test.js +78 -0
- package/clis/boss/send.js +3 -3
- package/clis/chatgpt/image.js +37 -8
- package/clis/chatgpt/image.test.js +92 -0
- package/clis/chatgpt/utils.js +39 -6
- package/clis/chatgpt/utils.test.js +63 -0
- package/clis/chatgpt-app/ask.js +4 -20
- package/clis/chatgpt-app/ax.js +135 -2
- package/clis/chatgpt-app/ax.test.js +35 -0
- package/clis/chatgpt-app/model.js +1 -1
- package/clis/chatgpt-app/new.js +1 -1
- package/clis/chatgpt-app/read.js +1 -1
- package/clis/chatgpt-app/send.js +3 -22
- package/clis/chatgpt-app/status.js +1 -1
- package/clis/chatwise/ask.js +2 -2
- package/clis/chatwise/model.js +2 -2
- package/clis/chatwise/send.js +2 -2
- package/clis/claude/ask.js +128 -0
- package/clis/claude/ask.test.js +338 -0
- package/clis/claude/commands.test.js +118 -0
- package/clis/claude/detail.js +29 -0
- package/clis/claude/history.js +31 -0
- package/clis/claude/new.js +21 -0
- package/clis/claude/read.js +24 -0
- package/clis/claude/send.js +41 -0
- package/clis/claude/status.js +24 -0
- package/clis/claude/utils.js +440 -0
- package/clis/claude/utils.test.js +148 -0
- package/clis/codex/ask.js +2 -2
- package/clis/codex/send.js +2 -2
- package/clis/ctrip/search.js +1 -1
- package/clis/ctrip/search.test.js +4 -4
- package/clis/cursor/ask.js +2 -2
- package/clis/cursor/composer.js +2 -2
- package/clis/cursor/send.js +2 -2
- package/clis/deepseek/ask.js +49 -10
- package/clis/deepseek/ask.test.js +150 -3
- package/clis/deepseek/utils.js +60 -22
- package/clis/deepseek/utils.test.js +124 -5
- package/clis/doubao/utils.js +53 -11
- package/clis/doubao/utils.test.js +22 -2
- package/clis/eastmoney/announcement.js +1 -1
- package/clis/eastmoney/convertible.js +1 -1
- package/clis/eastmoney/etf.js +1 -1
- package/clis/eastmoney/holders.js +1 -1
- package/clis/eastmoney/index-board.js +1 -1
- package/clis/eastmoney/kline.js +1 -1
- package/clis/eastmoney/kuaixun.js +1 -1
- package/clis/eastmoney/longhu.js +1 -1
- package/clis/eastmoney/money-flow.js +1 -1
- package/clis/eastmoney/northbound.js +1 -1
- package/clis/eastmoney/quote.js +1 -1
- package/clis/eastmoney/rank.js +1 -1
- package/clis/eastmoney/sectors.js +1 -1
- package/clis/facebook/marketplace-inbox.js +83 -0
- package/clis/facebook/marketplace-listings.js +83 -0
- package/clis/facebook/marketplace.test.js +91 -0
- package/clis/google/news.js +1 -1
- package/clis/google/suggest.js +1 -1
- package/clis/google/trends.js +1 -1
- package/clis/google-scholar/cite.js +74 -0
- package/clis/google-scholar/cite.test.js +47 -0
- package/clis/google-scholar/profile.js +92 -0
- package/clis/google-scholar/profile.test.js +49 -0
- package/clis/google-scholar/search.js +1 -1
- package/clis/google-scholar/search.test.js +15 -0
- package/clis/hf/top.js +1 -1
- package/clis/jd/item.js +679 -47
- package/clis/jd/item.test.js +318 -7
- package/clis/jd/item.test.ts +517 -0
- package/clis/lesswrong/comments.js +1 -1
- package/clis/lesswrong/curated.js +1 -1
- package/clis/lesswrong/frontpage.js +1 -1
- package/clis/lesswrong/new.js +1 -1
- package/clis/lesswrong/read.js +1 -1
- package/clis/lesswrong/sequences.js +1 -1
- package/clis/lesswrong/shortform.js +1 -1
- package/clis/lesswrong/tag.js +1 -1
- package/clis/lesswrong/tags.js +1 -1
- package/clis/lesswrong/top-month.js +1 -1
- package/clis/lesswrong/top-week.js +1 -1
- package/clis/lesswrong/top-year.js +1 -1
- package/clis/lesswrong/top.js +1 -1
- package/clis/lesswrong/user-posts.js +1 -1
- package/clis/lesswrong/user.js +1 -1
- package/clis/paperreview/commands.test.js +6 -6
- package/clis/paperreview/feedback.js +1 -1
- package/clis/paperreview/review.js +1 -1
- package/clis/paperreview/submit.js +1 -1
- package/clis/powerchina/search.js +250 -0
- package/clis/powerchina/search.test.js +67 -0
- package/clis/producthunt/posts.js +1 -1
- package/clis/producthunt/today.js +1 -1
- package/clis/sinablog/search.js +1 -1
- package/clis/sinafinance/news.js +1 -1
- package/clis/sinafinance/stock.js +6 -3
- package/clis/sinafinance/stock.test.js +59 -0
- package/clis/spotify/spotify.js +6 -6
- package/clis/substack/search.js +1 -1
- package/clis/toutiao/articles.js +80 -0
- package/clis/toutiao/articles.test.js +30 -0
- package/clis/twitter/followers.js +2 -2
- package/clis/twitter/following.js +224 -73
- package/clis/twitter/following.test.js +277 -0
- package/clis/twitter/post.js +184 -47
- package/clis/twitter/post.test.js +114 -34
- package/clis/uiverse/_shared.js +63 -4
- package/clis/uiverse/_shared.test.js +7 -0
- package/clis/uiverse/code.js +1 -0
- package/clis/uiverse/navigation.test.js +12 -0
- package/clis/uiverse/preview.js +1 -0
- package/clis/web/read.js +319 -81
- package/clis/web/read.test.js +221 -5
- package/clis/weibo/favorites.js +169 -0
- package/clis/weibo/favorites.test.js +114 -0
- package/clis/weibo/publish.js +282 -0
- package/clis/weibo/publish.test.js +183 -0
- package/clis/weixin/create-draft.js +225 -0
- package/clis/weixin/drafts.js +65 -0
- package/clis/weixin/drafts.test.js +65 -0
- package/clis/weread/ranking.js +1 -1
- package/clis/weread/search-regression.test.js +8 -8
- package/clis/weread/search.js +1 -1
- package/clis/wikipedia/random.js +1 -1
- package/clis/wikipedia/search.js +1 -1
- package/clis/wikipedia/summary.js +1 -1
- package/clis/wikipedia/trending.js +1 -1
- package/clis/xianyu/chat.js +3 -3
- package/clis/xianyu/item.js +2 -2
- package/clis/xianyu/item.test.js +3 -3
- package/clis/xiaohongshu/search.js +17 -2
- package/clis/xiaohongshu/search.test.js +37 -1
- package/clis/xiaoyuzhou/download.js +1 -1
- package/clis/xiaoyuzhou/download.test.js +3 -3
- package/clis/xiaoyuzhou/episode.js +1 -1
- package/clis/xiaoyuzhou/podcast-episodes.js +1 -1
- package/clis/xiaoyuzhou/podcast-episodes.test.js +2 -2
- package/clis/xiaoyuzhou/podcast.js +1 -1
- package/clis/xiaoyuzhou/transcript.js +1 -1
- package/clis/xiaoyuzhou/transcript.test.js +5 -5
- package/clis/yollomi/models.js +1 -1
- package/clis/youtube/channel.js +24 -1
- package/clis/youtube/channel.test.js +59 -0
- package/clis/zhihu/answer.js +21 -162
- package/clis/zhihu/answer.test.js +26 -53
- package/clis/zhihu/collection.js +197 -0
- package/clis/zhihu/collection.test.js +290 -0
- package/clis/zhihu/collections.js +127 -0
- package/clis/zhihu/collections.test.js +182 -0
- package/clis/zhihu/comment.js +24 -305
- package/clis/zhihu/comment.test.js +31 -35
- package/clis/zhihu/favorite.js +44 -182
- package/clis/zhihu/favorite.test.js +30 -167
- package/clis/zhihu/follow.js +25 -56
- package/clis/zhihu/follow.test.js +20 -23
- package/clis/zhihu/like.js +22 -67
- package/clis/zhihu/like.test.js +19 -42
- package/clis/zhihu/search.js +3 -2
- package/clis/zhihu/write-shared.js +8 -1
- package/clis/zhihu/write-shared.test.js +1 -0
- package/clis/zlibrary/commands.test.js +75 -0
- package/clis/zlibrary/info.js +47 -0
- package/clis/zlibrary/search.js +46 -0
- package/clis/zlibrary/utils.js +136 -0
- package/dist/src/adapter-source.d.ts +11 -0
- package/dist/src/adapter-source.js +24 -0
- package/dist/src/adapter-source.test.js +29 -0
- package/dist/src/browser/base-page.d.ts +3 -1
- package/dist/src/browser/base-page.js +76 -1
- package/dist/src/browser/base-page.test.d.ts +1 -0
- package/dist/src/browser/base-page.test.js +74 -0
- package/dist/src/browser/bridge.d.ts +1 -0
- package/dist/src/browser/bridge.js +36 -9
- package/dist/src/browser/cdp.d.ts +1 -0
- package/dist/src/browser/cdp.js +3 -3
- package/dist/src/browser/daemon-client.d.ts +38 -4
- package/dist/src/browser/daemon-client.js +24 -7
- package/dist/src/browser/daemon-client.test.js +49 -0
- package/dist/src/browser/errors.js +3 -0
- package/dist/src/browser/errors.test.js +3 -0
- package/dist/src/browser/network-cache.d.ts +1 -0
- package/dist/src/browser/page.d.ts +3 -1
- package/dist/src/browser/page.js +10 -2
- package/dist/src/browser/profile.d.ts +14 -0
- package/dist/src/browser/profile.js +85 -0
- package/dist/src/build-manifest.d.ts +2 -0
- package/dist/src/build-manifest.js +13 -3
- package/dist/src/build-manifest.test.js +20 -2
- package/dist/src/cli.d.ts +6 -0
- package/dist/src/cli.js +462 -32
- package/dist/src/cli.test.js +209 -2
- package/dist/src/commanderAdapter.js +29 -9
- package/dist/src/commanderAdapter.test.js +78 -2
- package/dist/src/commands/daemon.js +6 -0
- package/dist/src/completion-shared.js +1 -2
- package/dist/src/completion.test.js +3 -2
- package/dist/src/daemon.js +125 -41
- package/dist/src/doctor.d.ts +4 -6
- package/dist/src/doctor.js +80 -22
- package/dist/src/doctor.test.js +82 -0
- package/dist/src/engine.test.js +6 -5
- package/dist/src/errors.d.ts +14 -8
- package/dist/src/errors.js +36 -30
- package/dist/src/errors.test.js +5 -5
- package/dist/src/execution.d.ts +4 -0
- package/dist/src/execution.js +173 -25
- package/dist/src/execution.test.js +171 -1
- package/dist/src/main.js +10 -0
- package/dist/src/observation/artifact.d.ts +16 -0
- package/dist/src/observation/artifact.js +260 -0
- package/dist/src/observation/artifact.test.d.ts +1 -0
- package/dist/src/observation/artifact.test.js +121 -0
- package/dist/src/observation/events.d.ts +89 -0
- package/dist/src/observation/events.js +1 -0
- package/dist/src/observation/index.d.ts +7 -0
- package/dist/src/observation/index.js +7 -0
- package/dist/src/observation/manager.d.ts +9 -0
- package/dist/src/observation/manager.js +27 -0
- package/dist/src/observation/manager.test.d.ts +1 -0
- package/dist/src/observation/manager.test.js +13 -0
- package/dist/src/observation/redaction.d.ts +11 -0
- package/dist/src/observation/redaction.js +81 -0
- package/dist/src/observation/redaction.test.d.ts +1 -0
- package/dist/src/observation/redaction.test.js +32 -0
- package/dist/src/observation/retention.d.ts +32 -0
- package/dist/src/observation/retention.js +160 -0
- package/dist/src/observation/retention.test.d.ts +1 -0
- package/dist/src/observation/retention.test.js +118 -0
- package/dist/src/observation/ring-buffer.d.ts +22 -0
- package/dist/src/observation/ring-buffer.js +45 -0
- package/dist/src/observation/ring-buffer.test.d.ts +1 -0
- package/dist/src/observation/ring-buffer.test.js +22 -0
- package/dist/src/observation/session.d.ts +25 -0
- package/dist/src/observation/session.js +50 -0
- package/dist/src/pipeline/executor.test.js +1 -0
- package/dist/src/pipeline/steps/download.test.js +1 -0
- package/dist/src/pipeline/steps/fetch.js +1 -21
- package/dist/src/pipeline/steps/fetch.test.js +6 -12
- package/dist/src/plugin-scaffold.js +1 -1
- package/dist/src/plugin-scaffold.test.js +1 -1
- package/dist/src/registry.d.ts +40 -9
- package/dist/src/registry.js +3 -1
- package/dist/src/runtime-detect.d.ts +10 -0
- package/dist/src/runtime-detect.js +19 -0
- package/dist/src/runtime-detect.test.js +12 -1
- package/dist/src/runtime.d.ts +2 -0
- package/dist/src/runtime.js +1 -0
- package/dist/src/types.d.ts +22 -0
- package/dist/src/update-check.d.ts +31 -1
- package/dist/src/update-check.js +62 -16
- package/dist/src/update-check.test.js +86 -1
- package/package.json +1 -1
- package/dist/src/diagnostic.d.ts +0 -63
- package/dist/src/diagnostic.js +0 -292
- package/dist/src/diagnostic.test.js +0 -302
- /package/dist/src/{diagnostic.test.d.ts → adapter-source.test.d.ts} +0 -0
|
@@ -15,8 +15,9 @@ import { BasePage } from './base-page.js';
|
|
|
15
15
|
*/
|
|
16
16
|
export declare class Page extends BasePage {
|
|
17
17
|
private readonly workspace;
|
|
18
|
+
readonly contextId?: string | undefined;
|
|
18
19
|
private readonly _idleTimeout;
|
|
19
|
-
constructor(workspace?: string, idleTimeout?: number);
|
|
20
|
+
constructor(workspace?: string, idleTimeout?: number, contextId?: string | undefined);
|
|
20
21
|
/** Active page identity (targetId), set after navigate and used in all subsequent commands */
|
|
21
22
|
private _page;
|
|
22
23
|
private _networkCaptureUnsupported;
|
|
@@ -28,6 +29,7 @@ export declare class Page extends BasePage {
|
|
|
28
29
|
goto(url: string, options?: {
|
|
29
30
|
waitUntil?: 'load' | 'none';
|
|
30
31
|
settleMs?: number;
|
|
32
|
+
allowBoundNavigation?: boolean;
|
|
31
33
|
}): Promise<void>;
|
|
32
34
|
/** Get the active page identity (targetId) */
|
|
33
35
|
getActivePage(): string | undefined;
|
package/dist/src/browser/page.js
CHANGED
|
@@ -27,10 +27,12 @@ function isUnsupportedNetworkCaptureError(err) {
|
|
|
27
27
|
*/
|
|
28
28
|
export class Page extends BasePage {
|
|
29
29
|
workspace;
|
|
30
|
+
contextId;
|
|
30
31
|
_idleTimeout;
|
|
31
|
-
constructor(workspace = 'default', idleTimeout) {
|
|
32
|
+
constructor(workspace = 'default', idleTimeout, contextId) {
|
|
32
33
|
super();
|
|
33
34
|
this.workspace = workspace;
|
|
35
|
+
this.contextId = contextId;
|
|
34
36
|
this._idleTimeout = idleTimeout;
|
|
35
37
|
}
|
|
36
38
|
/** Active page identity (targetId), set after navigate and used in all subsequent commands */
|
|
@@ -39,12 +41,17 @@ export class Page extends BasePage {
|
|
|
39
41
|
_networkCaptureWarned = false;
|
|
40
42
|
/** Helper: spread workspace into command params */
|
|
41
43
|
_wsOpt() {
|
|
42
|
-
return {
|
|
44
|
+
return {
|
|
45
|
+
workspace: this.workspace,
|
|
46
|
+
...(this.contextId && { contextId: this.contextId }),
|
|
47
|
+
...(this._idleTimeout != null && { idleTimeout: this._idleTimeout }),
|
|
48
|
+
};
|
|
43
49
|
}
|
|
44
50
|
/** Helper: spread workspace + page identity into command params */
|
|
45
51
|
_cmdOpts() {
|
|
46
52
|
return {
|
|
47
53
|
workspace: this.workspace,
|
|
54
|
+
...(this.contextId && { contextId: this.contextId }),
|
|
48
55
|
...(this._page !== undefined && { page: this._page }),
|
|
49
56
|
...(this._idleTimeout != null && { idleTimeout: this._idleTimeout }),
|
|
50
57
|
};
|
|
@@ -53,6 +60,7 @@ export class Page extends BasePage {
|
|
|
53
60
|
const result = await sendCommandFull('navigate', {
|
|
54
61
|
url,
|
|
55
62
|
...this._cmdOpts(),
|
|
63
|
+
...(options?.allowBoundNavigation === true && { allowBoundNavigation: true }),
|
|
56
64
|
});
|
|
57
65
|
// Remember the page identity (targetId) for subsequent calls
|
|
58
66
|
if (result.page) {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const DEFAULT_CONTEXT_ID = "default";
|
|
2
|
+
export type ProfileConfig = {
|
|
3
|
+
version: 1;
|
|
4
|
+
defaultContextId?: string;
|
|
5
|
+
aliases: Record<string, string>;
|
|
6
|
+
};
|
|
7
|
+
export declare function normalizeContextId(value: string | undefined | null): string | undefined;
|
|
8
|
+
export declare function emptyProfileConfig(): ProfileConfig;
|
|
9
|
+
export declare function loadProfileConfig(): ProfileConfig;
|
|
10
|
+
export declare function saveProfileConfig(config: ProfileConfig): void;
|
|
11
|
+
export declare function resolveProfileContextId(profile?: string): string | undefined;
|
|
12
|
+
export declare function aliasForContextId(config: ProfileConfig, contextId: string): string | undefined;
|
|
13
|
+
export declare function renameProfile(contextId: string, alias: string): ProfileConfig;
|
|
14
|
+
export declare function setDefaultProfile(profile: string): ProfileConfig;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as os from 'node:os';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
export const DEFAULT_CONTEXT_ID = 'default';
|
|
5
|
+
function profileConfigPath() {
|
|
6
|
+
const baseDir = process.env.OPENCLI_CONFIG_DIR || path.join(os.homedir(), '.opencli');
|
|
7
|
+
return path.join(baseDir, 'browser-profiles.json');
|
|
8
|
+
}
|
|
9
|
+
export function normalizeContextId(value) {
|
|
10
|
+
const trimmed = value?.trim();
|
|
11
|
+
return trimmed || undefined;
|
|
12
|
+
}
|
|
13
|
+
export function emptyProfileConfig() {
|
|
14
|
+
return { version: 1, aliases: {} };
|
|
15
|
+
}
|
|
16
|
+
export function loadProfileConfig() {
|
|
17
|
+
try {
|
|
18
|
+
const raw = fs.readFileSync(profileConfigPath(), 'utf-8');
|
|
19
|
+
const parsed = JSON.parse(raw);
|
|
20
|
+
const aliases = parsed.aliases && typeof parsed.aliases === 'object'
|
|
21
|
+
? Object.fromEntries(Object.entries(parsed.aliases).filter((entry) => {
|
|
22
|
+
const [key, value] = entry;
|
|
23
|
+
return typeof key === 'string' && key.trim().length > 0
|
|
24
|
+
&& typeof value === 'string' && value.trim().length > 0;
|
|
25
|
+
}))
|
|
26
|
+
: {};
|
|
27
|
+
return {
|
|
28
|
+
version: 1,
|
|
29
|
+
aliases,
|
|
30
|
+
...(typeof parsed.defaultContextId === 'string' && parsed.defaultContextId.trim()
|
|
31
|
+
? { defaultContextId: parsed.defaultContextId.trim() }
|
|
32
|
+
: {}),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return emptyProfileConfig();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export function saveProfileConfig(config) {
|
|
40
|
+
const target = profileConfigPath();
|
|
41
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
42
|
+
fs.writeFileSync(target, JSON.stringify(config, null, 2) + '\n', 'utf-8');
|
|
43
|
+
}
|
|
44
|
+
export function resolveProfileContextId(profile) {
|
|
45
|
+
const config = loadProfileConfig();
|
|
46
|
+
const requested = normalizeContextId(profile)
|
|
47
|
+
?? normalizeContextId(process.env.OPENCLI_PROFILE)
|
|
48
|
+
?? normalizeContextId(config.defaultContextId);
|
|
49
|
+
if (!requested)
|
|
50
|
+
return undefined;
|
|
51
|
+
return config.aliases[requested] ?? requested;
|
|
52
|
+
}
|
|
53
|
+
export function aliasForContextId(config, contextId) {
|
|
54
|
+
for (const [alias, id] of Object.entries(config.aliases)) {
|
|
55
|
+
if (id === contextId)
|
|
56
|
+
return alias;
|
|
57
|
+
}
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
export function renameProfile(contextId, alias) {
|
|
61
|
+
const normalizedContextId = normalizeContextId(contextId);
|
|
62
|
+
const normalizedAlias = normalizeContextId(alias);
|
|
63
|
+
if (!normalizedContextId)
|
|
64
|
+
throw new Error('profile contextId is required');
|
|
65
|
+
if (!normalizedAlias)
|
|
66
|
+
throw new Error('profile alias is required');
|
|
67
|
+
const config = loadProfileConfig();
|
|
68
|
+
for (const [existingAlias, existingContextId] of Object.entries(config.aliases)) {
|
|
69
|
+
if (existingAlias !== normalizedAlias && existingContextId === normalizedContextId) {
|
|
70
|
+
delete config.aliases[existingAlias];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
config.aliases[normalizedAlias] = normalizedContextId;
|
|
74
|
+
saveProfileConfig(config);
|
|
75
|
+
return config;
|
|
76
|
+
}
|
|
77
|
+
export function setDefaultProfile(profile) {
|
|
78
|
+
const contextId = resolveProfileContextId(profile) ?? normalizeContextId(profile);
|
|
79
|
+
if (!contextId)
|
|
80
|
+
throw new Error('profile is required');
|
|
81
|
+
const config = loadProfileConfig();
|
|
82
|
+
config.defaultContextId = contextId;
|
|
83
|
+
saveProfileConfig(config);
|
|
84
|
+
return config;
|
|
85
|
+
}
|
|
@@ -39,5 +39,7 @@ export interface ManifestEntry {
|
|
|
39
39
|
/** Pre-navigation control — see CliCommand.navigateBefore */
|
|
40
40
|
navigateBefore?: boolean | string;
|
|
41
41
|
}
|
|
42
|
+
export declare function normalizeManifestPath(relativePath: string): string;
|
|
42
43
|
export declare function loadManifestEntries(filePath: string, site: string, importer?: (moduleHref: string) => Promise<unknown>): Promise<ManifestEntry[]>;
|
|
43
44
|
export declare function buildManifest(): Promise<ManifestEntry[]>;
|
|
45
|
+
export declare function serializeManifest(manifest: ManifestEntry[]): string;
|
|
@@ -36,6 +36,12 @@ function toModulePath(filePath, site) {
|
|
|
36
36
|
const baseName = path.basename(filePath, path.extname(filePath));
|
|
37
37
|
return `${site}/${baseName}.js`;
|
|
38
38
|
}
|
|
39
|
+
export function normalizeManifestPath(relativePath) {
|
|
40
|
+
return relativePath.replace(/\\/g, '/');
|
|
41
|
+
}
|
|
42
|
+
function toManifestRelativePath(filePath) {
|
|
43
|
+
return normalizeManifestPath(path.relative(CLIS_DIR, filePath));
|
|
44
|
+
}
|
|
39
45
|
function isCliCommandValue(value, site) {
|
|
40
46
|
return isRecord(value)
|
|
41
47
|
&& typeof value.site === 'string'
|
|
@@ -85,8 +91,9 @@ export async function loadManifestEntries(filePath, site, importer = moduleHref
|
|
|
85
91
|
return !previous || previous !== cmd;
|
|
86
92
|
})
|
|
87
93
|
.map(([, cmd]) => cmd);
|
|
88
|
-
//
|
|
89
|
-
|
|
94
|
+
// Manifest paths are cross-platform artifacts; keep them POSIX-style even
|
|
95
|
+
// when build-manifest runs on Windows.
|
|
96
|
+
const sourceRelative = toManifestRelativePath(filePath);
|
|
90
97
|
const seen = new Set();
|
|
91
98
|
return runtimeCommands
|
|
92
99
|
.filter((cmd) => {
|
|
@@ -128,10 +135,13 @@ export async function buildManifest() {
|
|
|
128
135
|
}
|
|
129
136
|
return [...manifest.values()].sort((a, b) => a.site.localeCompare(b.site) || a.name.localeCompare(b.name));
|
|
130
137
|
}
|
|
138
|
+
export function serializeManifest(manifest) {
|
|
139
|
+
return `${JSON.stringify(manifest, null, 2)}\n`;
|
|
140
|
+
}
|
|
131
141
|
async function main() {
|
|
132
142
|
const manifest = await buildManifest();
|
|
133
143
|
fs.mkdirSync(path.dirname(OUTPUT), { recursive: true });
|
|
134
|
-
fs.writeFileSync(OUTPUT,
|
|
144
|
+
fs.writeFileSync(OUTPUT, serializeManifest(manifest));
|
|
135
145
|
console.log(`✅ Manifest compiled: ${manifest.length} entries → ${OUTPUT}`);
|
|
136
146
|
// Restore executable permissions on bin entries.
|
|
137
147
|
// tsc does not preserve the +x bit, so after a clean rebuild the CLI
|
|
@@ -3,7 +3,7 @@ import * as fs from 'node:fs';
|
|
|
3
3
|
import * as os from 'node:os';
|
|
4
4
|
import * as path from 'node:path';
|
|
5
5
|
import { cli, getRegistry, Strategy } from './registry.js';
|
|
6
|
-
import { loadManifestEntries } from './build-manifest.js';
|
|
6
|
+
import { loadManifestEntries, normalizeManifestPath, serializeManifest } from './build-manifest.js';
|
|
7
7
|
describe('manifest helper rules', () => {
|
|
8
8
|
const tempDirs = [];
|
|
9
9
|
afterEach(() => {
|
|
@@ -76,8 +76,9 @@ describe('manifest helper rules', () => {
|
|
|
76
76
|
replacedBy: 'opencli demo new',
|
|
77
77
|
},
|
|
78
78
|
]);
|
|
79
|
-
// Verify sourceFile is included
|
|
79
|
+
// Verify sourceFile is included and stable for manifest consumers.
|
|
80
80
|
expect(entries[0].sourceFile).toBeDefined();
|
|
81
|
+
expect(entries[0].sourceFile).not.toContain('\\');
|
|
81
82
|
getRegistry().delete(key);
|
|
82
83
|
});
|
|
83
84
|
it('falls back to registry delta for side-effect-only cli modules', async () => {
|
|
@@ -139,4 +140,21 @@ describe('manifest helper rules', () => {
|
|
|
139
140
|
getRegistry().delete(screenKey);
|
|
140
141
|
getRegistry().delete(statusKey);
|
|
141
142
|
});
|
|
143
|
+
it('normalizes manifest paths to POSIX separators', () => {
|
|
144
|
+
expect(normalizeManifestPath('demo\\status.js')).toBe('demo/status.js');
|
|
145
|
+
expect(normalizeManifestPath('demo/status.js')).toBe('demo/status.js');
|
|
146
|
+
});
|
|
147
|
+
it('serializes manifest json with a trailing newline', () => {
|
|
148
|
+
const serialized = serializeManifest([{
|
|
149
|
+
site: 'demo',
|
|
150
|
+
name: 'status',
|
|
151
|
+
description: '',
|
|
152
|
+
strategy: 'public',
|
|
153
|
+
browser: false,
|
|
154
|
+
args: [],
|
|
155
|
+
type: 'js',
|
|
156
|
+
}]);
|
|
157
|
+
expect(serialized.endsWith('\n')).toBe(true);
|
|
158
|
+
expect(serialized).toContain('\n]');
|
|
159
|
+
});
|
|
142
160
|
});
|
package/dist/src/cli.d.ts
CHANGED
|
@@ -6,6 +6,12 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { Command } from 'commander';
|
|
8
8
|
import { findPackageRoot } from './package-paths.js';
|
|
9
|
+
export declare function selectFreshByTimestamp<T extends {
|
|
10
|
+
timestamp?: unknown;
|
|
11
|
+
}>(items: T[], lastSeenTs: number): {
|
|
12
|
+
fresh: T[];
|
|
13
|
+
lastSeenTs: number;
|
|
14
|
+
};
|
|
9
15
|
/**
|
|
10
16
|
* Check whether the site-memory scaffolding exists under
|
|
11
17
|
* ~/.opencli/sites/<site>/. Agents have a strong tendency to forget to write
|