better-notion 1.5.5__py3-none-any.whl → 1.6.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.
- better_notion/_cli/docs/__init__.py +20 -0
- better_notion/_cli/docs/base.py +204 -0
- better_notion/_cli/docs/formatters.py +128 -0
- better_notion/_cli/docs/registry.py +82 -0
- better_notion/_cli/main.py +167 -0
- better_notion/_cli/response.py +64 -8
- better_notion/plugins/official/agents.py +156 -0
- better_notion/plugins/official/agents_schema.py +369 -0
- {better_notion-1.5.5.dist-info → better_notion-1.6.0.dist-info}/METADATA +1 -1
- {better_notion-1.5.5.dist-info → better_notion-1.6.0.dist-info}/RECORD +13 -8
- {better_notion-1.5.5.dist-info → better_notion-1.6.0.dist-info}/WHEEL +0 -0
- {better_notion-1.5.5.dist-info → better_notion-1.6.0.dist-info}/entry_points.txt +0 -0
- {better_notion-1.5.5.dist-info → better_notion-1.6.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Documentation system for AI agents.
|
|
2
|
+
|
|
3
|
+
This module provides infrastructure for documenting CLI commands
|
|
4
|
+
in a machine-readable format that AI agents can consume to understand
|
|
5
|
+
the system at a high level of abstraction.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from better_notion._cli.docs.base import (
|
|
9
|
+
Command,
|
|
10
|
+
Concept,
|
|
11
|
+
Schema,
|
|
12
|
+
Workflow,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"Schema",
|
|
17
|
+
"Concept",
|
|
18
|
+
"Workflow",
|
|
19
|
+
"Command",
|
|
20
|
+
]
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"""Base classes for documentation system.
|
|
2
|
+
|
|
3
|
+
This module provides the core data structures for documenting
|
|
4
|
+
CLI commands and workflows in a machine-readable format.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class Concept:
|
|
13
|
+
"""A concept represents a high-level idea in the system.
|
|
14
|
+
|
|
15
|
+
Concepts help AI agents understand what things are
|
|
16
|
+
(e.g., "workspace", "task", "version") beyond just
|
|
17
|
+
command syntax.
|
|
18
|
+
|
|
19
|
+
Attributes:
|
|
20
|
+
name: Name of the concept
|
|
21
|
+
description: Human-readable description
|
|
22
|
+
properties: Dict of concept properties and their meanings
|
|
23
|
+
relationships: Relationships to other concepts
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
name: str
|
|
27
|
+
description: str
|
|
28
|
+
properties: dict[str, Any] = field(default_factory=dict)
|
|
29
|
+
relationships: dict[str, str] = field(default_factory=dict)
|
|
30
|
+
|
|
31
|
+
def to_dict(self) -> dict[str, Any]:
|
|
32
|
+
"""Convert to dictionary for JSON serialization."""
|
|
33
|
+
return {
|
|
34
|
+
"name": self.name,
|
|
35
|
+
"description": self.description,
|
|
36
|
+
"properties": self.properties,
|
|
37
|
+
"relationships": self.relationships,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass
|
|
42
|
+
class WorkflowStep:
|
|
43
|
+
"""A single step in a workflow.
|
|
44
|
+
|
|
45
|
+
Attributes:
|
|
46
|
+
description: What this step does
|
|
47
|
+
command: Optional command to execute
|
|
48
|
+
purpose: Why this step is needed
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
description: str
|
|
52
|
+
command: str | None = None
|
|
53
|
+
purpose: str | None = None
|
|
54
|
+
|
|
55
|
+
def to_dict(self) -> dict[str, Any]:
|
|
56
|
+
"""Convert to dictionary for JSON serialization."""
|
|
57
|
+
return {
|
|
58
|
+
"description": self.description,
|
|
59
|
+
"command": self.command,
|
|
60
|
+
"purpose": self.purpose,
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@dataclass
|
|
65
|
+
class ErrorRecovery:
|
|
66
|
+
"""Error recovery strategy for a command.
|
|
67
|
+
|
|
68
|
+
Attributes:
|
|
69
|
+
error_type: Type of error (e.g., "workspace_exists")
|
|
70
|
+
message: Human-readable error message
|
|
71
|
+
solutions: List of possible solutions with flags/actions
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
error_type: str
|
|
75
|
+
message: str
|
|
76
|
+
solutions: list[dict[str, Any]] = field(default_factory=list)
|
|
77
|
+
|
|
78
|
+
def to_dict(self) -> dict[str, Any]:
|
|
79
|
+
"""Convert to dictionary for JSON serialization."""
|
|
80
|
+
return {
|
|
81
|
+
"error_type": self.error_type,
|
|
82
|
+
"message": self.message,
|
|
83
|
+
"solutions": self.solutions,
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@dataclass
|
|
88
|
+
class Workflow:
|
|
89
|
+
"""A workflow represents a sequence of operations.
|
|
90
|
+
|
|
91
|
+
Workflows help AI agents understand how to accomplish
|
|
92
|
+
high-level goals (e.g., "initialize_workspace",
|
|
93
|
+
"create_task").
|
|
94
|
+
|
|
95
|
+
Attributes:
|
|
96
|
+
name: Workflow name
|
|
97
|
+
description: What this workflow accomplishes
|
|
98
|
+
steps: List of steps in the workflow
|
|
99
|
+
commands: Example commands for this workflow
|
|
100
|
+
prerequisites: Required conditions before starting
|
|
101
|
+
error_recovery: Error handling strategies
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
name: str
|
|
105
|
+
description: str
|
|
106
|
+
steps: list[WorkflowStep | dict[str, Any]] = field(default_factory=list)
|
|
107
|
+
commands: list[str] = field(default_factory=list)
|
|
108
|
+
prerequisites: list[str] = field(default_factory=list)
|
|
109
|
+
error_recovery: dict[str, dict[str, Any]] = field(default_factory=dict)
|
|
110
|
+
|
|
111
|
+
def to_dict(self) -> dict[str, Any]:
|
|
112
|
+
"""Convert to dictionary for JSON serialization."""
|
|
113
|
+
return {
|
|
114
|
+
"name": self.name,
|
|
115
|
+
"description": self.description,
|
|
116
|
+
"steps": [
|
|
117
|
+
step.to_dict() if isinstance(step, WorkflowStep) else step
|
|
118
|
+
for step in self.steps
|
|
119
|
+
],
|
|
120
|
+
"commands": self.commands,
|
|
121
|
+
"prerequisites": self.prerequisites,
|
|
122
|
+
"error_recovery": self.error_recovery,
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@dataclass
|
|
127
|
+
class Command:
|
|
128
|
+
"""Documentation for a single command.
|
|
129
|
+
|
|
130
|
+
Command docs go beyond --help text to provide semantic
|
|
131
|
+
meaning and workflow context.
|
|
132
|
+
|
|
133
|
+
Attributes:
|
|
134
|
+
name: Command name
|
|
135
|
+
purpose: What this command does (semantic meaning)
|
|
136
|
+
description: Detailed description
|
|
137
|
+
flags: Dict of flag -> purpose
|
|
138
|
+
workflow: Which workflow this command belongs to
|
|
139
|
+
when_to_use: When this command should be used
|
|
140
|
+
error_recovery: Error handling strategies
|
|
141
|
+
"""
|
|
142
|
+
|
|
143
|
+
name: str
|
|
144
|
+
purpose: str
|
|
145
|
+
description: str = ""
|
|
146
|
+
flags: dict[str, str] = field(default_factory=dict)
|
|
147
|
+
workflow: str | None = None
|
|
148
|
+
when_to_use: list[str] = field(default_factory=list)
|
|
149
|
+
error_recovery: dict[str, dict[str, Any]] = field(default_factory=dict)
|
|
150
|
+
|
|
151
|
+
def to_dict(self) -> dict[str, Any]:
|
|
152
|
+
"""Convert to dictionary for JSON serialization."""
|
|
153
|
+
return {
|
|
154
|
+
"name": self.name,
|
|
155
|
+
"purpose": self.purpose,
|
|
156
|
+
"description": self.description,
|
|
157
|
+
"flags": self.flags,
|
|
158
|
+
"workflow": self.workflow,
|
|
159
|
+
"when_to_use": self.when_to_use,
|
|
160
|
+
"error_recovery": self.error_recovery,
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
@dataclass
|
|
165
|
+
class Schema:
|
|
166
|
+
"""Complete schema documentation for a plugin.
|
|
167
|
+
|
|
168
|
+
A Schema provides everything an AI agent needs to understand
|
|
169
|
+
a plugin system at a high level.
|
|
170
|
+
|
|
171
|
+
Attributes:
|
|
172
|
+
name: Plugin name
|
|
173
|
+
version: Schema version
|
|
174
|
+
description: Plugin description
|
|
175
|
+
concepts: High-level concepts in the system
|
|
176
|
+
workflows: Available workflows
|
|
177
|
+
commands: Command documentation
|
|
178
|
+
best_practices: Recommended usage patterns
|
|
179
|
+
examples: Usage examples
|
|
180
|
+
"""
|
|
181
|
+
|
|
182
|
+
name: str
|
|
183
|
+
version: str
|
|
184
|
+
description: str
|
|
185
|
+
concepts: list[Concept] = field(default_factory=list)
|
|
186
|
+
workflows: list[Workflow] = field(default_factory=list)
|
|
187
|
+
commands: dict[str, Command] = field(default_factory=dict)
|
|
188
|
+
best_practices: list[str] = field(default_factory=list)
|
|
189
|
+
examples: dict[str, str] = field(default_factory=dict)
|
|
190
|
+
|
|
191
|
+
def to_dict(self) -> dict[str, Any]:
|
|
192
|
+
"""Convert to dictionary for JSON serialization."""
|
|
193
|
+
return {
|
|
194
|
+
"name": self.name,
|
|
195
|
+
"version": self.version,
|
|
196
|
+
"description": self.description,
|
|
197
|
+
"concepts": [concept.to_dict() for concept in self.concepts],
|
|
198
|
+
"workflows": [workflow.to_dict() for workflow in self.workflows],
|
|
199
|
+
"commands": {
|
|
200
|
+
name: command.to_dict() for name, command in self.commands.items()
|
|
201
|
+
},
|
|
202
|
+
"best_practices": self.best_practices,
|
|
203
|
+
"examples": self.examples,
|
|
204
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""Formatters for schema documentation.
|
|
2
|
+
|
|
3
|
+
This module provides utilities to format Schema objects
|
|
4
|
+
into different output formats (JSON, YAML).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from better_notion._cli.docs.base import Schema
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def format_schema_json(schema: Schema, *, pretty: bool = True) -> str:
|
|
14
|
+
"""Format a Schema as JSON.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
schema: Schema object to format
|
|
18
|
+
pretty: Whether to pretty-print with indentation
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
JSON string representation of the schema
|
|
22
|
+
"""
|
|
23
|
+
schema_dict = schema.to_dict()
|
|
24
|
+
if pretty:
|
|
25
|
+
return json.dumps(schema_dict, indent=2)
|
|
26
|
+
return json.dumps(schema_dict)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def format_schema_yaml(schema: Schema) -> str:
|
|
30
|
+
"""Format a Schema as YAML.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
schema: Schema object to format
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
YAML string representation of the schema
|
|
37
|
+
"""
|
|
38
|
+
try:
|
|
39
|
+
import yaml
|
|
40
|
+
|
|
41
|
+
return yaml.dump(schema.to_dict(), default_flow_style=False)
|
|
42
|
+
except ImportError:
|
|
43
|
+
# Fall back to JSON if pyyaml not installed
|
|
44
|
+
logger = __import__("logging").getLogger(__name__)
|
|
45
|
+
logger.warning("PyYAML not installed, falling back to JSON")
|
|
46
|
+
return format_schema_json(schema)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def format_schema_pretty(schema: Schema) -> str:
|
|
50
|
+
"""Format a Schema as human-readable text with sections.
|
|
51
|
+
|
|
52
|
+
This provides a more readable format for human consumption
|
|
53
|
+
while maintaining machine-parsable structure.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
schema: Schema object to format
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
Formatted text string
|
|
60
|
+
"""
|
|
61
|
+
lines = []
|
|
62
|
+
data = schema.to_dict()
|
|
63
|
+
|
|
64
|
+
# Header
|
|
65
|
+
lines.append(f"# {schema.name.upper()} SCHEMA")
|
|
66
|
+
lines.append(f"Version: {schema.version}")
|
|
67
|
+
lines.append(f"Description: {schema.description}")
|
|
68
|
+
lines.append("")
|
|
69
|
+
|
|
70
|
+
# Concepts
|
|
71
|
+
if data["concepts"]:
|
|
72
|
+
lines.append("## CONCEPTS")
|
|
73
|
+
for concept in data["concepts"]:
|
|
74
|
+
lines.append(f"### {concept['name']}")
|
|
75
|
+
lines.append(f"{concept['description']}")
|
|
76
|
+
if concept.get("properties"):
|
|
77
|
+
lines.append("**Properties:**")
|
|
78
|
+
for key, value in concept["properties"].items():
|
|
79
|
+
lines.append(f" - {key}: {value}")
|
|
80
|
+
if concept.get("relationships"):
|
|
81
|
+
lines.append("**Relationships:**")
|
|
82
|
+
for key, value in concept["relationships"].items():
|
|
83
|
+
lines.append(f" - {key}: {value}")
|
|
84
|
+
lines.append("")
|
|
85
|
+
|
|
86
|
+
# Workflows
|
|
87
|
+
if data["workflows"]:
|
|
88
|
+
lines.append("## WORKFLOWS")
|
|
89
|
+
for workflow in data["workflows"]:
|
|
90
|
+
lines.append(f"### {workflow['name']}")
|
|
91
|
+
lines.append(f"{workflow['description']}")
|
|
92
|
+
if workflow.get("steps"):
|
|
93
|
+
lines.append("**Steps:**")
|
|
94
|
+
for i, step in enumerate(workflow["steps"], 1):
|
|
95
|
+
if isinstance(step, dict):
|
|
96
|
+
lines.append(f" {i}. {step.get('description', step)}")
|
|
97
|
+
else:
|
|
98
|
+
lines.append(f" {i}. {step}")
|
|
99
|
+
if workflow.get("commands"):
|
|
100
|
+
lines.append("**Commands:**")
|
|
101
|
+
for cmd in workflow["commands"]:
|
|
102
|
+
lines.append(f" - {cmd}")
|
|
103
|
+
lines.append("")
|
|
104
|
+
|
|
105
|
+
# Commands
|
|
106
|
+
if data["commands"]:
|
|
107
|
+
lines.append("## COMMANDS")
|
|
108
|
+
for cmd_name, cmd in data["commands"].items():
|
|
109
|
+
lines.append(f"### {cmd_name}")
|
|
110
|
+
lines.append(f"**Purpose:** {cmd.get('purpose', 'N/A')}")
|
|
111
|
+
if cmd.get("flags"):
|
|
112
|
+
lines.append("**Flags:**")
|
|
113
|
+
for flag, purpose in cmd["flags"].items():
|
|
114
|
+
lines.append(f" - {flag}: {purpose}")
|
|
115
|
+
if cmd.get("when_to_use"):
|
|
116
|
+
lines.append("**When to use:**")
|
|
117
|
+
for usage in cmd["when_to_use"]:
|
|
118
|
+
lines.append(f" - {usage}")
|
|
119
|
+
lines.append("")
|
|
120
|
+
|
|
121
|
+
# Best Practices
|
|
122
|
+
if data.get("best_practices"):
|
|
123
|
+
lines.append("## BEST PRACTICES")
|
|
124
|
+
for practice in data["best_practices"]:
|
|
125
|
+
lines.append(f"- {practice}")
|
|
126
|
+
lines.append("")
|
|
127
|
+
|
|
128
|
+
return "\n".join(lines)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""Schema registry for plugin documentation.
|
|
2
|
+
|
|
3
|
+
This module provides a central registry where plugins can register
|
|
4
|
+
their documentation schemas for AI agent consumption.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from better_notion._cli.docs.base import Schema
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class SchemaRegistry:
|
|
16
|
+
"""Registry for plugin documentation schemas.
|
|
17
|
+
|
|
18
|
+
This class maintains a collection of plugin schemas that
|
|
19
|
+
AI agents can query to understand the system.
|
|
20
|
+
|
|
21
|
+
Example:
|
|
22
|
+
>>> # Register a plugin schema
|
|
23
|
+
>>> SchemaRegistry.register("agents", AGENTS_SCHEMA)
|
|
24
|
+
>>>
|
|
25
|
+
>>> # Query for a plugin schema
|
|
26
|
+
>>> schema = SchemaRegistry.get("agents")
|
|
27
|
+
>>>
|
|
28
|
+
>>> # List all available schemas
|
|
29
|
+
>>> all_schemas = SchemaRegistry.list_all()
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
_schemas: dict[str, Schema] = {}
|
|
33
|
+
|
|
34
|
+
@classmethod
|
|
35
|
+
def register(cls, plugin_name: str, schema: Schema) -> None:
|
|
36
|
+
"""Register a plugin schema.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
plugin_name: Name of the plugin (e.g., "agents")
|
|
40
|
+
schema: Schema object containing plugin documentation
|
|
41
|
+
"""
|
|
42
|
+
cls._schemas[plugin_name] = schema
|
|
43
|
+
logger.info(f"Registered schema for plugin: {plugin_name}")
|
|
44
|
+
|
|
45
|
+
@classmethod
|
|
46
|
+
def get(cls, plugin_name: str) -> Schema | None:
|
|
47
|
+
"""Get a plugin schema by name.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
plugin_name: Name of the plugin
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
Schema object if found, None otherwise
|
|
54
|
+
"""
|
|
55
|
+
return cls._schemas.get(plugin_name)
|
|
56
|
+
|
|
57
|
+
@classmethod
|
|
58
|
+
def list_all(cls) -> dict[str, Schema]:
|
|
59
|
+
"""List all registered plugin schemas.
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
Dict mapping plugin names to Schema objects
|
|
63
|
+
"""
|
|
64
|
+
return cls._schemas.copy()
|
|
65
|
+
|
|
66
|
+
@classmethod
|
|
67
|
+
def get_all_names(cls) -> list[str]:
|
|
68
|
+
"""Get list of all registered plugin names.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
List of plugin names
|
|
72
|
+
"""
|
|
73
|
+
return list(cls._schemas.keys())
|
|
74
|
+
|
|
75
|
+
@classmethod
|
|
76
|
+
def clear(cls) -> None:
|
|
77
|
+
"""Clear all registered schemas.
|
|
78
|
+
|
|
79
|
+
This is primarily useful for testing.
|
|
80
|
+
"""
|
|
81
|
+
cls._schemas.clear()
|
|
82
|
+
logger.debug("Cleared schema registry")
|
better_notion/_cli/main.py
CHANGED
|
@@ -118,6 +118,173 @@ def version(
|
|
|
118
118
|
console.print(f"[bold blue]Better Notion CLI[/bold blue] version [bold green]{__version__}[/bold green]")
|
|
119
119
|
|
|
120
120
|
|
|
121
|
+
@app.command()
|
|
122
|
+
def docs(
|
|
123
|
+
topic: str = typer.Argument(None, help="Documentation topic to retrieve"),
|
|
124
|
+
format: str = typer.Option("json", "--format", "-f", help="Output format (json, yaml, pretty)"),
|
|
125
|
+
) -> None:
|
|
126
|
+
"""
|
|
127
|
+
Get system documentation for AI agents.
|
|
128
|
+
|
|
129
|
+
This command provides comprehensive documentation about the Better Notion CLI
|
|
130
|
+
that AI agents can consume to understand the system at a high level.
|
|
131
|
+
|
|
132
|
+
Without arguments: List all available topics
|
|
133
|
+
With topic: Show detailed documentation for that topic
|
|
134
|
+
|
|
135
|
+
Available topics:
|
|
136
|
+
- overview: System architecture and core concepts
|
|
137
|
+
- plugins: Available plugins and their capabilities
|
|
138
|
+
- commands: All available commands and their purposes
|
|
139
|
+
|
|
140
|
+
Examples:
|
|
141
|
+
$ notion docs # List all topics
|
|
142
|
+
$ notion docs overview # Get system overview
|
|
143
|
+
$ notion docs overview --format json
|
|
144
|
+
"""
|
|
145
|
+
import json
|
|
146
|
+
|
|
147
|
+
# Define available topics
|
|
148
|
+
topics = {
|
|
149
|
+
"overview": {
|
|
150
|
+
"name": "overview",
|
|
151
|
+
"title": "System Overview",
|
|
152
|
+
"description": "Better Notion CLI - Command-line interface for Notion API",
|
|
153
|
+
"version": __version__,
|
|
154
|
+
"architecture": {
|
|
155
|
+
"description": "A CLI for interacting with Notion, designed for AI agents",
|
|
156
|
+
"features": [
|
|
157
|
+
"JSON-only output for programmatic parsing",
|
|
158
|
+
"Structured error codes for reliable error handling",
|
|
159
|
+
"Async command support for better performance",
|
|
160
|
+
"Plugin system for extensibility",
|
|
161
|
+
]
|
|
162
|
+
},
|
|
163
|
+
"core_concepts": [
|
|
164
|
+
{
|
|
165
|
+
"name": "Pages",
|
|
166
|
+
"description": "Notion pages with content blocks",
|
|
167
|
+
"commands": ["notion pages get", "notion pages create", "notion pages update"]
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"name": "Databases",
|
|
171
|
+
"description": "Notion databases with structured properties",
|
|
172
|
+
"commands": ["notion databases get", "notion databases query", "notion databases create"]
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"name": "Blocks",
|
|
176
|
+
"description": "Content blocks (paragraphs, headings, lists, etc.)",
|
|
177
|
+
"commands": ["notion blocks get", "notion blocks create"]
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"name": "Plugins",
|
|
181
|
+
"description": "Extensible command groups for specialized workflows",
|
|
182
|
+
"commands": ["notion agents", "notion plugin list"]
|
|
183
|
+
}
|
|
184
|
+
],
|
|
185
|
+
"getting_started": [
|
|
186
|
+
"1. Configure authentication: notion auth login",
|
|
187
|
+
"2. Check status: notion auth status",
|
|
188
|
+
"3. Get a page: notion pages get <page_id>"
|
|
189
|
+
]
|
|
190
|
+
},
|
|
191
|
+
"plugins": {
|
|
192
|
+
"name": "plugins",
|
|
193
|
+
"title": "Available Plugins",
|
|
194
|
+
"description": "Official plugins that extend CLI functionality",
|
|
195
|
+
"plugins": [
|
|
196
|
+
{
|
|
197
|
+
"name": "agents",
|
|
198
|
+
"description": "Workflow management system for software development",
|
|
199
|
+
"commands": ["agents init", "agents info", "agents schema"],
|
|
200
|
+
"documentation": "Run 'notion agents schema' for complete documentation"
|
|
201
|
+
}
|
|
202
|
+
]
|
|
203
|
+
},
|
|
204
|
+
"commands": {
|
|
205
|
+
"name": "commands",
|
|
206
|
+
"title": "Available Commands",
|
|
207
|
+
"description": "Core CLI commands organized by category",
|
|
208
|
+
"categories": [
|
|
209
|
+
{
|
|
210
|
+
"name": "Authentication",
|
|
211
|
+
"commands": [
|
|
212
|
+
{"command": "notion auth login", "purpose": "Authenticate with Notion"},
|
|
213
|
+
{"command": "notion auth status", "purpose": "Check authentication status"},
|
|
214
|
+
{"command": "notion auth logout", "purpose": "Logout and clear credentials"}
|
|
215
|
+
]
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
"name": "Pages",
|
|
219
|
+
"commands": [
|
|
220
|
+
{"command": "notion pages get <id>", "purpose": "Get page details"},
|
|
221
|
+
{"command": "notion pages create", "purpose": "Create a new page"},
|
|
222
|
+
{"command": "notion pages update <id>", "purpose": "Update page properties"},
|
|
223
|
+
{"command": "notion pages search <query>", "purpose": "Search for pages"}
|
|
224
|
+
]
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"name": "Databases",
|
|
228
|
+
"commands": [
|
|
229
|
+
{"command": "notion databases get <id>", "purpose": "Get database details"},
|
|
230
|
+
{"command": "notion databases query <id>", "purpose": "Query database with filters"},
|
|
231
|
+
{"command": "notion databases create", "purpose": "Create a new database"}
|
|
232
|
+
]
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"name": "Blocks",
|
|
236
|
+
"commands": [
|
|
237
|
+
{"command": "notion blocks get <id>", "purpose": "Get block details"},
|
|
238
|
+
{"command": "notion blocks children <id>", "purpose": "Get block children"}
|
|
239
|
+
]
|
|
240
|
+
}
|
|
241
|
+
]
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
# If no topic specified, list available topics
|
|
246
|
+
if topic is None:
|
|
247
|
+
topics_list = {
|
|
248
|
+
"available_topics": [
|
|
249
|
+
{
|
|
250
|
+
"name": name,
|
|
251
|
+
"title": info["title"],
|
|
252
|
+
"description": info["description"],
|
|
253
|
+
}
|
|
254
|
+
for name, info in topics.items()
|
|
255
|
+
],
|
|
256
|
+
"usage": "notion docs <topic> for detailed information",
|
|
257
|
+
"examples": [
|
|
258
|
+
"notion docs overview",
|
|
259
|
+
"notion docs plugins",
|
|
260
|
+
"notion docs commands"
|
|
261
|
+
]
|
|
262
|
+
}
|
|
263
|
+
typer.echo(json.dumps(topics_list, indent=2))
|
|
264
|
+
return
|
|
265
|
+
|
|
266
|
+
# Get the requested topic
|
|
267
|
+
topic_lower = topic.lower()
|
|
268
|
+
if topic_lower not in topics:
|
|
269
|
+
result = {
|
|
270
|
+
"success": False,
|
|
271
|
+
"error": {
|
|
272
|
+
"code": "UNKNOWN_TOPIC",
|
|
273
|
+
"message": f"Unknown topic: {topic}",
|
|
274
|
+
"retry": False,
|
|
275
|
+
"details": {
|
|
276
|
+
"available_topics": list(topics.keys())
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
typer.echo(json.dumps(result, indent=2))
|
|
281
|
+
raise typer.Exit(code=1)
|
|
282
|
+
|
|
283
|
+
# Return the topic documentation
|
|
284
|
+
topic_info = topics[topic_lower]
|
|
285
|
+
typer.echo(json.dumps(topic_info, indent=2))
|
|
286
|
+
|
|
287
|
+
|
|
121
288
|
@app.callback()
|
|
122
289
|
def main(
|
|
123
290
|
ctx: typer.Context,
|