@adhdev/daemon-core 0.5.24 → 0.5.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -569,15 +569,15 @@ async function detectIDEs() {
569
569
  var import_child_process2 = require("child_process");
570
570
  var os2 = __toESM(require("os"));
571
571
  function execAsync(cmd, timeoutMs = 5e3) {
572
- return new Promise((resolve7) => {
572
+ return new Promise((resolve8) => {
573
573
  const child = (0, import_child_process2.exec)(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
574
574
  if (err || !stdout?.trim()) {
575
- resolve7(null);
575
+ resolve8(null);
576
576
  } else {
577
- resolve7(stdout.trim());
577
+ resolve8(stdout.trim());
578
578
  }
579
579
  });
580
- child.on("error", () => resolve7(null));
580
+ child.on("error", () => resolve8(null));
581
581
  });
582
582
  }
583
583
  async function detectCLIs(providerLoader) {
@@ -935,7 +935,7 @@ var DaemonCdpManager = class {
935
935
  * Returns multiple entries if multiple IDE windows are open on same port
936
936
  */
937
937
  static listAllTargets(port) {
938
- return new Promise((resolve7) => {
938
+ return new Promise((resolve8) => {
939
939
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
940
940
  let data = "";
941
941
  res.on("data", (chunk) => data += chunk.toString());
@@ -951,16 +951,16 @@ var DaemonCdpManager = class {
951
951
  (t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
952
952
  );
953
953
  const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
954
- resolve7(mainPages.length > 0 ? mainPages : fallbackPages);
954
+ resolve8(mainPages.length > 0 ? mainPages : fallbackPages);
955
955
  } catch {
956
- resolve7([]);
956
+ resolve8([]);
957
957
  }
958
958
  });
959
959
  });
960
- req.on("error", () => resolve7([]));
960
+ req.on("error", () => resolve8([]));
961
961
  req.setTimeout(2e3, () => {
962
962
  req.destroy();
963
- resolve7([]);
963
+ resolve8([]);
964
964
  });
965
965
  });
966
966
  }
@@ -1000,7 +1000,7 @@ var DaemonCdpManager = class {
1000
1000
  }
1001
1001
  }
1002
1002
  findTargetOnPort(port) {
1003
- return new Promise((resolve7) => {
1003
+ return new Promise((resolve8) => {
1004
1004
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
1005
1005
  let data = "";
1006
1006
  res.on("data", (chunk) => data += chunk.toString());
@@ -1011,7 +1011,7 @@ var DaemonCdpManager = class {
1011
1011
  (t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
1012
1012
  );
1013
1013
  if (pages.length === 0) {
1014
- resolve7(targets.find((t) => t.webSocketDebuggerUrl) || null);
1014
+ resolve8(targets.find((t) => t.webSocketDebuggerUrl) || null);
1015
1015
  return;
1016
1016
  }
1017
1017
  const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
@@ -1021,24 +1021,24 @@ var DaemonCdpManager = class {
1021
1021
  const specific = list.find((t) => t.id === this._targetId);
1022
1022
  if (specific) {
1023
1023
  this._pageTitle = specific.title || "";
1024
- resolve7(specific);
1024
+ resolve8(specific);
1025
1025
  } else {
1026
1026
  this.log(`[CDP] Target ${this._targetId} not found in page list`);
1027
- resolve7(null);
1027
+ resolve8(null);
1028
1028
  }
1029
1029
  return;
1030
1030
  }
1031
1031
  this._pageTitle = list[0]?.title || "";
1032
- resolve7(list[0]);
1032
+ resolve8(list[0]);
1033
1033
  } catch {
1034
- resolve7(null);
1034
+ resolve8(null);
1035
1035
  }
1036
1036
  });
1037
1037
  });
1038
- req.on("error", () => resolve7(null));
1038
+ req.on("error", () => resolve8(null));
1039
1039
  req.setTimeout(2e3, () => {
1040
1040
  req.destroy();
1041
- resolve7(null);
1041
+ resolve8(null);
1042
1042
  });
1043
1043
  });
