mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-18 14:13:10 +00:00
refactor: rename the application package to docsgpt
The backend import package is now docsgpt, the name it will carry on PyPI; application was far too generic to install into anyone's site-packages. git mv plus a mechanical rewrite of every import, dotted string and path reference: 734 Python files, the compose files, Dockerfile, workflows, docs, setup scripts, devcontainer, k8s manifests, vscode config, pytest and coverage config, .gitignore. Behaviour is unchanged. Kept for one release: - A top-level application package whose meta-path finder resolves application.x.y to the already-imported docsgpt.x.y object, so old imports and entry points (celery -A application.app.celery, uvicorn application.asgi:asgi_app) keep working with a FutureWarning. - Celery registers every application.* task name as an alias of its docsgpt.* task on start-up, so messages queued by the previous release still run. The redbeat key prefix moves to redbeat:docsgpt:v2: so schedule entries the previous release wrote are left unread instead of firing twice. The backend image builds from the repository root (docker build -f docsgpt/Dockerfile .) so it can ship the alias package; a root .dockerignore allow-lists docsgpt/ and application/ and keeps caches, local data, .env files, the sample index files and the Dockerfile out. Compose and the image workflows point at the new context.
This commit is contained in:
1 parent
3e7f1f91b4
commit
574f96341e
984 files changed
+9847
-9682
No files matched your search
@@ -0,0 +1,84 @@
|
||||
"""Normalize a command segment to its sticky-approval pattern.
|
||||
|
||||
Rule: head + first sub-token (when present), wildcard the rest.
|
||||
``git checkout main -- file.txt`` -> ``git checkout *``
|
||||
``npm install foo bar`` -> ``npm install *``
|
||||
``ls -la /tmp`` -> ``ls *``
|
||||
``cat /etc/passwd`` -> ``cat *``
|
||||
|
||||
Compound commands are normalized segment-by-segment and rejoined with
|
||||
`` && ``, so a sticky only matches a command with the same normalized
|
||||
segment sequence:
|
||||
``ls /tmp && whoami`` -> ``ls * && whoami``
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import shlex
|
||||
from typing import Optional
|
||||
|
||||
from docsgpt.devices.splitter import split_command
|
||||
|
||||
|
||||
# Commands whose first arg is a sub-command (so the pattern is "cmd subcmd *").
|
||||
_TWO_WORD_HEADS = frozenset(
|
||||
{
|
||||
"git", "npm", "pnpm", "yarn", "pip", "uv", "poetry", "cargo",
|
||||
"docker", "kubectl", "brew", "apt", "apt-get", "dnf", "yum",
|
||||
"go", "rustup", "rustc", "make", "gradle", "mvn",
|
||||
"systemctl", "service",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def normalize_segment(segment: str) -> str:
|
||||
"""Reduce a segment to its sticky-pattern form.
|
||||
|
||||
Args:
|
||||
segment: A single shell command segment (no compound connectors).
|
||||
|
||||
Returns:
|
||||
Pattern like ``git checkout *``, ``ls *``, or just ``cat`` if the
|
||||
original had no args. Empty string for empty input.
|
||||
"""
|
||||
if not segment or not segment.strip():
|
||||
return ""
|
||||
try:
|
||||
tokens = shlex.split(segment.strip(), posix=True)
|
||||
except ValueError:
|
||||
tokens = segment.strip().split()
|
||||
if not tokens:
|
||||
return ""
|
||||
|
||||
head = tokens[0]
|
||||
|
||||
if head in _TWO_WORD_HEADS and len(tokens) >= 2:
|
||||
subcmd = tokens[1]
|
||||
if len(tokens) > 2:
|
||||
return f"{head} {subcmd} *"
|
||||
return f"{head} {subcmd}"
|
||||
|
||||
if len(tokens) > 1:
|
||||
return f"{head} *"
|
||||
return head
|
||||
|
||||
|
||||
def normalize_command(command: str) -> Optional[str]:
|
||||
"""Normalize an entire command into its joined sticky pattern.
|
||||
|
||||
Every segment is normalized and the results are joined with `` && ``,
|
||||
so a compound command's sticky only matches a command with the same
|
||||
normalized segment sequence (approving ``ls /tmp && whoami`` won't
|
||||
auto-approve ``ls /tmp && rm /tmp/x``). Empty segments are skipped;
|
||||
returns ``None`` if there are no non-empty segments.
|
||||
"""
|
||||
if not command:
|
||||
return None
|
||||
patterns = [
|
||||
normalize_segment(segment)
|
||||
for segment in split_command(command)
|
||||
]
|
||||
patterns = [p for p in patterns if p]
|
||||
if not patterns:
|
||||
return None
|
||||
return " && ".join(patterns)
|
||||
Reference in new issue
Block a user