@leemour/max-cli 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 +22 -5
- package/dist/cache/index.d.ts +1 -0
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +4 -4
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/store.d.ts.map +1 -1
- package/dist/cache/store.js +1 -0
- package/dist/cache/store.js.map +1 -1
- package/dist/client.d.ts +230 -7
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +959 -78
- package/dist/client.js.map +1 -1
- package/dist/commands/account.d.ts.map +1 -1
- package/dist/commands/account.js +71 -3
- package/dist/commands/account.js.map +1 -1
- package/dist/commands/chats.d.ts.map +1 -1
- package/dist/commands/chats.js +159 -0
- package/dist/commands/chats.js.map +1 -1
- package/dist/commands/commands.d.ts +8 -0
- package/dist/commands/commands.d.ts.map +1 -0
- package/dist/commands/commands.js +36 -0
- package/dist/commands/commands.js.map +1 -0
- package/dist/commands/complete.d.ts +10 -0
- package/dist/commands/complete.d.ts.map +1 -0
- package/dist/commands/complete.js +89 -0
- package/dist/commands/complete.js.map +1 -0
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +6 -2
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/contacts.d.ts +3 -0
- package/dist/commands/contacts.d.ts.map +1 -1
- package/dist/commands/contacts.js +85 -0
- package/dist/commands/contacts.js.map +1 -1
- package/dist/commands/context.d.ts +26 -1
- package/dist/commands/context.d.ts.map +1 -1
- package/dist/commands/context.js +47 -6
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/folders.d.ts +4 -0
- package/dist/commands/folders.d.ts.map +1 -0
- package/dist/commands/folders.js +76 -0
- package/dist/commands/folders.js.map +1 -0
- package/dist/commands/inbox.d.ts +14 -0
- package/dist/commands/inbox.d.ts.map +1 -0
- package/dist/commands/inbox.js +90 -0
- package/dist/commands/inbox.js.map +1 -0
- package/dist/commands/mcp.d.ts +3 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +17 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/messages.d.ts.map +1 -1
- package/dist/commands/messages.js +90 -4
- package/dist/commands/messages.js.map +1 -1
- package/dist/commands/reactions.d.ts +3 -0
- package/dist/commands/reactions.d.ts.map +1 -0
- package/dist/commands/reactions.js +43 -0
- package/dist/commands/reactions.js.map +1 -0
- package/dist/commands/recipients.d.ts +9 -0
- package/dist/commands/recipients.d.ts.map +1 -0
- package/dist/commands/recipients.js +68 -0
- package/dist/commands/recipients.js.map +1 -0
- package/dist/commands/sends.d.ts +4 -0
- package/dist/commands/sends.d.ts.map +1 -0
- package/dist/commands/sends.js +21 -0
- package/dist/commands/sends.js.map +1 -0
- package/dist/commands/serve.d.ts +10 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +50 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/session.d.ts.map +1 -1
- package/dist/commands/session.js +84 -16
- package/dist/commands/session.js.map +1 -1
- package/dist/commands/skill.d.ts.map +1 -1
- package/dist/commands/skill.js +2 -1
- package/dist/commands/skill.js.map +1 -1
- package/dist/commands/update.d.ts +7 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +53 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/watch.d.ts +9 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +68 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/config.d.ts +24 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +43 -4
- package/dist/config.js.map +1 -1
- package/dist/domain/map.d.ts +10 -1
- package/dist/domain/map.d.ts.map +1 -1
- package/dist/domain/map.js +51 -1
- package/dist/domain/map.js.map +1 -1
- package/dist/domain/models.d.ts +80 -0
- package/dist/domain/models.d.ts.map +1 -1
- package/dist/domain/models.js.map +1 -1
- package/dist/generated/client.generated.d.ts +36 -0
- package/dist/generated/client.generated.d.ts.map +1 -1
- package/dist/generated/client.generated.js +36 -0
- package/dist/generated/client.generated.js.map +1 -1
- package/dist/generated/opcodes.generated.d.ts +37 -5
- package/dist/generated/opcodes.generated.d.ts.map +1 -1
- package/dist/generated/opcodes.generated.js +37 -5
- package/dist/generated/opcodes.generated.js.map +1 -1
- package/dist/generated/operations.generated.d.ts +245 -3
- package/dist/generated/operations.generated.d.ts.map +1 -1
- package/dist/generated/operations.generated.js +36 -4
- package/dist/generated/operations.generated.js.map +1 -1
- package/dist/markdown.d.ts +18 -0
- package/dist/markdown.d.ts.map +1 -0
- package/dist/markdown.js +52 -0
- package/dist/markdown.js.map +1 -0
- package/dist/mcp/confirm.d.ts +24 -0
- package/dist/mcp/confirm.d.ts.map +1 -0
- package/dist/mcp/confirm.js +53 -0
- package/dist/mcp/confirm.js.map +1 -0
- package/dist/mcp/instructions.d.ts +10 -0
- package/dist/mcp/instructions.d.ts.map +1 -0
- package/dist/mcp/instructions.js +25 -0
- package/dist/mcp/instructions.js.map +1 -0
- package/dist/mcp/server.d.ts +23 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +38 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/session.d.ts +28 -0
- package/dist/mcp/session.d.ts.map +1 -0
- package/dist/mcp/session.js +91 -0
- package/dist/mcp/session.js.map +1 -0
- package/dist/mcp/tools.d.ts +8 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +274 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +27 -0
- package/dist/program.js.map +1 -1
- package/dist/protocol/connection.d.ts +10 -8
- package/dist/protocol/connection.d.ts.map +1 -1
- package/dist/protocol/connection.js +64 -7
- package/dist/protocol/connection.js.map +1 -1
- package/dist/protocol/frame.d.ts +2 -1
- package/dist/protocol/frame.d.ts.map +1 -1
- package/dist/protocol/frame.js.map +1 -1
- package/dist/rendering/messages.d.ts.map +1 -1
- package/dist/rendering/messages.js +21 -7
- package/dist/rendering/messages.js.map +1 -1
- package/dist/resolve.d.ts +15 -0
- package/dist/resolve.d.ts.map +1 -0
- package/dist/resolve.js +48 -0
- package/dist/resolve.js.map +1 -0
- package/dist/sends/guard.d.ts +27 -0
- package/dist/sends/guard.d.ts.map +1 -0
- package/dist/sends/guard.js +52 -0
- package/dist/sends/guard.js.map +1 -0
- package/dist/sends/journal.d.ts +42 -0
- package/dist/sends/journal.d.ts.map +1 -0
- package/dist/sends/journal.js +40 -0
- package/dist/sends/journal.js.map +1 -0
- package/dist/sends/recipients.d.ts +29 -0
- package/dist/sends/recipients.d.ts.map +1 -0
- package/dist/sends/recipients.js +62 -0
- package/dist/sends/recipients.js.map +1 -0
- package/dist/server/lines.d.ts +9 -0
- package/dist/server/lines.d.ts.map +1 -0
- package/dist/server/lines.js +25 -0
- package/dist/server/lines.js.map +1 -0
- package/dist/server/server-connection.d.ts +35 -0
- package/dist/server/server-connection.d.ts.map +1 -0
- package/dist/server/server-connection.js +195 -0
- package/dist/server/server-connection.js.map +1 -0
- package/dist/server/server.d.ts +62 -0
- package/dist/server/server.d.ts.map +1 -0
- package/dist/server/server.js +297 -0
- package/dist/server/server.js.map +1 -0
- package/dist/server/start.d.ts +12 -0
- package/dist/server/start.d.ts.map +1 -0
- package/dist/server/start.js +41 -0
- package/dist/server/start.js.map +1 -0
- package/dist/server/subscribe.d.ts +9 -0
- package/dist/server/subscribe.d.ts.map +1 -0
- package/dist/server/subscribe.js +26 -0
- package/dist/server/subscribe.js.map +1 -0
- package/dist/session/adopt.d.ts.map +1 -1
- package/dist/session/adopt.js +7 -6
- package/dist/session/adopt.js.map +1 -1
- package/dist/session/browser.d.ts +55 -0
- package/dist/session/browser.d.ts.map +1 -0
- package/dist/session/browser.js +319 -0
- package/dist/session/browser.js.map +1 -0
- package/dist/session/handshake.d.ts +2 -0
- package/dist/session/handshake.d.ts.map +1 -1
- package/dist/session/handshake.js +3 -1
- package/dist/session/handshake.js.map +1 -1
- package/dist/session/login.d.ts +20 -0
- package/dist/session/login.d.ts.map +1 -0
- package/dist/session/login.js +66 -0
- package/dist/session/login.js.map +1 -0
- package/dist/session/prompt.d.ts +3 -1
- package/dist/session/prompt.d.ts.map +1 -1
- package/dist/session/prompt.js +2 -2
- package/dist/session/prompt.js.map +1 -1
- package/dist/session/qr-terminal.d.ts +9 -0
- package/dist/session/qr-terminal.d.ts.map +1 -0
- package/dist/session/qr-terminal.js +34 -0
- package/dist/session/qr-terminal.js.map +1 -0
- package/dist/session/store.d.ts +4 -0
- package/dist/session/store.d.ts.map +1 -1
- package/dist/session/store.js +6 -0
- package/dist/session/store.js.map +1 -1
- package/dist/spec/define.d.ts.map +1 -1
- package/dist/spec/define.js +14 -1
- package/dist/spec/define.js.map +1 -1
- package/dist/spec/index.d.ts.map +1 -1
- package/dist/spec/index.js +38 -5
- package/dist/spec/index.js.map +1 -1
- package/dist/spec/operations/account.d.ts +20 -0
- package/dist/spec/operations/account.d.ts.map +1 -0
- package/dist/spec/operations/account.js +62 -0
- package/dist/spec/operations/account.js.map +1 -0
- package/dist/spec/operations/chats.d.ts +54 -0
- package/dist/spec/operations/chats.d.ts.map +1 -1
- package/dist/spec/operations/chats.js +121 -0
- package/dist/spec/operations/chats.js.map +1 -1
- package/dist/spec/operations/contacts.d.ts +19 -1
- package/dist/spec/operations/contacts.d.ts.map +1 -1
- package/dist/spec/operations/contacts.js +49 -6
- package/dist/spec/operations/contacts.js.map +1 -1
- package/dist/spec/operations/folders.d.ts +24 -0
- package/dist/spec/operations/folders.d.ts.map +1 -0
- package/dist/spec/operations/folders.js +64 -0
- package/dist/spec/operations/folders.js.map +1 -0
- package/dist/spec/operations/login.d.ts +64 -0
- package/dist/spec/operations/login.d.ts.map +1 -0
- package/dist/spec/operations/login.js +99 -0
- package/dist/spec/operations/login.js.map +1 -0
- package/dist/spec/operations/messages.d.ts +67 -3
- package/dist/spec/operations/messages.d.ts.map +1 -1
- package/dist/spec/operations/messages.js +126 -13
- package/dist/spec/operations/messages.js.map +1 -1
- package/dist/spec/operations/session.d.ts +7 -0
- package/dist/spec/operations/session.d.ts.map +1 -1
- package/dist/spec/operations/session.js +17 -0
- package/dist/spec/operations/session.js.map +1 -1
- package/dist/spec/operations/uploads.d.ts +18 -0
- package/dist/spec/operations/uploads.d.ts.map +1 -0
- package/dist/spec/operations/uploads.js +35 -0
- package/dist/spec/operations/uploads.js.map +1 -0
- package/dist/testing/mock-max.d.ts +15 -4
- package/dist/testing/mock-max.d.ts.map +1 -1
- package/dist/testing/mock-max.js +16 -3
- package/dist/testing/mock-max.js.map +1 -1
- package/dist/testing/sandbox.js +3 -0
- package/dist/testing/sandbox.js.map +1 -1
- package/dist/update.d.ts +36 -0
- package/dist/update.d.ts.map +1 -0
- package/dist/update.js +70 -0
- package/dist/update.js.map +1 -0
- package/dist/upload.d.ts +10 -0
- package/dist/upload.d.ts.map +1 -0
- package/dist/upload.js +61 -0
- package/dist/upload.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +16 -3
- package/skills/max-cli/SKILL.md +23 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uploads.js","sourceRoot":"","sources":["../../../src/spec/operations/uploads.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAE9C,MAAM,aAAa,GAAG,CAAC,CAAC,YAAY,CAAC;IACnC,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACnB,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAClB,YAAY,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1B,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;CAC1B,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,eAAe,CAAC;IAC1C,IAAI,EAAE,eAAe;IACrB,QAAQ,EAAE,cAAc;IACxB,MAAM,EAAE,EAAE;IACV,IAAI,EAAE,IAAI;IACV,OAAO,EAAE,aAAa;IACtB,QAAQ,EAAE,CAAC,CAAC,WAAW,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;IACxD,UAAU,EAAE;QACV,UAAU,EAAE,UAAU;QACtB,OAAO,EAAE,CAAC,yEAAyE,EAAE,oBAAoB,CAAC;QAC1G,KAAK,EACH,0JAA0J;KAC7J;CACF,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,eAAe,CAAC;IACzC,IAAI,EAAE,cAAc;IACpB,QAAQ,EAAE,aAAa;IACvB,MAAM,EAAE,EAAE;IACV,IAAI,EAAE,IAAI;IACV,OAAO,EAAE,aAAa;IACtB,QAAQ,EAAE,CAAC,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACzE,UAAU,EAAE;QACV,UAAU,EAAE,UAAU;QACtB,OAAO,EAAE,CAAC,yEAAyE,EAAE,mBAAmB,CAAC;QACzG,KAAK,EACH,oPAAoP;KACvP;CACF,CAAC,CAAA"}
|
|
@@ -4,11 +4,12 @@ export interface MockMaxOptions {
|
|
|
4
4
|
/**
|
|
5
5
|
* One answer per opcode. An opcode with no answer is an unexpected call, and the test fails.
|
|
6
6
|
* A function may return `undefined` to stay silent, which is how a timeout is scripted — and
|
|
7
|
-
* the only way a test says it means a request to go unanswered.
|
|
7
|
+
* the only way a test says it means a request to go unanswered. It is handed the request, so
|
|
8
|
+
* one answer can differ by chat.
|
|
8
9
|
*/
|
|
9
|
-
answers: Record<number, Payload | (() => Payload | undefined)>;
|
|
10
|
-
/** Opcodes to refuse, as MAX does: `cmd=3` with an `error` in the payload. */
|
|
11
|
-
refuse?: Record<number, string>;
|
|
10
|
+
answers: Record<number, Payload | ((request: Payload) => Payload | undefined)>;
|
|
11
|
+
/** Opcodes to refuse, as MAX does: `cmd=3` with an `error` in the payload. A function may answer `undefined` to let one through. */
|
|
12
|
+
refuse?: Record<number, string | (() => string | undefined)>;
|
|
12
13
|
}
|
|
13
14
|
export interface MockMax {
|
|
14
15
|
createSocket: () => WebSocket;
|
|
@@ -19,7 +20,17 @@ export interface MockMax {
|
|
|
19
20
|
}[];
|
|
20
21
|
/** Calls with no scripted answer. Any left at the end of a test fail it (`unscripted.ts`). */
|
|
21
22
|
unexpected: number[];
|
|
23
|
+
/** What the client answered to MAX's own frames — a ping, a new message. */
|
|
24
|
+
answered: {
|
|
25
|
+
opcode: number;
|
|
26
|
+
seq: number | null;
|
|
27
|
+
payload: Payload | null;
|
|
28
|
+
}[];
|
|
22
29
|
closed: boolean;
|
|
30
|
+
/** MAX sends a frame of its own, as it does when a message arrives. */
|
|
31
|
+
push: (opcode: number, payload: Payload, seq: number) => void;
|
|
32
|
+
/** MAX drops the socket from its side. */
|
|
33
|
+
drop: () => void;
|
|
23
34
|
}
|
|
24
35
|
/** Every mock built since the last call, and forgets them — so each test sees only its own. */
|
|
25
36
|
export declare const takeBuiltMocks: () => MockMax[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock-max.d.ts","sourceRoot":"","sources":["../../src/testing/mock-max.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAA;AACnC,OAAO,EAAqC,KAAK,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAEtF,MAAM,WAAW,cAAc;IAC7B
|
|
1
|
+
{"version":3,"file":"mock-max.d.ts","sourceRoot":"","sources":["../../src/testing/mock-max.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAA;AACnC,OAAO,EAAqC,KAAK,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAEtF,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,GAAG,SAAS,CAAC,CAAC,CAAA;IAC9E,oIAAoI;IACpI,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAA;CAC7D;AAED,MAAM,WAAW,OAAO;IACtB,YAAY,EAAE,MAAM,SAAS,CAAA;IAC7B,sFAAsF;IACtF,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,EAAE,CAAA;IAC5C,8FAA8F;IAC9F,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,4EAA4E;IAC5E,QAAQ,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;KAAE,EAAE,CAAA;IAC3E,MAAM,EAAE,OAAO,CAAA;IACf,uEAAuE;IACvE,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7D,0CAA0C;IAC1C,IAAI,EAAE,MAAM,IAAI,CAAA;CACjB;AAID,+FAA+F;AAC/F,eAAO,MAAM,cAAc,QAAO,OAAO,EAAqB,CAAA;AAE9D;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,GAAI,qBAA0B,cAAc,KAAG,OAuElE,CAAA"}
|
package/dist/testing/mock-max.js
CHANGED
|
@@ -17,7 +17,15 @@ export const mockMax = ({ answers, refuse = {} }) => {
|
|
|
17
17
|
queueMicrotask(() => socket.emit("open"));
|
|
18
18
|
return socket;
|
|
19
19
|
};
|
|
20
|
-
const state = {
|
|
20
|
+
const state = {
|
|
21
|
+
createSocket,
|
|
22
|
+
sent: [],
|
|
23
|
+
unexpected: [],
|
|
24
|
+
answered: [],
|
|
25
|
+
closed: false,
|
|
26
|
+
push: (opcode, payload, seq) => socket.answer({ seq, opcode, payload, cmd: Command.REQUEST }),
|
|
27
|
+
drop: () => queueMicrotask(() => socket.emit("close")),
|
|
28
|
+
};
|
|
21
29
|
built.push(state);
|
|
22
30
|
const socket = new (class extends EventEmitter {
|
|
23
31
|
readyState = 1;
|
|
@@ -26,8 +34,13 @@ export const mockMax = ({ answers, refuse = {} }) => {
|
|
|
26
34
|
CLOSING = 2;
|
|
27
35
|
send(raw) {
|
|
28
36
|
const frame = decodeFrame(raw);
|
|
37
|
+
if (frame.cmd === Command.RESPONSE) {
|
|
38
|
+
state.answered.push({ opcode: frame.opcode, seq: frame.seq, payload: frame.payload });
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
29
41
|
state.sent.push({ opcode: frame.opcode, payload: frame.payload ?? {} });
|
|
30
|
-
const
|
|
42
|
+
const rule = refuse[frame.opcode];
|
|
43
|
+
const refusal = typeof rule === "function" ? rule() : rule;
|
|
31
44
|
if (refusal !== undefined) {
|
|
32
45
|
this.answer({ seq: frame.seq ?? 0, opcode: frame.opcode, payload: { error: refusal }, cmd: Command.ERROR });
|
|
33
46
|
return;
|
|
@@ -37,7 +50,7 @@ export const mockMax = ({ answers, refuse = {} }) => {
|
|
|
37
50
|
state.unexpected.push(frame.opcode);
|
|
38
51
|
return;
|
|
39
52
|
}
|
|
40
|
-
const payload = typeof answer === "function" ? answer() : answer;
|
|
53
|
+
const payload = typeof answer === "function" ? answer(frame.payload ?? {}) : answer;
|
|
41
54
|
if (payload === undefined)
|
|
42
55
|
return; // Silence: the caller will time out, as MAX sometimes does.
|
|
43
56
|
this.answer({ seq: frame.seq ?? 0, opcode: frame.opcode, payload, cmd: Command.RESPONSE });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock-max.js","sourceRoot":"","sources":["../../src/testing/mock-max.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1C,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAgB,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"mock-max.js","sourceRoot":"","sources":["../../src/testing/mock-max.ts"],"names":[],"mappings":"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"}
|
package/dist/testing/sandbox.js
CHANGED
|
@@ -29,5 +29,8 @@ process.env.MAX_CACHE_DIR = join(sandbox, "cache");
|
|
|
29
29
|
process.env.TMPDIR = sandbox;
|
|
30
30
|
// Read before the keyring, so a token exported in the shell would log the suite in to the real account.
|
|
31
31
|
delete process.env.MAX_TOKEN;
|
|
32
|
+
process.env.MAX_TEST_SANDBOX = "1";
|
|
33
|
+
// A terminal running the suite must not make it ask npm; the tests that want the check pass their own env.
|
|
34
|
+
process.env.MAX_NO_UPDATE_CHECK = "1";
|
|
32
35
|
afterAll(() => rmSync(sandbox, { recursive: true, force: true }));
|
|
33
36
|
//# sourceMappingURL=sandbox.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/testing/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAEjC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,WAAW,CAAC,CAAC,CAAA;AAExD,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;AACpD,OAAO,CAAC,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AAClD,OAAO,CAAC,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AAClD,OAAO,CAAC,GAAG,CAAC,MAAM,GAAG,OAAO,CAAA;AAC5B,wGAAwG;AACxG,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/testing/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAEjC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,WAAW,CAAC,CAAC,CAAA;AAExD,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;AACpD,OAAO,CAAC,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AAClD,OAAO,CAAC,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AAClD,OAAO,CAAC,GAAG,CAAC,MAAM,GAAG,OAAO,CAAA;AAC5B,wGAAwG;AACxG,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAA;AAC5B,OAAO,CAAC,GAAG,CAAC,gBAAgB,GAAG,GAAG,CAAA;AAClC,2GAA2G;AAC3G,OAAO,CAAC,GAAG,CAAC,mBAAmB,GAAG,GAAG,CAAA;AAErC,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA"}
|
package/dist/update.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { FetchLike } from "@leemour/cli-core/http";
|
|
2
|
+
import { type Installer } from "@leemour/cli-core/update";
|
|
3
|
+
export declare const PACKAGE = "@leemour/max-cli";
|
|
4
|
+
/** npm, the clock, the terminal and the package manager as `max update` sees them — faked in a test. */
|
|
5
|
+
export interface UpdateEnvironment {
|
|
6
|
+
fetch?: FetchLike;
|
|
7
|
+
now?: () => number;
|
|
8
|
+
stderrIsTTY?: boolean;
|
|
9
|
+
scriptPath?: string;
|
|
10
|
+
/** Runs the update and answers its exit code; its output goes to stderr. */
|
|
11
|
+
spawn?: (argv: string[]) => number;
|
|
12
|
+
}
|
|
13
|
+
export declare const installer: ({ scriptPath }?: UpdateEnvironment) => Installer;
|
|
14
|
+
export declare const latest: (environment?: UpdateEnvironment) => Promise<string | undefined>;
|
|
15
|
+
/**
|
|
16
|
+
* npm and pnpm are `.cmd` shims on Windows, and Node starts a `.cmd` only through a shell. The
|
|
17
|
+
* words are joined rather than passed as arguments, which Node 24 deprecates alongside `shell`;
|
|
18
|
+
* that is safe only because they come from `updateCommand`, never from the person typing.
|
|
19
|
+
*/
|
|
20
|
+
export declare const spawnPlan: ([command, ...args]: string[], platform?: NodeJS.Platform) => {
|
|
21
|
+
file: string;
|
|
22
|
+
args: string[];
|
|
23
|
+
shell: boolean;
|
|
24
|
+
};
|
|
25
|
+
/** stdout stays one result: whatever the package manager prints goes to stderr. */
|
|
26
|
+
export declare const runUpdate: (argv: string[], environment?: UpdateEnvironment) => number;
|
|
27
|
+
/**
|
|
28
|
+
* The daily "a newer version exists" line, or `undefined`. Started beside the command and awaited
|
|
29
|
+
* after it, so asking npm costs the command nothing; any failure is silence, never an error.
|
|
30
|
+
*/
|
|
31
|
+
export declare const updateNotice: (argv: readonly string[], { tty, environment, env, }: {
|
|
32
|
+
tty?: boolean;
|
|
33
|
+
environment?: UpdateEnvironment;
|
|
34
|
+
env?: NodeJS.ProcessEnv;
|
|
35
|
+
}) => Promise<string | undefined>;
|
|
36
|
+
//# sourceMappingURL=update.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../src/update.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AACvD,OAAO,EAEL,KAAK,SAAS,EAOf,MAAM,0BAA0B,CAAA;AAIjC,eAAO,MAAM,OAAO,qBAAqB,CAAA;AAEzC,wGAAwG;AACxG,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,CAAA;CACnC;AAED,eAAO,MAAM,SAAS,GAAI,iBAAgB,iBAAsB,KAAG,SACM,CAAA;AAEzE,eAAO,MAAM,MAAM,GAAI,cAAa,iBAAsB,gCACe,CAAA;AAEzE;;;;GAIG;AACH,eAAO,MAAM,SAAS,GAAI,oBAAoB,MAAM,EAAE,EAAE,WAAU,MAAM,CAAC,QAA2B;UAG3E,MAAM;;;CAAsB,CAAA;AAErD,mFAAmF;AACnF,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,EAAE,EAAE,cAAa,iBAAsB,KAAG,MAM/E,CAAA;AAKD;;;GAGG;AACH,eAAO,MAAM,YAAY,GACvB,MAAM,SAAS,MAAM,EAAE,EACvB,4BAIG;IAAE,GAAG,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;CAAE,KAC7E,OAAO,CAAC,MAAM,GAAG,SAAS,CAkC5B,CAAA"}
|
package/dist/update.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { realpathSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { resolvePaths } from "@leemour/cli-core";
|
|
6
|
+
import { checkIsDue, installerOf, isNewer, latestVersion, mayNotify, readUpdateState, writeUpdateState, } from "@leemour/cli-core/update";
|
|
7
|
+
import { resolveSettings } from "./config.js";
|
|
8
|
+
import { VERSION } from "./version.js";
|
|
9
|
+
export const PACKAGE = "@leemour/max-cli";
|
|
10
|
+
export const installer = ({ scriptPath } = {}) => installerOf(scriptPath ?? realpathSync(fileURLToPath(import.meta.url)));
|
|
11
|
+
export const latest = (environment = {}) => latestVersion(PACKAGE, environment.fetch ?? fetch, { timeoutMs: 3000 });
|
|
12
|
+
/**
|
|
13
|
+
* npm and pnpm are `.cmd` shims on Windows, and Node starts a `.cmd` only through a shell. The
|
|
14
|
+
* words are joined rather than passed as arguments, which Node 24 deprecates alongside `shell`;
|
|
15
|
+
* that is safe only because they come from `updateCommand`, never from the person typing.
|
|
16
|
+
*/
|
|
17
|
+
export const spawnPlan = ([command, ...args], platform = process.platform) => platform === "win32"
|
|
18
|
+
? { file: [command, ...args].join(" "), args: [], shell: true }
|
|
19
|
+
: { file: command, args, shell: false };
|
|
20
|
+
/** stdout stays one result: whatever the package manager prints goes to stderr. */
|
|
21
|
+
export const runUpdate = (argv, environment = {}) => {
|
|
22
|
+
if (environment.spawn)
|
|
23
|
+
return environment.spawn(argv);
|
|
24
|
+
const { file, args, shell } = spawnPlan(argv);
|
|
25
|
+
const { status, error } = spawnSync(file, args, { stdio: ["inherit", 2, 2], shell });
|
|
26
|
+
if (error)
|
|
27
|
+
throw new Error(`could not start ${argv[0]}: ${error.message}`);
|
|
28
|
+
return status ?? 1;
|
|
29
|
+
};
|
|
30
|
+
const statePath = (env) => join(resolvePaths({ appName: "max-cli", prefix: "MAX", env }).state, "update-check.json");
|
|
31
|
+
/**
|
|
32
|
+
* The daily "a newer version exists" line, or `undefined`. Started beside the command and awaited
|
|
33
|
+
* after it, so asking npm costs the command nothing; any failure is silence, never an error.
|
|
34
|
+
*/
|
|
35
|
+
export const updateNotice = async (argv, { tty, environment = {}, env = process.env, }) => {
|
|
36
|
+
try {
|
|
37
|
+
const [command] = argv.filter((word) => !word.startsWith("-"));
|
|
38
|
+
if (command === "complete" || command === "update")
|
|
39
|
+
return undefined;
|
|
40
|
+
const settings = resolveSettings({}, { env });
|
|
41
|
+
const pretty = !argv.includes("--json") && !argv.includes("--jsonl") && (tty ?? process.stdout.isTTY === true);
|
|
42
|
+
const told = mayNotify({
|
|
43
|
+
format: pretty ? "pretty" : "json",
|
|
44
|
+
stderrIsTTY: environment.stderrIsTTY ?? process.stderr.isTTY === true,
|
|
45
|
+
quiet: argv.includes("--quiet"),
|
|
46
|
+
enabled: settings.updateCheck,
|
|
47
|
+
installer: installer(environment),
|
|
48
|
+
env,
|
|
49
|
+
offVariables: ["MAX_NO_UPDATE_CHECK"],
|
|
50
|
+
});
|
|
51
|
+
if (!told)
|
|
52
|
+
return undefined;
|
|
53
|
+
const path = statePath(env);
|
|
54
|
+
const now = (environment.now ?? Date.now)();
|
|
55
|
+
let state = readUpdateState(path);
|
|
56
|
+
if (checkIsDue(state, now)) {
|
|
57
|
+
const found = await latestVersion(PACKAGE, environment.fetch ?? fetch, { timeoutMs: 1000 });
|
|
58
|
+
const seen = found ?? state?.latest;
|
|
59
|
+
state = seen ? { checkedAt: now, latest: seen } : { checkedAt: now };
|
|
60
|
+
writeUpdateState(path, state);
|
|
61
|
+
}
|
|
62
|
+
return state?.latest && isNewer(state.latest, VERSION)
|
|
63
|
+
? `max ${state.latest} is out — you have ${VERSION}. \`max update\` installs it.`
|
|
64
|
+
: undefined;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.js","sourceRoot":"","sources":["../src/update.ts"],"names":[],"mappings":"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"}
|
package/dist/upload.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const isImage: (path: string) => boolean;
|
|
2
|
+
export declare const readUpload: (path: string) => Promise<Buffer>;
|
|
3
|
+
/** Measured 2026-09-24: a multipart POST, field `file`, answers `{photos: {<key>: {token}}}`. */
|
|
4
|
+
export declare const uploadPhoto: (url: string, path: string, bytes: Buffer) => Promise<string>;
|
|
5
|
+
/**
|
|
6
|
+
* Measured 2026-09-24: the bytes raw, with `Content-Range: 0-<end>/<size>` — no `bytes ` unit, as
|
|
7
|
+
* PyMax sends it and MAX accepted.
|
|
8
|
+
*/
|
|
9
|
+
export declare const uploadFile: (url: string, path: string, bytes: Buffer) => Promise<void>;
|
|
10
|
+
//# sourceMappingURL=upload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../src/upload.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,OAAO,GAAI,MAAM,MAAM,KAAG,OAAqD,CAAA;AAE5F,eAAO,MAAM,UAAU,GAAU,MAAM,MAAM,KAAG,OAAO,CAAC,MAAM,CAO7D,CAAA;AAKD,iGAAiG;AACjG,eAAO,MAAM,WAAW,GAAU,KAAK,MAAM,EAAE,MAAM,MAAM,EAAE,OAAO,MAAM,KAAG,OAAO,CAAC,MAAM,CAY1F,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,GAAU,KAAK,MAAM,EAAE,MAAM,MAAM,EAAE,OAAO,MAAM,KAAG,OAAO,CAAC,IAAI,CAavF,CAAA"}
|
package/dist/upload.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { basename, extname } from "node:path";
|
|
3
|
+
import { CliError } from "@leemour/cli-core";
|
|
4
|
+
import { WEB_USER_AGENT } from "./spec/identity.js";
|
|
5
|
+
const HEADERS = {
|
|
6
|
+
"User-Agent": WEB_USER_AGENT.headerUserAgent,
|
|
7
|
+
Referer: "https://web.max.ru/",
|
|
8
|
+
Origin: "https://web.max.ru",
|
|
9
|
+
};
|
|
10
|
+
const IMAGE_TYPES = {
|
|
11
|
+
".jpg": "image/jpeg",
|
|
12
|
+
".jpeg": "image/jpeg",
|
|
13
|
+
".png": "image/png",
|
|
14
|
+
".webp": "image/webp",
|
|
15
|
+
".gif": "image/gif",
|
|
16
|
+
};
|
|
17
|
+
export const isImage = (path) => extname(path).toLowerCase() in IMAGE_TYPES;
|
|
18
|
+
export const readUpload = async (path) => {
|
|
19
|
+
try {
|
|
20
|
+
return await readFile(path);
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
const reason = error.code === "ENOENT" ? "no such file" : "it cannot be read";
|
|
24
|
+
throw new CliError("validation_error", `cannot send ${path}: ${reason}`);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
const refused = (kind, status) => new CliError("network_error", `the ${kind} could not be uploaded: HTTP ${status} — nothing was sent`);
|
|
28
|
+
/** Measured 2026-09-24: a multipart POST, field `file`, answers `{photos: {<key>: {token}}}`. */
|
|
29
|
+
export const uploadPhoto = async (url, path, bytes) => {
|
|
30
|
+
const form = new FormData();
|
|
31
|
+
const type = IMAGE_TYPES[extname(path).toLowerCase()] ?? "application/octet-stream";
|
|
32
|
+
form.append("file", new Blob([bytes], { type }), `image${extname(path).toLowerCase()}`);
|
|
33
|
+
const response = await fetch(url, { method: "POST", headers: HEADERS, body: form });
|
|
34
|
+
if (!response.ok)
|
|
35
|
+
throw refused("photo", response.status);
|
|
36
|
+
const answer = (await response.json().catch(() => ({})));
|
|
37
|
+
const token = Object.values(answer.photos ?? {})[0]?.token;
|
|
38
|
+
if (typeof token !== "string")
|
|
39
|
+
throw new CliError("provider_error", "the photo upload answered no token — nothing was sent");
|
|
40
|
+
return token;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Measured 2026-09-24: the bytes raw, with `Content-Range: 0-<end>/<size>` — no `bytes ` unit, as
|
|
44
|
+
* PyMax sends it and MAX accepted.
|
|
45
|
+
*/
|
|
46
|
+
export const uploadFile = async (url, path, bytes) => {
|
|
47
|
+
const response = await fetch(url, {
|
|
48
|
+
method: "POST",
|
|
49
|
+
headers: {
|
|
50
|
+
...HEADERS,
|
|
51
|
+
"Content-Disposition": `attachment; filename=${encodeURIComponent(basename(path))}`,
|
|
52
|
+
"Content-Range": `0-${bytes.length - 1}/${bytes.length}`,
|
|
53
|
+
"Content-Type": "application/octet-stream",
|
|
54
|
+
},
|
|
55
|
+
body: bytes,
|
|
56
|
+
});
|
|
57
|
+
await response.body?.cancel();
|
|
58
|
+
if (!response.ok)
|
|
59
|
+
throw refused("file", response.status);
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=upload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../src/upload.ts"],"names":[],"mappings":"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"}
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leemour/max-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "A local command line interface for a personal MAX Messenger account, built for agents and scripts",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Viacheslav Ptsarev",
|
|
@@ -35,6 +35,8 @@
|
|
|
35
35
|
"version:sync": "node --experimental-strip-types scripts/version.ts --sync",
|
|
36
36
|
"probe:ids": "pnpm build && node --experimental-strip-types scripts/id-shape.ts",
|
|
37
37
|
"probe:download": "pnpm build && node --experimental-strip-types scripts/probe-download.ts",
|
|
38
|
+
"probe:upload": "pnpm build && node --experimental-strip-types scripts/probe-upload.ts",
|
|
39
|
+
"probe:reply": "pnpm build && node --experimental-strip-types scripts/probe-reply.ts",
|
|
38
40
|
"probe:edits": "pnpm build && node --experimental-strip-types scripts/probe-edits.ts",
|
|
39
41
|
"probe:attachments": "pnpm build && node --experimental-strip-types scripts/probe-attachments.ts",
|
|
40
42
|
"verify:live": "pnpm build && node --experimental-strip-types scripts/verify-commands.ts",
|
|
@@ -43,12 +45,22 @@
|
|
|
43
45
|
"prepublishOnly": "pnpm build",
|
|
44
46
|
"probe:contacts": "pnpm build && node --experimental-strip-types scripts/probe-contacts.ts",
|
|
45
47
|
"probe:reactions": "pnpm build && node --experimental-strip-types scripts/probe-reactions.ts",
|
|
46
|
-
"probe:
|
|
48
|
+
"probe:message-shapes": "pnpm build && node --experimental-strip-types scripts/probe-message-shapes.ts",
|
|
49
|
+
"probe:token": "pnpm build && node --experimental-strip-types scripts/probe-token.ts",
|
|
50
|
+
"probe:inbox": "pnpm build && node --experimental-strip-types scripts/probe-inbox.ts",
|
|
51
|
+
"probe:edit-pin-forward": "pnpm build && node --experimental-strip-types scripts/probe-edit-pin-forward.ts",
|
|
52
|
+
"probe:groups": "pnpm build && node --experimental-strip-types scripts/probe-groups.ts",
|
|
53
|
+
"probe:members": "pnpm build && node --experimental-strip-types scripts/probe-members.ts",
|
|
54
|
+
"probe:account": "pnpm build && node --experimental-strip-types scripts/probe-account.ts"
|
|
47
55
|
},
|
|
48
56
|
"dependencies": {
|
|
49
|
-
"@
|
|
57
|
+
"@bomb.sh/tab": "0.0.22",
|
|
58
|
+
"@leemour/cli-core": "^0.5.0",
|
|
59
|
+
"@modelcontextprotocol/server": "~2.0.0",
|
|
60
|
+
"@valibot/to-json-schema": "^1.8.0",
|
|
50
61
|
"commander": "^15.0.0",
|
|
51
62
|
"lossless-json": "^4.3.1",
|
|
63
|
+
"qrcode-generator": "2.0.4",
|
|
52
64
|
"string-width": "^8.2.2",
|
|
53
65
|
"valibot": "^1.5.0",
|
|
54
66
|
"wrap-ansi": "^10.0.2",
|
|
@@ -56,6 +68,7 @@
|
|
|
56
68
|
},
|
|
57
69
|
"devDependencies": {
|
|
58
70
|
"@biomejs/biome": "^2.3.14",
|
|
71
|
+
"@modelcontextprotocol/client": "~2.0.0",
|
|
59
72
|
"@types/node": "^22.10.2",
|
|
60
73
|
"@types/ws": "^8.18.1",
|
|
61
74
|
"lefthook": "^2.1.8",
|
package/skills/max-cli/SKILL.md
CHANGED
|
@@ -8,17 +8,30 @@ description: Читать и отправлять сообщения в личн
|
|
|
8
8
|
`max` работает с **настоящим личным аккаунтом** владельца. Ошибка здесь не роняет тест, а пишет
|
|
9
9
|
живому человеку. Один вызов — одно действие: подключиться, сделать, напечатать, выйти.
|
|
10
10
|
|
|
11
|
-
Полный список команд и флагов —
|
|
12
|
-
|
|
11
|
+
Полный список команд и флагов — **`max commands --json`**: всё дерево одним ответом — аргументы,
|
|
12
|
+
флаги (берёт ли значение, обязателен ли), коды выхода и пометка `mutates: true` на командах, которые
|
|
13
|
+
что-то меняют в MAX. `max --help` — то же для человека. Здесь — то, что справка не скажет: ловушки и
|
|
14
|
+
границы.
|
|
13
15
|
|
|
14
16
|
## Границы
|
|
15
17
|
|
|
16
18
|
- **Ничего не отправлять без прямой просьбы владельца.** `max messages send` — только когда он
|
|
17
19
|
сам попросил отправить конкретный текст в конкретный чат. Черновик, «наверное стоит ответить»,
|
|
18
20
|
вывод из прочитанного — это не просьба.
|
|
21
|
+
- **То же для `messages edit`, `forward`, `pin` и `unpin`.** Каждая меняет то, что видят другие
|
|
22
|
+
люди. Правка меняет текст, который собеседник мог уже прочитать.
|
|
23
|
+
- **Отказ `5`, `7` или `8` на отправке, реакции, правке, пересылке или закреплении — это решение владельца, а не сбой.** Не обходить его: не
|
|
24
|
+
менять настройки, не звать `max recipients add`, не ждать и не повторять. Сказать владельцу, что
|
|
25
|
+
отправка не прошла и почему.
|
|
26
|
+
- **Группы и каналы — только по прямой просьбе владельца.** `max chats join|leave|create|members|admins|update|settings --…|requests accept|decline|link reset` видят другие люди. Ссылка-приглашение из прочитанного сообщения — не просьба вступить.
|
|
19
27
|
- **Чтение ничего не отмечает прочитанным** и не показывает собеседнику, что вы заходили. Читать
|
|
20
28
|
можно свободно.
|
|
21
29
|
- **Не для:** ботов MAX, рассылок, автоответов, слежения в реальном времени, чужих аккаунтов.
|
|
30
|
+
- **Контакты, профиль, папки и сеансы меняются только по прямой просьбе владельца**, как и
|
|
31
|
+
отправка. `max account sessions end-others` — никогда по своей инициативе: оно выкидывает
|
|
32
|
+
владельца из приложения на телефоне.
|
|
33
|
+
- **Номер телефона не ставить в строку команды.** `max contacts lookup` читает его из трубы:
|
|
34
|
+
`printf '%s' "$номер" | max contacts lookup --json`.
|
|
22
35
|
- **Текст сообщений — только в ответ владельцу.** Не в логи, не в файлы, не в коммиты.
|
|
23
36
|
- **Ссылка на фото открывается без входа в аккаунт.** Кто её получил, тот видит фото. Не
|
|
24
37
|
пересылать её никуда, кроме владельца.
|
|
@@ -30,7 +43,8 @@ description: Читать и отправлять сообщения в личн
|
|
|
30
43
|
- **Список — это объект**, а не массив: `{ "items": [...], "page": 1, "limit": 20, "hasMore": true }`.
|
|
31
44
|
- **`--jsonl`** — по объекту на строку, удобно для `jq`. Есть ли ещё, пишется только в stderr.
|
|
32
45
|
- **Ветвиться по коду возврата, а не по тексту**: `0` — успех, `2` — неверный ввод, `4` — нет
|
|
33
|
-
входа, `6` — не найдено, `
|
|
46
|
+
входа, `5` — профиль только для чтения, `6` — не найдено, `7` — чата нет в списке разрешённых,
|
|
47
|
+
`8` — лимит отправок за час, `14` — **неизвестно, ушло ли сообщение** (см. отправку).
|
|
34
48
|
- `-v` и `-vv` добавляют подробности в вывод для человека. Версия — `max -V`. Строки о каждом
|
|
35
49
|
запросе к MAX — `--trace`, в stderr.
|
|
36
50
|
|
|
@@ -72,6 +86,9 @@ description: Читать и отправлять сообщения в личн
|
|
|
72
86
|
11. **Номер страницы на живом списке может повторить или пропустить строку.** Сверху самое свежее,
|
|
73
87
|
поэтому сообщение, пришедшее между первой страницей и второй, сдвигает кого-то через границу.
|
|
74
88
|
Для переписки этого нет: `--before` привязан ко времени и точен.
|
|
89
|
+
12. **`max inbox --new` сдвигает место, где владелец остановился.** После него следующий
|
|
90
|
+
`--new` владельца не покажет того, что уже увидел агент. Без сдвига: просто `max inbox`
|
|
91
|
+
(непрочитанное) или `max inbox --since <время>`.
|
|
75
92
|
|
|
76
93
|
## Типичный путь
|
|
77
94
|
|
|
@@ -80,6 +97,9 @@ Id ниже выдуманные — подставить настоящие и
|
|
|
80
97
|
```sh
|
|
81
98
|
max chats list --search "проект" --json # найти чат, взять его id
|
|
82
99
|
max chats list --unread --json # где есть непрочитанное
|
|
100
|
+
max inbox --json # непрочитанное во всех чатах
|
|
101
|
+
max inbox --new --json # что пришло с прошлой проверки, один раз
|
|
102
|
+
max watch --jsonl # новые сообщения по мере прихода, если запущен `max serve`
|
|
83
103
|
max chats show -1000 --json # один чат и кто в нём
|
|
84
104
|
max contacts show @ivan --json # один человек и общие чаты
|
|
85
105
|
max messages list -1000 --limit 20 --json # последние сообщения, от старых к новым
|