avrae-ls 0.2.1__py3-none-any.whl → 0.3.1__py3-none-any.whl

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.
avrae_ls/context.py CHANGED
@@ -93,31 +93,49 @@ class GVarResolver:
93
93
  async def ensure(self, key: str) -> bool:
94
94
  key = str(key)
95
95
  if key in self._cache:
96
+ log.debug("GVAR ensure cache hit for %s", key)
96
97
  return True
97
98
  if not self._config.enable_gvar_fetch:
99
+ log.warning("GVAR fetch disabled; skipping %s", key)
98
100
  return False
99
101
  if not self._config.service.token:
100
102
  log.debug("GVAR fetch skipped for %s: no token configured", key)
101
103
  return False
102
104
 
103
105
  base_url = self._config.service.base_url.rstrip("/")
104
- url = f"{base_url}/gvars/{key}"
105
- headers = {"Authorization": f"Bearer {self._config.service.token}"}
106
+ url = f"{base_url}/customizations/gvars/{key}"
107
+ # Avrae service expects the JWT directly in Authorization (no Bearer prefix).
108
+ headers = {"Authorization": str(self._config.service.token)}
106
109
  try:
110
+ log.debug("GVAR fetching %s from %s", key, url)
107
111
  async with httpx.AsyncClient(timeout=5) as client:
108
112
  resp = await client.get(url, headers=headers)
109
113
  except Exception as exc:
110
- log.debug("GVAR fetch failed for %s: %s", key, exc)
114
+ log.error("GVAR fetch failed for %s: %s", key, exc)
111
115
  return False
112
116
 
113
117
  if resp.status_code != 200:
114
- log.debug("GVAR fetch returned %s for %s", resp.status_code, key)
118
+ log.warning(
119
+ "GVAR fetch returned %s for %s (body: %s)",
120
+ resp.status_code,
121
+ key,
122
+ (resp.text or "").strip(),
123
+ )
115
124
  return False
116
125
 
117
- payload = resp.json()
118
- value = payload.get("value") or payload.get("content") or payload.get("body")
126
+ value: Any = None
127
+ try:
128
+ payload = resp.json()
129
+ except Exception:
130
+ payload = None
131
+
132
+ if isinstance(payload, dict) and "value" in payload:
133
+ value = payload["value"]
134
+
135
+ log.debug("GVAR fetch parsed value for %s (type=%s)", key, type(value).__name__)
136
+
119
137
  if value is None:
120
- log.debug("GVAR %s payload missing value", key)
138
+ log.error("GVAR %s payload missing value", key)
121
139
  return False
122
140
  self._cache[key] = value
123
141
  return True
avrae_ls/diagnostics.py CHANGED
@@ -149,6 +149,13 @@ class DiagnosticProvider:
149
149
  )
150
150
  )
151
151
 
152
+ def visit_Call(self, node: ast.Call):
153
+ if isinstance(node.func, ast.Name) and node.func.id == "using":
154
+ for kw in node.keywords:
155
+ if kw.arg:
156
+ self.tracker.add(str(kw.arg))
157
+ self.generic_visit(node)
158
+
152
159
  walker = Walker(known)
153
160
  for stmt in body:
154
161
  walker.visit(stmt)
@@ -200,24 +207,41 @@ async def _check_gvars(
200
207
  settings: DiagnosticSettings,
201
208
  ) -> List[types.Diagnostic]:
202
209
  diagnostics: list[types.Diagnostic] = []
210
+ seen: set[str] = set()
211
+
212
+ def _literal_value(node: ast.AST) -> str | None:
213
+ if isinstance(node, ast.Constant) and isinstance(node.value, str):
214
+ return node.value
215
+ if isinstance(node, ast.Str):
216
+ return node.s
217
+ return None
218
+
203
219
  for node in _iter_calls(body):
204
- if not isinstance(node.func, ast.Name) or node.func.id != "get_gvar":
220
+ if not isinstance(node.func, ast.Name):
205
221
  continue
