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.
Files changed (97) hide show
  1. agent_data_cli/PYPI_README.md +72 -0
  2. agent_data_cli/__init__.py +2 -0
  3. agent_data_cli/__main__.py +7 -0
  4. agent_data_cli/cli/__init__.py +2 -0
  5. agent_data_cli/cli/__main__.py +7 -0
  6. agent_data_cli/cli/commands/__init__.py +85 -0
  7. agent_data_cli/cli/commands/channel.py +78 -0
  8. agent_data_cli/cli/commands/common.py +97 -0
  9. agent_data_cli/cli/commands/config.py +270 -0
  10. agent_data_cli/cli/commands/content/__init__.py +29 -0
  11. agent_data_cli/cli/commands/content/common.py +172 -0
  12. agent_data_cli/cli/commands/content/interact.py +74 -0
  13. agent_data_cli/cli/commands/content/query.py +111 -0
  14. agent_data_cli/cli/commands/content/search.py +75 -0
  15. agent_data_cli/cli/commands/content/update.py +198 -0
  16. agent_data_cli/cli/commands/dashboard.py +87 -0
  17. agent_data_cli/cli/commands/group.py +128 -0
  18. agent_data_cli/cli/commands/help.py +44 -0
  19. agent_data_cli/cli/commands/hub.py +107 -0
  20. agent_data_cli/cli/commands/init.py +29 -0
  21. agent_data_cli/cli/commands/source.py +41 -0
  22. agent_data_cli/cli/commands/specs.py +241 -0
  23. agent_data_cli/cli/commands/sub.py +60 -0
  24. agent_data_cli/cli/formatters.py +537 -0
  25. agent_data_cli/cli/help.py +149 -0
  26. agent_data_cli/cli/main.py +46 -0
  27. agent_data_cli/core/__init__.py +2 -0
  28. agent_data_cli/core/base.py +222 -0
  29. agent_data_cli/core/capabilities.py +105 -0
  30. agent_data_cli/core/config.py +236 -0
  31. agent_data_cli/core/discovery.py +158 -0
  32. agent_data_cli/core/help.py +16 -0
  33. agent_data_cli/core/manifest.py +329 -0
  34. agent_data_cli/core/models.py +296 -0
  35. agent_data_cli/core/protocol.py +135 -0
  36. agent_data_cli/core/registry.py +353 -0
  37. agent_data_cli/core/source_defaults.py +24 -0
  38. agent_data_cli/dashboard/__init__.py +2 -0
  39. agent_data_cli/dashboard/adapters/__init__.py +2 -0
  40. agent_data_cli/dashboard/adapters/channel.py +73 -0
  41. agent_data_cli/dashboard/adapters/config.py +153 -0
  42. agent_data_cli/dashboard/adapters/content.py +350 -0
  43. agent_data_cli/dashboard/adapters/group.py +47 -0
  44. agent_data_cli/dashboard/adapters/help.py +32 -0
  45. agent_data_cli/dashboard/adapters/source.py +61 -0
  46. agent_data_cli/dashboard/adapters/sub.py +28 -0
  47. agent_data_cli/dashboard/context.py +29 -0
  48. agent_data_cli/dashboard/index.py +30 -0
  49. agent_data_cli/dashboard/pages/01_Source.py +57 -0
  50. agent_data_cli/dashboard/pages/02_Channel.py +99 -0
  51. agent_data_cli/dashboard/pages/03_Content_Search.py +64 -0
  52. agent_data_cli/dashboard/pages/04_Content_Query.py +79 -0
  53. agent_data_cli/dashboard/pages/05_Content_Update.py +103 -0
  54. agent_data_cli/dashboard/pages/06_Sub.py +51 -0
  55. agent_data_cli/dashboard/pages/07_Group.py +116 -0
  56. agent_data_cli/dashboard/pages/08_Config.py +114 -0
  57. agent_data_cli/dashboard/pages/09_Help.py +48 -0
  58. agent_data_cli/dashboard/pages/__init__.py +2 -0
  59. agent_data_cli/dashboard/runtime.py +208 -0
  60. agent_data_cli/dashboard/state.py +60 -0
  61. agent_data_cli/dashboard/widgets/__init__.py +2 -0
  62. agent_data_cli/dashboard/widgets/common.py +90 -0
  63. agent_data_cli/dashboard/widgets/forms.py +29 -0
  64. agent_data_cli/dashboard/widgets/tables.py +10 -0
  65. agent_data_cli/fetchers/__init__.py +2 -0
  66. agent_data_cli/fetchers/base.py +61 -0
  67. agent_data_cli/fetchers/browser.py +44 -0
  68. agent_data_cli/fetchers/http.py +313 -0
  69. agent_data_cli/fetchers/jina.py +44 -0
  70. agent_data_cli/hub/__init__.py +6 -0
  71. agent_data_cli/hub/models.py +20 -0
  72. agent_data_cli/hub/service.py +210 -0
  73. agent_data_cli/init_service.py +29 -0
  74. agent_data_cli/main.py +72 -0
  75. agent_data_cli/migration.py +53 -0
  76. agent_data_cli/runtime_paths.py +90 -0
  77. agent_data_cli/store/__init__.py +2 -0
  78. agent_data_cli/store/audit.py +42 -0
  79. agent_data_cli/store/channels.py +80 -0
  80. agent_data_cli/store/configs.py +134 -0
  81. agent_data_cli/store/content.py +770 -0
  82. agent_data_cli/store/db.py +298 -0
  83. agent_data_cli/store/groups.py +120 -0
  84. agent_data_cli/store/health.py +53 -0
  85. agent_data_cli/store/migrations.py +176 -0
  86. agent_data_cli/store/repositories.py +136 -0
  87. agent_data_cli/store/subscriptions.py +119 -0
  88. agent_data_cli/utils/__init__.py +2 -0
  89. agent_data_cli/utils/text.py +21 -0
  90. agent_data_cli/utils/time.py +63 -0
  91. agent_data_cli/utils/urls.py +8 -0
  92. agent_data_cli-0.1.0.dist-info/METADATA +104 -0
  93. agent_data_cli-0.1.0.dist-info/RECORD +97 -0
  94. agent_data_cli-0.1.0.dist-info/WHEEL +5 -0
  95. agent_data_cli-0.1.0.dist-info/entry_points.txt +2 -0
  96. agent_data_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
  97. 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,2 @@
1
+ from __future__ import annotations
2
+
@@ -0,0 +1,7 @@
1
+ from __future__ import annotations
2
+
3
+ from .main import console_main
4
+
5
+
6
+ if __name__ == "__main__":
7
+ console_main()
@@ -0,0 +1,2 @@
1
+ from __future__ import annotations
2
+
@@ -0,0 +1,7 @@
1
+ from __future__ import annotations
2
+
3
+ from .main import console_main
4
+
5
+
6
+ if __name__ == "__main__":
7
+ console_main()
@@ -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
+ ]