@vinihcrosa/lumem-os 0.5.0 → 0.7.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/README.md +16 -5
- package/bin/lumem.mjs +1110 -181
- package/dist/server/main.mjs +6477 -2785
- package/dist/web/assets/{codemirror-setup-DJO1HmWW.js → codemirror-setup-Dz1snhDw.js} +1 -1
- package/dist/web/assets/index-CS8iEPU6.css +32 -0
- package/dist/web/assets/index-e0RfxsGe.js +107 -0
- package/dist/web/index.html +2 -2
- package/drizzle/0033_agente_sempre_acp.sql +65 -0
- package/drizzle/0034_motivo_do_pendente.sql +1 -0
- package/drizzle/0035_conta_de_agente.sql +84 -0
- package/drizzle/0036_conta_do_encaixe.sql +5 -0
- package/drizzle/0037_continuacao_de_conta.sql +5 -0
- package/drizzle/0038_conta_principal.sql +7 -0
- package/drizzle/0039_espera_da_cota.sql +2 -0
- package/drizzle/0040_configuracao_do_daemon.sql +11 -0
- package/drizzle/meta/0033_snapshot.json +2644 -0
- package/drizzle/meta/0034_snapshot.json +2651 -0
- package/drizzle/meta/0035_snapshot.json +2823 -0
- package/drizzle/meta/0036_snapshot.json +2850 -0
- package/drizzle/meta/0037_snapshot.json +2870 -0
- package/drizzle/meta/0038_snapshot.json +2870 -0
- package/drizzle/meta/0039_snapshot.json +2885 -0
- package/drizzle/meta/0040_snapshot.json +2931 -0
- package/drizzle/meta/_journal.json +56 -0
- package/package.json +2 -2
- package/dist/web/assets/index-BV0JIdw9.css +0 -32
- package/dist/web/assets/index-Dzie5jh_.js +0 -101
package/bin/lumem.mjs
CHANGED
|
@@ -539,18 +539,18 @@ var ParseStatus = class _ParseStatus {
|
|
|
539
539
|
if (this.value !== "aborted")
|
|
540
540
|
this.value = "aborted";
|
|
541
541
|
}
|
|
542
|
-
static mergeArray(
|
|
542
|
+
static mergeArray(status2, results) {
|
|
543
543
|
const arrayValue = [];
|
|
544
544
|
for (const s of results) {
|
|
545
545
|
if (s.status === "aborted")
|
|
546
546
|
return INVALID;
|
|
547
547
|
if (s.status === "dirty")
|
|
548
|
-
|
|
548
|
+
status2.dirty();
|
|
549
549
|
arrayValue.push(s.value);
|
|
550
550
|
}
|
|
551
|
-
return { status:
|
|
551
|
+
return { status: status2.value, value: arrayValue };
|
|
552
552
|
}
|
|
553
|
-
static async mergeObjectAsync(
|
|
553
|
+
static async mergeObjectAsync(status2, pairs) {
|
|
554
554
|
const syncPairs = [];
|
|
555
555
|
for (const pair of pairs) {
|
|
556
556
|
const key = await pair.key;
|
|
@@ -560,9 +560,9 @@ var ParseStatus = class _ParseStatus {
|
|
|
560
560
|
value
|
|
561
561
|
});
|
|
562
562
|
}
|
|
563
|
-
return _ParseStatus.mergeObjectSync(
|
|
563
|
+
return _ParseStatus.mergeObjectSync(status2, syncPairs);
|
|
564
564
|
}
|
|
565
|
-
static mergeObjectSync(
|
|
565
|
+
static mergeObjectSync(status2, pairs) {
|
|
566
566
|
const finalObject = {};
|
|
567
567
|
for (const pair of pairs) {
|
|
568
568
|
const { key, value } = pair;
|
|
@@ -571,14 +571,14 @@ var ParseStatus = class _ParseStatus {
|
|
|
571
571
|
if (value.status === "aborted")
|
|
572
572
|
return INVALID;
|
|
573
573
|
if (key.status === "dirty")
|
|
574
|
-
|
|
574
|
+
status2.dirty();
|
|
575
575
|
if (value.status === "dirty")
|
|
576
|
-
|
|
576
|
+
status2.dirty();
|
|
577
577
|
if (key.value !== "__proto__" && (typeof value.value !== "undefined" || pair.alwaysSet)) {
|
|
578
578
|
finalObject[key.value] = value.value;
|
|
579
579
|
}
|
|
580
580
|
}
|
|
581
|
-
return { status:
|
|
581
|
+
return { status: status2.value, value: finalObject };
|
|
582
582
|
}
|
|
583
583
|
};
|
|
584
584
|
var INVALID = Object.freeze({
|
|
@@ -1038,7 +1038,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1038
1038
|
});
|
|
1039
1039
|
return INVALID;
|
|
1040
1040
|
}
|
|
1041
|
-
const
|
|
1041
|
+
const status2 = new ParseStatus();
|
|
1042
1042
|
let ctx = void 0;
|
|
1043
1043
|
for (const check of this._def.checks) {
|
|
1044
1044
|
if (check.kind === "min") {
|
|
@@ -1052,7 +1052,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1052
1052
|
exact: false,
|
|
1053
1053
|
message: check.message
|
|
1054
1054
|
});
|
|
1055
|
-
|
|
1055
|
+
status2.dirty();
|
|
1056
1056
|
}
|
|
1057
1057
|
} else if (check.kind === "max") {
|
|
1058
1058
|
if (input.data.length > check.value) {
|
|
@@ -1065,7 +1065,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1065
1065
|
exact: false,
|
|
1066
1066
|
message: check.message
|
|
1067
1067
|
});
|
|
1068
|
-
|
|
1068
|
+
status2.dirty();
|
|
1069
1069
|
}
|
|
1070
1070
|
} else if (check.kind === "length") {
|
|
1071
1071
|
const tooBig = input.data.length > check.value;
|
|
@@ -1091,7 +1091,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1091
1091
|
message: check.message
|
|
1092
1092
|
});
|
|
1093
1093
|
}
|
|
1094
|
-
|
|
1094
|
+
status2.dirty();
|
|
1095
1095
|
}
|
|
1096
1096
|
} else if (check.kind === "email") {
|
|
1097
1097
|
if (!emailRegex.test(input.data)) {
|
|
@@ -1101,7 +1101,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1101
1101
|
code: ZodIssueCode.invalid_string,
|
|
1102
1102
|
message: check.message
|
|
1103
1103
|
});
|
|
1104
|
-
|
|
1104
|
+
status2.dirty();
|
|
1105
1105
|
}
|
|
1106
1106
|
} else if (check.kind === "emoji") {
|
|
1107
1107
|
if (!emojiRegex) {
|
|
@@ -1114,7 +1114,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1114
1114
|
code: ZodIssueCode.invalid_string,
|
|
1115
1115
|
message: check.message
|
|
1116
1116
|
});
|
|
1117
|
-
|
|
1117
|
+
status2.dirty();
|
|
1118
1118
|
}
|
|
1119
1119
|
} else if (check.kind === "uuid") {
|
|
1120
1120
|
if (!uuidRegex.test(input.data)) {
|
|
@@ -1124,7 +1124,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1124
1124
|
code: ZodIssueCode.invalid_string,
|
|
1125
1125
|
message: check.message
|
|
1126
1126
|
});
|
|
1127
|
-
|
|
1127
|
+
status2.dirty();
|
|
1128
1128
|
}
|
|
1129
1129
|
} else if (check.kind === "nanoid") {
|
|
1130
1130
|
if (!nanoidRegex.test(input.data)) {
|
|
@@ -1134,7 +1134,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1134
1134
|
code: ZodIssueCode.invalid_string,
|
|
1135
1135
|
message: check.message
|
|
1136
1136
|
});
|
|
1137
|
-
|
|
1137
|
+
status2.dirty();
|
|
1138
1138
|
}
|
|
1139
1139
|
} else if (check.kind === "cuid") {
|
|
1140
1140
|
if (!cuidRegex.test(input.data)) {
|
|
@@ -1144,7 +1144,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1144
1144
|
code: ZodIssueCode.invalid_string,
|
|
1145
1145
|
message: check.message
|
|
1146
1146
|
});
|
|
1147
|
-
|
|
1147
|
+
status2.dirty();
|
|
1148
1148
|
}
|
|
1149
1149
|
} else if (check.kind === "cuid2") {
|
|
1150
1150
|
if (!cuid2Regex.test(input.data)) {
|
|
@@ -1154,7 +1154,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1154
1154
|
code: ZodIssueCode.invalid_string,
|
|
1155
1155
|
message: check.message
|
|
1156
1156
|
});
|
|
1157
|
-
|
|
1157
|
+
status2.dirty();
|
|
1158
1158
|
}
|
|
1159
1159
|
} else if (check.kind === "ulid") {
|
|
1160
1160
|
if (!ulidRegex.test(input.data)) {
|
|
@@ -1164,7 +1164,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1164
1164
|
code: ZodIssueCode.invalid_string,
|
|
1165
1165
|
message: check.message
|
|
1166
1166
|
});
|
|
1167
|
-
|
|
1167
|
+
status2.dirty();
|
|
1168
1168
|
}
|
|
1169
1169
|
} else if (check.kind === "url") {
|
|
1170
1170
|
try {
|
|
@@ -1176,7 +1176,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1176
1176
|
code: ZodIssueCode.invalid_string,
|
|
1177
1177
|
message: check.message
|
|
1178
1178
|
});
|
|
1179
|
-
|
|
1179
|
+
status2.dirty();
|
|
1180
1180
|
}
|
|
1181
1181
|
} else if (check.kind === "regex") {
|
|
1182
1182
|
check.regex.lastIndex = 0;
|
|
@@ -1188,7 +1188,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1188
1188
|
code: ZodIssueCode.invalid_string,
|
|
1189
1189
|
message: check.message
|
|
1190
1190
|
});
|
|
1191
|
-
|
|
1191
|
+
status2.dirty();
|
|
1192
1192
|
}
|
|
1193
1193
|
} else if (check.kind === "trim") {
|
|
1194
1194
|
input.data = input.data.trim();
|
|
@@ -1200,7 +1200,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1200
1200
|
validation: { includes: check.value, position: check.position },
|
|
1201
1201
|
message: check.message
|
|
1202
1202
|
});
|
|
1203
|
-
|
|
1203
|
+
status2.dirty();
|
|
1204
1204
|
}
|
|
1205
1205
|
} else if (check.kind === "toLowerCase") {
|
|
1206
1206
|
input.data = input.data.toLowerCase();
|
|
@@ -1214,7 +1214,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1214
1214
|
validation: { startsWith: check.value },
|
|
1215
1215
|
message: check.message
|
|
1216
1216
|
});
|
|
1217
|
-
|
|
1217
|
+
status2.dirty();
|
|
1218
1218
|
}
|
|
1219
1219
|
} else if (check.kind === "endsWith") {
|
|
1220
1220
|
if (!input.data.endsWith(check.value)) {
|
|
@@ -1224,7 +1224,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1224
1224
|
validation: { endsWith: check.value },
|
|
1225
1225
|
message: check.message
|
|
1226
1226
|
});
|
|
1227
|
-
|
|
1227
|
+
status2.dirty();
|
|
1228
1228
|
}
|
|
1229
1229
|
} else if (check.kind === "datetime") {
|
|
1230
1230
|
const regex = datetimeRegex(check);
|
|
@@ -1235,7 +1235,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1235
1235
|
validation: "datetime",
|
|
1236
1236
|
message: check.message
|
|
1237
1237
|
});
|
|
1238
|
-
|
|
1238
|
+
status2.dirty();
|
|
1239
1239
|
}
|
|
1240
1240
|
} else if (check.kind === "date") {
|
|
1241
1241
|
const regex = dateRegex;
|
|
@@ -1246,7 +1246,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1246
1246
|
validation: "date",
|
|
1247
1247
|
message: check.message
|
|
1248
1248
|
});
|
|
1249
|
-
|
|
1249
|
+
status2.dirty();
|
|
1250
1250
|
}
|
|
1251
1251
|
} else if (check.kind === "time") {
|
|
1252
1252
|
const regex = timeRegex(check);
|
|
@@ -1257,7 +1257,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1257
1257
|
validation: "time",
|
|
1258
1258
|
message: check.message
|
|
1259
1259
|
});
|
|
1260
|
-
|
|
1260
|
+
status2.dirty();
|
|
1261
1261
|
}
|
|
1262
1262
|
} else if (check.kind === "duration") {
|
|
1263
1263
|
if (!durationRegex.test(input.data)) {
|
|
@@ -1267,7 +1267,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1267
1267
|
code: ZodIssueCode.invalid_string,
|
|
1268
1268
|
message: check.message
|
|
1269
1269
|
});
|
|
1270
|
-
|
|
1270
|
+
status2.dirty();
|
|
1271
1271
|
}
|
|
1272
1272
|
} else if (check.kind === "ip") {
|
|
1273
1273
|
if (!isValidIP(input.data, check.version)) {
|
|
@@ -1277,7 +1277,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1277
1277
|
code: ZodIssueCode.invalid_string,
|
|
1278
1278
|
message: check.message
|
|
1279
1279
|
});
|
|
1280
|
-
|
|
1280
|
+
status2.dirty();
|
|
1281
1281
|
}
|
|
1282
1282
|
} else if (check.kind === "jwt") {
|
|
1283
1283
|
if (!isValidJWT(input.data, check.alg)) {
|
|
@@ -1287,7 +1287,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1287
1287
|
code: ZodIssueCode.invalid_string,
|
|
1288
1288
|
message: check.message
|
|
1289
1289
|
});
|
|
1290
|
-
|
|
1290
|
+
status2.dirty();
|
|
1291
1291
|
}
|
|
1292
1292
|
} else if (check.kind === "cidr") {
|
|
1293
1293
|
if (!isValidCidr(input.data, check.version)) {
|
|
@@ -1297,7 +1297,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1297
1297
|
code: ZodIssueCode.invalid_string,
|
|
1298
1298
|
message: check.message
|
|
1299
1299
|
});
|
|
1300
|
-
|
|
1300
|
+
status2.dirty();
|
|
1301
1301
|
}
|
|
1302
1302
|
} else if (check.kind === "base64") {
|
|
1303
1303
|
if (!base64Regex.test(input.data)) {
|
|
@@ -1307,7 +1307,7 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1307
1307
|
code: ZodIssueCode.invalid_string,
|
|
1308
1308
|
message: check.message
|
|
1309
1309
|
});
|
|
1310
|
-
|
|
1310
|
+
status2.dirty();
|
|
1311
1311
|
}
|
|
1312
1312
|
} else if (check.kind === "base64url") {
|
|
1313
1313
|
if (!base64urlRegex.test(input.data)) {
|
|
@@ -1317,13 +1317,13 @@ var ZodString = class _ZodString extends ZodType {
|
|
|
1317
1317
|
code: ZodIssueCode.invalid_string,
|
|
1318
1318
|
message: check.message
|
|
1319
1319
|
});
|
|
1320
|
-
|
|
1320
|
+
status2.dirty();
|
|
1321
1321
|
}
|
|
1322
1322
|
} else {
|
|
1323
1323
|
util.assertNever(check);
|
|
1324
1324
|
}
|
|
1325
1325
|
}
|
|
1326
|
-
return { status:
|
|
1326
|
+
return { status: status2.value, value: input.data };
|
|
1327
1327
|
}
|
|
1328
1328
|
_regex(regex, validation, message2) {
|
|
1329
1329
|
return this.refinement((data) => regex.test(data), {
|
|
@@ -1599,7 +1599,7 @@ var ZodNumber = class _ZodNumber extends ZodType {
|
|
|
1599
1599
|
return INVALID;
|
|
1600
1600
|
}
|
|
1601
1601
|
let ctx = void 0;
|
|
1602
|
-
const
|
|
1602
|
+
const status2 = new ParseStatus();
|
|
1603
1603
|
for (const check of this._def.checks) {
|
|
1604
1604
|
if (check.kind === "int") {
|
|
1605
1605
|
if (!util.isInteger(input.data)) {
|
|
@@ -1610,7 +1610,7 @@ var ZodNumber = class _ZodNumber extends ZodType {
|
|
|
1610
1610
|
received: "float",
|
|
1611
1611
|
message: check.message
|
|
1612
1612
|
});
|
|
1613
|
-
|
|
1613
|
+
status2.dirty();
|
|
1614
1614
|
}
|
|
1615
1615
|
} else if (check.kind === "min") {
|
|
1616
1616
|
const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value;
|
|
@@ -1624,7 +1624,7 @@ var ZodNumber = class _ZodNumber extends ZodType {
|
|
|
1624
1624
|
exact: false,
|
|
1625
1625
|
message: check.message
|
|
1626
1626
|
});
|
|
1627
|
-
|
|
1627
|
+
status2.dirty();
|
|
1628
1628
|
}
|
|
1629
1629
|
} else if (check.kind === "max") {
|
|
1630
1630
|
const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value;
|
|
@@ -1638,7 +1638,7 @@ var ZodNumber = class _ZodNumber extends ZodType {
|
|
|
1638
1638
|
exact: false,
|
|
1639
1639
|
message: check.message
|
|
1640
1640
|
});
|
|
1641
|
-
|
|
1641
|
+
status2.dirty();
|
|
1642
1642
|
}
|
|
1643
1643
|
} else if (check.kind === "multipleOf") {
|
|
1644
1644
|
if (floatSafeRemainder(input.data, check.value) !== 0) {
|
|
@@ -1648,7 +1648,7 @@ var ZodNumber = class _ZodNumber extends ZodType {
|
|
|
1648
1648
|
multipleOf: check.value,
|
|
1649
1649
|
message: check.message
|
|
1650
1650
|
});
|
|
1651
|
-
|
|
1651
|
+
status2.dirty();
|
|
1652
1652
|
}
|
|
1653
1653
|
} else if (check.kind === "finite") {
|
|
1654
1654
|
if (!Number.isFinite(input.data)) {
|
|
@@ -1657,13 +1657,13 @@ var ZodNumber = class _ZodNumber extends ZodType {
|
|
|
1657
1657
|
code: ZodIssueCode.not_finite,
|
|
1658
1658
|
message: check.message
|
|
1659
1659
|
});
|
|
1660
|
-
|
|
1660
|
+
status2.dirty();
|
|
1661
1661
|
}
|
|
1662
1662
|
} else {
|
|
1663
1663
|
util.assertNever(check);
|
|
1664
1664
|
}
|
|
1665
1665
|
}
|
|
1666
|
-
return { status:
|
|
1666
|
+
return { status: status2.value, value: input.data };
|
|
1667
1667
|
}
|
|
1668
1668
|
gte(value, message2) {
|
|
1669
1669
|
return this.setLimit("min", value, true, errorUtil.toString(message2));
|
|
@@ -1828,7 +1828,7 @@ var ZodBigInt = class _ZodBigInt extends ZodType {
|
|
|
1828
1828
|
return this._getInvalidInput(input);
|
|
1829
1829
|
}
|
|
1830
1830
|
let ctx = void 0;
|
|
1831
|
-
const
|
|
1831
|
+
const status2 = new ParseStatus();
|
|
1832
1832
|
for (const check of this._def.checks) {
|
|
1833
1833
|
if (check.kind === "min") {
|
|
1834
1834
|
const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value;
|
|
@@ -1841,7 +1841,7 @@ var ZodBigInt = class _ZodBigInt extends ZodType {
|
|
|
1841
1841
|
inclusive: check.inclusive,
|
|
1842
1842
|
message: check.message
|
|
1843
1843
|
});
|
|
1844
|
-
|
|
1844
|
+
status2.dirty();
|
|
1845
1845
|
}
|
|
1846
1846
|
} else if (check.kind === "max") {
|
|
1847
1847
|
const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value;
|
|
@@ -1854,7 +1854,7 @@ var ZodBigInt = class _ZodBigInt extends ZodType {
|
|
|
1854
1854
|
inclusive: check.inclusive,
|
|
1855
1855
|
message: check.message
|
|
1856
1856
|
});
|
|
1857
|
-
|
|
1857
|
+
status2.dirty();
|
|
1858
1858
|
}
|
|
1859
1859
|
} else if (check.kind === "multipleOf") {
|
|
1860
1860
|
if (input.data % check.value !== BigInt(0)) {
|
|
@@ -1864,13 +1864,13 @@ var ZodBigInt = class _ZodBigInt extends ZodType {
|
|
|
1864
1864
|
multipleOf: check.value,
|
|
1865
1865
|
message: check.message
|
|
1866
1866
|
});
|
|
1867
|
-
|
|
1867
|
+
status2.dirty();
|
|
1868
1868
|
}
|
|
1869
1869
|
} else {
|
|
1870
1870
|
util.assertNever(check);
|
|
1871
1871
|
}
|
|
1872
1872
|
}
|
|
1873
|
-
return { status:
|
|
1873
|
+
return { status: status2.value, value: input.data };
|
|
1874
1874
|
}
|
|
1875
1875
|
_getInvalidInput(input) {
|
|
1876
1876
|
const ctx = this._getOrReturnCtx(input);
|
|
@@ -2028,7 +2028,7 @@ var ZodDate = class _ZodDate extends ZodType {
|
|
|
2028
2028
|
});
|
|
2029
2029
|
return INVALID;
|
|
2030
2030
|
}
|
|
2031
|
-
const
|
|
2031
|
+
const status2 = new ParseStatus();
|
|
2032
2032
|
let ctx = void 0;
|
|
2033
2033
|
for (const check of this._def.checks) {
|
|
2034
2034
|
if (check.kind === "min") {
|
|
@@ -2042,7 +2042,7 @@ var ZodDate = class _ZodDate extends ZodType {
|
|
|
2042
2042
|
minimum: check.value,
|
|
2043
2043
|
type: "date"
|
|
2044
2044
|
});
|
|
2045
|
-
|
|
2045
|
+
status2.dirty();
|
|
2046
2046
|
}
|
|
2047
2047
|
} else if (check.kind === "max") {
|
|
2048
2048
|
if (input.data.getTime() > check.value) {
|
|
@@ -2055,14 +2055,14 @@ var ZodDate = class _ZodDate extends ZodType {
|
|
|
2055
2055
|
maximum: check.value,
|
|
2056
2056
|
type: "date"
|
|
2057
2057
|
});
|
|
2058
|
-
|
|
2058
|
+
status2.dirty();
|
|
2059
2059
|
}
|
|
2060
2060
|
} else {
|
|
2061
2061
|
util.assertNever(check);
|
|
2062
2062
|
}
|
|
2063
2063
|
}
|
|
2064
2064
|
return {
|
|
2065
|
-
status:
|
|
2065
|
+
status: status2.value,
|
|
2066
2066
|
value: new Date(input.data.getTime())
|
|
2067
2067
|
};
|
|
2068
2068
|
}
|
|
@@ -2248,7 +2248,7 @@ ZodVoid.create = (params) => {
|
|
|
2248
2248
|
};
|
|
2249
2249
|
var ZodArray = class _ZodArray extends ZodType {
|
|
2250
2250
|
_parse(input) {
|
|
2251
|
-
const { ctx, status } = this._processInputParams(input);
|
|
2251
|
+
const { ctx, status: status2 } = this._processInputParams(input);
|
|
2252
2252
|
const def = this._def;
|
|
2253
2253
|
if (ctx.parsedType !== ZodParsedType.array) {
|
|
2254
2254
|
addIssueToContext(ctx, {
|
|
@@ -2271,7 +2271,7 @@ var ZodArray = class _ZodArray extends ZodType {
|
|
|
2271
2271
|
exact: true,
|
|
2272
2272
|
message: def.exactLength.message
|
|
2273
2273
|
});
|
|
2274
|
-
|
|
2274
|
+
status2.dirty();
|
|
2275
2275
|
}
|
|
2276
2276
|
}
|
|
2277
2277
|
if (def.minLength !== null) {
|
|
@@ -2284,7 +2284,7 @@ var ZodArray = class _ZodArray extends ZodType {
|
|
|
2284
2284
|
exact: false,
|
|
2285
2285
|
message: def.minLength.message
|
|
2286
2286
|
});
|
|
2287
|
-
|
|
2287
|
+
status2.dirty();
|
|
2288
2288
|
}
|
|
2289
2289
|
}
|
|
2290
2290
|
if (def.maxLength !== null) {
|
|
@@ -2297,20 +2297,20 @@ var ZodArray = class _ZodArray extends ZodType {
|
|
|
2297
2297
|
exact: false,
|
|
2298
2298
|
message: def.maxLength.message
|
|
2299
2299
|
});
|
|
2300
|
-
|
|
2300
|
+
status2.dirty();
|
|
2301
2301
|
}
|
|
2302
2302
|
}
|
|
2303
2303
|
if (ctx.common.async) {
|
|
2304
2304
|
return Promise.all([...ctx.data].map((item, i) => {
|
|
2305
2305
|
return def.type._parseAsync(new ParseInputLazyPath(ctx, item, ctx.path, i));
|
|
2306
2306
|
})).then((result2) => {
|
|
2307
|
-
return ParseStatus.mergeArray(
|
|
2307
|
+
return ParseStatus.mergeArray(status2, result2);
|
|
2308
2308
|
});
|
|
2309
2309
|
}
|
|
2310
2310
|
const result = [...ctx.data].map((item, i) => {
|
|
2311
2311
|
return def.type._parseSync(new ParseInputLazyPath(ctx, item, ctx.path, i));
|
|
2312
2312
|
});
|
|
2313
|
-
return ParseStatus.mergeArray(
|
|
2313
|
+
return ParseStatus.mergeArray(status2, result);
|
|
2314
2314
|
}
|
|
2315
2315
|
get element() {
|
|
2316
2316
|
return this._def.type;
|
|
@@ -2399,7 +2399,7 @@ var ZodObject = class _ZodObject extends ZodType {
|
|
|
2399
2399
|
});
|
|
2400
2400
|
return INVALID;
|
|
2401
2401
|
}
|
|
2402
|
-
const { status, ctx } = this._processInputParams(input);
|
|
2402
|
+
const { status: status2, ctx } = this._processInputParams(input);
|
|
2403
2403
|
const { shape, keys: shapeKeys } = this._getCached();
|
|
2404
2404
|
const extraKeys = [];
|
|
2405
2405
|
if (!(this._def.catchall instanceof ZodNever && this._def.unknownKeys === "strip")) {
|
|
@@ -2434,7 +2434,7 @@ var ZodObject = class _ZodObject extends ZodType {
|
|
|
2434
2434
|
code: ZodIssueCode.unrecognized_keys,
|
|
2435
2435
|
keys: extraKeys
|
|
2436
2436
|
});
|
|
2437
|
-
|
|
2437
|
+
status2.dirty();
|
|
2438
2438
|
}
|
|
2439
2439
|
} else if (unknownKeys === "strip") {
|
|
2440
2440
|
} else {
|
|
@@ -2468,10 +2468,10 @@ var ZodObject = class _ZodObject extends ZodType {
|
|
|
2468
2468
|
}
|
|
2469
2469
|
return syncPairs;
|
|
2470
2470
|
}).then((syncPairs) => {
|
|
2471
|
-
return ParseStatus.mergeObjectSync(
|
|
2471
|
+
return ParseStatus.mergeObjectSync(status2, syncPairs);
|
|
2472
2472
|
});
|
|
2473
2473
|
} else {
|
|
2474
|
-
return ParseStatus.mergeObjectSync(
|
|
2474
|
+
return ParseStatus.mergeObjectSync(status2, pairs);
|
|
2475
2475
|
}
|
|
2476
2476
|
}
|
|
2477
2477
|
get shape() {
|
|
@@ -2949,7 +2949,7 @@ function mergeValues(a, b) {
|
|
|
2949
2949
|
}
|
|
2950
2950
|
var ZodIntersection = class extends ZodType {
|
|
2951
2951
|
_parse(input) {
|
|
2952
|
-
const { status, ctx } = this._processInputParams(input);
|
|
2952
|
+
const { status: status2, ctx } = this._processInputParams(input);
|
|
2953
2953
|
const handleParsed = (parsedLeft, parsedRight) => {
|
|
2954
2954
|
if (isAborted(parsedLeft) || isAborted(parsedRight)) {
|
|
2955
2955
|
return INVALID;
|
|
@@ -2962,9 +2962,9 @@ var ZodIntersection = class extends ZodType {
|
|
|
2962
2962
|
return INVALID;
|
|
2963
2963
|
}
|
|
2964
2964
|
if (isDirty(parsedLeft) || isDirty(parsedRight)) {
|
|
2965
|
-
|
|
2965
|
+
status2.dirty();
|
|
2966
2966
|
}
|
|
2967
|
-
return { status:
|
|
2967
|
+
return { status: status2.value, value: merged.data };
|
|
2968
2968
|
};
|
|
2969
2969
|
if (ctx.common.async) {
|
|
2970
2970
|
return Promise.all([
|
|
@@ -3002,7 +3002,7 @@ ZodIntersection.create = (left, right, params) => {
|
|
|
3002
3002
|
};
|
|
3003
3003
|
var ZodTuple = class _ZodTuple extends ZodType {
|
|
3004
3004
|
_parse(input) {
|
|
3005
|
-
const { status, ctx } = this._processInputParams(input);
|
|
3005
|
+
const { status: status2, ctx } = this._processInputParams(input);
|
|
3006
3006
|
if (ctx.parsedType !== ZodParsedType.array) {
|
|
3007
3007
|
addIssueToContext(ctx, {
|
|
3008
3008
|
code: ZodIssueCode.invalid_type,
|
|
@@ -3030,7 +3030,7 @@ var ZodTuple = class _ZodTuple extends ZodType {
|
|
|
3030
3030
|
exact: false,
|
|
3031
3031
|
type: "array"
|
|
3032
3032
|
});
|
|
3033
|
-
|
|
3033
|
+
status2.dirty();
|
|
3034
3034
|
}
|
|
3035
3035
|
const items = [...ctx.data].map((item, itemIndex) => {
|
|
3036
3036
|
const schema = this._def.items[itemIndex] || this._def.rest;
|
|
@@ -3040,10 +3040,10 @@ var ZodTuple = class _ZodTuple extends ZodType {
|
|
|
3040
3040
|
}).filter((x) => !!x);
|
|
3041
3041
|
if (ctx.common.async) {
|
|
3042
3042
|
return Promise.all(items).then((results) => {
|
|
3043
|
-
return ParseStatus.mergeArray(
|
|
3043
|
+
return ParseStatus.mergeArray(status2, results);
|
|
3044
3044
|
});
|
|
3045
3045
|
} else {
|
|
3046
|
-
return ParseStatus.mergeArray(
|
|
3046
|
+
return ParseStatus.mergeArray(status2, items);
|
|
3047
3047
|
}
|
|
3048
3048
|
}
|
|
3049
3049
|
get items() {
|
|
@@ -3075,7 +3075,7 @@ var ZodRecord = class _ZodRecord extends ZodType {
|
|
|
3075
3075
|
return this._def.valueType;
|
|
3076
3076
|
}
|
|
3077
3077
|
_parse(input) {
|
|
3078
|
-
const { status, ctx } = this._processInputParams(input);
|
|
3078
|
+
const { status: status2, ctx } = this._processInputParams(input);
|
|
3079
3079
|
if (ctx.parsedType !== ZodParsedType.object) {
|
|
3080
3080
|
addIssueToContext(ctx, {
|
|
3081
3081
|
code: ZodIssueCode.invalid_type,
|
|
@@ -3095,9 +3095,9 @@ var ZodRecord = class _ZodRecord extends ZodType {
|
|
|
3095
3095
|
});
|
|
3096
3096
|
}
|
|
3097
3097
|
if (ctx.common.async) {
|
|
3098
|
-
return ParseStatus.mergeObjectAsync(
|
|
3098
|
+
return ParseStatus.mergeObjectAsync(status2, pairs);
|
|
3099
3099
|
} else {
|
|
3100
|
-
return ParseStatus.mergeObjectSync(
|
|
3100
|
+
return ParseStatus.mergeObjectSync(status2, pairs);
|
|
3101
3101
|
}
|
|
3102
3102
|
}
|
|
3103
3103
|
get element() {
|
|
@@ -3128,7 +3128,7 @@ var ZodMap = class extends ZodType {
|
|
|
3128
3128
|
return this._def.valueType;
|
|
3129
3129
|
}
|
|
3130
3130
|
_parse(input) {
|
|
3131
|
-
const { status, ctx } = this._processInputParams(input);
|
|
3131
|
+
const { status: status2, ctx } = this._processInputParams(input);
|
|
3132
3132
|
if (ctx.parsedType !== ZodParsedType.map) {
|
|
3133
3133
|
addIssueToContext(ctx, {
|
|
3134
3134
|
code: ZodIssueCode.invalid_type,
|
|
@@ -3155,11 +3155,11 @@ var ZodMap = class extends ZodType {
|
|
|
3155
3155
|
return INVALID;
|
|
3156
3156
|
}
|
|
3157
3157
|
if (key.status === "dirty" || value.status === "dirty") {
|
|
3158
|
-
|
|
3158
|
+
status2.dirty();
|
|
3159
3159
|
}
|
|
3160
3160
|
finalMap.set(key.value, value.value);
|
|
3161
3161
|
}
|
|
3162
|
-
return { status:
|
|
3162
|
+
return { status: status2.value, value: finalMap };
|
|
3163
3163
|
});
|
|
3164
3164
|
} else {
|
|
3165
3165
|
const finalMap = /* @__PURE__ */ new Map();
|
|
@@ -3170,11 +3170,11 @@ var ZodMap = class extends ZodType {
|
|
|
3170
3170
|
return INVALID;
|
|
3171
3171
|
}
|
|
3172
3172
|
if (key.status === "dirty" || value.status === "dirty") {
|
|
3173
|
-
|
|
3173
|
+
status2.dirty();
|
|
3174
3174
|
}
|
|
3175
3175
|
finalMap.set(key.value, value.value);
|
|
3176
3176
|
}
|
|
3177
|
-
return { status:
|
|
3177
|
+
return { status: status2.value, value: finalMap };
|
|
3178
3178
|
}
|
|
3179
3179
|
}
|
|
3180
3180
|
};
|
|
@@ -3188,7 +3188,7 @@ ZodMap.create = (keyType, valueType, params) => {
|
|
|
3188
3188
|
};
|
|
3189
3189
|
var ZodSet = class _ZodSet extends ZodType {
|
|
3190
3190
|
_parse(input) {
|
|
3191
|
-
const { status, ctx } = this._processInputParams(input);
|
|
3191
|
+
const { status: status2, ctx } = this._processInputParams(input);
|
|
3192
3192
|
if (ctx.parsedType !== ZodParsedType.set) {
|
|
3193
3193
|
addIssueToContext(ctx, {
|
|
3194
3194
|
code: ZodIssueCode.invalid_type,
|
|
@@ -3208,7 +3208,7 @@ var ZodSet = class _ZodSet extends ZodType {
|
|
|
3208
3208
|
exact: false,
|
|
3209
3209
|
message: def.minSize.message
|
|
3210
3210
|
});
|
|
3211
|
-
|
|
3211
|
+
status2.dirty();
|
|
3212
3212
|
}
|
|
3213
3213
|
}
|
|
3214
3214
|
if (def.maxSize !== null) {
|
|
@@ -3221,7 +3221,7 @@ var ZodSet = class _ZodSet extends ZodType {
|
|
|
3221
3221
|
exact: false,
|
|
3222
3222
|
message: def.maxSize.message
|
|
3223
3223
|
});
|
|
3224
|
-
|
|
3224
|
+
status2.dirty();
|
|
3225
3225
|
}
|
|
3226
3226
|
}
|
|
3227
3227
|
const valueType = this._def.valueType;
|
|
@@ -3231,10 +3231,10 @@ var ZodSet = class _ZodSet extends ZodType {
|
|
|
3231
3231
|
if (element.status === "aborted")
|
|
3232
3232
|
return INVALID;
|
|
3233
3233
|
if (element.status === "dirty")
|
|
3234
|
-
|
|
3234
|
+
status2.dirty();
|
|
3235
3235
|
parsedSet.add(element.value);
|
|
3236
3236
|
}
|
|
3237
|
-
return { status:
|
|
3237
|
+
return { status: status2.value, value: parsedSet };
|
|
3238
3238
|
}
|
|
3239
3239
|
const elements = [...ctx.data.values()].map((item, i) => valueType._parse(new ParseInputLazyPath(ctx, item, ctx.path, i)));
|
|
3240
3240
|
if (ctx.common.async) {
|
|
@@ -3565,15 +3565,15 @@ var ZodEffects = class extends ZodType {
|
|
|
3565
3565
|
return this._def.schema._def.typeName === ZodFirstPartyTypeKind.ZodEffects ? this._def.schema.sourceType() : this._def.schema;
|
|
3566
3566
|
}
|
|
3567
3567
|
_parse(input) {
|
|
3568
|
-
const { status, ctx } = this._processInputParams(input);
|
|
3568
|
+
const { status: status2, ctx } = this._processInputParams(input);
|
|
3569
3569
|
const effect = this._def.effect || null;
|
|
3570
3570
|
const checkCtx = {
|
|
3571
3571
|
addIssue: (arg) => {
|
|
3572
3572
|
addIssueToContext(ctx, arg);
|
|
3573
3573
|
if (arg.fatal) {
|
|
3574
|
-
|
|
3574
|
+
status2.abort();
|
|
3575
3575
|
} else {
|
|
3576
|
-
|
|
3576
|
+
status2.dirty();
|
|
3577
3577
|
}
|
|
3578
3578
|
},
|
|
3579
3579
|
get path() {
|
|
@@ -3585,7 +3585,7 @@ var ZodEffects = class extends ZodType {
|
|
|
3585
3585
|
const processed = effect.transform(ctx.data, checkCtx);
|
|
3586
3586
|
if (ctx.common.async) {
|
|
3587
3587
|
return Promise.resolve(processed).then(async (processed2) => {
|
|
3588
|
-
if (
|
|
3588
|
+
if (status2.value === "aborted")
|
|
3589
3589
|
return INVALID;
|
|
3590
3590
|
const result = await this._def.schema._parseAsync({
|
|
3591
3591
|
data: processed2,
|
|
@@ -3596,12 +3596,12 @@ var ZodEffects = class extends ZodType {
|
|
|
3596
3596
|
return INVALID;
|
|
3597
3597
|
if (result.status === "dirty")
|
|
3598
3598
|
return DIRTY(result.value);
|
|
3599
|
-
if (
|
|
3599
|
+
if (status2.value === "dirty")
|
|
3600
3600
|
return DIRTY(result.value);
|
|
3601
3601
|
return result;
|
|
3602
3602
|
});
|
|
3603
3603
|
} else {
|
|
3604
|
-
if (
|
|
3604
|
+
if (status2.value === "aborted")
|
|
3605
3605
|
return INVALID;
|
|
3606
3606
|
const result = this._def.schema._parseSync({
|
|
3607
3607
|
data: processed,
|
|
@@ -3612,7 +3612,7 @@ var ZodEffects = class extends ZodType {
|
|
|
3612
3612
|
return INVALID;
|
|
3613
3613
|
if (result.status === "dirty")
|
|
3614
3614
|
return DIRTY(result.value);
|
|
3615
|
-
if (
|
|
3615
|
+
if (status2.value === "dirty")
|
|
3616
3616
|
return DIRTY(result.value);
|
|
3617
3617
|
return result;
|
|
3618
3618
|
}
|
|
@@ -3637,17 +3637,17 @@ var ZodEffects = class extends ZodType {
|
|
|
3637
3637
|
if (inner.status === "aborted")
|
|
3638
3638
|
return INVALID;
|
|
3639
3639
|
if (inner.status === "dirty")
|
|
3640
|
-
|
|
3640
|
+
status2.dirty();
|
|
3641
3641
|
executeRefinement(inner.value);
|
|
3642
|
-
return { status:
|
|
3642
|
+
return { status: status2.value, value: inner.value };
|
|
3643
3643
|
} else {
|
|
3644
3644
|
return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((inner) => {
|
|
3645
3645
|
if (inner.status === "aborted")
|
|
3646
3646
|
return INVALID;
|
|
3647
3647
|
if (inner.status === "dirty")
|
|
3648
|
-
|
|
3648
|
+
status2.dirty();
|
|
3649
3649
|
return executeRefinement(inner.value).then(() => {
|
|
3650
|
-
return { status:
|
|
3650
|
+
return { status: status2.value, value: inner.value };
|
|
3651
3651
|
});
|
|
3652
3652
|
});
|
|
3653
3653
|
}
|
|
@@ -3665,13 +3665,13 @@ var ZodEffects = class extends ZodType {
|
|
|
3665
3665
|
if (result instanceof Promise) {
|
|
3666
3666
|
throw new Error(`Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.`);
|
|
3667
3667
|
}
|
|
3668
|
-
return { status:
|
|
3668
|
+
return { status: status2.value, value: result };
|
|
3669
3669
|
} else {
|
|
3670
3670
|
return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((base) => {
|
|
3671
3671
|
if (!isValid(base))
|
|
3672
3672
|
return INVALID;
|
|
3673
3673
|
return Promise.resolve(effect.transform(base.value, checkCtx)).then((result) => ({
|
|
3674
|
-
status:
|
|
3674
|
+
status: status2.value,
|
|
3675
3675
|
value: result
|
|
3676
3676
|
}));
|
|
3677
3677
|
});
|
|
@@ -3850,7 +3850,7 @@ var ZodBranded = class extends ZodType {
|
|
|
3850
3850
|
};
|
|
3851
3851
|
var ZodPipeline = class _ZodPipeline extends ZodType {
|
|
3852
3852
|
_parse(input) {
|
|
3853
|
-
const { status, ctx } = this._processInputParams(input);
|
|
3853
|
+
const { status: status2, ctx } = this._processInputParams(input);
|
|
3854
3854
|
if (ctx.common.async) {
|
|
3855
3855
|
const handleAsync = async () => {
|
|
3856
3856
|
const inResult = await this._def.in._parseAsync({
|
|
@@ -3861,7 +3861,7 @@ var ZodPipeline = class _ZodPipeline extends ZodType {
|
|
|
3861
3861
|
if (inResult.status === "aborted")
|
|
3862
3862
|
return INVALID;
|
|
3863
3863
|
if (inResult.status === "dirty") {
|
|
3864
|
-
|
|
3864
|
+
status2.dirty();
|
|
3865
3865
|
return DIRTY(inResult.value);
|
|
3866
3866
|
} else {
|
|
3867
3867
|
return this._def.out._parseAsync({
|
|
@@ -3881,7 +3881,7 @@ var ZodPipeline = class _ZodPipeline extends ZodType {
|
|
|
3881
3881
|
if (inResult.status === "aborted")
|
|
3882
3882
|
return INVALID;
|
|
3883
3883
|
if (inResult.status === "dirty") {
|
|
3884
|
-
|
|
3884
|
+
status2.dirty();
|
|
3885
3885
|
return {
|
|
3886
3886
|
status: "dirty",
|
|
3887
3887
|
value: inResult.value
|
|
@@ -4047,6 +4047,7 @@ var coerce = {
|
|
|
4047
4047
|
var NEVER = INVALID;
|
|
4048
4048
|
|
|
4049
4049
|
// ../shared/src/acp-protocol.ts
|
|
4050
|
+
var ACP_MAX_FRAME_BYTES = 1024 * 1024;
|
|
4050
4051
|
var acpSessionStateSchema = external_exports.enum(["running", "exited"]);
|
|
4051
4052
|
var acpToolStatusSchema = external_exports.enum(["pending", "running", "ok", "failed", "cancelled"]);
|
|
4052
4053
|
var acpToolKindSchema = external_exports.enum([
|
|
@@ -4161,7 +4162,9 @@ var acpEventSchema = external_exports.discriminatedUnion("type", [
|
|
|
4161
4162
|
name: external_exports.string().nullish(),
|
|
4162
4163
|
kind: acpToolKindSchema,
|
|
4163
4164
|
status: acpToolStatusSchema,
|
|
4164
|
-
locations: external_exports.array(acpToolLocationSchema).default([])
|
|
4165
|
+
locations: external_exports.array(acpToolLocationSchema).default([]),
|
|
4166
|
+
/** O plano do plan mode chega aqui (`035`); ausente quando o adaptador não mandou. */
|
|
4167
|
+
content: external_exports.array(acpToolContentSchema).optional()
|
|
4165
4168
|
}),
|
|
4166
4169
|
/**
|
|
4167
4170
|
* A change to a call already announced. Every field but the id is optional:
|
|
@@ -4315,6 +4318,54 @@ var acpEventSchema = external_exports.discriminatedUnion("type", [
|
|
|
4315
4318
|
* at.
|
|
4316
4319
|
*/
|
|
4317
4320
|
external_exports.object({ type: external_exports.literal("resumed"), fromSessionId: external_exports.string() }),
|
|
4321
|
+
/**
|
|
4322
|
+
* O modelo de ontem não voltou na retomada (`033` F6.2).
|
|
4323
|
+
*
|
|
4324
|
+
* `session/load` não restaura o modelo trocado — medido na M2 —, e o daemon o
|
|
4325
|
+
* reaplica. Quando o agente de hoje não o oferece mais, a conversa continua e
|
|
4326
|
+
* **diz**: trocar calada é a pessoa gastando num modelo que não escolheu sem
|
|
4327
|
+
* saber. `current` vai junto, e não é lido da pílula, porque a linha tem de
|
|
4328
|
+
* dizer o mesmo numa transcrição relida depois de outra troca. Vazio quando o
|
|
4329
|
+
* agente não relata modelo nenhum.
|
|
4330
|
+
*/
|
|
4331
|
+
external_exports.object({ type: external_exports.literal("model_unavailable"), model: external_exports.string(), current: external_exports.string() }),
|
|
4332
|
+
/**
|
|
4333
|
+
* O modelo padrão da conta não está na lista desta sessão (`034` T9, Q9).
|
|
4334
|
+
*
|
|
4335
|
+
* Irmã da de cima, e separada dela: aquela é a **retomada** que não trouxe o
|
|
4336
|
+
* modelo de ontem; esta é a **conta** cujo trio guardado envelheceu — o
|
|
4337
|
+
* adaptador atualizou, ou a conta perdeu o plano. A sessão abre no que o
|
|
4338
|
+
* adaptador escolheu (`got`) em vez de falhar ou trocar em silêncio.
|
|
4339
|
+
*/
|
|
4340
|
+
external_exports.object({
|
|
4341
|
+
type: external_exports.literal("account_default_unavailable"),
|
|
4342
|
+
requested: external_exports.string(),
|
|
4343
|
+
got: external_exports.string()
|
|
4344
|
+
}),
|
|
4345
|
+
/**
|
|
4346
|
+
* Esta conversa continuou noutra conta (`034` T11, Q3b) — a linha no fim da
|
|
4347
|
+
* **origem**.
|
|
4348
|
+
*
|
|
4349
|
+
* Navegação e nada mais: a origem continua viva e aceitando prompt. `label` é
|
|
4350
|
+
* o `agente · conta` de destino, montado pelo daemon, porque a linha tem de
|
|
4351
|
+
* dizer o mesmo depois que alguém renomear a conta.
|
|
4352
|
+
*/
|
|
4353
|
+
external_exports.object({ type: external_exports.literal("continued_in"), sessionId: external_exports.string(), label: external_exports.string() }),
|
|
4354
|
+
/**
|
|
4355
|
+
* Esta conversa é a continuação de outra (`034` T11, Q3a e Q3b) — a linha no
|
|
4356
|
+
* começo da **nova**.
|
|
4357
|
+
*
|
|
4358
|
+
* `messages` e `approxTokens` são do corte que ela levou: a passagem não pode
|
|
4359
|
+
* ser invisível, e *"levou 40 mensagens, ~18 mil tokens"* é o que diz quanto
|
|
4360
|
+
* a conta nova pagou para saber do que se falava.
|
|
4361
|
+
*/
|
|
4362
|
+
external_exports.object({
|
|
4363
|
+
type: external_exports.literal("continued_from"),
|
|
4364
|
+
sessionId: external_exports.string(),
|
|
4365
|
+
label: external_exports.string(),
|
|
4366
|
+
messages: external_exports.number().int().nonnegative(),
|
|
4367
|
+
approxTokens: external_exports.number().int().nonnegative()
|
|
4368
|
+
}),
|
|
4318
4369
|
/**
|
|
4319
4370
|
* O núcleo da memória entrou no prompt (workspace-memory, D2).
|
|
4320
4371
|
*
|
|
@@ -4356,6 +4407,45 @@ var acpEventSchema = external_exports.discriminatedUnion("type", [
|
|
|
4356
4407
|
/** A frase pronta, porque quem monta a frase é quem sabe a unidade. */
|
|
4357
4408
|
message: external_exports.string()
|
|
4358
4409
|
}),
|
|
4410
|
+
/**
|
|
4411
|
+
* A conta desta sessão bateu no limite do agente (`028` T17).
|
|
4412
|
+
*
|
|
4413
|
+
* **Traduzido, e não repassado.** O que chega do adaptador é um
|
|
4414
|
+
* `session/prompt` recusado com `-32603` e um `data.errorKind` que só a `spec`
|
|
4415
|
+
* dele sabe ler; o que sai daqui é o conceito do Lumem — *esta conta não pode
|
|
4416
|
+
* mais responder agora* —, com a conta nomeada, porque desde a
|
|
4417
|
+
* [`034`](../../../docs/features/034-agent-accounts/prd.md) *"o Claude bateu no
|
|
4418
|
+
* limite"* não diz qual.
|
|
4419
|
+
*
|
|
4420
|
+
* **Fecha o turno.** O adaptador não manda `turn_end` numa recusa, e sem este
|
|
4421
|
+
* evento a conversa ficaria dizendo que o agente ainda está respondendo. Ele
|
|
4422
|
+
* não é um `turn_end` de propósito: o turno não aconteceu, e contar um turno
|
|
4423
|
+
* aqui gastaria o teto de `turnsPerSession` num turno que a conta recusou.
|
|
4424
|
+
*
|
|
4425
|
+
* `message` é o texto do adaptador, **só para mostrar** — *"resets 7pm"* está
|
|
4426
|
+
* nele e em nenhum outro campo, e nada no daemon o interpreta. `accountId` e
|
|
4427
|
+
* `accountLabel` são nulos quando a sessão não sabe a conta; `agent` é o
|
|
4428
|
+
* rótulo do catálogo.
|
|
4429
|
+
*/
|
|
4430
|
+
external_exports.object({
|
|
4431
|
+
type: external_exports.literal("quota_refused"),
|
|
4432
|
+
accountId: external_exports.string().nullable(),
|
|
4433
|
+
accountLabel: external_exports.string().nullable(),
|
|
4434
|
+
agent: external_exports.string(),
|
|
4435
|
+
message: external_exports.string()
|
|
4436
|
+
}),
|
|
4437
|
+
/**
|
|
4438
|
+
* O `session/prompt` foi recusado, e não por cota (irmão do `quota_refused`).
|
|
4439
|
+
*
|
|
4440
|
+
* **Fecha o turno**, pelo mesmo motivo: numa recusa o adaptador não manda
|
|
4441
|
+
* `turn_end`, e sem este evento a conversa ficava em `streaming` para sempre —
|
|
4442
|
+
* o botão de interromper aceso sobre um turno morto, e um `internal error`
|
|
4443
|
+
* genérico por cima. E **não** é um `turn_end`, que é onde o contador de turnos
|
|
4444
|
+
* vira: um turno que não aconteceu não gasta o teto de `turnsPerSession`.
|
|
4445
|
+
*
|
|
4446
|
+
* `message` é a frase do erro, **só para mostrar** — nada decide por ela.
|
|
4447
|
+
*/
|
|
4448
|
+
external_exports.object({ type: external_exports.literal("turn_failed"), message: external_exports.string() }),
|
|
4359
4449
|
/**
|
|
4360
4450
|
* An event the daemon received and could not name.
|
|
4361
4451
|
*
|
|
@@ -4475,6 +4565,50 @@ var acpServerMessageSchema = external_exports.discriminatedUnion("type", [
|
|
|
4475
4565
|
})
|
|
4476
4566
|
]);
|
|
4477
4567
|
|
|
4568
|
+
// ../shared/src/adapter-catalog.ts
|
|
4569
|
+
var adapterCatalogEntrySchema = external_exports.object({
|
|
4570
|
+
/** `spec.id` — `claude`, `codex`. */
|
|
4571
|
+
adapterId: external_exports.string().min(1),
|
|
4572
|
+
/**
|
|
4573
|
+
* De qual conta é a leitura (`034` T9). A lista de modelos **é** por conta
|
|
4574
|
+
* (§3.3 do estudo). Nulo é a leitura de antes de haver conta — o primeiro
|
|
4575
|
+
* acesso, ou o arquivo de antes da `034`, que o `load` migra para a conta
|
|
4576
|
+
* padrão do agente.
|
|
4577
|
+
*/
|
|
4578
|
+
accountId: external_exports.string().nullable().default(null),
|
|
4579
|
+
/**
|
|
4580
|
+
* O `spec.pinnedVersion` no instante da captura, e a chave de validade: trocar
|
|
4581
|
+
* o pino invalida a entrada (Q5).
|
|
4582
|
+
*
|
|
4583
|
+
* `null` quando o id não tem spec em `ADAPTERS` (a config fake dos e2e): não
|
|
4584
|
+
* há pino contra o que conferir, e o dia em que o id ganhar spec a entrada cai
|
|
4585
|
+
* sozinha, porque `null` não é versão nenhuma.
|
|
4586
|
+
*/
|
|
4587
|
+
adapterVersion: external_exports.string().nullable(),
|
|
4588
|
+
/**
|
|
4589
|
+
* As opções do `session/new`: o `currentValue` é o **padrão do ACP** (Q8), e
|
|
4590
|
+
* por isso nunca vem de `set_config_option`.
|
|
4591
|
+
*/
|
|
4592
|
+
configOptions: external_exports.array(acpConfigOptionSchema),
|
|
4593
|
+
/**
|
|
4594
|
+
* As opções **depois** de escolher cada modelo, pelo valor do modelo (M1a).
|
|
4595
|
+
*
|
|
4596
|
+
* Existe porque a opção de *effort* depende do modelo — `haiku` não tem, o
|
|
4597
|
+
* `gpt-6-astra` vai até `ultra` —, e o `session/new` só conta a do padrão.
|
|
4598
|
+
* Vazio quer dizer *ninguém percorreu os modelos ainda*.
|
|
4599
|
+
*/
|
|
4600
|
+
optionsByModel: external_exports.record(external_exports.string(), external_exports.array(acpConfigOptionSchema)),
|
|
4601
|
+
/** Do último probe; `false` quando veio de sessão real; `null` se nunca houve opção gravada. */
|
|
4602
|
+
authRequired: external_exports.boolean().nullable(),
|
|
4603
|
+
/**
|
|
4604
|
+
* `projectId` → os últimos comandos vistos (Q4). Por projeto porque as skills
|
|
4605
|
+
* do repositório entram na lista e dependem do `cwd`.
|
|
4606
|
+
*/
|
|
4607
|
+
commandsByProject: external_exports.record(external_exports.string(), external_exports.array(acpCommandSchema)),
|
|
4608
|
+
/** Epoch ms da última mudança de conteúdo. */
|
|
4609
|
+
capturedAt: external_exports.number().int()
|
|
4610
|
+
});
|
|
4611
|
+
|
|
4478
4612
|
// ../shared/src/adapters.ts
|
|
4479
4613
|
var CLAUDE_ADAPTER = {
|
|
4480
4614
|
id: "claude",
|
|
@@ -4522,12 +4656,69 @@ var CLAUDE_ADAPTER = {
|
|
|
4522
4656
|
apiKeyEnv: ["ANTHROPIC_API_KEY"],
|
|
4523
4657
|
// Medido na Q43, e é o único dos cinco que fecha o laço: `default`, `plan`,
|
|
4524
4658
|
// `acceptEdits` e `dontAsk` param no primeiro `Edit` esperando alguém.
|
|
4525
|
-
autonomousMode: "bypassPermissions"
|
|
4659
|
+
autonomousMode: "bypassPermissions",
|
|
4660
|
+
// Medido na fase 0 da `034` (§2.1): com a variável, a entrada do Keychain
|
|
4661
|
+
// ganha o sufixo `-<sha256(dir)[0:8]>` e não colide com a de hoje.
|
|
4662
|
+
accountEnv: "CLAUDE_CONFIG_DIR",
|
|
4663
|
+
defaultConfigDir: ".claude",
|
|
4664
|
+
/*
|
|
4665
|
+
* A lista da Q10 mais `agents/`: os subagentes do usuário moram lá, e a Q10
|
|
4666
|
+
* os conta entre o que a conta nova perde (§2.5 do estudo). Os MCPs de
|
|
4667
|
+
* usuário ficam **fora** — moram no `.claude.json`, junto do `oauthAccount`.
|
|
4668
|
+
*/
|
|
4669
|
+
inheritLinks: ["settings.json", "CLAUDE.md", "rules", "skills", "plugins", "agents"],
|
|
4670
|
+
// §2.5 do estudo: os `mcpServers` do usuário moram no `~/.claude.json`, junto
|
|
4671
|
+
// do `oauthAccount` — nenhum link traz um sem trazer o outro.
|
|
4672
|
+
notInherited: ["os servidores MCP do usu\xE1rio, que moram no ~/.claude.json junto da identidade"],
|
|
4673
|
+
// §4 do estudo: 0,57 s, zero token, com `email` e `subscriptionType` no JSON.
|
|
4674
|
+
// O `session/new` não serve: o do `0.75.1` fecha sem credencial nenhuma.
|
|
4675
|
+
identity: "cli-auth-status",
|
|
4676
|
+
/*
|
|
4677
|
+
* Medido em 2026-09-28, com uma cota semanal esgotada de verdade no `0.75.1`
|
|
4678
|
+
* (`docs/project/agent-accounts-measurements.md` §7): `session/prompt` recusado
|
|
4679
|
+
* com `{ code: -32603, message: "Internal error: You've hit your weekly limit ·
|
|
4680
|
+
* …", data: { errorKind: "rate_limit" } }`, depois de um `agent_message_chunk`
|
|
4681
|
+
* com o mesmo texto e de um `usage_update` zerado, e sem `turn_end`.
|
|
4682
|
+
*/
|
|
4683
|
+
quotaRefusalKind: "rate_limit",
|
|
4684
|
+
/*
|
|
4685
|
+
* Medido em 2026-09-29 contra o `0.75.1` (`036`): o SDK de dentro
|
|
4686
|
+
* (`0.3.257`) nasce com `thinking.display: "omitted"`, e o adaptador só emite
|
|
4687
|
+
* `agent_thought_chunk` quando o bloco tem texto (`acp-agent.js:7742`) — então,
|
|
4688
|
+
* desde 2026-09-08, nenhum pensamento chegava. `_meta.claudeCode.options` é
|
|
4689
|
+
* espalhado direto nas opções do SDK (`:5963`), no `session/new` e no
|
|
4690
|
+
* `session/load`. A cobrança é a mesma com `summarized` e `omitted`.
|
|
4691
|
+
*
|
|
4692
|
+
* Não `MAX_THINKING_TOKENS`: o adaptador a traduz em `enabled` com orçamento e
|
|
4693
|
+
* sem `display`, e o texto continua vazio.
|
|
4694
|
+
*/
|
|
4695
|
+
reasoningMeta: { claudeCode: { options: { thinking: { type: "adaptive", display: "summarized" } } } }
|
|
4526
4696
|
};
|
|
4527
4697
|
var DEFAULT_ADAPTER_ID = CLAUDE_ADAPTER.id;
|
|
4528
4698
|
|
|
4529
4699
|
// ../shared/src/constants.ts
|
|
4530
|
-
var LUMEM_VERSION = "0.
|
|
4700
|
+
var LUMEM_VERSION = "0.7.0";
|
|
4701
|
+
|
|
4702
|
+
// ../shared/src/desktop.ts
|
|
4703
|
+
var DESKTOP_PLATFORMS = ["darwin-arm64", "darwin-x64", "linux-x64", "linux-arm64"];
|
|
4704
|
+
var DESKTOP_APP_NAME = "Lumem";
|
|
4705
|
+
var DESKTOP_CONFIG_FILE = "lumem-desktop.json";
|
|
4706
|
+
function desktopPlatformOf(platform, arch) {
|
|
4707
|
+
const key = `${platform}-${arch}`;
|
|
4708
|
+
return DESKTOP_PLATFORMS.find((known) => known === key) ?? null;
|
|
4709
|
+
}
|
|
4710
|
+
function desktopPackageName(platform) {
|
|
4711
|
+
return `@vinihcrosa/lumem-desktop-${platform}`;
|
|
4712
|
+
}
|
|
4713
|
+
function desktopDataDir({
|
|
4714
|
+
platform,
|
|
4715
|
+
home,
|
|
4716
|
+
env
|
|
4717
|
+
}) {
|
|
4718
|
+
if (platform === "darwin") return `${home}/Library/Application Support/${DESKTOP_APP_NAME}`;
|
|
4719
|
+
const config = env.XDG_CONFIG_HOME;
|
|
4720
|
+
return `${config !== void 0 && config !== "" ? config : `${home}/.config`}/${DESKTOP_APP_NAME}`;
|
|
4721
|
+
}
|
|
4531
4722
|
|
|
4532
4723
|
// ../shared/src/pty-protocol.ts
|
|
4533
4724
|
var ptySessionStateSchema = external_exports.enum(["running", "exited"]);
|
|
@@ -4574,16 +4765,94 @@ var ptyServerMessageSchema = external_exports.discriminatedUnion("type", [
|
|
|
4574
4765
|
external_exports.object({ type: external_exports.literal("error"), code: ptyErrorCodeSchema, message: external_exports.string() })
|
|
4575
4766
|
]);
|
|
4576
4767
|
|
|
4768
|
+
// ../shared/src/update.ts
|
|
4769
|
+
var PACKAGE_NAME = "@vinihcrosa/lumem-os";
|
|
4770
|
+
var REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME.replace("/", "%2F")}/latest`;
|
|
4771
|
+
function detectPackageManager(installPath) {
|
|
4772
|
+
const path = installPath.replace(/\\/g, "/");
|
|
4773
|
+
if (/\/\.?pnpm[/-]/.test(path)) return "pnpm";
|
|
4774
|
+
if (path.includes("/.bun/")) return "bun";
|
|
4775
|
+
if (/\/\.?yarn\//.test(path)) return "yarn";
|
|
4776
|
+
return "npm";
|
|
4777
|
+
}
|
|
4778
|
+
function installCommand(manager, spec) {
|
|
4779
|
+
switch (manager) {
|
|
4780
|
+
case "pnpm":
|
|
4781
|
+
return { command: "pnpm", args: ["add", "--global", spec] };
|
|
4782
|
+
case "yarn":
|
|
4783
|
+
return { command: "yarn", args: ["global", "add", spec] };
|
|
4784
|
+
case "bun":
|
|
4785
|
+
return { command: "bun", args: ["add", "--global", spec] };
|
|
4786
|
+
case "npm":
|
|
4787
|
+
return { command: "npm", args: ["install", "--global", spec] };
|
|
4788
|
+
}
|
|
4789
|
+
}
|
|
4790
|
+
function uninstallCommand(manager, name) {
|
|
4791
|
+
switch (manager) {
|
|
4792
|
+
case "pnpm":
|
|
4793
|
+
return { command: "pnpm", args: ["remove", "--global", name] };
|
|
4794
|
+
case "yarn":
|
|
4795
|
+
return { command: "yarn", args: ["global", "remove", name] };
|
|
4796
|
+
case "bun":
|
|
4797
|
+
return { command: "bun", args: ["remove", "--global", name] };
|
|
4798
|
+
case "npm":
|
|
4799
|
+
return { command: "npm", args: ["uninstall", "--global", name] };
|
|
4800
|
+
}
|
|
4801
|
+
}
|
|
4802
|
+
function compareVersions(a, b) {
|
|
4803
|
+
const split = (version) => {
|
|
4804
|
+
const [core = "", pre = ""] = version.trim().replace(/^v/, "").split("-", 2);
|
|
4805
|
+
return { parts: core.split(".").map((n) => Number.parseInt(n, 10) || 0), pre };
|
|
4806
|
+
};
|
|
4807
|
+
const left = split(a);
|
|
4808
|
+
const right = split(b);
|
|
4809
|
+
for (let i = 0; i < 3; i += 1) {
|
|
4810
|
+
const l = left.parts[i] ?? 0;
|
|
4811
|
+
const r = right.parts[i] ?? 0;
|
|
4812
|
+
if (l !== r) return l < r ? -1 : 1;
|
|
4813
|
+
}
|
|
4814
|
+
if (left.pre === right.pre) return 0;
|
|
4815
|
+
if (left.pre === "") return 1;
|
|
4816
|
+
if (right.pre === "") return -1;
|
|
4817
|
+
return left.pre < right.pre ? -1 : 1;
|
|
4818
|
+
}
|
|
4819
|
+
async function fetchLatestVersion({
|
|
4820
|
+
request = fetch,
|
|
4821
|
+
timeoutMs = 1e4
|
|
4822
|
+
} = {}) {
|
|
4823
|
+
const response = await request(REGISTRY_URL, {
|
|
4824
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
4825
|
+
headers: { accept: "application/json" }
|
|
4826
|
+
});
|
|
4827
|
+
if (!response.ok) throw new Error(`o registry respondeu ${String(response.status)}`);
|
|
4828
|
+
const body = await response.json();
|
|
4829
|
+
if (typeof body.version !== "string" || body.version === "") {
|
|
4830
|
+
throw new Error("o registry respondeu sem vers\xE3o");
|
|
4831
|
+
}
|
|
4832
|
+
return body.version;
|
|
4833
|
+
}
|
|
4834
|
+
|
|
4577
4835
|
// src/run.ts
|
|
4578
|
-
import {
|
|
4836
|
+
import { realpathSync } from "node:fs";
|
|
4837
|
+
import { isAbsolute, join as join3, resolve } from "node:path";
|
|
4838
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
4579
4839
|
|
|
4580
4840
|
// src/args.ts
|
|
4581
4841
|
import { parseArgs } from "node:util";
|
|
4842
|
+
var MENUBAR_ACTIONS = ["install", "open", "uninstall"];
|
|
4582
4843
|
var HELP = `lumem \u2014 harness local de agentes de c\xF3digo
|
|
4583
4844
|
|
|
4584
4845
|
Uso:
|
|
4585
|
-
lumem
|
|
4846
|
+
lumem start [op\xE7\xF5es] instala o Lumem como servi\xE7o, sobe e serve a interface
|
|
4847
|
+
(\xE9 o que \`lumem\`, sem verbo, faz)
|
|
4848
|
+
lumem run [op\xE7\xF5es] roda o daemon em primeiro plano, neste terminal
|
|
4849
|
+
lumem stop para o servi\xE7o e o tira do login
|
|
4850
|
+
lumem status diz se est\xE1 rodando (sa\xEDda 0) ou parado (sa\xEDda 3)
|
|
4851
|
+
lumem logs [-f] as \xFAltimas 200 linhas do log do daemon; -f segue
|
|
4586
4852
|
lumem upgrade [--check] atualiza o daemon para a \xFAltima vers\xE3o do npm
|
|
4853
|
+
lumem menubar install instala o app do Lumem na barra do sistema (macOS e Linux)
|
|
4854
|
+
lumem menubar open abre o painel do app como janela (GNOME sem AppIndicator)
|
|
4855
|
+
lumem menubar uninstall remove o app, o item de login e os arquivos dele
|
|
4587
4856
|
lumem version imprime a vers\xE3o
|
|
4588
4857
|
lumem help imprime esta ajuda
|
|
4589
4858
|
|
|
@@ -4592,6 +4861,7 @@ Op\xE7\xF5es:
|
|
|
4592
4861
|
--host <endere\xE7o> interface de escuta (padr\xE3o: 127.0.0.1)
|
|
4593
4862
|
--state-dir <caminho> onde o Lumem guarda tudo (padr\xE3o: ~/.lumem)
|
|
4594
4863
|
--open abre o navegador quando subir
|
|
4864
|
+
-f, --follow em \`logs\`, segue o que for escrito
|
|
4595
4865
|
--check em \`upgrade\`, s\xF3 diz se tem vers\xE3o nova
|
|
4596
4866
|
-v, --version o mesmo que \`lumem version\`
|
|
4597
4867
|
-h, --help o mesmo que \`lumem help\`
|
|
@@ -4603,6 +4873,7 @@ function toPort(raw) {
|
|
|
4603
4873
|
const port = Number.parseInt(raw.trim(), 10);
|
|
4604
4874
|
return port >= 0 && port <= 65535 ? port : null;
|
|
4605
4875
|
}
|
|
4876
|
+
var VERBS_WITH_WHERE = /* @__PURE__ */ new Set(["start", "run", "stop", "status", "logs", "menubar"]);
|
|
4606
4877
|
function parseCommand(argv) {
|
|
4607
4878
|
let parsed;
|
|
4608
4879
|
try {
|
|
@@ -4616,6 +4887,7 @@ function parseCommand(argv) {
|
|
|
4616
4887
|
"state-dir": { type: "string" },
|
|
4617
4888
|
open: { type: "boolean", default: false },
|
|
4618
4889
|
check: { type: "boolean", default: false },
|
|
4890
|
+
follow: { type: "boolean", short: "f", default: false },
|
|
4619
4891
|
version: { type: "boolean", short: "v", default: false },
|
|
4620
4892
|
help: { type: "boolean", short: "h", default: false }
|
|
4621
4893
|
}
|
|
@@ -4627,24 +4899,98 @@ function parseCommand(argv) {
|
|
|
4627
4899
|
if (values.help === true) return { kind: "help" };
|
|
4628
4900
|
if (values.version === true) return { kind: "version" };
|
|
4629
4901
|
const verb = positionals[0] ?? "start";
|
|
4630
|
-
if (positionals.length > 1) {
|
|
4631
|
-
return { kind: "invalid", message: `comando desconhecido: ${positionals.slice(1).join(" ")}` };
|
|
4902
|
+
if (positionals.length > (verb === "menubar" ? 2 : 1)) {
|
|
4903
|
+
return { kind: "invalid", message: `comando desconhecido: ${positionals.slice(verb === "menubar" ? 2 : 1).join(" ")}` };
|
|
4632
4904
|
}
|
|
4633
4905
|
if (verb === "help") return { kind: "help" };
|
|
4634
4906
|
if (verb === "version") return { kind: "version" };
|
|
4635
4907
|
if (verb === "upgrade") return { kind: "upgrade", check: values.check === true };
|
|
4636
|
-
if (verb
|
|
4908
|
+
if (!VERBS_WITH_WHERE.has(verb)) return { kind: "invalid", message: `comando desconhecido: ${verb}` };
|
|
4909
|
+
if (values.follow === true && verb !== "logs") {
|
|
4910
|
+
return { kind: "invalid", message: "-f s\xF3 existe em `lumem logs`" };
|
|
4911
|
+
}
|
|
4637
4912
|
const port = values.port === void 0 ? null : toPort(values.port);
|
|
4638
4913
|
if (values.port !== void 0 && port === null) {
|
|
4639
4914
|
return { kind: "invalid", message: `--port tem que ser um n\xFAmero entre 0 e 65535, e veio: ${values.port}` };
|
|
4640
4915
|
}
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4916
|
+
const where = { port, host: values.host ?? null, stateDir: values["state-dir"] ?? null };
|
|
4917
|
+
if (verb === "menubar") {
|
|
4918
|
+
const action = MENUBAR_ACTIONS.find((known) => known === positionals[1]);
|
|
4919
|
+
if (action === void 0) {
|
|
4920
|
+
return {
|
|
4921
|
+
kind: "invalid",
|
|
4922
|
+
message: `menubar pede ${MENUBAR_ACTIONS.join(", ")}${positionals[1] === void 0 ? "" : `, e veio: ${positionals[1]}`}`
|
|
4923
|
+
};
|
|
4924
|
+
}
|
|
4925
|
+
return { kind: "menubar", action, ...where };
|
|
4926
|
+
}
|
|
4927
|
+
if (verb === "stop" || verb === "status") return { kind: verb, ...where };
|
|
4928
|
+
if (verb === "logs") return { kind: "logs", ...where, follow: values.follow === true };
|
|
4929
|
+
return { kind: verb === "run" ? "run" : "start", ...where, open: values.open === true };
|
|
4930
|
+
}
|
|
4931
|
+
|
|
4932
|
+
// src/logs.ts
|
|
4933
|
+
import { closeSync, openSync, readFileSync, readSync, statSync } from "node:fs";
|
|
4934
|
+
import { StringDecoder } from "node:string_decoder";
|
|
4935
|
+
var LOG_TAIL_LINES = 200;
|
|
4936
|
+
function lastLines(text, count) {
|
|
4937
|
+
const lines = text.split("\n");
|
|
4938
|
+
if (lines.at(-1) === "") lines.pop();
|
|
4939
|
+
return lines.slice(-count);
|
|
4940
|
+
}
|
|
4941
|
+
async function logs({
|
|
4942
|
+
path,
|
|
4943
|
+
follow,
|
|
4944
|
+
out,
|
|
4945
|
+
err,
|
|
4946
|
+
interrupt,
|
|
4947
|
+
sleep,
|
|
4948
|
+
pollMs = 250
|
|
4949
|
+
}) {
|
|
4950
|
+
let content;
|
|
4951
|
+
try {
|
|
4952
|
+
content = readFileSync(path);
|
|
4953
|
+
} catch {
|
|
4954
|
+
err(`n\xE3o achei o log do daemon em ${path}. O Lumem j\xE1 subiu como servi\xE7o (\`lumem start\`)?`);
|
|
4955
|
+
return 1;
|
|
4956
|
+
}
|
|
4957
|
+
for (const line of lastLines(content.toString("utf8"), LOG_TAIL_LINES)) out(line);
|
|
4958
|
+
if (!follow) return 0;
|
|
4959
|
+
let offset = content.length;
|
|
4960
|
+
let carry = "";
|
|
4961
|
+
const decoder = new StringDecoder("utf8");
|
|
4962
|
+
while (!interrupt.aborted) {
|
|
4963
|
+
await sleep(pollMs);
|
|
4964
|
+
const size = safeSize(path);
|
|
4965
|
+
if (size < offset) {
|
|
4966
|
+
offset = 0;
|
|
4967
|
+
carry = "";
|
|
4968
|
+
}
|
|
4969
|
+
if (size === offset) continue;
|
|
4970
|
+
carry += decoder.write(readRange(path, offset, size));
|
|
4971
|
+
offset = size;
|
|
4972
|
+
const lines = carry.split("\n");
|
|
4973
|
+
carry = lines.pop() ?? "";
|
|
4974
|
+
for (const line of lines) out(line);
|
|
4975
|
+
}
|
|
4976
|
+
return 0;
|
|
4977
|
+
}
|
|
4978
|
+
function safeSize(path) {
|
|
4979
|
+
try {
|
|
4980
|
+
return statSync(path).size;
|
|
4981
|
+
} catch {
|
|
4982
|
+
return 0;
|
|
4983
|
+
}
|
|
4984
|
+
}
|
|
4985
|
+
function readRange(path, start2, end) {
|
|
4986
|
+
const buffer = Buffer.alloc(end - start2);
|
|
4987
|
+
const fd = openSync(path, "r");
|
|
4988
|
+
try {
|
|
4989
|
+
readSync(fd, buffer, 0, buffer.length, start2);
|
|
4990
|
+
} finally {
|
|
4991
|
+
closeSync(fd);
|
|
4992
|
+
}
|
|
4993
|
+
return buffer;
|
|
4648
4994
|
}
|
|
4649
4995
|
|
|
4650
4996
|
// src/open.ts
|
|
@@ -4666,7 +5012,7 @@ function openInBrowser({
|
|
|
4666
5012
|
}
|
|
4667
5013
|
|
|
4668
5014
|
// src/port.ts
|
|
4669
|
-
async function
|
|
5015
|
+
async function readHealth({
|
|
4670
5016
|
origin,
|
|
4671
5017
|
request = fetch,
|
|
4672
5018
|
timeoutMs = 1500
|
|
@@ -4683,68 +5029,432 @@ async function probePort({
|
|
|
4683
5029
|
const body = await response.json();
|
|
4684
5030
|
const data = body.result?.data;
|
|
4685
5031
|
if (data?.ok !== true) return { kind: "other" };
|
|
4686
|
-
return { kind: "lumem", version: data.version ?? "?" };
|
|
5032
|
+
return { kind: "lumem", version: data.version ?? "?", supervised: data.supervised === true };
|
|
4687
5033
|
} catch {
|
|
4688
5034
|
return { kind: "other" };
|
|
4689
5035
|
}
|
|
4690
5036
|
}
|
|
5037
|
+
async function probePort(options) {
|
|
5038
|
+
const health = await readHealth(options);
|
|
5039
|
+
return health.kind === "lumem" ? { kind: "lumem", version: health.version } : health;
|
|
5040
|
+
}
|
|
4691
5041
|
|
|
4692
|
-
// src/
|
|
5042
|
+
// src/service.ts
|
|
5043
|
+
import { execFile } from "node:child_process";
|
|
5044
|
+
import { existsSync, mkdirSync, readFileSync as readFileSync2, rmSync, writeFileSync } from "node:fs";
|
|
5045
|
+
import { homedir } from "node:os";
|
|
5046
|
+
import { dirname, join } from "node:path";
|
|
5047
|
+
var SERVICE_LABEL = "tech.cazimi.lumem";
|
|
5048
|
+
var SYSTEMD_UNIT = "lumem.service";
|
|
5049
|
+
var START_TIMEOUT_MS = 15e3;
|
|
5050
|
+
var STOP_TIMEOUT_MS = 1e4;
|
|
5051
|
+
var POLL_MS = 250;
|
|
5052
|
+
function serviceIdentity(env) {
|
|
5053
|
+
return {
|
|
5054
|
+
label: env["LUMEM_SERVICE_LABEL"] || SERVICE_LABEL,
|
|
5055
|
+
unit: env["LUMEM_SERVICE_UNIT"] || SYSTEMD_UNIT
|
|
5056
|
+
};
|
|
5057
|
+
}
|
|
5058
|
+
function supervisorOf(platform) {
|
|
5059
|
+
if (platform === "darwin") return "launchd";
|
|
5060
|
+
if (platform === "linux") return "systemd";
|
|
5061
|
+
return null;
|
|
5062
|
+
}
|
|
5063
|
+
function daemonLogPath(stateDir) {
|
|
5064
|
+
return join(stateDir, "daemon.log");
|
|
5065
|
+
}
|
|
5066
|
+
function serviceFilePath(host, spec) {
|
|
5067
|
+
return supervisorOf(host.platform) === "launchd" ? join(host.home, "Library", "LaunchAgents", `${spec.label}.plist`) : join(host.home, ".config", "systemd", "user", spec.unit);
|
|
5068
|
+
}
|
|
5069
|
+
function recordedLumemPath(host) {
|
|
5070
|
+
const versioned = /^(.*)\/\.pnpm\/[^/]+\/node_modules\/(@vinihcrosa\/lumem-os\/bin\/lumem\.mjs)$/.exec(host.lumemPath);
|
|
5071
|
+
if (versioned === null) return host.lumemPath;
|
|
5072
|
+
const stable = `${versioned[1] ?? ""}/node_modules/${versioned[2] ?? ""}`;
|
|
5073
|
+
return host.exists(stable) ? stable : host.lumemPath;
|
|
5074
|
+
}
|
|
5075
|
+
function xml(text) {
|
|
5076
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
5077
|
+
}
|
|
5078
|
+
function renderPlist(host, spec) {
|
|
5079
|
+
const environment = { PATH: host.path, ...spec.env, LUMEM_SUPERVISOR: "launchd" };
|
|
5080
|
+
const log = xml(daemonLogPath(spec.stateDir));
|
|
5081
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
5082
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
5083
|
+
<plist version="1.0">
|
|
5084
|
+
<dict>
|
|
5085
|
+
<key>Label</key>
|
|
5086
|
+
<string>${xml(spec.label)}</string>
|
|
5087
|
+
<key>ProgramArguments</key>
|
|
5088
|
+
<array>
|
|
5089
|
+
<string>${xml(host.nodePath)}</string>
|
|
5090
|
+
<string>${xml(recordedLumemPath(host))}</string>
|
|
5091
|
+
<string>run</string>
|
|
5092
|
+
</array>
|
|
5093
|
+
<key>EnvironmentVariables</key>
|
|
5094
|
+
<dict>
|
|
5095
|
+
${Object.entries(environment).map(([key, value]) => ` <key>${xml(key)}</key>
|
|
5096
|
+
<string>${xml(value)}</string>`).join("\n")}
|
|
5097
|
+
</dict>
|
|
5098
|
+
<key>KeepAlive</key>
|
|
5099
|
+
<true/>
|
|
5100
|
+
<key>RunAtLoad</key>
|
|
5101
|
+
<true/>
|
|
5102
|
+
<key>StandardOutPath</key>
|
|
5103
|
+
<string>${log}</string>
|
|
5104
|
+
<key>StandardErrorPath</key>
|
|
5105
|
+
<string>${log}</string>
|
|
5106
|
+
</dict>
|
|
5107
|
+
</plist>
|
|
5108
|
+
`;
|
|
5109
|
+
}
|
|
5110
|
+
function unitWord(word) {
|
|
5111
|
+
const escaped = word.replace(/%/g, "%%").replace(/\$/g, "$$$$");
|
|
5112
|
+
return /[\s"'\\]/.test(escaped) ? `"${escaped.replace(/(["\\])/g, "\\$1")}"` : escaped;
|
|
5113
|
+
}
|
|
5114
|
+
function unitEnvironment(key, value) {
|
|
5115
|
+
const escaped = value.replace(/%/g, "%%");
|
|
5116
|
+
const assignment = `${key}=${escaped}`;
|
|
5117
|
+
return /[\s"'\\]/.test(assignment) ? `Environment="${assignment.replace(/(["\\])/g, "\\$1")}"` : `Environment=${assignment}`;
|
|
5118
|
+
}
|
|
5119
|
+
function renderUnit(host, spec) {
|
|
5120
|
+
const environment = { PATH: host.path, ...spec.env, LUMEM_SUPERVISOR: "systemd" };
|
|
5121
|
+
const log = `append:${daemonLogPath(spec.stateDir)}`;
|
|
5122
|
+
return `[Unit]
|
|
5123
|
+
Description=Lumem
|
|
5124
|
+
|
|
5125
|
+
[Service]
|
|
5126
|
+
ExecStart=${unitWord(host.nodePath)} ${unitWord(recordedLumemPath(host))} run
|
|
5127
|
+
${Object.entries(environment).map(([key, value]) => unitEnvironment(key, value)).join("\n")}
|
|
5128
|
+
Restart=always
|
|
5129
|
+
RestartSec=2
|
|
5130
|
+
StandardOutput=${log}
|
|
5131
|
+
StandardError=${log}
|
|
5132
|
+
|
|
5133
|
+
[Install]
|
|
5134
|
+
WantedBy=default.target
|
|
5135
|
+
`;
|
|
5136
|
+
}
|
|
5137
|
+
function renderService(host, spec) {
|
|
5138
|
+
return supervisorOf(host.platform) === "launchd" ? renderPlist(host, spec) : renderUnit(host, spec);
|
|
5139
|
+
}
|
|
5140
|
+
function isCurrent(host, spec) {
|
|
5141
|
+
return host.read(serviceFilePath(host, spec)) === renderService(host, spec);
|
|
5142
|
+
}
|
|
5143
|
+
var domain = (host) => `gui/${String(host.uid)}`;
|
|
5144
|
+
async function supervisorAnswers(host) {
|
|
5145
|
+
const supervisor = supervisorOf(host.platform);
|
|
5146
|
+
if (supervisor === "launchd") return (await host.exec("launchctl", ["print", domain(host)])).code === 0;
|
|
5147
|
+
if (supervisor === "systemd") {
|
|
5148
|
+
return (await host.exec("systemctl", ["--user", "show-environment"])).code === 0;
|
|
5149
|
+
}
|
|
5150
|
+
return false;
|
|
5151
|
+
}
|
|
5152
|
+
async function isLoaded(host, identity) {
|
|
5153
|
+
const supervisor = supervisorOf(host.platform);
|
|
5154
|
+
if (supervisor === "launchd") {
|
|
5155
|
+
return (await host.exec("launchctl", ["print", `${domain(host)}/${identity.label}`])).code === 0;
|
|
5156
|
+
}
|
|
5157
|
+
if (supervisor === "systemd") {
|
|
5158
|
+
return (await host.exec("systemctl", ["--user", "is-active", identity.unit])).code === 0;
|
|
5159
|
+
}
|
|
5160
|
+
return false;
|
|
5161
|
+
}
|
|
5162
|
+
function failure(step, result) {
|
|
5163
|
+
const detail = result.stderr.trim() || result.stdout.trim() || `saiu com ${String(result.code)}`;
|
|
5164
|
+
return { ok: false, reason: `${step} falhou: ${detail}` };
|
|
5165
|
+
}
|
|
5166
|
+
async function installService(host, spec) {
|
|
5167
|
+
const supervisor = supervisorOf(host.platform);
|
|
5168
|
+
if (supervisor === null) {
|
|
5169
|
+
return {
|
|
5170
|
+
ok: false,
|
|
5171
|
+
reason: `n\xE3o h\xE1 supervisor para ${host.platform}; use \`lumem run\` para rodar em primeiro plano.`
|
|
5172
|
+
};
|
|
5173
|
+
}
|
|
5174
|
+
if (!await supervisorAnswers(host)) {
|
|
5175
|
+
const which = supervisor === "launchd" ? "o launchd n\xE3o responde nesta sess\xE3o (\xE9 preciso uma sess\xE3o gr\xE1fica de usu\xE1rio)" : "o `systemctl --user` n\xE3o responde";
|
|
5176
|
+
return { ok: false, reason: `${which}; use \`lumem run\` para rodar em primeiro plano.` };
|
|
5177
|
+
}
|
|
5178
|
+
const loaded = await isLoaded(host, spec);
|
|
5179
|
+
const file = serviceFilePath(host, spec);
|
|
5180
|
+
host.mkdir(spec.stateDir);
|
|
5181
|
+
host.write(file, renderService(host, spec));
|
|
5182
|
+
if (supervisor === "launchd") {
|
|
5183
|
+
if (loaded) await host.exec("launchctl", ["bootout", `${domain(host)}/${spec.label}`]);
|
|
5184
|
+
const bootstrap = await host.exec("launchctl", ["bootstrap", domain(host), file]);
|
|
5185
|
+
return bootstrap.code === 0 ? { ok: true, file } : failure("`launchctl bootstrap`", bootstrap);
|
|
5186
|
+
}
|
|
5187
|
+
const reload = await host.exec("systemctl", ["--user", "daemon-reload"]);
|
|
5188
|
+
if (reload.code !== 0) return failure("`systemctl --user daemon-reload`", reload);
|
|
5189
|
+
const enable = await host.exec("systemctl", ["--user", "enable", "--now", spec.unit]);
|
|
5190
|
+
if (enable.code !== 0) return failure("`systemctl --user enable --now`", enable);
|
|
5191
|
+
if (loaded) {
|
|
5192
|
+
const restart = await host.exec("systemctl", ["--user", "restart", spec.unit]);
|
|
5193
|
+
if (restart.code !== 0) return failure("`systemctl --user restart`", restart);
|
|
5194
|
+
}
|
|
5195
|
+
return { ok: true, file };
|
|
5196
|
+
}
|
|
5197
|
+
async function restartService(host, identity) {
|
|
5198
|
+
const supervisor = supervisorOf(host.platform);
|
|
5199
|
+
if (supervisor === null) return { ok: false, reason: `n\xE3o h\xE1 supervisor para ${host.platform}` };
|
|
5200
|
+
const [command, args] = supervisor === "launchd" ? ["launchctl", ["kickstart", "-k", `${domain(host)}/${identity.label}`]] : ["systemctl", ["--user", "restart", identity.unit]];
|
|
5201
|
+
const result = await host.exec(command, args);
|
|
5202
|
+
if (result.code === 0) return { ok: true };
|
|
5203
|
+
return failure(`\`${command} ${args.join(" ")}\``, result);
|
|
5204
|
+
}
|
|
5205
|
+
async function waitUntil(host, check, timeoutMs) {
|
|
5206
|
+
const deadline = host.now() + timeoutMs;
|
|
5207
|
+
for (; ; ) {
|
|
5208
|
+
if (await check()) return true;
|
|
5209
|
+
if (host.now() >= deadline) return false;
|
|
5210
|
+
await host.sleep(POLL_MS);
|
|
5211
|
+
}
|
|
5212
|
+
}
|
|
5213
|
+
async function stopService(host, spec, isUp) {
|
|
5214
|
+
const supervisor = supervisorOf(host.platform);
|
|
5215
|
+
const loaded = await isLoaded(host, spec);
|
|
5216
|
+
if (!loaded && await isUp()) {
|
|
5217
|
+
return {
|
|
5218
|
+
ok: false,
|
|
5219
|
+
reason: "o Lumem que responde n\xE3o roda como servi\xE7o; pare-o onde ele roda (Ctrl-C no terminal do `lumem run`)."
|
|
5220
|
+
};
|
|
5221
|
+
}
|
|
5222
|
+
if (supervisor === "launchd") {
|
|
5223
|
+
await host.exec("launchctl", ["bootout", `${domain(host)}/${spec.label}`]);
|
|
5224
|
+
host.remove(serviceFilePath(host, spec));
|
|
5225
|
+
} else if (supervisor === "systemd") {
|
|
5226
|
+
await host.exec("systemctl", ["--user", "disable", "--now", spec.unit]);
|
|
5227
|
+
}
|
|
5228
|
+
const stopped = await waitUntil(host, async () => !await isUp(), STOP_TIMEOUT_MS);
|
|
5229
|
+
return stopped ? { ok: true } : { ok: false, reason: `o Lumem ainda responde depois de ${String(STOP_TIMEOUT_MS / 1e3)} s.` };
|
|
5230
|
+
}
|
|
5231
|
+
function nodeServiceHost(env, lumemPath) {
|
|
5232
|
+
return {
|
|
5233
|
+
platform: process.platform,
|
|
5234
|
+
uid: process.getuid?.() ?? 0,
|
|
5235
|
+
home: homedir(),
|
|
5236
|
+
nodePath: process.execPath,
|
|
5237
|
+
lumemPath,
|
|
5238
|
+
path: env["PATH"] ?? "",
|
|
5239
|
+
exec: (command, args) => new Promise((resolve2) => {
|
|
5240
|
+
execFile(command, [...args], { encoding: "utf8" }, (error, stdout, stderr) => {
|
|
5241
|
+
if (error === null) return resolve2({ code: 0, stdout, stderr });
|
|
5242
|
+
const code2 = typeof error.code === "number" ? error.code : 127;
|
|
5243
|
+
resolve2({ code: code2, stdout, stderr: stderr === "" ? error.message : stderr });
|
|
5244
|
+
});
|
|
5245
|
+
}),
|
|
5246
|
+
read: (path) => {
|
|
5247
|
+
try {
|
|
5248
|
+
return readFileSync2(path, "utf8");
|
|
5249
|
+
} catch {
|
|
5250
|
+
return null;
|
|
5251
|
+
}
|
|
5252
|
+
},
|
|
5253
|
+
exists: (path) => existsSync(path),
|
|
5254
|
+
write: (path, content) => {
|
|
5255
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
5256
|
+
writeFileSync(path, content);
|
|
5257
|
+
},
|
|
5258
|
+
mkdir: (path) => {
|
|
5259
|
+
mkdirSync(path, { recursive: true });
|
|
5260
|
+
},
|
|
5261
|
+
remove: (path) => {
|
|
5262
|
+
rmSync(path, { force: true });
|
|
5263
|
+
},
|
|
5264
|
+
now: () => Date.now(),
|
|
5265
|
+
sleep: (ms) => new Promise((resolve2) => setTimeout(resolve2, ms))
|
|
5266
|
+
};
|
|
5267
|
+
}
|
|
5268
|
+
|
|
5269
|
+
// src/menubar.ts
|
|
4693
5270
|
import { spawn as spawn2 } from "node:child_process";
|
|
5271
|
+
import { dirname as dirname2, join as join2 } from "node:path";
|
|
4694
5272
|
import { fileURLToPath } from "node:url";
|
|
4695
|
-
var
|
|
4696
|
-
var
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
5273
|
+
var APP_BUNDLE = "Lumem.app";
|
|
5274
|
+
var APP_ZIP = "Lumem.zip";
|
|
5275
|
+
var LINUX_EXECUTABLE = ["app", "lumem-desktop"];
|
|
5276
|
+
var USERNS_CLONE = "/proc/sys/kernel/unprivileged_userns_clone";
|
|
5277
|
+
var APPARMOR_RESTRICT = "/proc/sys/kernel/apparmor_restrict_unprivileged_userns";
|
|
5278
|
+
function probeSandbox(read) {
|
|
5279
|
+
const usernsClone = read(USERNS_CLONE)?.trim() ?? null;
|
|
5280
|
+
const apparmorRestrict = read(APPARMOR_RESTRICT)?.trim() ?? null;
|
|
5281
|
+
return { usernsClone, apparmorRestrict, refused: usernsClone === "0" || apparmorRestrict === "1" };
|
|
4703
5282
|
}
|
|
4704
|
-
function
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
return { command: "pnpm", args: ["add", "--global", spec] };
|
|
4708
|
-
case "yarn":
|
|
4709
|
-
return { command: "yarn", args: ["global", "add", spec] };
|
|
4710
|
-
case "bun":
|
|
4711
|
-
return { command: "bun", args: ["add", "--global", spec] };
|
|
4712
|
-
case "npm":
|
|
4713
|
-
return { command: "npm", args: ["install", "--global", spec] };
|
|
4714
|
-
}
|
|
5283
|
+
function sandboxReason({ usernsClone }) {
|
|
5284
|
+
const why = usernsClone === "0" ? "unprivileged_userns_clone=0" : "apparmor_restrict_unprivileged_userns=1";
|
|
5285
|
+
return `o kernel n\xE3o deixa o Chromium criar o sandbox (${why}); os .desktop levam --no-sandbox.`;
|
|
4715
5286
|
}
|
|
4716
|
-
function
|
|
4717
|
-
const
|
|
4718
|
-
|
|
4719
|
-
|
|
5287
|
+
function layoutOf(deps) {
|
|
5288
|
+
const { host, arch, env } = deps;
|
|
5289
|
+
const platform = desktopPlatformOf(host.platform, arch);
|
|
5290
|
+
if (platform === null) return null;
|
|
5291
|
+
const scope = dirname2(dirname2(dirname2(recordedLumemPath(host))));
|
|
5292
|
+
const packageDir = join2(scope, `lumem-desktop-${platform}`);
|
|
5293
|
+
const macApp = join2(host.home, "Applications", APP_BUNDLE);
|
|
5294
|
+
return {
|
|
5295
|
+
platform,
|
|
5296
|
+
packageName: desktopPackageName(platform),
|
|
5297
|
+
packageDir,
|
|
5298
|
+
dataDir: desktopDataDir({ platform: host.platform, home: host.home, env }),
|
|
5299
|
+
macApp,
|
|
5300
|
+
executable: host.platform === "darwin" ? join2(macApp, "Contents", "MacOS", "Lumem") : join2(packageDir, ...LINUX_EXECUTABLE),
|
|
5301
|
+
applicationsEntry: join2(host.home, ".local", "share", "applications", "lumem.desktop"),
|
|
5302
|
+
autostartEntry: join2(host.home, ".config", "autostart", "lumem.desktop")
|
|
4720
5303
|
};
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
|
|
5304
|
+
}
|
|
5305
|
+
function refuse({ host, arch, err }) {
|
|
5306
|
+
err(`o app de desktop n\xE3o existe para ${host.platform}-${arch}. Plataformas com app:`);
|
|
5307
|
+
for (const platform of DESKTOP_PLATFORMS) err(` ${platform}`);
|
|
5308
|
+
return 1;
|
|
5309
|
+
}
|
|
5310
|
+
async function menubar(action, deps) {
|
|
5311
|
+
const layout = layoutOf(deps);
|
|
5312
|
+
if (layout === null) return refuse(deps);
|
|
5313
|
+
if (action === "install") return await installDesktop(deps, layout);
|
|
5314
|
+
if (action === "open") return openDesktop(deps, layout);
|
|
5315
|
+
return await uninstallDesktop(deps, layout);
|
|
5316
|
+
}
|
|
5317
|
+
async function installDesktop(deps, layout) {
|
|
5318
|
+
const { out, err, host, version, where, install } = deps;
|
|
5319
|
+
const command = installCommand(managerOf(deps), `${layout.packageName}@${version}`);
|
|
5320
|
+
out(`instalando o app do Lumem: v${version}`);
|
|
5321
|
+
out(`$ ${command.command} ${command.args.join(" ")}`);
|
|
5322
|
+
const code2 = await runManager(install, command, err);
|
|
5323
|
+
if (code2 !== 0) {
|
|
5324
|
+
err(`o ${command.command} saiu com ${String(code2)}; o app n\xE3o foi instalado.`);
|
|
5325
|
+
return code2;
|
|
4727
5326
|
}
|
|
4728
|
-
if (
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
5327
|
+
if (!host.exists(layout.packageDir)) {
|
|
5328
|
+
err(`o ${command.command} instalou, mas o pacote n\xE3o est\xE1 em ${layout.packageDir}.`);
|
|
5329
|
+
return 1;
|
|
5330
|
+
}
|
|
5331
|
+
const config = {
|
|
5332
|
+
node: host.nodePath,
|
|
5333
|
+
lumem: recordedLumemPath(host),
|
|
5334
|
+
stateDir: where.stateDir,
|
|
5335
|
+
origin: where.origin,
|
|
5336
|
+
path: host.path
|
|
5337
|
+
};
|
|
5338
|
+
host.write(join2(layout.dataDir, DESKTOP_CONFIG_FILE), `${JSON.stringify(config, null, 2)}
|
|
5339
|
+
`);
|
|
5340
|
+
const placed = await placeApp(host, layout, out);
|
|
5341
|
+
if (placed !== null) {
|
|
5342
|
+
err(placed);
|
|
5343
|
+
return 1;
|
|
5344
|
+
}
|
|
5345
|
+
const launch = deps.launch ?? spawnDetached;
|
|
5346
|
+
if (host.platform === "darwin") launch("open", [layout.macApp]);
|
|
5347
|
+
else launch(layout.executable, []);
|
|
5348
|
+
out(
|
|
5349
|
+
host.platform === "darwin" ? `app em ${layout.macApp}; o \xEDcone est\xE1 na barra de menus.` : `app instalado; o \xEDcone est\xE1 na bandeja e o autostart est\xE1 ligado.`
|
|
5350
|
+
);
|
|
5351
|
+
return 0;
|
|
4732
5352
|
}
|
|
4733
|
-
async function
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
const
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
if (
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
5353
|
+
async function takeDesktopAlong(deps) {
|
|
5354
|
+
const layout = layoutOf(deps);
|
|
5355
|
+
const { out, err, host, version } = deps;
|
|
5356
|
+
if (layout === null || !host.exists(layout.packageDir)) return 0;
|
|
5357
|
+
const command = installCommand(managerOf(deps), `${layout.packageName}@${version}`);
|
|
5358
|
+
out(`o app do Lumem vai junto: v${version}`);
|
|
5359
|
+
out(`$ ${command.command} ${command.args.join(" ")}`);
|
|
5360
|
+
const code2 = await runManager(deps.install, command, err);
|
|
5361
|
+
if (code2 !== 0) {
|
|
5362
|
+
err(`o ${command.command} saiu com ${String(code2)}; o app continua na vers\xE3o de antes.`);
|
|
5363
|
+
return code2;
|
|
5364
|
+
}
|
|
5365
|
+
const placed = await placeApp(host, layout, out);
|
|
5366
|
+
if (placed !== null) {
|
|
5367
|
+
err(placed);
|
|
5368
|
+
return 1;
|
|
5369
|
+
}
|
|
5370
|
+
out("app atualizado.");
|
|
5371
|
+
return 0;
|
|
5372
|
+
}
|
|
5373
|
+
async function placeApp(host, layout, out) {
|
|
5374
|
+
if (host.platform !== "darwin") {
|
|
5375
|
+
const sandbox = probeSandbox(host.read);
|
|
5376
|
+
if (sandbox.refused) out(sandboxReason(sandbox));
|
|
5377
|
+
const flags = sandbox.refused ? ["--no-sandbox"] : [];
|
|
5378
|
+
host.write(layout.applicationsEntry, desktopEntry(layout, [...flags, "--panel"]));
|
|
5379
|
+
host.write(layout.autostartEntry, desktopEntry(layout, flags, "X-GNOME-Autostart-enabled=true\n"));
|
|
5380
|
+
return null;
|
|
5381
|
+
}
|
|
5382
|
+
const applications = dirname2(layout.macApp);
|
|
5383
|
+
host.mkdir(applications);
|
|
5384
|
+
await host.exec("rm", ["-rf", layout.macApp]);
|
|
5385
|
+
const unzip = await host.exec("ditto", ["-x", "-k", join2(layout.packageDir, APP_ZIP), applications]);
|
|
5386
|
+
if (unzip.code === 0) return null;
|
|
5387
|
+
return `n\xE3o consegui copiar o app para ${layout.macApp}: ${unzip.stderr.trim() || `ditto saiu com ${String(unzip.code)}`}`;
|
|
5388
|
+
}
|
|
5389
|
+
function execWord(word) {
|
|
5390
|
+
return `"${word.replace(/(["`$\\])/g, "\\$1")}"`;
|
|
5391
|
+
}
|
|
5392
|
+
function desktopEntry(layout, args, extra = "") {
|
|
5393
|
+
const exec = [execWord(layout.executable), ...args].join(" ");
|
|
5394
|
+
return `[Desktop Entry]
|
|
5395
|
+
Type=Application
|
|
5396
|
+
Name=Lumem
|
|
5397
|
+
Comment=O painel do Lumem
|
|
5398
|
+
Exec=${exec}
|
|
5399
|
+
Icon=${join2(layout.packageDir, "icon.png")}
|
|
5400
|
+
Terminal=false
|
|
5401
|
+
Categories=Development;
|
|
5402
|
+
StartupWMClass=Lumem
|
|
5403
|
+
${extra}`;
|
|
5404
|
+
}
|
|
5405
|
+
function openDesktop(deps, layout) {
|
|
5406
|
+
const { err, host } = deps;
|
|
5407
|
+
if (!host.exists(layout.packageDir) || host.platform === "darwin" && !host.exists(layout.macApp)) {
|
|
5408
|
+
err("o app de desktop n\xE3o est\xE1 instalado. Rode `lumem menubar install`.");
|
|
5409
|
+
return 1;
|
|
5410
|
+
}
|
|
5411
|
+
(deps.launch ?? spawnDetached)(layout.executable, ["--panel"]);
|
|
5412
|
+
return 0;
|
|
5413
|
+
}
|
|
5414
|
+
async function uninstallDesktop(deps, layout) {
|
|
5415
|
+
const { out, err, host, install } = deps;
|
|
5416
|
+
const command = uninstallCommand(managerOf(deps), layout.packageName);
|
|
5417
|
+
out(`$ ${command.command} ${command.args.join(" ")}`);
|
|
5418
|
+
const code2 = await runManager(install, command, err);
|
|
5419
|
+
if (code2 !== 0) {
|
|
5420
|
+
err(`o ${command.command} saiu com ${String(code2)}; o app continua instalado.`);
|
|
5421
|
+
return code2;
|
|
5422
|
+
}
|
|
5423
|
+
if (host.platform === "darwin") {
|
|
5424
|
+
if (host.exists(layout.macApp)) await host.exec(layout.executable, ["--uninstall"]);
|
|
5425
|
+
await host.exec("rm", ["-rf", layout.macApp]);
|
|
5426
|
+
} else {
|
|
5427
|
+
host.remove(layout.applicationsEntry);
|
|
5428
|
+
host.remove(layout.autostartEntry);
|
|
5429
|
+
}
|
|
5430
|
+
await host.exec("rm", ["-rf", layout.dataDir]);
|
|
5431
|
+
out("app do Lumem removido.");
|
|
5432
|
+
return 0;
|
|
5433
|
+
}
|
|
5434
|
+
function managerOf(deps) {
|
|
5435
|
+
return deps.manager ?? detectPackageManager(fileURLToPath(import.meta.url));
|
|
5436
|
+
}
|
|
5437
|
+
async function runManager(install, command, err) {
|
|
5438
|
+
try {
|
|
5439
|
+
return await install(command);
|
|
5440
|
+
} catch (error) {
|
|
5441
|
+
err(`n\xE3o consegui rodar o ${command.command}: ${error instanceof Error ? error.message : String(error)}`);
|
|
5442
|
+
return 1;
|
|
5443
|
+
}
|
|
5444
|
+
}
|
|
5445
|
+
function spawnDetached(command, args) {
|
|
5446
|
+
try {
|
|
5447
|
+
const child = spawn2(command, args, { stdio: "ignore", detached: true });
|
|
5448
|
+
child.on("error", () => {
|
|
5449
|
+
});
|
|
5450
|
+
child.unref();
|
|
5451
|
+
} catch {
|
|
4745
5452
|
}
|
|
4746
|
-
return body.version;
|
|
4747
5453
|
}
|
|
5454
|
+
|
|
5455
|
+
// src/upgrade.ts
|
|
5456
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
5457
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
4748
5458
|
async function upgrade(deps) {
|
|
4749
5459
|
const {
|
|
4750
5460
|
out,
|
|
@@ -4754,8 +5464,10 @@ async function upgrade(deps) {
|
|
|
4754
5464
|
origin,
|
|
4755
5465
|
fetchLatest = () => fetchLatestVersion(),
|
|
4756
5466
|
install = runInstall,
|
|
4757
|
-
manager = detectPackageManager(
|
|
4758
|
-
probe = probePort
|
|
5467
|
+
manager = detectPackageManager(fileURLToPath2(import.meta.url)),
|
|
5468
|
+
probe = probePort,
|
|
5469
|
+
service,
|
|
5470
|
+
desktop
|
|
4759
5471
|
} = deps;
|
|
4760
5472
|
let latest;
|
|
4761
5473
|
try {
|
|
@@ -4793,21 +5505,69 @@ async function upgrade(deps) {
|
|
|
4793
5505
|
return code2;
|
|
4794
5506
|
}
|
|
4795
5507
|
out(`pronto: v${latest} instalado.`);
|
|
5508
|
+
const app = desktop === void 0 ? 0 : await takeDesktopAlong({ out, err, ...desktop, version: latest, manager, install });
|
|
5509
|
+
const daemon = await reachTheNewDaemon({ service, probe, origin, latest, out, err });
|
|
5510
|
+
return daemon !== 0 ? daemon : app;
|
|
5511
|
+
}
|
|
5512
|
+
async function reachTheNewDaemon({
|
|
5513
|
+
service,
|
|
5514
|
+
probe,
|
|
5515
|
+
origin,
|
|
5516
|
+
latest,
|
|
5517
|
+
out,
|
|
5518
|
+
err
|
|
5519
|
+
}) {
|
|
5520
|
+
if (service !== void 0 && await isLoaded(service.host, service.identity)) {
|
|
5521
|
+
return await restartLoadedService({ service, probe, origin, latest, out, err });
|
|
5522
|
+
}
|
|
4796
5523
|
const occupant = await probe({ origin });
|
|
4797
5524
|
if (occupant.kind === "lumem") {
|
|
4798
5525
|
out(`o daemon em ${origin} ainda est\xE1 na v${occupant.version}: pare e suba de novo para valer.`);
|
|
4799
5526
|
}
|
|
4800
5527
|
return 0;
|
|
4801
5528
|
}
|
|
5529
|
+
async function restartLoadedService({
|
|
5530
|
+
service,
|
|
5531
|
+
probe,
|
|
5532
|
+
origin,
|
|
5533
|
+
latest,
|
|
5534
|
+
out,
|
|
5535
|
+
err
|
|
5536
|
+
}) {
|
|
5537
|
+
const restarted = await restartService(service.host, service.identity);
|
|
5538
|
+
if (!restarted.ok) {
|
|
5539
|
+
err(`a vers\xE3o nova est\xE1 instalada, mas o servi\xE7o n\xE3o reiniciou: ${restarted.reason}`);
|
|
5540
|
+
err("rode `lumem stop` e `lumem start` para subir a vers\xE3o nova.");
|
|
5541
|
+
return 1;
|
|
5542
|
+
}
|
|
5543
|
+
let seen = "nenhuma";
|
|
5544
|
+
const came = await waitUntil(
|
|
5545
|
+
service.host,
|
|
5546
|
+
async () => {
|
|
5547
|
+
const occupant = await probe({ origin });
|
|
5548
|
+
if (occupant.kind !== "lumem") return false;
|
|
5549
|
+
seen = `v${occupant.version}`;
|
|
5550
|
+
return occupant.version === latest;
|
|
5551
|
+
},
|
|
5552
|
+
START_TIMEOUT_MS
|
|
5553
|
+
);
|
|
5554
|
+
if (!came) {
|
|
5555
|
+
err(`o servi\xE7o reiniciou, mas o Lumem em ${origin} ainda responde ${seen} e n\xE3o v${latest}.`);
|
|
5556
|
+
err("`lumem logs` mostra o que o daemon escreveu.");
|
|
5557
|
+
return 1;
|
|
5558
|
+
}
|
|
5559
|
+
out(`o servi\xE7o reiniciou: o Lumem em ${origin} agora responde v${latest}.`);
|
|
5560
|
+
return 0;
|
|
5561
|
+
}
|
|
4802
5562
|
function message(error) {
|
|
4803
5563
|
return error instanceof Error ? error.message : String(error);
|
|
4804
5564
|
}
|
|
4805
5565
|
async function runInstall({ command, args }) {
|
|
4806
|
-
return await new Promise((
|
|
4807
|
-
const child =
|
|
5566
|
+
return await new Promise((resolve2, reject) => {
|
|
5567
|
+
const child = spawn3(command, args, { stdio: "inherit" });
|
|
4808
5568
|
child.on("error", reject);
|
|
4809
5569
|
child.on("close", (code2) => {
|
|
4810
|
-
|
|
5570
|
+
resolve2(code2 ?? 1);
|
|
4811
5571
|
});
|
|
4812
5572
|
});
|
|
4813
5573
|
}
|
|
@@ -4817,18 +5577,7 @@ var DEFAULT_PORT = 4317;
|
|
|
4817
5577
|
var DEFAULT_HOST = "127.0.0.1";
|
|
4818
5578
|
var DAEMON_ENTRY = "../dist/server/main.mjs";
|
|
4819
5579
|
async function run(argv, deps) {
|
|
4820
|
-
const {
|
|
4821
|
-
out,
|
|
4822
|
-
err,
|
|
4823
|
-
env,
|
|
4824
|
-
version,
|
|
4825
|
-
startDaemon = async () => {
|
|
4826
|
-
await import(fileURLToPath2(new URL(DAEMON_ENTRY, import.meta.url)));
|
|
4827
|
-
},
|
|
4828
|
-
probe = probePort,
|
|
4829
|
-
open = openInBrowser,
|
|
4830
|
-
upgrade: upgrade2 = upgrade
|
|
4831
|
-
} = deps;
|
|
5580
|
+
const { out, err, env, version } = deps;
|
|
4832
5581
|
const command = parseCommand(argv);
|
|
4833
5582
|
if (command.kind === "help") {
|
|
4834
5583
|
out(HELP);
|
|
@@ -4843,17 +5592,104 @@ async function run(argv, deps) {
|
|
|
4843
5592
|
err("`lumem help` lista o que existe.");
|
|
4844
5593
|
return 2;
|
|
4845
5594
|
}
|
|
4846
|
-
const
|
|
5595
|
+
const probe = deps.probe ?? probePort;
|
|
4847
5596
|
if (command.kind === "upgrade") {
|
|
4848
|
-
return await
|
|
5597
|
+
return await (deps.upgrade ?? upgrade)({
|
|
4849
5598
|
out,
|
|
4850
5599
|
err,
|
|
4851
5600
|
current: version,
|
|
4852
5601
|
check: command.check,
|
|
4853
5602
|
origin: originOf(Number(env["LUMEM_PORT"] ?? DEFAULT_PORT), env["LUMEM_HOST"] ?? DEFAULT_HOST),
|
|
4854
|
-
probe
|
|
5603
|
+
probe,
|
|
5604
|
+
service: {
|
|
5605
|
+
host: deps.service ?? nodeServiceHost(env, ownPath()),
|
|
5606
|
+
identity: serviceIdentity(env)
|
|
5607
|
+
},
|
|
5608
|
+
desktop: { host: deps.service ?? nodeServiceHost(env, ownPath()), arch: process.arch, env }
|
|
5609
|
+
});
|
|
5610
|
+
}
|
|
5611
|
+
if (command.kind === "menubar") {
|
|
5612
|
+
const host2 = deps.service ?? nodeServiceHost(env, ownPath());
|
|
5613
|
+
const where2 = resolveWhere(command, env, host2.home);
|
|
5614
|
+
return await (deps.menubar ?? menubar)(command.action, {
|
|
5615
|
+
out,
|
|
5616
|
+
err,
|
|
5617
|
+
host: host2,
|
|
5618
|
+
arch: process.arch,
|
|
5619
|
+
env,
|
|
5620
|
+
version,
|
|
5621
|
+
where: { stateDir: where2.stateDir, origin: where2.origin },
|
|
5622
|
+
install: runInstall
|
|
5623
|
+
});
|
|
5624
|
+
}
|
|
5625
|
+
if (command.kind === "run") return await runForeground(command, deps);
|
|
5626
|
+
const host = deps.service ?? nodeServiceHost(env, ownPath());
|
|
5627
|
+
const where = resolveWhere(command, env, host.home);
|
|
5628
|
+
switch (command.kind) {
|
|
5629
|
+
case "start":
|
|
5630
|
+
return await start(command, deps, host, where);
|
|
5631
|
+
case "stop":
|
|
5632
|
+
return await stop(deps, host, where);
|
|
5633
|
+
case "status":
|
|
5634
|
+
return await status(deps, where);
|
|
5635
|
+
case "logs":
|
|
5636
|
+
return await logs({
|
|
5637
|
+
path: daemonLogPath(where.stateDir),
|
|
5638
|
+
follow: command.follow,
|
|
5639
|
+
out,
|
|
5640
|
+
err,
|
|
5641
|
+
interrupt: deps.interrupt ?? (command.follow ? untilInterrupted() : new AbortController().signal),
|
|
5642
|
+
sleep: host.sleep
|
|
5643
|
+
});
|
|
5644
|
+
}
|
|
5645
|
+
}
|
|
5646
|
+
function untilInterrupted() {
|
|
5647
|
+
const controller = new AbortController();
|
|
5648
|
+
for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
5649
|
+
process.once(signal, () => {
|
|
5650
|
+
controller.abort();
|
|
4855
5651
|
});
|
|
4856
5652
|
}
|
|
5653
|
+
return controller.signal;
|
|
5654
|
+
}
|
|
5655
|
+
function originOf(port, host) {
|
|
5656
|
+
return `http://${host === "0.0.0.0" ? "127.0.0.1" : host}:${String(port)}`;
|
|
5657
|
+
}
|
|
5658
|
+
function ownPath() {
|
|
5659
|
+
const invoked = process.argv[1] ?? "";
|
|
5660
|
+
try {
|
|
5661
|
+
return realpathSync(invoked);
|
|
5662
|
+
} catch {
|
|
5663
|
+
return invoked;
|
|
5664
|
+
}
|
|
5665
|
+
}
|
|
5666
|
+
function resolveWhere(command, env, home) {
|
|
5667
|
+
const port = command.port ?? Number(env["LUMEM_PORT"] ?? DEFAULT_PORT);
|
|
5668
|
+
const host = command.host ?? env["LUMEM_HOST"] ?? DEFAULT_HOST;
|
|
5669
|
+
const rawStateDir = command.stateDir ?? env["LUMEM_STATE_DIR"];
|
|
5670
|
+
const requested = {};
|
|
5671
|
+
if (command.port !== null || env["LUMEM_PORT"] !== void 0) requested["LUMEM_PORT"] = String(port);
|
|
5672
|
+
if (command.host !== null || env["LUMEM_HOST"] !== void 0) requested["LUMEM_HOST"] = host;
|
|
5673
|
+
const stateDir = absolute(rawStateDir ?? join3(home, ".lumem"), home);
|
|
5674
|
+
if (rawStateDir !== void 0) requested["LUMEM_STATE_DIR"] = stateDir;
|
|
5675
|
+
return { port, host, origin: originOf(port, host), stateDir, requested };
|
|
5676
|
+
}
|
|
5677
|
+
function absolute(raw, home) {
|
|
5678
|
+
const expanded = raw === "~" || raw.startsWith("~/") ? join3(home, raw.slice(1)) : raw;
|
|
5679
|
+
return isAbsolute(expanded) ? join3(expanded) : resolve(expanded);
|
|
5680
|
+
}
|
|
5681
|
+
async function runForeground(command, deps) {
|
|
5682
|
+
const {
|
|
5683
|
+
out,
|
|
5684
|
+
err,
|
|
5685
|
+
env,
|
|
5686
|
+
version,
|
|
5687
|
+
startDaemon = async () => {
|
|
5688
|
+
await import(fileURLToPath3(new URL(DAEMON_ENTRY, import.meta.url)));
|
|
5689
|
+
},
|
|
5690
|
+
probe = probePort,
|
|
5691
|
+
open = openInBrowser
|
|
5692
|
+
} = deps;
|
|
4857
5693
|
const port = command.port ?? Number(env["LUMEM_PORT"] ?? DEFAULT_PORT);
|
|
4858
5694
|
const host = command.host ?? env["LUMEM_HOST"] ?? DEFAULT_HOST;
|
|
4859
5695
|
const origin = originOf(port, host);
|
|
@@ -4875,6 +5711,99 @@ async function run(argv, deps) {
|
|
|
4875
5711
|
if (command.open) open({ url: origin });
|
|
4876
5712
|
return 0;
|
|
4877
5713
|
}
|
|
5714
|
+
var START_FAILURE_LOG_LINES = 20;
|
|
5715
|
+
async function start(command, deps, host, where) {
|
|
5716
|
+
const { out, err, env } = deps;
|
|
5717
|
+
const probe = deps.probe ?? probePort;
|
|
5718
|
+
const open = deps.open ?? openInBrowser;
|
|
5719
|
+
const spec = {
|
|
5720
|
+
...serviceIdentity(env),
|
|
5721
|
+
stateDir: where.stateDir,
|
|
5722
|
+
env: where.requested
|
|
5723
|
+
};
|
|
5724
|
+
const occupant = await probe({ origin: where.origin });
|
|
5725
|
+
if (occupant.kind === "other") {
|
|
5726
|
+
err(`a porta ${String(where.port)} est\xE1 ocupada por outra coisa. Use \`lumem start --port <outra>\`.`);
|
|
5727
|
+
return 1;
|
|
5728
|
+
}
|
|
5729
|
+
if (occupant.kind === "lumem") {
|
|
5730
|
+
if (!await isLoaded(host, spec)) {
|
|
5731
|
+
err(
|
|
5732
|
+
`outro Lumem (v${occupant.version}) roda fora do servi\xE7o em ${where.origin}. Pare-o (Ctrl-C no terminal do \`lumem run\`) e rode \`lumem start\` de novo, ou use --port.`
|
|
5733
|
+
);
|
|
5734
|
+
return 1;
|
|
5735
|
+
}
|
|
5736
|
+
if (isCurrent(host, spec)) {
|
|
5737
|
+
out(`o Lumem j\xE1 roda como servi\xE7o em ${where.origin} (v${occupant.version})`);
|
|
5738
|
+
if (command.open) open({ url: where.origin });
|
|
5739
|
+
return 0;
|
|
5740
|
+
}
|
|
5741
|
+
out("o arquivo do servi\xE7o mudou (PATH, node ou lumem); reiniciando o servi\xE7o.");
|
|
5742
|
+
}
|
|
5743
|
+
const installed = await installService(host, spec);
|
|
5744
|
+
if (!installed.ok) {
|
|
5745
|
+
err(installed.reason);
|
|
5746
|
+
return 1;
|
|
5747
|
+
}
|
|
5748
|
+
let running = "?";
|
|
5749
|
+
const answered = await waitUntil(
|
|
5750
|
+
host,
|
|
5751
|
+
async () => {
|
|
5752
|
+
const now = await probe({ origin: where.origin });
|
|
5753
|
+
if (now.kind === "lumem") running = now.version;
|
|
5754
|
+
return now.kind === "lumem";
|
|
5755
|
+
},
|
|
5756
|
+
START_TIMEOUT_MS
|
|
5757
|
+
);
|
|
5758
|
+
if (!answered) {
|
|
5759
|
+
reportStartFailure(deps, host, where);
|
|
5760
|
+
return 1;
|
|
5761
|
+
}
|
|
5762
|
+
out(`Lumem v${running} rodando como servi\xE7o \u2014 ${where.origin}`);
|
|
5763
|
+
out("`lumem logs` mostra o log; `lumem stop` para o servi\xE7o.");
|
|
5764
|
+
if (command.open) open({ url: where.origin });
|
|
5765
|
+
return 0;
|
|
5766
|
+
}
|
|
5767
|
+
function reportStartFailure(deps, host, where) {
|
|
5768
|
+
const { err } = deps;
|
|
5769
|
+
const path = daemonLogPath(where.stateDir);
|
|
5770
|
+
err(`o Lumem n\xE3o respondeu em ${where.origin} em ${String(START_TIMEOUT_MS / 1e3)} s.`);
|
|
5771
|
+
const log = host.read(path);
|
|
5772
|
+
if (log === null) {
|
|
5773
|
+
err(`(sem log em ${path})`);
|
|
5774
|
+
return;
|
|
5775
|
+
}
|
|
5776
|
+
err(`\xFAltimas linhas de ${path}:`);
|
|
5777
|
+
for (const line of lastLines(log, START_FAILURE_LOG_LINES)) err(line);
|
|
5778
|
+
}
|
|
5779
|
+
async function stop(deps, host, where) {
|
|
5780
|
+
const { out, err, env } = deps;
|
|
5781
|
+
const probe = deps.probe ?? probePort;
|
|
5782
|
+
const spec = { ...serviceIdentity(env), stateDir: where.stateDir, env: {} };
|
|
5783
|
+
const result = await stopService(
|
|
5784
|
+
host,
|
|
5785
|
+
spec,
|
|
5786
|
+
async () => (await probe({ origin: where.origin })).kind === "lumem"
|
|
5787
|
+
);
|
|
5788
|
+
if (!result.ok) {
|
|
5789
|
+
err(result.reason);
|
|
5790
|
+
return 1;
|
|
5791
|
+
}
|
|
5792
|
+
out("Lumem parado.");
|
|
5793
|
+
return 0;
|
|
5794
|
+
}
|
|
5795
|
+
async function status(deps, where) {
|
|
5796
|
+
const { out } = deps;
|
|
5797
|
+
const health = await (deps.health ?? readHealth)({ origin: where.origin });
|
|
5798
|
+
if (health.kind === "lumem") {
|
|
5799
|
+
const how = health.supervised ? "supervisionado" : "em primeiro plano";
|
|
5800
|
+
out(`rodando \xB7 v${health.version} \xB7 ${where.origin} \xB7 ${how}`);
|
|
5801
|
+
return 0;
|
|
5802
|
+
}
|
|
5803
|
+
const stranger = health.kind === "other" ? " \xB7 a porta responde, mas n\xE3o \xE9 um Lumem" : "";
|
|
5804
|
+
out(`parado \xB7 ${where.origin}${stranger}`);
|
|
5805
|
+
return 3;
|
|
5806
|
+
}
|
|
4878
5807
|
|
|
4879
5808
|
// src/main.ts
|
|
4880
5809
|
var code = await run(process.argv.slice(2), {
|