gamealgo-cli 0.2.1 → 0.3.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 CHANGED
@@ -35,6 +35,22 @@ gamealgo docs api GameAlgo.Init --platform lua
35
35
 
36
36
  Help and documentation are fetched from the configured Server on every invocation. The CLI intentionally does not keep a documentation cache.
37
37
 
38
+ ## Agent skill
39
+
40
+ Install or update the bundled GameAlgo skill for the current agent:
41
+
42
+ ```bash
43
+ gamealgo skill install --agent codex
44
+ gamealgo skill install --agent claude
45
+ ```
46
+
47
+ The skill uses the project-bound CLI and live Server content. It can discover the complete iteration catalog without copied prompts:
48
+
49
+ ```bash
50
+ gamealgo optimize list --json
51
+ gamealgo optimize get ad-monetization --json
52
+ ```
53
+
38
54
  Adjust S2S event forwarding can be configured with an explicit event allowlist:
39
55
 
40
56
  ```bash
package/dist/client.js CHANGED
@@ -177,6 +177,12 @@ export class GameAlgoAdminClient {
177
177
  const params = new URLSearchParams({ environment, platform });
178
178
  return await this.get(`/admin/v1/games/${encodeURIComponent(await this.gameId())}/integration/plan?${params.toString()}`);
179
179
  }
180
+ async listOptimizationTasks() {
181
+ return await this.get(`/admin/v1/games/${encodeURIComponent(await this.gameId())}/optimization/tasks`);
182
+ }
183
+ async getOptimizationTask(taskId) {
184
+ return await this.get(`/admin/v1/games/${encodeURIComponent(await this.gameId())}/optimization/tasks/${encodeURIComponent(taskId)}`);
185
+ }
180
186
  async getAdjustMarketing(platform) {
181
187
  const query = platform ? `?platform=${encodeURIComponent(platform)}` : "";
182
188
  return await this.get(`/admin/v1/games/${encodeURIComponent(await this.gameId())}/marketing/adjust${query}`);
@@ -0,0 +1,35 @@
1
+ import YAML from "yaml";
2
+ import { parseFlags } from "../args.js";
3
+ import { printResult } from "../output.js";
4
+ import { writeTextFile } from "../resources.js";
5
+ export async function handleOptimize(client, args, global) {
6
+ const sub = args.shift();
7
+ const flags = parseFlags(args);
8
+ if (sub === "list") {
9
+ if (args.length)
10
+ throw new Error("usage: gamealgo optimize list [--out tasks.json]");
11
+ await writeOptimizationOutput(await client.listOptimizationTasks(), flags, global);
12
+ return;
13
+ }
14
+ if (sub === "get") {
15
+ const taskId = args.shift();
16
+ if (!taskId || args.length)
17
+ throw new Error("usage: gamealgo optimize get <task-id> [--out task.json]");
18
+ await writeOptimizationOutput(await client.getOptimizationTask(taskId), flags, global);
19
+ return;
20
+ }
21
+ throw new Error("usage: gamealgo optimize <list|get>");
22
+ }
23
+ async function writeOptimizationOutput(value, flags, global) {
24
+ if (flags.out) {
25
+ if (typeof flags.out !== "string")
26
+ throw new Error("--out requires a file path");
27
+ const content = flags.out.toLowerCase().endsWith(".json")
28
+ ? `${JSON.stringify(value, null, 2)}\n`
29
+ : YAML.stringify(value);
30
+ await writeTextFile(flags.out, content);
31
+ await printResult({ ok: true, out: flags.out }, global);
32
+ return;
33
+ }
34
+ await printResult(value, global);
35
+ }
@@ -0,0 +1,57 @@
1
+ import { cp, mkdir, stat } from "node:fs/promises";
2
+ import { homedir } from "node:os";
3
+ import { dirname, join, resolve } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { parseFlags } from "../args.js";
6
+ import { printResult } from "../output.js";
7
+ const SKILL_NAME = "gamealgo";
8
+ export async function handleSkill(args, global) {
9
+ const sub = args.shift();
10
+ const flags = parseFlags(args);
11
+ if (sub !== "install" || args.length) {
12
+ throw new Error("usage: gamealgo skill install --agent <codex|claude> [--dest <skill-directory>]");
13
+ }
14
+ const destination = skillDestination(flags);
15
+ const updated = await pathExists(destination);
16
+ await installBundledGameAlgoSkill(destination);
17
+ await printResult({
18
+ ok: true,
19
+ skill: SKILL_NAME,
20
+ destination,
21
+ action: updated ? "updated" : "installed",
22
+ note: "The skill is available to new agent turns. Restart the agent if it does not appear.",
23
+ }, global);
24
+ }
25
+ export async function installBundledGameAlgoSkill(destination) {
26
+ const source = bundledSkillDirectory();
27
+ await mkdir(dirname(destination), { recursive: true });
28
+ await cp(source, destination, { recursive: true, force: true });
29
+ }
30
+ export function skillDestination(flags) {
31
+ if (typeof flags.dest === "string")
32
+ return resolve(flags.dest);
33
+ if (flags.dest === true)
34
+ throw new Error("--dest requires a directory path");
35
+ const agent = typeof flags.agent === "string" ? flags.agent.toLowerCase() : "";
36
+ if (agent === "codex") {
37
+ return join(process.env.CODEX_HOME || join(homedir(), ".codex"), "skills", SKILL_NAME);
38
+ }
39
+ if (agent === "claude") {
40
+ return join(process.env.CLAUDE_CONFIG_DIR || join(homedir(), ".claude"), "skills", SKILL_NAME);
41
+ }
42
+ throw new Error("--agent must be codex or claude when --dest is not provided");
43
+ }
44
+ function bundledSkillDirectory() {
45
+ return resolve(dirname(fileURLToPath(import.meta.url)), "../../skills", SKILL_NAME);
46
+ }
47
+ async function pathExists(path) {
48
+ try {
49
+ await stat(path);
50
+ return true;
51
+ }
52
+ catch (error) {
53
+ if (error.code === "ENOENT")
54
+ return false;
55
+ throw error;
56
+ }
57
+ }
package/dist/main.js CHANGED
@@ -6,8 +6,10 @@ import { handleExperiment } from "./commands/experiment.js";
6
6
  import { handleIntegration } from "./commands/integration.js";
7
7
  import { handleGameKey } from "./commands/keys.js";
8
8
  import { handleMarketing } from "./commands/marketing.js";
9
+ import { handleOptimize } from "./commands/optimize.js";
9
10
  import { handleReport } from "./commands/report.js";
10
11
  import { handleFileResource } from "./commands/resources.js";
12
+ import { handleSkill } from "./commands/skill.js";
11
13
  import { loadPackageMetadata } from "./config.js";
12
14
  import { handleDocs, handleHelp } from "./docs.js";
13
15
  import { printResult } from "./output.js";
@@ -57,6 +59,10 @@ export async function main() {
57
59
  await handleAdminKey(args, global);
58
60
  return;
59
61
  }
62
+ if (command === "skill") {
63
+ await handleSkill(args, global);
64
+ return;
65
+ }
60
66
  const client = await createClient(global);
61
67
  if (command === "experiment") {
62
68
  await handleExperiment(client, args, global);
@@ -90,6 +96,10 @@ export async function main() {
90
96
  await handleMarketing(client, args, global);
91
97
  return;
92
98
  }
99
+ if (command === "optimize") {
100
+ await handleOptimize(client, args, global);
101
+ return;
102
+ }
93
103
  throw new Error(`Unknown command: ${command}`);
94
104
  }
95
105
  catch (error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gamealgo-cli",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "GameAlgo command-line client for AI agents and game developers",
5
5
  "repository": {
6
6
  "type": "git",
@@ -16,6 +16,7 @@
16
16
  },
17
17
  "files": [
18
18
  "dist/",
19
+ "skills/",
19
20
  "README.md",
20
21
  "LICENSE"
21
22
  ],
@@ -0,0 +1,50 @@
1
+ ---
2
+ name: gamealgo
3
+ description: Integrate and improve games with GameAlgo using the project-bound CLI, live Server documentation, and the Server-maintained optimization task catalog. Use when working on GameAlgo SDK setup, telemetry events, report packs, Adjust attribution, remote strategies, experiments, or when discovering supported GameAlgo iteration tasks for a game.
4
+ ---
5
+
6
+ # GameAlgo
7
+
8
+ Use the GameAlgo CLI as the source of current project identity and Server-maintained instructions. Do not rely on remembered SDK signatures, copied prompts, or stale local documentation.
9
+
10
+ ## Start In The Game Repository
11
+
12
+ Run commands from the game repository that owns the integration. Before any game-level operation:
13
+
14
+ 1. Run `gamealgo version`. If unavailable or rejected by the Server, install the version named by the CLI or Server error.
15
+ 2. Run `gamealgo whoami --json` and confirm the project-bound `gameId`. If the project is not logged in, ask the developer for that game's Game Admin Key and run the displayed login command from the repository root.
16
+ 3. Never put `ga_admin_*` credentials in client code, logs, generated reports, commits, or chat summaries.
17
+
18
+ ## Discover Supported Work
19
+
20
+ When the user asks what GameAlgo can do, asks for ongoing iteration, or names a broad optimization goal:
21
+
22
+ 1. Run `gamealgo optimize list --json` to load the complete current task catalog from the Server.
23
+ 2. Treat the result as an unranked capability catalog. Do not claim that a task is recommended or ready until its prerequisites have been checked against the current game.
24
+ 3. Once the user selects a task, or their request clearly identifies one, run `gamealgo optimize get <task-id> --json`.
25
+ 4. Read each topic named in the task's `docs` field with `gamealgo docs <topic>` before implementation.
26
+ 5. Follow the returned `agentSteps` and use `deliverables` as the completion checklist.
27
+
28
+ Do not run every catalog task in sequence. Complete the selected task and report unmet prerequisites instead of manufacturing missing data.
29
+
30
+ ## Integration Work
31
+
32
+ For SDK integration or telemetry changes, determine the actual deployment environment and runtime platform, then run:
33
+
34
+ ```bash
35
+ gamealgo integration get-plan --environment <domestic|overseas> --platform <ios|android|maker|rest> --json
36
+ ```
37
+
38
+ Inspect the existing project before editing. Reuse existing SDK wrappers, user identity, lifecycle, event, advertising, purchase, and attribution flows. Use `gamealgo docs api <function> --platform <platform>` for exact public APIs; do not invent methods or infer support from another platform.
39
+
40
+ Before adding events, run `gamealgo events list --days 30 --json`. Reuse events with the same business meaning, register new fields with their real JSON types, and verify non-debug context and business events with real runtime traffic.
41
+
42
+ ## Changes And Verification
43
+
44
+ - Make repository changes when the selected task requires them; keep unrelated files unchanged.
45
+ - Preserve local fallback behavior when adding remote configuration, scripts, or experiments.
46
+ - Validate Report Packs before preview or publication and compare results with real event counts.
47
+ - Show the relevant diff and impact before publishing reports, remote configuration, scripts, or experiments unless the user has already explicitly authorized that exact operation.
48
+ - Do not push directly to a protected primary branch. Follow the repository's branch and merge-request workflow.
49
+
50
+ Finish with the changed files, checks executed, observed data evidence, unmet prerequisites, and any operation still awaiting developer approval. Only call initial integration activated after real configuration and event acceptance checks pass.
@@ -0,0 +1,7 @@
1
+ interface:
2
+ display_name: "GameAlgo"
3
+ short_description: "接入 GameAlgo 并执行服务端维护的游戏优化任务"
4
+ default_prompt: "Use $gamealgo to inspect this game and load the current GameAlgo task catalog."
5
+
6
+ policy:
7
+ allow_implicit_invocation: true