@capacitor/cli 9.0.0-alpha.7 → 9.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/android-template.tar.gz +0 -0
- package/assets/capacitor-cordova-android-plugins.tar.gz +0 -0
- package/assets/capacitor-cordova-ios-plugins.tar.gz +0 -0
- package/assets/ios-pods-template.tar.gz +0 -0
- package/assets/ios-spm-template.tar.gz +0 -0
- package/dist/android/network-security-config.js +230 -0
- package/dist/android/update.js +5 -1
- package/dist/common.js +1 -1
- package/dist/config.js +4 -3
- package/dist/cordova.js +8 -17
- package/dist/declarations.d.ts +8 -41
- package/dist/index.js +4 -14
- package/dist/ios/common.js +1 -1
- package/dist/ios/update.js +9 -17
- package/dist/ipc.js +51 -11
- package/dist/plugin.js +1 -1
- package/dist/run-context/declared.js +54 -0
- package/dist/run-context/index.js +111 -0
- package/dist/run-context/registry.js +45 -0
- package/dist/run-context/signals.js +115 -0
- package/dist/run-context/types.js +2 -0
- package/dist/run-context/unknown.js +46 -0
- package/dist/run-context/version.js +74 -0
- package/dist/tasks/copy.js +3 -1
- package/dist/tasks/doctor.js +4 -1
- package/dist/tasks/list.js +1 -1
- package/dist/tasks/migrate-debug-xcconfig.js +60 -0
- package/dist/tasks/migrate-spm.js +0 -1
- package/dist/tasks/migrate-swiftui.js +344 -54
- package/dist/tasks/migrate-to-modern-project.js +27 -0
- package/dist/tasks/migrate.js +41 -4
- package/dist/tasks/run.js +8 -3
- package/dist/tasks/telemetry.js +8 -1
- package/dist/telemetry.js +303 -57
- package/dist/util/capacitor-package.js +95 -146
- package/dist/util/cordova-ios.js +13 -8
- package/dist/util/js.js +1 -1
- package/dist/util/monorepotools.js +2 -2
- package/dist/util/node.js +3 -3
- package/dist/util/npm.js +120 -0
- package/dist/util/spm.js +35 -25
- package/dist/util/subprocess.js +2 -2
- package/dist/util/xcode.js +193 -2
- package/dist/util/xml.js +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectDeclared = void 0;
|
|
4
|
+
const agent_cli_detector_1 = require("agent-cli-detector");
|
|
5
|
+
const registry_1 = require("./registry");
|
|
6
|
+
const strategy = new agent_cli_detector_1.EnvironmentDetectionStrategy();
|
|
7
|
+
/**
|
|
8
|
+
* Identify a registered harness from the variables it sets to announce itself.
|
|
9
|
+
*
|
|
10
|
+
* Driven through the strategy rather than the package's `detectAgent()` because
|
|
11
|
+
* that reduces to a bare `{ detected, agent }` and discards which variable
|
|
12
|
+
* matched — which callers need in order to report an unrecognised harness.
|
|
13
|
+
*
|
|
14
|
+
* Only the agent id and the session variable's *name* leave this function. The
|
|
15
|
+
* evidence also carries each matched variable's live value, and some of those
|
|
16
|
+
* hold access tokens, so nothing else from it is propagated.
|
|
17
|
+
*/
|
|
18
|
+
function detectDeclared(env) {
|
|
19
|
+
var _a, _b;
|
|
20
|
+
// `pid` and `maxProcessDepth` are required by the context type but unread by
|
|
21
|
+
// the environment strategy. Walking the process tree needs a subprocess call
|
|
22
|
+
// with no portable Windows equivalent, so this path stays environment-only.
|
|
23
|
+
const evidence = strategy.detect({
|
|
24
|
+
env,
|
|
25
|
+
agents: registry_1.capacitorAgents,
|
|
26
|
+
pid: 0,
|
|
27
|
+
maxProcessDepth: 0,
|
|
28
|
+
});
|
|
29
|
+
if (evidence.length === 0) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
const matchCounts = new Map();
|
|
33
|
+
for (const { agent } of evidence) {
|
|
34
|
+
matchCounts.set(agent.id, ((_a = matchCounts.get(agent.id)) !== null && _a !== void 0 ? _a : 0) + 1);
|
|
35
|
+
}
|
|
36
|
+
// One environment can satisfy several harnesses at once — an agent CLI run
|
|
37
|
+
// from inside another vendor's terminal declares both. Most matched signals
|
|
38
|
+
// wins; Map iteration preserves registry order, so ties resolve the same way
|
|
39
|
+
// on every platform instead of depending on `Object.keys(env)`.
|
|
40
|
+
let winner = '';
|
|
41
|
+
let best = 0;
|
|
42
|
+
for (const [id, count] of matchCounts) {
|
|
43
|
+
if (count > best) {
|
|
44
|
+
winner = id;
|
|
45
|
+
best = count;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const definition = registry_1.capacitorAgents.find((agent) => agent.id === winner);
|
|
49
|
+
return {
|
|
50
|
+
id: winner,
|
|
51
|
+
sessionVar: (_b = definition === null || definition === void 0 ? void 0 : definition.sessionEnv) === null || _b === void 0 ? void 0 : _b.find((name) => env[name]),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
exports.detectDeclared = detectDeclared;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isAgentDriven = exports.isCI = exports.detectRunContext = exports.CONVENTION_PATTERN = exports.CONVENTION_DENYLIST = void 0;
|
|
4
|
+
const utils_terminal_1 = require("@ionic/utils-terminal");
|
|
5
|
+
const net_1 = require("net");
|
|
6
|
+
const declared_1 = require("./declared");
|
|
7
|
+
const signals_1 = require("./signals");
|
|
8
|
+
const unknown_1 = require("./unknown");
|
|
9
|
+
const version_1 = require("./version");
|
|
10
|
+
var unknown_2 = require("./unknown");
|
|
11
|
+
Object.defineProperty(exports, "CONVENTION_DENYLIST", { enumerable: true, get: function () { return unknown_2.CONVENTION_DENYLIST; } });
|
|
12
|
+
Object.defineProperty(exports, "CONVENTION_PATTERN", { enumerable: true, get: function () { return unknown_2.CONVENTION_PATTERN; } });
|
|
13
|
+
/**
|
|
14
|
+
* Any single signal happens legitimately — a `cat` pager, a missing TTY, a
|
|
15
|
+
* local proxy. Three together, with no terminal anywhere, is what separates a
|
|
16
|
+
* machine-driven run from a developer with an unusual setup.
|
|
17
|
+
*/
|
|
18
|
+
const HEURISTIC_THRESHOLD = 3;
|
|
19
|
+
/**
|
|
20
|
+
* Classify this invocation as human, CI, or agent-driven from the environment
|
|
21
|
+
* alone — no process spawn, no filesystem read.
|
|
22
|
+
*
|
|
23
|
+
* Every input is injectable and nothing is captured at module load, so tests
|
|
24
|
+
* can drive the whole thing. This is also why `@ionic/utils-terminal`'s
|
|
25
|
+
* `TERMINAL_INFO` isn't used: it snapshots the real process when the module is
|
|
26
|
+
* first imported and freezes it.
|
|
27
|
+
*/
|
|
28
|
+
function detectRunContext(options = {}) {
|
|
29
|
+
var _a, _b, _c, _d;
|
|
30
|
+
const env = (_a = options.env) !== null && _a !== void 0 ? _a : process.env;
|
|
31
|
+
const streams = (_b = options.streams) !== null && _b !== void 0 ? _b : readStreamStates();
|
|
32
|
+
const cwd = (_c = options.cwd) !== null && _c !== void 0 ? _c : process.cwd();
|
|
33
|
+
const execPath = (_d = options.execPath) !== null && _d !== void 0 ? _d : process.execPath;
|
|
34
|
+
const scan = (0, signals_1.scanSignals)(env, streams, cwd, execPath);
|
|
35
|
+
const surface = (0, signals_1.deriveSurface)(env, scan);
|
|
36
|
+
// CI is classified but never delivered, so nothing below needs to run.
|
|
37
|
+
if (isCI(env)) {
|
|
38
|
+
return { report: false, surface, confidence: 'none' };
|
|
39
|
+
}
|
|
40
|
+
const declared = (0, declared_1.detectDeclared)(env);
|
|
41
|
+
if (declared) {
|
|
42
|
+
return {
|
|
43
|
+
report: true,
|
|
44
|
+
agentId: declared.id,
|
|
45
|
+
agentVersion: (0, version_1.detectAgentVersion)(env, declared.id),
|
|
46
|
+
surface,
|
|
47
|
+
confidence: 'declared',
|
|
48
|
+
sessionVar: declared.sessionVar,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
// Neither path below may report a run with a terminal attached, which makes
|
|
52
|
+
// "someone at a terminal is never reported as an agent" a guarantee rather
|
|
53
|
+
// than a likelihood. The convention rule needs the gate most: it matches on
|
|
54
|
+
// the shape of a variable name alone, which desktop sessions and shells also
|
|
55
|
+
// produce, yet returns the stronger `declared` confidence.
|
|
56
|
+
const headless = scan.headless.includes(signals_1.NO_TTY_SIGNAL);
|
|
57
|
+
const detectedBy = headless ? (0, unknown_1.detectUnknownHarness)(env) : undefined;
|
|
58
|
+
if (detectedBy) {
|
|
59
|
+
return {
|
|
60
|
+
report: true,
|
|
61
|
+
agentId: 'unknown',
|
|
62
|
+
agentDetectedBy: detectedBy,
|
|
63
|
+
surface,
|
|
64
|
+
confidence: 'declared',
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
// This path exists for harnesses that strip their environment before
|
|
68
|
+
// invoking the CLI.
|
|
69
|
+
const weight = headless ? scan.headless.length + scan.sandbox.length : 0;
|
|
70
|
+
if (weight >= HEURISTIC_THRESHOLD) {
|
|
71
|
+
return {
|
|
72
|
+
report: true,
|
|
73
|
+
agentId: 'unknown',
|
|
74
|
+
surface,
|
|
75
|
+
confidence: 'heuristic',
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
return { report: true, surface, confidence: 'none' };
|
|
79
|
+
}
|
|
80
|
+
exports.detectRunContext = detectRunContext;
|
|
81
|
+
/**
|
|
82
|
+
* Whether this is a build server. Reuses the CLI's existing variable list
|
|
83
|
+
* rather than a copy of it, so the gate can't drift from `isInteractive()`.
|
|
84
|
+
*/
|
|
85
|
+
function isCI(env) {
|
|
86
|
+
return utils_terminal_1.CI_ENVIRONMENT_VARIABLES.some((name) => Boolean(env[name]));
|
|
87
|
+
}
|
|
88
|
+
exports.isCI = isCI;
|
|
89
|
+
/**
|
|
90
|
+
* Whether something other than a person invoked the CLI. True for an
|
|
91
|
+
* unrecognised harness as well as a named one — both mean there is nobody
|
|
92
|
+
* waiting on the terminal.
|
|
93
|
+
*/
|
|
94
|
+
function isAgentDriven(runContext) {
|
|
95
|
+
return Boolean(runContext.agentId);
|
|
96
|
+
}
|
|
97
|
+
exports.isAgentDriven = isAgentDriven;
|
|
98
|
+
function readStreamStates() {
|
|
99
|
+
const { stdin, stdout, stderr } = process;
|
|
100
|
+
return {
|
|
101
|
+
tty: [Boolean(stdin.isTTY), Boolean(stdout.isTTY), Boolean(stderr.isTTY)],
|
|
102
|
+
socket: [isPipe(stdin), isPipe(stdout), isPipe(stderr)],
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* `tty.ReadStream` extends `net.Socket`, so a real terminal has to be excluded
|
|
107
|
+
* rather than just testing the prototype.
|
|
108
|
+
*/
|
|
109
|
+
function isPipe(stream) {
|
|
110
|
+
return stream instanceof net_1.Socket && !stream.isTTY;
|
|
111
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.capacitorAgents = exports.overrideFor = exports.AGENT_OVERRIDES = void 0;
|
|
4
|
+
const agent_cli_detector_1 = require("agent-cli-detector");
|
|
5
|
+
/**
|
|
6
|
+
* Capacitor's additions to the published registry, keyed by the upstream agent
|
|
7
|
+
* id. `agent-cli-detector@0.1.7` matches Codex only through its sandbox
|
|
8
|
+
* markers, knows none of Claude Code's entrypoint or hosted-sandbox variables,
|
|
9
|
+
* and carries no version information for anyone.
|
|
10
|
+
*
|
|
11
|
+
* Keying against the package's own id union means a rename or removal upstream
|
|
12
|
+
* fails to compile instead of silently dropping the entry. It also means this
|
|
13
|
+
* map can only extend a harness the package already lists; a vendor it has
|
|
14
|
+
* never heard of needs an upstream addition first.
|
|
15
|
+
*
|
|
16
|
+
* Re-verify the version variables before every release — vendors rename them
|
|
17
|
+
* between versions.
|
|
18
|
+
*
|
|
19
|
+
* Claude Code's `CLAUDE_CODE_HOST_*_PROXY_PORT` variables are deliberately
|
|
20
|
+
* absent: a wildcard can't be expressed as an `EnvSignal.name`, and they are
|
|
21
|
+
* loopback proxy markers, so `signals.ts` matches them instead.
|
|
22
|
+
*/
|
|
23
|
+
exports.AGENT_OVERRIDES = {
|
|
24
|
+
antigravity: { versionVariable: 'ANTIGRAVITY_LS_VERSION' },
|
|
25
|
+
'claude-code': { env: [{ name: 'CLAUDE_CODE_ENTRYPOINT' }, { name: 'CLAUDE_TMPDIR' }] },
|
|
26
|
+
codex: {
|
|
27
|
+
env: [{ name: 'CODEX_VERSION' }, { name: 'CODEX_SANDBOX' }],
|
|
28
|
+
versionVariable: 'CODEX_VERSION',
|
|
29
|
+
},
|
|
30
|
+
kilocode: { versionVariable: 'KILOCODE_VERSION' },
|
|
31
|
+
muse: { versionVariable: 'MUSE_RELEASE_INFO', versionIsJson: true },
|
|
32
|
+
};
|
|
33
|
+
function overrideFor(agentId) {
|
|
34
|
+
return exports.AGENT_OVERRIDES[agentId];
|
|
35
|
+
}
|
|
36
|
+
exports.overrideFor = overrideFor;
|
|
37
|
+
/**
|
|
38
|
+
* The published registry with Capacitor's additions layered on. Extending a
|
|
39
|
+
* listed harness means editing `AGENT_OVERRIDES` and nothing else.
|
|
40
|
+
*/
|
|
41
|
+
exports.capacitorAgents = agent_cli_detector_1.defaultAgents.map((agent) => {
|
|
42
|
+
var _a, _b;
|
|
43
|
+
const extra = (_a = overrideFor(agent.id)) === null || _a === void 0 ? void 0 : _a.env;
|
|
44
|
+
return extra ? { ...agent, env: [...((_b = agent.env) !== null && _b !== void 0 ? _b : []), ...extra] } : agent;
|
|
45
|
+
});
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deriveSurface = exports.scanSignals = exports.NO_TTY_SIGNAL = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* No standard stream is attached to a terminal. The strongest of the headless
|
|
6
|
+
* signals, and the one the heuristic verdict is gated on.
|
|
7
|
+
*/
|
|
8
|
+
exports.NO_TTY_SIGNAL = 'no-tty';
|
|
9
|
+
/**
|
|
10
|
+
* Variables whose value is a proxy target. The `_PORT` spelling is how hosted
|
|
11
|
+
* Claude Code sandboxes expose theirs.
|
|
12
|
+
*/
|
|
13
|
+
const PROXY_VARIABLE_PATTERN = /_PROXY$|_PROXY_PORT$|^(?:HTTP|HTTPS|ALL)_PROXY$/;
|
|
14
|
+
const LOOPBACK_PATTERN = /(?:^|\/\/|@)(?:127\.0\.0\.1|localhost|\[::1\]|0\.0\.0\.0)(?::\d+)?(?:$|[/?])/i;
|
|
15
|
+
/**
|
|
16
|
+
* Some hosted sandboxes mint an adjective-adjective-surname username per
|
|
17
|
+
* session. Inferred from observed sandboxes, not documented by any vendor —
|
|
18
|
+
* which is why it only ever contributes to a heuristic verdict.
|
|
19
|
+
*/
|
|
20
|
+
const GENERATED_USERNAME_PATTERN = /^[a-z]+[-_][a-z]+[-_][a-z]+$/;
|
|
21
|
+
/** A session-scoped mount carries a generated id in its path. Also inferred. */
|
|
22
|
+
const SESSION_MOUNT_PATTERN = /[/\\](?:sessions?|workspaces?)[/\\][0-9a-f][0-9a-f-]{7,}/i;
|
|
23
|
+
const JAVA_AGENT_PATTERN = /-javaagent/i;
|
|
24
|
+
const JETBRAINS_TERMINAL_PATTERN = /jetbrains/i;
|
|
25
|
+
function scanSignals(env, streams, cwd, execPath) {
|
|
26
|
+
return {
|
|
27
|
+
headless: scanHeadless(env, streams),
|
|
28
|
+
sandbox: scanSandbox(env, cwd, execPath),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
exports.scanSignals = scanSignals;
|
|
32
|
+
/**
|
|
33
|
+
* Derive the execution environment, most specific match first. Independent of
|
|
34
|
+
* the agent verdict by design, so a terminal agent and an IDE agent are
|
|
35
|
+
* distinguishable downstream.
|
|
36
|
+
*/
|
|
37
|
+
function deriveSurface(env, scan) {
|
|
38
|
+
if (scan.sandbox.length > 0) {
|
|
39
|
+
return 'cloud-sandbox';
|
|
40
|
+
}
|
|
41
|
+
if (isDesktopShell(env)) {
|
|
42
|
+
return 'desktop-app';
|
|
43
|
+
}
|
|
44
|
+
if (isIde(env)) {
|
|
45
|
+
return 'ide';
|
|
46
|
+
}
|
|
47
|
+
return 'terminal';
|
|
48
|
+
}
|
|
49
|
+
exports.deriveSurface = deriveSurface;
|
|
50
|
+
function scanHeadless(env, streams) {
|
|
51
|
+
const signals = [];
|
|
52
|
+
if (!streams.tty.some(Boolean)) {
|
|
53
|
+
signals.push(exports.NO_TTY_SIGNAL);
|
|
54
|
+
}
|
|
55
|
+
if (streams.socket.some(Boolean)) {
|
|
56
|
+
signals.push('stream-socket');
|
|
57
|
+
}
|
|
58
|
+
// A human wouldn't set contradictory color rules; a wrapper assembling an
|
|
59
|
+
// environment from defaults does.
|
|
60
|
+
if (env.NO_COLOR && env.CLICOLOR_FORCE) {
|
|
61
|
+
signals.push('contradictory-color');
|
|
62
|
+
}
|
|
63
|
+
if (env.PAGER === 'cat' || env.GIT_PAGER === 'cat' || env.GIT_EDITOR === 'true') {
|
|
64
|
+
signals.push('pager-disabled');
|
|
65
|
+
}
|
|
66
|
+
if (isDesktopShell(env)) {
|
|
67
|
+
signals.push('gui-bundle-no-term');
|
|
68
|
+
}
|
|
69
|
+
return signals;
|
|
70
|
+
}
|
|
71
|
+
function scanSandbox(env, cwd, execPath) {
|
|
72
|
+
var _a, _b;
|
|
73
|
+
const signals = [];
|
|
74
|
+
if (countLoopbackProxies(env) >= 3) {
|
|
75
|
+
signals.push('loopback-proxies');
|
|
76
|
+
}
|
|
77
|
+
if (env.SANDBOX_RUNTIME) {
|
|
78
|
+
signals.push('sandbox-runtime');
|
|
79
|
+
}
|
|
80
|
+
if (env.JAVA_TOOL_OPTIONS && JAVA_AGENT_PATTERN.test(env.JAVA_TOOL_OPTIONS)) {
|
|
81
|
+
signals.push('java-tool-options-agent');
|
|
82
|
+
}
|
|
83
|
+
if (GENERATED_USERNAME_PATTERN.test((_b = (_a = env.USER) !== null && _a !== void 0 ? _a : env.USERNAME) !== null && _b !== void 0 ? _b : '')) {
|
|
84
|
+
signals.push('generated-username');
|
|
85
|
+
}
|
|
86
|
+
if (SESSION_MOUNT_PATTERN.test(cwd) || SESSION_MOUNT_PATTERN.test(execPath)) {
|
|
87
|
+
signals.push('session-mount');
|
|
88
|
+
}
|
|
89
|
+
return signals;
|
|
90
|
+
}
|
|
91
|
+
function countLoopbackProxies(env) {
|
|
92
|
+
return Object.entries(env).filter(([name, value]) => {
|
|
93
|
+
const normalized = name.toUpperCase();
|
|
94
|
+
if (!value || !PROXY_VARIABLE_PATTERN.test(normalized)) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
// A bare port is only ever a local one, so `*_PROXY_PORT` needs no host.
|
|
98
|
+
return normalized.endsWith('_PORT') ? /^\d+$/.test(value) : LOOPBACK_PATTERN.test(value);
|
|
99
|
+
}).length;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* A GUI application spawned a bare shell. Shared by the headless scan and the
|
|
103
|
+
* surface derivation so the two can't drift apart.
|
|
104
|
+
*/
|
|
105
|
+
function isDesktopShell(env) {
|
|
106
|
+
return Boolean(env.__CFBundleIdentifier || env.ELECTRON_RUN_AS_NODE) && !env.TERM;
|
|
107
|
+
}
|
|
108
|
+
function isIde(env) {
|
|
109
|
+
var _a;
|
|
110
|
+
return Boolean(env.VSCODE_PID ||
|
|
111
|
+
env.VSCODE_GIT_ASKPASS_NODE ||
|
|
112
|
+
env.JETBRAINS_IDE ||
|
|
113
|
+
env.TERM_PROGRAM === 'vscode' ||
|
|
114
|
+
JETBRAINS_TERMINAL_PATTERN.test((_a = env.TERMINAL_EMULATOR) !== null && _a !== void 0 ? _a : ''));
|
|
115
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectUnknownHarness = exports.CONVENTION_DENYLIST = exports.CONVENTION_PATTERN = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Agent harnesses name their declaring variables consistently, so one missing
|
|
6
|
+
* from the registry can still be noticed by shape alone. A name that shows up
|
|
7
|
+
* across many projects is the signal to register the vendor properly.
|
|
8
|
+
*/
|
|
9
|
+
exports.CONVENTION_PATTERN = /^[A-Z0-9_]+_(AGENT|TOOL_USE_ID|SESSION_ID|THREAD_ID|CONVERSATION_ID|TRAJECTORY_ID)$/;
|
|
10
|
+
/**
|
|
11
|
+
* Non-agent tools that follow the same convention. Terminals, SSH and GPG all
|
|
12
|
+
* mint session identifiers of their own. Tested one entry at a time.
|
|
13
|
+
*
|
|
14
|
+
* The caller only consults this rule for a run with no terminal attached, so a
|
|
15
|
+
* name missing here can only affect a headless run.
|
|
16
|
+
*/
|
|
17
|
+
exports.CONVENTION_DENYLIST = [
|
|
18
|
+
'TERM_SESSION_ID',
|
|
19
|
+
'ITERM_SESSION_ID',
|
|
20
|
+
'SSH_SESSION_ID',
|
|
21
|
+
'XDG_SESSION_ID',
|
|
22
|
+
'USER_AGENT',
|
|
23
|
+
'HTTP_USER_AGENT',
|
|
24
|
+
'GPG_AGENT',
|
|
25
|
+
'SSH_AGENT',
|
|
26
|
+
];
|
|
27
|
+
/**
|
|
28
|
+
* Return the name of the first variable that looks like an unregistered
|
|
29
|
+
* harness, or undefined. Names are sorted so the result doesn't depend on
|
|
30
|
+
* environment insertion order.
|
|
31
|
+
*/
|
|
32
|
+
function detectUnknownHarness(env) {
|
|
33
|
+
for (const name of Object.keys(env).sort()) {
|
|
34
|
+
// Windows environment variables are case-insensitive, so normalize before
|
|
35
|
+
// both tests — otherwise a denylisted name in mixed case slips through.
|
|
36
|
+
const normalized = name.toUpperCase();
|
|
37
|
+
if (exports.CONVENTION_DENYLIST.includes(normalized)) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (exports.CONVENTION_PATTERN.test(normalized)) {
|
|
41
|
+
return name;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
exports.detectUnknownHarness = detectUnknownHarness;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectAgentVersion = void 0;
|
|
4
|
+
const semver_1 = require("semver");
|
|
5
|
+
const registry_1 = require("./registry");
|
|
6
|
+
/**
|
|
7
|
+
* Several harnesses set `AI_AGENT` in a shared `<vendor>_<version>_agent`
|
|
8
|
+
* format, with the version's dots written as dashes. It's the only
|
|
9
|
+
* non-per-vendor source, so a harness adopting the convention is picked up
|
|
10
|
+
* without a registry change.
|
|
11
|
+
*/
|
|
12
|
+
const AI_AGENT_PATTERN = /^[A-Za-z0-9-]+_(\d[\d-]*)_agent$/;
|
|
13
|
+
/**
|
|
14
|
+
* Resolve the harness version from the first source that carries one.
|
|
15
|
+
*
|
|
16
|
+
* "First source" means first *present*, not first valid: a harness that sets
|
|
17
|
+
* `AI_AGENT` to something malformed reports `unknown` rather than falling
|
|
18
|
+
* through to a variable it never set.
|
|
19
|
+
*
|
|
20
|
+
* Both sources are environment variables by design. The executable path looks
|
|
21
|
+
* like a third, but it is always the Node binary running the CLI rather than
|
|
22
|
+
* the harness's entrypoint — reading a version out of it reports the user's
|
|
23
|
+
* nvm or Homebrew Node version as the agent's.
|
|
24
|
+
*/
|
|
25
|
+
function detectAgentVersion(env, agentId) {
|
|
26
|
+
var _a;
|
|
27
|
+
const raw = (_a = fromAiAgent(env)) !== null && _a !== void 0 ? _a : fromVendorVariable(env, agentId);
|
|
28
|
+
return raw && (0, semver_1.valid)(raw) ? raw : 'unknown';
|
|
29
|
+
}
|
|
30
|
+
exports.detectAgentVersion = detectAgentVersion;
|
|
31
|
+
function fromAiAgent(env) {
|
|
32
|
+
const value = env.AI_AGENT;
|
|
33
|
+
if (!value) {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
const match = AI_AGENT_PATTERN.exec(value);
|
|
37
|
+
// An unparseable value is still a hit — it gets rejected by semver below.
|
|
38
|
+
return match ? match[1].replace(/-/g, '.') : value;
|
|
39
|
+
}
|
|
40
|
+
function fromVendorVariable(env, agentId) {
|
|
41
|
+
var _a;
|
|
42
|
+
const override = (0, registry_1.overrideFor)(agentId);
|
|
43
|
+
if (!(override === null || override === void 0 ? void 0 : override.versionVariable)) {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
const value = env[override.versionVariable];
|
|
47
|
+
if (!value) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
return override.versionIsJson ? ((_a = fromJson(value)) !== null && _a !== void 0 ? _a : value) : value;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Pull a version out of a JSON-valued vendor variable. The field name isn't
|
|
54
|
+
* documented by any vendor we've seen, so the common spellings are tried and
|
|
55
|
+
* anything else falls through to semver rejection.
|
|
56
|
+
*/
|
|
57
|
+
function fromJson(value) {
|
|
58
|
+
try {
|
|
59
|
+
const parsed = JSON.parse(value);
|
|
60
|
+
if (typeof parsed !== 'object' || parsed === null) {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
const record = parsed;
|
|
64
|
+
for (const field of ['version', 'release', 'tag']) {
|
|
65
|
+
if (typeof record[field] === 'string') {
|
|
66
|
+
return record[field];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
}
|
package/dist/tasks/copy.js
CHANGED
|
@@ -57,7 +57,9 @@ async function copy(config, platformName, inline = false) {
|
|
|
57
57
|
usesLiveUpdates = true;
|
|
58
58
|
}
|
|
59
59
|
let usesSSLPinning = false;
|
|
60
|
-
if (allPlugins.filter((plugin) => plugin.id === '@ionic-enterprise/ssl-pinning' ||
|
|
60
|
+
if (allPlugins.filter((plugin) => plugin.id === '@ionic-enterprise/ssl-pinning' ||
|
|
61
|
+
plugin.id === '@capacitor/ssl-pinning' ||
|
|
62
|
+
plugin.id === '@capacitor-community/ssl-pinning').length > 0) {
|
|
61
63
|
usesSSLPinning = true;
|
|
62
64
|
}
|
|
63
65
|
if (platformName === config.ios.name) {
|
package/dist/tasks/doctor.js
CHANGED
|
@@ -10,6 +10,7 @@ const doctor_2 = require("../ios/doctor");
|
|
|
10
10
|
const log_1 = require("../log");
|
|
11
11
|
const emoji_1 = require("../util/emoji");
|
|
12
12
|
const node_1 = require("../util/node");
|
|
13
|
+
const npm_1 = require("../util/npm");
|
|
13
14
|
const subprocess_1 = require("../util/subprocess");
|
|
14
15
|
async function doctorCommand(config, selectedPlatformName) {
|
|
15
16
|
log_1.output.write(`${(0, emoji_1.emoji)('💊', '')} ${colors_1.default.strong('Capacitor Doctor')} ${(0, emoji_1.emoji)('💊', '')} \n\n`);
|
|
@@ -21,11 +22,12 @@ async function doctorCommand(config, selectedPlatformName) {
|
|
|
21
22
|
}
|
|
22
23
|
exports.doctorCommand = doctorCommand;
|
|
23
24
|
async function doctorCore(config) {
|
|
24
|
-
const [cliVersion, coreVersion, androidVersion, iosVersion] = await Promise.all([
|
|
25
|
+
const [cliVersion, coreVersion, androidVersion, iosVersion, blockedInstallScripts] = await Promise.all([
|
|
25
26
|
(0, subprocess_1.getCommandOutput)('npm', ['info', '@capacitor/cli', 'version']),
|
|
26
27
|
(0, subprocess_1.getCommandOutput)('npm', ['info', '@capacitor/core', 'version']),
|
|
27
28
|
(0, subprocess_1.getCommandOutput)('npm', ['info', '@capacitor/android', 'version']),
|
|
28
29
|
(0, subprocess_1.getCommandOutput)('npm', ['info', '@capacitor/ios', 'version']),
|
|
30
|
+
(0, npm_1.getBlockedInstallScripts)(config.app.rootDir),
|
|
29
31
|
]);
|
|
30
32
|
log_1.output.write(`${colors_1.default.strong('Latest Dependencies:')}\n\n` +
|
|
31
33
|
` @capacitor/cli: ${colors_1.default.weak(cliVersion !== null && cliVersion !== void 0 ? cliVersion : 'unknown')}\n` +
|
|
@@ -35,6 +37,7 @@ async function doctorCore(config) {
|
|
|
35
37
|
`${colors_1.default.strong('Installed Dependencies:')}\n\n`);
|
|
36
38
|
await printInstalledPackages(config);
|
|
37
39
|
log_1.output.write('\n');
|
|
40
|
+
(0, npm_1.logBlockedInstallScripts)(blockedInstallScripts);
|
|
38
41
|
}
|
|
39
42
|
exports.doctorCore = doctorCore;
|
|
40
43
|
async function printInstalledPackages(config) {
|
package/dist/tasks/list.js
CHANGED
|
@@ -26,7 +26,7 @@ async function listCommand(config, selectedPlatformName) {
|
|
|
26
26
|
exports.listCommand = listCommand;
|
|
27
27
|
async function list(config, platform) {
|
|
28
28
|
const allPlugins = await (0, plugin_1.getPlugins)(config, platform);
|
|
29
|
-
let plugins
|
|
29
|
+
let plugins;
|
|
30
30
|
if (platform === config.ios.name) {
|
|
31
31
|
plugins = await (0, common_3.getIOSPlugins)(allPlugins);
|
|
32
32
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.__testables = exports.removeDebugXcconfig = void 0;
|
|
4
|
+
const fs_extra_1 = require("fs-extra");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const log_1 = require("../log");
|
|
7
|
+
const spm_1 = require("../util/spm");
|
|
8
|
+
const xcode_1 = require("../util/xcode");
|
|
9
|
+
const STOCK_LINE = /^CAPACITOR_DEBUG\s*=\s*true$/;
|
|
10
|
+
async function removeDebugXcconfig(config) {
|
|
11
|
+
if ((await config.ios.packageManager) !== 'SPM') {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const xcconfigPath = (0, path_1.join)(config.ios.platformDirAbs, 'debug.xcconfig');
|
|
15
|
+
const state = classifyDebugXcconfig(xcconfigPath);
|
|
16
|
+
if (state === 'customized') {
|
|
17
|
+
log_1.logger.warn(`${xcconfigPath} declares build settings besides CAPACITOR_DEBUG, leaving it in place. ` +
|
|
18
|
+
`Remove the CAPACITOR_DEBUG line yourself — Capacitor 9 no longer reads it.`);
|
|
19
|
+
}
|
|
20
|
+
else if (state === 'stock' && unregisterFromXcodeProject(config)) {
|
|
21
|
+
await (0, fs_extra_1.remove)(xcconfigPath);
|
|
22
|
+
log_1.logger.info(`Removed ${xcconfigPath}.`);
|
|
23
|
+
}
|
|
24
|
+
const result = (0, spm_1.removeInfoPlistDebug)(config);
|
|
25
|
+
if (result.status === 'skipped') {
|
|
26
|
+
log_1.logger.warn(`CAPACITOR_DEBUG not removed from Info.plist: ${result.reason}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
exports.removeDebugXcconfig = removeDebugXcconfig;
|
|
30
|
+
/**
|
|
31
|
+
* Deleting the file while the Debug build configuration still points at it fails the
|
|
32
|
+
* Xcode build, so the file only goes once the project has been rewritten.
|
|
33
|
+
*/
|
|
34
|
+
function unregisterFromXcodeProject(config) {
|
|
35
|
+
var _a;
|
|
36
|
+
const pbxprojPath = (0, path_1.join)(config.ios.nativeXcodeProjDirAbs, 'project.pbxproj');
|
|
37
|
+
try {
|
|
38
|
+
(0, xcode_1.removeBaseConfigurationFile)(pbxprojPath, 'debug.xcconfig');
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
log_1.logger.warn(`Could not remove the debug.xcconfig reference from ${pbxprojPath}: ${(_a = err === null || err === void 0 ? void 0 : err.message) !== null && _a !== void 0 ? _a : err}. ` +
|
|
43
|
+
`Remove debug.xcconfig from the Xcode project manually.`);
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function classifyDebugXcconfig(path) {
|
|
48
|
+
if (!(0, fs_extra_1.existsSync)(path)) {
|
|
49
|
+
return 'absent';
|
|
50
|
+
}
|
|
51
|
+
const settings = (0, fs_extra_1.readFileSync)(path, 'utf-8')
|
|
52
|
+
.split('\n')
|
|
53
|
+
.map((line) => line.trim())
|
|
54
|
+
.filter((line) => line.length > 0 && !line.startsWith('//'));
|
|
55
|
+
return settings.every((line) => STOCK_LINE.test(line)) ? 'stock' : 'customized';
|
|
56
|
+
}
|
|
57
|
+
// Exported for tests.
|
|
58
|
+
exports.__testables = {
|
|
59
|
+
classifyDebugXcconfig,
|
|
60
|
+
};
|
|
@@ -15,7 +15,6 @@ async function migrateToSPM(config) {
|
|
|
15
15
|
await (0, spm_1.extractSPMPackageDirectory)(config);
|
|
16
16
|
await (0, spm_1.runCocoapodsDeintegrate)(config);
|
|
17
17
|
await (0, spm_1.removeCocoapodsFiles)(config);
|
|
18
|
-
await (0, spm_1.addInfoPlistDebugIfNeeded)(config);
|
|
19
18
|
const configWritable = config;
|
|
20
19
|
configWritable.ios.packageManager = Promise.resolve('SPM');
|
|
21
20
|
await (0, update_1.update)(configWritable, 'ios', false);
|