jingyi 0.1.0__tar.gz
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.
- jingyi-0.1.0/PKG-INFO +28 -0
- jingyi-0.1.0/README.md +18 -0
- jingyi-0.1.0/jingyi/__init__.py +2 -0
- jingyi-0.1.0/jingyi/channels/__init__.py +2 -0
- jingyi-0.1.0/jingyi/channels/plugins/__init__.py +2 -0
- jingyi-0.1.0/jingyi/channels/plugins/discord_plugin.py +24 -0
- jingyi-0.1.0/jingyi/channels/plugins/message_actions.py +31 -0
- jingyi-0.1.0/jingyi/channels/plugins/types.py +23 -0
- jingyi-0.1.0/jingyi/channels/registry.py +27 -0
- jingyi-0.1.0/jingyi/cli/__init__.py +2 -0
- jingyi-0.1.0/jingyi/cli/app.py +58 -0
- jingyi-0.1.0/jingyi/cli/route.py +17 -0
- jingyi-0.1.0/jingyi/commands/__init__.py +2 -0
- jingyi-0.1.0/jingyi/commands/message.py +28 -0
- jingyi-0.1.0/jingyi/config.py +16 -0
- jingyi-0.1.0/jingyi/infra/__init__.py +2 -0
- jingyi-0.1.0/jingyi/infra/outbound/__init__.py +2 -0
- jingyi-0.1.0/jingyi/infra/outbound/message_action_runner.py +85 -0
- jingyi-0.1.0/jingyi/main.py +14 -0
- jingyi-0.1.0/jingyi/runtime.py +11 -0
- jingyi-0.1.0/jingyi.egg-info/PKG-INFO +28 -0
- jingyi-0.1.0/jingyi.egg-info/SOURCES.txt +44 -0
- jingyi-0.1.0/jingyi.egg-info/dependency_links.txt +1 -0
- jingyi-0.1.0/jingyi.egg-info/entry_points.txt +2 -0
- jingyi-0.1.0/jingyi.egg-info/requires.txt +4 -0
- jingyi-0.1.0/jingyi.egg-info/top_level.txt +1 -0
- jingyi-0.1.0/pyproject.toml +29 -0
- jingyi-0.1.0/setup.cfg +4 -0
jingyi-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: jingyi
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: OpenClaw-inspired Python demo agent
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: typer<1.0,>=0.12
|
|
8
|
+
Provides-Extra: dev
|
|
9
|
+
Requires-Dist: pytest<9.0,>=8.0; extra == "dev"
|
|
10
|
+
|
|
11
|
+
# jingyi
|
|
12
|
+
|
|
13
|
+
An OpenClaw-inspired Python demo agent package.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install jingyi
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## CLI
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
jingyi health
|
|
25
|
+
jingyi status
|
|
26
|
+
jingyi message send --to channel:123 --message "hello" --channel discord
|
|
27
|
+
```
|
|
28
|
+
|
jingyi-0.1.0/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# jingyi
|
|
2
|
+
|
|
3
|
+
An OpenClaw-inspired Python demo agent package.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install jingyi
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## CLI
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
jingyi health
|
|
15
|
+
jingyi status
|
|
16
|
+
jingyi message send --to channel:123 --message "hello" --channel discord
|
|
17
|
+
```
|
|
18
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from .types import ChannelActionContext
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def handle_discord_action(ctx: ChannelActionContext) -> dict:
|
|
5
|
+
if ctx.action == "send":
|
|
6
|
+
return {
|
|
7
|
+
"ok": True,
|
|
8
|
+
"channel": ctx.channel,
|
|
9
|
+
"action": ctx.action,
|
|
10
|
+
"message_id": "discord-msg-001",
|
|
11
|
+
"to": str(ctx.params.get("to", "")),
|
|
12
|
+
}
|
|
13
|
+
if ctx.action == "poll":
|
|
14
|
+
return {
|
|
15
|
+
"ok": True,
|
|
16
|
+
"channel": ctx.channel,
|
|
17
|
+
"action": ctx.action,
|
|
18
|
+
"poll_id": "discord-poll-001",
|
|
19
|
+
"to": str(ctx.params.get("to", "")),
|
|
20
|
+
}
|
|
21
|
+
if ctx.action in ("react", "delete"):
|
|
22
|
+
return {"ok": True, "channel": ctx.channel, "action": ctx.action}
|
|
23
|
+
raise ValueError(f"Action {ctx.action} not supported for channel {ctx.channel}")
|
|
24
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from typing import Dict, Optional
|
|
2
|
+
|
|
3
|
+
from .discord_plugin import handle_discord_action
|
|
4
|
+
from .types import ChannelActionContext, ChannelPlugin
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def _default_handler(ctx: ChannelActionContext) -> dict:
|
|
8
|
+
if ctx.action not in ("send", "poll", "react", "delete"):
|
|
9
|
+
raise ValueError(f"Action {ctx.action} not supported for channel {ctx.channel}")
|
|
10
|
+
return {
|
|
11
|
+
"ok": True,
|
|
12
|
+
"channel": ctx.channel,
|
|
13
|
+
"action": ctx.action,
|
|
14
|
+
"to": str(ctx.params.get("to", "")),
|
|
15
|
+
"message_id": f"{ctx.channel}-msg-001",
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
PLUGIN_REGISTRY: Dict[str, ChannelPlugin] = {
|
|
20
|
+
"discord": ChannelPlugin(id="discord", handle_action=handle_discord_action),
|
|
21
|
+
"telegram": ChannelPlugin(id="telegram", handle_action=_default_handler),
|
|
22
|
+
"whatsapp": ChannelPlugin(id="whatsapp", handle_action=_default_handler),
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def dispatch_channel_message_action(ctx: ChannelActionContext) -> Optional[dict]:
|
|
27
|
+
plugin = PLUGIN_REGISTRY.get(ctx.channel)
|
|
28
|
+
if not plugin:
|
|
29
|
+
return None
|
|
30
|
+
return plugin.handle_action(ctx)
|
|
31
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Callable, Dict, Literal, Optional
|
|
3
|
+
|
|
4
|
+
ChannelId = Literal["discord", "telegram", "whatsapp"]
|
|
5
|
+
ChannelMessageActionName = Literal["send", "poll", "broadcast", "react", "delete"]
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class ChannelActionContext:
|
|
10
|
+
channel: ChannelId
|
|
11
|
+
action: ChannelMessageActionName
|
|
12
|
+
params: Dict[str, object]
|
|
13
|
+
account_id: Optional[str] = None
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
ActionHandler = Callable[[ChannelActionContext], Dict[str, object]]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass
|
|
20
|
+
class ChannelPlugin:
|
|
21
|
+
id: ChannelId
|
|
22
|
+
handle_action: ActionHandler
|
|
23
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Dict, Optional
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@dataclass(frozen=True)
|
|
6
|
+
class ChannelMeta:
|
|
7
|
+
id: str
|
|
8
|
+
label: str
|
|
9
|
+
blurb: str
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
CHANNEL_ORDER = ("telegram", "whatsapp", "discord")
|
|
13
|
+
CHANNEL_ALIASES: Dict[str, str] = {"tg": "telegram", "wa": "whatsapp"}
|
|
14
|
+
CHANNEL_META: Dict[str, ChannelMeta] = {
|
|
15
|
+
"telegram": ChannelMeta("telegram", "Telegram", "Bot API style channel"),
|
|
16
|
+
"whatsapp": ChannelMeta("whatsapp", "WhatsApp", "Web session style channel"),
|
|
17
|
+
"discord": ChannelMeta("discord", "Discord", "Bot token style channel"),
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def normalize_channel_id(raw: Optional[str]) -> Optional[str]:
|
|
22
|
+
if not raw:
|
|
23
|
+
return None
|
|
24
|
+
key = raw.strip().lower()
|
|
25
|
+
key = CHANNEL_ALIASES.get(key, key)
|
|
26
|
+
return key if key in CHANNEL_META else None
|
|
27
|
+
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
from typing import List, Optional
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
|
|
5
|
+
from ..commands.message import message_command
|
|
6
|
+
from ..config import load_config
|
|
7
|
+
from ..runtime import default_runtime
|
|
8
|
+
|
|
9
|
+
app = typer.Typer(help="OpenClaw-inspired Python demo")
|
|
10
|
+
message_app = typer.Typer(help="Send messages and channel actions")
|
|
11
|
+
app.add_typer(message_app, name="message")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@message_app.command("send")
|
|
15
|
+
def message_send(
|
|
16
|
+
to: str = typer.Option(..., "--to", help="Target peer"),
|
|
17
|
+
message: str = typer.Option("", "--message", help="Message text"),
|
|
18
|
+
channel: Optional[str] = typer.Option(None, "--channel", help="Channel id"),
|
|
19
|
+
dry_run: bool = typer.Option(False, "--dry-run", help="Do not execute channel call"),
|
|
20
|
+
) -> None:
|
|
21
|
+
cfg = load_config()
|
|
22
|
+
data = {
|
|
23
|
+
"action": "send",
|
|
24
|
+
"to": to,
|
|
25
|
+
"message": message,
|
|
26
|
+
"channel": channel,
|
|
27
|
+
"dry_run": dry_run,
|
|
28
|
+
}
|
|
29
|
+
message_command(data, default_runtime, cfg)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@message_app.command("poll")
|
|
33
|
+
def message_poll(
|
|
34
|
+
to: str = typer.Option(..., "--to", help="Target peer"),
|
|
35
|
+
poll_question: str = typer.Option(..., "--poll-question", help="Poll question"),
|
|
36
|
+
poll_option: List[str] = typer.Option(..., "--poll-option", help="Poll options"),
|
|
37
|
+
channel: Optional[str] = typer.Option(None, "--channel", help="Channel id"),
|
|
38
|
+
dry_run: bool = typer.Option(False, "--dry-run", help="Do not execute channel call"),
|
|
39
|
+
) -> None:
|
|
40
|
+
cfg = load_config()
|
|
41
|
+
data = {
|
|
42
|
+
"action": "poll",
|
|
43
|
+
"to": to,
|
|
44
|
+
"pollQuestion": poll_question,
|
|
45
|
+
"pollOption": poll_option,
|
|
46
|
+
"channel": channel,
|
|
47
|
+
"dry_run": dry_run,
|
|
48
|
+
}
|
|
49
|
+
message_command(data, default_runtime, cfg)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@app.command("routes")
|
|
53
|
+
def show_routes() -> None:
|
|
54
|
+
typer.echo("message send")
|
|
55
|
+
typer.echo("message poll")
|
|
56
|
+
typer.echo("health")
|
|
57
|
+
typer.echo("status")
|
|
58
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def try_route_cli(argv: List[str]) -> bool:
|
|
7
|
+
if len(argv) < 2:
|
|
8
|
+
return False
|
|
9
|
+
cmd = argv[1]
|
|
10
|
+
if cmd == "health":
|
|
11
|
+
typer.echo("ok")
|
|
12
|
+
raise typer.Exit(code=0)
|
|
13
|
+
if cmd == "status":
|
|
14
|
+
typer.echo("demo-status: healthy")
|
|
15
|
+
raise typer.Exit(code=0)
|
|
16
|
+
return False
|
|
17
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Dict
|
|
3
|
+
|
|
4
|
+
from ..config import DemoConfig
|
|
5
|
+
from ..infra.outbound.message_action_runner import RunMessageActionParams, run_message_action
|
|
6
|
+
from ..runtime import Runtime
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass
|
|
10
|
+
class MessageResult:
|
|
11
|
+
data: Dict[str, object]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def message_command(opts: Dict[str, object], runtime: Runtime, cfg: DemoConfig) -> MessageResult:
|
|
15
|
+
raw_action = str(opts.get("action", "send")).strip().lower()
|
|
16
|
+
if raw_action not in ("send", "poll", "broadcast", "react", "delete"):
|
|
17
|
+
raise ValueError(f"Unknown message action: {raw_action}")
|
|
18
|
+
result = run_message_action(
|
|
19
|
+
RunMessageActionParams(
|
|
20
|
+
cfg=cfg,
|
|
21
|
+
action=raw_action, # type: ignore[arg-type]
|
|
22
|
+
params=opts,
|
|
23
|
+
dry_run=bool(opts.get("dry_run", False)),
|
|
24
|
+
)
|
|
25
|
+
)
|
|
26
|
+
runtime.log(f"[{result['handled_by']}] {result['action']} on {result['channel']}")
|
|
27
|
+
return MessageResult(data=result)
|
|
28
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from typing import Dict, List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@dataclass
|
|
6
|
+
class DemoConfig:
|
|
7
|
+
default_channel: str = "discord"
|
|
8
|
+
enabled_channels: List[str] = field(
|
|
9
|
+
default_factory=lambda: ["discord", "telegram", "whatsapp"]
|
|
10
|
+
)
|
|
11
|
+
bindings: Dict[str, str] = field(default_factory=dict)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def load_config() -> DemoConfig:
|
|
15
|
+
return DemoConfig()
|
|
16
|
+
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Dict, Optional
|
|
3
|
+
|
|
4
|
+
from ...channels.plugins.message_actions import dispatch_channel_message_action
|
|
5
|
+
from ...channels.plugins.types import ChannelActionContext, ChannelMessageActionName
|
|
6
|
+
from ...channels.registry import normalize_channel_id
|
|
7
|
+
from ...config import DemoConfig
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class RunMessageActionParams:
|
|
12
|
+
cfg: DemoConfig
|
|
13
|
+
action: ChannelMessageActionName
|
|
14
|
+
params: Dict[str, object]
|
|
15
|
+
default_account_id: Optional[str] = None
|
|
16
|
+
dry_run: bool = False
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _resolve_channel(cfg: DemoConfig, params: Dict[str, object]) -> str:
|
|
20
|
+
raw = params.get("channel")
|
|
21
|
+
channel = normalize_channel_id(str(raw)) if raw is not None else None
|
|
22
|
+
if channel is None:
|
|
23
|
+
channel = normalize_channel_id(cfg.default_channel)
|
|
24
|
+
if channel is None:
|
|
25
|
+
raise ValueError("No valid channel resolved.")
|
|
26
|
+
if channel not in cfg.enabled_channels:
|
|
27
|
+
raise ValueError(f"Channel {channel} is not enabled.")
|
|
28
|
+
return channel
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _normalize_target(params: Dict[str, object]) -> None:
|
|
32
|
+
target = str(params.get("target", "")).strip()
|
|
33
|
+
to = str(params.get("to", "")).strip()
|
|
34
|
+
if target and not to:
|
|
35
|
+
params["to"] = target
|
|
36
|
+
if not str(params.get("to", "")).strip():
|
|
37
|
+
raise ValueError("Action requires a target. Pass --to or --target.")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def run_message_action(input_data: RunMessageActionParams) -> dict:
|
|
41
|
+
args = dict(input_data.params)
|
|
42
|
+
channel = _resolve_channel(input_data.cfg, args)
|
|
43
|
+
|
|
44
|
+
if input_data.action in ("send", "poll", "react", "delete"):
|
|
45
|
+
_normalize_target(args)
|
|
46
|
+
|
|
47
|
+
if input_data.action == "broadcast":
|
|
48
|
+
raw_targets = args.get("targets", [])
|
|
49
|
+
if not isinstance(raw_targets, list) or not raw_targets:
|
|
50
|
+
raise ValueError("Broadcast requires non-empty --targets.")
|
|
51
|
+
if input_data.dry_run:
|
|
52
|
+
return {"kind": "broadcast", "handled_by": "dry-run", "results": raw_targets}
|
|
53
|
+
return {
|
|
54
|
+
"kind": "broadcast",
|
|
55
|
+
"handled_by": "core",
|
|
56
|
+
"results": [{"channel": channel, "to": target, "ok": True} for target in raw_targets],
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if input_data.dry_run:
|
|
60
|
+
return {
|
|
61
|
+
"kind": "action",
|
|
62
|
+
"channel": channel,
|
|
63
|
+
"action": input_data.action,
|
|
64
|
+
"handled_by": "dry-run",
|
|
65
|
+
"payload": {"ok": True},
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
handled = dispatch_channel_message_action(
|
|
69
|
+
ChannelActionContext(
|
|
70
|
+
channel=channel,
|
|
71
|
+
action=input_data.action,
|
|
72
|
+
params=args,
|
|
73
|
+
account_id=input_data.default_account_id,
|
|
74
|
+
)
|
|
75
|
+
)
|
|
76
|
+
if handled is None:
|
|
77
|
+
raise ValueError(f"No plugin registered for channel {channel}")
|
|
78
|
+
return {
|
|
79
|
+
"kind": "action",
|
|
80
|
+
"channel": channel,
|
|
81
|
+
"action": input_data.action,
|
|
82
|
+
"handled_by": "plugin",
|
|
83
|
+
"payload": handled,
|
|
84
|
+
}
|
|
85
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: jingyi
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: OpenClaw-inspired Python demo agent
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: typer<1.0,>=0.12
|
|
8
|
+
Provides-Extra: dev
|
|
9
|
+
Requires-Dist: pytest<9.0,>=8.0; extra == "dev"
|
|
10
|
+
|
|
11
|
+
# jingyi
|
|
12
|
+
|
|
13
|
+
An OpenClaw-inspired Python demo agent package.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install jingyi
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## CLI
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
jingyi health
|
|
25
|
+
jingyi status
|
|
26
|
+
jingyi message send --to channel:123 --message "hello" --channel discord
|
|
27
|
+
```
|
|
28
|
+
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
./jingyi/__init__.py
|
|
4
|
+
./jingyi/config.py
|
|
5
|
+
./jingyi/main.py
|
|
6
|
+
./jingyi/runtime.py
|
|
7
|
+
./jingyi/channels/__init__.py
|
|
8
|
+
./jingyi/channels/registry.py
|
|
9
|
+
./jingyi/channels/plugins/__init__.py
|
|
10
|
+
./jingyi/channels/plugins/discord_plugin.py
|
|
11
|
+
./jingyi/channels/plugins/message_actions.py
|
|
12
|
+
./jingyi/channels/plugins/types.py
|
|
13
|
+
./jingyi/cli/__init__.py
|
|
14
|
+
./jingyi/cli/app.py
|
|
15
|
+
./jingyi/cli/route.py
|
|
16
|
+
./jingyi/commands/__init__.py
|
|
17
|
+
./jingyi/commands/message.py
|
|
18
|
+
./jingyi/infra/__init__.py
|
|
19
|
+
./jingyi/infra/outbound/__init__.py
|
|
20
|
+
./jingyi/infra/outbound/message_action_runner.py
|
|
21
|
+
jingyi/__init__.py
|
|
22
|
+
jingyi/config.py
|
|
23
|
+
jingyi/main.py
|
|
24
|
+
jingyi/runtime.py
|
|
25
|
+
jingyi.egg-info/PKG-INFO
|
|
26
|
+
jingyi.egg-info/SOURCES.txt
|
|
27
|
+
jingyi.egg-info/dependency_links.txt
|
|
28
|
+
jingyi.egg-info/entry_points.txt
|
|
29
|
+
jingyi.egg-info/requires.txt
|
|
30
|
+
jingyi.egg-info/top_level.txt
|
|
31
|
+
jingyi/channels/__init__.py
|
|
32
|
+
jingyi/channels/registry.py
|
|
33
|
+
jingyi/channels/plugins/__init__.py
|
|
34
|
+
jingyi/channels/plugins/discord_plugin.py
|
|
35
|
+
jingyi/channels/plugins/message_actions.py
|
|
36
|
+
jingyi/channels/plugins/types.py
|
|
37
|
+
jingyi/cli/__init__.py
|
|
38
|
+
jingyi/cli/app.py
|
|
39
|
+
jingyi/cli/route.py
|
|
40
|
+
jingyi/commands/__init__.py
|
|
41
|
+
jingyi/commands/message.py
|
|
42
|
+
jingyi/infra/__init__.py
|
|
43
|
+
jingyi/infra/outbound/__init__.py
|
|
44
|
+
jingyi/infra/outbound/message_action_runner.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
jingyi
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=69", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "jingyi"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "OpenClaw-inspired Python demo agent"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"typer>=0.12,<1.0",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[project.optional-dependencies]
|
|
16
|
+
dev = [
|
|
17
|
+
"pytest>=8.0,<9.0",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[project.scripts]
|
|
21
|
+
jingyi = "jingyi.main:main"
|
|
22
|
+
|
|
23
|
+
[tool.setuptools]
|
|
24
|
+
package-dir = {"" = "."}
|
|
25
|
+
|
|
26
|
+
[tool.setuptools.packages.find]
|
|
27
|
+
where = ["."]
|
|
28
|
+
include = ["jingyi*"]
|
|
29
|
+
|
jingyi-0.1.0/setup.cfg
ADDED