@stage5/lumine 0.2.36 → 0.2.37
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/lib/admin.js +26 -17
- package/lib/commands.js +2 -1
- package/package.json +1 -1
- package/sdk/LUMINE_ADMIN.md +24 -0
package/lib/admin.js
CHANGED
|
@@ -4,19 +4,17 @@ import { assertAuthScope, resolveAuth } from "./auth.js";
|
|
|
4
4
|
import { requestJson } from "./http.js";
|
|
5
5
|
|
|
6
6
|
const MAX_EDITORIAL_FILE_BYTES = 256 * 1024;
|
|
7
|
-
const
|
|
8
|
-
const
|
|
7
|
+
const MAX_COMPOSED_TEXT_FILE_BYTES = 64 * 1024;
|
|
8
|
+
const MAX_COMPOSED_TEXT_LENGTH = 10_000;
|
|
9
9
|
const MAX_NOTABLE_NOTE_LENGTH = 2_000;
|
|
10
10
|
|
|
11
|
-
// Operator-composed persona
|
|
12
|
-
//
|
|
11
|
+
// Operator-composed persona text (plain UTF-8, not JSON). The agent writes
|
|
12
|
+
// the content in the bot's persona itself; the server never invokes
|
|
13
13
|
// its model and no AI Energy is spent.
|
|
14
|
-
function
|
|
14
|
+
function readComposedTextFile(filePath) {
|
|
15
15
|
const normalizedPath = String(filePath || "").trim();
|
|
16
16
|
if (!normalizedPath) {
|
|
17
|
-
throw cliValidationError(
|
|
18
|
-
"Pass composed comment text with --file <comment.md>.",
|
|
19
|
-
);
|
|
17
|
+
throw cliValidationError("Pass composed text with --file <file.md>.");
|
|
20
18
|
}
|
|
21
19
|
let contents;
|
|
22
20
|
try {
|
|
@@ -24,18 +22,18 @@ function readComposedCommentFile(filePath) {
|
|
|
24
22
|
} catch {
|
|
25
23
|
throw cliValidationError(`Could not read ${normalizedPath}.`);
|
|
26
24
|
}
|
|
27
|
-
if (Buffer.byteLength(contents, "utf8") >
|
|
28
|
-
throw cliValidationError("The composed
|
|
25
|
+
if (Buffer.byteLength(contents, "utf8") > MAX_COMPOSED_TEXT_FILE_BYTES) {
|
|
26
|
+
throw cliValidationError("The composed text file must be under 64KB.");
|
|
29
27
|
}
|
|
30
28
|
const normalized = contents.trim();
|
|
31
29
|
if (!normalized) {
|
|
32
30
|
throw cliValidationError(
|
|
33
|
-
`${normalizedPath} is empty;
|
|
31
|
+
`${normalizedPath} is empty; composed text is required.`,
|
|
34
32
|
);
|
|
35
33
|
}
|
|
36
|
-
if (normalized.length >
|
|
34
|
+
if (normalized.length > MAX_COMPOSED_TEXT_LENGTH) {
|
|
37
35
|
throw cliValidationError(
|
|
38
|
-
`
|
|
36
|
+
`Composed text must be at most ${MAX_COMPOSED_TEXT_LENGTH} characters.`,
|
|
39
37
|
);
|
|
40
38
|
}
|
|
41
39
|
return normalized;
|
|
@@ -724,6 +722,17 @@ export function parseAdminOperation(options) {
|
|
|
724
722
|
);
|
|
725
723
|
}
|
|
726
724
|
|
|
725
|
+
if (namespace === "announcement" && action === "post") {
|
|
726
|
+
return writeOperation(
|
|
727
|
+
"announcement.post",
|
|
728
|
+
"POST",
|
|
729
|
+
"/cli/admin/announcements",
|
|
730
|
+
{
|
|
731
|
+
content: readComposedTextFile(options.adminFile),
|
|
732
|
+
},
|
|
733
|
+
);
|
|
734
|
+
}
|
|
735
|
+
|
|
727
736
|
if (namespace === "chat" && action === "send") {
|
|
728
737
|
const rawTarget = String(target || "").trim();
|
|
729
738
|
if (!rawTarget) {
|
|
@@ -735,7 +744,7 @@ export function parseAdminOperation(options) {
|
|
|
735
744
|
// the bot's voice; the server never invokes a model for it.
|
|
736
745
|
return writeOperation("chat.send", "POST", "/cli/admin/chat-messages", {
|
|
737
746
|
target: rawTarget,
|
|
738
|
-
content:
|
|
747
|
+
content: readComposedTextFile(options.adminFile),
|
|
739
748
|
});
|
|
740
749
|
}
|
|
741
750
|
|
|
@@ -821,7 +830,7 @@ export function parseAdminOperation(options) {
|
|
|
821
830
|
? parseIdentity(options.adminIdentity)
|
|
822
831
|
: undefined,
|
|
823
832
|
...(options.adminFile
|
|
824
|
-
? { content:
|
|
833
|
+
? { content: readComposedTextFile(options.adminFile) }
|
|
825
834
|
: {}),
|
|
826
835
|
...(reviewedBuildVersionId ? { reviewedBuildVersionId } : {}),
|
|
827
836
|
...(buildReviewMethod ? { buildReviewMethod } : {}),
|
|
@@ -849,7 +858,7 @@ export function parseAdminOperation(options) {
|
|
|
849
858
|
"comment.edit",
|
|
850
859
|
"PUT",
|
|
851
860
|
`/cli/admin/comments/${commentId}`,
|
|
852
|
-
{ content:
|
|
861
|
+
{ content: readComposedTextFile(options.adminFile) },
|
|
853
862
|
);
|
|
854
863
|
}
|
|
855
864
|
if (action === "post") {
|
|
@@ -868,7 +877,7 @@ export function parseAdminOperation(options) {
|
|
|
868
877
|
}
|
|
869
878
|
|
|
870
879
|
throw cliValidationError(
|
|
871
|
-
"Usage: lumine admin identity|daily-run|recommendations|builds|post|subjects|subject|featured|comment|chat|news|audit|brief|bot-output|notable ...",
|
|
880
|
+
"Usage: lumine admin identity|daily-run|recommendations|builds|post|subjects|subject|featured|comment|announcement|chat|news|audit|brief|bot-output|notable ...",
|
|
872
881
|
);
|
|
873
882
|
}
|
|
874
883
|
|
package/lib/commands.js
CHANGED
|
@@ -2541,6 +2541,7 @@ export function printHelp() {
|
|
|
2541
2541
|
lumine admin comment edit <comment-id> --file <comment.md> [--json]
|
|
2542
2542
|
lumine admin brief [--days <1..30>] [--json]
|
|
2543
2543
|
lumine admin bot-output [--days <1..30>] [--json]
|
|
2544
|
+
lumine admin announcement post --file <announcement.md> [--json]
|
|
2544
2545
|
lumine admin chat send <user-id|username> --file <message.md> [--json]
|
|
2545
2546
|
lumine admin notable add <user-id|username> --note <text> [--json]
|
|
2546
2547
|
lumine admin audit [list] [--run current|last|<run-id>] [--target <target>] [--actions <a,b>] [--full] [--cursor <cursor>] [--json]
|
|
@@ -2626,7 +2627,7 @@ Options:
|
|
|
2626
2627
|
--reward-twinkles 3 Pair a recommendation with exactly 3 Twinkles
|
|
2627
2628
|
--twinkles 3 Give exactly 3 Twinkles through the normal economy
|
|
2628
2629
|
--draft-id <id> Canonical delegated comment draft ID
|
|
2629
|
-
--file <path> Editorial JSON or composed
|
|
2630
|
+
--file <path> Editorial JSON or composed text file
|
|
2630
2631
|
--reviewed-version <id> Published Build artifact version actually reviewed
|
|
2631
2632
|
--reviewed-via <method> Build review method: runtime or code
|
|
2632
2633
|
--reason <text> Reason when marking an admin run failed
|
package/package.json
CHANGED
package/sdk/LUMINE_ADMIN.md
CHANGED
|
@@ -1621,6 +1621,30 @@ Ordinary warm follow-ups (checking on a member the bots already know after
|
|
|
1621
1621
|
something the run surfaced) are within a run's judgment, sparingly, and are
|
|
1622
1622
|
always reported in the run report.
|
|
1623
1623
|
|
|
1624
|
+
## Official announcements
|
|
1625
|
+
|
|
1626
|
+
```bash
|
|
1627
|
+
lumine admin announcement post --file announcement.md --json
|
|
1628
|
+
```
|
|
1629
|
+
|
|
1630
|
+
The run's selected bot posts one composed message to General's announcement
|
|
1631
|
+
subchannel (`channelId` 2, `subchannelId` 2). This is the public official
|
|
1632
|
+
board, not a DM and not a Home comment. Mechanics:
|
|
1633
|
+
|
|
1634
|
+
- requires the `chat:post` scope of a comment-mode `post` run;
|
|
1635
|
+
- composed-only (`--file`, same 10,000-character limit as `chat send`);
|
|
1636
|
+
- authors as Zero or Ciel only — the ordinary chat post route and the
|
|
1637
|
+
announcement socket relay now treat those two IDs as allowed announcement
|
|
1638
|
+
authors, same as management-level 3 humans;
|
|
1639
|
+
- persists through the ordinary `msg_chats` insert (channel lock +
|
|
1640
|
+
visibility restore), writes the Twinkle Newspaper `announcement:<messageId>`
|
|
1641
|
+
event, and relays `new_chat_message` on General. No bot socket, session, or
|
|
1642
|
+
presence;
|
|
1643
|
+
- audited as `announcement.post` and idempotent per request key.
|
|
1644
|
+
|
|
1645
|
+
Use this only when Mikey asks for an official announcement. Do not treat a
|
|
1646
|
+
management run as a standing license to post there.
|
|
1647
|
+
|
|
1624
1648
|
## Audit history
|
|
1625
1649
|
|
|
1626
1650
|
```bash
|