@elizaos/skills 2.0.0-alpha.43 → 2.0.0-alpha.430
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 +4 -0
- package/dist/formatter.d.ts.map +1 -1
- package/dist/formatter.js +3 -3
- package/dist/frontmatter.d.ts +13 -1
- package/dist/frontmatter.d.ts.map +1 -1
- package/dist/frontmatter.js +51 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +10 -3
- package/dist/resolver.d.ts +17 -0
- package/dist/resolver.d.ts.map +1 -1
- package/dist/resolver.js +54 -1
- package/dist/types.d.ts +38 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +7 -6
- package/skills/apple-reminders/SKILL.md +1 -1
- package/skills/blucli/SKILL.md +1 -1
- package/skills/bluebubbles/SKILL.md +1 -1
- package/skills/camsnap/SKILL.md +1 -1
- package/skills/canvas/SKILL.md +6 -6
- package/skills/coding-agent/SKILL.md +2 -2
- package/skills/eliza-app-development/SKILL.md +62 -0
- package/skills/eliza-app-development/references/repo-map.md +70 -0
- package/skills/eliza-app-development/references/runtime-and-cloud.md +61 -0
- package/skills/eliza-cloud/SKILL.md +39 -0
- package/skills/eliza-cloud/references/apps-and-containers.md +73 -0
- package/skills/eliza-cloud/references/cloud-backend-and-monetization.md +99 -0
- package/skills/elizaos/SKILL.md +27 -0
- package/skills/elizaos/references/core-abstractions.md +101 -0
- package/skills/elizaos/references/plugin-development.md +74 -0
- package/skills/github/SKILL.md +1 -1
- package/skills/imsg/SKILL.md +1 -1
- package/skills/nano-banana-pro/SKILL.md +1 -1
- package/skills/nano-pdf/SKILL.md +1 -1
- package/skills/notion/SKILL.md +1 -1
- package/skills/obsidian/SKILL.md +1 -1
- package/skills/ordercli/SKILL.md +1 -1
- package/skills/skill-creator/SKILL.md +1 -1
- package/skills/slack/SKILL.md +1 -1
- package/skills/spotify-player/SKILL.md +1 -1
- package/skills/tmux/SKILL.md +1 -1
- package/skills/trello/SKILL.md +1 -1
- package/skills/wacli/SKILL.md +1 -1
- package/skills/weather/SKILL.md +1 -1
- package/skills/yara-authoring/SKILL.md +111 -0
- package/skills/bear-notes/SKILL.md +0 -107
- package/skills/bird/SKILL.md +0 -224
- package/skills/blogwatcher/SKILL.md +0 -69
- package/skills/clawhub/SKILL.md +0 -77
- package/skills/eightctl/SKILL.md +0 -50
- package/skills/food-order/SKILL.md +0 -48
- package/skills/gemini/SKILL.md +0 -43
- package/skills/gifgrep/SKILL.md +0 -79
- package/skills/gog/SKILL.md +0 -116
- package/skills/goplaces/SKILL.md +0 -52
- package/skills/himalaya/SKILL.md +0 -257
- package/skills/himalaya/references/configuration.md +0 -184
- package/skills/himalaya/references/message-composition.md +0 -199
- package/skills/local-places/SERVER_README.md +0 -101
- package/skills/local-places/SKILL.md +0 -102
- package/skills/local-places/pyproject.toml +0 -21
- package/skills/local-places/src/local_places/__init__.py +0 -2
- package/skills/local-places/src/local_places/google_places.py +0 -314
- package/skills/local-places/src/local_places/main.py +0 -65
- package/skills/local-places/src/local_places/schemas.py +0 -107
- package/skills/mcporter/SKILL.md +0 -61
- package/skills/model-usage/SKILL.md +0 -69
- package/skills/model-usage/references/codexbar-cli.md +0 -33
- package/skills/model-usage/scripts/model_usage.py +0 -310
- package/skills/openai-image-gen/SKILL.md +0 -89
- package/skills/openai-image-gen/scripts/gen.py +0 -240
- package/skills/openai-whisper/SKILL.md +0 -38
- package/skills/openai-whisper-api/SKILL.md +0 -52
- package/skills/openai-whisper-api/scripts/transcribe.sh +0 -85
- package/skills/openhue/SKILL.md +0 -51
- package/skills/oracle/SKILL.md +0 -125
- package/skills/peekaboo/SKILL.md +0 -190
- package/skills/sag/SKILL.md +0 -87
- package/skills/session-logs/SKILL.md +0 -115
- package/skills/sharp-edges/.claude-plugin/plugin.json +0 -10
- package/skills/sharp-edges/README.md +0 -48
- package/skills/sharp-edges/SKILL.md +0 -292
- package/skills/sharp-edges/skills/sharp-edges/SKILL.md +0 -292
- package/skills/sharp-edges/skills/sharp-edges/references/auth-patterns.md +0 -252
- package/skills/sharp-edges/skills/sharp-edges/references/case-studies.md +0 -274
- package/skills/sharp-edges/skills/sharp-edges/references/config-patterns.md +0 -333
- package/skills/sharp-edges/skills/sharp-edges/references/crypto-apis.md +0 -190
- package/skills/sharp-edges/skills/sharp-edges/references/lang-c.md +0 -205
- package/skills/sharp-edges/skills/sharp-edges/references/lang-csharp.md +0 -285
- package/skills/sharp-edges/skills/sharp-edges/references/lang-go.md +0 -270
- package/skills/sharp-edges/skills/sharp-edges/references/lang-java.md +0 -263
- package/skills/sharp-edges/skills/sharp-edges/references/lang-javascript.md +0 -269
- package/skills/sharp-edges/skills/sharp-edges/references/lang-kotlin.md +0 -265
- package/skills/sharp-edges/skills/sharp-edges/references/lang-php.md +0 -245
- package/skills/sharp-edges/skills/sharp-edges/references/lang-python.md +0 -274
- package/skills/sharp-edges/skills/sharp-edges/references/lang-ruby.md +0 -273
- package/skills/sharp-edges/skills/sharp-edges/references/lang-rust.md +0 -272
- package/skills/sharp-edges/skills/sharp-edges/references/lang-swift.md +0 -287
- package/skills/sharp-edges/skills/sharp-edges/references/language-specific.md +0 -588
- package/skills/sherpa-onnx-tts/SKILL.md +0 -103
- package/skills/sherpa-onnx-tts/bin/sherpa-onnx-tts +0 -178
- package/skills/songsee/SKILL.md +0 -49
- package/skills/sonoscli/SKILL.md +0 -46
- package/skills/spec-to-code-compliance/.claude-plugin/plugin.json +0 -10
- package/skills/spec-to-code-compliance/README.md +0 -67
- package/skills/spec-to-code-compliance/SKILL.md +0 -349
- package/skills/spec-to-code-compliance/commands/spec-compliance.md +0 -22
- package/skills/spec-to-code-compliance/skills/spec-to-code-compliance/SKILL.md +0 -349
- package/skills/spec-to-code-compliance/skills/spec-to-code-compliance/resources/COMPLETENESS_CHECKLIST.md +0 -69
- package/skills/spec-to-code-compliance/skills/spec-to-code-compliance/resources/IR_EXAMPLES.md +0 -417
- package/skills/spec-to-code-compliance/skills/spec-to-code-compliance/resources/OUTPUT_REQUIREMENTS.md +0 -105
- package/skills/static-analysis/.claude-plugin/plugin.json +0 -8
- package/skills/static-analysis/README.md +0 -59
- package/skills/static-analysis/SKILL.md +0 -91
- package/skills/static-analysis/skills/codeql/SKILL.md +0 -315
- package/skills/static-analysis/skills/sarif-parsing/SKILL.md +0 -479
- package/skills/static-analysis/skills/sarif-parsing/resources/jq-queries.md +0 -162
- package/skills/static-analysis/skills/sarif-parsing/resources/sarif_helpers.py +0 -331
- package/skills/static-analysis/skills/semgrep/SKILL.md +0 -337
- package/skills/summarize/SKILL.md +0 -87
- package/skills/testing-handbook-skills/.claude-plugin/plugin.json +0 -8
- package/skills/testing-handbook-skills/README.md +0 -241
- package/skills/testing-handbook-skills/SKILL.md +0 -104
- package/skills/testing-handbook-skills/scripts/pyproject.toml +0 -8
- package/skills/testing-handbook-skills/scripts/validate-skills.py +0 -657
- package/skills/testing-handbook-skills/skills/address-sanitizer/SKILL.md +0 -341
- package/skills/testing-handbook-skills/skills/aflpp/SKILL.md +0 -640
- package/skills/testing-handbook-skills/skills/atheris/SKILL.md +0 -515
- package/skills/testing-handbook-skills/skills/cargo-fuzz/SKILL.md +0 -454
- package/skills/testing-handbook-skills/skills/codeql/SKILL.md +0 -549
- package/skills/testing-handbook-skills/skills/constant-time-testing/SKILL.md +0 -507
- package/skills/testing-handbook-skills/skills/coverage-analysis/SKILL.md +0 -607
- package/skills/testing-handbook-skills/skills/fuzzing-dictionary/SKILL.md +0 -297
- package/skills/testing-handbook-skills/skills/fuzzing-obstacles/SKILL.md +0 -426
- package/skills/testing-handbook-skills/skills/harness-writing/SKILL.md +0 -614
- package/skills/testing-handbook-skills/skills/libafl/SKILL.md +0 -625
- package/skills/testing-handbook-skills/skills/libfuzzer/SKILL.md +0 -795
- package/skills/testing-handbook-skills/skills/ossfuzz/SKILL.md +0 -426
- package/skills/testing-handbook-skills/skills/ruzzy/SKILL.md +0 -443
- package/skills/testing-handbook-skills/skills/semgrep/SKILL.md +0 -601
- package/skills/testing-handbook-skills/skills/testing-handbook-generator/SKILL.md +0 -372
- package/skills/testing-handbook-skills/skills/testing-handbook-generator/agent-prompt.md +0 -280
- package/skills/testing-handbook-skills/skills/testing-handbook-generator/discovery.md +0 -452
- package/skills/testing-handbook-skills/skills/testing-handbook-generator/templates/domain-skill.md +0 -504
- package/skills/testing-handbook-skills/skills/testing-handbook-generator/templates/fuzzer-skill.md +0 -454
- package/skills/testing-handbook-skills/skills/testing-handbook-generator/templates/technique-skill.md +0 -527
- package/skills/testing-handbook-skills/skills/testing-handbook-generator/templates/tool-skill.md +0 -366
- package/skills/testing-handbook-skills/skills/testing-handbook-generator/testing.md +0 -482
- package/skills/testing-handbook-skills/skills/wycheproof/SKILL.md +0 -533
- package/skills/video-frames/SKILL.md +0 -46
- package/skills/video-frames/scripts/frame.sh +0 -81
- package/skills/voice-call/SKILL.md +0 -45
|
@@ -1,314 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import logging
|
|
4
|
-
import os
|
|
5
|
-
from typing import Any
|
|
6
|
-
|
|
7
|
-
import httpx
|
|
8
|
-
from fastapi import HTTPException
|
|
9
|
-
|
|
10
|
-
from local_places.schemas import (
|
|
11
|
-
LatLng,
|
|
12
|
-
LocationResolveRequest,
|
|
13
|
-
LocationResolveResponse,
|
|
14
|
-
PlaceDetails,
|
|
15
|
-
PlaceSummary,
|
|
16
|
-
ResolvedLocation,
|
|
17
|
-
SearchRequest,
|
|
18
|
-
SearchResponse,
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
GOOGLE_PLACES_BASE_URL = os.getenv(
|
|
22
|
-
"GOOGLE_PLACES_BASE_URL", "https://places.googleapis.com/v1"
|
|
23
|
-
)
|
|
24
|
-
logger = logging.getLogger("local_places.google_places")
|
|
25
|
-
|
|
26
|
-
_PRICE_LEVEL_TO_ENUM = {
|
|
27
|
-
0: "PRICE_LEVEL_FREE",
|
|
28
|
-
1: "PRICE_LEVEL_INEXPENSIVE",
|
|
29
|
-
2: "PRICE_LEVEL_MODERATE",
|
|
30
|
-
3: "PRICE_LEVEL_EXPENSIVE",
|
|
31
|
-
4: "PRICE_LEVEL_VERY_EXPENSIVE",
|
|
32
|
-
}
|
|
33
|
-
_ENUM_TO_PRICE_LEVEL = {value: key for key, value in _PRICE_LEVEL_TO_ENUM.items()}
|
|
34
|
-
|
|
35
|
-
_SEARCH_FIELD_MASK = (
|
|
36
|
-
"places.id,"
|
|
37
|
-
"places.displayName,"
|
|
38
|
-
"places.formattedAddress,"
|
|
39
|
-
"places.location,"
|
|
40
|
-
"places.rating,"
|
|
41
|
-
"places.priceLevel,"
|
|
42
|
-
"places.types,"
|
|
43
|
-
"places.currentOpeningHours,"
|
|
44
|
-
"nextPageToken"
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
_DETAILS_FIELD_MASK = (
|
|
48
|
-
"id,"
|
|
49
|
-
"displayName,"
|
|
50
|
-
"formattedAddress,"
|
|
51
|
-
"location,"
|
|
52
|
-
"rating,"
|
|
53
|
-
"priceLevel,"
|
|
54
|
-
"types,"
|
|
55
|
-
"regularOpeningHours,"
|
|
56
|
-
"currentOpeningHours,"
|
|
57
|
-
"nationalPhoneNumber,"
|
|
58
|
-
"websiteUri"
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
_RESOLVE_FIELD_MASK = (
|
|
62
|
-
"places.id,"
|
|
63
|
-
"places.displayName,"
|
|
64
|
-
"places.formattedAddress,"
|
|
65
|
-
"places.location,"
|
|
66
|
-
"places.types"
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
class _GoogleResponse:
|
|
71
|
-
def __init__(self, response: httpx.Response):
|
|
72
|
-
self.status_code = response.status_code
|
|
73
|
-
self._response = response
|
|
74
|
-
|
|
75
|
-
def json(self) -> dict[str, Any]:
|
|
76
|
-
return self._response.json()
|
|
77
|
-
|
|
78
|
-
@property
|
|
79
|
-
def text(self) -> str:
|
|
80
|
-
return self._response.text
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def _api_headers(field_mask: str) -> dict[str, str]:
|
|
84
|
-
api_key = os.getenv("GOOGLE_PLACES_API_KEY")
|
|
85
|
-
if not api_key:
|
|
86
|
-
raise HTTPException(
|
|
87
|
-
status_code=500,
|
|
88
|
-
detail="GOOGLE_PLACES_API_KEY is not set.",
|
|
89
|
-
)
|
|
90
|
-
return {
|
|
91
|
-
"Content-Type": "application/json",
|
|
92
|
-
"X-Goog-Api-Key": api_key,
|
|
93
|
-
"X-Goog-FieldMask": field_mask,
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
def _request(
|
|
98
|
-
method: str, url: str, payload: dict[str, Any] | None, field_mask: str
|
|
99
|
-
) -> _GoogleResponse:
|
|
100
|
-
try:
|
|
101
|
-
with httpx.Client(timeout=10.0) as client:
|
|
102
|
-
response = client.request(
|
|
103
|
-
method=method,
|
|
104
|
-
url=url,
|
|
105
|
-
headers=_api_headers(field_mask),
|
|
106
|
-
json=payload,
|
|
107
|
-
)
|
|
108
|
-
except httpx.HTTPError as exc:
|
|
109
|
-
raise HTTPException(status_code=502, detail="Google Places API unavailable.") from exc
|
|
110
|
-
|
|
111
|
-
return _GoogleResponse(response)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
def _build_text_query(request: SearchRequest) -> str:
|
|
115
|
-
keyword = request.filters.keyword if request.filters else None
|
|
116
|
-
if keyword:
|
|
117
|
-
return f"{request.query} {keyword}".strip()
|
|
118
|
-
return request.query
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
def _build_search_body(request: SearchRequest) -> dict[str, Any]:
|
|
122
|
-
body: dict[str, Any] = {
|
|
123
|
-
"textQuery": _build_text_query(request),
|
|
124
|
-
"pageSize": request.limit,
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if request.page_token:
|
|
128
|
-
body["pageToken"] = request.page_token
|
|
129
|
-
|
|
130
|
-
if request.location_bias:
|
|
131
|
-
body["locationBias"] = {
|
|
132
|
-
"circle": {
|
|
133
|
-
"center": {
|
|
134
|
-
"latitude": request.location_bias.lat,
|
|
135
|
-
"longitude": request.location_bias.lng,
|
|
136
|
-
},
|
|
137
|
-
"radius": request.location_bias.radius_m,
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
if request.filters:
|
|
142
|
-
filters = request.filters
|
|
143
|
-
if filters.types:
|
|
144
|
-
body["includedType"] = filters.types[0]
|
|
145
|
-
if filters.open_now is not None:
|
|
146
|
-
body["openNow"] = filters.open_now
|
|
147
|
-
if filters.min_rating is not None:
|
|
148
|
-
body["minRating"] = filters.min_rating
|
|
149
|
-
if filters.price_levels:
|
|
150
|
-
body["priceLevels"] = [
|
|
151
|
-
_PRICE_LEVEL_TO_ENUM[level] for level in filters.price_levels
|
|
152
|
-
]
|
|
153
|
-
|
|
154
|
-
return body
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
def _parse_lat_lng(raw: dict[str, Any] | None) -> LatLng | None:
|
|
158
|
-
if not raw:
|
|
159
|
-
return None
|
|
160
|
-
latitude = raw.get("latitude")
|
|
161
|
-
longitude = raw.get("longitude")
|
|
162
|
-
if latitude is None or longitude is None:
|
|
163
|
-
return None
|
|
164
|
-
return LatLng(lat=latitude, lng=longitude)
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
def _parse_display_name(raw: dict[str, Any] | None) -> str | None:
|
|
168
|
-
if not raw:
|
|
169
|
-
return None
|
|
170
|
-
return raw.get("text")
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
def _parse_open_now(raw: dict[str, Any] | None) -> bool | None:
|
|
174
|
-
if not raw:
|
|
175
|
-
return None
|
|
176
|
-
return raw.get("openNow")
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
def _parse_hours(raw: dict[str, Any] | None) -> list[str] | None:
|
|
180
|
-
if not raw:
|
|
181
|
-
return None
|
|
182
|
-
return raw.get("weekdayDescriptions")
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
def _parse_price_level(raw: str | None) -> int | None:
|
|
186
|
-
if not raw:
|
|
187
|
-
return None
|
|
188
|
-
return _ENUM_TO_PRICE_LEVEL.get(raw)
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
def search_places(request: SearchRequest) -> SearchResponse:
|
|
192
|
-
url = f"{GOOGLE_PLACES_BASE_URL}/places:searchText"
|
|
193
|
-
response = _request("POST", url, _build_search_body(request), _SEARCH_FIELD_MASK)
|
|
194
|
-
|
|
195
|
-
if response.status_code >= 400:
|
|
196
|
-
logger.error(
|
|
197
|
-
"Google Places API error %s. response=%s",
|
|
198
|
-
response.status_code,
|
|
199
|
-
response.text,
|
|
200
|
-
)
|
|
201
|
-
raise HTTPException(
|
|
202
|
-
status_code=502,
|
|
203
|
-
detail=f"Google Places API error ({response.status_code}).",
|
|
204
|
-
)
|
|
205
|
-
|
|
206
|
-
try:
|
|
207
|
-
payload = response.json()
|
|
208
|
-
except ValueError as exc:
|
|
209
|
-
logger.error(
|
|
210
|
-
"Google Places API returned invalid JSON. response=%s",
|
|
211
|
-
response.text,
|
|
212
|
-
)
|
|
213
|
-
raise HTTPException(status_code=502, detail="Invalid Google response.") from exc
|
|
214
|
-
|
|
215
|
-
places = payload.get("places", [])
|
|
216
|
-
results = []
|
|
217
|
-
for place in places:
|
|
218
|
-
results.append(
|
|
219
|
-
PlaceSummary(
|
|
220
|
-
place_id=place.get("id", ""),
|
|
221
|
-
name=_parse_display_name(place.get("displayName")),
|
|
222
|
-
address=place.get("formattedAddress"),
|
|
223
|
-
location=_parse_lat_lng(place.get("location")),
|
|
224
|
-
rating=place.get("rating"),
|
|
225
|
-
price_level=_parse_price_level(place.get("priceLevel")),
|
|
226
|
-
types=place.get("types"),
|
|
227
|
-
open_now=_parse_open_now(place.get("currentOpeningHours")),
|
|
228
|
-
)
|
|
229
|
-
)
|
|
230
|
-
|
|
231
|
-
return SearchResponse(
|
|
232
|
-
results=results,
|
|
233
|
-
next_page_token=payload.get("nextPageToken"),
|
|
234
|
-
)
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
def get_place_details(place_id: str) -> PlaceDetails:
|
|
238
|
-
url = f"{GOOGLE_PLACES_BASE_URL}/places/{place_id}"
|
|
239
|
-
response = _request("GET", url, None, _DETAILS_FIELD_MASK)
|
|
240
|
-
|
|
241
|
-
if response.status_code >= 400:
|
|
242
|
-
logger.error(
|
|
243
|
-
"Google Places API error %s. response=%s",
|
|
244
|
-
response.status_code,
|
|
245
|
-
response.text,
|
|
246
|
-
)
|
|
247
|
-
raise HTTPException(
|
|
248
|
-
status_code=502,
|
|
249
|
-
detail=f"Google Places API error ({response.status_code}).",
|
|
250
|
-
)
|
|
251
|
-
|
|
252
|
-
try:
|
|
253
|
-
payload = response.json()
|
|
254
|
-
except ValueError as exc:
|
|
255
|
-
logger.error(
|
|
256
|
-
"Google Places API returned invalid JSON. response=%s",
|
|
257
|
-
response.text,
|
|
258
|
-
)
|
|
259
|
-
raise HTTPException(status_code=502, detail="Invalid Google response.") from exc
|
|
260
|
-
|
|
261
|
-
return PlaceDetails(
|
|
262
|
-
place_id=payload.get("id", place_id),
|
|
263
|
-
name=_parse_display_name(payload.get("displayName")),
|
|
264
|
-
address=payload.get("formattedAddress"),
|
|
265
|
-
location=_parse_lat_lng(payload.get("location")),
|
|
266
|
-
rating=payload.get("rating"),
|
|
267
|
-
price_level=_parse_price_level(payload.get("priceLevel")),
|
|
268
|
-
types=payload.get("types"),
|
|
269
|
-
phone=payload.get("nationalPhoneNumber"),
|
|
270
|
-
website=payload.get("websiteUri"),
|
|
271
|
-
hours=_parse_hours(payload.get("regularOpeningHours")),
|
|
272
|
-
open_now=_parse_open_now(payload.get("currentOpeningHours")),
|
|
273
|
-
)
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
def resolve_locations(request: LocationResolveRequest) -> LocationResolveResponse:
|
|
277
|
-
url = f"{GOOGLE_PLACES_BASE_URL}/places:searchText"
|
|
278
|
-
body = {"textQuery": request.location_text, "pageSize": request.limit}
|
|
279
|
-
response = _request("POST", url, body, _RESOLVE_FIELD_MASK)
|
|
280
|
-
|
|
281
|
-
if response.status_code >= 400:
|
|
282
|
-
logger.error(
|
|
283
|
-
"Google Places API error %s. response=%s",
|
|
284
|
-
response.status_code,
|
|
285
|
-
response.text,
|
|
286
|
-
)
|
|
287
|
-
raise HTTPException(
|
|
288
|
-
status_code=502,
|
|
289
|
-
detail=f"Google Places API error ({response.status_code}).",
|
|
290
|
-
)
|
|
291
|
-
|
|
292
|
-
try:
|
|
293
|
-
payload = response.json()
|
|
294
|
-
except ValueError as exc:
|
|
295
|
-
logger.error(
|
|
296
|
-
"Google Places API returned invalid JSON. response=%s",
|
|
297
|
-
response.text,
|
|
298
|
-
)
|
|
299
|
-
raise HTTPException(status_code=502, detail="Invalid Google response.") from exc
|
|
300
|
-
|
|
301
|
-
places = payload.get("places", [])
|
|
302
|
-
results = []
|
|
303
|
-
for place in places:
|
|
304
|
-
results.append(
|
|
305
|
-
ResolvedLocation(
|
|
306
|
-
place_id=place.get("id", ""),
|
|
307
|
-
name=_parse_display_name(place.get("displayName")),
|
|
308
|
-
address=place.get("formattedAddress"),
|
|
309
|
-
location=_parse_lat_lng(place.get("location")),
|
|
310
|
-
types=place.get("types"),
|
|
311
|
-
)
|
|
312
|
-
)
|
|
313
|
-
|
|
314
|
-
return LocationResolveResponse(results=results)
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
import os
|
|
3
|
-
|
|
4
|
-
from fastapi import FastAPI, Request
|
|
5
|
-
from fastapi.encoders import jsonable_encoder
|
|
6
|
-
from fastapi.exceptions import RequestValidationError
|
|
7
|
-
from fastapi.responses import JSONResponse
|
|
8
|
-
|
|
9
|
-
from local_places.google_places import get_place_details, resolve_locations, search_places
|
|
10
|
-
from local_places.schemas import (
|
|
11
|
-
LocationResolveRequest,
|
|
12
|
-
LocationResolveResponse,
|
|
13
|
-
PlaceDetails,
|
|
14
|
-
SearchRequest,
|
|
15
|
-
SearchResponse,
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
app = FastAPI(
|
|
19
|
-
title="My API",
|
|
20
|
-
servers=[{"url": os.getenv("OPENAPI_SERVER_URL", "http://maxims-macbook-air:8000")}],
|
|
21
|
-
)
|
|
22
|
-
logger = logging.getLogger("local_places.validation")
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
@app.get("/ping")
|
|
26
|
-
def ping() -> dict[str, str]:
|
|
27
|
-
return {"message": "pong"}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
@app.exception_handler(RequestValidationError)
|
|
31
|
-
async def validation_exception_handler(
|
|
32
|
-
request: Request, exc: RequestValidationError
|
|
33
|
-
) -> JSONResponse:
|
|
34
|
-
logger.error(
|
|
35
|
-
"Validation error on %s %s. body=%s errors=%s",
|
|
36
|
-
request.method,
|
|
37
|
-
request.url.path,
|
|
38
|
-
exc.body,
|
|
39
|
-
exc.errors(),
|
|
40
|
-
)
|
|
41
|
-
return JSONResponse(
|
|
42
|
-
status_code=422,
|
|
43
|
-
content=jsonable_encoder({"detail": exc.errors()}),
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
@app.post("/places/search", response_model=SearchResponse)
|
|
48
|
-
def places_search(request: SearchRequest) -> SearchResponse:
|
|
49
|
-
return search_places(request)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
@app.get("/places/{place_id}", response_model=PlaceDetails)
|
|
53
|
-
def places_details(place_id: str) -> PlaceDetails:
|
|
54
|
-
return get_place_details(place_id)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
@app.post("/locations/resolve", response_model=LocationResolveResponse)
|
|
58
|
-
def locations_resolve(request: LocationResolveRequest) -> LocationResolveResponse:
|
|
59
|
-
return resolve_locations(request)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if __name__ == "__main__":
|
|
63
|
-
import uvicorn
|
|
64
|
-
|
|
65
|
-
uvicorn.run("local_places.main:app", host="0.0.0.0", port=8000)
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from pydantic import BaseModel, Field, field_validator
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class LatLng(BaseModel):
|
|
7
|
-
lat: float = Field(ge=-90, le=90)
|
|
8
|
-
lng: float = Field(ge=-180, le=180)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class LocationBias(BaseModel):
|
|
12
|
-
lat: float = Field(ge=-90, le=90)
|
|
13
|
-
lng: float = Field(ge=-180, le=180)
|
|
14
|
-
radius_m: float = Field(gt=0)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class Filters(BaseModel):
|
|
18
|
-
types: list[str] | None = None
|
|
19
|
-
open_now: bool | None = None
|
|
20
|
-
min_rating: float | None = Field(default=None, ge=0, le=5)
|
|
21
|
-
price_levels: list[int] | None = None
|
|
22
|
-
keyword: str | None = Field(default=None, min_length=1)
|
|
23
|
-
|
|
24
|
-
@field_validator("types")
|
|
25
|
-
@classmethod
|
|
26
|
-
def validate_types(cls, value: list[str] | None) -> list[str] | None:
|
|
27
|
-
if value is None:
|
|
28
|
-
return value
|
|
29
|
-
if len(value) > 1:
|
|
30
|
-
raise ValueError(
|
|
31
|
-
"Only one type is supported. Use query/keyword for additional filtering."
|
|
32
|
-
)
|
|
33
|
-
return value
|
|
34
|
-
|
|
35
|
-
@field_validator("price_levels")
|
|
36
|
-
@classmethod
|
|
37
|
-
def validate_price_levels(cls, value: list[int] | None) -> list[int] | None:
|
|
38
|
-
if value is None:
|
|
39
|
-
return value
|
|
40
|
-
invalid = [level for level in value if level not in range(0, 5)]
|
|
41
|
-
if invalid:
|
|
42
|
-
raise ValueError("price_levels must be integers between 0 and 4.")
|
|
43
|
-
return value
|
|
44
|
-
|
|
45
|
-
@field_validator("min_rating")
|
|
46
|
-
@classmethod
|
|
47
|
-
def validate_min_rating(cls, value: float | None) -> float | None:
|
|
48
|
-
if value is None:
|
|
49
|
-
return value
|
|
50
|
-
if (value * 2) % 1 != 0:
|
|
51
|
-
raise ValueError("min_rating must be in 0.5 increments.")
|
|
52
|
-
return value
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
class SearchRequest(BaseModel):
|
|
56
|
-
query: str = Field(min_length=1)
|
|
57
|
-
location_bias: LocationBias | None = None
|
|
58
|
-
filters: Filters | None = None
|
|
59
|
-
limit: int = Field(default=10, ge=1, le=20)
|
|
60
|
-
page_token: str | None = None
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
class PlaceSummary(BaseModel):
|
|
64
|
-
place_id: str
|
|
65
|
-
name: str | None = None
|
|
66
|
-
address: str | None = None
|
|
67
|
-
location: LatLng | None = None
|
|
68
|
-
rating: float | None = None
|
|
69
|
-
price_level: int | None = None
|
|
70
|
-
types: list[str] | None = None
|
|
71
|
-
open_now: bool | None = None
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
class SearchResponse(BaseModel):
|
|
75
|
-
results: list[PlaceSummary]
|
|
76
|
-
next_page_token: str | None = None
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
class LocationResolveRequest(BaseModel):
|
|
80
|
-
location_text: str = Field(min_length=1)
|
|
81
|
-
limit: int = Field(default=5, ge=1, le=10)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
class ResolvedLocation(BaseModel):
|
|
85
|
-
place_id: str
|
|
86
|
-
name: str | None = None
|
|
87
|
-
address: str | None = None
|
|
88
|
-
location: LatLng | None = None
|
|
89
|
-
types: list[str] | None = None
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
class LocationResolveResponse(BaseModel):
|
|
93
|
-
results: list[ResolvedLocation]
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
class PlaceDetails(BaseModel):
|
|
97
|
-
place_id: str
|
|
98
|
-
name: str | None = None
|
|
99
|
-
address: str | None = None
|
|
100
|
-
location: LatLng | None = None
|
|
101
|
-
rating: float | None = None
|
|
102
|
-
price_level: int | None = None
|
|
103
|
-
types: list[str] | None = None
|
|
104
|
-
phone: str | None = None
|
|
105
|
-
website: str | None = None
|
|
106
|
-
hours: list[str] | None = None
|
|
107
|
-
open_now: bool | None = None
|
package/skills/mcporter/SKILL.md
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: mcporter
|
|
3
|
-
description: Use the mcporter CLI to list, configure, auth, and call MCP servers/tools directly (HTTP or stdio), including ad-hoc servers, config edits, and CLI/type generation.
|
|
4
|
-
homepage: http://mcporter.dev
|
|
5
|
-
metadata:
|
|
6
|
-
{
|
|
7
|
-
"otto":
|
|
8
|
-
{
|
|
9
|
-
"emoji": "📦",
|
|
10
|
-
"requires": { "bins": ["mcporter"] },
|
|
11
|
-
"install":
|
|
12
|
-
[
|
|
13
|
-
{
|
|
14
|
-
"id": "node",
|
|
15
|
-
"kind": "node",
|
|
16
|
-
"package": "mcporter",
|
|
17
|
-
"bins": ["mcporter"],
|
|
18
|
-
"label": "Install mcporter (node)",
|
|
19
|
-
},
|
|
20
|
-
],
|
|
21
|
-
},
|
|
22
|
-
}
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
# mcporter
|
|
26
|
-
|
|
27
|
-
Use `mcporter` to work with MCP servers directly.
|
|
28
|
-
|
|
29
|
-
Quick start
|
|
30
|
-
|
|
31
|
-
- `mcporter list`
|
|
32
|
-
- `mcporter list <server> --schema`
|
|
33
|
-
- `mcporter call <server.tool> key=value`
|
|
34
|
-
|
|
35
|
-
Call tools
|
|
36
|
-
|
|
37
|
-
- Selector: `mcporter call linear.list_issues team=ENG limit:5`
|
|
38
|
-
- Function syntax: `mcporter call "linear.create_issue(title: \"Bug\")"`
|
|
39
|
-
- Full URL: `mcporter call https://api.example.com/mcp.fetch url:https://example.com`
|
|
40
|
-
- Stdio: `mcporter call --stdio "bun run ./server.ts" scrape url=https://example.com`
|
|
41
|
-
- JSON payload: `mcporter call <server.tool> --args '{"limit":5}'`
|
|
42
|
-
|
|
43
|
-
Auth + config
|
|
44
|
-
|
|
45
|
-
- OAuth: `mcporter auth <server | url> [--reset]`
|
|
46
|
-
- Config: `mcporter config list|get|add|remove|import|login|logout`
|
|
47
|
-
|
|
48
|
-
Daemon
|
|
49
|
-
|
|
50
|
-
- `mcporter daemon start|status|stop|restart`
|
|
51
|
-
|
|
52
|
-
Codegen
|
|
53
|
-
|
|
54
|
-
- CLI: `mcporter generate-cli --server <name>` or `--command <url>`
|
|
55
|
-
- Inspect: `mcporter inspect-cli <path> [--json]`
|
|
56
|
-
- TS: `mcporter emit-ts <server> --mode client|types`
|
|
57
|
-
|
|
58
|
-
Notes
|
|
59
|
-
|
|
60
|
-
- Config default: `./config/mcporter.json` (override with `--config`).
|
|
61
|
-
- Prefer `--output json` for machine-readable results.
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: model-usage
|
|
3
|
-
description: Use CodexBar CLI local cost usage to summarize per-model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.
|
|
4
|
-
metadata:
|
|
5
|
-
{
|
|
6
|
-
"otto":
|
|
7
|
-
{
|
|
8
|
-
"emoji": "📊",
|
|
9
|
-
"os": ["darwin"],
|
|
10
|
-
"requires": { "bins": ["codexbar"] },
|
|
11
|
-
"install":
|
|
12
|
-
[
|
|
13
|
-
{
|
|
14
|
-
"id": "brew-cask",
|
|
15
|
-
"kind": "brew",
|
|
16
|
-
"cask": "steipete/tap/codexbar",
|
|
17
|
-
"bins": ["codexbar"],
|
|
18
|
-
"label": "Install CodexBar (brew cask)",
|
|
19
|
-
},
|
|
20
|
-
],
|
|
21
|
-
},
|
|
22
|
-
}
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
# Model usage
|
|
26
|
-
|
|
27
|
-
## Overview
|
|
28
|
-
|
|
29
|
-
Get per-model usage cost from CodexBar's local cost logs. Supports "current model" (most recent daily entry) or "all models" summaries for Codex or Claude.
|
|
30
|
-
|
|
31
|
-
TODO: add Linux CLI support guidance once CodexBar CLI install path is documented for Linux.
|
|
32
|
-
|
|
33
|
-
## Quick start
|
|
34
|
-
|
|
35
|
-
1. Fetch cost JSON via CodexBar CLI or pass a JSON file.
|
|
36
|
-
2. Use the bundled script to summarize by model.
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
python {baseDir}/scripts/model_usage.py --provider codex --mode current
|
|
40
|
-
python {baseDir}/scripts/model_usage.py --provider codex --mode all
|
|
41
|
-
python {baseDir}/scripts/model_usage.py --provider claude --mode all --format json --pretty
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
## Current model logic
|
|
45
|
-
|
|
46
|
-
- Uses the most recent daily row with `modelBreakdowns`.
|
|
47
|
-
- Picks the model with the highest cost in that row.
|
|
48
|
-
- Falls back to the last entry in `modelsUsed` when breakdowns are missing.
|
|
49
|
-
- Override with `--model <name>` when you need a specific model.
|
|
50
|
-
|
|
51
|
-
## Inputs
|
|
52
|
-
|
|
53
|
-
- Default: runs `codexbar cost --format json --provider <codex|claude>`.
|
|
54
|
-
- File or stdin:
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
codexbar cost --provider codex --format json > /tmp/cost.json
|
|
58
|
-
python {baseDir}/scripts/model_usage.py --input /tmp/cost.json --mode all
|
|
59
|
-
cat /tmp/cost.json | python {baseDir}/scripts/model_usage.py --input - --mode current
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
## Output
|
|
63
|
-
|
|
64
|
-
- Text (default) or JSON (`--format json --pretty`).
|
|
65
|
-
- Values are cost-only per model; tokens are not split by model in CodexBar output.
|
|
66
|
-
|
|
67
|
-
## References
|
|
68
|
-
|
|
69
|
-
- Read `references/codexbar-cli.md` for CLI flags and cost JSON fields.
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# CodexBar CLI quick ref (usage + cost)
|
|
2
|
-
|
|
3
|
-
## Install
|
|
4
|
-
|
|
5
|
-
- App: Preferences -> Advanced -> Install CLI
|
|
6
|
-
- Repo: ./bin/install-codexbar-cli.sh
|
|
7
|
-
|
|
8
|
-
## Commands
|
|
9
|
-
|
|
10
|
-
- Usage snapshot (web/cli sources):
|
|
11
|
-
- codexbar usage --format json --pretty
|
|
12
|
-
- codexbar --provider all --format json
|
|
13
|
-
- Local cost usage (Codex + Claude only):
|
|
14
|
-
- codexbar cost --format json --pretty
|
|
15
|
-
- codexbar cost --provider codex|claude --format json
|
|
16
|
-
|
|
17
|
-
## Cost JSON fields
|
|
18
|
-
|
|
19
|
-
The payload is an array (one per provider).
|
|
20
|
-
|
|
21
|
-
- provider, source, updatedAt
|
|
22
|
-
- sessionTokens, sessionCostUSD
|
|
23
|
-
- last30DaysTokens, last30DaysCostUSD
|
|
24
|
-
- daily[]: date, inputTokens, outputTokens, cacheReadTokens, cacheCreationTokens, totalTokens, totalCost, modelsUsed, modelBreakdowns[]
|
|
25
|
-
- modelBreakdowns[]: modelName, cost
|
|
26
|
-
- totals: totalInputTokens, totalOutputTokens, cacheReadTokens, cacheCreationTokens, totalTokens, totalCost
|
|
27
|
-
|
|
28
|
-
## Notes
|
|
29
|
-
|
|
30
|
-
- Cost usage is local-only. It reads JSONL logs under:
|
|
31
|
-
- Codex: ~/.codex/sessions/\*_/_.jsonl
|
|
32
|
-
- Claude: ~/.config/claude/projects/**/\*.jsonl or ~/.claude/projects/**/\*.jsonl
|
|
33
|
-
- If web usage is required (non-local), use codexbar usage (not cost).
|