206
- if not node.args:
207
- continue
208
- arg = node.args[0]
209
- if isinstance(arg, (ast.Str, ast.Constant)) and isinstance(getattr(arg, "s", None) or arg.value, str):
210
- gvar_id = arg.s if isinstance(arg, ast.Str) else arg.value
222
+
223
+ async def _validate_gvar(arg_node: ast.AST):
224
+ gvar_id = _literal_value(arg_node)
225
+ if gvar_id is None or gvar_id in seen:
226
+ return
227
+ seen.add(gvar_id)
211
228
  found_local = resolver.get_local(gvar_id)
212
229
  ensured = found_local is not None or await resolver.ensure(gvar_id)
213
230
  if not ensured:
214
231
  diagnostics.append(
215
232
  _make_diagnostic(
216
- arg,
233
+ arg_node,
217
234
  f"Unknown gvar '{gvar_id}'",
218
235
  settings.semantic_level,
219
236
  )
220
237
  )
238
+
239
+ if node.func.id == "get_gvar":
240
+ if node.args:
241
+ await _validate_gvar(node.args[0])
242
+ elif node.func.id == "using":
243
+ for kw in node.keywords:
244
+ await _validate_gvar(kw.value)
221
245
  return diagnostics
222
246
 
223
247
 
@@ -342,7 +366,7 @@ def _build_builtin_signatures() -> dict[str, inspect.Signature]:
342
366
  def get(name, default=None): ...
343
367
  def using(**imports): ...
344
368
  def signature(data=0): ...
345
- def verify_signature(sig=None): ...
369
+ def verify_signature(data): ...
346
370
  def print_fn(*args, sep=" ", end="\n"): ...
347
371
 