1044
1044
  }
@@ -1049,7 +1049,7 @@ var DaemonCdpManager = class {
1049
1049
  this.extensionProviders = providers;
1050
1050
  }
1051
1051
  connectToTarget(wsUrl) {
1052
- return new Promise((resolve7) => {
1052
+ return new Promise((resolve8) => {
1053
1053
  this.ws = new import_ws.default(wsUrl);
1054
1054
  this.ws.on("open", async () => {
1055
1055
  this._connected = true;
@@ -1059,17 +1059,17 @@ var DaemonCdpManager = class {
1059
1059
  }
1060
1060
  this.connectBrowserWs().catch(() => {
1061
1061
  });
1062
- resolve7(true);
1062
+ resolve8(true);
1063
1063
  });
1064
1064
  this.ws.on("message", (data) => {
1065
1065
  try {
1066
1066
  const msg = JSON.parse(data.toString());
1067
1067
  if (msg.id && this.pending.has(msg.id)) {
1068
- const { resolve: resolve8, reject } = this.pending.get(msg.id);
1068
+ const { resolve: resolve9, reject } = this.pending.get(msg.id);
1069
1069
  this.pending.delete(msg.id);
1070
1070
  this.failureCount = 0;
1071
1071
  if (msg.error) reject(new Error(msg.error.message));
1072
- else resolve8(msg.result);
1072
+ else resolve9(msg.result);
1073
1073
  } else if (msg.method === "Runtime.executionContextCreated") {
1074
1074
  this.contexts.add(msg.params.context.id);
1075
1075
  } else if (msg.method === "Runtime.executionContextDestroyed") {
@@ -1092,7 +1092,7 @@ var DaemonCdpManager = class {
1092
1092
  this.ws.on("error", (err) => {
1093
1093
  this.log(`[CDP] WebSocket error: ${err.message}`);
1094
1094
  this._connected = false;
1095
- resolve7(false);
1095
+ resolve8(false);
1096
1096
  });
1097
1097
  });
1098
1098
  }
@@ -1106,7 +1106,7 @@ var DaemonCdpManager = class {
1106
1106
  return;
1107
1107
  }
1108
1108
  this.log(`[CDP] Connecting browser WS for target discovery...`);
1109
- await new Promise((resolve7, reject) => {
1109
+ await new Promise((resolve8, reject) => {
1110
1110
  this.browserWs = new import_ws.default(browserWsUrl);
1111
1111
  this.browserWs.on("open", async () => {
1112
1112
  this._browserConnected = true;
@@ -1116,16 +1116,16 @@ var DaemonCdpManager = class {
1116
1116
  } catch (e) {
1117
1117
  this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
1118
1118
  }
1119
- resolve7();
1119
+ resolve8();
1120
1120
  });
1121
1121
  this.browserWs.on("message", (data) => {
1122
1122
  try {
1123
1123
  const msg = JSON.parse(data.toString());
1124
1124
  if (msg.id && this.browserPending.has(msg.id)) {
1125
- const { resolve: resolve8, reject: reject2 } = this.browserPending.get(msg.id);
1125
+ const { resolve: resolve9, reject: reject2 } = this.browserPending.get(msg.id);
1126
1126
  this.browserPending.delete(msg.id);
1127
1127
  if (msg.error) reject2(new Error(msg.error.message));
1128
- else resolve8(msg.result);
1128
+ else resolve9(msg.result);
1129
1129
  }
1130
1130
  } catch {
1131
1131
  }
@@ -1145,31 +1145,31 @@ var DaemonCdpManager = class {
1145
1145
  }
1146
1146
  }
1147
1147
  getBrowserWsUrl() {
1148
- return new Promise((resolve7) => {
1148
+ return new Promise((resolve8) => {
1149
1149
  const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
1150
1150
  let data = "";
1151
1151
  res.on("data", (chunk) => data += chunk.toString());
1152
1152
  res.on("end", () => {
1153
1153
  try {
1154
1154
  const info = JSON.parse(data);
1155
- resolve7(info.webSocketDebuggerUrl || null);
1155
+ resolve8(info.webSocketDebuggerUrl || null);
1156
1156
  } catch {
1157
- resolve7(null);
1157
+ resolve8(null);
1158
1158
  }
1159
1159
  });
1160
1160
  });
1161
- req.on("error", () => resolve7(null));
1161
+ req.on("error", () => resolve8(null));
1162
1162
  req.setTimeout(3e3, () => {
1163
1163
  req.destroy();
1164
- resolve7(null);
1164
+ resolve8(null);
1165
1165
  });
1166
1166
  });
1167
1167
  }
1168
1168
  sendBrowser(method, params = {}, timeoutMs = 15e3) {
1169
- return new Promise((resolve7, reject) => {
1169
+ return new Promise((resolve8, reject) => {
1170
1170
  if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
1171
1171
  const id = this.browserMsgId++;
1172
- this.browserPending.set(id, { resolve: resolve7, reject });
1172
+ this.browserPending.set(id, { resolve: resolve8, reject });
1173
1173
  this.browserWs.send(JSON.stringify({ id, method, params }));
1174
1174
  setTimeout(() => {
1175
1175
  if (this.browserPending.has(id)) {
@@ -1209,11 +1209,11 @@ var DaemonCdpManager = class {
1209
1209
  }
1210
1210
  // ─── CDP Protocol ────────────────────────────────────────
1211
1211
  sendInternal(method, params = {}, timeoutMs = 15e3) {
1212
- return new Promise((resolve7, reject) => {
1212
+ return new Promise((resolve8, reject) => {
1213
1213
  if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
1214
1214
  if (this.ws.readyState !== import_ws.default.OPEN) return reject(new Error("WebSocket not open"));
1215
1215
  const id = this.msgId++;
1216
- this.pending.set(id, { resolve: resolve7, reject });
1216
+ this.pending.set(id, { resolve: resolve8, reject });
1217
1217
  this.ws.send(JSON.stringify({ id, method, params }));
1218
1218
  setTimeout(() => {
1219
1219
  if (this.pending.has(id)) {
@@ -1422,7 +1422,7 @@ var DaemonCdpManager = class {
1422
1422
  const browserWs = this.browserWs;
1423
1423
  let msgId = this.browserMsgId;
1424
1424
  const sendWs = (method, params = {}, sessionId) => {
1425
- return new Promise((resolve7, reject) => {
1425
+ return new Promise((resolve8, reject) => {
1426
1426
  const mid = msgId++;
1427
1427
  this.browserMsgId = msgId;
1428
1428
  const handler = (raw) => {
@@ -1431,7 +1431,7 @@ var DaemonCdpManager = class {
1431
1431
  if (msg.id === mid) {
1432
1432
  browserWs.removeListener("message", handler);
1433
1433
  if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
1434
- else resolve7(msg.result);
1434
+ else resolve8(msg.result);
1435
1435
  }
1436
1436
  } catch {
1437
1437
  }
@@ -1605,14 +1605,14 @@ var DaemonCdpManager = class {
1605
1605
  if (!ws || ws.readyState !== import_ws.default.OPEN) {
1606
1606
  throw new Error("CDP not connected");
1607
1607
  }
1608
- return new Promise((resolve7, reject) => {
1608
+ return new Promise((resolve8, reject) => {
1609
1609
  const id = getNextId();
1610
1610
  pendingMap.set(id, {
1611
1611
  resolve: (result) => {
1612
1612
  if (result?.result?.subtype === "error") {
1613
1613
  reject(new Error(result.result.description));
1614
1614
  } else {
1615
- resolve7(result?.result?.value);
1615
+ resolve8(result?.result?.value);
1616
1616
  }
1617
1617
  },
1618
1618
  reject
@@ -1644,10 +1644,10 @@ var DaemonCdpManager = class {
1644
1644
  throw new Error("CDP not connected");
1645
1645
  }
1646
1646
  const sendViaSession = (method, params = {}) => {
1647
- return new Promise((resolve7, reject) => {
1647
+ return new Promise((resolve8, reject) => {
1648
1648
  const pendingMap = this._browserConnected ? this.browserPending : this.pending;
1649
1649
  const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
1650
- pendingMap.set(id, { resolve: resolve7, reject });
1650
+ pendingMap.set(id, { resolve: resolve8, reject });
1651
1651
  ws.send(JSON.stringify({ id, sessionId, method, params }));
1652
1652
  setTimeout(() => {
1653
1653
  if (pendingMap.has(id)) {
@@ -5229,7 +5229,7 @@ var ProviderLoader = class _ProviderLoader {
5229
5229
  return { updated: false };
5230
5230
  }
5231
5231
  try {
5232
- const etag = await new Promise((resolve7, reject) => {
5232
+ const etag = await new Promise((resolve8, reject) => {
5233
5233
  const options = {
5234
5234
  method: "HEAD",
5235
5235
  hostname: "github.com",
@@ -5247,7 +5247,7 @@ var ProviderLoader = class _ProviderLoader {
5247
5247
  headers: { "User-Agent": "adhdev-launcher" },
5248
5248
  timeout: 1e4
5249
5249
  }, (res2) => {
5250
- resolve7(res2.headers.etag || res2.headers["last-modified"] || "");
5250
+ resolve8(res2.headers.etag || res2.headers["last-modified"] || "");
5251
5251
  });
5252
5252
  req2.on("error", reject);
5253
5253
  req2.on("timeout", () => {
@@ -5256,7 +5256,7 @@ var ProviderLoader = class _ProviderLoader {
5256
5256
  });
5257
5257
  req2.end();
5258
5258
  } else {
5259
- resolve7(res.headers.etag || res.headers["last-modified"] || "");
5259
+ resolve8(res.headers.etag || res.headers["last-modified"] || "");
5260
5260
  }
5261
5261
  });
5262
5262
  req.on("error", reject);
@@ -5320,7 +5320,7 @@ var ProviderLoader = class _ProviderLoader {
5320
5320
  downloadFile(url, destPath) {
5321
5321
  const https = require("https");
5322
5322
  const http3 = require("http");
5323
- return new Promise((resolve7, reject) => {
5323
+ return new Promise((resolve8, reject) => {
5324
5324
  const doRequest = (reqUrl, redirectCount = 0) => {
5325
5325
  if (redirectCount > 5) {
5326
5326
  reject(new Error("Too many redirects"));
@@ -5340,7 +5340,7 @@ var ProviderLoader = class _ProviderLoader {
5340
5340
  res.pipe(ws);
5341
5341
  ws.on("finish", () => {
5342
5342
  ws.close();
5343
- resolve7();
5343
+ resolve8();
5344
5344
  });
5345
5345
  ws.on("error", reject);
5346
5346
  });
@@ -5677,17 +5677,17 @@ async function findFreePort(ports) {
5677
5677
  throw new Error("No free port found");
5678
5678
  }
5679
5679
  function checkPortFree(port) {
5680
- return new Promise((resolve7) => {
5680
+ return new Promise((resolve8) => {
5681
5681
  const server = net.createServer();
5682
5682
  server.unref();
5683
- server.on("error", () => resolve7(false));
5683
+ server.on("error", () => resolve8(false));
5684
5684
  server.listen(port, "127.0.0.1", () => {
5685
- server.close(() => resolve7(true));
5685
+ server.close(() => resolve8(true));
5686
5686
  });
5687
5687
  });
5688
5688
  }
5689
5689
  async function isCdpActive(port) {
5690
- return new Promise((resolve7) => {
5690
+ return new Promise((resolve8) => {
5691
5691
  const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
5692
5692
  timeout: 2e3
5693
5693
  }, (res) => {
@@ -5696,16 +5696,16 @@ async function isCdpActive(port) {
5696
5696
  res.on("end", () => {
5697
5697
  try {
5698
5698
  const info = JSON.parse(data);
5699
- resolve7(!!info["WebKit-Version"] || !!info["Browser"]);
5699
+ resolve8(!!info["WebKit-Version"] || !!info["Browser"]);
5700
5700
  } catch {
5701
- resolve7(false);
5701
+ resolve8(false);
5702
5702
  }
5703
5703
  });
5704
5704
  });
5705
- req.on("error", () => resolve7(false));
5705
+ req.on("error", () => resolve8(false));
5706
5706
  req.on("timeout", () => {
5707
5707
  req.destroy();
5708
- resolve7(false);
5708
+ resolve8(false);
5709
5709
  });
5710
5710
  });
5711
5711
  }
@@ -6650,7 +6650,7 @@ try {
6650
6650
  if (os11.platform() !== "win32") {
6651
6651
  try {
6652
6652
  const fs10 = require("fs");
6653
- const ptyDir = path9.dirname(require.resolve("node-pty"));
6653
+ const ptyDir = path9.resolve(path9.dirname(require.resolve("node-pty")), "..");
6654
6654
  const arch3 = os11.arch() === "arm64" ? "darwin-arm64" : "darwin-x64";
6655
6655
  const helper = path9.join(ptyDir, "prebuilds", arch3, "spawn-helper");
6656
6656
  if (fs10.existsSync(helper)) {
@@ -7851,13 +7851,13 @@ var AcpProviderInstance = class {
7851
7851
  }
7852
7852
  this.currentStatus = "waiting_approval";
7853
7853
  this.detectStatusTransition();
7854
- const approved = await new Promise((resolve7) => {
7855
- this.permissionResolvers.push(resolve7);
7854
+ const approved = await new Promise((resolve8) => {
7855
+ this.permissionResolvers.push(resolve8);
7856
7856
  setTimeout(() => {
7857
- const idx = this.permissionResolvers.indexOf(resolve7);
7857
+ const idx = this.permissionResolvers.indexOf(resolve8);
7858
7858
  if (idx >= 0) {
7859
7859
  this.permissionResolvers.splice(idx, 1);
7860
- resolve7(false);
7860
+ resolve8(false);
7861
7861
  }
7862
7862
  }, 3e5);
7863
7863
  });
@@ -9097,6 +9097,18 @@ var AgentStreamPoller = class {
9097
9097
  }
9098
9098
  }
9099
9099
  }
9100
+ if (this._activeIdeType === ideType && agentStreamManager.activeAgentType) {
9101
+ const activeType = agentStreamManager.activeAgentType;
9102
+ const enabledExtTypes = new Set(
9103
+ providerLoader.getEnabledExtensionProviders(ideType).map((p) => p.type)
9104
+ );
9105
+ if (!enabledExtTypes.has(activeType)) {
9106
+ LOG.info("AgentStream", `Active agent ${activeType} was disabled for ${ideType} \u2014 detaching`);
9107
+ await agentStreamManager.switchActiveAgent(cdp, null);
9108
+ this._activeIdeType = null;
9109
+ this.deps.onStreamsUpdated?.(ideType, []);
9110
+ }
9111
+ }
9100
9112
  }
9101
9113
  if (this._activeIdeType) {
9102
9114
  const cdp = cdpManagers.get(this._activeIdeType);
@@ -9907,15 +9919,15 @@ var DevServer = class _DevServer {
9907
9919
  this.json(res, 500, { error: e.message });
9908
9920
  }
9909
9921
  });
9910
- return new Promise((resolve7, reject) => {
9922
+ return new Promise((resolve8, reject) => {
9911
9923
  this.server.listen(port, "127.0.0.1", () => {
9912
9924
  this.log(`Dev server listening on http://127.0.0.1:${port}`);
9913
- resolve7();
9925
+ resolve8();
9914
9926
  });
9915
9927
  this.server.on("error", (e) => {
9916
9928
  if (e.code === "EADDRINUSE") {
9917
9929
  this.log(`Port ${port} in use, skipping dev server`);
9918
- resolve7();
9930
+ resolve8();
9919
9931
  } else {
9920
9932
  reject(e);
9921
9933
  }
@@ -9998,20 +10010,20 @@ var DevServer = class _DevServer {
9998
10010
  child.stderr?.on("data", (d) => {
9999
10011
  stderr += d.toString().slice(0, 2e3);
10000
10012
  });
10001
- await new Promise((resolve7) => {
10013
+ await new Promise((resolve8) => {
10002
10014
  const timer = setTimeout(() => {
10003
10015
  child.kill();
10004
- resolve7();
10016
+ resolve8();
10005
10017
  }, 3e3);
10006
10018
  child.on("exit", () => {
10007
10019
  clearTimeout(timer);
10008
- resolve7();
10020
+ resolve8();
10009
10021
  });
10010
10022
  child.stdout?.once("data", () => {
10011
10023
  setTimeout(() => {
10012
10024
  child.kill();
10013
10025
  clearTimeout(timer);
10014
- resolve7();
10026
+ resolve8();
10015
10027
  }, 500);
10016
10028
  });
10017
10029
  });
@@ -10696,14 +10708,14 @@ var DevServer = class _DevServer {
10696
10708
  child.stderr?.on("data", (d) => {
10697
10709
  stderr += d.toString();
10698
10710
  });
10699
- await new Promise((resolve7) => {
10711
+ await new Promise((resolve8) => {
10700
10712
  const timer = setTimeout(() => {
10701
10713
  child.kill();
10702
- resolve7();
10714
+ resolve8();
10703
10715
  }, timeout);
10704
10716
  child.on("exit", () => {
10705
10717
  clearTimeout(timer);
10706
- resolve7();
10718
+ resolve8();
10707
10719
  });
10708
10720
  });
10709
10721
  const elapsed = Date.now() - start;
@@ -12105,14 +12117,14 @@ data: ${JSON.stringify(msg.data)}
12105
12117
  res.end(JSON.stringify(data, null, 2));
12106
12118
  }
12107
12119
  async readBody(req) {
12108
- return new Promise((resolve7) => {
12120
+ return new Promise((resolve8) => {
12109
12121
  let body = "";
12110
12122
  req.on("data", (chunk) => body += chunk);
12111
12123
  req.on("end", () => {
12112
12124
  try {
12113
- resolve7(JSON.parse(body));
12125
+ resolve8(JSON.parse(body));
12114
12126
  } catch {
12115
- resolve7({});
12127
+ resolve8({});
12116
12128
  }
12117
12129
  });
12118
12130
  });
@@ -12481,10 +12493,10 @@ async function installExtension(ide, extension) {
12481
12493
  const buffer = Buffer.from(await res.arrayBuffer());
12482
12494
  const fs10 = await import("fs");
12483
12495
  fs10.writeFileSync(vsixPath, buffer);
12484
- return new Promise((resolve7) => {
12496
+ return new Promise((resolve8) => {
12485
12497
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
12486
12498
  (0, import_child_process8.exec)(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
12487
- resolve7({
12499
+ resolve8({
12488
12500
  extensionId: extension.id,
12489
12501
  marketplaceId: extension.marketplaceId,
12490
12502
  success: !error,
@@ -12497,11 +12509,11 @@ async function installExtension(ide, extension) {
12497
12509
  } catch (e) {
12498
12510
  }
12499
12511
  }
12500
- return new Promise((resolve7) => {
12512
+ return new Promise((resolve8) => {
12501
12513
  const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
12502
12514
  (0, import_child_process8.exec)(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
12503
12515
  if (error) {
12504
- resolve7({
12516
+ resolve8({
12505
12517
  extensionId: extension.id,
12506
12518
  marketplaceId: extension.marketplaceId,
12507
12519
  success: false,
@@ -12509,7 +12521,7 @@ async function installExtension(ide, extension) {
12509
12521
  error: stderr || error.message
12510
12522
  });
12511
12523
  } else {
12512
- resolve7({
12524
+ resolve8({
12513
12525
  extensionId: extension.id,
12514
12526
  marketplaceId: extension.marketplaceId,
12515
12527
  success: true,