Skip to content

Commit d29da58

Browse files
bozhou8bo-zhou-ms
andauthored
Add initial AGENTS.md and skills for vibe coding (#1050)
* Add initial AGENTS.md and skills for vibe coding * Update agent configs for _base_api * Add pr-review-comments skill and CLAUDE.md * Update skills --------- Co-authored-by: Bo Zhou <zhoubo@microsoft.com>
1 parent 80fd83c commit d29da58

File tree

19 files changed

+5241
-4
lines changed

19 files changed

+5241
-4
lines changed

.agent_cache/.gitkeep

Whitespace-only changes.
Lines changed: 378 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,378 @@
1+
---
2+
name: add-function
3+
description: Guide for adding new functions to the library. Use this when implementing new API wrappers or utility functions.
4+
---
5+
6+
# Adding New Functions
7+
8+
This skill covers the workflow for adding new functions to the Semantic Link Labs library.
9+
10+
## When to Use This Skill
11+
12+
Use this skill when you need to:
13+
- Add a new API wrapper function
14+
- Create a new utility function
15+
- Extend existing functionality with new features
16+
- Add functions to submodules (admin, report, lakehouse, etc.)
17+
18+
---
19+
20+
## Function Categories
21+
22+
| Category | Location | Purpose |
23+
|----------|----------|---------|
24+
| **Top-level functions** | `src/sempy_labs/_*.py` | Main library exports |
25+
| **Admin functions** | `src/sempy_labs/admin/` | Admin API operations |
26+
| **Report functions** | `src/sempy_labs/report/` | Report operations |
27+
| **Lakehouse functions** | `src/sempy_labs/lakehouse/` | Lakehouse operations |
28+
| **Direct Lake functions** | `src/sempy_labs/directlake/` | Direct Lake model operations |
29+
| **TOM methods** | `src/sempy_labs/tom/_model.py` | TOMWrapper class methods |
30+
31+
---
32+
33+
## Step 0: Find the API Documentation
34+
35+
Before implementing an API wrapper, find the relevant API documentation:
36+
37+
```bash
38+
# Use the API search tool
39+
cd .claude/skills/rest-api-patterns/scripts
40+
python search_public_api_doc.py "your search query"
41+
42+
# Examples:
43+
python search_public_api_doc.py "workspace users" --source fabric
44+
python search_public_api_doc.py "dataset refresh" --source powerbi
45+
```
46+
47+
See the [REST API Patterns](../rest-api-patterns/SKILL.md) skill for more details.
48+
49+
---
50+
51+
## Step 1: Choose the Right Location
52+
53+
### Top-Level Function
54+
55+
For general-purpose functions exported from `sempy_labs`:
56+
57+
```python
58+
# src/sempy_labs/_my_feature.py
59+
```
60+
61+
### Submodule Function
62+
63+
For functions belonging to a specific domain:
64+
65+
```python
66+
# src/sempy_labs/admin/_my_admin_function.py
67+
# src/sempy_labs/lakehouse/_my_lakehouse_function.py
68+
# src/sempy_labs/report/_my_report_function.py
69+
```
70+
71+
---
72+
73+
## Step 2: Create the Function
74+
75+
### Required Imports
76+
77+
```python
78+
import pandas as pd
79+
from typing import Optional, List
80+
from uuid import UUID
81+
82+
# Logging decorator from sempy
83+
from sempy._utils._log import log
84+
85+
# Helper functions
86+
from sempy_labs._helper_functions import (
87+
resolve_workspace_name_and_id,
88+
resolve_workspace_id,
89+
_base_api,
90+
_create_dataframe,
91+
)
92+
93+
# Icons for user messages
94+
import sempy_labs._icons as icons
95+
```
96+
97+
### Function Template
98+
99+
```python
100+
@log
101+
def my_new_function(
102+
item: str | UUID,
103+
workspace: Optional[str | UUID] = None,
104+
option: str = "default",
105+
) -> pd.DataFrame:
106+
"""
107+
Short description of what the function does.
108+
109+
Extended description with more details about the function's behavior,
110+
use cases, and any important notes.
111+
112+
This is a wrapper function for the following API: `API Name <https://learn.microsoft.com/rest/api/...>`_.
113+
114+
Service Principal Authentication is supported (see `here <https://github.com/microsoft/semantic-link-labs/blob/main/notebooks/Service%20Principal.ipynb>`_ for examples).
115+
116+
Parameters
117+
----------
118+
item : str | uuid.UUID
119+
The name or ID of the item.
120+
workspace : str | uuid.UUID, default=None
121+
The Fabric workspace name or ID.
122+
Defaults to None which resolves to the workspace of the attached lakehouse
123+
or if no lakehouse attached, resolves to the workspace of the notebook.
124+
option : str, default="default"
125+
An option that controls function behavior.
126+
127+
Returns
128+
-------
129+
pandas.DataFrame
130+
A pandas dataframe showing the results.
131+
Columns include: 'Column1', 'Column2', 'Column3'.
132+
133+
Raises
134+
------
135+
ValueError
136+
If the item does not exist.
137+
FabricHTTPException
138+
If the API request fails.
139+
"""
140+
141+
# Resolve workspace
142+
(workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace)
143+
144+
# Define result DataFrame structure
145+
columns = {
146+
"Column1": "string",
147+
"Column2": "string",
148+
"Column3": "int",
149+
}
150+
df = _create_dataframe(columns=columns)
151+
152+
# Make API call
153+
responses = _base_api(
154+
request=f"/v1/workspaces/{workspace_id}/items",
155+
uses_pagination=True,
156+
client="fabric_sp",
157+
)
158+
159+
# Process responses
160+
rows = []
161+
for r in responses:
162+
for item in r.get("value", []):
163+
rows.append({
164+
"Column1": item.get("id"),
165+
"Column2": item.get("name"),
166+
"Column3": item.get("count", 0),
167+
})
168+
169+
if rows:
170+
df = pd.DataFrame(rows)
171+
172+
return df
173+
```
174+
175+
---
176+
177+
## Step 3: Export the Function
178+
179+
### From Module File
180+
181+
Add to the module's `__init__.py`:
182+
183+
```python
184+
# src/sempy_labs/admin/__init__.py (example for admin submodule)
185+
186+
from ._my_admin_function import my_new_function
187+
188+
__all__ = [
189+
...,
190+
"my_new_function",
191+
]
192+
```
193+
194+
### From Main Package
195+
196+
For top-level functions, add to `src/sempy_labs/__init__.py`:
197+
198+
```python
199+
from ._my_feature import my_new_function
200+
201+
__all__ = [
202+
...,
203+
"my_new_function",
204+
]
205+
```
206+
207+
---
208+
209+
## Common Patterns
210+
211+
### Functions That Modify Resources
212+
213+
```python
214+
@log
215+
def create_item(
216+
name: str,
217+
workspace: Optional[str | UUID] = None,
218+
) -> None:
219+
"""
220+
Creates a new item.
221+
...
222+
"""
223+
(workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace)
224+
225+
payload = {
226+
"displayName": name,
227+
}
228+
229+
_base_api(
230+
request=f"/v1/workspaces/{workspace_id}/items",
231+
method="post",
232+
payload=payload,
233+
status_codes=[201, 202],
234+
client="fabric_sp",
235+
)
236+
237+
print(
238+
f"{icons.green_dot} The '{name}' item has been successfully created "
239+
f"in the '{workspace_name}' workspace."
240+
)
241+
```
242+
243+
### Functions That Delete Resources
244+
245+
```python
246+
@log
247+
def delete_item(
248+
item: str | UUID,
249+
workspace: Optional[str | UUID] = None,
250+
) -> None:
251+
"""
252+
Deletes an item.
253+
...
254+
"""
255+
(workspace_name, workspace_id) = resolve_workspace_name_and_id(workspace)
256+
item_id = resolve_item_id(item=item, type="ItemType", workspace=workspace_id)
257+
258+
_base_api(
259+
request=f"/v1/workspaces/{workspace_id}/items/{item_id}",
260+
method="delete",
261+
client="fabric_sp",
262+
)
263+
264+
print(
265+
f"{icons.green_dot} The item has been successfully deleted "
266+
f"from the '{workspace_name}' workspace."
267+
)
268+
```
269+
270+
### Functions With Long-Running Operations
271+
272+
```python
273+
@log
274+
def long_running_operation(
275+
item: str | UUID,
276+
workspace: Optional[str | UUID] = None,
277+
) -> dict:
278+
"""
279+
Performs a long-running operation.
280+
...
281+
"""
282+
workspace_id = resolve_workspace_id(workspace)
283+
item_id = resolve_item_id(item=item, type="ItemType", workspace=workspace_id)
284+
285+
# lro_return_json handles polling for completion
286+
result = _base_api(
287+
request=f"/v1/workspaces/{workspace_id}/items/{item_id}/operation",
288+
method="post",
289+
lro_return_json=True,
290+
client="fabric_sp",
291+
)
292+
293+
return result
294+
```
295+
296+
---
297+
298+
## Step 4: Add Tests
299+
300+
Create tests for the new function:
301+
302+
```python
303+
# tests/test_my_feature.py
304+
305+
import pytest
306+
import pandas as pd
307+
308+
309+
def test_my_new_function_returns_dataframe():
310+
"""Test that my_new_function returns a DataFrame."""
311+
from sempy_labs import my_new_function
312+
313+
# This might require mocking for unit tests
314+
result = my_new_function()
315+
316+
assert isinstance(result, pd.DataFrame)
317+
318+
319+
def test_my_new_function_with_workspace():
320+
"""Test my_new_function with specific workspace."""
321+
from sempy_labs import my_new_function
322+
323+
result = my_new_function(workspace="Test Workspace")
324+
325+
assert isinstance(result, pd.DataFrame)
326+
```
327+
328+
---
329+
330+
## Step 5: Document the Function
331+
332+
Ensure the docstring follows numpydoc style:
333+
334+
1. ✅ Short description (one line)
335+
2. ✅ Extended description (if needed)
336+
3. ✅ API reference link (for wrapper functions)
337+
4. ✅ Service Principal note (if supported)
338+
5. ✅ All parameters documented with types
339+
6. ✅ Return value documented
340+
7. ✅ Exceptions documented (if applicable)
341+
342+
---
343+
344+
## Checklist Before Committing
345+
346+
- [ ] Function follows naming conventions (`list_`, `get_`, `create_`, etc.)
347+
- [ ] `@log` decorator is applied
348+
- [ ] Complete docstring with numpydoc style
349+
- [ ] Type hints for all parameters and return value
350+
- [ ] Uses standard helper functions (`_base_api`, `resolve_*`, etc.)
351+
- [ ] Function exported in `__init__.py`
352+
- [ ] Tests written for the new function
353+
- [ ] Code formatted with black
354+
- [ ] No linting errors
355+
- [ ] Documentation builds without warnings
356+
357+
---
358+
359+
## Example: Complete New Function
360+
361+
See [_workspaces.py](../../src/sempy_labs/_workspaces.py) for well-implemented examples:
362+
363+
- `list_workspace_users` — List function returning DataFrame
364+
- `update_workspace_user` — Update function with parameters
365+
- `delete_user_from_workspace` — Delete function with confirmation message
366+
367+
---
368+
369+
## API Documentation Resources
370+
371+
When wrapping REST APIs, reference the official documentation:
372+
373+
| API | Documentation |
374+
|-----|---------------|
375+
| Fabric Core API | [https://learn.microsoft.com/rest/api/fabric/core/](https://learn.microsoft.com/rest/api/fabric/core/) |
376+
| Fabric Admin API | [https://learn.microsoft.com/rest/api/fabric/admin/](https://learn.microsoft.com/rest/api/fabric/admin/) |
377+
| Power BI REST API | [https://learn.microsoft.com/rest/api/power-bi/](https://learn.microsoft.com/rest/api/power-bi/) |
378+
| Azure Management API | [https://learn.microsoft.com/rest/api/resources/](https://learn.microsoft.com/rest/api/resources/) |

0 commit comments

Comments
 (0)