kimi-agent-module-api 1.3.0__tar.gz → 2.0.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.
Files changed (22) hide show
  1. {kimi_agent_module_api-1.3.0/src/kimi_agent_module_api.egg-info → kimi_agent_module_api-2.0.0}/PKG-INFO +28 -5
  2. {kimi_agent_module_api-1.3.0 → kimi_agent_module_api-2.0.0}/README.md +27 -4
  3. {kimi_agent_module_api-1.3.0 → kimi_agent_module_api-2.0.0}/pyproject.toml +1 -1
  4. {kimi_agent_module_api-1.3.0 → kimi_agent_module_api-2.0.0}/src/kimi_agent_module_api/__init__.py +17 -24
  5. {kimi_agent_module_api-1.3.0 → kimi_agent_module_api-2.0.0}/src/kimi_agent_module_api/contracts.py +0 -1
  6. {kimi_agent_module_api-1.3.0 → kimi_agent_module_api-2.0.0/src/kimi_agent_module_api.egg-info}/PKG-INFO +28 -5
  7. {kimi_agent_module_api-1.3.0 → kimi_agent_module_api-2.0.0}/tests/test_contracts.py +19 -3
  8. {kimi_agent_module_api-1.3.0 → kimi_agent_module_api-2.0.0}/tests/test_public_api.py +16 -0
  9. {kimi_agent_module_api-1.3.0 → kimi_agent_module_api-2.0.0}/LICENSE +0 -0
  10. {kimi_agent_module_api-1.3.0 → kimi_agent_module_api-2.0.0}/setup.cfg +0 -0
  11. {kimi_agent_module_api-1.3.0 → kimi_agent_module_api-2.0.0}/src/kimi_agent_module_api/events.py +0 -0
  12. {kimi_agent_module_api-1.3.0 → kimi_agent_module_api-2.0.0}/src/kimi_agent_module_api/images.py +0 -0
  13. {kimi_agent_module_api-1.3.0 → kimi_agent_module_api-2.0.0}/src/kimi_agent_module_api/py.typed +0 -0
  14. {kimi_agent_module_api-1.3.0 → kimi_agent_module_api-2.0.0}/src/kimi_agent_module_api/settings.py +0 -0
  15. {kimi_agent_module_api-1.3.0 → kimi_agent_module_api-2.0.0}/src/kimi_agent_module_api/testing.py +0 -0
  16. {kimi_agent_module_api-1.3.0 → kimi_agent_module_api-2.0.0}/src/kimi_agent_module_api/tools.py +0 -0
  17. {kimi_agent_module_api-1.3.0 → kimi_agent_module_api-2.0.0}/src/kimi_agent_module_api/trust.py +0 -0
  18. {kimi_agent_module_api-1.3.0 → kimi_agent_module_api-2.0.0}/src/kimi_agent_module_api.egg-info/SOURCES.txt +0 -0
  19. {kimi_agent_module_api-1.3.0 → kimi_agent_module_api-2.0.0}/src/kimi_agent_module_api.egg-info/dependency_links.txt +0 -0
  20. {kimi_agent_module_api-1.3.0 → kimi_agent_module_api-2.0.0}/src/kimi_agent_module_api.egg-info/requires.txt +0 -0
  21. {kimi_agent_module_api-1.3.0 → kimi_agent_module_api-2.0.0}/src/kimi_agent_module_api.egg-info/top_level.txt +0 -0
  22. {kimi_agent_module_api-1.3.0 → kimi_agent_module_api-2.0.0}/tests/test_testing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kimi-agent-module-api
3
- Version: 1.3.0
3
+ Version: 2.0.0
4
4
  Summary: Stable contracts for community-built assistant modules
5
5
  Author: Webhead
6
6
  License-Expression: MIT
@@ -39,31 +39,54 @@ group:
39
39
 
40
40
  ```toml
41
41
  [project]
42
- dependencies = ["kimi-agent-module-api>=1,<2"]
42
+ dependencies = ["kimi-agent-module-api>=2,<3"]
43
43
 
44
44
  [project.entry-points."kimi_agent.modules"]
45
45
  my_module = "my_module_package:SPEC"
46
46
  ```
47
47
 
