@mastra/code-sdk 1.0.3-alpha.0 → 1.1.0-alpha.2
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/CHANGELOG.md +49 -0
- package/dist/acp/agent.js +155 -167
- package/dist/acp/agent.js.map +1 -1
- package/dist/acp/event-mapper.js +193 -168
- package/dist/acp/event-mapper.js.map +1 -1
- package/dist/acp/index.js +60 -49
- package/dist/acp/index.js.map +1 -1
- package/dist/acp/server.js +31 -30
- package/dist/acp/server.js.map +1 -1
- package/dist/acp.js +1 -4
- package/dist/agents/credential-resolver.js +40 -29
- package/dist/agents/credential-resolver.js.map +1 -1
- package/dist/agents/custom-provider-source.js +16 -9
- package/dist/agents/custom-provider-source.js.map +1 -1
- package/dist/agents/instructions.js +27 -36
- package/dist/agents/instructions.js.map +1 -1
- package/dist/agents/mastracode-gateway.js +355 -428
- package/dist/agents/mastracode-gateway.js.map +1 -1
- package/dist/agents/memory.js +87 -78
- package/dist/agents/memory.js.map +1 -1
- package/dist/agents/model.js +114 -119
- package/dist/agents/model.js.map +1 -1
- package/dist/agents/modes/build.js +12 -13
- package/dist/agents/modes/build.js.map +1 -1
- package/dist/agents/modes/explore.js +14 -13
- package/dist/agents/modes/explore.js.map +1 -1
- package/dist/agents/modes/plan.js +14 -15
- package/dist/agents/modes/plan.js.map +1 -1
- package/dist/agents/prompts/agent-instructions.js +78 -69
- package/dist/agents/prompts/agent-instructions.js.map +1 -1
- package/dist/agents/prompts/build.js +19 -16
- package/dist/agents/prompts/build.js.map +1 -1
- package/dist/agents/prompts/fast.js +8 -4
- package/dist/agents/prompts/fast.js.map +1 -1
- package/dist/agents/prompts/index.js +48 -47
- package/dist/agents/prompts/index.js.map +1 -1
- package/dist/agents/prompts/model.js +6 -5
- package/dist/agents/prompts/model.js.map +1 -1
- package/dist/agents/prompts/plan.js +20 -16
- package/dist/agents/prompts/plan.js.map +1 -1
- package/dist/agents/prompts/tool-guidance.js +77 -109
- package/dist/agents/prompts/tool-guidance.js.map +1 -1
- package/dist/agents/sandbox-filesystem.js +245 -259
- package/dist/agents/sandbox-filesystem.js.map +1 -1
- package/dist/agents/sandbox-reattach.js +9 -11
- package/dist/agents/sandbox-reattach.js.map +1 -1
- package/dist/agents/thread-caveman-state.js +92 -81
- package/dist/agents/thread-caveman-state.js.map +1 -1
- package/dist/agents/tool-availability.js +62 -80
- package/dist/agents/tool-availability.js.map +1 -1
- package/dist/agents/tools.js +99 -139
- package/dist/agents/tools.js.map +1 -1
- package/dist/agents/workspace.js +232 -225
- package/dist/agents/workspace.js.map +1 -1
- package/dist/analytics.js +139 -128
- package/dist/analytics.js.map +1 -1
- package/dist/auth/authorization-input.js +39 -25
- package/dist/auth/authorization-input.js.map +1 -1
- package/dist/auth/device-code.js +112 -80
- package/dist/auth/device-code.js.map +1 -1
- package/dist/auth/index.js +2 -9
- package/dist/auth/pkce.js +27 -16
- package/dist/auth/pkce.js.map +1 -1
- package/dist/auth/providers/anthropic.js +107 -93
- package/dist/auth/providers/anthropic.js.map +1 -1
- package/dist/auth/providers/github-copilot.js +304 -293
- package/dist/auth/providers/github-copilot.js.map +1 -1
- package/dist/auth/providers/openai-codex.js +442 -460
- package/dist/auth/providers/openai-codex.js.map +1 -1
- package/dist/auth/providers/xai.js +179 -145
- package/dist/auth/providers/xai.js.map +1 -1
- package/dist/auth/storage.js +182 -175
- package/dist/auth/storage.js.map +1 -1
- package/dist/auth/types.js +1 -1
- package/dist/clipboard/index.js +206 -172
- package/dist/clipboard/index.js.map +1 -1
- package/dist/constants.js +11 -16
- package/dist/constants.js.map +1 -1
- package/dist/error-classification.js +19 -11
- package/dist/error-classification.js.map +1 -1
- package/dist/evals/context-builder.js +145 -104
- package/dist/evals/context-builder.js.map +1 -1
- package/dist/evals/index.js +4 -7
- package/dist/evals/scorers/classify-command.js +62 -41
- package/dist/evals/scorers/classify-command.js.map +1 -1
- package/dist/evals/scorers/efficiency.js +239 -181
- package/dist/evals/scorers/efficiency.js.map +1 -1
- package/dist/evals/scorers/extract-tools.js +51 -47
- package/dist/evals/scorers/extract-tools.js.map +1 -1
- package/dist/evals/scorers/index.js +1 -5
- package/dist/evals/scorers/outcome.js +321 -212
- package/dist/evals/scorers/outcome.js.map +1 -1
- package/dist/goal-manager.js +266 -261
- package/dist/goal-manager.js.map +1 -1
- package/dist/goal-signal.js +14 -13
- package/dist/goal-signal.js.map +1 -1
- package/dist/headless/cli.js +153 -154
- package/dist/headless/cli.js.map +1 -1
- package/dist/headless/flags.js +180 -178
- package/dist/headless/flags.js.map +1 -1
- package/dist/headless/format.js +72 -71
- package/dist/headless/format.js.map +1 -1
- package/dist/headless/index.js +5 -31
- package/dist/headless/policy.js +35 -31
- package/dist/headless/policy.js.map +1 -1
- package/dist/headless/run-mc.js +332 -334
- package/dist/headless/run-mc.js.map +1 -1
- package/dist/headless/types.js +16 -7
- package/dist/headless/types.js.map +1 -1
- package/dist/hooks/config.js +56 -61
- package/dist/hooks/config.js.map +1 -1
- package/dist/hooks/executor.js +118 -116
- package/dist/hooks/executor.js.map +1 -1
- package/dist/hooks/index.js +4 -15
- package/dist/hooks/manager.js +221 -280
- package/dist/hooks/manager.js.map +1 -1
- package/dist/hooks/types.js +5 -4
- package/dist/hooks/types.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +632 -712
- package/dist/index.js.map +1 -1
- package/dist/ipc/ipc-reporter.js +19 -22
- package/dist/ipc/ipc-reporter.js.map +1 -1
- package/dist/lsp/client.js +248 -306
- package/dist/lsp/client.js.map +1 -1
- package/dist/lsp/index.js +1 -6
- package/dist/lsp/language.js +39 -43
- package/dist/lsp/language.js.map +1 -1
- package/dist/lsp/manager.js +78 -93
- package/dist/lsp/manager.js.map +1 -1
- package/dist/lsp/server.js +151 -120
- package/dist/lsp/server.js.map +1 -1
- package/dist/lsp/workspace.js +50 -47
- package/dist/lsp/workspace.js.map +1 -1
- package/dist/mcp/config.js +210 -199
- package/dist/mcp/config.js.map +1 -1
- package/dist/mcp/index.js +2 -9
- package/dist/mcp/manager.js +482 -475
- package/dist/mcp/manager.js.map +1 -1
- package/dist/mcp/types.js +1 -1
- package/dist/onboarding/custom-packs.js +14 -17
- package/dist/onboarding/custom-packs.js.map +1 -1
- package/dist/onboarding/custom-providers.js +22 -20
- package/dist/onboarding/custom-providers.js.map +1 -1
- package/dist/onboarding/index.d.ts +1 -1
- package/dist/onboarding/index.d.ts.map +1 -1
- package/dist/onboarding/index.js +3 -21
- package/dist/onboarding/om-settings.d.ts +5 -0
- package/dist/onboarding/om-settings.d.ts.map +1 -1
- package/dist/onboarding/om-settings.js +41 -20
- package/dist/onboarding/om-settings.js.map +1 -1
- package/dist/onboarding/packs.d.ts +4 -6
- package/dist/onboarding/packs.d.ts.map +1 -1
- package/dist/onboarding/packs.js +154 -105
- package/dist/onboarding/packs.js.map +1 -1
- package/dist/onboarding/settings.js +575 -517
- package/dist/onboarding/settings.js.map +1 -1
- package/dist/permissions.js +112 -99
- package/dist/permissions.js.map +1 -1
- package/dist/plugin.js +21 -23
- package/dist/plugin.js.map +1 -1
- package/dist/plugins/dependencies.js +64 -87
- package/dist/plugins/dependencies.js.map +1 -1
- package/dist/plugins/install.js +159 -169
- package/dist/plugins/install.js.map +1 -1
- package/dist/plugins/loader.js +170 -185
- package/dist/plugins/loader.js.map +1 -1
- package/dist/plugins/manager.js +374 -380
- package/dist/plugins/manager.js.map +1 -1
- package/dist/plugins/manifest.js +38 -63
- package/dist/plugins/manifest.js.map +1 -1
- package/dist/plugins/package-link.js +48 -64
- package/dist/plugins/package-link.js.map +1 -1
- package/dist/plugins/paths.js +18 -19
- package/dist/plugins/paths.js.map +1 -1
- package/dist/plugins/registry.js +97 -81
- package/dist/plugins/registry.js.map +1 -1
- package/dist/plugins/scaffold.js +62 -98
- package/dist/plugins/scaffold.js.map +1 -1
- package/dist/plugins/types.js +1 -1
- package/dist/processors/plan-rejection-abort.js +45 -44
- package/dist/processors/plan-rejection-abort.js.map +1 -1
- package/dist/providers/amazon-bedrock-gateway.js +134 -125
- package/dist/providers/amazon-bedrock-gateway.js.map +1 -1
- package/dist/providers/amazon-bedrock.js +68 -47
- package/dist/providers/amazon-bedrock.js.map +1 -1
- package/dist/providers/claude-max.js +153 -133
- package/dist/providers/claude-max.js.map +1 -1
- package/dist/providers/github-copilot.js +232 -230
- package/dist/providers/github-copilot.js.map +1 -1
- package/dist/providers/openai-codex.js +271 -260
- package/dist/providers/openai-codex.js.map +1 -1
- package/dist/providers/xai.js +57 -50
- package/dist/providers/xai.js.map +1 -1
- package/dist/schema.js +91 -89
- package/dist/schema.js.map +1 -1
- package/dist/theme-palette.js +18 -14
- package/dist/theme-palette.js.map +1 -1
- package/dist/tool-names.js +46 -37
- package/dist/tool-names.js.map +1 -1
- package/dist/tools/index.js +2 -8
- package/dist/tools/request-sandbox-access.js +71 -80
- package/dist/tools/request-sandbox-access.js.map +1 -1
- package/dist/tools/utils.js +26 -16
- package/dist/tools/utils.js.map +1 -1
- package/dist/tools/web-search.js +51 -55
- package/dist/tools/web-search.js.map +1 -1
- package/dist/utils/binaries.js +65 -61
- package/dist/utils/binaries.js.map +1 -1
- package/dist/utils/debug-log.js +51 -47
- package/dist/utils/debug-log.js.map +1 -1
- package/dist/utils/errors.js +157 -192
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/gateway-sync.js +49 -37
- package/dist/utils/gateway-sync.js.map +1 -1
- package/dist/utils/path-security.js +7 -6
- package/dist/utils/path-security.js.map +1 -1
- package/dist/utils/plan-diff.js +58 -39
- package/dist/utils/plan-diff.js.map +1 -1
- package/dist/utils/plans.js +92 -74
- package/dist/utils/plans.js.map +1 -1
- package/dist/utils/project.js +318 -256
- package/dist/utils/project.js.map +1 -1
- package/dist/utils/signals-pubsub.js +117 -99
- package/dist/utils/signals-pubsub.js.map +1 -1
- package/dist/utils/slash-command-loader.js +118 -154
- package/dist/utils/slash-command-loader.js.map +1 -1
- package/dist/utils/slash-command-processor.js +92 -83
- package/dist/utils/slash-command-processor.js.map +1 -1
- package/dist/utils/stdin-pipe.js +87 -63
- package/dist/utils/stdin-pipe.js.map +1 -1
- package/dist/utils/storage-factory.js +104 -84
- package/dist/utils/storage-factory.js.map +1 -1
- package/dist/utils/storage-maintenance.js +249 -211
- package/dist/utils/storage-maintenance.js.map +1 -1
- package/dist/utils/thread-lock.js +96 -92
- package/dist/utils/thread-lock.js.map +1 -1
- package/dist/utils/token-estimator.js +12 -12
- package/dist/utils/token-estimator.js.map +1 -1
- package/dist/utils/update-check.d.ts +1 -1
- package/dist/utils/update-check.js +341 -259
- package/dist/utils/update-check.js.map +1 -1
- package/dist/voice/stt-registry.js +131 -113
- package/dist/voice/stt-registry.js.map +1 -1
- package/package.json +11 -11
- package/dist/acp.js.map +0 -1
- package/dist/auth/index.js.map +0 -1
- package/dist/auth/types.js.map +0 -1
- package/dist/evals/index.js.map +0 -1
- package/dist/evals/scorers/index.js.map +0 -1
- package/dist/headless/index.js.map +0 -1
- package/dist/hooks/index.js.map +0 -1
- package/dist/lsp/index.js.map +0 -1
- package/dist/mcp/index.js.map +0 -1
- package/dist/mcp/types.js.map +0 -1
- package/dist/onboarding/index.js.map +0 -1
- package/dist/plugins/types.js.map +0 -1
- package/dist/tools/index.js.map +0 -1
package/dist/analytics.js
CHANGED
|
@@ -1,152 +1,163 @@
|
|
|
1
|
-
import { randomUUID } from "
|
|
2
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "
|
|
3
|
-
import os from "
|
|
4
|
-
import path from "
|
|
1
|
+
import { randomUUID } from "crypto";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
3
|
+
import os from "os";
|
|
4
|
+
import path from "path";
|
|
5
5
|
import { PostHog } from "posthog-node";
|
|
6
|
+
//#region src/analytics.ts
|
|
6
7
|
const POSTHOG_API_KEY = "phc_SBLpZVAB6jmHOct9CABq3PF0Yn5FU3G2FgT4xUr2XrT";
|
|
7
8
|
const POSTHOG_HOST = "https://us.posthog.com";
|
|
8
9
|
const MASTRA_SOURCE = "mastracode";
|
|
9
|
-
const TRUTHY_DISABLED_VALUES = /* @__PURE__ */ new Set([
|
|
10
|
+
const TRUTHY_DISABLED_VALUES = /* @__PURE__ */ new Set([
|
|
11
|
+
"1",
|
|
12
|
+
"true",
|
|
13
|
+
"yes",
|
|
14
|
+
"on"
|
|
15
|
+
]);
|
|
10
16
|
const ANALYTICS_CONFIG_PATH = path.join(os.homedir(), ".mastracode", "analytics.json");
|
|
11
17
|
function createMastraAnalyticsDistinctId() {
|
|
12
|
-
|
|
18
|
+
return `mastra-${randomUUID()}`;
|
|
13
19
|
}
|
|
14
20
|
function isHostnameDerivedDistinctId(distinctId, hostname = os.hostname()) {
|
|
15
|
-
|
|
21
|
+
return distinctId === `mastra-${hostname}`;
|
|
16
22
|
}
|
|
17
23
|
function isValidMastraAnalyticsDistinctId(distinctId) {
|
|
18
|
-
|
|
24
|
+
return /^mastra-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(distinctId);
|
|
19
25
|
}
|
|
20
26
|
function writeAnalyticsConfig(distinctId, configPath = ANALYTICS_CONFIG_PATH) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
27
|
+
try {
|
|
28
|
+
mkdirSync(path.dirname(configPath), { recursive: true });
|
|
29
|
+
writeFileSync(configPath, JSON.stringify({ distinctId }));
|
|
30
|
+
} catch {}
|
|
26
31
|
}
|
|
27
32
|
function getMastraAnalyticsDistinctId(configPath = ANALYTICS_CONFIG_PATH) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const distinctId = createMastraAnalyticsDistinctId();
|
|
38
|
-
writeAnalyticsConfig(distinctId, configPath);
|
|
39
|
-
return distinctId;
|
|
33
|
+
try {
|
|
34
|
+
if (existsSync(configPath)) {
|
|
35
|
+
const config = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
36
|
+
if (config.distinctId && isValidMastraAnalyticsDistinctId(config.distinctId) && !isHostnameDerivedDistinctId(config.distinctId)) return config.distinctId;
|
|
37
|
+
}
|
|
38
|
+
} catch {}
|
|
39
|
+
const distinctId = createMastraAnalyticsDistinctId();
|
|
40
|
+
writeAnalyticsConfig(distinctId, configPath);
|
|
41
|
+
return distinctId;
|
|
40
42
|
}
|
|
41
43
|
function isAnalyticsDebugEnabled() {
|
|
42
|
-
|
|
44
|
+
return TRUTHY_DISABLED_VALUES.has(process.env.MASTRACODE_ANALYTICS_DEBUG?.trim().toLowerCase() ?? "");
|
|
43
45
|
}
|
|
44
46
|
function debugAnalytics(message, properties) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const suffix = properties ? ` ${JSON.stringify(properties)}` : "";
|
|
49
|
-
process.stderr.write(`[mastracode analytics] ${message}${suffix}
|
|
50
|
-
`);
|
|
51
|
-
}
|
|
52
|
-
class NoopMastraCodeAnalytics {
|
|
53
|
-
capture(event) {
|
|
54
|
-
debugAnalytics("capture skipped: telemetry disabled", { event });
|
|
55
|
-
}
|
|
56
|
-
trackCommand(command) {
|
|
57
|
-
debugAnalytics("command skipped: telemetry disabled", { command });
|
|
58
|
-
}
|
|
59
|
-
trackInteractivePrompt(promptType) {
|
|
60
|
-
debugAnalytics("interactive prompt skipped: telemetry disabled", { promptType });
|
|
61
|
-
}
|
|
62
|
-
async shutdown() {
|
|
63
|
-
debugAnalytics("shutdown skipped: telemetry disabled");
|
|
64
|
-
}
|
|
65
|
-
isEnabled() {
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
class PostHogMastraCodeAnalytics {
|
|
70
|
-
client;
|
|
71
|
-
distinctId;
|
|
72
|
-
sessionId = randomUUID();
|
|
73
|
-
version;
|
|
74
|
-
constructor({ version, apiKey = POSTHOG_API_KEY, host = POSTHOG_HOST }) {
|
|
75
|
-
this.version = version;
|
|
76
|
-
this.distinctId = getMastraAnalyticsDistinctId();
|
|
77
|
-
this.client = new PostHog(apiKey, {
|
|
78
|
-
host,
|
|
79
|
-
flushAt: 1,
|
|
80
|
-
flushInterval: 0,
|
|
81
|
-
disableGeoip: false
|
|
82
|
-
});
|
|
83
|
-
this.client.register({ mastraSource: MASTRA_SOURCE });
|
|
84
|
-
debugAnalytics("enabled", { host, distinctId: this.distinctId, version });
|
|
85
|
-
}
|
|
86
|
-
capture(event, properties) {
|
|
87
|
-
try {
|
|
88
|
-
const eventProperties = {
|
|
89
|
-
...this.getBaseProperties(),
|
|
90
|
-
...properties
|
|
91
|
-
};
|
|
92
|
-
debugAnalytics("capture", { event, properties: eventProperties });
|
|
93
|
-
this.client.capture({
|
|
94
|
-
distinctId: this.distinctId,
|
|
95
|
-
event,
|
|
96
|
-
properties: eventProperties
|
|
97
|
-
});
|
|
98
|
-
} catch (error) {
|
|
99
|
-
debugAnalytics("capture failed", { event, error: error instanceof Error ? error.message : String(error) });
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
trackCommand(command, properties) {
|
|
103
|
-
this.capture("mastracode_command_used", { command, ...properties });
|
|
104
|
-
}
|
|
105
|
-
trackInteractivePrompt(promptType, properties) {
|
|
106
|
-
this.capture("mastracode_interactive_prompt_shown", { promptType, ...properties });
|
|
107
|
-
}
|
|
108
|
-
async shutdown() {
|
|
109
|
-
try {
|
|
110
|
-
debugAnalytics("shutdown start");
|
|
111
|
-
await this.client.shutdown();
|
|
112
|
-
debugAnalytics("shutdown complete");
|
|
113
|
-
} catch (error) {
|
|
114
|
-
debugAnalytics("shutdown failed", { error: error instanceof Error ? error.message : String(error) });
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
isEnabled() {
|
|
118
|
-
return true;
|
|
119
|
-
}
|
|
120
|
-
getBaseProperties() {
|
|
121
|
-
return {
|
|
122
|
-
mastraSource: MASTRA_SOURCE,
|
|
123
|
-
sessionId: this.sessionId,
|
|
124
|
-
version: this.version,
|
|
125
|
-
os: process.platform,
|
|
126
|
-
osVersion: os.release(),
|
|
127
|
-
nodeVersion: process.version,
|
|
128
|
-
platform: process.arch,
|
|
129
|
-
machineId: os.hostname()
|
|
130
|
-
};
|
|
131
|
-
}
|
|
47
|
+
if (!isAnalyticsDebugEnabled()) return;
|
|
48
|
+
const suffix = properties ? ` ${JSON.stringify(properties)}` : "";
|
|
49
|
+
process.stderr.write(`[mastracode analytics] ${message}${suffix}\n`);
|
|
132
50
|
}
|
|
51
|
+
var NoopMastraCodeAnalytics = class {
|
|
52
|
+
capture(event) {
|
|
53
|
+
debugAnalytics("capture skipped: telemetry disabled", { event });
|
|
54
|
+
}
|
|
55
|
+
trackCommand(command) {
|
|
56
|
+
debugAnalytics("command skipped: telemetry disabled", { command });
|
|
57
|
+
}
|
|
58
|
+
trackInteractivePrompt(promptType) {
|
|
59
|
+
debugAnalytics("interactive prompt skipped: telemetry disabled", { promptType });
|
|
60
|
+
}
|
|
61
|
+
async shutdown() {
|
|
62
|
+
debugAnalytics("shutdown skipped: telemetry disabled");
|
|
63
|
+
}
|
|
64
|
+
isEnabled() {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
var PostHogMastraCodeAnalytics = class {
|
|
69
|
+
client;
|
|
70
|
+
distinctId;
|
|
71
|
+
sessionId = randomUUID();
|
|
72
|
+
version;
|
|
73
|
+
constructor({ version, apiKey = POSTHOG_API_KEY, host = POSTHOG_HOST }) {
|
|
74
|
+
this.version = version;
|
|
75
|
+
this.distinctId = getMastraAnalyticsDistinctId();
|
|
76
|
+
this.client = new PostHog(apiKey, {
|
|
77
|
+
host,
|
|
78
|
+
flushAt: 1,
|
|
79
|
+
flushInterval: 0,
|
|
80
|
+
disableGeoip: false
|
|
81
|
+
});
|
|
82
|
+
this.client.register({ mastraSource: MASTRA_SOURCE });
|
|
83
|
+
debugAnalytics("enabled", {
|
|
84
|
+
host,
|
|
85
|
+
distinctId: this.distinctId,
|
|
86
|
+
version
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
capture(event, properties) {
|
|
90
|
+
try {
|
|
91
|
+
const eventProperties = {
|
|
92
|
+
...this.getBaseProperties(),
|
|
93
|
+
...properties
|
|
94
|
+
};
|
|
95
|
+
debugAnalytics("capture", {
|
|
96
|
+
event,
|
|
97
|
+
properties: eventProperties
|
|
98
|
+
});
|
|
99
|
+
this.client.capture({
|
|
100
|
+
distinctId: this.distinctId,
|
|
101
|
+
event,
|
|
102
|
+
properties: eventProperties
|
|
103
|
+
});
|
|
104
|
+
} catch (error) {
|
|
105
|
+
debugAnalytics("capture failed", {
|
|
106
|
+
event,
|
|
107
|
+
error: error instanceof Error ? error.message : String(error)
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
trackCommand(command, properties) {
|
|
112
|
+
this.capture("mastracode_command_used", {
|
|
113
|
+
command,
|
|
114
|
+
...properties
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
trackInteractivePrompt(promptType, properties) {
|
|
118
|
+
this.capture("mastracode_interactive_prompt_shown", {
|
|
119
|
+
promptType,
|
|
120
|
+
...properties
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
async shutdown() {
|
|
124
|
+
try {
|
|
125
|
+
debugAnalytics("shutdown start");
|
|
126
|
+
await this.client.shutdown();
|
|
127
|
+
debugAnalytics("shutdown complete");
|
|
128
|
+
} catch (error) {
|
|
129
|
+
debugAnalytics("shutdown failed", { error: error instanceof Error ? error.message : String(error) });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
isEnabled() {
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
getBaseProperties() {
|
|
136
|
+
return {
|
|
137
|
+
mastraSource: MASTRA_SOURCE,
|
|
138
|
+
sessionId: this.sessionId,
|
|
139
|
+
version: this.version,
|
|
140
|
+
os: process.platform,
|
|
141
|
+
osVersion: os.release(),
|
|
142
|
+
nodeVersion: process.version,
|
|
143
|
+
platform: process.arch,
|
|
144
|
+
machineId: os.hostname()
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
};
|
|
133
148
|
function isTelemetryDisabled(env = process.env) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
return TRUTHY_DISABLED_VALUES.has(value.trim().toLowerCase());
|
|
149
|
+
const value = env.MASTRA_TELEMETRY_DISABLED;
|
|
150
|
+
if (!value) return false;
|
|
151
|
+
return TRUTHY_DISABLED_VALUES.has(value.trim().toLowerCase());
|
|
139
152
|
}
|
|
140
153
|
function createMastraCodeAnalytics(options) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
154
|
+
if (isTelemetryDisabled()) {
|
|
155
|
+
debugAnalytics("disabled by MASTRA_TELEMETRY_DISABLED", { value: process.env.MASTRA_TELEMETRY_DISABLED });
|
|
156
|
+
return new NoopMastraCodeAnalytics();
|
|
157
|
+
}
|
|
158
|
+
return new PostHogMastraCodeAnalytics(options);
|
|
146
159
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
isTelemetryDisabled
|
|
151
|
-
};
|
|
160
|
+
//#endregion
|
|
161
|
+
export { createMastraCodeAnalytics, getMastraAnalyticsDistinctId, isTelemetryDisabled };
|
|
162
|
+
|
|
152
163
|
//# sourceMappingURL=analytics.js.map
|
package/dist/analytics.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/analytics.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { PostHog } from 'posthog-node';\n\nconst POSTHOG_API_KEY = 'phc_SBLpZVAB6jmHOct9CABq3PF0Yn5FU3G2FgT4xUr2XrT';\nconst POSTHOG_HOST = 'https://us.posthog.com';\nconst MASTRA_SOURCE = 'mastracode';\nconst TRUTHY_DISABLED_VALUES = new Set(['1', 'true', 'yes', 'on']);\nconst ANALYTICS_CONFIG_PATH = path.join(os.homedir(), '.mastracode', 'analytics.json');\n\ninterface AnalyticsConfig {\n distinctId?: string;\n}\n\nfunction createMastraAnalyticsDistinctId(): string {\n return `mastra-${randomUUID()}`;\n}\n\nfunction isHostnameDerivedDistinctId(distinctId: string, hostname = os.hostname()): boolean {\n return distinctId === `mastra-${hostname}`;\n}\n\nfunction isValidMastraAnalyticsDistinctId(distinctId: string): boolean {\n return /^mastra-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(distinctId);\n}\n\nfunction writeAnalyticsConfig(distinctId: string, configPath = ANALYTICS_CONFIG_PATH): void {\n try {\n mkdirSync(path.dirname(configPath), { recursive: true });\n writeFileSync(configPath, JSON.stringify({ distinctId }));\n } catch {\n // swallow analytics persistence errors\n }\n}\n\nexport function getMastraAnalyticsDistinctId(configPath = ANALYTICS_CONFIG_PATH): string {\n try {\n if (existsSync(configPath)) {\n const config = JSON.parse(readFileSync(configPath, 'utf-8')) as AnalyticsConfig;\n if (\n config.distinctId &&\n isValidMastraAnalyticsDistinctId(config.distinctId) &&\n !isHostnameDerivedDistinctId(config.distinctId)\n ) {\n return config.distinctId;\n }\n }\n } catch {\n // regenerate below\n }\n\n const distinctId = createMastraAnalyticsDistinctId();\n writeAnalyticsConfig(distinctId, configPath);\n return distinctId;\n}\n\nfunction isAnalyticsDebugEnabled(): boolean {\n return TRUTHY_DISABLED_VALUES.has(process.env.MASTRACODE_ANALYTICS_DEBUG?.trim().toLowerCase() ?? '');\n}\n\nfunction debugAnalytics(message: string, properties?: Record<string, unknown>): void {\n if (!isAnalyticsDebugEnabled()) {\n return;\n }\n\n const suffix = properties ? ` ${JSON.stringify(properties)}` : '';\n process.stderr.write(`[mastracode analytics] ${message}${suffix}\\n`);\n}\n\nexport type MastraCodeAnalyticsEvent =\n | 'mastracode_session_started'\n | 'mastracode_prompt_submitted'\n | 'mastracode_thread_changed'\n | 'mastracode_model_changed'\n | 'mastracode_command_used'\n | 'mastracode_interactive_prompt_shown';\n\nexport interface MastraCodeAnalytics {\n capture(event: MastraCodeAnalyticsEvent, properties?: Record<string, unknown>): void;\n trackCommand(command: string, properties?: Record<string, unknown>): void;\n trackInteractivePrompt(promptType: string, properties?: Record<string, unknown>): void;\n shutdown(): Promise<void>;\n isEnabled(): boolean;\n}\n\ninterface MastraCodeAnalyticsOptions {\n version: string;\n host?: string;\n apiKey?: string;\n}\n\nclass NoopMastraCodeAnalytics implements MastraCodeAnalytics {\n capture(event: MastraCodeAnalyticsEvent): void {\n debugAnalytics('capture skipped: telemetry disabled', { event });\n }\n trackCommand(command: string): void {\n debugAnalytics('command skipped: telemetry disabled', { command });\n }\n trackInteractivePrompt(promptType: string): void {\n debugAnalytics('interactive prompt skipped: telemetry disabled', { promptType });\n }\n async shutdown(): Promise<void> {\n debugAnalytics('shutdown skipped: telemetry disabled');\n }\n isEnabled(): boolean {\n return false;\n }\n}\n\nclass PostHogMastraCodeAnalytics implements MastraCodeAnalytics {\n private readonly client: PostHog;\n private readonly distinctId: string;\n private readonly sessionId = randomUUID();\n private readonly version: string;\n\n constructor({ version, apiKey = POSTHOG_API_KEY, host = POSTHOG_HOST }: MastraCodeAnalyticsOptions) {\n this.version = version;\n this.distinctId = getMastraAnalyticsDistinctId();\n this.client = new PostHog(apiKey, {\n host,\n flushAt: 1,\n flushInterval: 0,\n disableGeoip: false,\n });\n this.client.register({ mastraSource: MASTRA_SOURCE });\n debugAnalytics('enabled', { host, distinctId: this.distinctId, version });\n }\n\n capture(event: MastraCodeAnalyticsEvent, properties?: Record<string, unknown>): void {\n try {\n const eventProperties = {\n ...this.getBaseProperties(),\n ...properties,\n };\n debugAnalytics('capture', { event, properties: eventProperties });\n this.client.capture({\n distinctId: this.distinctId,\n event,\n properties: eventProperties,\n });\n } catch (error) {\n debugAnalytics('capture failed', { event, error: error instanceof Error ? error.message : String(error) });\n // swallow analytics errors\n }\n }\n\n trackCommand(command: string, properties?: Record<string, unknown>): void {\n this.capture('mastracode_command_used', { command, ...properties });\n }\n\n trackInteractivePrompt(promptType: string, properties?: Record<string, unknown>): void {\n this.capture('mastracode_interactive_prompt_shown', { promptType, ...properties });\n }\n\n async shutdown(): Promise<void> {\n try {\n debugAnalytics('shutdown start');\n await this.client.shutdown();\n debugAnalytics('shutdown complete');\n } catch (error) {\n debugAnalytics('shutdown failed', { error: error instanceof Error ? error.message : String(error) });\n // swallow analytics errors\n }\n }\n\n isEnabled(): boolean {\n return true;\n }\n\n private getBaseProperties(): Record<string, unknown> {\n return {\n mastraSource: MASTRA_SOURCE,\n sessionId: this.sessionId,\n version: this.version,\n os: process.platform,\n osVersion: os.release(),\n nodeVersion: process.version,\n platform: process.arch,\n machineId: os.hostname(),\n };\n }\n}\n\nexport function isTelemetryDisabled(env: NodeJS.ProcessEnv = process.env): boolean {\n const value = env.MASTRA_TELEMETRY_DISABLED;\n if (!value) {\n return false;\n }\n\n return TRUTHY_DISABLED_VALUES.has(value.trim().toLowerCase());\n}\n\nexport function createMastraCodeAnalytics(options: MastraCodeAnalyticsOptions): MastraCodeAnalytics {\n if (isTelemetryDisabled()) {\n debugAnalytics('disabled by MASTRA_TELEMETRY_DISABLED', { value: process.env.MASTRA_TELEMETRY_DISABLED });\n return new NoopMastraCodeAnalytics();\n }\n\n return new PostHogMastraCodeAnalytics(options);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"analytics.js","names":[],"sources":["../src/analytics.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { PostHog } from 'posthog-node';\n\nconst POSTHOG_API_KEY = 'phc_SBLpZVAB6jmHOct9CABq3PF0Yn5FU3G2FgT4xUr2XrT';\nconst POSTHOG_HOST = 'https://us.posthog.com';\nconst MASTRA_SOURCE = 'mastracode';\nconst TRUTHY_DISABLED_VALUES = new Set(['1', 'true', 'yes', 'on']);\nconst ANALYTICS_CONFIG_PATH = path.join(os.homedir(), '.mastracode', 'analytics.json');\n\ninterface AnalyticsConfig {\n distinctId?: string;\n}\n\nfunction createMastraAnalyticsDistinctId(): string {\n return `mastra-${randomUUID()}`;\n}\n\nfunction isHostnameDerivedDistinctId(distinctId: string, hostname = os.hostname()): boolean {\n return distinctId === `mastra-${hostname}`;\n}\n\nfunction isValidMastraAnalyticsDistinctId(distinctId: string): boolean {\n return /^mastra-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(distinctId);\n}\n\nfunction writeAnalyticsConfig(distinctId: string, configPath = ANALYTICS_CONFIG_PATH): void {\n try {\n mkdirSync(path.dirname(configPath), { recursive: true });\n writeFileSync(configPath, JSON.stringify({ distinctId }));\n } catch {\n // swallow analytics persistence errors\n }\n}\n\nexport function getMastraAnalyticsDistinctId(configPath = ANALYTICS_CONFIG_PATH): string {\n try {\n if (existsSync(configPath)) {\n const config = JSON.parse(readFileSync(configPath, 'utf-8')) as AnalyticsConfig;\n if (\n config.distinctId &&\n isValidMastraAnalyticsDistinctId(config.distinctId) &&\n !isHostnameDerivedDistinctId(config.distinctId)\n ) {\n return config.distinctId;\n }\n }\n } catch {\n // regenerate below\n }\n\n const distinctId = createMastraAnalyticsDistinctId();\n writeAnalyticsConfig(distinctId, configPath);\n return distinctId;\n}\n\nfunction isAnalyticsDebugEnabled(): boolean {\n return TRUTHY_DISABLED_VALUES.has(process.env.MASTRACODE_ANALYTICS_DEBUG?.trim().toLowerCase() ?? '');\n}\n\nfunction debugAnalytics(message: string, properties?: Record<string, unknown>): void {\n if (!isAnalyticsDebugEnabled()) {\n return;\n }\n\n const suffix = properties ? ` ${JSON.stringify(properties)}` : '';\n process.stderr.write(`[mastracode analytics] ${message}${suffix}\\n`);\n}\n\nexport type MastraCodeAnalyticsEvent =\n | 'mastracode_session_started'\n | 'mastracode_prompt_submitted'\n | 'mastracode_thread_changed'\n | 'mastracode_model_changed'\n | 'mastracode_command_used'\n | 'mastracode_interactive_prompt_shown';\n\nexport interface MastraCodeAnalytics {\n capture(event: MastraCodeAnalyticsEvent, properties?: Record<string, unknown>): void;\n trackCommand(command: string, properties?: Record<string, unknown>): void;\n trackInteractivePrompt(promptType: string, properties?: Record<string, unknown>): void;\n shutdown(): Promise<void>;\n isEnabled(): boolean;\n}\n\ninterface MastraCodeAnalyticsOptions {\n version: string;\n host?: string;\n apiKey?: string;\n}\n\nclass NoopMastraCodeAnalytics implements MastraCodeAnalytics {\n capture(event: MastraCodeAnalyticsEvent): void {\n debugAnalytics('capture skipped: telemetry disabled', { event });\n }\n trackCommand(command: string): void {\n debugAnalytics('command skipped: telemetry disabled', { command });\n }\n trackInteractivePrompt(promptType: string): void {\n debugAnalytics('interactive prompt skipped: telemetry disabled', { promptType });\n }\n async shutdown(): Promise<void> {\n debugAnalytics('shutdown skipped: telemetry disabled');\n }\n isEnabled(): boolean {\n return false;\n }\n}\n\nclass PostHogMastraCodeAnalytics implements MastraCodeAnalytics {\n private readonly client: PostHog;\n private readonly distinctId: string;\n private readonly sessionId = randomUUID();\n private readonly version: string;\n\n constructor({ version, apiKey = POSTHOG_API_KEY, host = POSTHOG_HOST }: MastraCodeAnalyticsOptions) {\n this.version = version;\n this.distinctId = getMastraAnalyticsDistinctId();\n this.client = new PostHog(apiKey, {\n host,\n flushAt: 1,\n flushInterval: 0,\n disableGeoip: false,\n });\n this.client.register({ mastraSource: MASTRA_SOURCE });\n debugAnalytics('enabled', { host, distinctId: this.distinctId, version });\n }\n\n capture(event: MastraCodeAnalyticsEvent, properties?: Record<string, unknown>): void {\n try {\n const eventProperties = {\n ...this.getBaseProperties(),\n ...properties,\n };\n debugAnalytics('capture', { event, properties: eventProperties });\n this.client.capture({\n distinctId: this.distinctId,\n event,\n properties: eventProperties,\n });\n } catch (error) {\n debugAnalytics('capture failed', { event, error: error instanceof Error ? error.message : String(error) });\n // swallow analytics errors\n }\n }\n\n trackCommand(command: string, properties?: Record<string, unknown>): void {\n this.capture('mastracode_command_used', { command, ...properties });\n }\n\n trackInteractivePrompt(promptType: string, properties?: Record<string, unknown>): void {\n this.capture('mastracode_interactive_prompt_shown', { promptType, ...properties });\n }\n\n async shutdown(): Promise<void> {\n try {\n debugAnalytics('shutdown start');\n await this.client.shutdown();\n debugAnalytics('shutdown complete');\n } catch (error) {\n debugAnalytics('shutdown failed', { error: error instanceof Error ? error.message : String(error) });\n // swallow analytics errors\n }\n }\n\n isEnabled(): boolean {\n return true;\n }\n\n private getBaseProperties(): Record<string, unknown> {\n return {\n mastraSource: MASTRA_SOURCE,\n sessionId: this.sessionId,\n version: this.version,\n os: process.platform,\n osVersion: os.release(),\n nodeVersion: process.version,\n platform: process.arch,\n machineId: os.hostname(),\n };\n }\n}\n\nexport function isTelemetryDisabled(env: NodeJS.ProcessEnv = process.env): boolean {\n const value = env.MASTRA_TELEMETRY_DISABLED;\n if (!value) {\n return false;\n }\n\n return TRUTHY_DISABLED_VALUES.has(value.trim().toLowerCase());\n}\n\nexport function createMastraCodeAnalytics(options: MastraCodeAnalyticsOptions): MastraCodeAnalytics {\n if (isTelemetryDisabled()) {\n debugAnalytics('disabled by MASTRA_TELEMETRY_DISABLED', { value: process.env.MASTRA_TELEMETRY_DISABLED });\n return new NoopMastraCodeAnalytics();\n }\n\n return new PostHogMastraCodeAnalytics(options);\n}\n"],"mappings":";;;;;;AAOA,MAAM,kBAAkB;AACxB,MAAM,eAAe;AACrB,MAAM,gBAAgB;AACtB,MAAM,yCAAyB,IAAI,IAAI;CAAC;CAAK;CAAQ;CAAO;AAAI,CAAC;AACjE,MAAM,wBAAwB,KAAK,KAAK,GAAG,QAAQ,GAAG,eAAe,gBAAgB;AAMrF,SAAS,kCAA0C;CACjD,OAAO,UAAU,WAAW;AAC9B;AAEA,SAAS,4BAA4B,YAAoB,WAAW,GAAG,SAAS,GAAY;CAC1F,OAAO,eAAe,UAAU;AAClC;AAEA,SAAS,iCAAiC,YAA6B;CACrE,OAAO,yEAAyE,KAAK,UAAU;AACjG;AAEA,SAAS,qBAAqB,YAAoB,aAAa,uBAA6B;CAC1F,IAAI;EACF,UAAU,KAAK,QAAQ,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;EACvD,cAAc,YAAY,KAAK,UAAU,EAAE,WAAW,CAAC,CAAC;CAC1D,QAAQ,CAER;AACF;AAEA,SAAgB,6BAA6B,aAAa,uBAA+B;CACvF,IAAI;EACF,IAAI,WAAW,UAAU,GAAG;GAC1B,MAAM,SAAS,KAAK,MAAM,aAAa,YAAY,OAAO,CAAC;GAC3D,IACE,OAAO,cACP,iCAAiC,OAAO,UAAU,KAClD,CAAC,4BAA4B,OAAO,UAAU,GAE9C,OAAO,OAAO;EAElB;CACF,QAAQ,CAER;CAEA,MAAM,aAAa,gCAAgC;CACnD,qBAAqB,YAAY,UAAU;CAC3C,OAAO;AACT;AAEA,SAAS,0BAAmC;CAC1C,OAAO,uBAAuB,IAAI,QAAQ,IAAI,4BAA4B,KAAK,CAAC,CAAC,YAAY,KAAK,EAAE;AACtG;AAEA,SAAS,eAAe,SAAiB,YAA4C;CACnF,IAAI,CAAC,wBAAwB,GAC3B;CAGF,MAAM,SAAS,aAAa,IAAI,KAAK,UAAU,UAAU,MAAM;CAC/D,QAAQ,OAAO,MAAM,0BAA0B,UAAU,OAAO,GAAG;AACrE;AAwBA,IAAM,0BAAN,MAA6D;CAC3D,QAAQ,OAAuC;EAC7C,eAAe,uCAAuC,EAAE,MAAM,CAAC;CACjE;CACA,aAAa,SAAuB;EAClC,eAAe,uCAAuC,EAAE,QAAQ,CAAC;CACnE;CACA,uBAAuB,YAA0B;EAC/C,eAAe,kDAAkD,EAAE,WAAW,CAAC;CACjF;CACA,MAAM,WAA0B;EAC9B,eAAe,sCAAsC;CACvD;CACA,YAAqB;EACnB,OAAO;CACT;AACF;AAEA,IAAM,6BAAN,MAAgE;CAC9D;CACA;CACA,YAA6B,WAAW;CACxC;CAEA,YAAY,EAAE,SAAS,SAAS,iBAAiB,OAAO,gBAA4C;EAClG,KAAK,UAAU;EACf,KAAK,aAAa,6BAA6B;EAC/C,KAAK,SAAS,IAAI,QAAQ,QAAQ;GAChC;GACA,SAAS;GACT,eAAe;GACf,cAAc;EAChB,CAAC;EACD,KAAK,OAAO,SAAS,EAAE,cAAc,cAAc,CAAC;EACpD,eAAe,WAAW;GAAE;GAAM,YAAY,KAAK;GAAY;EAAQ,CAAC;CAC1E;CAEA,QAAQ,OAAiC,YAA4C;EACnF,IAAI;GACF,MAAM,kBAAkB;IACtB,GAAG,KAAK,kBAAkB;IAC1B,GAAG;GACL;GACA,eAAe,WAAW;IAAE;IAAO,YAAY;GAAgB,CAAC;GAChE,KAAK,OAAO,QAAQ;IAClB,YAAY,KAAK;IACjB;IACA,YAAY;GACd,CAAC;EACH,SAAS,OAAO;GACd,eAAe,kBAAkB;IAAE;IAAO,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;GAAE,CAAC;EAE3G;CACF;CAEA,aAAa,SAAiB,YAA4C;EACxE,KAAK,QAAQ,2BAA2B;GAAE;GAAS,GAAG;EAAW,CAAC;CACpE;CAEA,uBAAuB,YAAoB,YAA4C;EACrF,KAAK,QAAQ,uCAAuC;GAAE;GAAY,GAAG;EAAW,CAAC;CACnF;CAEA,MAAM,WAA0B;EAC9B,IAAI;GACF,eAAe,gBAAgB;GAC/B,MAAM,KAAK,OAAO,SAAS;GAC3B,eAAe,mBAAmB;EACpC,SAAS,OAAO;GACd,eAAe,mBAAmB,EAAE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,CAAC;EAErG;CACF;CAEA,YAAqB;EACnB,OAAO;CACT;CAEA,oBAAqD;EACnD,OAAO;GACL,cAAc;GACd,WAAW,KAAK;GAChB,SAAS,KAAK;GACd,IAAI,QAAQ;GACZ,WAAW,GAAG,QAAQ;GACtB,aAAa,QAAQ;GACrB,UAAU,QAAQ;GAClB,WAAW,GAAG,SAAS;EACzB;CACF;AACF;AAEA,SAAgB,oBAAoB,MAAyB,QAAQ,KAAc;CACjF,MAAM,QAAQ,IAAI;CAClB,IAAI,CAAC,OACH,OAAO;CAGT,OAAO,uBAAuB,IAAI,MAAM,KAAK,CAAC,CAAC,YAAY,CAAC;AAC9D;AAEA,SAAgB,0BAA0B,SAA0D;CAClG,IAAI,oBAAoB,GAAG;EACzB,eAAe,yCAAyC,EAAE,OAAO,QAAQ,IAAI,0BAA0B,CAAC;EACxG,OAAO,IAAI,wBAAwB;CACrC;CAEA,OAAO,IAAI,2BAA2B,OAAO;AAC/C"}
|
|
@@ -1,28 +1,42 @@
|
|
|
1
|
+
//#region src/auth/authorization-input.ts
|
|
2
|
+
/**
|
|
3
|
+
* Forgiving parser for user-pasted OAuth authorization input.
|
|
4
|
+
*
|
|
5
|
+
* Accepts, in order of preference:
|
|
6
|
+
* - a full redirect URL (`https://.../callback?code=...&state=...`)
|
|
7
|
+
* - the `code#state` form shown on Anthropic's hosted callback page
|
|
8
|
+
* - a raw query string (`code=...&state=...`)
|
|
9
|
+
* - a bare authorization code
|
|
10
|
+
*
|
|
11
|
+
* Ported from pi-mono's `parseAuthorizationInput`.
|
|
12
|
+
*/
|
|
1
13
|
function parseAuthorizationInput(input) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
14
|
+
const value = input.trim();
|
|
15
|
+
if (!value) return {};
|
|
16
|
+
try {
|
|
17
|
+
const url = new URL(value);
|
|
18
|
+
return {
|
|
19
|
+
code: url.searchParams.get("code") ?? void 0,
|
|
20
|
+
state: url.searchParams.get("state") ?? void 0
|
|
21
|
+
};
|
|
22
|
+
} catch {}
|
|
23
|
+
if (value.includes("#")) {
|
|
24
|
+
const [code, state] = value.split("#", 2);
|
|
25
|
+
return {
|
|
26
|
+
code,
|
|
27
|
+
state
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
if (value.includes("code=")) {
|
|
31
|
+
const params = new URLSearchParams(value);
|
|
32
|
+
return {
|
|
33
|
+
code: params.get("code") ?? void 0,
|
|
34
|
+
state: params.get("state") ?? void 0
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return { code: value };
|
|
24
38
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
39
|
+
//#endregion
|
|
40
|
+
export { parseAuthorizationInput };
|
|
41
|
+
|
|
28
42
|
//# sourceMappingURL=authorization-input.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/auth/authorization-input.ts"],"sourcesContent":["/**\n * Forgiving parser for user-pasted OAuth authorization input.\n *\n * Accepts, in order of preference:\n * - a full redirect URL (`https://.../callback?code=...&state=...`)\n * - the `code#state` form shown on Anthropic's hosted callback page\n * - a raw query string (`code=...&state=...`)\n * - a bare authorization code\n *\n * Ported from pi-mono's `parseAuthorizationInput`.\n */\nexport function parseAuthorizationInput(input: string): {\n code?: string;\n state?: string;\n} {\n const value = input.trim();\n if (!value) return {};\n\n try {\n const url = new URL(value);\n return {\n code: url.searchParams.get('code') ?? undefined,\n state: url.searchParams.get('state') ?? undefined,\n };\n } catch {\n // not a URL\n }\n\n if (value.includes('#')) {\n const [code, state] = value.split('#', 2);\n return { code, state };\n }\n\n if (value.includes('code=')) {\n const params = new URLSearchParams(value);\n return {\n code: params.get('code') ?? undefined,\n state: params.get('state') ?? undefined,\n };\n }\n\n return { code: value };\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"authorization-input.js","names":[],"sources":["../../src/auth/authorization-input.ts"],"sourcesContent":["/**\n * Forgiving parser for user-pasted OAuth authorization input.\n *\n * Accepts, in order of preference:\n * - a full redirect URL (`https://.../callback?code=...&state=...`)\n * - the `code#state` form shown on Anthropic's hosted callback page\n * - a raw query string (`code=...&state=...`)\n * - a bare authorization code\n *\n * Ported from pi-mono's `parseAuthorizationInput`.\n */\nexport function parseAuthorizationInput(input: string): {\n code?: string;\n state?: string;\n} {\n const value = input.trim();\n if (!value) return {};\n\n try {\n const url = new URL(value);\n return {\n code: url.searchParams.get('code') ?? undefined,\n state: url.searchParams.get('state') ?? undefined,\n };\n } catch {\n // not a URL\n }\n\n if (value.includes('#')) {\n const [code, state] = value.split('#', 2);\n return { code, state };\n }\n\n if (value.includes('code=')) {\n const params = new URLSearchParams(value);\n return {\n code: params.get('code') ?? undefined,\n state: params.get('state') ?? undefined,\n };\n }\n\n return { code: value };\n}\n"],"mappings":";;;;;;;;;;;;AAWA,SAAgB,wBAAwB,OAGtC;CACA,MAAM,QAAQ,MAAM,KAAK;CACzB,IAAI,CAAC,OAAO,OAAO,CAAC;CAEpB,IAAI;EACF,MAAM,MAAM,IAAI,IAAI,KAAK;EACzB,OAAO;GACL,MAAM,IAAI,aAAa,IAAI,MAAM,KAAK,KAAA;GACtC,OAAO,IAAI,aAAa,IAAI,OAAO,KAAK,KAAA;EAC1C;CACF,QAAQ,CAER;CAEA,IAAI,MAAM,SAAS,GAAG,GAAG;EACvB,MAAM,CAAC,MAAM,SAAS,MAAM,MAAM,KAAK,CAAC;EACxC,OAAO;GAAE;GAAM;EAAM;CACvB;CAEA,IAAI,MAAM,SAAS,OAAO,GAAG;EAC3B,MAAM,SAAS,IAAI,gBAAgB,KAAK;EACxC,OAAO;GACL,MAAM,OAAO,IAAI,MAAM,KAAK,KAAA;GAC5B,OAAO,OAAO,IAAI,OAAO,KAAK,KAAA;EAChC;CACF;CAEA,OAAO,EAAE,MAAM,MAAM;AACvB"}
|
package/dist/auth/device-code.js
CHANGED
|
@@ -1,97 +1,129 @@
|
|
|
1
|
+
//#region src/auth/device-code.ts
|
|
2
|
+
/**
|
|
3
|
+
* Generic RFC 8628 (OAuth 2.0 Device Authorization Grant) polling helpers.
|
|
4
|
+
*
|
|
5
|
+
* Ported from pi-mono's device-code utility, restructured as a single-step
|
|
6
|
+
* API so the same poll semantics can be driven two ways:
|
|
7
|
+
* - `pollDeviceCodeUntilComplete()` — blocking loop for TUI flows.
|
|
8
|
+
* - `stepDeviceCodePoll()` — exactly one upstream poll per call, with a
|
|
9
|
+
* JSON-serializable `DeviceCodePollState` so web routes can persist the
|
|
10
|
+
* state between HTTP requests (any replica can continue the poll).
|
|
11
|
+
*
|
|
12
|
+
* Inspired by pi-mono:
|
|
13
|
+
* https://github.com/badlogic/pi-mono/blob/main/packages/ai/src/utils/oauth/device-code.ts
|
|
14
|
+
*/
|
|
1
15
|
const DEFAULT_INTERVAL_SECONDS = 5;
|
|
2
16
|
const INITIAL_POLL_INTERVAL_MULTIPLIER = 1.2;
|
|
3
17
|
const SLOW_DOWN_POLL_INTERVAL_MULTIPLIER = 1.4;
|
|
4
18
|
const SLOW_DOWN_INTERVAL_INCREMENT_MS = 5e3;
|
|
5
19
|
function createDeviceCodePollState(options) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
20
|
+
const now = options.now ?? Date.now();
|
|
21
|
+
const intervalSeconds = typeof options.intervalSeconds === "number" && options.intervalSeconds > 0 ? options.intervalSeconds : DEFAULT_INTERVAL_SECONDS;
|
|
22
|
+
return {
|
|
23
|
+
deadlineAt: now + options.expiresInSeconds * 1e3,
|
|
24
|
+
intervalMs: Math.max(1e3, Math.floor(intervalSeconds * 1e3)),
|
|
25
|
+
slowDownResponses: 0
|
|
26
|
+
};
|
|
13
27
|
}
|
|
14
28
|
function timeoutMessage(state) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
return "Device flow timed out";
|
|
29
|
+
if (state.slowDownResponses > 0) return "Device flow timed out after one or more slow_down responses. This is often caused by clock drift in WSL or VM environments. Please sync or restart the VM clock and try again.";
|
|
30
|
+
return "Device flow timed out";
|
|
19
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Delay to wait before the next poll, honoring slow_down growth and clamped
|
|
34
|
+
* to the remaining lifetime of the device code.
|
|
35
|
+
*/
|
|
20
36
|
function nextPollDelayMs(state, now = Date.now()) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
37
|
+
const multiplier = state.slowDownResponses > 0 ? SLOW_DOWN_POLL_INTERVAL_MULTIPLIER : INITIAL_POLL_INTERVAL_MULTIPLIER;
|
|
38
|
+
const remainingMs = Math.max(0, state.deadlineAt - now);
|
|
39
|
+
return Math.min(Math.ceil(state.intervalMs * multiplier), remainingMs);
|
|
24
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Perform exactly one upstream poll and fold the outcome into the poll state.
|
|
43
|
+
* Never throws for flow-level conditions — timeouts and provider errors are
|
|
44
|
+
* reported as `{ status: 'failed' }` so callers can persist/report them.
|
|
45
|
+
*/
|
|
25
46
|
async function stepDeviceCodePoll(state, pollOnce, now = Date.now()) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
if (now >= state.deadlineAt) return {
|
|
48
|
+
status: "failed",
|
|
49
|
+
error: timeoutMessage(state),
|
|
50
|
+
state
|
|
51
|
+
};
|
|
52
|
+
const outcome = await pollOnce();
|
|
53
|
+
switch (outcome.status) {
|
|
54
|
+
case "complete": return {
|
|
55
|
+
status: "complete",
|
|
56
|
+
result: outcome.result,
|
|
57
|
+
state
|
|
58
|
+
};
|
|
59
|
+
case "failed": return {
|
|
60
|
+
status: "failed",
|
|
61
|
+
error: outcome.error,
|
|
62
|
+
state
|
|
63
|
+
};
|
|
64
|
+
case "slow_down": {
|
|
65
|
+
const next = {
|
|
66
|
+
...state,
|
|
67
|
+
slowDownResponses: state.slowDownResponses + 1,
|
|
68
|
+
intervalMs: typeof outcome.intervalSeconds === "number" && outcome.intervalSeconds > 0 ? outcome.intervalSeconds * 1e3 : Math.max(1e3, state.intervalMs + SLOW_DOWN_INTERVAL_INCREMENT_MS)
|
|
69
|
+
};
|
|
70
|
+
return {
|
|
71
|
+
status: "slow_down",
|
|
72
|
+
nextPollMs: nextPollDelayMs(next, now),
|
|
73
|
+
state: next
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
case "pending": {
|
|
77
|
+
const next = typeof outcome.intervalSeconds === "number" && outcome.intervalSeconds > 0 ? {
|
|
78
|
+
...state,
|
|
79
|
+
intervalMs: Math.max(1e3, outcome.intervalSeconds * 1e3)
|
|
80
|
+
} : state;
|
|
81
|
+
return {
|
|
82
|
+
status: "pending",
|
|
83
|
+
nextPollMs: nextPollDelayMs(next, now),
|
|
84
|
+
state: next
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
50
88
|
}
|
|
89
|
+
/** Sleep that can be interrupted by an AbortSignal. */
|
|
51
90
|
function abortableSleep(ms, signal) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
91
|
+
return new Promise((resolve, reject) => {
|
|
92
|
+
if (signal?.aborted) {
|
|
93
|
+
reject(/* @__PURE__ */ new Error("Login cancelled"));
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
let timeout;
|
|
97
|
+
const onAbort = () => {
|
|
98
|
+
clearTimeout(timeout);
|
|
99
|
+
reject(/* @__PURE__ */ new Error("Login cancelled"));
|
|
100
|
+
};
|
|
101
|
+
timeout = setTimeout(() => {
|
|
102
|
+
signal?.removeEventListener("abort", onAbort);
|
|
103
|
+
resolve();
|
|
104
|
+
}, ms);
|
|
105
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
106
|
+
});
|
|
68
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Blocking poll loop for TUI flows: waits the appropriate interval between
|
|
110
|
+
* polls, honors slow_down growth, aborts on the signal, and throws on
|
|
111
|
+
* failure/timeout (with a clock-drift hint after slow_down responses).
|
|
112
|
+
*/
|
|
69
113
|
async function pollDeviceCodeUntilComplete(options) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
state = step.state;
|
|
82
|
-
if (step.status === "complete") {
|
|
83
|
-
return step.result;
|
|
84
|
-
}
|
|
85
|
-
if (step.status === "failed") {
|
|
86
|
-
throw new Error(step.error);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
114
|
+
let state = options.state;
|
|
115
|
+
const sleep = options.sleep ?? abortableSleep;
|
|
116
|
+
while (true) {
|
|
117
|
+
if (options.signal?.aborted) throw new Error("Login cancelled");
|
|
118
|
+
if (Date.now() >= state.deadlineAt) throw new Error(timeoutMessage(state));
|
|
119
|
+
await sleep(nextPollDelayMs(state), options.signal);
|
|
120
|
+
const step = await stepDeviceCodePoll(state, options.pollOnce);
|
|
121
|
+
state = step.state;
|
|
122
|
+
if (step.status === "complete") return step.result;
|
|
123
|
+
if (step.status === "failed") throw new Error(step.error);
|
|
124
|
+
}
|
|
89
125
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
nextPollDelayMs,
|
|
94
|
-
pollDeviceCodeUntilComplete,
|
|
95
|
-
stepDeviceCodePoll
|
|
96
|
-
};
|
|
126
|
+
//#endregion
|
|
127
|
+
export { abortableSleep, createDeviceCodePollState, nextPollDelayMs, pollDeviceCodeUntilComplete, stepDeviceCodePoll };
|
|
128
|
+
|
|
97
129
|
//# sourceMappingURL=device-code.js.map
|