@agent-os-lab/agent-game-sdk 0.1.6 → 0.1.8

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
@@ -14,7 +14,6 @@ import { mountAgentGameOffice } from "@agent-os-lab/agent-game-sdk/office";
14
14
 
15
15
  const client = new AgentGameRuntimeBrowserClient({
16
16
  baseUrl: "",
17
- tokenPath: "/api/agent-game-runtime-token",
18
17
  accessToken: async () => getScopedToken(),
19
18
  });
20
19
 
@@ -94,7 +93,9 @@ Built-in room types are `office`, `auditorium`, and `gym`. `capacity` is optiona
94
93
 
95
94
  Runtime statuses stay unchanged. The SDK locally distributes `idle` and `resting` agents across ambient areas such as lounge, pantry, gym, and reading/bookcase anchors so inactive agents do not all gather at the sofa.
96
95
 
97
- Browser clients should call an application BFF endpoint. Keep the AgentOS service API key on the server; the SDK server client forwards it to Agent Game Runtime:
96
+ Browser clients should call an application BFF endpoint. By default the browser client requests `/api/agent-game-runtime-token` on the same origin. Configure `tokenPath` only if your application exposes that BFF route at a different path.
97
+
98
+ Keep the AgentOS service API key on the server; the SDK server client forwards it to Agent Game Runtime. The runtime token endpoint path is SDK-managed and defaults to Agent Game Runtime's `/api/v1/game-runtime-token`, so application code only needs `baseUrl` and `apiKey`:
98
99
 
99
100
  ```ts
100
101
  import { AgentGameRuntimeServerClient } from "@agent-os-lab/agent-game-sdk";
package/USAGE.md CHANGED
@@ -73,16 +73,16 @@ import { AgentGameRuntimeBrowserClient } from "@agent-os-lab/agent-game-sdk";
73
73
 
74
74
  const browserClient = new AgentGameRuntimeBrowserClient({
75
75
  baseUrl: "",
76
- tokenPath: "/api/agent-game-runtime-token",
77
76
  });
78
77
  ```
79
78
 
79
+ The default browser token path is `/api/agent-game-runtime-token`. Configure `tokenPath` only when your application exposes its BFF/proxy endpoint at a different same-origin path. This browser path is not the Agent Game Runtime service path.
80
+
80
81
  If your application backend expects an application-scoped browser token, provide `accessToken`. This token is for your BFF/proxy, not for Agent Game Runtime directly.
81
82
 
82
83
  ```ts
83
84
  const browserClient = new AgentGameRuntimeBrowserClient({
84
85
  baseUrl: "",
85
- tokenPath: "/api/agent-game-runtime-token",
86
86
  accessToken: async () => getScopedApplicationToken(),
87
87
  });
88
88
  ```
@@ -141,7 +141,6 @@ import { mountAgentGameOffice } from "@agent-os-lab/agent-game-sdk/office";
141
141
 
142
142
  const client = new AgentGameRuntimeBrowserClient({
143
143
  baseUrl: "",
144
- tokenPath: "/api/agent-game-runtime-token",
145
144
  });
146
145
 