48
+ The source must pin the API contract it implements when constructing the
49
+ specification:
50
+
51
+ ```python
52
+ from kimi_agent_module_api import ModuleSpec
53
+
54
+ SPEC = ModuleSpec(
55
+ name="my_module",
56
+ version="0.1.0",
57
+ create=create,
58
+ api_version=2,
59
+ )
60
+ ```
61
+
62
+ `api_version` is a required keyword. Keep it as a literal rather than deriving
63
+ it from the installed SDK's `MODULE_API_VERSION`; unchanged module source must
64
+ not silently claim compatibility merely because it was rebuilt with a newer
65
+ SDK.
66
+
48
67
  The [module guide](https://github.com/webhead2oo9/kimi-agent/blob/main/docs/modules.md)
49
68
  documents installation, declarations, lifecycle, and every runtime port. The
50
69
  [reference module](https://github.com/webhead2oo9/kimi-agent/tree/main/bot/modules/example)
51
70
  is a complete, commented example that exercises most ports; start there.
52
71
 
53
72
  Guild-scoped live command replacement was added in 1.1. Modules using
54
- `InteractionRouter.replace_guild_commands()` should depend on
55
- `kimi-agent-module-api>=1.1,<2` and require the host capability
73
+ `InteractionRouter.replace_guild_commands()` should require the host capability
56
74
  `discord.guild_commands.v1`.
57
75
 
58
76
  Version 1.2 adds typed modal forms and a narrow Components V2 layout model. Once a response uses
59
77
  that layout model, Discord requires every later edit of the same message to remain a layout.
60
- Modules using them should depend on `kimi-agent-module-api>=1.2,<2` and require
78
+ Modules using them should require
61
79
  `discord.modals.v1` and/or `discord.components_v2.v1`.
62
80
 
63
81
  Version 1.3 adds cached author classification to message-deletion events:
64
82
  `MessageDeleteEvent.author_is_bot` and `MessageBulkDeleteEvent.bot_message_ids`.
65
83
  The values remain unknown for messages that were absent from Discord's cache.
66
84
 
85
+ Version 2 requires an explicit, source-pinned `ModuleSpec.api_version`, and
86
+ removes the temporary guild-settings legacy flag and module table aliases.
87
+ Modules must use namespaced guild documents and migrate legacy tables to the
88
+ physical names returned by `ctx.storage.table()` before upgrading.
89
+
67
90
  ## Testing the SDK
68
91
 
69
92
  From this package directory, run its tests without installing the Kimi application:
@@ -22,31 +22,54 @@ group:
22
22
 
23
23
  ```toml
24
24
  [project]
25
- dependencies = ["kimi-agent-module-api>=1,<2"]
25
+ dependencies = ["kimi-agent-module-api>=2,<3"]
26
26
 
27
27
  [project.entry-points."kimi_agent.modules"]
28
28
  my_module = "my_module_package:SPEC"
29
29
  ```
30
30
 
31
+ The source must pin the API contract it implements when constructing the
32
+ specification:
33
+
34
+ ```python
35
+ from kimi_agent_module_api import ModuleSpec
36
+
37
+ SPEC = ModuleSpec(
38
+ name="my_module",
39
+ version="0.1.0",
40
+ create=create,
41
+ api_version=2,
42
+ )
43
+ ```
44
+
45
+ `api_version` is a required keyword. Keep it as a literal rather than deriving
46
+ it from the installed SDK's `MODULE_API_VERSION`; unchanged module source must
47
+ not silently claim compatibility merely because it was rebuilt with a newer
48
+ SDK.
49
+
31
50
  The [module guide](https://github.com/webhead2oo9/kimi-agent/blob/main/docs/modules.md)
32
51
  documents installation, declarations, lifecycle, and every runtime port. The
33
52
  [reference module](https://github.com/webhead2oo9/kimi-agent/tree/main/bot/modules/example)
34
53
  is a complete, commented example that exercises most ports; start there.
35
54
 
36
55
  Guild-scoped live command replacement was added in 1.1. Modules using
37
- `InteractionRouter.replace_guild_commands()` should depend on
38
- `kimi-agent-module-api>=1.1,<2` and require the host capability
56
+ `InteractionRouter.replace_guild_commands()` should require the host capability
39
57
  `discord.guild_commands.v1`.
40
58
 
41
59
  Version 1.2 adds typed modal forms and a narrow Components V2 layout model. Once a response uses
42
60
  that layout model, Discord requires every later edit of the same message to remain a layout.
43
- Modules using them should depend on `kimi-agent-module-api>=1.2,<2` and require
61
+ Modules using them should require
44
62
  `discord.modals.v1` and/or `discord.components_v2.v1`.
45
63
 
46
64
  Version 1.3 adds cached author classification to message-deletion events:
47
65
  `MessageDeleteEvent.author_is_bot` and `MessageBulkDeleteEvent.bot_message_ids`.
48
66
  The values remain unknown for messages that were absent from Discord's cache.
49
67
 
68
+ Version 2 requires an explicit, source-pinned `ModuleSpec.api_version`, and
69
+ removes the temporary guild-settings legacy flag and module table aliases.
70
+ Modules must use namespaced guild documents and migrate legacy tables to the
71
+ physical names returned by `ctx.storage.table()` before upgrading.
72
+
50
73
  ## Testing the SDK
51
74
 
52
75
  From this package directory, run its tests without installing the Kimi application:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "kimi-agent-module-api"
3
- version = "1.3.0"
3
+ version = "2.0.0"
4
4
  description = "Stable contracts for community-built assistant modules"
5
5
  requires-python = ">=3.14"
6
6
  authors = [{ name = "Webhead" }]
@@ -3,23 +3,19 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from collections.abc import Callable, Mapping, Sequence
6
- from dataclasses import dataclass, field
6
+ from dataclasses import KW_ONLY, dataclass, field
7
7
  from pathlib import Path
8
8
  from typing import Any, Protocol, TypeVar
9
9
 
10
10
  from pydantic_settings import BaseSettings
11
11
 
12
+ from kimi_agent_module_api import contracts as _contracts
12
13
  from kimi_agent_module_api.contracts import (
13
14
  ConfigSnapshot,
14
15
  RoleSnapshot,
15
16
  render_guild_settings,
16
- DiscordActions,
17
- EventBus,
18
- GuildSettings,
19
17
  GuildSettingsSchema,
20
- HealthReporter,
21
18
  InviteSnapshot,
22
- InteractionRouter,
23
19
  LayoutGallery,
24
20
  LayoutItem,
25
21
  LayoutSection,
@@ -27,9 +23,7 @@ from kimi_agent_module_api.contracts import (
27
23
  LayoutSeparatorSpacing,
28
24
  LayoutText,
29
25
  ModalSpec,
30
- ModuleHttp,
31
26
  ModulePermissions,
32
- ModuleStorage,
33
27
  OutgoingLayout,
34
28
  ScopedModuleMigration,
35
29
  ProposalActor,
@@ -37,11 +31,8 @@ from kimi_agent_module_api.contracts import (
37
31
  ProposalRef,
38
32
  ProposalService,
39
33
  ProposalState,
40
- Scheduler,
41
34
  ServiceDeclaration,
42
- ServiceRegistry,
43
35
  ServiceRequirement,
44
- TrustLookup,
45
36
  TextInputSpec,
46
37
  TextInputStyle,
47
38
  )
@@ -53,7 +44,7 @@ from kimi_agent_module_api.tools import (
53
44
  )
54
45
  from kimi_agent_module_api.trust import TrustTier
55
46
 
56
- MODULE_API_VERSION = 1
47
+ MODULE_API_VERSION = 2
57
48
  MODULE_ENTRYPOINT_GROUP = "kimi_agent.modules"
58
49
  # Capabilities every compatible host advertises regardless of configuration.
59
50
  BASELINE_CAPABILITIES: frozenset[str] = frozenset({"discord.history.v1", "proposals.v2"})
@@ -82,10 +73,13 @@ class AppModule(Protocol):
82
73
 
83
74
  @dataclass(frozen=True)
84
75
  class ModuleSpec:
76
+ """A module declaration with an explicit, source-pinned host API version."""
77
+
85
78
  name: str
86
79
  version: str
87
80
  create: Callable[[ModuleLoadContext], AppModule]
88
- api_version: int = MODULE_API_VERSION
81
+ _: KW_ONLY
82
+ api_version: int
89
83
  dependencies: tuple[str, ...] = ()
90
84
  settings: ModuleSettingsDefinition | None = None
91
85
  requires_capabilities: tuple[str, ...] = ()
@@ -94,7 +88,6 @@ class ModuleSpec:
94
88
  guild_settings: GuildSettingsSchema | None = None
95
89
  provides: tuple[ServiceDeclaration, ...] = ()
96
90
  consumes: tuple[ServiceRequirement, ...] = ()
97
- table_aliases: Mapping[str, str] = field(default_factory=dict)
98
91
 
99
92
 
100
93
  @dataclass(frozen=True)
@@ -138,16 +131,16 @@ class ModuleRuntimeContext:
138
131
  is_guild_active: Callable[[int], bool]
139
132
  current_config_dir: Callable[[], Path]
140
133
  capabilities: ModuleCapabilities
141
- events: EventBus
142
- scheduler: Scheduler
143
- storage: ModuleStorage
144
- health: HealthReporter
145
- discord: DiscordActions
146
- interactions: InteractionRouter
147
- http: ModuleHttp
148
- services: ServiceRegistry
149
- trust: TrustLookup
150
- guild_settings: GuildSettings | None = None
134
+ events: _contracts.EventBus
135
+ scheduler: _contracts.Scheduler
136
+ storage: _contracts.ModuleStorage
137
+ health: _contracts.HealthReporter
138
+ discord: _contracts.DiscordActions
139
+ interactions: _contracts.InteractionRouter
140
+ http: _contracts.ModuleHttp
141
+ services: _contracts.ServiceRegistry
142
+ trust: _contracts.TrustLookup
143
+ guild_settings: _contracts.GuildSettings | None = None
151
144
  proposals: ProposalService | None = None
152
145
  raw_bot: Any = None
153
146
  raw_storage: Any = None
@@ -1466,7 +1466,6 @@ class GuildSettingsSnapshot:
1466
1466
  valid: bool
1467
1467
  errors: tuple[str, ...]
1468
1468
  revision: str
1469
- legacy: bool = False
1470
1469
 
1471
1470
 
1472
1471
  class GuildSettings(Protocol):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kimi-agent-module-api
3
- Version: 1.3.0
3
+ Version: 2.0.0
4
4
  Summary: Stable contracts for community-built assistant modules
5
5
  Author: Webhead
6
6
  License-Expression: MIT
@@ -39,31 +39,54 @@ group:
39
39
 
40
40
  ```toml
41
41
  [project]
42
- dependencies = ["kimi-agent-module-api>=1,<2"]
42
+ dependencies = ["kimi-agent-module-api>=2,<3"]
43
43
 
44
44
  [project.entry-points."kimi_agent.modules"]
45
45
  my_module = "my_module_package:SPEC"
46
46
  ```
47
47
 
48
+ The source must pin the API contract it implements when constructing the
49
+ specification:
50
+
51
+ ```python
52
+ from kimi_agent_module_api import ModuleSpec
53
+
54
+ SPEC = ModuleSpec(
55
+ name="my_module",
56
+ version="0.1.0",
57
+ create=create,
58
+ api_version=2,
59
+ )
60
+ ```
61
+
62
+ `api_version` is a required keyword. Keep it as a literal rather than deriving
63
+ it from the installed SDK's `MODULE_API_VERSION`; unchanged module source must
64
+ not silently claim compatibility merely because it was rebuilt with a newer
65
+ SDK.
66
+
48
67
  The [module guide](https://github.com/webhead2oo9/kimi-agent/blob/main/docs/modules.md)
49
68
  documents installation, declarations, lifecycle, and every runtime port. The
50
69
  [reference module](https://github.com/webhead2oo9/kimi-agent/tree/main/bot/modules/example)
51
70
  is a complete, commented example that exercises most ports; start there.
52
71
 
53
72
  Guild-scoped live command replacement was added in 1.1. Modules using
54
- `InteractionRouter.replace_guild_commands()` should depend on
55
- `kimi-agent-module-api>=1.1,<2` and require the host capability
73
+ `InteractionRouter.replace_guild_commands()` should require the host capability
56
74
  `discord.guild_commands.v1`.
57
75
 
58
76
  Version 1.2 adds typed modal forms and a narrow Components V2 layout model. Once a response uses
59
77
  that layout model, Discord requires every later edit of the same message to remain a layout.
60
- Modules using them should depend on `kimi-agent-module-api>=1.2,<2` and require
78
+ Modules using them should require
61
79
  `discord.modals.v1` and/or `discord.components_v2.v1`.
62
80
 
63
81
  Version 1.3 adds cached author classification to message-deletion events:
64
82
  `MessageDeleteEvent.author_is_bot` and `MessageBulkDeleteEvent.bot_message_ids`.
65
83
  The values remain unknown for messages that were absent from Discord's cache.
66
84
 
85
+ Version 2 requires an explicit, source-pinned `ModuleSpec.api_version`, and
86
+ removes the temporary guild-settings legacy flag and module table aliases.
87
+ Modules must use namespaced guild documents and migrate legacy tables to the
88
+ physical names returned by `ctx.storage.table()` before upgrading.
89
+
67
90
  ## Testing the SDK
68
91
 
69
92
  From this package directory, run its tests without installing the Kimi application:
@@ -11,6 +11,7 @@ from pydantic_settings import BaseSettings
11
11
  from kimi_agent_module_api import (
12
12
  BASELINE_CAPABILITIES,
13
13
  MODULE_API_VERSION,
14
+ AppModule,
14
15
  ModuleCapabilities,
15
16
  ModuleLoadContext,
16
17
  ModulePermissions,
@@ -57,15 +58,20 @@ class OtherSettings(BaseSettings):
57
58
 
58
59
 
59
60
  def _spec(name: str = "demo") -> ModuleSpec:
60
- def create(_ctx: ModuleLoadContext) -> object:
61
+ def create(_ctx: ModuleLoadContext) -> AppModule:
61
62
  raise AssertionError("not called")
62
63
 
63
- return ModuleSpec(name=name, version="1.0.0", create=create) # type: ignore[arg-type]
64
+ return ModuleSpec(
65
+ name=name,
66
+ version="1.0.0",
67
+ create=create,
68
+ api_version=MODULE_API_VERSION,
69
+ )
64
70
 
65
71
 
66
72
  def test_spec_and_runtime_context_keep_stable_defaults() -> None:
67
73
  spec = _spec()
68
- assert spec.api_version == MODULE_API_VERSION == 1
74
+ assert spec.api_version == MODULE_API_VERSION == 2
69
75
  assert spec.permissions == ModulePermissions()
70
76
  assert spec.dependencies == ()
71
77
  required = {
@@ -76,6 +82,16 @@ def test_spec_and_runtime_context_keep_stable_defaults() -> None:
76
82
  assert {"events", "scheduler", "storage", "discord", "interactions", "services"} <= required
77
83
 
78
84
 
85
+ def test_spec_requires_an_explicit_keyword_api_version() -> None:
86
+ def create(_ctx: ModuleLoadContext) -> AppModule:
87
+ raise AssertionError("not called")
88
+
89
+ with pytest.raises(TypeError, match="required keyword-only argument: 'api_version'"):
90
+ ModuleSpec("demo", "1.0.0", create) # type: ignore[call-arg]
91
+ with pytest.raises(TypeError, match="positional arguments"):
92
+ ModuleSpec("demo", "1.0.0", create, MODULE_API_VERSION) # type: ignore[call-arg]
93
+
94
+
79
95
  def test_load_context_exercises_public_create_helpers() -> None:
80
96
  settings = DemoSettings(greeting="hi")
81
97
  context, recorder = load_context(settings)
@@ -17,6 +17,22 @@ def test_public_exports_resolve() -> None:
17
17
  assert all(getattr(api, name, None) is not None for name in api.__all__)
18
18
 
19
19
 
20
+ def test_contract_ports_are_not_accidental_package_root_exports() -> None:
21
+ hidden_ports = {
22
+ "DiscordActions",
23
+ "EventBus",
24
+ "GuildSettings",
25
+ "HealthReporter",
26
+ "InteractionRouter",
27
+ "ModuleHttp",
28
+ "ModuleStorage",
29
+ "Scheduler",
30
+ "ServiceRegistry",
31
+ "TrustLookup",
32
+ }
33
+ assert hidden_ports.isdisjoint(vars(api))
34
+
35
+
20
36
  def test_standalone_environment_has_no_core_runtime() -> None:
21
37
  """CI runs this package from an isolated environment, outside core's import root."""
22
38
  assert importlib.util.find_spec("app") is None