dsh-agora 0.2.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/LICENSE +21 -0
- package/README.md +88 -0
- package/assets/agora/SKILL.md +113 -0
- package/assets/agora/references/cli/README.md +161 -0
- package/assets/agora/references/cli/automation.md +189 -0
- package/assets/agora/references/cli/doctor.md +129 -0
- package/assets/agora/references/cli/env.md +158 -0
- package/assets/agora/references/cli/install-auth.md +152 -0
- package/assets/agora/references/cli/projects.md +116 -0
- package/assets/agora/references/cli/quickstarts.md +117 -0
- package/assets/agora/references/cloud-recording/README.md +86 -0
- package/assets/agora/references/conversational-ai/README.md +285 -0
- package/assets/agora/references/conversational-ai/agent-client-toolkit-react.md +182 -0
- package/assets/agora/references/conversational-ai/agent-samples.md +101 -0
- package/assets/agora/references/conversational-ai/agent-toolkit-android.md +209 -0
- package/assets/agora/references/conversational-ai/agent-toolkit-ios.md +208 -0
- package/assets/agora/references/conversational-ai/agent-toolkit.md +201 -0
- package/assets/agora/references/conversational-ai/agent-ui-kit.md +63 -0
- package/assets/agora/references/conversational-ai/architecture.md +221 -0
- package/assets/agora/references/conversational-ai/auth-flow.md +154 -0
- package/assets/agora/references/conversational-ai/conversational-ai-studio.md +173 -0
- package/assets/agora/references/conversational-ai/go-sdk.md +184 -0
- package/assets/agora/references/conversational-ai/integration-from-quickstart.md +203 -0
- package/assets/agora/references/conversational-ai/python-sdk.md +122 -0
- package/assets/agora/references/conversational-ai/quickstarts.md +710 -0
- package/assets/agora/references/conversational-ai/server-custom-llm.md +45 -0
- package/assets/agora/references/conversational-ai/server-mcp.md +40 -0
- package/assets/agora/references/conversational-ai/server-sdk-rename.md +78 -0
- package/assets/agora/references/conversational-ai/server-sdks.md +128 -0
- package/assets/agora/references/doc-fetching.md +67 -0
- package/assets/agora/references/integration-patterns.md +201 -0
- package/assets/agora/references/mcp-tools.md +49 -0
- package/assets/agora/references/rtc/README.md +104 -0
- package/assets/agora/references/rtc/android.md +344 -0
- package/assets/agora/references/rtc/cross-platform-coordination.md +61 -0
- package/assets/agora/references/rtc/flutter.md +282 -0
- package/assets/agora/references/rtc/ios.md +306 -0
- package/assets/agora/references/rtc/nextjs.md +87 -0
- package/assets/agora/references/rtc/react-native.md +266 -0
- package/assets/agora/references/rtc/react.md +186 -0
- package/assets/agora/references/rtc/web.md +506 -0
- package/assets/agora/references/rtm/README.md +80 -0
- package/assets/agora/references/rtm/android.md +277 -0
- package/assets/agora/references/rtm/ios.md +231 -0
- package/assets/agora/references/rtm/web.md +348 -0
- package/assets/agora/references/server/README.md +22 -0
- package/assets/agora/references/server/tokens.md +74 -0
- package/assets/agora/references/server-gateway/README.md +80 -0
- package/assets/agora/references/server-gateway/linux-cpp.md +251 -0
- package/assets/agora/references/testing-guidance/SKILL.md +65 -0
- package/assets/agora/references/testing-guidance/completeness-gate.md +28 -0
- package/assets/agora/references/testing-guidance/convoai-rest.md +83 -0
- package/assets/agora/references/testing-guidance/mobile-rtm-and-renewal.md +109 -0
- package/assets/agora/references/testing-guidance/rtc-android.md +70 -0
- package/assets/agora/references/testing-guidance/rtc-ios.md +73 -0
- package/assets/agora/references/testing-guidance/rtc-react.md +51 -0
- package/assets/agora/references/testing-guidance/rtc-web.md +94 -0
- package/cordis.patch.yml +5 -0
- package/index.js +53 -0
- package/package.json +49 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Testing Guidance — RTC React (`agora-rtc-react`)
|
|
2
|
+
|
|
3
|
+
Mock at the hooks boundary. `agora-rtc-react` wraps `agora-rtc-sdk-ng` — mock the
|
|
4
|
+
hooks directly rather than re-mocking the underlying SDK.
|
|
5
|
+
|
|
6
|
+
Pattern: mock the `agora-rtc-react` module and wrap components under a mock provider.
|
|
7
|
+
|
|
8
|
+
```javascript
|
|
9
|
+
jest.mock('agora-rtc-react', () => ({
|
|
10
|
+
AgoraRTCProvider: ({ children }) => children,
|
|
11
|
+
useLocalMicrophoneTrack: jest.fn().mockReturnValue({
|
|
12
|
+
localMicrophoneTrack: null,
|
|
13
|
+
isLoading: false,
|
|
14
|
+
error: null,
|
|
15
|
+
}),
|
|
16
|
+
useLocalCameraTrack: jest.fn().mockReturnValue({
|
|
17
|
+
localCameraTrack: null,
|
|
18
|
+
isLoading: false,
|
|
19
|
+
error: null,
|
|
20
|
+
}),
|
|
21
|
+
useRemoteUsers: jest.fn().mockReturnValue([]),
|
|
22
|
+
useJoin: jest.fn().mockReturnValue({ isConnected: false, isLoading: false }),
|
|
23
|
+
usePublish: jest.fn(),
|
|
24
|
+
}))
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
For integration tests that need real hook behavior, wrap the component under a real
|
|
28
|
+
`AgoraRTCProvider` with a mocked `IAgoraRTCClient` injected as the `client` prop.
|
|
29
|
+
|
|
30
|
+
Example:
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
import { render, screen } from '@testing-library/react'
|
|
34
|
+
import { useRemoteUsers } from 'agora-rtc-react'
|
|
35
|
+
|
|
36
|
+
test('renders remote users returned by the hook', () => {
|
|
37
|
+
useRemoteUsers.mockReturnValue([{ uid: 42 }, { uid: 43 }])
|
|
38
|
+
|
|
39
|
+
render(<CallGrid />)
|
|
40
|
+
|
|
41
|
+
expect(screen.getByTestId('remote-user-42')).toBeInTheDocument()
|
|
42
|
+
expect(screen.getByTestId('remote-user-43')).toBeInTheDocument()
|
|
43
|
+
})
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Primary assertions:
|
|
47
|
+
|
|
48
|
+
- loading and error states from hooks render correctly
|
|
49
|
+
- join/publish hooks are called with expected inputs
|
|
50
|
+
- remote user state updates the UI
|
|
51
|
+
- provider cleanup occurs on unmount if the component owns client lifecycle
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Testing Guidance — RTC Web (`agora-rtc-sdk-ng`)
|
|
2
|
+
|
|
3
|
+
Mock at the module boundary. The key interfaces to mock:
|
|
4
|
+
|
|
5
|
+
- `AgoraRTC.createClient()` → mock client with `join`, `leave`, `publish`, `subscribe`
|
|
6
|
+
- `AgoraRTC.createMicrophoneAudioTrack()` / `createCameraVideoTrack()` → mock tracks
|
|
7
|
+
- `client.on(event, handler)` → capture event handlers for test assertions
|
|
8
|
+
|
|
9
|
+
Pattern: use Jest's `jest.mock` with a manual mock file.
|
|
10
|
+
|
|
11
|
+
```javascript
|
|
12
|
+
// __mocks__/agora-rtc-sdk-ng.js
|
|
13
|
+
const mockClient = {
|
|
14
|
+
join: jest.fn().mockResolvedValue(undefined),
|
|
15
|
+
leave: jest.fn().mockResolvedValue(undefined),
|
|
16
|
+
publish: jest.fn().mockResolvedValue(undefined),
|
|
17
|
+
subscribe: jest.fn().mockResolvedValue(undefined),
|
|
18
|
+
renewToken: jest.fn().mockResolvedValue(undefined),
|
|
19
|
+
on: jest.fn(),
|
|
20
|
+
off: jest.fn(),
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const mockTrack = {
|
|
24
|
+
play: jest.fn(),
|
|
25
|
+
stop: jest.fn(),
|
|
26
|
+
close: jest.fn(),
|
|
27
|
+
setEnabled: jest.fn().mockResolvedValue(undefined),
|
|
28
|
+
getVolumeLevel: jest.fn().mockReturnValue(0.5),
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const AgoraRTC = {
|
|
32
|
+
createClient: jest.fn().mockReturnValue(mockClient),
|
|
33
|
+
createMicrophoneAudioTrack: jest.fn().mockResolvedValue({ ...mockTrack }),
|
|
34
|
+
createCameraVideoTrack: jest.fn().mockResolvedValue({ ...mockTrack }),
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
module.exports = AgoraRTC;
|
|
38
|
+
module.exports.default = AgoraRTC;
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
In tests, call `jest.mock('agora-rtc-sdk-ng')` at the top of the file to activate the
|
|
42
|
+
manual mock automatically.
|
|
43
|
+
|
|
44
|
+
Capture event handlers so tests can simulate SDK callbacks:
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
test('subscribes when user-published fires', async () => {
|
|
48
|
+
const handlers = {}
|
|
49
|
+
mockClient.on.mockImplementation((event, cb) => {
|
|
50
|
+
handlers[event] = cb
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
render(<VideoCall />)
|
|
54
|
+
|
|
55
|
+
const user = {
|
|
56
|
+
uid: 42,
|
|
57
|
+
audioTrack: { play: jest.fn() },
|
|
58
|
+
videoTrack: { play: jest.fn() },
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const onUserPublished = handlers['user-published']
|
|
62
|
+
await onUserPublished(user, 'audio')
|
|
63
|
+
|
|
64
|
+
expect(mockClient.subscribe).toHaveBeenCalledWith(user, 'audio')
|
|
65
|
+
expect(user.audioTrack.play).toHaveBeenCalled()
|
|
66
|
+
})
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Token renewal is a required production behavior:
|
|
70
|
+
|
|
71
|
+
```javascript
|
|
72
|
+
test('renews token before expiry', async () => {
|
|
73
|
+
global.fetch = jest.fn().mockResolvedValue({
|
|
74
|
+
ok: true,
|
|
75
|
+
json: async () => ({ token: 'new-token-xyz' }),
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
const handler = mockClient.on.mock.calls
|
|
79
|
+
.find(([e]) => e === 'token-privilege-will-expire')[1]
|
|
80
|
+
|
|
81
|
+
await handler()
|
|
82
|
+
|
|
83
|
+
expect(fetch).toHaveBeenCalledWith(expect.stringContaining('/token'))
|
|
84
|
+
expect(mockClient.renewToken).toHaveBeenCalledWith('new-token-xyz')
|
|
85
|
+
})
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Primary assertions:
|
|
89
|
+
|
|
90
|
+
- joins the correct channel/UID
|
|
91
|
+
- publishes expected tracks
|
|
92
|
+
- subscribes after remote publish events
|
|
93
|
+
- renews token before expiry
|
|
94
|
+
- stops and closes tracks before leave
|
package/cordis.patch.yml
ADDED
package/index.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// dsh-agora — bundled skill provider for DeepSeek Harness.
|
|
2
|
+
//
|
|
3
|
+
// Registers the `agora` skill on ctx.skills, mirroring the official
|
|
4
|
+
// `@deepseek-ai/dsh-skill-badge` provider pattern: a Cordis plugin whose
|
|
5
|
+
// apply() registers one immutable provider. The SKILL.md body and references/
|
|
6
|
+
// live in assets/agora/ and are synced verbatim from AgoraIO/skills at a
|
|
7
|
+
// pinned release tag (see scripts/sync-deps.sh) — zero rewrite, no drift.
|
|
8
|
+
import { readFile } from 'node:fs/promises'
|
|
9
|
+
import { fileURLToPath } from 'node:url'
|
|
10
|
+
import { BUNDLED_SKILL_RANK } from '@deepseek-ai/dsh-skill'
|
|
11
|
+
|
|
12
|
+
const PROVIDER_NAME = 'agora'
|
|
13
|
+
const SKILL_DIR_URL = new URL('./assets/agora/', import.meta.url)
|
|
14
|
+
const SKILL_BODY_URL = new URL('./assets/agora/SKILL.md', import.meta.url)
|
|
15
|
+
const RESOURCE_BASE = {
|
|
16
|
+
kind: 'directory',
|
|
17
|
+
path: fileURLToPath(SKILL_DIR_URL),
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const CANDIDATE = {
|
|
21
|
+
name: 'agora',
|
|
22
|
+
description:
|
|
23
|
+
'Activate when the user wants to build voice AI agents, video or voice calls, live streaming, screen sharing, in-app messaging and presence, recording, token or auth flows, or use the `agora` CLI for login, quickstarts, env setup, diagnostics, introspection, skills, or MCP serving, especially when integrating Agora into an app.',
|
|
24
|
+
invocation: {
|
|
25
|
+
modelInvocable: true,
|
|
26
|
+
userInvocable: true,
|
|
27
|
+
},
|
|
28
|
+
provider: PROVIDER_NAME,
|
|
29
|
+
source: 'bundled',
|
|
30
|
+
resourceBase: RESOURCE_BASE,
|
|
31
|
+
rank: BUNDLED_SKILL_RANK,
|
|
32
|
+
locator: SKILL_BODY_URL,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const provider = {
|
|
36
|
+
name: PROVIDER_NAME,
|
|
37
|
+
list: () => Promise.resolve([CANDIDATE]),
|
|
38
|
+
async get(_candidate) {
|
|
39
|
+
return {
|
|
40
|
+
...CANDIDATE,
|
|
41
|
+
content: await readFile(SKILL_BODY_URL, 'utf8'),
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Cordis plugin name. */
|
|
47
|
+
export const name = 'agora-skills'
|
|
48
|
+
/** Service required by the bundled provider. */
|
|
49
|
+
export const inject = ['skills']
|
|
50
|
+
/** Register the bundled `agora` provider on `ctx.skills`. */
|
|
51
|
+
export function apply(ctx) {
|
|
52
|
+
ctx.skills.registerProvider(() => provider)
|
|
53
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-agora",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "DSH skill bundle: the Agora skill (RTC, RTM, ConvoAI, CLI, Cloud Recording, tokens) synced verbatim from AgoraIO/skills at a pinned release tag. Install to add the `agora` skill to DeepSeek Harness.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./index.js",
|
|
9
|
+
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
10
|
+
"./package.json": "./package.json"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"index.js",
|
|
14
|
+
"cordis.patch.yml",
|
|
15
|
+
"assets/agora"
|
|
16
|
+
],
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/littleDogWang/dsh-agora.git"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"deepseek-harness",
|
|
24
|
+
"dsh",
|
|
25
|
+
"plugin",
|
|
26
|
+
"skill",
|
|
27
|
+
"agora",
|
|
28
|
+
"conversational-ai",
|
|
29
|
+
"rtc",
|
|
30
|
+
"rtm",
|
|
31
|
+
"voice-ai"
|
|
32
|
+
],
|
|
33
|
+
"dsh": {
|
|
34
|
+
"bundle": {
|
|
35
|
+
"patch": "./cordis.patch.yml"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"sync:deps": "bash scripts/sync-deps.sh",
|
|
40
|
+
"prepack": "bash scripts/sync-deps.sh"
|
|
41
|
+
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"@deepseek-ai/dsh-skill": "^0.1.0-rc.7",
|
|
44
|
+
"@deepseek-ai/cordis": "^4.0.1"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@deepseek-ai/dsh-skill": "^0.1.0-rc.7"
|
|
48
|
+
}
|
|
49
|
+
}
|