agent-data-cli 0.1.0__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.
- agent_data_cli/PYPI_README.md +72 -0
- agent_data_cli/__init__.py +2 -0
- agent_data_cli/__main__.py +7 -0
- agent_data_cli/cli/__init__.py +2 -0
- agent_data_cli/cli/__main__.py +7 -0
- agent_data_cli/cli/commands/__init__.py +85 -0
- agent_data_cli/cli/commands/channel.py +78 -0
- agent_data_cli/cli/commands/common.py +97 -0
- agent_data_cli/cli/commands/config.py +270 -0
- agent_data_cli/cli/commands/content/__init__.py +29 -0
- agent_data_cli/cli/commands/content/common.py +172 -0
- agent_data_cli/cli/commands/content/interact.py +74 -0
- agent_data_cli/cli/commands/content/query.py +111 -0
- agent_data_cli/cli/commands/content/search.py +75 -0
- agent_data_cli/cli/commands/content/update.py +198 -0
- agent_data_cli/cli/commands/dashboard.py +87 -0
- agent_data_cli/cli/commands/group.py +128 -0
- agent_data_cli/cli/commands/help.py +44 -0
- agent_data_cli/cli/commands/hub.py +107 -0
- agent_data_cli/cli/commands/init.py +29 -0
- agent_data_cli/cli/commands/source.py +41 -0
- agent_data_cli/cli/commands/specs.py +241 -0
- agent_data_cli/cli/commands/sub.py +60 -0
- agent_data_cli/cli/formatters.py +537 -0
- agent_data_cli/cli/help.py +149 -0
- agent_data_cli/cli/main.py +46 -0
- agent_data_cli/core/__init__.py +2 -0
- agent_data_cli/core/base.py +222 -0
- agent_data_cli/core/capabilities.py +105 -0
- agent_data_cli/core/config.py +236 -0
- agent_data_cli/core/discovery.py +158 -0
- agent_data_cli/core/help.py +16 -0
- agent_data_cli/core/manifest.py +329 -0
- agent_data_cli/core/models.py +296 -0
- agent_data_cli/core/protocol.py +135 -0
- agent_data_cli/core/registry.py +353 -0
- agent_data_cli/core/source_defaults.py +24 -0
- agent_data_cli/dashboard/__init__.py +2 -0
- agent_data_cli/dashboard/adapters/__init__.py +2 -0
- agent_data_cli/dashboard/adapters/channel.py +73 -0
- agent_data_cli/dashboard/adapters/config.py +153 -0
- agent_data_cli/dashboard/adapters/content.py +350 -0
- agent_data_cli/dashboard/adapters/group.py +47 -0
- agent_data_cli/dashboard/adapters/help.py +32 -0
- agent_data_cli/dashboard/adapters/source.py +61 -0
- agent_data_cli/dashboard/adapters/sub.py +28 -0
- agent_data_cli/dashboard/context.py +29 -0
- agent_data_cli/dashboard/index.py +30 -0
- agent_data_cli/dashboard/pages/01_Source.py +57 -0
- agent_data_cli/dashboard/pages/02_Channel.py +99 -0
- agent_data_cli/dashboard/pages/03_Content_Search.py +64 -0
- agent_data_cli/dashboard/pages/04_Content_Query.py +79 -0
- agent_data_cli/dashboard/pages/05_Content_Update.py +103 -0
- agent_data_cli/dashboard/pages/06_Sub.py +51 -0
- agent_data_cli/dashboard/pages/07_Group.py +116 -0
- agent_data_cli/dashboard/pages/08_Config.py +114 -0
- agent_data_cli/dashboard/pages/09_Help.py +48 -0
- agent_data_cli/dashboard/pages/__init__.py +2 -0
- agent_data_cli/dashboard/runtime.py +208 -0
- agent_data_cli/dashboard/state.py +60 -0
- agent_data_cli/dashboard/widgets/__init__.py +2 -0
- agent_data_cli/dashboard/widgets/common.py +90 -0
- agent_data_cli/dashboard/widgets/forms.py +29 -0
- agent_data_cli/dashboard/widgets/tables.py +10 -0
- agent_data_cli/fetchers/__init__.py +2 -0
- agent_data_cli/fetchers/base.py +61 -0
- agent_data_cli/fetchers/browser.py +44 -0
- agent_data_cli/fetchers/http.py +313 -0
- agent_data_cli/fetchers/jina.py +44 -0
- agent_data_cli/hub/__init__.py +6 -0
- agent_data_cli/hub/models.py +20 -0
- agent_data_cli/hub/service.py +210 -0
- agent_data_cli/init_service.py +29 -0
- agent_data_cli/main.py +72 -0
- agent_data_cli/migration.py +53 -0
- agent_data_cli/runtime_paths.py +90 -0
- agent_data_cli/store/__init__.py +2 -0
- agent_data_cli/store/audit.py +42 -0
- agent_data_cli/store/channels.py +80 -0
- agent_data_cli/store/configs.py +134 -0
- agent_data_cli/store/content.py +770 -0
- agent_data_cli/store/db.py +298 -0
- agent_data_cli/store/groups.py +120 -0
- agent_data_cli/store/health.py +53 -0
- agent_data_cli/store/migrations.py +176 -0
- agent_data_cli/store/repositories.py +136 -0
- agent_data_cli/store/subscriptions.py +119 -0
- agent_data_cli/utils/__init__.py +2 -0
- agent_data_cli/utils/text.py +21 -0
- agent_data_cli/utils/time.py +63 -0
- agent_data_cli/utils/urls.py +8 -0
- agent_data_cli-0.1.0.dist-info/METADATA +104 -0
- agent_data_cli-0.1.0.dist-info/RECORD +97 -0
- agent_data_cli-0.1.0.dist-info/WHEEL +5 -0
- agent_data_cli-0.1.0.dist-info/entry_points.txt +2 -0
- agent_data_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
- agent_data_cli-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# agent-data-cli
|
|
2
|
+
|
|
3
|
+
`agent-data-cli` is a unified multi-source content CLI for discovery, sync, local query, and explicit interaction.
|
|
4
|
+
|
|
5
|
+
It is designed for agent workflows and human operators who want one stable command surface across news, RSS, social media, market data, and other content sources that fit the `source/channel/content` model.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
Recommended:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
uv tool install agent-data-cli
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
PyPA-standard CLI install:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pipx install agent-data-cli
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
If you also want the dashboard:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
uv tool install "agent-data-cli[dashboard]"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
or:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pipx install "agent-data-cli[dashboard]"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
adc init --defaults
|
|
37
|
+
adc help
|
|
38
|
+
adc source list
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`adc init` creates the local runtime home at `~/.adc`, initializes the database, and prepares the default `source_workspace`.
|
|
42
|
+
|
|
43
|
+
## Typical Flow
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
adc hub search --query xiaohongshu
|
|
47
|
+
adc hub install xiaohongshu
|
|
48
|
+
adc source list
|
|
49
|
+
adc channel search --source xiaohongshu --query 咖啡
|
|
50
|
+
adc sub add --source xiaohongshu --channel <channel>
|
|
51
|
+
adc content update --source xiaohongshu
|
|
52
|
+
adc content query --source xiaohongshu --limit 20
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Dashboard
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
adc dashboard
|
|
59
|
+
adc dashboard start --daemon
|
|
60
|
+
adc dashboard status
|
|
61
|
+
adc dashboard stop
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Python Version
|
|
65
|
+
|
|
66
|
+
- Python `3.12+`
|
|
67
|
+
|
|
68
|
+
## Links
|
|
69
|
+
|
|
70
|
+
- Source: <https://github.com/severinzhong/agent-data-cli>
|
|
71
|
+
- Issues: <https://github.com/severinzhong/agent-data-cli/issues>
|
|
72
|
+
- Companion source workspace: <https://github.com/severinzhong/agent-data-hub>
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from agent_data_cli.cli.commands.channel import CHANNEL_COMMAND
|
|
4
|
+
from agent_data_cli.cli.commands.config import CONFIG_COMMAND
|
|
5
|
+
from agent_data_cli.cli.commands.content import CONTENT_COMMAND
|
|
6
|
+
from agent_data_cli.cli.commands.dashboard import DASHBOARD_COMMAND
|
|
7
|
+
from agent_data_cli.cli.commands.group import GROUP_COMMAND
|
|
8
|
+
from agent_data_cli.cli.commands.help import make_help_command
|
|
9
|
+
from agent_data_cli.cli.commands.hub import HUB_COMMAND
|
|
10
|
+
from agent_data_cli.cli.commands.init import INIT_COMMAND
|
|
11
|
+
from agent_data_cli.cli.commands.source import SOURCE_COMMAND
|
|
12
|
+
from agent_data_cli.cli.commands.specs import (
|
|
13
|
+
CommandContext,
|
|
14
|
+
CommandNodeSpec,
|
|
15
|
+
build_command_help_doc as _build_command_help_doc,
|
|
16
|
+
build_global_help_doc as _build_global_help_doc,
|
|
17
|
+
build_root_parser,
|
|
18
|
+
dispatch_command,
|
|
19
|
+
parse_command_argv,
|
|
20
|
+
)
|
|
21
|
+
from agent_data_cli.cli.commands.sub import SUB_COMMAND
|
|
22
|
+
from agent_data_cli.core.help import HelpSection
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
_BASE_COMMANDS: tuple[CommandNodeSpec, ...] = (
|
|
26
|
+
INIT_COMMAND,
|
|
27
|
+
HUB_COMMAND,
|
|
28
|
+
SOURCE_COMMAND,
|
|
29
|
+
CHANNEL_COMMAND,
|
|
30
|
+
CONTENT_COMMAND,
|
|
31
|
+
SUB_COMMAND,
|
|
32
|
+
GROUP_COMMAND,
|
|
33
|
+
CONFIG_COMMAND,
|
|
34
|
+
DASHBOARD_COMMAND,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
GLOBAL_HELP_SECTIONS = (
|
|
38
|
+
HelpSection(
|
|
39
|
+
title="Examples",
|
|
40
|
+
lines=[
|
|
41
|
+
"init --defaults",
|
|
42
|
+
"hub search --query <query>",
|
|
43
|
+
"help content search",
|
|
44
|
+
"source list",
|
|
45
|
+
"channel search --source <source> --query <query>",
|
|
46
|
+
"content update --group <group> --dry-run",
|
|
47
|
+
"dashboard --daemon",
|
|
48
|
+
],
|
|
49
|
+
),
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
HELP_COMMAND = make_help_command(
|
|
53
|
+
build_global_help_doc=lambda: build_global_help_doc(),
|
|
54
|
+
build_command_help_doc=lambda topic: build_command_help_doc(topic),
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
ROOT_COMMANDS: tuple[CommandNodeSpec, ...] = (*_BASE_COMMANDS, HELP_COMMAND)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def build_parser():
|
|
61
|
+
return build_root_parser(ROOT_COMMANDS)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def build_global_help_doc():
|
|
65
|
+
return _build_global_help_doc(
|
|
66
|
+
title="agent-data-cli",
|
|
67
|
+
summary="Unified multi-source content CLI.",
|
|
68
|
+
commands=ROOT_COMMANDS,
|
|
69
|
+
sections=GLOBAL_HELP_SECTIONS,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def build_command_help_doc(topic: str):
|
|
74
|
+
return _build_command_help_doc(ROOT_COMMANDS, topic)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
__all__ = [
|
|
78
|
+
"CommandContext",
|
|
79
|
+
"ROOT_COMMANDS",
|
|
80
|
+
"build_command_help_doc",
|
|
81
|
+
"build_global_help_doc",
|
|
82
|
+
"build_parser",
|
|
83
|
+
"dispatch_command",
|
|
84
|
+
"parse_command_argv",
|
|
85
|
+
]
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from agent_data_cli.cli.formatters import build_channel_json_rows, print_channels, print_csv_rows, print_jsonl_rows
|
|
4
|
+
from agent_data_cli.cli.commands.common import require_action, require_option, resolve_limit
|
|
5
|
+
from agent_data_cli.cli.commands.specs import CommandArgSpec, CommandContext, CommandNodeSpec
|
|
6
|
+
from agent_data_cli.core.help import HelpSection
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _run_channel_list(args, extras: list[str], ctx: CommandContext) -> int:
|
|
10
|
+
_ = extras
|
|
11
|
+
source = ctx.registry.build(args.source)
|
|
12
|
+
require_action(ctx.registry, args.source, "channel.list")
|
|
13
|
+
print_channels(source.list_channels())
|
|
14
|
+
return 0
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _run_channel_search(args, extras: list[str], ctx: CommandContext) -> int:
|
|
18
|
+
_ = extras
|
|
19
|
+
source = ctx.registry.build(args.source)
|
|
20
|
+
require_action(ctx.registry, args.source, "channel.search")
|
|
21
|
+
require_option(ctx.registry, args.source, "channel.search", "query")
|
|
22
|
+
if args.limit is not None:
|
|
23
|
+
require_option(ctx.registry, args.source, "channel.search", "limit")
|
|
24
|
+
limit = resolve_limit(args.limit)
|
|
25
|
+
channels = source.search_channels(query=args.query, limit=limit)
|
|
26
|
+
view = source.get_channel_search_view()
|
|
27
|
+
rows = build_channel_json_rows(channels, view=view)
|
|
28
|
+
if args.jsonl:
|
|
29
|
+
print_jsonl_rows(rows)
|
|
30
|
+
return 0
|
|
31
|
+
if args.csv:
|
|
32
|
+
print_csv_rows(rows)
|
|
33
|
+
return 0
|
|
34
|
+
print_channels(channels, view=view)
|
|
35
|
+
return 0
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
CHANNEL_COMMAND = CommandNodeSpec(
|
|
39
|
+
name="channel",
|
|
40
|
+
summary="List or discover channels.",
|
|
41
|
+
child_dest="channel_command",
|
|
42
|
+
children=(
|
|
43
|
+
CommandNodeSpec(
|
|
44
|
+
name="list",
|
|
45
|
+
summary="List built-in channels for a source.",
|
|
46
|
+
arg_specs=(CommandArgSpec(names=("source",), value_name="source"),),
|
|
47
|
+
run=_run_channel_list,
|
|
48
|
+
),
|
|
49
|
+
CommandNodeSpec(
|
|
50
|
+
name="search",
|
|
51
|
+
summary="Discover remote channels without persistence.",
|
|
52
|
+
sections=(
|
|
53
|
+
HelpSection(
|
|
54
|
+
title="Semantics",
|
|
55
|
+
lines=[
|
|
56
|
+
"--source is required",
|
|
57
|
+
"--query is required",
|
|
58
|
+
"Returns channel results only and does not write to the local database",
|
|
59
|
+
],
|
|
60
|
+
),
|
|
61
|
+
HelpSection(
|
|
62
|
+
title="Examples",
|
|
63
|
+
lines=[
|
|
64
|
+
"channel search --source <source> --query <query> --limit <n>",
|
|
65
|
+
],
|
|
66
|
+
),
|
|
67
|
+
),
|
|
68
|
+
arg_specs=(
|
|
69
|
+
CommandArgSpec(names=("--source",), value_name="source", required=True),
|
|
70
|
+
CommandArgSpec(names=("--query",), value_name="query", required=True),
|
|
71
|
+
CommandArgSpec(names=("--limit",), value_name="n", type=int),
|
|
72
|
+
CommandArgSpec(names=("--jsonl",), action="store_true", exclusive_group="machine_output"),
|
|
73
|
+
CommandArgSpec(names=("--csv",), action="store_true", exclusive_group="machine_output"),
|
|
74
|
+
),
|
|
75
|
+
run=_run_channel_search,
|
|
76
|
+
),
|
|
77
|
+
),
|
|
78
|
+
)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
|
|
5
|
+
from agent_data_cli.core.models import ActionAuditRecord
|
|
6
|
+
from agent_data_cli.core.protocol import UnsupportedActionError
|
|
7
|
+
from agent_data_cli.store.db import Store
|
|
8
|
+
from agent_data_cli.utils.time import parse_since_expr, since_datetime_to_iso, utc_now_iso
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
DEFAULT_LIMIT = 20
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def require_action(registry, source_name: str, action_id: str) -> None:
|
|
15
|
+
status = registry.get_resolver(source_name).action_status(action_id)
|
|
16
|
+
if status.status == "supported":
|
|
17
|
+
return
|
|
18
|
+
if status.status == "mode_unsupported":
|
|
19
|
+
raise RuntimeError(f"{source_name} {action_id} is not supported in current mode")
|
|
20
|
+
if status.status == "requires_config":
|
|
21
|
+
raise RuntimeError(f"{source_name} {action_id} requires config: {', '.join(status.missing_keys)}")
|
|
22
|
+
raise UnsupportedActionError(f"{source_name} does not support {action_id}")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def require_option(registry, source_name: str, action_id: str, option_name: str) -> None:
|
|
26
|
+
status = registry.get_resolver(source_name).option_status(action_id, option_name)
|
|
27
|
+
if status.status == "supported":
|
|
28
|
+
return
|
|
29
|
+
if status.status == "mode_unsupported":
|
|
30
|
+
raise RuntimeError(f"{source_name} {action_id} option {option_name} is not supported in current mode")
|
|
31
|
+
if status.status == "requires_config":
|
|
32
|
+
raise RuntimeError(
|
|
33
|
+
f"{source_name} {action_id} {option_name} requires config: {', '.join(status.missing_keys)}"
|
|
34
|
+
)
|
|
35
|
+
raise RuntimeError(f"{source_name} does not support option {option_name} for {action_id}")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def resolve_limit(raw_limit: int | None) -> int:
|
|
39
|
+
return DEFAULT_LIMIT if raw_limit is None else raw_limit
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def parse_since(raw_since: str) -> datetime:
|
|
43
|
+
from agent_data_cli.cli import main as cli_main
|
|
44
|
+
|
|
45
|
+
try:
|
|
46
|
+
return cli_main.parse_since_expr(raw_since)
|
|
47
|
+
except ValueError as exc:
|
|
48
|
+
raise RuntimeError(f"invalid --since value: {raw_since}") from exc
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def write_audit(
|
|
52
|
+
store: Store,
|
|
53
|
+
source,
|
|
54
|
+
*,
|
|
55
|
+
action: str,
|
|
56
|
+
target_kind: str,
|
|
57
|
+
targets: tuple[str, ...],
|
|
58
|
+
dry_run: bool,
|
|
59
|
+
params_summary: str,
|
|
60
|
+
status: str,
|
|
61
|
+
error: str | None,
|
|
62
|
+
) -> None:
|
|
63
|
+
store.insert_action_audit(
|
|
64
|
+
ActionAuditRecord(
|
|
65
|
+
executed_at=utc_now_iso(),
|
|
66
|
+
action=action,
|
|
67
|
+
source=source.name,
|
|
68
|
+
mode=source.resolve_mode() or None,
|
|
69
|
+
target_kind=target_kind,
|
|
70
|
+
targets=targets,
|
|
71
|
+
params_summary=params_summary,
|
|
72
|
+
status=status,
|
|
73
|
+
error=error,
|
|
74
|
+
dry_run=dry_run,
|
|
75
|
+
)
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def summarize_update_params(*, limit: int | None, since: datetime | None, fetch_all: bool) -> str:
|
|
80
|
+
parts = []
|
|
81
|
+
if limit is not None:
|
|
82
|
+
parts.append(f"limit={limit}")
|
|
83
|
+
if since is not None:
|
|
84
|
+
parts.append(f"since={since_datetime_to_iso(since)}")
|
|
85
|
+
if fetch_all:
|
|
86
|
+
parts.append("all=1")
|
|
87
|
+
return ",".join(parts)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def summarize_interact_params(verb: str, params: dict[str, object]) -> str:
|
|
91
|
+
parts = [f"verb={verb}"]
|
|
92
|
+
for key in sorted(params):
|
|
93
|
+
value = params[key]
|
|
94
|
+
if value in (None, False, [], ""):
|
|
95
|
+
continue
|
|
96
|
+
parts.append(f"{key}={value}")
|
|
97
|
+
return ",".join(parts)
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from agent_data_cli.cli.formatters import print_cli_config_entries, print_config_check, print_config_entries
|
|
4
|
+
from agent_data_cli.cli.commands.specs import CommandArgSpec, CommandContext, CommandNodeSpec
|
|
5
|
+
from agent_data_cli.core.config import validate_config_value
|
|
6
|
+
from agent_data_cli.core.help import HelpSection
|
|
7
|
+
from agent_data_cli.core.manifest import CORE_ACTION_NAMES, SOURCE_ACTION_NAMES
|
|
8
|
+
from agent_data_cli.migration import migrate_home, migrate_source_workspace
|
|
9
|
+
from agent_data_cli.runtime_paths import RuntimePaths, resolve_runtime_paths
|
|
10
|
+
from agent_data_cli.store.db import Store
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
CONFIG_CHECK_ACTION_IDS = CORE_ACTION_NAMES | SOURCE_ACTION_NAMES
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _run_config_cli_list(args, extras: list[str], ctx: CommandContext) -> int:
|
|
17
|
+
_ = args, extras
|
|
18
|
+
_print_cli_config_entries(ctx)
|
|
19
|
+
return 0
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _run_config_cli_set(args, extras: list[str], ctx: CommandContext) -> int:
|
|
23
|
+
_ = extras
|
|
24
|
+
spec = ctx.registry.get_cli_config_field_spec(args.key)
|
|
25
|
+
validate_config_value(spec, args.value, owner="cli")
|
|
26
|
+
current_paths = _resolve_active_runtime_paths(ctx)
|
|
27
|
+
if args.key == "home":
|
|
28
|
+
migrated_paths = migrate_home(current_paths, args.value)
|
|
29
|
+
_print_cli_config_entries_with_paths(ctx, migrated_paths)
|
|
30
|
+
return 0
|
|
31
|
+
if args.key == "source_workspace":
|
|
32
|
+
migrated_paths = migrate_source_workspace(current_paths, args.value)
|
|
33
|
+
_print_cli_config_entries_with_paths(ctx, migrated_paths)
|
|
34
|
+
return 0
|
|
35
|
+
ctx.store.set_cli_config(args.key, args.value, spec.type, spec.secret)
|
|
36
|
+
_print_cli_config_entries_with_paths(ctx, current_paths)
|
|
37
|
+
return 0
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _run_config_cli_unset(args, extras: list[str], ctx: CommandContext) -> int:
|
|
41
|
+
_ = extras
|
|
42
|
+
ctx.store.unset_cli_config(args.key)
|
|
43
|
+
_print_cli_config_entries_with_paths(ctx, _resolve_active_runtime_paths(ctx))
|
|
44
|
+
return 0
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _run_config_cli_explain(args, extras: list[str], ctx: CommandContext) -> int:
|
|
48
|
+
_ = extras
|
|
49
|
+
_print_config_explain("cli", ctx.registry.get_cli_config_field_spec(args.key))
|
|
50
|
+
return 0
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _run_config_source_list(args, extras: list[str], ctx: CommandContext) -> int:
|
|
54
|
+
_ = extras
|
|
55
|
+
print_config_entries(ctx.store.list_source_configs(args.source))
|
|
56
|
+
return 0
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _run_config_source_set(args, extras: list[str], ctx: CommandContext) -> int:
|
|
60
|
+
_ = extras
|
|
61
|
+
spec = ctx.registry.get_source_config_field_spec(args.source, args.key)
|
|
62
|
+
validate_config_value(spec, args.value, owner=args.source)
|
|
63
|
+
ctx.store.set_source_config(args.source, args.key, args.value, spec.type, spec.secret)
|
|
64
|
+
print_config_entries(ctx.store.list_source_configs(args.source))
|
|
65
|
+
return 0
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _run_config_source_unset(args, extras: list[str], ctx: CommandContext) -> int:
|
|
69
|
+
_ = extras
|
|
70
|
+
ctx.store.unset_source_config(args.source, args.key)
|
|
71
|
+
print_config_entries(ctx.store.list_source_configs(args.source))
|
|
72
|
+
return 0
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _run_config_source_explain(args, extras: list[str], ctx: CommandContext) -> int:
|
|
76
|
+
_ = extras
|
|
77
|
+
_print_config_explain(args.source, ctx.registry.get_source_config_field_spec(args.source, args.key))
|
|
78
|
+
return 0
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _run_config_source_check(args, extras: list[str], ctx: CommandContext) -> int:
|
|
82
|
+
_ = extras
|
|
83
|
+
_validate_config_check_action_id(args.action_id)
|
|
84
|
+
if args.action_id == "content.interact" and not args.verb:
|
|
85
|
+
raise RuntimeError("config source check --for content.interact requires --verb")
|
|
86
|
+
print_config_check(ctx.registry.config_check(args.source, action_id=args.action_id, verb=args.verb))
|
|
87
|
+
return 0
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _print_config_explain(owner: str, spec) -> None:
|
|
91
|
+
print(f"{owner}.{spec.key}")
|
|
92
|
+
print(f"type: {spec.type}")
|
|
93
|
+
print(f"secret: {int(spec.secret)}")
|
|
94
|
+
print(f"description: {spec.description}")
|
|
95
|
+
if spec.inherits_from_cli:
|
|
96
|
+
print(f"inherits_from_cli: {spec.inherits_from_cli}")
|
|
97
|
+
if spec.choices:
|
|
98
|
+
print(f"choices: {', '.join(spec.choices)}")
|
|
99
|
+
if spec.obtain_hint:
|
|
100
|
+
print(f"obtain_hint: {spec.obtain_hint}")
|
|
101
|
+
if spec.example:
|
|
102
|
+
print(f"example: {spec.example}")
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _print_cli_config_entries(ctx: CommandContext) -> None:
|
|
106
|
+
_print_cli_config_entries_with_paths(ctx, _resolve_active_runtime_paths(ctx))
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _print_cli_config_entries_with_paths(ctx: CommandContext, paths: RuntimePaths) -> None:
|
|
110
|
+
store = ctx.store
|
|
111
|
+
if str(paths.db_path) != getattr(ctx.store, "path", "") and paths.db_path.exists():
|
|
112
|
+
store = Store(str(paths.db_path))
|
|
113
|
+
defaults_by_key = {
|
|
114
|
+
spec.key: ctx.registry.get_cli_config_default(spec.key)
|
|
115
|
+
for spec in ctx.registry.get_cli_config_specs()
|
|
116
|
+
}
|
|
117
|
+
defaults_by_key["home"] = str(paths.home)
|
|
118
|
+
defaults_by_key["source_workspace"] = str(paths.source_workspace)
|
|
119
|
+
print_cli_config_entries(
|
|
120
|
+
ctx.registry.get_cli_config_specs(),
|
|
121
|
+
store.list_cli_configs(),
|
|
122
|
+
defaults_by_key,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _resolve_active_runtime_paths(ctx: CommandContext) -> RuntimePaths:
|
|
127
|
+
paths = resolve_runtime_paths()
|
|
128
|
+
source_workspace_entry = ctx.store.get_cli_config_map().get("source_workspace")
|
|
129
|
+
if source_workspace_entry is None:
|
|
130
|
+
return paths
|
|
131
|
+
return RuntimePaths(
|
|
132
|
+
home=paths.home,
|
|
133
|
+
db_path=paths.db_path,
|
|
134
|
+
source_workspace=resolve_runtime_paths(source_workspace_override=source_workspace_entry.value).source_workspace,
|
|
135
|
+
runtime_dir=paths.runtime_dir,
|
|
136
|
+
launcher_path=paths.launcher_path,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def _validate_config_check_action_id(action_id: str | None) -> None:
|
|
141
|
+
if action_id is None:
|
|
142
|
+
return
|
|
143
|
+
if action_id not in CONFIG_CHECK_ACTION_IDS:
|
|
144
|
+
raise RuntimeError(f"unknown action id: {action_id}")
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
CONFIG_COMMAND = CommandNodeSpec(
|
|
148
|
+
name="config",
|
|
149
|
+
summary="Inspect and modify CLI or source configuration.",
|
|
150
|
+
sections=(
|
|
151
|
+
HelpSection(
|
|
152
|
+
title="Scopes",
|
|
153
|
+
lines=[
|
|
154
|
+
"config cli ... manages ADC-level settings",
|
|
155
|
+
"config source ... manages one source's settings",
|
|
156
|
+
],
|
|
157
|
+
),
|
|
158
|
+
HelpSection(
|
|
159
|
+
title="Common Commands",
|
|
160
|
+
lines=[
|
|
161
|
+
"config cli list",
|
|
162
|
+
"config cli explain <key>",
|
|
163
|
+
"config cli set <key> <value>",
|
|
164
|
+
"config cli unset <key>",
|
|
165
|
+
"config source list <source>",
|
|
166
|
+
"config source explain <source> <key>",
|
|
167
|
+
"config source set <source> <key> <value>",
|
|
168
|
+
"config source unset <source> <key>",
|
|
169
|
+
"config source check <source> [--for <action-id>] [--verb <verb>]",
|
|
170
|
+
],
|
|
171
|
+
),
|
|
172
|
+
HelpSection(
|
|
173
|
+
title="Typical Flow",
|
|
174
|
+
lines=[
|
|
175
|
+
"List current values first",
|
|
176
|
+
"Use explain before setting a key you do not recognize",
|
|
177
|
+
"Set the value",
|
|
178
|
+
"Run config source check when a source action still says it requires config",
|
|
179
|
+
],
|
|
180
|
+
),
|
|
181
|
+
),
|
|
182
|
+
child_dest="config_scope",
|
|
183
|
+
children=(
|
|
184
|
+
CommandNodeSpec(
|
|
185
|
+
name="cli",
|
|
186
|
+
summary="Manage CLI-level configuration.",
|
|
187
|
+
child_dest="config_command",
|
|
188
|
+
children=(
|
|
189
|
+
CommandNodeSpec(
|
|
190
|
+
name="list",
|
|
191
|
+
summary="List CLI configuration.",
|
|
192
|
+
run=_run_config_cli_list,
|
|
193
|
+
),
|
|
194
|
+
CommandNodeSpec(
|
|
195
|
+
name="set",
|
|
196
|
+
summary="Set a CLI configuration value.",
|
|
197
|
+
arg_specs=(
|
|
198
|
+
CommandArgSpec(names=("key",), value_name="key"),
|
|
199
|
+
CommandArgSpec(names=("value",), value_name="value"),
|
|
200
|
+
),
|
|
201
|
+
run=_run_config_cli_set,
|
|
202
|
+
),
|
|
203
|
+
CommandNodeSpec(
|
|
204
|
+
name="unset",
|
|
205
|
+
summary="Unset a CLI configuration value.",
|
|
206
|
+
arg_specs=(CommandArgSpec(names=("key",), value_name="key"),),
|
|
207
|
+
run=_run_config_cli_unset,
|
|
208
|
+
),
|
|
209
|
+
CommandNodeSpec(
|
|
210
|
+
name="explain",
|
|
211
|
+
summary="Explain a CLI configuration field.",
|
|
212
|
+
arg_specs=(CommandArgSpec(names=("key",), value_name="key"),),
|
|
213
|
+
run=_run_config_cli_explain,
|
|
214
|
+
),
|
|
215
|
+
),
|
|
216
|
+
),
|
|
217
|
+
CommandNodeSpec(
|
|
218
|
+
name="source",
|
|
219
|
+
summary="Manage source configuration.",
|
|
220
|
+
child_dest="config_command",
|
|
221
|
+
children=(
|
|
222
|
+
CommandNodeSpec(
|
|
223
|
+
name="list",
|
|
224
|
+
summary="List configuration for a source.",
|
|
225
|
+
arg_specs=(CommandArgSpec(names=("source",), value_name="source"),),
|
|
226
|
+
run=_run_config_source_list,
|
|
227
|
+
),
|
|
228
|
+
CommandNodeSpec(
|
|
229
|
+
name="set",
|
|
230
|
+
summary="Set a source configuration value.",
|
|
231
|
+
arg_specs=(
|
|
232
|
+
CommandArgSpec(names=("source",), value_name="source"),
|
|
233
|
+
CommandArgSpec(names=("key",), value_name="key"),
|
|
234
|
+
CommandArgSpec(names=("value",), value_name="value"),
|
|
235
|
+
),
|
|
236
|
+
run=_run_config_source_set,
|
|
237
|
+
),
|
|
238
|
+
CommandNodeSpec(
|
|
239
|
+
name="unset",
|
|
240
|
+
summary="Unset a source configuration value.",
|
|
241
|
+
arg_specs=(
|
|
242
|
+
CommandArgSpec(names=("source",), value_name="source"),
|
|
243
|
+
CommandArgSpec(names=("key",), value_name="key"),
|
|
244
|
+
),
|
|
245
|
+
run=_run_config_source_unset,
|
|
246
|
+
),
|
|
247
|
+
CommandNodeSpec(
|
|
248
|
+
name="explain",
|
|
249
|
+
summary="Explain a source configuration field.",
|
|
250
|
+
arg_specs=(
|
|
251
|
+
CommandArgSpec(names=("source",), value_name="source"),
|
|
252
|
+
CommandArgSpec(names=("key",), value_name="key"),
|
|
253
|
+
),
|
|
254
|
+
run=_run_config_source_explain,
|
|
255
|
+
),
|
|
256
|
+
CommandNodeSpec(
|
|
257
|
+
name="check",
|
|
258
|
+
summary="Check configuration status for a source.",
|
|
259
|
+
usage_override="config source check <source> [--for <action-id>] [--verb <verb>]",
|
|
260
|
+
arg_specs=(
|
|
261
|
+
CommandArgSpec(names=("source",), value_name="source"),
|
|
262
|
+
CommandArgSpec(names=("--for",), value_name="action-id", dest="action_id"),
|
|
263
|
+
CommandArgSpec(names=("--verb",), value_name="verb"),
|
|
264
|
+
),
|
|
265
|
+
run=_run_config_source_check,
|
|
266
|
+
),
|
|
267
|
+
),
|
|
268
|
+
),
|
|
269
|
+
),
|
|
270
|
+
)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from agent_data_cli.cli.commands.content.interact import CONTENT_INTERACT_COMMAND, run_content_interact
|
|
4
|
+
from agent_data_cli.cli.commands.content.query import CONTENT_QUERY_COMMAND, run_content_query
|
|
5
|
+
from agent_data_cli.cli.commands.content.search import CONTENT_SEARCH_COMMAND, run_content_search
|
|
6
|
+
from agent_data_cli.cli.commands.content.update import CONTENT_UPDATE_COMMAND, run_content_update
|
|
7
|
+
from agent_data_cli.cli.commands.specs import CommandNodeSpec
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
CONTENT_COMMAND = CommandNodeSpec(
|
|
11
|
+
name="content",
|
|
12
|
+
summary="Unified content operations.",
|
|
13
|
+
child_dest="content_command",
|
|
14
|
+
children=(
|
|
15
|
+
CONTENT_SEARCH_COMMAND,
|
|
16
|
+
CONTENT_UPDATE_COMMAND,
|
|
17
|
+
CONTENT_QUERY_COMMAND,
|
|
18
|
+
CONTENT_INTERACT_COMMAND,
|
|
19
|
+
),
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
"CONTENT_COMMAND",
|
|
25
|
+
"run_content_interact",
|
|
26
|
+
"run_content_query",
|
|
27
|
+
"run_content_search",
|
|
28
|
+
"run_content_update",
|
|
29
|
+
]
|