@crewx/sdk 0.9.0-rc.9 → 0.9.0-rc.90
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 +1 -1
- package/dist/account/auth-client.d.ts +61 -0
- package/dist/account/auth-json-v2.d.ts +1 -0
- package/dist/account/auth-json.d.ts +30 -0
- package/dist/account/config.d.ts +8 -0
- package/dist/account/errors.d.ts +24 -0
- package/dist/account/index.d.ts +10 -0
- package/dist/account/index.js +1 -0
- package/dist/account/session-manager.d.ts +47 -0
- package/dist/activity-log/builder.d.ts +55 -6
- package/dist/config/canonicalize-agent-options.d.ts +17 -0
- package/dist/config/global-settings.d.ts +33 -0
- package/dist/config/migrate-grok-mode.d.ts +6 -0
- package/dist/config/model-compat.d.ts +31 -0
- package/dist/config/models.generated.d.ts +37 -0
- package/dist/config/models.remote.d.ts +1 -0
- package/dist/config/overdrive.d.ts +7 -0
- package/dist/config/pricing.d.ts +8 -5
- package/dist/config/pricing.generated.d.ts +4 -0
- package/dist/config/pricing.types.d.ts +4 -10
- package/dist/config/timeout.config.d.ts +3 -0
- package/dist/config/wi-boards.d.ts +19 -0
- package/dist/context-budget/continuity.d.ts +61 -0
- package/dist/context-budget/index.d.ts +140 -0
- package/dist/conversation/index.d.ts +1 -1
- package/dist/conversation/sqlite-provider.d.ts +5 -1
- package/dist/conversation/to-template-messages.d.ts +7 -0
- package/dist/conversation/types.d.ts +43 -0
- package/dist/desktop/command-runner.d.ts +4 -0
- package/dist/desktop/default-adapters.d.ts +4 -0
- package/dist/desktop/global-install.d.ts +19 -0
- package/dist/desktop/index.d.ts +2 -0
- package/dist/desktop/index.js +3 -0
- package/dist/desktop/install.d.ts +5 -0
- package/dist/desktop/lnk.d.ts +22 -0
- package/dist/desktop/manifest.d.ts +21 -0
- package/dist/desktop/types.d.ts +67 -0
- package/dist/desktop/version.d.ts +1 -0
- package/dist/desktop/windows-paths.d.ts +21 -0
- package/dist/desktop/wrapper.d.ts +18 -0
- package/dist/esm/account/index.js +1 -0
- package/dist/esm/desktop/index.js +3 -0
- package/dist/esm/index.js +353 -98
- package/dist/esm/plugins/index.js +213 -103
- package/dist/esm/publish/index.js +1 -0
- package/dist/esm/repository/index.js +200 -94
- package/dist/esm/testing/index.js +1 -1
- package/dist/events/types.d.ts +4 -0
- package/dist/facade/Crewx.d.ts +40 -2
- package/dist/highlight/thread-highlight-prompt.d.ts +2 -0
- package/dist/highlight/thread-highlighter.d.ts +326 -0
- package/dist/index.browser.d.ts +11 -1
- package/dist/index.browser.js +6 -2
- package/dist/index.d.ts +71 -11
- package/dist/index.js +353 -98
- package/dist/internal/windows-spawn.d.ts +10 -0
- package/dist/layout/types.d.ts +17 -1
- package/dist/local-server/base-url.d.ts +18 -0
- package/dist/local-server/index.d.ts +8 -0
- package/dist/local-server/opencode.d.ts +8 -0
- package/dist/local-server/probe.d.ts +3 -0
- package/dist/local-server/runtime.d.ts +26 -0
- package/dist/local-server/types.d.ts +43 -0
- package/dist/migrations/0008_careful_black_bird.sql +17 -0
- package/dist/migrations/0009_hot_dark_phoenix.sql +1 -0
- package/dist/migrations/0010_analyze_stats.sql +6 -0
- package/dist/migrations/0011_far_black_tarantula.sql +1 -0
- package/dist/migrations/0012_blue_turbo.sql +23 -0
- package/dist/migrations/0013_hesitant_adam_destine.sql +15 -0
- package/dist/migrations/0014_organic_mongu.sql +73 -0
- package/dist/migrations/0015_panoramic_gorilla_man.sql +71 -0
- package/dist/migrations/0016_fuzzy_hemingway.sql +14 -0
- package/dist/migrations/0017_project_stage_sdk_migration.sql +29 -0
- package/dist/migrations/0018_bored_jackal.sql +33 -0
- package/dist/migrations/0019_backfill_task_thread_ids.sql +74 -0
- package/dist/migrations/0020_useful_iron_lad.sql +55 -0
- package/dist/migrations/0021_dashing_peter_quill.sql +51 -0
- package/dist/migrations/0022_wandering_bucky.sql +1 -0
- package/dist/migrations/0023_red_payback.sql +1 -0
- package/dist/migrations/meta/0008_snapshot.json +1327 -0
- package/dist/migrations/meta/0009_snapshot.json +1335 -0
- package/dist/migrations/meta/0010_snapshot.json +1335 -0
- package/dist/migrations/meta/0011_snapshot.json +1342 -0
- package/dist/migrations/meta/0012_snapshot.json +1494 -0
- package/dist/migrations/meta/0013_snapshot.json +1592 -0
- package/dist/migrations/meta/0014_snapshot.json +1975 -0
- package/dist/migrations/meta/0015_snapshot.json +2315 -0
- package/dist/migrations/meta/0016_snapshot.json +2419 -0
- package/dist/migrations/meta/0017_snapshot.json +2419 -0
- package/dist/migrations/meta/0018_snapshot.json +2570 -0
- package/dist/migrations/meta/0020_snapshot.json +2895 -0
- package/dist/migrations/meta/0021_snapshot.json +3031 -0
- package/dist/migrations/meta/0022_snapshot.json +3039 -0
- package/dist/migrations/meta/0023_snapshot.json +3047 -0
- package/dist/migrations/meta/_journal.json +112 -0
- package/dist/paths.d.ts +1 -0
- package/dist/plugin/types.d.ts +1 -0
- package/dist/plugins/index.js +213 -103
- package/dist/plugins/sqlite-tracing.d.ts +23 -0
- package/dist/provider/acp/connection.d.ts +4 -0
- package/dist/provider/acp/meta.d.ts +11 -0
- package/dist/provider/bridge.d.ts +6 -0
- package/dist/provider/classify-task-error.d.ts +2 -0
- package/dist/provider/cli/adapter.types.d.ts +8 -1
- package/dist/provider/cli/adapters/agent-call.util.d.ts +1 -1
- package/dist/provider/cli/adapters/cli-knob.util.d.ts +7 -0
- package/dist/provider/cli/adapters/grok.d.ts +2 -0
- package/dist/provider/cli/adapters/index.d.ts +1 -0
- package/dist/provider/cli/index.d.ts +1 -1
- package/dist/provider/cli/meta.d.ts +5 -0
- package/dist/provider/cli/protocol-envelope.d.ts +2 -0
- package/dist/provider/errors.d.ts +1 -0
- package/dist/provider/idle-watchdog.d.ts +19 -0
- package/dist/provider/models.d.ts +17 -12
- package/dist/provider/order.d.ts +1 -1
- package/dist/provider/parse-usage.d.ts +6 -0
- package/dist/provider/provider-selection.d.ts +8 -0
- package/dist/provider/redact-technical-message.d.ts +1 -0
- package/dist/provider/task-error.types.d.ts +16 -0
- package/dist/publish/constants.d.ts +6 -0
- package/dist/publish/index.d.ts +26 -0
- package/dist/publish/index.js +1 -0
- package/dist/publish/manifest.d.ts +17 -0
- package/dist/publish/marketplace-api.constants.d.ts +1 -0
- package/dist/publish/pack.d.ts +2 -0
- package/dist/publish/scan.d.ts +9 -0
- package/dist/publish/secrets.d.ts +6 -0
- package/dist/publish/upload.d.ts +18 -0
- package/dist/remote/execution-profile.d.ts +9 -0
- package/dist/remote/index.d.ts +1 -0
- package/dist/remote/types.d.ts +28 -0
- package/dist/repository/agent-suggestion.repository.d.ts +34 -0
- package/dist/repository/common-code.repository.d.ts +45 -0
- package/dist/repository/db.d.ts +8 -0
- package/dist/repository/index.d.ts +28 -4
- package/dist/repository/index.js +200 -94
- package/dist/repository/notification.repository.d.ts +58 -0
- package/dist/repository/project.repository.d.ts +90 -0
- package/dist/repository/request-log.repository.d.ts +1 -0
- package/dist/repository/task-log-migration.d.ts +74 -0
- package/dist/repository/task-log.repository.d.ts +44 -0
- package/dist/repository/task.repository.d.ts +120 -0
- package/dist/repository/thread-history.repository.d.ts +193 -0
- package/dist/repository/thread-title-common-code-migration.d.ts +13 -0
- package/dist/repository/thread-title.types.d.ts +29 -0
- package/dist/repository/thread.repository.d.ts +21 -2
- package/dist/repository/usage-report.repository.d.ts +27 -0
- package/dist/repository/workspace.repository.d.ts +3 -0
- package/dist/schema/agent-suggestions.d.ts +199 -0
- package/dist/schema/common-codes.d.ts +216 -0
- package/dist/schema/index.d.ts +9 -0
- package/dist/schema/notifications.d.ts +303 -0
- package/dist/schema/projects.d.ts +610 -0
- package/dist/schema/task-log-events.d.ts +119 -0
- package/dist/schema/tasks.d.ts +53 -0
- package/dist/schema/thread-history.d.ts +734 -0
- package/dist/schema/threads.d.ts +2 -0
- package/dist/schema/ui-action-receipts.d.ts +303 -0
- package/dist/schema/ui-instances.d.ts +267 -0
- package/dist/schema/usage-reports.d.ts +252 -0
- package/dist/schema/workspaces.d.ts +17 -0
- package/dist/task-log/anchor-child-tasks.d.ts +7 -0
- package/dist/task-log/delegation-trailer.d.ts +34 -0
- package/dist/testing/index.js +1 -1
- package/dist/types/index.d.ts +1536 -3
- package/dist/types/task-log.types.d.ts +2 -0
- package/dist/ui-card/index.d.ts +2 -0
- package/dist/ui-card/legacy-card-parser.d.ts +11 -0
- package/dist/ui-instance/definition.d.ts +6 -0
- package/dist/ui-instance/errors.d.ts +17 -0
- package/dist/ui-instance/index.d.ts +6 -0
- package/dist/ui-instance/json.d.ts +5 -0
- package/dist/ui-instance/runtime.d.ts +13 -0
- package/dist/ui-instance/store.d.ts +65 -0
- package/dist/ui-instance/types.d.ts +200 -0
- package/dist/ui-plugin/index.d.ts +3 -0
- package/dist/ui-plugin/manifest.d.ts +3 -0
- package/dist/ui-plugin/types.d.ts +76 -0
- package/dist/ui-plugin/validator.d.ts +9 -0
- package/dist/utils/crewx-executable.d.ts +54 -0
- package/dist/utils/crewx-home.d.ts +1 -0
- package/dist/utils/env-defaults.d.ts +2 -0
- package/dist/utils/id.d.ts +1 -1
- package/dist/utils/timestamp.d.ts +1 -0
- package/dist/wi/create.d.ts +48 -0
- package/dist/wi/select.d.ts +20 -0
- package/package.json +25 -2
- package/templates/agents/default.yaml +244 -120
- package/templates/documents/crewx-manual.md +138 -138
- package/templates/workflows/wi-default-flow.yaml +65 -0
- package/templates/workflows/wi-plan-flow.yaml +140 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
export declare const DEFAULT_INPUT_BUDGET_PERCENT = 60;
|
|
2
|
+
export declare const MIN_INPUT_BUDGET_PERCENT = 30;
|
|
3
|
+
export declare const MAX_INPUT_BUDGET_PERCENT = 80;
|
|
4
|
+
export declare const INPUT_BUDGET_TOKENIZER_ENCODING = "o200k_base";
|
|
5
|
+
export declare const FRESH_PROVIDER_INITIAL_INPUT_SEPARATOR = "\n\n---\n\n";
|
|
6
|
+
export declare const FRESH_PROVIDER_INITIAL_INPUT_FRAMING = "system_prompt\\n\\n---\\n\\nmessage";
|
|
7
|
+
export declare const RESUME_PROVIDER_INITIAL_INPUT_FRAMING = "message";
|
|
8
|
+
export type InputBudgetUnresolvedReason = 'invalid_input_budget_percent' | 'provider_catalog_unavailable' | 'model_not_found' | 'context_window_tokens_unavailable';
|
|
9
|
+
export type TokenizerFallbackReason = 'vendor_tokenizer_unavailable';
|
|
10
|
+
export interface ResolveInputBudgetOptions {
|
|
11
|
+
provider: string;
|
|
12
|
+
model: string;
|
|
13
|
+
inputBudgetPercent?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface TokenizerOptions {
|
|
16
|
+
provider?: string;
|
|
17
|
+
model?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface TokenizerMetadata {
|
|
20
|
+
provider: string;
|
|
21
|
+
model: string;
|
|
22
|
+
encoding: typeof INPUT_BUDGET_TOKENIZER_ENCODING;
|
|
23
|
+
exact: boolean;
|
|
24
|
+
fallbackReason?: TokenizerFallbackReason;
|
|
25
|
+
}
|
|
26
|
+
export interface ResolvedInputBudget {
|
|
27
|
+
resolved: true;
|
|
28
|
+
requestedProvider: string;
|
|
29
|
+
provider: string;
|
|
30
|
+
model: string;
|
|
31
|
+
contextWindowTokens: number;
|
|
32
|
+
inputBudgetPercent: number;
|
|
33
|
+
inputBudgetTokens: number;
|
|
34
|
+
tokenizer: TokenizerMetadata;
|
|
35
|
+
}
|
|
36
|
+
export interface UnresolvedInputBudget {
|
|
37
|
+
resolved: false;
|
|
38
|
+
requestedProvider: string;
|
|
39
|
+
provider: string;
|
|
40
|
+
model: string;
|
|
41
|
+
reason: InputBudgetUnresolvedReason;
|
|
42
|
+
inputBudgetPercent?: number;
|
|
43
|
+
tokenizer: TokenizerMetadata;
|
|
44
|
+
}
|
|
45
|
+
export type ResolveInputBudgetResult = ResolvedInputBudget | UnresolvedInputBudget;
|
|
46
|
+
export type ContextBudgetPhase = 'fresh' | 'resume';
|
|
47
|
+
export type ProviderInitialInputFraming = typeof FRESH_PROVIDER_INITIAL_INPUT_FRAMING | typeof RESUME_PROVIDER_INITIAL_INPUT_FRAMING;
|
|
48
|
+
export interface ContextBudgetLayoutCapability {
|
|
49
|
+
layoutId: string;
|
|
50
|
+
supportsSemanticContinuity: boolean;
|
|
51
|
+
slot: string | null;
|
|
52
|
+
requiredForOmittedTurns: boolean;
|
|
53
|
+
warning?: string;
|
|
54
|
+
}
|
|
55
|
+
export interface ContextBudgetActivityDegradation {
|
|
56
|
+
taskId: string;
|
|
57
|
+
taskDistance: number;
|
|
58
|
+
action: 'reduced' | 'omitted';
|
|
59
|
+
}
|
|
60
|
+
export type ContextBudgetAssemblyErrorCode = 'INPUT_BUDGET_EXCEEDED' | 'CONTINUITY_SLOT_REQUIRED';
|
|
61
|
+
export declare class ContextBudgetLayoutError extends Error {
|
|
62
|
+
readonly layoutId: string;
|
|
63
|
+
readonly omittedTurnCount: number;
|
|
64
|
+
readonly code: "CONTINUITY_SLOT_REQUIRED";
|
|
65
|
+
constructor(message: string, layoutId: string, omittedTurnCount: number);
|
|
66
|
+
}
|
|
67
|
+
export interface ContextBudgetManifest {
|
|
68
|
+
phase: ContextBudgetPhase;
|
|
69
|
+
initialInputFraming: ProviderInitialInputFraming;
|
|
70
|
+
resolved: boolean;
|
|
71
|
+
reason?: InputBudgetUnresolvedReason;
|
|
72
|
+
requestedProvider: string;
|
|
73
|
+
requestedModel: string | null;
|
|
74
|
+
effectiveProvider: string;
|
|
75
|
+
effectiveModel: string | null;
|
|
76
|
+
contextWindowTokens: number | null;
|
|
77
|
+
inputBudgetPercent: number | null;
|
|
78
|
+
inputBudgetTokens: number | null;
|
|
79
|
+
tokenizer: TokenizerMetadata;
|
|
80
|
+
initialTokenCount: number | null;
|
|
81
|
+
finalTokenCount: number | null;
|
|
82
|
+
activityLogTokenCount: number | null;
|
|
83
|
+
activityIncludedEntries: number | null;
|
|
84
|
+
activityOmittedEntries: number | null;
|
|
85
|
+
activityRemovedForBudget: boolean;
|
|
86
|
+
activityNewestTaskTokenCap: number | null;
|
|
87
|
+
historyOriginalMessages: number;
|
|
88
|
+
historyIncludedMessages: number;
|
|
89
|
+
historyOmittedMessages: number;
|
|
90
|
+
turnOriginal: number;
|
|
91
|
+
turnIncluded: number;
|
|
92
|
+
turnOmitted: number;
|
|
93
|
+
highlightOriginal: number;
|
|
94
|
+
highlightIncluded: number;
|
|
95
|
+
highlightOmitted: number;
|
|
96
|
+
highlightTruncated: number;
|
|
97
|
+
representedOmittedTurns: number;
|
|
98
|
+
unrepresentedOmittedTurns: number;
|
|
99
|
+
activityDegraded: boolean;
|
|
100
|
+
activityIncludedTasks: number;
|
|
101
|
+
activityOmittedTasks: number;
|
|
102
|
+
activityDegradation: ContextBudgetActivityDegradation[];
|
|
103
|
+
highlightLookupFailed: boolean;
|
|
104
|
+
layoutCapability: ContextBudgetLayoutCapability;
|
|
105
|
+
overBudget: boolean;
|
|
106
|
+
}
|
|
107
|
+
export interface TokenCountResult {
|
|
108
|
+
tokenCount: number;
|
|
109
|
+
tokenizer: TokenizerMetadata;
|
|
110
|
+
}
|
|
111
|
+
export interface TokenCounter {
|
|
112
|
+
metadata: TokenizerMetadata;
|
|
113
|
+
countTokens(text: string): number;
|
|
114
|
+
}
|
|
115
|
+
export interface FreshProviderInitialInput {
|
|
116
|
+
systemPrompt?: string | null;
|
|
117
|
+
message: string;
|
|
118
|
+
}
|
|
119
|
+
type PieceCacheEventType = 'hit' | 'miss' | 'evict' | 'full_encode';
|
|
120
|
+
interface PieceCacheEvent {
|
|
121
|
+
type: PieceCacheEventType;
|
|
122
|
+
piece?: string;
|
|
123
|
+
tokenCount?: number;
|
|
124
|
+
reason?: 'special_token';
|
|
125
|
+
}
|
|
126
|
+
type PieceCacheObserver = (event: PieceCacheEvent) => void;
|
|
127
|
+
interface TokenCounterInternalOptions {
|
|
128
|
+
pieceCacheMaxEntries?: number;
|
|
129
|
+
observePieceCache?: PieceCacheObserver;
|
|
130
|
+
}
|
|
131
|
+
export declare function normalizeInputBudgetProvider(provider: string): string;
|
|
132
|
+
export declare function resolveTokenizerMetadata(options?: TokenizerOptions): TokenizerMetadata;
|
|
133
|
+
export declare function countTokens(text: string, options?: TokenizerOptions): TokenCountResult;
|
|
134
|
+
export declare function renderFreshProviderInitialInput(input: FreshProviderInitialInput): string;
|
|
135
|
+
export declare function countFreshProviderInitialInput(input: FreshProviderInitialInput, count: (text: string) => number): number;
|
|
136
|
+
export declare function createTokenCounter(options?: TokenizerOptions): TokenCounter;
|
|
137
|
+
export declare function __createTokenCounterForTest(options?: TokenizerOptions, internalOptions?: TokenCounterInternalOptions): TokenCounter;
|
|
138
|
+
export declare function resolveInputBudget(options: ResolveInputBudgetOptions): ResolveInputBudgetResult;
|
|
139
|
+
export { DEFAULT_HIGHLIGHT_BUDGET_PERCENT, DEFAULT_PROTECTED_TURN_COUNT, MAX_ACTIVE_HIGHLIGHT_CHARS, MAX_ACTIVE_HIGHLIGHTS, MAX_THREAD_STATE_VALUE_CHARS, MAX_THREAD_TITLE_CHARS, buildSemanticContinuityContext, buildThreadStateContext, getConversationMessageTaskId, groupConversationTurns, materializeConversationTurn, selectConversationHighlights, selectConversationTurns, } from './continuity.js';
|
|
140
|
+
export type { BuildSemanticContinuityContextOptions, ConversationHighlightSelection, ConversationTurn, ConversationTurnSelection, GroupedConversationTurns, SelectConversationHighlightsOptions, SelectConversationTurnsOptions, } from './continuity.js';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export * from './types.js';
|
|
2
2
|
export { toTaskReader } from './to-task-reader.js';
|
|
3
|
-
export { toTemplateMessages } from './to-template-messages.js';
|
|
3
|
+
export { LEGACY_UI_CARD_SAFE_SUMMARY, sanitizeLegacyUiCardText, sanitizeTemplateMessages, toTemplateMessages, } from './to-template-messages.js';
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type { ConversationThread, FetchHistoryOptions, IConversationHistoryProvider, Platform } from './types';
|
|
1
|
+
import type { ConversationHighlight, ConversationThread, ConversationThreadState, FetchHistoryOptions, IConversationHistoryProvider, Platform } from './types';
|
|
2
2
|
export declare class SqliteConversationProvider implements IConversationHistoryProvider {
|
|
3
3
|
private readonly dbPath;
|
|
4
4
|
constructor(dbPath?: string);
|
|
5
5
|
private getThreadRepo;
|
|
6
|
+
private getThreadHistoryRepo;
|
|
6
7
|
updateThread(id: string, patch: {
|
|
7
8
|
title?: string;
|
|
8
9
|
}): void;
|
|
@@ -10,6 +11,8 @@ export declare class SqliteConversationProvider implements IConversationHistoryP
|
|
|
10
11
|
created: boolean;
|
|
11
12
|
}>;
|
|
12
13
|
fetchHistory(threadId: string, options?: FetchHistoryOptions): Promise<ConversationThread>;
|
|
14
|
+
fetchThreadState(threadId: string): Promise<ConversationThreadState | undefined>;
|
|
15
|
+
fetchHighlights(threadId: string): Promise<ConversationHighlight[] | undefined>;
|
|
13
16
|
saveUserMessage(threadId: string, text: string, _userId?: string, _metadata?: Record<string, unknown>): Promise<{
|
|
14
17
|
id: string;
|
|
15
18
|
firstMessage: boolean;
|
|
@@ -19,5 +22,6 @@ export declare class SqliteConversationProvider implements IConversationHistoryP
|
|
|
19
22
|
}>;
|
|
20
23
|
close(): void;
|
|
21
24
|
private normalizeStatus;
|
|
25
|
+
private readActiveHighlights;
|
|
22
26
|
private rowsToMessages;
|
|
23
27
|
}
|
|
@@ -1,2 +1,9 @@
|
|
|
1
1
|
import type { ConversationThread, TemplateMessage } from './types';
|
|
2
|
+
import type { UiAgentContextProjection } from '../ui-instance/types.js';
|
|
3
|
+
export declare const LEGACY_UI_CARD_SAFE_SUMMARY = "[workflow card omitted from AI context]";
|
|
4
|
+
export declare const V2_UI_INSTANCE_SAFE_SUMMARY = "[workflow UI instance omitted from AI context]";
|
|
5
|
+
export declare function sanitizeUiInstanceReferenceText(text: string): string;
|
|
6
|
+
export declare function sanitizeLegacyUiCardText(text: string): string;
|
|
7
|
+
export declare function sanitizeTemplateMessages(messages: readonly TemplateMessage[]): TemplateMessage[];
|
|
8
|
+
export declare function appendUiProjections(messages: readonly TemplateMessage[], projections: readonly UiAgentContextProjection[] | undefined): TemplateMessage[];
|
|
2
9
|
export declare function toTemplateMessages(thread: ConversationThread): TemplateMessage[];
|
|
@@ -4,13 +4,50 @@ export interface ConversationMessage {
|
|
|
4
4
|
text: string;
|
|
5
5
|
isAssistant: boolean;
|
|
6
6
|
timestamp: number;
|
|
7
|
+
taskId?: string;
|
|
7
8
|
metadata?: Record<string, unknown>;
|
|
8
9
|
}
|
|
9
10
|
export type Platform = 'cli' | 'web' | 'api' | 'mcp' | `channel/${string}`;
|
|
11
|
+
export interface ConversationHighlight {
|
|
12
|
+
id: string;
|
|
13
|
+
text: string;
|
|
14
|
+
kind?: string;
|
|
15
|
+
source?: string;
|
|
16
|
+
coversFromTaskId?: string;
|
|
17
|
+
coversToTaskId?: string;
|
|
18
|
+
covers_from_task_id?: string;
|
|
19
|
+
covers_to_task_id?: string;
|
|
20
|
+
createdAt?: number | string;
|
|
21
|
+
created_at?: number | string;
|
|
22
|
+
}
|
|
23
|
+
export interface SemanticContinuityContext {
|
|
24
|
+
highlights: ConversationHighlight[];
|
|
25
|
+
truncatedHighlights?: number;
|
|
26
|
+
omittedTurns: {
|
|
27
|
+
count: number;
|
|
28
|
+
represented: number;
|
|
29
|
+
unrepresented: number;
|
|
30
|
+
taskIds: string[];
|
|
31
|
+
};
|
|
32
|
+
rendered?: string;
|
|
33
|
+
}
|
|
34
|
+
export type ConversationSemanticContinuityContext = SemanticContinuityContext;
|
|
35
|
+
export interface ConversationThreadStateValue {
|
|
36
|
+
code: string;
|
|
37
|
+
name: string;
|
|
38
|
+
}
|
|
39
|
+
export interface ConversationThreadState {
|
|
40
|
+
title?: string;
|
|
41
|
+
priority?: ConversationThreadStateValue;
|
|
42
|
+
state?: ConversationThreadStateValue;
|
|
43
|
+
rendered?: string;
|
|
44
|
+
}
|
|
45
|
+
export type ThreadStateContext = ConversationThreadState;
|
|
10
46
|
export interface ConversationThread {
|
|
11
47
|
threadId: string;
|
|
12
48
|
platform: Platform;
|
|
13
49
|
messages: ConversationMessage[];
|
|
50
|
+
highlights?: ConversationHighlight[];
|
|
14
51
|
metadata?: {
|
|
15
52
|
title?: string;
|
|
16
53
|
firstMessage?: string;
|
|
@@ -20,10 +57,13 @@ export interface ConversationThread {
|
|
|
20
57
|
};
|
|
21
58
|
}
|
|
22
59
|
export interface TemplateMessage {
|
|
60
|
+
id?: string;
|
|
23
61
|
text: string;
|
|
24
62
|
isAssistant: boolean;
|
|
63
|
+
taskId?: string;
|
|
25
64
|
timestamp?: number;
|
|
26
65
|
metadata?: Record<string, unknown>;
|
|
66
|
+
activity_log?: string;
|
|
27
67
|
files?: Array<{
|
|
28
68
|
name: string;
|
|
29
69
|
size?: number;
|
|
@@ -33,6 +73,7 @@ export interface TemplateMessage {
|
|
|
33
73
|
export interface FetchHistoryOptions {
|
|
34
74
|
limit?: number;
|
|
35
75
|
maxContextLength?: number;
|
|
76
|
+
includeHighlights?: boolean;
|
|
36
77
|
currentTraceId?: string;
|
|
37
78
|
}
|
|
38
79
|
export interface IConversationHistoryProvider {
|
|
@@ -40,6 +81,8 @@ export interface IConversationHistoryProvider {
|
|
|
40
81
|
created: boolean;
|
|
41
82
|
}>;
|
|
42
83
|
fetchHistory(threadId: string, options?: FetchHistoryOptions): Promise<ConversationThread>;
|
|
84
|
+
fetchThreadState?(threadId: string): Promise<ConversationThreadState | undefined>;
|
|
85
|
+
fetchHighlights?(threadId: string): Promise<ConversationHighlight[] | undefined>;
|
|
43
86
|
saveUserMessage(threadId: string, text: string, userId?: string, metadata?: Record<string, unknown>): Promise<{
|
|
44
87
|
id: string;
|
|
45
88
|
firstMessage: boolean;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CommandRunner, GlobalCrewxInfo, ShortcutProgressEvent } from './types';
|
|
2
|
+
export interface DetectGlobalCrewxOptions {
|
|
3
|
+
env: NodeJS.ProcessEnv;
|
|
4
|
+
cwd: string;
|
|
5
|
+
run: CommandRunner;
|
|
6
|
+
}
|
|
7
|
+
export declare function detectGlobalCrewx(opts: DetectGlobalCrewxOptions): Promise<GlobalCrewxInfo>;
|
|
8
|
+
export interface EnsureGlobalCrewxOptions {
|
|
9
|
+
env: NodeJS.ProcessEnv;
|
|
10
|
+
cwd: string;
|
|
11
|
+
run: CommandRunner;
|
|
12
|
+
targetVersion: string;
|
|
13
|
+
currentInfo?: GlobalCrewxInfo;
|
|
14
|
+
installRoot?: string;
|
|
15
|
+
onProgress?: (event: ShortcutProgressEvent) => void;
|
|
16
|
+
}
|
|
17
|
+
export declare function ensureGlobalCrewx(opts: EnsureGlobalCrewxOptions): Promise<{
|
|
18
|
+
info: GlobalCrewxInfo;
|
|
19
|
+
}>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { getShortcutStatus, installShortcut, uninstallShortcut, dismissShortcutNotice, } from './install';
|
|
2
|
+
export { ShortcutError, type ShortcutState, type DesktopSource, type GlobalCrewxInfo, type ShortcutStatus, type ShortcutInstallResult, type ShortcutProgressPhase, type ShortcutProgressEvent, type ShortcutEnvOptions, type InstallShortcutOptions, type ShortcutErrorCode, type CommandResult, type CommandRunner, type CommandRunOptions, type ShortcutFsLike, } from './types';
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
'use strict';var d=require('path'),crypto=require('crypto'),fs=require('fs'),os=require('os'),child_process=require('child_process'),module$1=require('module');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var d__namespace=/*#__PURE__*/_interopNamespace(d);var D=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var f=class extends Error{code;constructor(t,n){super(`${t}: ${n}`),this.code=t,this.name="ShortcutError";}};var X={existsSync:e=>fs.existsSync(e),readFileSync:e=>fs.readFileSync(e,"utf8"),readBinaryFileSync:e=>new Uint8Array(fs.readFileSync(e)),writeFileSync:(e,t)=>fs.writeFileSync(e,t,"utf8"),mkdirSync:e=>{fs.mkdirSync(e,{recursive:true});},unlinkSync:e=>{fs.unlinkSync(e);}},G=os.homedir;function _(e){return typeof e!="string"?void 0:e.trim()||void 0}function N(e){return _(e)?.toLowerCase()??""}function v(e){try{return fs.statSync(e).isFile()}catch{return false}}function Le(e,t){if(e===t)return true;let n=d__namespace.default.relative(e,t);return n!==""&&!n.startsWith("..")&&!d__namespace.default.isAbsolute(n)}function ke(e,t){if(d__namespace.default.basename(e)!==".bin")return false;let n=d__namespace.default.dirname(e);if(d__namespace.default.basename(n)!=="node_modules")return false;let r=d__namespace.default.dirname(n);return Le(r,t)}function U(e,t={}){if(e.includes("/")||e.includes("\\")||d__namespace.default.isAbsolute(e))return e;let n=t.platform??process.platform,r=t.env??process.env,i=d__namespace.default.resolve(t.cwd??process.cwd()),l=(t.resolution??"global_first")==="global_first",o=r.PATH??r.Path??process.env.PATH??process.env.Path??"",s=n==="win32"?";":":",a=o.split(s).map(u=>u.trim()).filter(Boolean),c=d__namespace.default.extname(e).length>0,h=r.PATHEXT??r.Pathext??process.env.PATHEXT??process.env.Pathext??".EXE;.CMD;.BAT;.COM",m=n==="win32"?c?[""]:h.split(";").map(u=>u.trim()).filter(Boolean).map(u=>u.startsWith(".")?u:`.${u}`):[""];for(let u of a){let p=d__namespace.default.resolve(i,u);if(!(l&&ke(p,i)))for(let w of m){let y=N(w),g=w.toUpperCase();for(let k of [w,y,g]){let H=d__namespace.default.join(p,`${e}${k}`);if(v(H))return H}}}return e}function _e(e){if(!v(e))return null;try{let t=fs.readFileSync(e,"utf8"),n=d__namespace.default.dirname(e),r=[];for(let s of t.matchAll(/"([^"\r\n]*)"/g)){let h=(s[1]??"").match(/%~?dp0%?\s*[\\/]*(.*)$/i)?.[1]?.trim();if(!h)continue;let m=h.replace(/[\\/]+/g,d__namespace.default.sep).replace(/^[\\/]+/,""),u=d__namespace.default.resolve(n,m);v(u)&&r.push(u);}let i=[],l=new Map;for(let s of t.matchAll(/SET\s+"(\w+)=%~?dp0%?[\\/]?([^"]+)"/gi)){let a=s[1].toUpperCase(),c=s[2].trim().replace(/[\\/]+/g,d__namespace.default.sep).replace(/^[\\/]+/,"");l.set(a,d__namespace.default.resolve(n,c));}for(let s of t.split(/\r?\n/))if(s.includes("%*"))for(let a of s.matchAll(/"%(\w+)%"/g)){let c=l.get(a[1].toUpperCase());c&&v(c)&&i.push(c);}let o=s=>s.find(a=>{let c=N(d__namespace.default.basename(a));return c!=="node.exe"&&c!=="node"})??null;return o(i)??o(r)}catch{return null}}function Ne(e,t){if(typeof t=="string")return _(t)||null;if(!t||typeof t!="object")return null;if(e){let n=t[e],r=typeof n=="string"?_(n):void 0;if(r)return r}for(let n of Object.values(t)){let r=typeof n=="string"?_(n):void 0;if(r)return r}return null}function Oe(e,t){if(!t)return null;let n=d__namespace.default.dirname(e),r=[d__namespace.default.resolve(n,"..",t),d__namespace.default.resolve(n,"node_modules",t)];for(let i of r){let l=d__namespace.default.join(i,"package.json");if(v(l))try{let o=JSON.parse(fs.readFileSync(l,"utf8")),s=Ne(t,o.bin);if(!s)continue;let a=d__namespace.default.resolve(i,s);if(v(a))return a}catch{}}return null}function be(e){let t=e.platform??process.platform,n=e.env??process.env,r=e.execPath??process.execPath,i=e.cwd,l=e.resolution;if(t!=="win32")return {command:U(e.command,{cwd:i,env:n,platform:t,resolution:l}),leadingArgv:[],resolution:"direct"};let o=U(e.command,{cwd:i,env:n,platform:t,resolution:l}),s=N(d__namespace.default.extname(o));if(s===".js"||s===".cjs"||s===".mjs")return {command:r,leadingArgv:[o],resolution:"node-entrypoint",windowsHide:true};if(s===".cmd"||s===".bat"){let a=_e(o)??Oe(o,e.packageName);return a?N(d__namespace.default.extname(a))===".exe"?{command:a,leadingArgv:[],resolution:"exe-entrypoint",windowsHide:true}:{command:r,leadingArgv:[a],resolution:"node-entrypoint",windowsHide:true}:{command:o,leadingArgv:[],resolution:"unresolved-wrapper"}}return {command:o,leadingArgv:[],resolution:"direct"}}function Ae(e){if(e.candidate.resolution!=="unresolved-wrapper")return {command:e.candidate.command,leadingArgv:e.candidate.leadingArgv,resolution:e.candidate.resolution,windowsHide:e.candidate.windowsHide};throw new Error(`${d__namespace.default.basename(e.candidate.command)} wrapper resolved, but no executable/Node entrypoint could be resolved without shell execution.`)}function J(e){let t=be(e);return Ae({candidate:t})}function K(e,t){return {command:e.command,argv:[...e.leadingArgv,...t],resolution:e.resolution,shell:e.shell,windowsHide:e.windowsHide}}var z=3e4;function De(e){if(typeof e.pid!="number"){e.kill();return}if(process.platform==="win32"){child_process.spawn("taskkill",["/pid",String(e.pid),"/t","/f"],{windowsHide:true}).on("error",()=>{});return}try{process.kill(-e.pid,"SIGKILL");}catch{e.kill("SIGKILL");}}var Q=(e,t,n={})=>new Promise((r,i)=>{let l=n.env??process.env,o=process.platform,s;try{let p=J({command:e,platform:o,env:l,cwd:n.cwd,allowShellFallback:!1});s=K(p,t);}catch(p){i(p instanceof Error?p:new Error(String(p)));return}let a=child_process.spawn(s.command,s.argv,{cwd:n.cwd,env:l,shell:s.shell,windowsHide:s.windowsHide??true,detached:o!=="win32"}),c="",h="",m=false,u=setTimeout(()=>{m||(m=true,De(a),i(new Error(`Command timed out after ${n.timeoutMs??z}ms: ${e} ${t.join(" ")}`)));},n.timeoutMs??z);a.stdout?.on("data",p=>{c+=p.toString();}),a.stderr?.on("data",p=>{h+=p.toString();}),a.on("error",p=>{m||(m=true,clearTimeout(u),i(p));}),a.on("close",p=>{m||(m=true,clearTimeout(u),r({code:p??0,stdout:c,stderr:h}));});});function Fe(){try{return (typeof D=="function"?D:module$1.createRequire(__filename)).resolve("@crewx/sdk/package.json")}catch{return null}}function Me(){let e=[Fe(),d.join(__dirname,"../../package.json"),d.join(__dirname,"../../../package.json")].filter(t=>!!t);for(let t of e)try{let n=JSON.parse(fs.readFileSync(t,"utf8"));if(n.name==="@crewx/sdk"&&n.version)return n.version}catch{}return "0.0.0"}var Z=Me();var P=d__namespace.win32;function W(e){return P.join(e,".crewx")}function te(e){return P.join(W(e),"shortcut.json")}function ne(e){return P.join(W(e),"launcher.json")}function re(e){return P.join(W(e),"bin","crewx-launcher.cmd")}function oe(e){return P.join(e,"CrewX.lnk")}function T(e,t){return P.normalize(e).toLowerCase()===P.normalize(t).toLowerCase()}var Be="[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; [Environment]::GetFolderPath('DesktopDirectory')";async function se(e){try{let n=await e.run("powershell",["-NoProfile","-NonInteractive","-Command",Be],{env:e.env}),r=n.stdout.trim();if(n.code===0&&r)return {dir:r,source:"known-folder"}}catch{}let t=e.env.USERPROFILE||e.env.Userprofile||e.homedir();return t?{dir:P.join(t,"Desktop"),source:"fallback"}:null}function F(e,t){let n=P.resolve(t,"node_modules",".bin").toLowerCase();return e.split(";").filter(r=>r?P.resolve(r).toLowerCase()!==n:true).join(";")}function ie(e){return e?/\\Program Files( \(x86\))?\\/i.test(e)&&/crewx/i.test(e):false}function $e(e,t){let n=a=>{let[c,...h]=a.split("-"),m=h.join("-")||void 0;return {parts:(c??"").split(".").map(p=>Number.parseInt(p,10)||0),pre:m}},r=n(e),i=n(t),l=Math.max(r.parts.length,i.parts.length);for(let a=0;a<l;a++){let c=r.parts[a]??0,h=i.parts[a]??0;if(c!==h)return c<h?-1:1}if(r.pre===i.pre)return 0;if(!r.pre&&i.pre)return 1;if(r.pre&&!i.pre)return -1;let o=Number.parseInt(r.pre.match(/(\d+)$/)?.[1]??"",10),s=Number.parseInt(i.pre.match(/(\d+)$/)?.[1]??"",10);return !Number.isNaN(o)&&!Number.isNaN(s)&&o!==s?o<s?-1:1:r.pre<i.pre?-1:r.pre>i.pre?1:0}function C(e,t){return $e(e,t)<0}var ce=d__namespace.win32,le=1;function ue(e,t){if(!e.existsSync(t))return null;try{let n=JSON.parse(e.readFileSync(t));return {schema:n.schema??le,shortcutPath:n.shortcutPath,version:n.version,iconHash:typeof n.iconHash=="string"?n.iconHash:void 0,owned:!!n.owned,declined:!!n.declined,desktopSource:n.desktopSource,updatedAt:n.updatedAt}}catch{return null}}function O(e,t,n){let r={schema:le,...n,updatedAt:new Date().toISOString()};e.mkdirSync(ce.dirname(t)),e.writeFileSync(t,JSON.stringify(r,null,2));}function b(e,t){if(!e.existsSync(t))return null;try{let n=JSON.parse(e.readFileSync(t));return {schema:n.schema??0,binPath:n.binPath,updatedAt:n.updatedAt}}catch{return null}}function de(e,t,n){e.mkdirSync(ce.dirname(t)),e.writeFileSync(t,JSON.stringify(n,null,2));}var He=d__namespace.win32,x=1;function Ve(e){return e.replace(/%/g,"%%")}function Xe(e){return ["@echo off","setlocal DisableDelayedExpansion","chcp 65001 >nul","",'set "CREWX_WORKDIR=%USERPROFILE%\\crewx"','if not exist "%CREWX_WORKDIR%" mkdir "%CREWX_WORKDIR%" >nul 2>nul','cd /d "%CREWX_WORKDIR%"',"",'set "CREWX_PORT_EFFECTIVE=%CREWX_PORT%"','if "%CREWX_PORT_EFFECTIVE%"=="" set "CREWX_PORT_EFFECTIVE=8150"','set "CREWX_HEALTH_URL=http://127.0.0.1:%CREWX_PORT_EFFECTIVE%/api/v1/health"','set "CREWX_ORIGIN_URL=http://127.0.0.1:%CREWX_PORT_EFFECTIVE%/"',"",e.bakedBinPath?`set "CREWX_FALLBACK_BIN=${Ve(e.bakedBinPath)}"`:'set "CREWX_FALLBACK_BIN="','set "CREWX_RESOLVED_BIN=%CREWX_BIN%"','if "%CREWX_RESOLVED_BIN%"=="" set "CREWX_RESOLVED_BIN=%CREWX_FALLBACK_BIN%"','if "%CREWX_RESOLVED_BIN%"=="" (',` for /f "delims=" %%I in ('where crewx 2^>nul') do (`,' if not defined CREWX_RESOLVED_BIN set "CREWX_RESOLVED_BIN=%%I"'," )",")","",'powershell -NoProfile -NonInteractive -Command "try { $r = Invoke-WebRequest -Uri $env:CREWX_HEALTH_URL -TimeoutSec 1 -UseBasicParsing; if ($r.StatusCode -eq 200) { exit 0 } else { exit 1 } } catch { exit 1 }"',"if %ERRORLEVEL% EQU 0 (",' start "" "%CREWX_ORIGIN_URL%"'," exit /b 0",")","",'if "%CREWX_RESOLVED_BIN%"=="" ('," echo CrewX executable not found. Please reinstall the desktop shortcut."," pause"," exit /b 1",")","",'start "CrewX" /min "%CREWX_RESOLVED_BIN%"',""].join(`\r
|
|
2
|
+
`)}function fe(e){let t=b(e.fs,e.launcherManifestPath),n=!!t&&t.schema>=x&&e.fs.existsSync(e.wrapperPath),r=n&&!t.binPath&&!!e.bakedBinPath;if(n&&!r)return {wrapperPath:e.wrapperPath,wrote:false,schema:t.schema};let l=Xe({bakedBinPath:e.bakedBinPath});try{e.fs.mkdirSync(He.dirname(e.wrapperPath)),e.fs.writeFileSync(e.wrapperPath,l),de(e.fs,e.launcherManifestPath,{schema:x,binPath:e.bakedBinPath,updatedAt:new Date().toISOString()});}catch(o){throw o instanceof f?o:new f("WRITE_DENIED",`Could not write launcher wrapper: ${o instanceof Error?o.message:String(o)}`)}return {wrapperPath:e.wrapperPath,wrote:true,schema:x}}var Ge=["$ws = New-Object -ComObject WScript.Shell","$sc = $ws.CreateShortcut($env:CREWX_LNK_PATH)","$sc.TargetPath = $env:CREWX_LNK_TARGET","if ($env:CREWX_LNK_WORKDIR) { $sc.WorkingDirectory = $env:CREWX_LNK_WORKDIR }","$sc.WindowStyle = 7","if ($env:CREWX_LNK_ICON) { $sc.IconLocation = $env:CREWX_LNK_ICON }","$sc.Save()"].join("; "),Ue=["[Console]::OutputEncoding = [System.Text.Encoding]::UTF8","$ws = New-Object -ComObject WScript.Shell","$sc = $ws.CreateShortcut($env:CREWX_LNK_PATH)","[PSCustomObject]@{ TargetPath = $sc.TargetPath; WorkingDirectory = $sc.WorkingDirectory; IconLocation = $sc.IconLocation } | ConvertTo-Json -Compress"].join("; ");async function he(e){let t={...e.env,CREWX_LNK_PATH:e.shortcutPath,CREWX_LNK_TARGET:e.targetPath,CREWX_LNK_WORKDIR:e.workingDirectory??"",CREWX_LNK_ICON:e.iconPath??""},n;try{n=await e.run("powershell",["-NoProfile","-NonInteractive","-Command",Ge],{env:t});}catch(r){throw new f("POWERSHELL_UNAVAILABLE",`Could not run PowerShell: ${r instanceof Error?r.message:String(r)}`)}if(n.code!==0)throw new f("POWERSHELL_UNAVAILABLE",`Failed to create desktop shortcut: ${n.stderr||n.stdout}`)}function me(e){let t=e.trim(),n=t.lastIndexOf(",");return n!==-1&&/^-?\d+$/.test(t.slice(n+1).trim())&&(t=t.slice(0,n).trim()),t.length>=2&&t.startsWith('"')&&t.endsWith('"')&&(t=t.slice(1,-1).trim()),t}async function ge(e){try{let t={...e.env,CREWX_LNK_PATH:e.shortcutPath},n=await e.run("powershell",["-NoProfile","-NonInteractive","-Command",Ue],{env:t});if(n.code!==0||!n.stdout.trim())return null;let r=JSON.parse(n.stdout.trim());return {targetPath:r.TargetPath??"",workingDirectory:r.WorkingDirectory??"",iconLocation:r.IconLocation??""}}catch{return null}}var B=d__namespace.win32;async function I(e){let t=F(e.env.PATH??e.env.Path??"",e.cwd),n={...e.env,PATH:t,Path:t},r;try{r=await e.run("npm",["list","-g","crewx","--depth=0","--json"],{env:n});}catch{return {installed:false}}let i;try{i=JSON.parse(r.stdout||"{}");}catch{return {installed:false}}let l=i.dependencies?.crewx;if(!l?.version)return {installed:false};let o;try{let a=await e.run("npm",["prefix","-g"],{env:n});a.code===0&&(o=a.stdout.trim()||void 0);}catch{}let s=o?B.join(o,"crewx.cmd"):void 0;return {installed:true,version:l.version,binPath:s,prefix:o}}var je=/EACCES|EPERM|EROFS/,Je=/ENOTFOUND|ETIMEDOUT|ECONNREFUSED|network|registry/i,Ke=/^\d+\.\d+\.\d+/;function ze(e){return !!e&&e!=="0.0.0"&&Ke.test(e)}var M=10*6e4;async function Se(e){if(!ze(e.targetVersion))throw new f("GLOBAL_INSTALL_FAILED",`RUNNING_VERSION_UNKNOWN: cannot reliably determine the running crewx version to install (got ${JSON.stringify(e.targetVersion)}); refusing to fall back to crewx@latest`);if(e.currentInfo?.installed&&e.currentInfo.version&&!C(e.currentInfo.version,e.targetVersion))return {info:e.currentInfo};let t=F(e.env.PATH??e.env.Path??"",e.cwd),n={...e.env,PATH:t,Path:t},r=`crewx@${e.targetVersion}`;e.onProgress?.({phase:"global-install",message:`Installing crewx globally (npm install -g ${r})`});let i;try{i=await e.run("npm",["install","-g",r,"--no-audit","--no-fund"],{env:n,timeoutMs:M});}catch(o){throw new f("NPM_UNAVAILABLE",`Could not run npm: ${o instanceof Error?o.message:String(o)}`)}if(i.code===0)return {info:await I({env:n,cwd:e.cwd,run:e.run})};let l=`${i.stdout}
|
|
3
|
+
${i.stderr}`;if(je.test(l)){e.onProgress?.({phase:"global-install",message:"Permission denied \u2014 retrying with a user-scoped npm prefix"});let o=e.env.LOCALAPPDATA||B.join(e.env.USERPROFILE??"","AppData","Local"),s={...n,npm_config_prefix:B.join(o,"crewx","npm")},a;try{a=await e.run("npm",["install","-g",r,"--no-audit","--no-fund"],{env:s,timeoutMs:M});}catch(c){throw new f("NPM_PERMISSION_DENIED",`Retry with user-scoped prefix failed: ${c instanceof Error?c.message:String(c)}`)}if(a.code===0)return {info:await I({env:s,cwd:e.cwd,run:e.run})};throw new f("NPM_PERMISSION_DENIED",`npm install -g failed after user-scoped prefix retry: ${a.stderr||a.stdout}`)}if(Je.test(l)){if(!e.installRoot)throw new f("OFFLINE_NO_SOURCE","The npm registry is unreachable and no local installRoot was provided for an offline install");e.onProgress?.({phase:"global-install",message:`Registry unreachable \u2014 installing offline from ${e.installRoot}`});let o;try{o=await e.run("npm",["install","-g",e.installRoot,"--offline","--no-audit","--no-fund"],{env:n,timeoutMs:M});}catch(s){throw new f("GLOBAL_INSTALL_FAILED",`Offline install failed: ${s instanceof Error?s.message:String(s)}`)}if(o.code===0)return {info:await I({env:n,cwd:e.cwd,run:e.run})};throw new f("GLOBAL_INSTALL_FAILED",`Offline install failed: ${o.stderr||o.stdout}`)}throw new f("GLOBAL_INSTALL_FAILED",l.trim()||`npm install -g ${r} failed`)}function Qe(e){return e.run??Q}function Ye(e){return e.fs??X}async function A(e){let t=e.platform??process.platform,n=e.env??process.env,r=e.homedir??G,i=Qe(e),l=Ye(e),o=e.runningVersion??Z,s=e.cwd??process.cwd(),a=r(),c=te(a),h=ne(a),m=re(a),u=null;t==="win32"&&(u=await se({env:n,homedir:r,run:i}));let p=u?oe(u.dir):null;return {platform:t,env:n,homedir:r,run:i,fs:l,runningVersion:o,cwd:s,installRoot:e.installRoot,shortcutManifestPath:c,launcherManifestPath:h,wrapperPath:m,desktop:u,shortcutPath:p}}function Pe(e){return e?d__namespace.win32.normalize(e).toLowerCase().endsWith(`${d__namespace.win32.sep}bin${d__namespace.win32.sep}crewx.ico`):false}function $(e,t){let n=e.readBinaryFileSync;if(n)try{return crypto.createHash("sha256").update(n(t)).digest("hex")}catch{return}}async function Ze(e){try{await e.run("ie4uinit.exe",["-show"],{env:e.env});}catch{}}async function E(e){if(e.platform!=="win32")return {supported:false,state:"unsupported",globalCrewx:null,runningVersion:e.runningVersion,errors:[],manifest:null,iconStale:false};let t=[];e.desktop||t.push("NO_DESKTOP_DIR: could not resolve the Windows Desktop directory");let n=ue(e.fs,e.shortcutManifestPath),r=b(e.fs,e.launcherManifestPath),i=await I({env:e.env,cwd:e.cwd,run:e.run}),l=e.shortcutPath?e.fs.existsSync(e.shortcutPath):false,o,s=false,a,c;if(!l)o=n?.declined?"declined":"not-installed";else {let h=!!n?.owned&&!!e.shortcutPath&&n.shortcutPath===e.shortcutPath,m=false,u=e.shortcutPath?await ge({run:e.run,env:e.env,shortcutPath:e.shortcutPath}):null;if(h||(u&&T(u.targetPath,e.wrapperPath)?h=true:u&&ie(u.targetPath)&&(m=true)),m)o="foreign",t.push("NSIS_PRESENT: an NSIS-installed CrewX shortcut was detected");else if(!h)o="foreign";else if(n?.version&&C(e.runningVersion,n.version))o="superseded",t.push(`SUPERSEDED: running version ${e.runningVersion} is older than the installed shortcut's version ${n.version}; refusing to modify it`);else {let p=!r||r.schema<x||!e.fs.existsSync(e.wrapperPath);if(u){let w=me(u.iconLocation);if(!(!!w&&e.fs.existsSync(w)))s=true;else {a=w;let g=Ee(i,e.fs);g?T(w,g)?(c=$(e.fs,w),s=!c||n?.iconHash!==c):s=true:Pe(w)?(c=$(e.fs,w),s=!c||n?.iconHash!==c):s=true;}}o=p||s?"stale":"installed";}}return {supported:true,state:o,shortcutPath:e.shortcutPath??void 0,desktopDir:e.desktop?.dir,desktopSource:e.desktop?.source,wrapperPath:e.wrapperPath,wrapperSchema:r?.schema,globalCrewx:i.installed?i:{installed:false},runningVersion:e.runningVersion,errors:t,manifest:n,iconStale:s,iconPath:a,iconHash:c}}function Ee(e,t){if(!e?.installed||!e.prefix)return;let n=d__namespace.win32.join(e.prefix,"node_modules","crewx","bin","crewx.ico");return t.existsSync(n)?n:void 0}function R(e){let{manifest:t,iconStale:n,iconPath:r,iconHash:i,...l}=e;return l}async function et(e={}){let t=await A(e),n=await E(t);return R(n)}async function tt(e={}){let t=await A(e);e.onProgress?.({phase:"detect",message:"Checking current shortcut status"});let n=await E(t),r=R(n);if(!r.supported)return {...r,changed:false,installedGlobal:false};if(r.state==="superseded")return {...r,changed:false,installedGlobal:false};if(r.state==="foreign"){if(n.errors.some(g=>g.startsWith("NSIS_PRESENT")))throw new f("NSIS_PRESENT",`An NSIS-installed CrewX shortcut was detected at ${r.shortcutPath}`);if(!e.force)throw new f("FOREIGN_SHORTCUT",`An existing shortcut at ${r.shortcutPath} is not managed by CrewX`)}if(!t.desktop||!t.shortcutPath)throw new f("NO_DESKTOP_DIR","Could not resolve the Windows Desktop directory");let i=false,l=false,o=r.globalCrewx,s=[],a=n.manifest?.iconHash,c=false;if(!!o?.installed&&!!o.version&&C(o.version,t.runningVersion)||!o?.installed&&r.state!=="installed"){let g=await Se({env:t.env,cwd:t.cwd,run:t.run,targetVersion:t.runningVersion,currentInfo:o??void 0,installRoot:t.installRoot,onProgress:e.onProgress});o=g.info,l=g.info.installed,i=true,l||s.push(`GLOBAL_INSTALL_UNCONFIRMED: npm install -g crewx@${t.runningVersion} exited successfully but a follow-up check could not confirm the global install`);}if(e.onProgress?.({phase:"wrapper",message:"Ensuring launcher wrapper"}),fe({fs:t.fs,wrapperPath:t.wrapperPath,launcherManifestPath:t.launcherManifestPath,bakedBinPath:o?.binPath}).wrote&&(i=true),!((r.state==="installed"||r.state==="stale")&&!n.iconStale)){let g=Ee(o,t.fs)??(n.iconPath&&Pe(n.iconPath)&&t.fs.existsSync(n.iconPath)?n.iconPath:void 0);if(n.iconStale&&!g)throw new f("ICON_UNAVAILABLE",`Could not locate the global CrewX icon (bin\\crewx.ico) to repair the desktop shortcut at ${t.shortcutPath}; the existing shortcut was left untouched`);e.onProgress?.({phase:"lnk",message:"Creating desktop shortcut"}),await he({run:t.run,env:t.env,shortcutPath:t.shortcutPath,targetPath:t.wrapperPath,iconPath:g}),i=true,c=n.iconStale;let k=g?$(t.fs,g):void 0;k&&(a=k);}i&&O(t.fs,t.shortcutManifestPath,{shortcutPath:t.shortcutPath,version:t.runningVersion,owned:true,declined:false,desktopSource:t.desktop.source,iconHash:a}),c&&await Ze(t);let w=await E(t),y=R(w);return {...y,errors:[...y.errors,...s],changed:i,installedGlobal:l}}async function nt(e={}){let t=await A(e),n=await E(t),r=R(n);if(!r.supported)return r;if((r.state==="installed"||r.state==="stale")&&t.shortcutPath)try{t.fs.unlinkSync(t.shortcutPath);}catch{}O(t.fs,t.shortcutManifestPath,{shortcutPath:void 0,version:n.manifest?.version,owned:false,declined:true,desktopSource:void 0,iconHash:void 0});let i=await E(t);return R(i)}async function rt(e={}){let t=await A(e),n=await E(t),r=R(n);if(!r.supported)return r;O(t.fs,t.shortcutManifestPath,{shortcutPath:n.manifest?.shortcutPath,version:n.manifest?.version,owned:n.manifest?.owned??false,declined:true,desktopSource:n.manifest?.desktopSource,iconHash:n.manifest?.iconHash});let i=await E(t);return R(i)}exports.ShortcutError=f;exports.dismissShortcutNotice=rt;exports.getShortcutStatus=et;exports.installShortcut=tt;exports.uninstallShortcut=nt;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type InstallShortcutOptions, type ShortcutEnvOptions, type ShortcutInstallResult, type ShortcutStatus } from './types';
|
|
2
|
+
export declare function getShortcutStatus(options?: ShortcutEnvOptions): Promise<ShortcutStatus>;
|
|
3
|
+
export declare function installShortcut(options?: InstallShortcutOptions): Promise<ShortcutInstallResult>;
|
|
4
|
+
export declare function uninstallShortcut(options?: ShortcutEnvOptions): Promise<ShortcutStatus>;
|
|
5
|
+
export declare function dismissShortcutNotice(options?: ShortcutEnvOptions): Promise<ShortcutStatus>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { CommandRunner } from './types';
|
|
2
|
+
export interface WriteLnkOptions {
|
|
3
|
+
run: CommandRunner;
|
|
4
|
+
env: NodeJS.ProcessEnv;
|
|
5
|
+
shortcutPath: string;
|
|
6
|
+
targetPath: string;
|
|
7
|
+
workingDirectory?: string;
|
|
8
|
+
iconPath?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function writeLnk(opts: WriteLnkOptions): Promise<void>;
|
|
11
|
+
export interface LnkInfo {
|
|
12
|
+
targetPath: string;
|
|
13
|
+
workingDirectory: string;
|
|
14
|
+
iconLocation: string;
|
|
15
|
+
}
|
|
16
|
+
export interface ReadLnkOptions {
|
|
17
|
+
run: CommandRunner;
|
|
18
|
+
env: NodeJS.ProcessEnv;
|
|
19
|
+
shortcutPath: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function normalizeIconLocation(raw: string): string;
|
|
22
|
+
export declare function readLnkTarget(opts: ReadLnkOptions): Promise<LnkInfo | null>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { DesktopSource, ShortcutFsLike } from './types';
|
|
2
|
+
export declare const MANIFEST_SCHEMA_VERSION = 1;
|
|
3
|
+
export interface ShortcutManifest {
|
|
4
|
+
schema: number;
|
|
5
|
+
shortcutPath?: string;
|
|
6
|
+
version?: string;
|
|
7
|
+
iconHash?: string;
|
|
8
|
+
owned: boolean;
|
|
9
|
+
declined: boolean;
|
|
10
|
+
desktopSource?: DesktopSource;
|
|
11
|
+
updatedAt?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface LauncherManifest {
|
|
14
|
+
schema: number;
|
|
15
|
+
binPath?: string;
|
|
16
|
+
updatedAt?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function readShortcutManifest(fs: ShortcutFsLike, manifestPath: string): ShortcutManifest | null;
|
|
19
|
+
export declare function writeShortcutManifest(fs: ShortcutFsLike, manifestPath: string, data: Omit<ShortcutManifest, 'schema' | 'updatedAt'>): void;
|
|
20
|
+
export declare function readLauncherManifest(fs: ShortcutFsLike, manifestPath: string): LauncherManifest | null;
|
|
21
|
+
export declare function writeLauncherManifest(fs: ShortcutFsLike, manifestPath: string, data: LauncherManifest): void;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export type ShortcutState = 'unsupported' | 'not-installed' | 'installed' | 'stale' | 'foreign' | 'superseded' | 'declined';
|
|
2
|
+
export type DesktopSource = 'known-folder' | 'fallback';
|
|
3
|
+
export interface GlobalCrewxInfo {
|
|
4
|
+
installed: boolean;
|
|
5
|
+
version?: string;
|
|
6
|
+
binPath?: string;
|
|
7
|
+
prefix?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ShortcutStatus {
|
|
10
|
+
supported: boolean;
|
|
11
|
+
state: ShortcutState;
|
|
12
|
+
shortcutPath?: string;
|
|
13
|
+
desktopDir?: string;
|
|
14
|
+
desktopSource?: DesktopSource;
|
|
15
|
+
wrapperPath?: string;
|
|
16
|
+
wrapperSchema?: number;
|
|
17
|
+
globalCrewx: GlobalCrewxInfo | null;
|
|
18
|
+
runningVersion: string;
|
|
19
|
+
errors: string[];
|
|
20
|
+
}
|
|
21
|
+
export interface ShortcutInstallResult extends ShortcutStatus {
|
|
22
|
+
changed: boolean;
|
|
23
|
+
installedGlobal: boolean;
|
|
24
|
+
}
|
|
25
|
+
export type ShortcutProgressPhase = 'detect' | 'global-install' | 'wrapper' | 'lnk';
|
|
26
|
+
export interface ShortcutProgressEvent {
|
|
27
|
+
phase: ShortcutProgressPhase;
|
|
28
|
+
message: string;
|
|
29
|
+
}
|
|
30
|
+
export interface CommandResult {
|
|
31
|
+
code: number;
|
|
32
|
+
stdout: string;
|
|
33
|
+
stderr: string;
|
|
34
|
+
}
|
|
35
|
+
export interface CommandRunOptions {
|
|
36
|
+
env?: NodeJS.ProcessEnv;
|
|
37
|
+
cwd?: string;
|
|
38
|
+
timeoutMs?: number;
|
|
39
|
+
}
|
|
40
|
+
export type CommandRunner = (command: string, args: string[], opts?: CommandRunOptions) => Promise<CommandResult>;
|
|
41
|
+
export interface ShortcutFsLike {
|
|
42
|
+
existsSync(path: string): boolean;
|
|
43
|
+
readFileSync(path: string): string;
|
|
44
|
+
readBinaryFileSync?: (path: string) => Uint8Array;
|
|
45
|
+
writeFileSync(path: string, data: string): void;
|
|
46
|
+
mkdirSync(path: string): void;
|
|
47
|
+
unlinkSync(path: string): void;
|
|
48
|
+
}
|
|
49
|
+
export interface ShortcutEnvOptions {
|
|
50
|
+
platform?: NodeJS.Platform;
|
|
51
|
+
env?: NodeJS.ProcessEnv;
|
|
52
|
+
homedir?: () => string;
|
|
53
|
+
run?: CommandRunner;
|
|
54
|
+
fs?: ShortcutFsLike;
|
|
55
|
+
runningVersion?: string;
|
|
56
|
+
cwd?: string;
|
|
57
|
+
}
|
|
58
|
+
export interface InstallShortcutOptions extends ShortcutEnvOptions {
|
|
59
|
+
force?: boolean;
|
|
60
|
+
onProgress?: (event: ShortcutProgressEvent) => void;
|
|
61
|
+
installRoot?: string;
|
|
62
|
+
}
|
|
63
|
+
export type ShortcutErrorCode = 'NOT_WINDOWS' | 'NO_DESKTOP_DIR' | 'NPM_UNAVAILABLE' | 'NPM_PERMISSION_DENIED' | 'OFFLINE_NO_SOURCE' | 'GLOBAL_INSTALL_FAILED' | 'POWERSHELL_UNAVAILABLE' | 'WRITE_DENIED' | 'FOREIGN_SHORTCUT' | 'NSIS_PRESENT' | 'ICON_UNAVAILABLE';
|
|
64
|
+
export declare class ShortcutError extends Error {
|
|
65
|
+
readonly code: ShortcutErrorCode;
|
|
66
|
+
constructor(code: ShortcutErrorCode, message: string);
|
|
67
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const SDK_VERSION: string;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { CommandRunner, DesktopSource } from './types';
|
|
2
|
+
export declare function crewxHomeDir(homedir: string): string;
|
|
3
|
+
export declare function shortcutManifestPath(homedir: string): string;
|
|
4
|
+
export declare function launcherManifestPath(homedir: string): string;
|
|
5
|
+
export declare function wrapperPath(homedir: string): string;
|
|
6
|
+
export declare function shortcutLnkPath(desktopDir: string): string;
|
|
7
|
+
export declare function samePath(a: string, b: string): boolean;
|
|
8
|
+
export interface ResolveDesktopDirOptions {
|
|
9
|
+
env: NodeJS.ProcessEnv;
|
|
10
|
+
homedir: () => string;
|
|
11
|
+
run: CommandRunner;
|
|
12
|
+
}
|
|
13
|
+
export interface ResolvedDesktopDir {
|
|
14
|
+
dir: string;
|
|
15
|
+
source: DesktopSource;
|
|
16
|
+
}
|
|
17
|
+
export declare function resolveDesktopDir(opts: ResolveDesktopDirOptions): Promise<ResolvedDesktopDir | null>;
|
|
18
|
+
export declare function filterWorkspaceLocalBin(pathValue: string, cwd: string): string;
|
|
19
|
+
export declare function looksLikeNsisInstall(targetPath: string): boolean;
|
|
20
|
+
export declare function compareVersions(a: string, b: string): -1 | 0 | 1;
|
|
21
|
+
export declare function isOlderVersion(a: string, b: string): boolean;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ShortcutFsLike } from './types';
|
|
2
|
+
export declare const WRAPPER_SCHEMA_VERSION = 1;
|
|
3
|
+
export interface BuildWrapperScriptOptions {
|
|
4
|
+
bakedBinPath?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function buildWrapperScript(opts: BuildWrapperScriptOptions): string;
|
|
7
|
+
export interface EnsureWrapperOptions {
|
|
8
|
+
fs: ShortcutFsLike;
|
|
9
|
+
wrapperPath: string;
|
|
10
|
+
launcherManifestPath: string;
|
|
11
|
+
bakedBinPath?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface EnsureWrapperResult {
|
|
14
|
+
wrapperPath: string;
|
|
15
|
+
wrote: boolean;
|
|
16
|
+
schema: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function ensureWrapper(opts: EnsureWrapperOptions): EnsureWrapperResult;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import {randomUUID}from'crypto';import*as D from'fs';import {existsSync,readFileSync,mkdirSync,writeFileSync,chmodSync,renameSync,unlinkSync}from'fs';import*as w from'path';import {join,dirname}from'path';import*as I from'os';var s=class extends Error{code;kind;status;constructor(e,n,r,o){super(o??`Account authentication request failed (${e})`),this.name="AccountAuthError",this.code=e,this.kind=n,this.status=r;}};var p=class extends Error{code="LOGIN_REQUIRED";constructor(){super("Login required \u2014 please log in again"),this.name="LoginRequiredError";}},d=class extends Error{code;constructor(e,n){super(n),this.name="SessionManagerError",this.code=e;}},u=class extends Error{code;constructor(e,n="auth.json is invalid \u2014 please log in again"){super(n),this.name="AuthJsonValidationError",this.code=e;}},c=class extends s{constructor(e){let n=e.startsWith("ACCOUNT_BASE_URL")?"CREWX_ACCOUNT_BASE_URL":e.startsWith("ACCOUNT_ISSUER")?"CREWX_ACCOUNT_ISSUER":"CREWX_MARKETPLACE_URL";super(e,"configuration",void 0,`${n} is missing or invalid \u2014 configure it and try again`),this.name="AccountConfigurationError";}};var b="CREWX_ACCOUNT_BASE_URL",L="CREWX_ACCOUNT_ISSUER",P="CREWX_MARKETPLACE_URL";function V(t,e,n,r=false){let o=t?.trim();if(!o)throw new c(e);try{let i=new URL(o);if(i.protocol!=="http:"&&i.protocol!=="https:"||i.username.length>0||i.password.length>0||i.hostname.length===0||i.search.length>0||i.hash.length>0||r&&i.pathname!=="/")throw new Error("invalid URL")}catch{throw new c(n)}return o.replace(/\/+$/,"")}function k(t=process.env){return V(t[b],"ACCOUNT_BASE_URL_MISSING","ACCOUNT_BASE_URL_INVALID",true)}function Y(t=process.env){return V(t[P],"MARKETPLACE_URL_MISSING","MARKETPLACE_URL_INVALID")}function C(t=process.env){let e=t[L]?.trim();if(!e)throw new c("ACCOUNT_ISSUER_MISSING");try{let n=new URL(e);if(n.protocol!=="http:"&&n.protocol!=="https:"||n.username.length>0||n.password.length>0||n.hostname.length===0||n.search.length>0||n.hash.length>0)throw new Error("invalid issuer")}catch{throw new c("ACCOUNT_ISSUER_INVALID")}return e}function R(t,e){return `${t.replace(/\/+$/,"")}/${e.replace(/^\/+/,"")}`}function J(){if(process.env.CREWX_HOME)try{return D.realpathSync(process.env.CREWX_HOME)}catch{return w.join(I.homedir(),".crewx")}return process.platform!=="win32"&&process.env.XDG_CONFIG_HOME?w.join(process.env.XDG_CONFIG_HOME,"crewx"):w.join(I.homedir(),".crewx")}var B="auth.json",v=2,G=["version","sub","email","access_token","refresh_token","expires_at","updated_at"];function h(t="auth.json is invalid \u2014 please log in again"){throw new u("AUTH_JSON_INVALID",t)}function oe(){throw new u("AUTH_JSON_LEGACY","auth.json uses an unsupported legacy format \u2014 please log in again")}function se(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function ie(t){try{return A(t),!0}catch{return false}}function A(t){if(!se(t))return h();if(t.version===1)return oe();if(t.version!==v)return h();let e=Object.keys(t);if(e.length!==G.length||e.some(r=>!G.includes(r))||typeof t.sub!="string"||t.sub.length===0||typeof t.email!="string"||t.email.length===0||typeof t.access_token!="string"||t.access_token.length===0||typeof t.refresh_token!="string"||t.refresh_token.length===0)return h();let n=t.expires_at;return typeof n!="number"||!Number.isSafeInteger(n)||n<0||typeof t.updated_at!="string"||t.updated_at.length===0||Number.isNaN(Date.parse(t.updated_at))?h():{version:v,sub:t.sub,email:t.email,access_token:t.access_token,refresh_token:t.refresh_token,expires_at:n,updated_at:t.updated_at}}function K(t){let e;try{e=JSON.parse(t);}catch{return h()}return A(e)}function q(t){return t??join(J(),B)}var f=class{configuredPath;constructor(e={}){this.configuredPath=typeof e=="string"?e:e.filePath;}path(){return q(this.configuredPath)}read(){let e=this.path();if(!existsSync(e))return null;try{return K(readFileSync(e,"utf8"))}catch(n){throw n instanceof u?n:new u("AUTH_JSON_INVALID")}}write(e){let n=A(e),r=this.path(),o=dirname(r);mkdirSync(o,{recursive:true,mode:448});let i=`${r}.tmp.${process.pid}.${randomUUID()}`;try{writeFileSync(i,JSON.stringify(n,null,2),{encoding:"utf8",mode:384}),chmodSync(i,384),renameSync(i,r),chmodSync(r,384);}catch{try{existsSync(i)&&unlinkSync(i);}catch{}throw new Error("Could not persist auth.json securely")}}clear(){let e=this.path();try{existsSync(e)&&unlinkSync(e);}catch{throw new Error("Could not clear auth.json")}}};function ce(t){let e=new f({filePath:t}).read();if(!e)throw new p;return e}function ae(t,e){new f({filePath:e}).write(t);}function ue(t){new f({filePath:t}).clear();}var W="/auth/v1/oauth/device/code",X="/auth/v1/oauth/token",$="/auth/v1/oauth/revoke",T="crewx-cli",m="urn:ietf:params:oauth:grant-type:device_code";function a(t){return typeof t=="string"&&t.trim().length>0}function S(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)?t:null}function he(t){let e=S(t),n=e?.error??e?.code;if(typeof n=="string")return n.toLowerCase();let r=S(n),o=r?.code??r?.error;return typeof o=="string"?o.toLowerCase():void 0}function pe(t){let e=S(t);if(!e||!a(e.device_code)||!a(e.user_code)||!a(e.verification_uri))throw new s("AUTH_RESPONSE_INVALID","protocol");let n=e.expires_in,r=e.interval;if(typeof n!="number"||!Number.isSafeInteger(n)||n<=0)throw new s("AUTH_RESPONSE_INVALID","protocol");if(e.verification_uri_complete!==void 0&&!a(e.verification_uri_complete))throw new s("AUTH_RESPONSE_INVALID","protocol");if(r!==void 0&&(typeof r!="number"||!Number.isSafeInteger(r)||r<0))throw new s("AUTH_RESPONSE_INVALID","protocol");let o={device_code:e.device_code,user_code:e.user_code,verification_uri:e.verification_uri,expires_in:n};return e.verification_uri_complete!==void 0&&(o.verification_uri_complete=e.verification_uri_complete),r!==void 0&&(o.interval=r),o}function de(t){let e=S(t),n=S(e?.account),r=e?.expires_in;if(!e||!a(e.access_token)||!a(e.refresh_token)||typeof r!="number"||!Number.isSafeInteger(r)||r<=0||!n||!a(n.sub)||!a(n.email))throw new s("AUTH_RESPONSE_INVALID","protocol");let o={access_token:e.access_token,refresh_token:e.refresh_token,expires_in:r,account:{sub:n.sub,email:n.email}};return typeof e.token_type=="string"&&e.token_type.length>0&&(o.token_type=e.token_type),typeof e.scope=="string"&&e.scope.length>0&&(o.scope=e.scope),o}var E=class{configuredBaseUrl;fetchImpl;timeoutMs;constructor(e={}){let n=typeof e=="string"?{baseUrl:e}:e;this.configuredBaseUrl=n.baseUrl===void 0?void 0:fe(n.baseUrl),this.fetchImpl=n.fetch??n.fetchImpl,this.timeoutMs=n.timeoutMs??1e4;}baseUrl(){return this.configuredBaseUrl!==void 0?this.configuredBaseUrl:k()}signal(e){if(!(e<=0||typeof AbortSignal>"u"||typeof AbortSignal.timeout!="function"))return AbortSignal.timeout(e)}async request(e,n,r,o={}){let i=R(this.baseUrl(),e),x=this.fetchImpl??globalThis.fetch;if(typeof x!="function")throw new s("AUTH_NETWORK_ERROR","network");let l;try{l=await x(i,{...n,signal:n.signal??this.signal(o.timeoutMs??this.timeoutMs)});}catch{throw new s("AUTH_NETWORK_ERROR","network")}if(o.parseBody===false){if(!l.ok)throw j(l.status,null,r);return}let y=null;try{y=await l.json();}catch{y=null;}if(!l.ok)throw j(l.status,y,r);return y}async requestDeviceCode(){let e=new URLSearchParams;e.set("client_id",T);let n=await this.request(W,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:e.toString()});return pe(n)}async requestToken(e){Ae(e);let n=new URLSearchParams;n.set("grant_type",e.grant_type),n.set("client_id",T),e.grant_type===m?n.set("device_code",e.device_code):n.set("refresh_token",e.refresh_token);let r=await this.request(X,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:n.toString()},e);return de(r)}async exchangeDeviceCode(e){return this.requestToken({grant_type:m,device_code:e})}async refreshToken(e){return this.requestToken({grant_type:"refresh_token",refresh_token:e})}async deviceCode(){return this.requestDeviceCode()}async getDeviceCode(){return this.requestDeviceCode()}async token(e){return this.requestToken(e)}async getToken(e){return this.requestToken(e)}async refresh(e){return this.refreshToken(e)}async refreshAccessToken(e){return this.refreshToken(e)}async revokeToken(e){if(!a(e))throw new s("AUTH_INPUT_INVALID","protocol");let n=new URLSearchParams;n.set("token",e),n.set("token_type_hint","refresh_token"),n.set("client_id",T),await this.request($,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:n.toString()},void 0,{parseBody:false,timeoutMs:3e3});}async revoke(e){return this.revokeToken(e)}};function fe(t){if(typeof t!="string"||!t.trim())throw new c("ACCOUNT_BASE_URL_MISSING");try{let e=new URL(t.trim());if(e.protocol!=="http:"&&e.protocol!=="https:"||e.username.length>0||e.password.length>0||e.hostname.length===0||e.pathname!=="/"||e.search.length>0||e.hash.length>0)throw new Error("invalid URL")}catch{throw new c("ACCOUNT_BASE_URL_INVALID")}return t.trim().replace(/\/+$/,"")}function Ae(t){if(!t||t.grant_type!==m&&t.grant_type!=="refresh_token"||t.grant_type===m&&!a(t.device_code)||t.grant_type==="refresh_token"&&!a(t.refresh_token))throw new s("AUTH_INPUT_INVALID","protocol")}function j(t,e,n){let r=he(e);if(t>=500)return new s("AUTH_SERVER_ERROR","server",t);if(n?.grant_type==="refresh_token"&&(r==="invalid_grant"||t===401))return new s("INVALID_REFRESH_TOKEN","invalid_refresh",t);if(n?.grant_type===m){if(r==="authorization_pending")return new s("AUTHORIZATION_PENDING","pending",t);if(r==="slow_down")return new s("SLOW_DOWN","pending",t);if(r==="access_denied")return new s("ACCESS_DENIED","denied",t);if(r==="expired_token")return new s("EXPIRED_TOKEN","expired",t)}return new s("AUTH_HTTP_ERROR","http",t)}var U=class{client;store;refreshSkewSeconds;now;nowSecondsOverride;refreshPromise=null;constructor(e={},n){let r=_e(e)?e:void 0,o=r?{}:e;this.client=r??o.client??o.authClient??new E,this.store=o.store??o.storage??n??new f,this.refreshSkewSeconds=o.refreshSkewSeconds??60,this.now=o.now??(()=>Date.now()),this.nowSecondsOverride=o.nowSeconds;}getSession(){return this.readSession()}isLoggedIn(){return this.readSession()!==null}async getAccessToken(){let e=this.requireSession();return e.expires_at>this.epochSeconds()+this.refreshSkewSeconds?e.access_token:(await this.refreshSession(e)).access_token}async getValidAccessToken(){return this.getAccessToken()}async getToken(){return this.getAccessToken()}async refresh(){return this.refreshSession(this.requireSession())}async loginWithDeviceCode(e){let n=await this.client.exchangeDeviceCode(e);return this.persistTokenResponse(n)}async login(e){return this.loginWithDeviceCode(e)}async setSession(e){return this.persistTokenResponse(e)}clear(){this.store.clear();}async withAccessToken(e){return e(await this.getAccessToken())}readSession(){try{let e=this.store.read();if(e===null)return null;let n=A(e);return F(n.access_token,n.sub),n}catch(e){throw e instanceof u?new p:e}}requireSession(){let e=this.readSession();if(!e)throw new p;return e}epochSeconds(){return this.nowSecondsOverride?.()??Math.floor(this.now()/1e3)}refreshSession(e){if(this.refreshPromise)return this.refreshPromise;let n;return n=this.performRefresh(e).finally(()=>{this.refreshPromise===n&&(this.refreshPromise=null);}),this.refreshPromise=n,n}async performRefresh(e){try{let n=await this.client.refreshToken(e.refresh_token);return this.persistTokenResponse(n,e.sub)}catch(n){throw le(n)?(this.store.clear(),new p):n}}persistTokenResponse(e,n){let r=e?.account;if(!e||typeof e.access_token!="string"||e.access_token.length===0||typeof e.refresh_token!="string"||e.refresh_token.length===0||!Number.isSafeInteger(e.expires_in)||e.expires_in<=0||!r||typeof r.sub!="string"||r.sub.length===0||typeof r.email!="string"||r.email.length===0)throw new d("AUTH_RESPONSE_INVALID","Account token response is malformed");if(n!==void 0&&r.sub!==n)throw new d("ACCOUNT_SUB_MISMATCH","Account subject changed during token refresh \u2014 please log in again");F(e.access_token,r.sub);let o=A({version:2,sub:r.sub,email:r.email,access_token:e.access_token,refresh_token:e.refresh_token,expires_at:this.epochSeconds()+e.expires_in,updated_at:new Date(this.now()).toISOString()});return this.store.write(o),o}};function le(t){return t instanceof s?t.kind==="invalid_refresh":typeof t=="object"&&t!==null&&(t.kind==="invalid_refresh"||t.code==="INVALID_REFRESH_TOKEN")}function _e(t){return typeof t.exchangeDeviceCode=="function"&&typeof t.refreshToken=="function"}function F(t,e){let n=C(),r=ge(t);if(r.iss!==n)throw new d("ACCOUNT_ISSUER_MISMATCH","Access token issuer does not match the configured account issuer \u2014 please log in again");if(r.sub!==e)throw new d("ACCOUNT_SUB_MISMATCH","Access token subject does not match the account session \u2014 please log in again")}function ge(t){if(typeof t!="string")throw O();let e=t.split(".");if(e.length!==3||e.some(n=>!/^[A-Za-z0-9_-]+$/.test(n)))throw O();try{let n=JSON.parse(Buffer.from(e[1],"base64url").toString("utf8"));if(typeof n!="object"||n===null||Array.isArray(n)||typeof n.iss!="string"||n.iss.length===0||typeof n.sub!="string"||n.sub.length===0)throw new Error("missing identity claims");return {iss:n.iss,sub:n.sub}}catch{throw O()}}function O(){return new d("ACCESS_TOKEN_INVALID","Access token identity could not be verified \u2014 please log in again")}export{b as ACCOUNT_BASE_URL_ENV,L as ACCOUNT_ISSUER_ENV,B as AUTH_JSON_FILENAME,v as AUTH_JSON_VERSION,s as AccountAuthError,c as AccountConfigurationError,E as AuthClient,s as AuthClientError,s as AuthError,f as AuthJsonStore,u as AuthJsonValidationError,m as DEVICE_CODE_GRANT_TYPE,W as DEVICE_CODE_PATH,p as LoginRequiredError,P as MARKETPLACE_URL_ENV,T as OAUTH_CLIENT_ID,$ as REVOKE_PATH,U as SessionManager,d as SessionManagerError,X as TOKEN_PATH,R as appendEndpoint,q as authJsonPath,ue as clearAuthJson,ie as isAuthJsonV2,K as parseAuthJson,ce as readAuthJson,k as resolveAccountBaseUrl,C as resolveAccountIssuer,Y as resolveMarketplaceUrl,A as validateAuthJson,ae as writeAuthJson};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import*as d from'path';import d__default,{join}from'path';import {fileURLToPath}from'url';import {createHash}from'crypto';import {readFileSync,unlinkSync,mkdirSync,writeFileSync,existsSync,statSync}from'fs';import {homedir}from'os';import {spawn}from'child_process';import {createRequire}from'module';var W=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var X=()=>fileURLToPath(import.meta.url),xe=()=>d__default.dirname(X()),w=xe(),P=X();var f=class extends Error{code;constructor(t,n){super(`${t}: ${n}`),this.code=t,this.name="ShortcutError";}};var U={existsSync:e=>existsSync(e),readFileSync:e=>readFileSync(e,"utf8"),readBinaryFileSync:e=>new Uint8Array(readFileSync(e)),writeFileSync:(e,t)=>writeFileSync(e,t,"utf8"),mkdirSync:e=>{mkdirSync(e,{recursive:true});},unlinkSync:e=>{unlinkSync(e);}},j=homedir;function N(e){return typeof e!="string"?void 0:e.trim()||void 0}function O(e){return N(e)?.toLowerCase()??""}function y(e){try{return statSync(e).isFile()}catch{return false}}function be(e,t){if(e===t)return true;let n=d__default.relative(e,t);return n!==""&&!n.startsWith("..")&&!d__default.isAbsolute(n)}function Ae(e,t){if(d__default.basename(e)!==".bin")return false;let n=d__default.dirname(e);if(d__default.basename(n)!=="node_modules")return false;let r=d__default.dirname(n);return be(r,t)}function J(e,t={}){if(e.includes("/")||e.includes("\\")||d__default.isAbsolute(e))return e;let n=t.platform??process.platform,r=t.env??process.env,i=d__default.resolve(t.cwd??process.cwd()),l=(t.resolution??"global_first")==="global_first",o=r.PATH??r.Path??process.env.PATH??process.env.Path??"",s=n==="win32"?";":":",a=o.split(s).map(u=>u.trim()).filter(Boolean),c=d__default.extname(e).length>0,h=r.PATHEXT??r.Pathext??process.env.PATHEXT??process.env.Pathext??".EXE;.CMD;.BAT;.COM",m=n==="win32"?c?[""]:h.split(";").map(u=>u.trim()).filter(Boolean).map(u=>u.startsWith(".")?u:`.${u}`):[""];for(let u of a){let p=d__default.resolve(i,u);if(!(l&&Ae(p,i)))for(let S of m){let C=O(S),g=S.toUpperCase();for(let _ of [S,C,g]){let V=d__default.join(p,`${e}${_}`);if(y(V))return V}}}return e}function De(e){if(!y(e))return null;try{let t=readFileSync(e,"utf8"),n=d__default.dirname(e),r=[];for(let s of t.matchAll(/"([^"\r\n]*)"/g)){let h=(s[1]??"").match(/%~?dp0%?\s*[\\/]*(.*)$/i)?.[1]?.trim();if(!h)continue;let m=h.replace(/[\\/]+/g,d__default.sep).replace(/^[\\/]+/,""),u=d__default.resolve(n,m);y(u)&&r.push(u);}let i=[],l=new Map;for(let s of t.matchAll(/SET\s+"(\w+)=%~?dp0%?[\\/]?([^"]+)"/gi)){let a=s[1].toUpperCase(),c=s[2].trim().replace(/[\\/]+/g,d__default.sep).replace(/^[\\/]+/,"");l.set(a,d__default.resolve(n,c));}for(let s of t.split(/\r?\n/))if(s.includes("%*"))for(let a of s.matchAll(/"%(\w+)%"/g)){let c=l.get(a[1].toUpperCase());c&&y(c)&&i.push(c);}let o=s=>s.find(a=>{let c=O(d__default.basename(a));return c!=="node.exe"&&c!=="node"})??null;return o(i)??o(r)}catch{return null}}function We(e,t){if(typeof t=="string")return N(t)||null;if(!t||typeof t!="object")return null;if(e){let n=t[e],r=typeof n=="string"?N(n):void 0;if(r)return r}for(let n of Object.values(t)){let r=typeof n=="string"?N(n):void 0;if(r)return r}return null}function Te(e,t){if(!t)return null;let n=d__default.dirname(e),r=[d__default.resolve(n,"..",t),d__default.resolve(n,"node_modules",t)];for(let i of r){let l=d__default.join(i,"package.json");if(y(l))try{let o=JSON.parse(readFileSync(l,"utf8")),s=We(t,o.bin);if(!s)continue;let a=d__default.resolve(i,s);if(y(a))return a}catch{}}return null}function Fe(e){let t=e.platform??process.platform,n=e.env??process.env,r=e.execPath??process.execPath,i=e.cwd,l=e.resolution;if(t!=="win32")return {command:J(e.command,{cwd:i,env:n,platform:t,resolution:l}),leadingArgv:[],resolution:"direct"};let o=J(e.command,{cwd:i,env:n,platform:t,resolution:l}),s=O(d__default.extname(o));if(s===".js"||s===".cjs"||s===".mjs")return {command:r,leadingArgv:[o],resolution:"node-entrypoint",windowsHide:true};if(s===".cmd"||s===".bat"){let a=De(o)??Te(o,e.packageName);return a?O(d__default.extname(a))===".exe"?{command:a,leadingArgv:[],resolution:"exe-entrypoint",windowsHide:true}:{command:r,leadingArgv:[a],resolution:"node-entrypoint",windowsHide:true}:{command:o,leadingArgv:[],resolution:"unresolved-wrapper"}}return {command:o,leadingArgv:[],resolution:"direct"}}function Me(e){if(e.candidate.resolution!=="unresolved-wrapper")return {command:e.candidate.command,leadingArgv:e.candidate.leadingArgv,resolution:e.candidate.resolution,windowsHide:e.candidate.windowsHide};throw new Error(`${d__default.basename(e.candidate.command)} wrapper resolved, but no executable/Node entrypoint could be resolved without shell execution.`)}function z(e){let t=Fe(e);return Me({candidate:t})}function q(e,t){return {command:e.command,argv:[...e.leadingArgv,...t],resolution:e.resolution,shell:e.shell,windowsHide:e.windowsHide}}var Q=3e4;function Be(e){if(typeof e.pid!="number"){e.kill();return}if(process.platform==="win32"){spawn("taskkill",["/pid",String(e.pid),"/t","/f"],{windowsHide:true}).on("error",()=>{});return}try{process.kill(-e.pid,"SIGKILL");}catch{e.kill("SIGKILL");}}var Z=(e,t,n={})=>new Promise((r,i)=>{let l=n.env??process.env,o=process.platform,s;try{let p=z({command:e,platform:o,env:l,cwd:n.cwd,allowShellFallback:!1});s=q(p,t);}catch(p){i(p instanceof Error?p:new Error(String(p)));return}let a=spawn(s.command,s.argv,{cwd:n.cwd,env:l,shell:s.shell,windowsHide:s.windowsHide??true,detached:o!=="win32"}),c="",h="",m=false,u=setTimeout(()=>{m||(m=true,Be(a),i(new Error(`Command timed out after ${n.timeoutMs??Q}ms: ${e} ${t.join(" ")}`)));},n.timeoutMs??Q);a.stdout?.on("data",p=>{c+=p.toString();}),a.stderr?.on("data",p=>{h+=p.toString();}),a.on("error",p=>{m||(m=true,clearTimeout(u),i(p));}),a.on("close",p=>{m||(m=true,clearTimeout(u),r({code:p??0,stdout:c,stderr:h}));});});function Ve(){try{return (typeof W=="function"?W:createRequire(P)).resolve("@crewx/sdk/package.json")}catch{return null}}function Xe(){let e=[Ve(),join(w,"../../package.json"),join(w,"../../../package.json")].filter(t=>!!t);for(let t of e)try{let n=JSON.parse(readFileSync(t,"utf8"));if(n.name==="@crewx/sdk"&&n.version)return n.version}catch{}return "0.0.0"}var te=Xe();var E=d.win32;function T(e){return E.join(e,".crewx")}function re(e){return E.join(T(e),"shortcut.json")}function oe(e){return E.join(T(e),"launcher.json")}function se(e){return E.join(T(e),"bin","crewx-launcher.cmd")}function ie(e){return E.join(e,"CrewX.lnk")}function F(e,t){return E.normalize(e).toLowerCase()===E.normalize(t).toLowerCase()}var Ge="[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; [Environment]::GetFolderPath('DesktopDirectory')";async function ae(e){try{let n=await e.run("powershell",["-NoProfile","-NonInteractive","-Command",Ge],{env:e.env}),r=n.stdout.trim();if(n.code===0&&r)return {dir:r,source:"known-folder"}}catch{}let t=e.env.USERPROFILE||e.env.Userprofile||e.homedir();return t?{dir:E.join(t,"Desktop"),source:"fallback"}:null}function M(e,t){let n=E.resolve(t,"node_modules",".bin").toLowerCase();return e.split(";").filter(r=>r?E.resolve(r).toLowerCase()!==n:true).join(";")}function ce(e){return e?/\\Program Files( \(x86\))?\\/i.test(e)&&/crewx/i.test(e):false}function Ue(e,t){let n=a=>{let[c,...h]=a.split("-"),m=h.join("-")||void 0;return {parts:(c??"").split(".").map(p=>Number.parseInt(p,10)||0),pre:m}},r=n(e),i=n(t),l=Math.max(r.parts.length,i.parts.length);for(let a=0;a<l;a++){let c=r.parts[a]??0,h=i.parts[a]??0;if(c!==h)return c<h?-1:1}if(r.pre===i.pre)return 0;if(!r.pre&&i.pre)return 1;if(r.pre&&!i.pre)return -1;let o=Number.parseInt(r.pre.match(/(\d+)$/)?.[1]??"",10),s=Number.parseInt(i.pre.match(/(\d+)$/)?.[1]??"",10);return !Number.isNaN(o)&&!Number.isNaN(s)&&o!==s?o<s?-1:1:r.pre<i.pre?-1:r.pre>i.pre?1:0}function x(e,t){return Ue(e,t)<0}var ue=d.win32,de=1;function pe(e,t){if(!e.existsSync(t))return null;try{let n=JSON.parse(e.readFileSync(t));return {schema:n.schema??de,shortcutPath:n.shortcutPath,version:n.version,iconHash:typeof n.iconHash=="string"?n.iconHash:void 0,owned:!!n.owned,declined:!!n.declined,desktopSource:n.desktopSource,updatedAt:n.updatedAt}}catch{return null}}function b(e,t,n){let r={schema:de,...n,updatedAt:new Date().toISOString()};e.mkdirSync(ue.dirname(t)),e.writeFileSync(t,JSON.stringify(r,null,2));}function A(e,t){if(!e.existsSync(t))return null;try{let n=JSON.parse(e.readFileSync(t));return {schema:n.schema??0,binPath:n.binPath,updatedAt:n.updatedAt}}catch{return null}}function fe(e,t,n){e.mkdirSync(ue.dirname(t)),e.writeFileSync(t,JSON.stringify(n,null,2));}var je=d.win32,L=1;function Je(e){return e.replace(/%/g,"%%")}function Ke(e){return ["@echo off","setlocal DisableDelayedExpansion","chcp 65001 >nul","",'set "CREWX_WORKDIR=%USERPROFILE%\\crewx"','if not exist "%CREWX_WORKDIR%" mkdir "%CREWX_WORKDIR%" >nul 2>nul','cd /d "%CREWX_WORKDIR%"',"",'set "CREWX_PORT_EFFECTIVE=%CREWX_PORT%"','if "%CREWX_PORT_EFFECTIVE%"=="" set "CREWX_PORT_EFFECTIVE=8150"','set "CREWX_HEALTH_URL=http://127.0.0.1:%CREWX_PORT_EFFECTIVE%/api/v1/health"','set "CREWX_ORIGIN_URL=http://127.0.0.1:%CREWX_PORT_EFFECTIVE%/"',"",e.bakedBinPath?`set "CREWX_FALLBACK_BIN=${Je(e.bakedBinPath)}"`:'set "CREWX_FALLBACK_BIN="','set "CREWX_RESOLVED_BIN=%CREWX_BIN%"','if "%CREWX_RESOLVED_BIN%"=="" set "CREWX_RESOLVED_BIN=%CREWX_FALLBACK_BIN%"','if "%CREWX_RESOLVED_BIN%"=="" (',` for /f "delims=" %%I in ('where crewx 2^>nul') do (`,' if not defined CREWX_RESOLVED_BIN set "CREWX_RESOLVED_BIN=%%I"'," )",")","",'powershell -NoProfile -NonInteractive -Command "try { $r = Invoke-WebRequest -Uri $env:CREWX_HEALTH_URL -TimeoutSec 1 -UseBasicParsing; if ($r.StatusCode -eq 200) { exit 0 } else { exit 1 } } catch { exit 1 }"',"if %ERRORLEVEL% EQU 0 (",' start "" "%CREWX_ORIGIN_URL%"'," exit /b 0",")","",'if "%CREWX_RESOLVED_BIN%"=="" ('," echo CrewX executable not found. Please reinstall the desktop shortcut."," pause"," exit /b 1",")","",'start "CrewX" /min "%CREWX_RESOLVED_BIN%"',""].join(`\r
|
|
2
|
+
`)}function me(e){let t=A(e.fs,e.launcherManifestPath),n=!!t&&t.schema>=L&&e.fs.existsSync(e.wrapperPath),r=n&&!t.binPath&&!!e.bakedBinPath;if(n&&!r)return {wrapperPath:e.wrapperPath,wrote:false,schema:t.schema};let l=Ke({bakedBinPath:e.bakedBinPath});try{e.fs.mkdirSync(je.dirname(e.wrapperPath)),e.fs.writeFileSync(e.wrapperPath,l),fe(e.fs,e.launcherManifestPath,{schema:L,binPath:e.bakedBinPath,updatedAt:new Date().toISOString()});}catch(o){throw o instanceof f?o:new f("WRITE_DENIED",`Could not write launcher wrapper: ${o instanceof Error?o.message:String(o)}`)}return {wrapperPath:e.wrapperPath,wrote:true,schema:L}}var ze=["$ws = New-Object -ComObject WScript.Shell","$sc = $ws.CreateShortcut($env:CREWX_LNK_PATH)","$sc.TargetPath = $env:CREWX_LNK_TARGET","if ($env:CREWX_LNK_WORKDIR) { $sc.WorkingDirectory = $env:CREWX_LNK_WORKDIR }","$sc.WindowStyle = 7","if ($env:CREWX_LNK_ICON) { $sc.IconLocation = $env:CREWX_LNK_ICON }","$sc.Save()"].join("; "),qe=["[Console]::OutputEncoding = [System.Text.Encoding]::UTF8","$ws = New-Object -ComObject WScript.Shell","$sc = $ws.CreateShortcut($env:CREWX_LNK_PATH)","[PSCustomObject]@{ TargetPath = $sc.TargetPath; WorkingDirectory = $sc.WorkingDirectory; IconLocation = $sc.IconLocation } | ConvertTo-Json -Compress"].join("; ");async function ge(e){let t={...e.env,CREWX_LNK_PATH:e.shortcutPath,CREWX_LNK_TARGET:e.targetPath,CREWX_LNK_WORKDIR:e.workingDirectory??"",CREWX_LNK_ICON:e.iconPath??""},n;try{n=await e.run("powershell",["-NoProfile","-NonInteractive","-Command",ze],{env:t});}catch(r){throw new f("POWERSHELL_UNAVAILABLE",`Could not run PowerShell: ${r instanceof Error?r.message:String(r)}`)}if(n.code!==0)throw new f("POWERSHELL_UNAVAILABLE",`Failed to create desktop shortcut: ${n.stderr||n.stdout}`)}function we(e){let t=e.trim(),n=t.lastIndexOf(",");return n!==-1&&/^-?\d+$/.test(t.slice(n+1).trim())&&(t=t.slice(0,n).trim()),t.length>=2&&t.startsWith('"')&&t.endsWith('"')&&(t=t.slice(1,-1).trim()),t}async function Se(e){try{let t={...e.env,CREWX_LNK_PATH:e.shortcutPath},n=await e.run("powershell",["-NoProfile","-NonInteractive","-Command",qe],{env:t});if(n.code!==0||!n.stdout.trim())return null;let r=JSON.parse(n.stdout.trim());return {targetPath:r.TargetPath??"",workingDirectory:r.WorkingDirectory??"",iconLocation:r.IconLocation??""}}catch{return null}}var $=d.win32;async function I(e){let t=M(e.env.PATH??e.env.Path??"",e.cwd),n={...e.env,PATH:t,Path:t},r;try{r=await e.run("npm",["list","-g","crewx","--depth=0","--json"],{env:n});}catch{return {installed:false}}let i;try{i=JSON.parse(r.stdout||"{}");}catch{return {installed:false}}let l=i.dependencies?.crewx;if(!l?.version)return {installed:false};let o;try{let a=await e.run("npm",["prefix","-g"],{env:n});a.code===0&&(o=a.stdout.trim()||void 0);}catch{}let s=o?$.join(o,"crewx.cmd"):void 0;return {installed:true,version:l.version,binPath:s,prefix:o}}var Qe=/EACCES|EPERM|EROFS/,Ye=/ENOTFOUND|ETIMEDOUT|ECONNREFUSED|network|registry/i,Ze=/^\d+\.\d+\.\d+/;function et(e){return !!e&&e!=="0.0.0"&&Ze.test(e)}var B=10*6e4;async function Ee(e){if(!et(e.targetVersion))throw new f("GLOBAL_INSTALL_FAILED",`RUNNING_VERSION_UNKNOWN: cannot reliably determine the running crewx version to install (got ${JSON.stringify(e.targetVersion)}); refusing to fall back to crewx@latest`);if(e.currentInfo?.installed&&e.currentInfo.version&&!x(e.currentInfo.version,e.targetVersion))return {info:e.currentInfo};let t=M(e.env.PATH??e.env.Path??"",e.cwd),n={...e.env,PATH:t,Path:t},r=`crewx@${e.targetVersion}`;e.onProgress?.({phase:"global-install",message:`Installing crewx globally (npm install -g ${r})`});let i;try{i=await e.run("npm",["install","-g",r,"--no-audit","--no-fund"],{env:n,timeoutMs:B});}catch(o){throw new f("NPM_UNAVAILABLE",`Could not run npm: ${o instanceof Error?o.message:String(o)}`)}if(i.code===0)return {info:await I({env:n,cwd:e.cwd,run:e.run})};let l=`${i.stdout}
|
|
3
|
+
${i.stderr}`;if(Qe.test(l)){e.onProgress?.({phase:"global-install",message:"Permission denied \u2014 retrying with a user-scoped npm prefix"});let o=e.env.LOCALAPPDATA||$.join(e.env.USERPROFILE??"","AppData","Local"),s={...n,npm_config_prefix:$.join(o,"crewx","npm")},a;try{a=await e.run("npm",["install","-g",r,"--no-audit","--no-fund"],{env:s,timeoutMs:B});}catch(c){throw new f("NPM_PERMISSION_DENIED",`Retry with user-scoped prefix failed: ${c instanceof Error?c.message:String(c)}`)}if(a.code===0)return {info:await I({env:s,cwd:e.cwd,run:e.run})};throw new f("NPM_PERMISSION_DENIED",`npm install -g failed after user-scoped prefix retry: ${a.stderr||a.stdout}`)}if(Ye.test(l)){if(!e.installRoot)throw new f("OFFLINE_NO_SOURCE","The npm registry is unreachable and no local installRoot was provided for an offline install");e.onProgress?.({phase:"global-install",message:`Registry unreachable \u2014 installing offline from ${e.installRoot}`});let o;try{o=await e.run("npm",["install","-g",e.installRoot,"--offline","--no-audit","--no-fund"],{env:n,timeoutMs:B});}catch(s){throw new f("GLOBAL_INSTALL_FAILED",`Offline install failed: ${s instanceof Error?s.message:String(s)}`)}if(o.code===0)return {info:await I({env:n,cwd:e.cwd,run:e.run})};throw new f("GLOBAL_INSTALL_FAILED",`Offline install failed: ${o.stderr||o.stdout}`)}throw new f("GLOBAL_INSTALL_FAILED",l.trim()||`npm install -g ${r} failed`)}function nt(e){return e.run??Z}function rt(e){return e.fs??U}async function D(e){let t=e.platform??process.platform,n=e.env??process.env,r=e.homedir??j,i=nt(e),l=rt(e),o=e.runningVersion??te,s=e.cwd??process.cwd(),a=r(),c=re(a),h=oe(a),m=se(a),u=null;t==="win32"&&(u=await ae({env:n,homedir:r,run:i}));let p=u?ie(u.dir):null;return {platform:t,env:n,homedir:r,run:i,fs:l,runningVersion:o,cwd:s,installRoot:e.installRoot,shortcutManifestPath:c,launcherManifestPath:h,wrapperPath:m,desktop:u,shortcutPath:p}}function Re(e){return e?d.win32.normalize(e).toLowerCase().endsWith(`${d.win32.sep}bin${d.win32.sep}crewx.ico`):false}function H(e,t){let n=e.readBinaryFileSync;if(n)try{return createHash("sha256").update(n(t)).digest("hex")}catch{return}}async function ot(e){try{await e.run("ie4uinit.exe",["-show"],{env:e.env});}catch{}}async function R(e){if(e.platform!=="win32")return {supported:false,state:"unsupported",globalCrewx:null,runningVersion:e.runningVersion,errors:[],manifest:null,iconStale:false};let t=[];e.desktop||t.push("NO_DESKTOP_DIR: could not resolve the Windows Desktop directory");let n=pe(e.fs,e.shortcutManifestPath),r=A(e.fs,e.launcherManifestPath),i=await I({env:e.env,cwd:e.cwd,run:e.run}),l=e.shortcutPath?e.fs.existsSync(e.shortcutPath):false,o,s=false,a,c;if(!l)o=n?.declined?"declined":"not-installed";else {let h=!!n?.owned&&!!e.shortcutPath&&n.shortcutPath===e.shortcutPath,m=false,u=e.shortcutPath?await Se({run:e.run,env:e.env,shortcutPath:e.shortcutPath}):null;if(h||(u&&F(u.targetPath,e.wrapperPath)?h=true:u&&ce(u.targetPath)&&(m=true)),m)o="foreign",t.push("NSIS_PRESENT: an NSIS-installed CrewX shortcut was detected");else if(!h)o="foreign";else if(n?.version&&x(e.runningVersion,n.version))o="superseded",t.push(`SUPERSEDED: running version ${e.runningVersion} is older than the installed shortcut's version ${n.version}; refusing to modify it`);else {let p=!r||r.schema<L||!e.fs.existsSync(e.wrapperPath);if(u){let S=we(u.iconLocation);if(!(!!S&&e.fs.existsSync(S)))s=true;else {a=S;let g=ve(i,e.fs);g?F(S,g)?(c=H(e.fs,S),s=!c||n?.iconHash!==c):s=true:Re(S)?(c=H(e.fs,S),s=!c||n?.iconHash!==c):s=true;}}o=p||s?"stale":"installed";}}return {supported:true,state:o,shortcutPath:e.shortcutPath??void 0,desktopDir:e.desktop?.dir,desktopSource:e.desktop?.source,wrapperPath:e.wrapperPath,wrapperSchema:r?.schema,globalCrewx:i.installed?i:{installed:false},runningVersion:e.runningVersion,errors:t,manifest:n,iconStale:s,iconPath:a,iconHash:c}}function ve(e,t){if(!e?.installed||!e.prefix)return;let n=d.win32.join(e.prefix,"node_modules","crewx","bin","crewx.ico");return t.existsSync(n)?n:void 0}function v(e){let{manifest:t,iconStale:n,iconPath:r,iconHash:i,...l}=e;return l}async function st(e={}){let t=await D(e),n=await R(t);return v(n)}async function it(e={}){let t=await D(e);e.onProgress?.({phase:"detect",message:"Checking current shortcut status"});let n=await R(t),r=v(n);if(!r.supported)return {...r,changed:false,installedGlobal:false};if(r.state==="superseded")return {...r,changed:false,installedGlobal:false};if(r.state==="foreign"){if(n.errors.some(g=>g.startsWith("NSIS_PRESENT")))throw new f("NSIS_PRESENT",`An NSIS-installed CrewX shortcut was detected at ${r.shortcutPath}`);if(!e.force)throw new f("FOREIGN_SHORTCUT",`An existing shortcut at ${r.shortcutPath} is not managed by CrewX`)}if(!t.desktop||!t.shortcutPath)throw new f("NO_DESKTOP_DIR","Could not resolve the Windows Desktop directory");let i=false,l=false,o=r.globalCrewx,s=[],a=n.manifest?.iconHash,c=false;if(!!o?.installed&&!!o.version&&x(o.version,t.runningVersion)||!o?.installed&&r.state!=="installed"){let g=await Ee({env:t.env,cwd:t.cwd,run:t.run,targetVersion:t.runningVersion,currentInfo:o??void 0,installRoot:t.installRoot,onProgress:e.onProgress});o=g.info,l=g.info.installed,i=true,l||s.push(`GLOBAL_INSTALL_UNCONFIRMED: npm install -g crewx@${t.runningVersion} exited successfully but a follow-up check could not confirm the global install`);}if(e.onProgress?.({phase:"wrapper",message:"Ensuring launcher wrapper"}),me({fs:t.fs,wrapperPath:t.wrapperPath,launcherManifestPath:t.launcherManifestPath,bakedBinPath:o?.binPath}).wrote&&(i=true),!((r.state==="installed"||r.state==="stale")&&!n.iconStale)){let g=ve(o,t.fs)??(n.iconPath&&Re(n.iconPath)&&t.fs.existsSync(n.iconPath)?n.iconPath:void 0);if(n.iconStale&&!g)throw new f("ICON_UNAVAILABLE",`Could not locate the global CrewX icon (bin\\crewx.ico) to repair the desktop shortcut at ${t.shortcutPath}; the existing shortcut was left untouched`);e.onProgress?.({phase:"lnk",message:"Creating desktop shortcut"}),await ge({run:t.run,env:t.env,shortcutPath:t.shortcutPath,targetPath:t.wrapperPath,iconPath:g}),i=true,c=n.iconStale;let _=g?H(t.fs,g):void 0;_&&(a=_);}i&&b(t.fs,t.shortcutManifestPath,{shortcutPath:t.shortcutPath,version:t.runningVersion,owned:true,declined:false,desktopSource:t.desktop.source,iconHash:a}),c&&await ot(t);let S=await R(t),C=v(S);return {...C,errors:[...C.errors,...s],changed:i,installedGlobal:l}}async function at(e={}){let t=await D(e),n=await R(t),r=v(n);if(!r.supported)return r;if((r.state==="installed"||r.state==="stale")&&t.shortcutPath)try{t.fs.unlinkSync(t.shortcutPath);}catch{}b(t.fs,t.shortcutManifestPath,{shortcutPath:void 0,version:n.manifest?.version,owned:false,declined:true,desktopSource:void 0,iconHash:void 0});let i=await R(t);return v(i)}async function ct(e={}){let t=await D(e),n=await R(t),r=v(n);if(!r.supported)return r;b(t.fs,t.shortcutManifestPath,{shortcutPath:n.manifest?.shortcutPath,version:n.manifest?.version,owned:n.manifest?.owned??false,declined:true,desktopSource:n.manifest?.desktopSource,iconHash:n.manifest?.iconHash});let i=await R(t);return v(i)}export{f as ShortcutError,ct as dismissShortcutNotice,st as getShortcutStatus,it as installShortcut,at as uninstallShortcut};
|