348
372
  helpers = {
avrae_ls/runtime.py CHANGED
@@ -1,12 +1,13 @@
1
1
  from __future__ import annotations
2
2
 
3
- import io
4
- import logging
5
- import time
6
3
  import ast
4
+ import io
7
5
  import json
8
- import random
6
+ import logging
9
7
  import math
8
+ import random
9
+ import time
10
+ from types import SimpleNamespace
10
11
  try: # optional dependency
11
12
  import yaml
12
13
  except ImportError: # pragma: no cover - fallback when PyYAML is absent
@@ -16,10 +17,11 @@ from typing import Any, Dict, Set, Callable
16
17
 
17
18
  import d20
18
19
  import draconic
20
+ import httpx
19
21
  from draconic.interpreter import _Break, _Continue, _Return
20
22
 
21
23
  from .context import ContextData, GVarResolver
22
- from .config import VarSources
24
+ from .config import AvraeServiceConfig, VarSources
23
25
  from .api import AliasContextAPI, CharacterAPI, SimpleCombat, SimpleRollResult
24
26
  from . import argparser as avrae_argparser
25
27
  # Minimal stand-in for Avrae's AliasException
@@ -127,12 +129,9 @@ def _default_builtins() -> Dict[str, Any]:
127
129
  "abs": abs,
128
130
  "range": range,
129
131
  "enumerate": enumerate,
130
- "sorted": sorted,
131
- "reversed": reversed,
132
132
  "int": int,
133
133
  "float": float,
134
134
  "str": str,
135
- "bool": bool,
136
135
  "round": round,
137
136
  "ceil": math.ceil,
138
137
  "floor": math.floor,
@@ -156,8 +155,9 @@ def _default_builtins() -> Dict[str, Any]:
156
155
 
157
156
 
158
157
  class MockExecutor:
159
- def __init__(self):
158
+ def __init__(self, service_config: AvraeServiceConfig | None = None):
160
159
  self._base_builtins = _default_builtins()
160
+ self._service_config = service_config or AvraeServiceConfig()
161
161
 
162
162
  def available_names(self, ctx_data: ContextData) -> Set[str]:
163
163
  builtin_names = set(self._base_builtins.keys())
@@ -220,12 +220,16 @@ class MockExecutor:
220
220
  runtime_character = CharacterAPI(ctx_data.character)
221
221
  return runtime_character # type: ignore[return-value]
222
222
 
223
+ import_cache: dict[str, SimpleNamespace] = {}
224
+ import_stack: list[str] = []
223
225
  builtins = self._build_builtins(
224
226
  ctx_data,
225
227
  resolver,
226
228
  buffer,
227
229
  character_provider=_character_provider,
228
230
  interpreter_ref=interpreter_ref,
231
+ import_cache=import_cache,
232
+ import_stack=import_stack,
229
233
  )
230
234
  interpreter = draconic.DraconicInterpreter(
231
235
  builtins=builtins,
@@ -266,10 +270,18 @@ class MockExecutor:
266
270
  buffer: io.StringIO,
267
271
  character_provider: Callable[[], CharacterAPI] | None = None,
268
272
  interpreter_ref: Dict[str, draconic.DraconicInterpreter | None] | None = None,
273
+ import_cache: Dict[str, SimpleNamespace] | None = None,
274
+ import_stack: list[str] | None = None,
269
275
  ) -> Dict[str, Any]:
270
276
  builtins = dict(self._base_builtins)
271
277
  var_store = ctx_data.vars
272
278
  interpreter_ref = interpreter_ref or {"interpreter": None}
279
+ import_cache = import_cache or {}
280
+ import_stack = import_stack or []
281
+ service_cfg = self._service_config
282
+ verify_cache_sig: str | None = None
283
+ verify_cache_result: Dict[str, Any] | None = None
284
+ verify_cache_error: ValueError | None = None
273
285
 
274
286
  def _print(*args, sep=" ", end="\n"):
275
287
  buffer.write(sep.join(map(str, args)) + end)
@@ -283,22 +295,25 @@ class MockExecutor:
283
295
  return var_store.svars.get(str(name), default)
284
296
 
285
297
  def _get_cvar(name: str, default=None):
286
- return var_store.cvars.get(str(name), default)
298
+ val = var_store.cvars.get(str(name), default)
299
+ return str(val) if val is not None else default
287
300
 
288
301
  def _get_uvar(name: str, default=None):
289
- return var_store.uvars.get(str(name), default)
302
+ val = var_store.uvars.get(str(name), default)
303
+ return str(val) if val is not None else default
290
304
 
291
305
  def _get_uvars():
292
- return dict(var_store.uvars)
306
+ return {k: (str(v) if v is not None else v) for k, v in var_store.uvars.items()}
293
307
 
294
308
  def _set_uvar(name: str, value: Any):
295
- var_store.uvars[str(name)] = value
296
- return value
309
+ str_val = str(value) if value is not None else None
310
+ var_store.uvars[str(name)] = str_val
311
+ return str_val
297
312
 
298
313
  def _set_uvar_nx(name: str, value: Any):
299
314
  key = str(name)
300
315
  if key not in var_store.uvars:
301
- var_store.uvars[key] = value
316
+ var_store.uvars[key] = str(value) if value is not None else None
302
317
  return var_store.uvars[key]
303
318
 
304
319
  def _delete_uvar(name: str):
@@ -307,37 +322,136 @@ class MockExecutor:
307
322
  def _uvar_exists(name: str) -> bool:
308
323
  return str(name) in var_store.uvars
309
324
 
310
- def _exists(name: str) -> bool:
325
+ def _resolve_name(key: str) -> tuple[bool, Any]:
326
+ key = str(key)
311
327
  interp = interpreter_ref.get("interpreter")
312
- if interp is None:
313
- return False
314
- return str(name) in getattr(interp, "_names", {})
328
+ if interp is not None:
329
+ names = getattr(interp, "_names", {})
330
+ if key in names:
331
+ return True, names[key]
332
+
333
+ if key in var_store.cvars:
334
+ return True, var_store.cvars[key]
335
+
336
+ if key in var_store.uvars:
337
+ return True, var_store.uvars[key]
338
+
339
+ return False, None
340
+
341
+ def _exists(name: str) -> bool:
342
+ found, _ = _resolve_name(name)
343
+ return found
315
344
 
316
345
  def _get(name: str, default=None):
317
- interp = interpreter_ref.get("interpreter")
318
- if interp is None:
319
- return default
320
- return getattr(interp, "_names", {}).get(str(name), default)
346
+ found, value = _resolve_name(name)
347
+ return value if found else default
321
348
 
322
349
  def _using(**imports):
323
350
  interp = interpreter_ref.get("interpreter")
324
351
  if interp is None:
325
352
  return None
353
+ user_ns = getattr(interp, "_names", {})
354
+
355
+ def _load_module(addr: str) -> SimpleNamespace:
356
+ if addr in import_cache:
357
+ return import_cache[addr]
358
+ if resolver is None:
359
+ raise ModuleNotFoundError(f"No gvar named {addr!r}")
360
+ mod_contents = resolver.get_local(addr)
361
+ if mod_contents is None:
362
+ raise ModuleNotFoundError(f"No gvar named {addr!r}")
363
+
364
+ old_names = getattr(interp, "_names", {})
365
+ depth_increased = False
366
+ try:
367
+ interp._names = {}
368
+ interp._depth += 1
369
+ depth_increased = True
370
+ if interp._depth > interp._config.max_recursion_depth:
371
+ raise RecursionError("Maximum recursion depth exceeded")
372
+ interp.execute_module(str(mod_contents), module_name=addr)
373
+ mod_ns = SimpleNamespace(**getattr(interp, "_names", {}))
374
+ import_cache[addr] = mod_ns
375
+ return mod_ns
376
+ finally:
377
+ if depth_increased:
378
+ interp._depth -= 1
379
+ interp._names = old_names
380
+
326
381
  for ns, addr in imports.items():
327
- val = None
328
- if resolver:
329
- val = resolver.get_local(addr)
330
- interp._names[str(ns)] = val # type: ignore[attr-defined]
382
+ addr_str = str(addr)
383
+ if addr_str in import_stack:
384
+ circle = " imports\n".join(import_stack)
385
+ raise ImportError(f"Circular import detected!\n{circle} imports\n{addr_str}")
386
+ import_stack.append(addr_str)
387
+ try:
388
+ mod_ns = _load_module(addr_str)
389
+ finally:
390
+ import_stack.pop()
391
+ name = str(ns)
392
+ if name in interp.builtins:
393
+ raise ValueError(f"{name} is already builtin (no shadow assignments).")
394
+ user_ns[name] = mod_ns
395
+
396
+ interp._names = user_ns
331
397
  return None
332
398
 
333
399
  def _signature(data=0):
334
- return f"signature:{int(data)}"
400
+ try:
401
+ data = int(data)
402
+ except ValueError:
403
+ raise TypeError(f"Data {data} could not be converted to integer.")
404
+ return f"mock-signature:{int(data)}"
335
405
 
336
406
  def _verify_signature(sig):
407
+ nonlocal verify_cache_sig, verify_cache_result, verify_cache_error
408
+ sig_str = str(sig)
409
+ if sig_str == verify_cache_sig:
410
+ if verify_cache_error:
411
+ raise verify_cache_error
412
+ return verify_cache_result
413
+
414
+ verify_cache_sig = sig_str
415
+ verify_cache_error = None
416
+ verify_cache_result = None
417
+
418
+ def _call_verify_api(signature: str) -> Dict[str, Any]:
419
+ base_url = (service_cfg.base_url if service_cfg else AvraeServiceConfig.base_url).rstrip("/")
420
+ url = f"{base_url}/bot/signature/verify"
421
+ headers = {"Content-Type": "application/json"}
422
+ if service_cfg and service_cfg.token:
423
+ headers["Authorization"] = str(service_cfg.token)
424
+ try:
425
+ resp = httpx.post(url, json={"signature": signature}, headers=headers, timeout=5)
426
+ except Exception as exc:
427
+ raise ValueError(f"Failed to verify signature: {exc}") from exc
428
+
429
+ try:
430
+ payload = resp.json()
431
+ except Exception as exc:
432
+ raise ValueError("Failed to verify signature: invalid response body") from exc
433
+
434
+ if resp.status_code != 200:
435
+ message = payload.get("error") if isinstance(payload, dict) else None
436
+ raise ValueError(message or f"Failed to verify signature: HTTP {resp.status_code}")
437
+
438
+ if not isinstance(payload, dict):
439
+ raise ValueError("Failed to verify signature: invalid response")
440
+ if payload.get("success") is not True:
441
+ message = payload.get("error")
442
+ raise ValueError(message or "Failed to verify signature: unsuccessful response")
443
+
444
+ data = payload.get("data")
445
+ if not isinstance(data, dict):
446
+ raise ValueError("Failed to verify signature: malformed response")
447
+ return data
448
+
337
449
  try:
338
- return {"signature": str(sig), "valid": True}
339
- except Exception:
340
- return {"signature": None, "valid": False}
450
+ verify_cache_result = _call_verify_api(sig_str)
451
+ except ValueError as exc:
452
+ verify_cache_error = exc
453
+ raise
454
+ return verify_cache_result
341
455
 
342
456
  def _argparse(args, character=None, splitter=avrae_argparser.argsplit, parse_ephem=True):
343
457
  return avrae_argparser.argparse(args, character=character, splitter=splitter, parse_ephem=parse_ephem)
@@ -449,12 +563,20 @@ def _literal_gvars(code: str) -> Set[str]:
449
563
 
450
564
  gvars: set[str] = set()
451
565
  for node in ast.walk(tree):
452
- if isinstance(node, ast.Call) and isinstance(node.func, ast.Name) and node.func.id == "get_gvar":
453
- if not node.args:
454
- continue
455
- arg = node.args[0]
456
- if isinstance(arg, ast.Constant) and isinstance(arg.value, str):
457
- gvars.add(arg.value)
458
- elif isinstance(arg, ast.Str):
459
- gvars.add(arg.s)
566
+ if isinstance(node, ast.Call) and isinstance(node.func, ast.Name):
567
+ if node.func.id == "get_gvar":
568
+ if not node.args:
569
+ continue
570
+ arg = node.args[0]
571
+ if isinstance(arg, ast.Constant) and isinstance(arg.value, str):
572
+ gvars.add(arg.value)
573
+ elif isinstance(arg, ast.Str):
574
+ gvars.add(arg.s)
575
+ elif node.func.id == "using":
576
+ for kw in node.keywords:
577
+ val = kw.value
578
+ if isinstance(val, ast.Constant) and isinstance(val.value, str):
579
+ gvars.add(val.value)
580
+ elif isinstance(val, ast.Str):
581
+ gvars.add(val.s)
460
582
  return gvars
avrae_ls/server.py CHANGED
@@ -68,7 +68,7 @@ class AvraeLanguageServer(LanguageServer):
68
68
 
69
69
  def load_workspace(self, root: Path) -> None:
70
70
  config, warnings = load_config(root)
71
- executor = MockExecutor()
71
+ executor = MockExecutor(config.service)
72
72
  context_builder = ContextBuilder(config)
73
73
  diagnostics = DiagnosticProvider(executor, config.diagnostics)
74
74
  self._state = ServerState(
@@ -45,26 +45,80 @@ def _builtin_sigs() -> Dict[str, FunctionSig]:
45
45
 
46
46
  def _runtime_helper_sigs() -> Dict[str, FunctionSig]:
47
47
  helpers = {
48
- "get_gvar": ["address"],
49
- "get_svar": ["name", "default=None"],
50
- "get_cvar": ["name", "default=None"],
51
- "get_uvar": ["name", "default=None"],
52
- "get_uvars": [],
53
- "set_uvar": ["name", "value"],
54
- "set_uvar_nx": ["name", "value"],
55
- "delete_uvar": ["name"],
56
- "uvar_exists": ["name"],
57
- "exists": ["name"],
58
- "get": ["name", "default=None"],
59
- "using": ["**imports"],
60
- "signature": ["data=0"],
61
- "verify_signature": ["sig"],
62
- "print": ["*values"],
63
- "character": [],
64
- "combat": [],
65
- "argparse": ["args", "character=None", "splitter=argsplit", "parse_ephem=True"],
48
+ "get_gvar": (
49
+ ["address"],
50
+ "Retrieves and returns the value of a global variable (gvar) by address.",
51
+ ),
52
+ "get_svar": (
53
+ ["name", "default=None"],
54
+ "Gets a server variable by name, returning default if it is not present.",
55
+ ),
56
+ "get_cvar": (
57
+ ["name", "default=None"],
58
+ "Gets a character variable by name as a string, returning default if it is not present.",
59
+ ),
60
+ "get_uvar": (
61
+ ["name", "default=None"],
62
+ "Gets a user variable by name as a string, returning default if it is not present.",
63
+ ),
64
+ "get_uvars": (
65
+ [],
66
+ "Returns the mapping of user variables available to the caller (values are strings).",
67
+ ),
68
+ "set_uvar": (
69
+ ["name", "value"],
70
+ "Sets a user variable (stored as a string) and returns the stored value.",
71
+ ),
72
+ "set_uvar_nx": (
73
+ ["name", "value"],
74
+ "Sets a user variable only if it does not already exist; returns the stored string value.",
75
+ ),
76
+ "delete_uvar": (
77
+ ["name"],
78
+ "Deletes a user variable and returns its previous value or None if missing.",
79
+ ),
80
+ "uvar_exists": (
81
+ ["name"],
82
+ "Returns whether a user variable is set.",
83
+ ),
84
+ "exists": (
85
+ ["name"],
86
+ "Returns whether a name is set in the current evaluation context.",
87
+ ),
88
+ "get": (
89
+ ["name", "default=None"],
90
+ "Gets the value of a name using local > cvar > uvar resolution order; returns default if not set.",
91
+ ),
92
+ "using": (
93
+ ["**imports"],
94
+ "Imports one or more gvars as modules into the current namespace with the provided aliases.",
95
+ ),
96
+ "signature": (
97
+ ["data=0"],
98
+ "Generates a signed invocation signature encoding invocation context and optional 5-bit user data.",
99
+ ),
100
+ "verify_signature": (
101
+ ["data"],
102
+ "Verifies a signature generated by signature(); returns context data or raises ValueError when invalid.",
103
+ ),
104
+ "print": (
105
+ ["*values"],
106
+ "Writes values to alias output using the configured separator/end (mirrors Python print).",
107
+ ),
108
+ "character": (
109
+ [],
110
+ "Returns the active character object for this alias, or raises if none is available.",
111
+ ),
112
+ "combat": (
113
+ [],
114
+ "Returns the current combat context if one exists, otherwise None.",
115
+ ),
116
+ "argparse": (
117
+ ["args", "character=None", "splitter=argsplit", "parse_ephem=True"],
118
+ "Parses alias arguments using Avrae's argparse helper.",
119
+ ),
66
120
  }
67
- return {name: FunctionSig(name=name, params=params) for name, params in helpers.items()}
121
+ return {name: FunctionSig(name=name, params=params, doc=doc) for name, (params, doc) in helpers.items()}
68
122
 
69
123
 
70
124
  def _avrae_function_sigs() -> Dict[str, FunctionSig]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: avrae-ls
3
- Version: 0.2.1
3
+ Version: 0.3.1
4
4
  Summary: Language server for Avrae draconic aliases
5
5
  Author: 1drturtle
6
6
  Requires-Python: >=3.11
@@ -23,7 +23,7 @@ Language Server Protocol (LSP) implementation targeting Avrae-style draconic ali
23
23
 
24
24
  ## Install (released package)
25
25
 
26
- - CLI/server via `uv tool` (preferred): `uv tool install avrae-ls` then `uv tool run avrae-ls --help` to see stdio/TCP options (same as `python -m avrae_ls`). The VS Code extension uses this invocation by default. The draconic interpreter is vendored, so no Git deps are needed.
26
+ - CLI/server via `uv tool` (preferred): `uv tool install avrae-ls` then `avrae-ls --help` to see stdio/TCP options (same as `python -m avrae_ls`). The VS Code extension uses this invocation by default. The draconic interpreter is vendored, so no Git deps are needed.
27
27
 
28
28
  ## VS Code extension (released)
29
29
 
@@ -37,10 +37,11 @@ Language Server Protocol (LSP) implementation targeting Avrae-style draconic ali
37
37
  - Build everything locally: `make package` (wheel + VSIX in `dist/`).
38
38
  - Run tests/lint: `make check`.
39
39
  - Run via uv tool from source: `uv tool install --from . avrae-ls`.
40
+ - Run diagnostics for a single file (stdout + stderr logs): `avrae-ls --analyze path/to/alias.txt --log-level DEBUG`.
40
41
 
41
42
  ## Releasing (maintainers)
42
43
 
43
44
  1. Bump `pyproject.toml` version.
44
- 2. `make release` (clean, build, `twine check`, upload to PyPI).
45
+ 2. `make release` (clean, build, upload to PyPI).
45
46
  3. Build and attach the VSIX to the GitHub release (`make vsix`).
46
47
  4. Tag and push.
@@ -1,21 +1,21 @@
1
1
  avrae_ls/__init__.py,sha256=BmjrnksGkbG7TPqwbyQvgYj9uei8pFSFpfkRpaGVdJU,63
2
- avrae_ls/__main__.py,sha256=7Osdjqme9unqaGKIHchxVf31egPFlI4_KpBWZvXKpUE,826
2
+ avrae_ls/__main__.py,sha256=ch287lWe11go5xHAE9OkVppixt0vRF401E4zTs2tqQ0,3557
3
3
  avrae_ls/alias_preview.py,sha256=Wy_ZNRq73ojPiLFf6P6fJ7rG7DeFFsFLkLlhFrAjkKI,6117
4
- avrae_ls/api.py,sha256=7kKxFmrvghM4_gv59uRp94DH2MxnVspyjQROT1bY_NE,59430
4
+ avrae_ls/api.py,sha256=sGbwWs5o6M49lyk3qZi6gNdSH_u_BMdghsTlAjpviqQ,64852
5
5
  avrae_ls/argparser.py,sha256=-6RKrXavbSjEyyEeaoz8hRamnB-MEmJt3Cw2smRbmdI,13483
6
6
  avrae_ls/argument_parsing.py,sha256=ezKl65VwuNEDxt6KlYwVQcpy1110UDvf4BqZqgZTcqk,2122
7
- avrae_ls/completions.py,sha256=RAKwDemcg0EUZkc7ncoPO5mKZ8e0cWN2pMt8XKirB9o,18835
7
+ avrae_ls/completions.py,sha256=WSyP967_t_oBhRMjLk-QQKyXWiNh4sJTH560VdMBQeg,34336
8
8
  avrae_ls/config.py,sha256=C51wfG6-82uX4dsffqcDLMiXbZZL9JQgfpulAr8eiqs,15267
9
- avrae_ls/context.py,sha256=jAV0GbpqHrD7jvWYNcOeh-hUcnPLsMFX8Emo48Jc59U,5122
9
+ avrae_ls/context.py,sha256=w0uVSR6Pis3q1fF3kSPsqbTirKOE6n3k2XMO8UZI7sk,5719
10
10
  avrae_ls/cvars.py,sha256=0tcVbUHx_CKJ6aou3kEsKX37LRWAjkUWlqqIuSRFlXk,3197
11
- avrae_ls/diagnostics.py,sha256=a0x8CWTQbapno0JOFVw75gYZnPak4uQ0fySr9B8_xj0,15440
11
+ avrae_ls/diagnostics.py,sha256=EAdbckvvWu0pswopaZ6JyVGCHXUl5ZvGBhP2PDVCrVw,16180
12
12
  avrae_ls/dice.py,sha256=DY7V7L-EwAXaCgddgVe9xU1s9lVtiw5Zc2reipNgdTk,874
13
13
  avrae_ls/parser.py,sha256=AuNxNkkfquN9dcyTpmzAZxWcAQ7CV3PQLHUDYLMz_7U,1148
14
- avrae_ls/runtime.py,sha256=HFBCyL0oR4D91z0x4Id8rl6nhPZl3HINHJyBfoVn3Pk,15115
15
- avrae_ls/server.py,sha256=8togXNRC5aM2fX2sss7V-aedkbJBPM7dmawc57_IU7g,13056
16
- avrae_ls/signature_help.py,sha256=S9VnmmvD_CvFQLPuWMlo33eRAhmNi_CsRpWFcoRY6Rk,4823
14
+ avrae_ls/runtime.py,sha256=sSN_C48TrF7F5NtsUpgHr_cZyYX6HCQHBfCpAYxsDJo,20792
15
+ avrae_ls/server.py,sha256=L3qGTpCDOa64hWFmfWfoKbrDZ3262gmu5wYhHkdLBPY,13070
16
+ avrae_ls/signature_help.py,sha256=JheaEzINV4FO72t5U0AJfL2ZX15y3-gcA6xk3M1jHcY,6980
17
17
  avrae_ls/symbols.py,sha256=8aMalHBDnRsRvhwdbmf0nOazio7G185qw9le45Xb5Mk,4449
18
- avrae_ls-0.2.1.dist-info/licenses/LICENSE,sha256=O-0zMbcEi6wXz1DiSdVgzMlQjJcNqNe5KDv08uYzqR0,1055
18
+ avrae_ls-0.3.1.dist-info/licenses/LICENSE,sha256=O-0zMbcEi6wXz1DiSdVgzMlQjJcNqNe5KDv08uYzqR0,1055
19
19
  draconic/LICENSE,sha256=Fzvu32_DafLKKn2mzxhEdlmrKZzAsigDZ87O7uoVqZI,1067
20
20
  draconic/__init__.py,sha256=YPH420Pcn_nTkfB62hJy_YqC5kpJdzSa78jP8n4z_xY,109
21
21
  draconic/exceptions.py,sha256=siahnHIsumbaUhKBDSrw_DmLZ-0oZks8L5oytPH8hD4,3753
@@ -25,8 +25,8 @@ draconic/string.py,sha256=kGrRc6wNHRq1y5xw8Os-fBhfINDtIY2nBWQWkyLSfQI,2858
25
25
  draconic/types.py,sha256=1Lsr6z8bW5agglGI4hLt_nPtYuZOIf_ueSpPDB4WDrs,13686
26
26
  draconic/utils.py,sha256=D4vJ-txqS2-rlqsEpXAC46_j1sZX4UjY-9zIgElo96k,3122
27
27
  draconic/versions.py,sha256=CUEsgUWjAmjez0432WwiBwZlIzWPIObwZUf8Yld18EE,84
28
- avrae_ls-0.2.1.dist-info/METADATA,sha256=ukIqEUjW7AT9Ry2CeW4U9nFsDUJ4Clwfa-mbFpjv0SQ,2016
29
- avrae_ls-0.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
30
- avrae_ls-0.2.1.dist-info/entry_points.txt,sha256=OtYXipMQzqmxpMoApgo0MeJYFmMbkbFN51Ibhpb8hF4,52
31
- avrae_ls-0.2.1.dist-info/top_level.txt,sha256=TL68uzGHmB2R2ID32_s2zocmcNnpMJVQ6_4NBvyo8a4,18
32
- avrae_ls-0.2.1.dist-info/RECORD,,
28
+ avrae_ls-0.3.1.dist-info/METADATA,sha256=TRJQs5mkNC4TPeYBkO2rXDnvkJhjf2jws1ginLXaXq4,2107
29
+ avrae_ls-0.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
30
+ avrae_ls-0.3.1.dist-info/entry_points.txt,sha256=OtYXipMQzqmxpMoApgo0MeJYFmMbkbFN51Ibhpb8hF4,52
31
+ avrae_ls-0.3.1.dist-info/top_level.txt,sha256=TL68uzGHmB2R2ID32_s2zocmcNnpMJVQ6_4NBvyo8a4,18
32
+ avrae_ls-0.3.1.dist-info/RECORD,,