Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 10 additions & 20 deletions .github/workflows/proto-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@ on:
- 'proto/**'
- 'python/amplifier_core/_grpc_gen/**'
- 'crates/amplifier-core/src/generated/**'
- 'scripts/generate_grpc_stubs.py'
- '.github/workflows/proto-check.yml'
pull_request:
branches: [main]
paths:
- 'proto/**'
- 'python/amplifier_core/_grpc_gen/**'
- 'crates/amplifier-core/src/generated/**'
- 'scripts/generate_grpc_stubs.py'
- '.github/workflows/proto-check.yml'

jobs:
proto-sync:
Expand All @@ -32,32 +36,18 @@ jobs:
python-version: '3.12'

- name: Install grpcio-tools
run: pip install grpcio-tools
run: pip install grpcio-tools==1.78.0

- name: Regenerate Python stubs
run: |
mkdir -p /tmp/proto_check
python -m grpc_tools.protoc \
-Iproto \
--python_out=/tmp/proto_check \
--grpc_python_out=/tmp/proto_check \
proto/amplifier_module.proto
python scripts/generate_grpc_stubs.py --output /tmp/proto_check

- name: Compare with committed stubs
run: |
# Check that key message classes exist in regenerated output
python -c "
import importlib.util, sys
spec = importlib.util.spec_from_file_location('pb2', '/tmp/proto_check/amplifier_module_pb2.py')
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
required = ['ChatRequest', 'ChatResponse', 'ToolResult', 'HookResult', 'ModuleInfo']
missing = [t for t in required if not hasattr(mod, t)]
if missing:
print(f'FAIL: Missing types in regenerated stubs: {missing}')
sys.exit(1)
print('PASS: Regenerated stubs contain all required types')
"
diff -u python/amplifier_core/_grpc_gen/amplifier_module_pb2.py \
/tmp/proto_check/amplifier_module_pb2.py
diff -u python/amplifier_core/_grpc_gen/amplifier_module_pb2_grpc.py \
/tmp/proto_check/amplifier_module_pb2_grpc.py

rust-build:
name: Rust build and test
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,14 @@ maturin develop
uv run maturin develop
```

To regenerate the committed Python gRPC stubs, install the pinned generator
and run the canonical command:

```bash
python -m pip install grpcio-tools==1.78.0
python scripts/generate_grpc_stubs.py
```

See [docs/RUST_CORE_TESTING.md](docs/RUST_CORE_TESTING.md) for the full development setup guide.

**Build dependencies**: Rust 1.70+, maturin
Expand Down
9 changes: 9 additions & 0 deletions bindings/node/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ export const enum UserMessageLevel {
Warning = 'Warning',
Error = 'Error'
}
export interface JsContextInjection {
content: string
role: ContextInjectionRole
ephemeral: boolean
appendToLastToolResult: boolean
hookName: string
event: string
}
export interface JsHookResult {
action: HookAction
reason?: string
Expand All @@ -44,6 +52,7 @@ export interface JsHookResult {
approvalPrompt?: string
approvalTimeout?: number
approvalDefault?: ApprovalDefault
contextInjections?: Array<JsContextInjection>
}
/** Structured error object returned to JS with a typed `code` property. */
export interface JsAmplifierError {
Expand Down
31 changes: 30 additions & 1 deletion bindings/node/src/hook_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,20 @@
// Structs — exported as TypeScript interfaces via #[napi(object)]
// ---------------------------------------------------------------------------

use amplifier_core::models::HookResult;
use amplifier_core::models::{ContextInjection, HookResult};

use crate::enums::{ApprovalDefault, ContextInjectionRole, HookAction, UserMessageLevel};

#[napi(object)]
pub struct JsContextInjection {
pub content: String,
pub role: ContextInjectionRole,
pub ephemeral: bool,
pub append_to_last_tool_result: bool,
pub hook_name: String,
pub event: String,
}

#[napi(object)]
pub struct JsHookResult {
pub action: HookAction,
Expand All @@ -20,6 +30,7 @@ pub struct JsHookResult {
pub approval_prompt: Option<String>,
pub approval_timeout: Option<f64>,
pub approval_default: Option<ApprovalDefault>,
pub context_injections: Option<Vec<JsContextInjection>>,
}

// ---------------------------------------------------------------------------
Expand All @@ -40,5 +51,23 @@ pub(crate) fn hook_result_to_js(result: HookResult) -> JsHookResult {
approval_prompt: result.approval_prompt,
approval_timeout: Some(result.approval_timeout),
approval_default: Some(result.approval_default.into()),
context_injections: Some(
result
.context_injections
.into_iter()
.map(context_injection_to_js)
.collect(),
),
}
}

fn context_injection_to_js(injection: ContextInjection) -> JsContextInjection {
JsContextInjection {
content: injection.content,
role: injection.role.into(),
ephemeral: injection.ephemeral,
append_to_last_tool_result: injection.append_to_last_tool_result,
hook_name: injection.hook_name,
event: injection.event,
}
}
2 changes: 1 addition & 1 deletion bindings/node/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub use enums::{
ApprovalDefault, ContextInjectionRole, HookAction, SessionState, UserMessageLevel,
};
pub use errors::{amplifier_error_to_js, JsAmplifierError};
pub use hook_result::JsHookResult;
pub use hook_result::{JsContextInjection, JsHookResult};
pub use hooks::JsHookRegistry;
pub use module_resolver::{load_wasm_from_path, resolve_module, JsModuleManifest};
pub use session::JsAmplifierSession;
Expand Down
Loading
Loading