147
146
  const view = await mountAgentGameOffice(container, {
@@ -318,6 +317,8 @@ AGENT_GAME_RUNTIME_BASE_URL=http://localhost:3107 AGENTOS_API_KEY=... bun run de
318
317
 
319
318
  Open `http://localhost:7357`.
320
319
 
320
+ The demo exposes the browser BFF route at `/api/agent-game-runtime-token`. It does not require `AGENT_GAME_RUNTIME_TOKEN_PATH`; the SDK server client owns the runtime token path and uses Agent Game Runtime's default `/api/v1/game-runtime-token`.
321
+
321
322
  Set `PORT=7358` or another value to change the port.
322
323
 
323
324
  ## Publish
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-os-lab/agent-game-sdk",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src",
@@ -29,7 +29,7 @@ export function mapPresenceToOfficeAgents(
29
29
  role: agent.scene ?? null,
30
30
  statusLabel: statusLabels[agent.status],
31
31
  activity: agent.activity,
32
- activityLabel: sanitizeActivityLabel(agent.activity),
32
+ activityLabel: sanitizeActivityLabel(agent.activity, agent.status),
33
33
  sceneState: mapStatusToSceneState(agent.status),
34
34
  zoneId: mapStatusToZoneId(agent.status, agent.agentId),
35
35
  updatedAt: agent.updatedAt,
@@ -68,7 +68,13 @@ function mapStatusToSceneState(status: AgentPresenceStatus): AgentGameOfficeScen
68
68
  return status;
69
69
  }
70
70
 
71
- function sanitizeActivityLabel(activity: AgentPresence["activity"]): string | undefined {
71
+ function sanitizeActivityLabel(
72
+ activity: AgentPresence["activity"],
73
+ status: AgentPresenceStatus,
74
+ ): string | undefined {
75
+ if (!isActiveWorkStatus(status)) {
76
+ return undefined;
77
+ }
72
78
  if (activity?.kind === "completed") {
73
79
  return undefined;
74
80
  }
@@ -108,6 +114,10 @@ function formatToolActivityLabel(label: string): string {
108
114
  return label === "正在使用工具" ? "正在调用工具..." : label;
109
115
  }
110
116
 
117
+ function isActiveWorkStatus(status: AgentPresenceStatus): boolean {
118
+ return status === "working" || status === "thinking";
119
+ }
120
+
111
121
  function mapStatusToZoneId(status: AgentPresenceStatus, agentId: string): AgentGameOfficeZoneId {
112
122
  switch (status) {
113
123
  case "working":
@@ -44,6 +44,7 @@ const WORKING_FOLLOW_RESET_DELAY_MS = 30_000;
44
44
  const WORK_EXIT_WAIT_MS = 30_000;
45
45
  const WORKING_FOLLOW_CAMERA_OFFSET = new THREE.Vector3(9, 12, 12);
46
46
  const OFFICE_CAMERA_TRANSITION_DURATION_MS = 600;
47
+ const OFFICE_CAMERA_UP = new THREE.Vector3(0, 1, 0);
47
48
 
48
49
  export type WorkingAgentFollowState = {
49
50
  selectedAgentId: string | null;
@@ -478,14 +479,14 @@ export function createFollowOfficeCameraView(agentPosition: THREE.Vector3): Offi
478
479
  const target = new THREE.Vector3(agentPosition.x, 1, agentPosition.z);
479
480
  const position = target.clone().add(WORKING_FOLLOW_CAMERA_OFFSET);
480
481
  const rotation = new THREE.Euler();
481
- const matrix = new THREE.Matrix4().lookAt(position, target, new THREE.Vector3(0, 1, 0));
482
+ const matrix = new THREE.Matrix4().lookAt(position, target, OFFICE_CAMERA_UP);
482
483
  rotation.setFromRotationMatrix(matrix);
483
484
 
484
485
  return {
485
486
  position,
486
487
  rotation,
487
488
  target,
488
- up: new THREE.Vector3(0, 1, 0),
489
+ up: OFFICE_CAMERA_UP.clone(),
489
490
  distance: position.distanceTo(target),
490
491
  };
491
492
  }
@@ -502,16 +503,20 @@ export function createInitialOfficeCameraView(
502
503
  );
503
504
  const quaternion = new THREE.Quaternion().setFromEuler(rotation);
504
505
  const forward = new THREE.Vector3(0, 0, -1).applyQuaternion(quaternion).normalize();
505
- const up = new THREE.Vector3(0, 1, 0).applyQuaternion(quaternion).normalize();
506
506
  const target = new THREE.Vector3(layout.scene.center.x, OFFICE_CAMERA_BOUNDS_HEIGHT / 2, layout.scene.center.z);
507
- const distance = resolveOfficeCameraDistance(layout, target, quaternion, aspect, fovDegrees);
507
+ const preliminaryPosition = target.clone().sub(forward.clone());
508
+ const orbitRotation = new THREE.Euler();
509
+ const matrix = new THREE.Matrix4().lookAt(preliminaryPosition, target, OFFICE_CAMERA_UP);
510
+ orbitRotation.setFromRotationMatrix(matrix);
511
+ const orbitQuaternion = new THREE.Quaternion().setFromEuler(orbitRotation);
512
+ const distance = resolveOfficeCameraDistance(layout, target, orbitQuaternion, aspect, fovDegrees);
508
513
  const position = target.clone().sub(forward.multiplyScalar(distance));
509
514
 
510
515
  return {
511
516
  position,
512
- rotation,
517
+ rotation: orbitRotation,
513
518
  target,
514
- up,
519
+ up: OFFICE_CAMERA_UP.clone(),
515
520
  distance,
516
521
  };
517
522
  }