gamealgo-cli 0.2.1 → 0.3.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/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.1",
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,71 @@
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
+ ## Route Work To Required Documentation
31
+
32
+ Classify the requested work by the actions it requires, not only by the user's task title. Before implementation or interpreting results, load every applicable source below from the current Server:
33
+
34
+ - SDK installation, identity, lifecycle, telemetry, attribution, advertising, or purchase work: run `gamealgo integration get-plan --environment <domestic|overseas> --platform <ios|android|maker|rest> --json`, then read `gamealgo docs sdk-integration`.
35
+ - Calling or changing a concrete public SDK function: additionally run `gamealgo docs api <function> --platform <platform>` for each affected function. Never infer one platform's API from another.
36
+ - Adding or changing events: additionally run `gamealgo events list --days 30 --json` before defining fields or names.
37
+ - Reading, creating, changing, previewing, or publishing Report Packs, charts, report SQL, or business metrics: read `gamealgo docs reports` before interpreting data or editing definitions.
38
+ - Creating or changing remote configuration, strategies, experiments, variants, objectives, rollout, or assessment: read `gamealgo docs experiments`; also load the integration plan and exact API documentation when client code changes.
39
+ - Adjust or marketing attribution work: load the selected optimization task when one applies, read every topic in its `docs`, and load the integration plan and exact identifier/attribution APIs for the target platform.
40
+
41
+ If work crosses domains, combine their requirements. For example, an advertising event used by an experiment report requires the integration plan, event inventory, SDK API documentation, report documentation, and experiment documentation. Read a topic once per turn unless the task expands or the Server documentation version changes.
42
+
43
+ ## Follow Mandatory Checkpoints
44
+
45
+ 1. Confirm project identity, environment, platform, requested outcome, and available permissions.
46
+ 2. Load the required live documents and task detail before making implementation decisions.
47
+ 3. Inspect existing code, configuration, event inventory, Report Pack, or experiment state before editing. Reuse established project patterns and preserve local fallback behavior.
48
+ 4. Make the smallest coherent change and run local validation, Report Pack validation, previews, or dry runs supported by the current workflow.
49
+ 5. Before publishing reports, remote configuration, scripts, strategies, experiments, rollout changes, or other externally visible mutations, show the relevant diff and impact unless the user has already explicitly authorized that exact operation.
50
+ 6. After execution, verify with real configuration retrieval, accepted non-debug events, report results, or experiment state as appropriate. A code diff or successful request alone is not business verification.
51
+
52
+ Reading documentation does not grant permission to mutate production. CLI and Server validation, scopes, project binding, and explicit approval requirements still apply.
53
+
54
+ ## Integration Details
55
+
56
+ For SDK integration or telemetry changes, determine the actual deployment environment and runtime platform, then run:
57
+
58
+ ```bash
59
+ gamealgo integration get-plan --environment <domestic|overseas> --platform <ios|android|maker|rest> --json
60
+ ```
61
+
62
+ Inspect the existing project before editing. Reuse existing SDK wrappers, user identity, lifecycle, event, advertising, purchase, and attribution flows.
63
+
64
+ 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.
65
+
66
+ ## Changes And Verification
67
+
68
+ - Make repository changes when the selected task requires them; keep unrelated files unchanged.
69
+ - Do not push directly to a protected primary branch. Follow the repository's branch and merge-request workflow.
70
+
71
+ Finish with the live documentation and task detail consulted, 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