@kokimoki/app 1.17.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.js +3 -0
- package/dist/core/kokimoki-client.d.ts +361 -0
- package/dist/core/kokimoki-client.js +819 -0
- package/dist/core/room-subscription-mode.d.ts +5 -0
- package/dist/core/room-subscription-mode.js +6 -0
- package/dist/core/room-subscription.d.ts +15 -0
- package/dist/core/room-subscription.js +53 -0
- package/dist/fields.d.ts +110 -0
- package/dist/fields.js +158 -0
- package/dist/index.d.ts +4 -8
- package/dist/index.js +4 -9
- package/dist/kokimoki-ai.d.ts +153 -0
- package/dist/kokimoki-ai.js +164 -0
- package/dist/kokimoki-awareness.d.ts +14 -13
- package/dist/kokimoki-awareness.js +41 -33
- package/dist/kokimoki-client-refactored.d.ts +80 -0
- package/dist/kokimoki-client-refactored.js +400 -0
- package/dist/kokimoki-client.d.ts +282 -76
- package/dist/kokimoki-client.js +295 -232
- package/dist/kokimoki-leaderboard.d.ts +175 -0
- package/dist/kokimoki-leaderboard.js +203 -0
- package/dist/kokimoki-schema.d.ts +113 -0
- package/dist/kokimoki-schema.js +162 -0
- package/dist/kokimoki-storage.d.ts +156 -0
- package/dist/kokimoki-storage.js +208 -0
- package/dist/kokimoki.min.d.ts +775 -110
- package/dist/kokimoki.min.js +4088 -2408
- package/dist/kokimoki.min.js.map +1 -1
- package/dist/llms.txt +657 -0
- package/dist/message-queue.d.ts +8 -0
- package/dist/message-queue.js +19 -0
- package/dist/protocol/ws-message/index.d.ts +3 -0
- package/dist/protocol/ws-message/index.js +3 -0
- package/dist/protocol/ws-message/reader.d.ts +11 -0
- package/dist/protocol/ws-message/reader.js +36 -0
- package/dist/protocol/ws-message/type.d.ts +11 -0
- package/dist/protocol/ws-message/type.js +12 -0
- package/dist/protocol/ws-message/writer.d.ts +9 -0
- package/dist/protocol/ws-message/writer.js +45 -0
- package/dist/services/index.d.ts +3 -0
- package/dist/services/index.js +3 -0
- package/dist/services/kokimoki-ai.d.ts +153 -0
- package/dist/services/kokimoki-ai.js +164 -0
- package/dist/services/kokimoki-leaderboard.d.ts +175 -0
- package/dist/services/kokimoki-leaderboard.js +203 -0
- package/dist/services/kokimoki-storage.d.ts +155 -0
- package/dist/services/kokimoki-storage.js +208 -0
- package/dist/stores/index.d.ts +3 -0
- package/dist/stores/index.js +3 -0
- package/dist/stores/kokimoki-local-store.d.ts +11 -0
- package/dist/stores/kokimoki-local-store.js +40 -0
- package/dist/stores/kokimoki-store.d.ts +22 -0
- package/dist/stores/kokimoki-store.js +117 -0
- package/dist/stores/kokimoki-transaction.d.ts +18 -0
- package/dist/stores/kokimoki-transaction.js +143 -0
- package/dist/synced-schema.d.ts +74 -0
- package/dist/synced-schema.js +83 -0
- package/dist/synced-store.d.ts +10 -0
- package/dist/synced-store.js +9 -0
- package/dist/synced-types.d.ts +47 -0
- package/dist/synced-types.js +67 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.js +3 -0
- package/dist/utils/valtio.d.ts +7 -0
- package/dist/utils/valtio.js +6 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +2 -1
- package/dist/ws-message-type copy.d.ts +6 -0
- package/dist/ws-message-type copy.js +7 -0
- package/package.json +4 -3
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export class WsMessageReader {
|
|
2
|
+
buffer;
|
|
3
|
+
_view;
|
|
4
|
+
_offset = 0;
|
|
5
|
+
constructor(buffer) {
|
|
6
|
+
this.buffer = buffer;
|
|
7
|
+
this._view = new DataView(buffer);
|
|
8
|
+
}
|
|
9
|
+
readInt32() {
|
|
10
|
+
const value = this._view.getInt32(this._offset, true);
|
|
11
|
+
this._offset += 4;
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
readUint32() {
|
|
15
|
+
const value = this._view.getUint32(this._offset, true);
|
|
16
|
+
this._offset += 4;
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
readString() {
|
|
20
|
+
const length = this.readInt32();
|
|
21
|
+
let value = "";
|
|
22
|
+
for (let i = 0; i < length; i++) {
|
|
23
|
+
value += String.fromCharCode(this._view.getUint8(this._offset++));
|
|
24
|
+
}
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
readUint8Array() {
|
|
28
|
+
const length = this.readInt32();
|
|
29
|
+
const value = new Uint8Array(this.buffer, this._offset, length);
|
|
30
|
+
this._offset += length;
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
get end() {
|
|
34
|
+
return this._offset === this.buffer.byteLength;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export var WsMessageType;
|
|
2
|
+
(function (WsMessageType) {
|
|
3
|
+
WsMessageType[WsMessageType["SubscribeReq"] = 1] = "SubscribeReq";
|
|
4
|
+
WsMessageType[WsMessageType["SubscribeRes"] = 2] = "SubscribeRes";
|
|
5
|
+
WsMessageType[WsMessageType["Transaction"] = 3] = "Transaction";
|
|
6
|
+
WsMessageType[WsMessageType["RoomUpdate"] = 4] = "RoomUpdate";
|
|
7
|
+
WsMessageType[WsMessageType["Error"] = 5] = "Error";
|
|
8
|
+
WsMessageType[WsMessageType["Ping"] = 6] = "Ping";
|
|
9
|
+
WsMessageType[WsMessageType["Pong"] = 7] = "Pong";
|
|
10
|
+
WsMessageType[WsMessageType["UnsubscribeReq"] = 8] = "UnsubscribeReq";
|
|
11
|
+
WsMessageType[WsMessageType["UnsubscribeRes"] = 9] = "UnsubscribeRes";
|
|
12
|
+
})(WsMessageType || (WsMessageType = {}));
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare class WsMessageWriter {
|
|
2
|
+
private _parts;
|
|
3
|
+
writeInt32(value: number): void;
|
|
4
|
+
writeUint32(value: number): void;
|
|
5
|
+
writeString(value: string): void;
|
|
6
|
+
writeChar(value: string): void;
|
|
7
|
+
writeUint8Array(value: Uint8Array): void;
|
|
8
|
+
getBuffer(): ArrayBuffer;
|
|
9
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export class WsMessageWriter {
|
|
2
|
+
_parts = [];
|
|
3
|
+
writeInt32(value) {
|
|
4
|
+
const buffer = new Uint8Array(4);
|
|
5
|
+
const view = new DataView(buffer.buffer);
|
|
6
|
+
view.setInt32(0, value, true);
|
|
7
|
+
this._parts.push(buffer);
|
|
8
|
+
}
|
|
9
|
+
writeUint32(value) {
|
|
10
|
+
const buffer = new Uint8Array(4);
|
|
11
|
+
const view = new DataView(buffer.buffer);
|
|
12
|
+
view.setUint32(0, value, true);
|
|
13
|
+
this._parts.push(buffer);
|
|
14
|
+
}
|
|
15
|
+
writeString(value) {
|
|
16
|
+
// Write length
|
|
17
|
+
this.writeInt32(value.length);
|
|
18
|
+
// Write chars
|
|
19
|
+
const buffer = new Uint8Array(value.length);
|
|
20
|
+
for (let i = 0; i < value.length; i++) {
|
|
21
|
+
buffer[i] = value.charCodeAt(i);
|
|
22
|
+
}
|
|
23
|
+
this._parts.push(buffer);
|
|
24
|
+
}
|
|
25
|
+
writeChar(value) {
|
|
26
|
+
const buffer = new Uint8Array(1);
|
|
27
|
+
buffer[0] = value.charCodeAt(0);
|
|
28
|
+
this._parts.push(buffer);
|
|
29
|
+
}
|
|
30
|
+
writeUint8Array(value) {
|
|
31
|
+
this.writeInt32(value.byteLength);
|
|
32
|
+
this._parts.push(value);
|
|
33
|
+
}
|
|
34
|
+
getBuffer() {
|
|
35
|
+
const size = this._parts.reduce((acc, part) => acc + part.byteLength, 0);
|
|
36
|
+
const buffer = new ArrayBuffer(size);
|
|
37
|
+
let offset = 0;
|
|
38
|
+
for (const part of this._parts) {
|
|
39
|
+
const view = new Uint8Array(buffer, offset);
|
|
40
|
+
view.set(part);
|
|
41
|
+
offset += part.byteLength;
|
|
42
|
+
}
|
|
43
|
+
return buffer;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { KokimokiClient } from "../core";
|
|
2
|
+
import type { Upload } from "../types";
|
|
3
|
+
/**
|
|
4
|
+
* Kokimoki AI Integration Service
|
|
5
|
+
*
|
|
6
|
+
* Provides built-in AI capabilities for game applications without requiring API keys or setup.
|
|
7
|
+
* Includes text generation, structured JSON output, and image modification.
|
|
8
|
+
*
|
|
9
|
+
* **Key Features:**
|
|
10
|
+
* - Multiple AI models (GPT-4, GPT-5, Gemini variants)
|
|
11
|
+
* - Text generation with configurable creativity (temperature)
|
|
12
|
+
* - Structured JSON output for game data
|
|
13
|
+
* - AI-powered image modifications
|
|
14
|
+
* - No API keys or configuration required
|
|
15
|
+
*
|
|
16
|
+
* **Common Use Cases:**
|
|
17
|
+
* - Generate dynamic game content (quests, dialogues, stories)
|
|
18
|
+
* - Create AI opponents or NPCs with personalities
|
|
19
|
+
* - Generate quiz questions or trivia
|
|
20
|
+
* - Create game assets (character stats, item descriptions)
|
|
21
|
+
* - Transform user-uploaded images
|
|
22
|
+
* - Generate procedural content
|
|
23
|
+
*
|
|
24
|
+
* Access via `kmClient.ai`
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* // Generate story text
|
|
29
|
+
* const story = await kmClient.ai.chat({
|
|
30
|
+
* systemPrompt: 'You are a fantasy story writer',
|
|
31
|
+
* userPrompt: 'Write a short quest description',
|
|
32
|
+
* temperature: 0.8
|
|
33
|
+
* });
|
|
34
|
+
*
|
|
35
|
+
* // Generate structured game data
|
|
36
|
+
* interface Enemy {
|
|
37
|
+
* name: string;
|
|
38
|
+
* health: number;
|
|
39
|
+
* attack: number;
|
|
40
|
+
* }
|
|
41
|
+
* const enemy = await kmClient.ai.generateJson<Enemy>({
|
|
42
|
+
* userPrompt: 'Create a level 5 goblin warrior'
|
|
43
|
+
* });
|
|
44
|
+
*
|
|
45
|
+
* // Transform image
|
|
46
|
+
* const modified = await kmClient.ai.modifyImage(
|
|
47
|
+
* imageUrl,
|
|
48
|
+
* 'Make it look like pixel art'
|
|
49
|
+
* );
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare class KokimokiAiService {
|
|
53
|
+
private readonly client;
|
|
54
|
+
constructor(client: KokimokiClient);
|
|
55
|
+
/**
|
|
56
|
+
* Generate a chat response from the AI model.
|
|
57
|
+
*
|
|
58
|
+
* Sends a chat request to the AI service and returns the generated response.
|
|
59
|
+
* Supports multiple AI models including GPT and Gemini variants with configurable
|
|
60
|
+
* parameters for fine-tuning the response behavior.
|
|
61
|
+
*
|
|
62
|
+
* @param req The chat request parameters.
|
|
63
|
+
* @param req.model Optional. The AI model to use. Defaults to server-side default if not specified.
|
|
64
|
+
* Available models:
|
|
65
|
+
* - `gpt-4o`: OpenAI GPT-4 Optimized
|
|
66
|
+
* - `gpt-4o-mini`: Smaller, faster GPT-4 variant
|
|
67
|
+
* - `gpt-5`: OpenAI GPT-5 (latest)
|
|
68
|
+
* - `gpt-5-mini`: Smaller GPT-5 variant
|
|
69
|
+
* - `gpt-5-nano`: Smallest GPT-5 variant for lightweight tasks
|
|
70
|
+
* - `gemini-2.5-flash-lite`: Google Gemini lite variant
|
|
71
|
+
* - `gemini-2.5-flash`: Google Gemini fast variant
|
|
72
|
+
* @param req.systemPrompt Optional. The system message that sets the behavior and context for the AI.
|
|
73
|
+
* This helps define the AI's role, personality, and constraints.
|
|
74
|
+
* @param req.userPrompt The user's message or question to send to the AI.
|
|
75
|
+
* @param req.temperature Optional. Controls randomness in the response (0.0 to 1.0).
|
|
76
|
+
* Lower values make output more focused and deterministic,
|
|
77
|
+
* higher values make it more creative and varied.
|
|
78
|
+
* @param req.maxTokens Optional. The maximum number of tokens to generate in the response.
|
|
79
|
+
* Controls the length of the AI's output.
|
|
80
|
+
*
|
|
81
|
+
* @returns A promise that resolves to an object containing the AI-generated response.
|
|
82
|
+
* @returns {string} content The text content of the AI's response.
|
|
83
|
+
*
|
|
84
|
+
* @throws An error object if the API request fails.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const response = await client.ai.chat({
|
|
89
|
+
* model: "gpt-4o",
|
|
90
|
+
* systemPrompt: "You are a helpful coding assistant.",
|
|
91
|
+
* userPrompt: "Explain what TypeScript is in one sentence.",
|
|
92
|
+
* temperature: 0.7,
|
|
93
|
+
* maxTokens: 100
|
|
94
|
+
* });
|
|
95
|
+
* console.log(response.content);
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
chat(req: {
|
|
99
|
+
model?: "gpt-4o" | "gpt-4o-mini" | "gpt-5" | "gpt-5-mini" | "gpt-5-nano" | "gemini-2.5-flash-lite" | "gemini-2.5-flash";
|
|
100
|
+
systemPrompt?: string;
|
|
101
|
+
userPrompt: string;
|
|
102
|
+
temperature?: number;
|
|
103
|
+
maxTokens?: number;
|
|
104
|
+
responseMimeType?: string;
|
|
105
|
+
}): Promise<{
|
|
106
|
+
content: string;
|
|
107
|
+
}>;
|
|
108
|
+
/**
|
|
109
|
+
* Generate structured JSON output from the AI model.
|
|
110
|
+
*
|
|
111
|
+
* Sends a chat request to the AI service with the expectation of receiving
|
|
112
|
+
* a JSON-formatted response. This is useful for scenarios where the output
|
|
113
|
+
* needs to be parsed or processed programmatically.
|
|
114
|
+
*
|
|
115
|
+
* @param req The chat request parameters.
|
|
116
|
+
* @param req.model Optional. The AI model to use. Defaults to server-side default if not specified.
|
|
117
|
+
* Available models:
|
|
118
|
+
* - `gpt-4o`: OpenAI GPT-4 Optimized
|
|
119
|
+
* - `gpt-4o-mini`: Smaller, faster GPT-4 variant
|
|
120
|
+
* - `gpt-5`: OpenAI GPT-5 (latest)
|
|
121
|
+
* - `gpt-5-mini`: Smaller GPT-5 variant
|
|
122
|
+
* - `gpt-5-nano`: Smallest GPT-5 variant for lightweight tasks
|
|
123
|
+
* - `gemini-2.5-flash-lite`: Google Gemini lite variant
|
|
124
|
+
* - `gemini-2.5-flash`: Google Gemini fast variant
|
|
125
|
+
* @param req.systemPrompt Optional. The system message that sets the behavior and context for the AI.
|
|
126
|
+
* This helps define the AI's role, personality, and constraints.
|
|
127
|
+
* @param req.userPrompt The user's message or question to send to the AI.
|
|
128
|
+
* @param req.temperature Optional. Controls randomness in the response (0.0 to 1.0).
|
|
129
|
+
* Lower values make output more focused and deterministic,
|
|
130
|
+
* higher values make it more creative and varied.
|
|
131
|
+
* @param req.maxTokens Optional. The maximum number of tokens to generate in the response.
|
|
132
|
+
* Controls the length of the AI's output.
|
|
133
|
+
*
|
|
134
|
+
* @returns A promise that resolves to the parsed JSON object generated by the AI.
|
|
135
|
+
*
|
|
136
|
+
* @throws An error object if the API request fails or if the response is not valid JSON.
|
|
137
|
+
*/
|
|
138
|
+
generateJson<T extends object>(req: {
|
|
139
|
+
model?: "gpt-4o" | "gpt-4o-mini" | "gpt-5" | "gpt-5-mini" | "gpt-5-nano" | "gemini-2.5-flash-lite" | "gemini-2.5-flash";
|
|
140
|
+
systemPrompt?: string;
|
|
141
|
+
userPrompt: string;
|
|
142
|
+
temperature?: number;
|
|
143
|
+
maxTokens?: number;
|
|
144
|
+
}): Promise<T>;
|
|
145
|
+
/**
|
|
146
|
+
* Modify an image using the AI service.
|
|
147
|
+
* @param baseImageUrl The URL of the base image to modify.
|
|
148
|
+
* @param prompt The modification prompt to apply to the image.
|
|
149
|
+
* @param tags Optional. Tags to associate with the image.
|
|
150
|
+
* @returns A promise that resolves to the modified image upload information.
|
|
151
|
+
*/
|
|
152
|
+
modifyImage(baseImageUrl: string, prompt: string, tags?: string[]): Promise<Upload>;
|
|
153
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kokimoki AI Integration Service
|
|
3
|
+
*
|
|
4
|
+
* Provides built-in AI capabilities for game applications without requiring API keys or setup.
|
|
5
|
+
* Includes text generation, structured JSON output, and image modification.
|
|
6
|
+
*
|
|
7
|
+
* **Key Features:**
|
|
8
|
+
* - Multiple AI models (GPT-4, GPT-5, Gemini variants)
|
|
9
|
+
* - Text generation with configurable creativity (temperature)
|
|
10
|
+
* - Structured JSON output for game data
|
|
11
|
+
* - AI-powered image modifications
|
|
12
|
+
* - No API keys or configuration required
|
|
13
|
+
*
|
|
14
|
+
* **Common Use Cases:**
|
|
15
|
+
* - Generate dynamic game content (quests, dialogues, stories)
|
|
16
|
+
* - Create AI opponents or NPCs with personalities
|
|
17
|
+
* - Generate quiz questions or trivia
|
|
18
|
+
* - Create game assets (character stats, item descriptions)
|
|
19
|
+
* - Transform user-uploaded images
|
|
20
|
+
* - Generate procedural content
|
|
21
|
+
*
|
|
22
|
+
* Access via `kmClient.ai`
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* // Generate story text
|
|
27
|
+
* const story = await kmClient.ai.chat({
|
|
28
|
+
* systemPrompt: 'You are a fantasy story writer',
|
|
29
|
+
* userPrompt: 'Write a short quest description',
|
|
30
|
+
* temperature: 0.8
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* // Generate structured game data
|
|
34
|
+
* interface Enemy {
|
|
35
|
+
* name: string;
|
|
36
|
+
* health: number;
|
|
37
|
+
* attack: number;
|
|
38
|
+
* }
|
|
39
|
+
* const enemy = await kmClient.ai.generateJson<Enemy>({
|
|
40
|
+
* userPrompt: 'Create a level 5 goblin warrior'
|
|
41
|
+
* });
|
|
42
|
+
*
|
|
43
|
+
* // Transform image
|
|
44
|
+
* const modified = await kmClient.ai.modifyImage(
|
|
45
|
+
* imageUrl,
|
|
46
|
+
* 'Make it look like pixel art'
|
|
47
|
+
* );
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export class KokimokiAiService {
|
|
51
|
+
client;
|
|
52
|
+
constructor(client) {
|
|
53
|
+
this.client = client;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Generate a chat response from the AI model.
|
|
57
|
+
*
|
|
58
|
+
* Sends a chat request to the AI service and returns the generated response.
|
|
59
|
+
* Supports multiple AI models including GPT and Gemini variants with configurable
|
|
60
|
+
* parameters for fine-tuning the response behavior.
|
|
61
|
+
*
|
|
62
|
+
* @param req The chat request parameters.
|
|
63
|
+
* @param req.model Optional. The AI model to use. Defaults to server-side default if not specified.
|
|
64
|
+
* Available models:
|
|
65
|
+
* - `gpt-4o`: OpenAI GPT-4 Optimized
|
|
66
|
+
* - `gpt-4o-mini`: Smaller, faster GPT-4 variant
|
|
67
|
+
* - `gpt-5`: OpenAI GPT-5 (latest)
|
|
68
|
+
* - `gpt-5-mini`: Smaller GPT-5 variant
|
|
69
|
+
* - `gpt-5-nano`: Smallest GPT-5 variant for lightweight tasks
|
|
70
|
+
* - `gemini-2.5-flash-lite`: Google Gemini lite variant
|
|
71
|
+
* - `gemini-2.5-flash`: Google Gemini fast variant
|
|
72
|
+
* @param req.systemPrompt Optional. The system message that sets the behavior and context for the AI.
|
|
73
|
+
* This helps define the AI's role, personality, and constraints.
|
|
74
|
+
* @param req.userPrompt The user's message or question to send to the AI.
|
|
75
|
+
* @param req.temperature Optional. Controls randomness in the response (0.0 to 1.0).
|
|
76
|
+
* Lower values make output more focused and deterministic,
|
|
77
|
+
* higher values make it more creative and varied.
|
|
78
|
+
* @param req.maxTokens Optional. The maximum number of tokens to generate in the response.
|
|
79
|
+
* Controls the length of the AI's output.
|
|
80
|
+
*
|
|
81
|
+
* @returns A promise that resolves to an object containing the AI-generated response.
|
|
82
|
+
* @returns {string} content The text content of the AI's response.
|
|
83
|
+
*
|
|
84
|
+
* @throws An error object if the API request fails.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const response = await client.ai.chat({
|
|
89
|
+
* model: "gpt-4o",
|
|
90
|
+
* systemPrompt: "You are a helpful coding assistant.",
|
|
91
|
+
* userPrompt: "Explain what TypeScript is in one sentence.",
|
|
92
|
+
* temperature: 0.7,
|
|
93
|
+
* maxTokens: 100
|
|
94
|
+
* });
|
|
95
|
+
* console.log(response.content);
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
async chat(req) {
|
|
99
|
+
const res = await fetch(`${this.client.apiUrl}/ai/chat`, {
|
|
100
|
+
method: "POST",
|
|
101
|
+
headers: this.client.apiHeaders,
|
|
102
|
+
body: JSON.stringify(req),
|
|
103
|
+
});
|
|
104
|
+
if (!res.ok) {
|
|
105
|
+
throw await res.json();
|
|
106
|
+
}
|
|
107
|
+
return await res.json();
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Generate structured JSON output from the AI model.
|
|
111
|
+
*
|
|
112
|
+
* Sends a chat request to the AI service with the expectation of receiving
|
|
113
|
+
* a JSON-formatted response. This is useful for scenarios where the output
|
|
114
|
+
* needs to be parsed or processed programmatically.
|
|
115
|
+
*
|
|
116
|
+
* @param req The chat request parameters.
|
|
117
|
+
* @param req.model Optional. The AI model to use. Defaults to server-side default if not specified.
|
|
118
|
+
* Available models:
|
|
119
|
+
* - `gpt-4o`: OpenAI GPT-4 Optimized
|
|
120
|
+
* - `gpt-4o-mini`: Smaller, faster GPT-4 variant
|
|
121
|
+
* - `gpt-5`: OpenAI GPT-5 (latest)
|
|
122
|
+
* - `gpt-5-mini`: Smaller GPT-5 variant
|
|
123
|
+
* - `gpt-5-nano`: Smallest GPT-5 variant for lightweight tasks
|
|
124
|
+
* - `gemini-2.5-flash-lite`: Google Gemini lite variant
|
|
125
|
+
* - `gemini-2.5-flash`: Google Gemini fast variant
|
|
126
|
+
* @param req.systemPrompt Optional. The system message that sets the behavior and context for the AI.
|
|
127
|
+
* This helps define the AI's role, personality, and constraints.
|
|
128
|
+
* @param req.userPrompt The user's message or question to send to the AI.
|
|
129
|
+
* @param req.temperature Optional. Controls randomness in the response (0.0 to 1.0).
|
|
130
|
+
* Lower values make output more focused and deterministic,
|
|
131
|
+
* higher values make it more creative and varied.
|
|
132
|
+
* @param req.maxTokens Optional. The maximum number of tokens to generate in the response.
|
|
133
|
+
* Controls the length of the AI's output.
|
|
134
|
+
*
|
|
135
|
+
* @returns A promise that resolves to the parsed JSON object generated by the AI.
|
|
136
|
+
*
|
|
137
|
+
* @throws An error object if the API request fails or if the response is not valid JSON.
|
|
138
|
+
*/
|
|
139
|
+
async generateJson(req) {
|
|
140
|
+
const { content } = await this.chat({
|
|
141
|
+
...req,
|
|
142
|
+
responseMimeType: "application/json",
|
|
143
|
+
});
|
|
144
|
+
return JSON.parse(content);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Modify an image using the AI service.
|
|
148
|
+
* @param baseImageUrl The URL of the base image to modify.
|
|
149
|
+
* @param prompt The modification prompt to apply to the image.
|
|
150
|
+
* @param tags Optional. Tags to associate with the image.
|
|
151
|
+
* @returns A promise that resolves to the modified image upload information.
|
|
152
|
+
*/
|
|
153
|
+
async modifyImage(baseImageUrl, prompt, tags = []) {
|
|
154
|
+
const res = await fetch(`${this.client.apiUrl}/ai/modify-image`, {
|
|
155
|
+
method: "POST",
|
|
156
|
+
headers: this.client.apiHeaders,
|
|
157
|
+
body: JSON.stringify({ baseImageUrl, prompt, tags }),
|
|
158
|
+
});
|
|
159
|
+
if (!res.ok) {
|
|
160
|
+
throw await res.json();
|
|
161
|
+
}
|
|
162
|
+
return await res.json();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { KokimokiClient } from "../core";
|
|
2
|
+
import type { Paginated } from "../types";
|
|
3
|
+
/**
|
|
4
|
+
* Kokimoki Leaderboard Service
|
|
5
|
+
*
|
|
6
|
+
* Provides efficient player ranking and score tracking with database indexes and optimized queries.
|
|
7
|
+
* Ideal for games with large numbers of players and competitive scoring.
|
|
8
|
+
*
|
|
9
|
+
* **Key Features:**
|
|
10
|
+
* - Efficient ranking with database indexes
|
|
11
|
+
* - Support for ascending (lowest-is-best) and descending (highest-is-best) sorting
|
|
12
|
+
* - Pagination for large leaderboards
|
|
13
|
+
* - Public and private metadata for entries
|
|
14
|
+
* - Insert (preserve all attempts) or upsert (keep latest only) modes
|
|
15
|
+
*
|
|
16
|
+
* **When to use Leaderboard API vs Global Store:**
|
|
17
|
+
*
|
|
18
|
+
* Use the **Leaderboard API** when:
|
|
19
|
+
* - You have a large number of entries (hundreds to thousands of players)
|
|
20
|
+
* - You need efficient ranking and sorting with database indexes
|
|
21
|
+
* - You want pagination and optimized queries for top scores
|
|
22
|
+
* - Memory and network efficiency are important
|
|
23
|
+
*
|
|
24
|
+
* Use a **Global Store** when:
|
|
25
|
+
* - You have a small number of players (typically under 100)
|
|
26
|
+
* - You need real-time updates and live leaderboard changes
|
|
27
|
+
* - You want to combine player scores with other game state
|
|
28
|
+
* - The leaderboard is temporary (session-based or reset frequently)
|
|
29
|
+
*
|
|
30
|
+
* Access via `kmClient.leaderboard`
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* // Submit a high score
|
|
35
|
+
* const { rank } = await kmClient.leaderboard.upsertEntry(
|
|
36
|
+
* 'high-scores',
|
|
37
|
+
* 'desc',
|
|
38
|
+
* 1500,
|
|
39
|
+
* { playerName: 'Alice' },
|
|
40
|
+
* {}
|
|
41
|
+
* );
|
|
42
|
+
*
|
|
43
|
+
* // Get top 10
|
|
44
|
+
* const { items } = await kmClient.leaderboard.listEntries('high-scores', 'desc', 0, 10);
|
|
45
|
+
*
|
|
46
|
+
* // Get player's best
|
|
47
|
+
* const best = await kmClient.leaderboard.getBestEntry('high-scores', 'desc');
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare class KokimokiLeaderboardService {
|
|
51
|
+
private readonly client;
|
|
52
|
+
constructor(client: KokimokiClient);
|
|
53
|
+
/**
|
|
54
|
+
* Add a new entry to a leaderboard.
|
|
55
|
+
*
|
|
56
|
+
* Creates a new entry each time it's called, preserving all attempts. Use this when you want
|
|
57
|
+
* to track every score submission (e.g., all game attempts).
|
|
58
|
+
*
|
|
59
|
+
* @param leaderboardName The name of the leaderboard to add the entry to
|
|
60
|
+
* @param sortDir Sort direction: "asc" for lowest-is-best (e.g., completion time),
|
|
61
|
+
* "desc" for highest-is-best (e.g., points)
|
|
62
|
+
* @param score The numeric score value
|
|
63
|
+
* @param metadata Public metadata visible to all players (e.g., player name, level)
|
|
64
|
+
* @param privateMetadata Private metadata only accessible via API calls (e.g., session ID)
|
|
65
|
+
* @returns A promise resolving to an object with the entry's rank
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* const { rank } = await kmClient.leaderboard.insertEntry(
|
|
70
|
+
* 'high-scores',
|
|
71
|
+
* 'desc',
|
|
72
|
+
* 1500,
|
|
73
|
+
* { playerName: 'Alice', level: 10 },
|
|
74
|
+
* { sessionId: 'abc123' }
|
|
75
|
+
* );
|
|
76
|
+
* console.log(`New rank: ${rank}`);
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
insertEntry<MetadataT, PrivateMetadataT>(leaderboardName: string, sortDir: "asc" | "desc", score: number, metadata: MetadataT, privateMetadata: PrivateMetadataT): Promise<{
|
|
80
|
+
rank: number;
|
|
81
|
+
}>;
|
|
82
|
+
/**
|
|
83
|
+
* Add or update the latest entry for the current client in a leaderboard.
|
|
84
|
+
*
|
|
85
|
+
* Replaces the previous entry if one exists for this client. Use this when you only want
|
|
86
|
+
* to keep the latest or best score per player (e.g., daily high score).
|
|
87
|
+
*
|
|
88
|
+
* @param leaderboardName The name of the leaderboard to upsert the entry in
|
|
89
|
+
* @param sortDir Sort direction: "asc" for lowest-is-best (e.g., completion time),
|
|
90
|
+
* "desc" for highest-is-best (e.g., points)
|
|
91
|
+
* @param score The numeric score value
|
|
92
|
+
* @param metadata Public metadata visible to all players (e.g., player name, completion time)
|
|
93
|
+
* @param privateMetadata Private metadata only accessible via API calls (e.g., device ID)
|
|
94
|
+
* @returns A promise resolving to an object with the entry's updated rank
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const { rank } = await kmClient.leaderboard.upsertEntry(
|
|
99
|
+
* 'daily-scores',
|
|
100
|
+
* 'desc',
|
|
101
|
+
* 2000,
|
|
102
|
+
* { playerName: 'Bob', completionTime: 120 },
|
|
103
|
+
* { deviceId: 'xyz789' }
|
|
104
|
+
* );
|
|
105
|
+
* console.log(`Updated rank: ${rank}`);
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
upsertEntry<MetadataT, PrivateMetadataT>(leaderboardName: string, sortDir: "asc" | "desc", score: number, metadata: MetadataT, privateMetadata: PrivateMetadataT): Promise<{
|
|
109
|
+
rank: number;
|
|
110
|
+
}>;
|
|
111
|
+
/**
|
|
112
|
+
* List entries in a leaderboard with pagination.
|
|
113
|
+
*
|
|
114
|
+
* Retrieves a sorted list of leaderboard entries. Use skip and limit parameters for
|
|
115
|
+
* pagination (e.g., showing top 10, or implementing "load more" functionality).
|
|
116
|
+
*
|
|
117
|
+
* @param leaderboardName The name of the leaderboard to query
|
|
118
|
+
* @param sortDir Sort direction: "asc" for lowest-is-best (e.g., completion time),
|
|
119
|
+
* "desc" for highest-is-best (e.g., points)
|
|
120
|
+
* @param skip Number of entries to skip for pagination (default: 0)
|
|
121
|
+
* @param limit Maximum number of entries to return (default: 100)
|
|
122
|
+
* @returns A promise resolving to a paginated list of entries with rank, score, and metadata
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* // Get top 10 scores
|
|
127
|
+
* const { items, total } = await kmClient.leaderboard.listEntries(
|
|
128
|
+
* 'weekly-scores',
|
|
129
|
+
* 'desc',
|
|
130
|
+
* 0,
|
|
131
|
+
* 10
|
|
132
|
+
* );
|
|
133
|
+
*
|
|
134
|
+
* items.forEach(entry => {
|
|
135
|
+
* console.log(`Rank ${entry.rank}: ${entry.metadata.playerName} - ${entry.score}`);
|
|
136
|
+
* });
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
listEntries<MetadataT>(leaderboardName: string, sortDir: "asc" | "desc", skip?: number, limit?: number): Promise<Paginated<{
|
|
140
|
+
rank: number;
|
|
141
|
+
score: number;
|
|
142
|
+
metadata: MetadataT;
|
|
143
|
+
}>>;
|
|
144
|
+
/**
|
|
145
|
+
* Get the best entry for a specific client in a leaderboard.
|
|
146
|
+
*
|
|
147
|
+
* Retrieves the highest-ranked entry for a client based on the sort direction.
|
|
148
|
+
* Defaults to the current client if no clientId is provided.
|
|
149
|
+
*
|
|
150
|
+
* @param leaderboardName The name of the leaderboard to query
|
|
151
|
+
* @param sortDir Sort direction: "asc" for lowest-is-best (e.g., completion time),
|
|
152
|
+
* "desc" for highest-is-best (e.g., points)
|
|
153
|
+
* @param clientId The client ID to get the best entry for (optional, defaults to current client)
|
|
154
|
+
* @returns A promise resolving to the best entry with rank, score, and metadata
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* ```typescript
|
|
158
|
+
* // Get current client's best entry
|
|
159
|
+
* const myBest = await kmClient.leaderboard.getBestEntry('all-time-high', 'desc');
|
|
160
|
+
* console.log(`My best: Rank ${myBest.rank}, Score ${myBest.score}`);
|
|
161
|
+
*
|
|
162
|
+
* // Get another player's best entry
|
|
163
|
+
* const otherBest = await kmClient.leaderboard.getBestEntry(
|
|
164
|
+
* 'all-time-high',
|
|
165
|
+
* 'desc',
|
|
166
|
+
* 'other-client-id'
|
|
167
|
+
* );
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
getBestEntry<MetadataT>(leaderboardName: string, sortDir: "asc" | "desc", clientId?: string): Promise<{
|
|
171
|
+
rank: number;
|
|
172
|
+
score: number;
|
|
173
|
+
metadata: MetadataT;
|
|
174
|
+
}>;
|
|
175
|
+
}
|