You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maka.apache.org by wy...@apache.org on 2026/10/14 01:19:01 UTC
(maka) 01/14: feat(agent): restore model Code Mode and nested service tools
This is an automated email from the ASF dual-hosted git repository.
M4n5ter pushed a commit to branch feat/runtime-host-rust
in repository https://gitbox.apache.org/repos/asf/maka.git
commit 5a4f67e2fab6c23aadffd87d52b3d4f7398a5163
Author: Wang <m4...@gmail.com>
AuthorDate: Tue Oct 13 14:56:52 2026 +0800
feat(agent): restore model Code Mode and nested service tools
---
packages/plugin-sdk/src/configurations.ts | 10 ++
packages/plugin-sdk/src/generated/runtime.ts | 5 +
plugins/agent/api/src/contract.rs | 4 +
plugins/agent/native/README.md | 2 +
plugins/agent/native/README.zh-CN.md | 2 +
plugins/agent/native/src/model.rs | 13 +++
plugins/agent/native/src/owner/execution.rs | 5 +-
plugins/agent/native/src/owner/queue.rs | 1 +
.../agent/native/src/owner/tests/attachments.rs | 2 +-
plugins/agent/native/src/owner/tests/selection.rs | 65 +++++++++++
.../agent/native/src/owner/tests/service_tools.rs | 124 +++++++++++++++++++++
plugins/agent/native/src/tools.rs | 6 +-
products/maka/bundle/src/installation.ts | 10 +-
products/maka/cli/notices.json | 6 +-
14 files changed, 248 insertions(+), 7 deletions(-)
diff --git a/packages/plugin-sdk/src/configurations.ts b/packages/plugin-sdk/src/configurations.ts
index ec4799858b..53f9b89d86 100644
--- a/packages/plugin-sdk/src/configurations.ts
+++ b/packages/plugin-sdk/src/configurations.ts
@@ -337,6 +337,11 @@ export const configurations = {
AgentServiceTool: {
type: 'object',
properties: {
+ nestable: {
+ description:
+ 'Allow this selected service inside Code Mode. Binding and permission\nchecks are identical to a direct call; omitted keeps direct-only behavior.',
+ type: 'boolean',
+ },
input: {
description:
'Explicit input projection. Skill tools receive the actual Agent tool names,\noutside model-controlled arguments; this is compatibility data, not authority.',
@@ -796,6 +801,11 @@ export const configurations = {
type: 'object',
additionalProperties: false,
properties: {
+ nestable: {
+ type: 'boolean',
+ description:
+ 'Allow this selected service inside Code Mode. Binding and permission\nchecks are identical to a direct call; omitted keeps direct-only behavior.',
+ },
input: {
$ref: '#/$defs/AgentToolInput',
description:
diff --git a/packages/plugin-sdk/src/generated/runtime.ts b/packages/plugin-sdk/src/generated/runtime.ts
index 5eaf30baf4..6d1a06f0bb 100644
--- a/packages/plugin-sdk/src/generated/runtime.ts
+++ b/packages/plugin-sdk/src/generated/runtime.ts
@@ -6644,6 +6644,11 @@ export interface DirectoryRootSpec {
path: string;
}
export interface AgentServiceTool {
+ /**
+ * Allow this selected service inside Code Mode. Binding and permission
+ * checks are identical to a direct call; omitted keeps direct-only behavior.
+ */
+ nestable?: boolean;
/**
* Explicit input projection. Skill tools receive the actual Agent tool names,
* outside model-controlled arguments; this is compatibility data, not authority.
diff --git a/plugins/agent/api/src/contract.rs b/plugins/agent/api/src/contract.rs
index bc024e44ce..7899c5b5cc 100644
--- a/plugins/agent/api/src/contract.rs
+++ b/plugins/agent/api/src/contract.rs
@@ -105,6 +105,10 @@ pub struct AssistantConfiguration {
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(rename = "AgentServiceTool")]
pub struct ServiceTool {
+ /// Allow this selected service inside Code Mode. Binding and permission
+ /// checks are identical to a direct call; omitted keeps direct-only behavior.
+ #[serde(default, skip_serializing_if = "std::ops::Not::not")]
+ pub nestable: bool,
/// Explicit input projection. Skill tools receive the actual Agent tool names,
/// outside model-controlled arguments; this is compatibility data, not authority.
#[serde(default)]
diff --git a/plugins/agent/native/README.md b/plugins/agent/native/README.md
index 6c65d5b6d6..32cb91fc36 100644
--- a/plugins/agent/native/README.md
+++ b/plugins/agent/native/README.md
@@ -25,4 +25,6 @@ Exposes Agent execution as native application services. `provide` registers fact
The service owns its activation and delegates runs to `maka-agent-engine`. Session history, controls and tool calls use admitted scopes and original operation receipts. Files, processes, skills and other services are explicit dependencies selected by composition.
+The Agent captures the model's Code Mode default or explicit `codeMode` override when it accepts a message. Queued work and resumed runs retain their original mode. A service tool can opt into Code Mode with `nestable: true`; nested calls use the same permissions, operation receipts and cleanup as direct calls. Omitted `nestable` keeps the tool callable only directly. The Maka default composition enables nesting for files, processes, Web and Skills.
+
[Source](src/lib.rs) · [Cargo manifest](Cargo.toml)
diff --git a/plugins/agent/native/README.zh-CN.md b/plugins/agent/native/README.zh-CN.md
index a2cd93d858..c348f59eb6 100644
--- a/plugins/agent/native/README.zh-CN.md
+++ b/plugins/agent/native/README.zh-CN.md
@@ -25,4 +25,6 @@
服务管理自己的激活,并委托 `maka-agent-engine` 执行运行。会话历史、控制和工具调用使用获准作用域与原始操作回执。文件、进程、技能等服务都是通过组合显式选择的依赖。
+Agent 接收消息时保存模型的 Code Mode 默认值或显式 `codeMode` 覆盖设置;排队消息和恢复运行保留原模式。服务工具可以通过 `nestable: true` 允许代码内调用,仍执行与直接调用相同的权限检查、操作回执和清理流程。省略该字段时仅允许直接调用。Maka 默认组合为文件、进程、Web 和 Skills 工具启用嵌套调用。
+
[源码](src/lib.rs) · [Cargo 配置](Cargo.toml)
diff --git a/plugins/agent/native/src/model.rs b/plugins/agent/native/src/model.rs
index f340c8e4bf..92d15ec204 100644
--- a/plugins/agent/native/src/model.rs
+++ b/plugins/agent/native/src/model.rs
@@ -27,6 +27,7 @@ use maka_agent_facts::configuration::ModelInfo;
use maka_agent_facts::configuration::ModelSelection;
use maka_agent_facts::execution::ModelBinding;
use maka_agent_facts::execution::ThinkingLevel;
+use maka_agent_facts::execution::ToolMode;
use maka_agent_ports::provider::Connection;
use maka_agent_ports::provider::Definition;
use maka_agent_ports::provider::Model;
@@ -69,6 +70,10 @@ impl ExecutionBasis {
pub(crate) struct AcceptedModel {
pub binding: ModelBinding,
pub thinking_level: Option<ThinkingLevel>,
+ /// Execution policy is captured at message admission. Later model settings
+ /// do not reinterpret queued work. Older accepted messages remain Direct.
+ #[serde(default)]
+ pub tool_mode: ToolMode,
provider: maka_agent_facts::provider::Identity,
provider_configuration: Value,
basis: ExecutionBasis,
@@ -109,6 +114,14 @@ impl Source {
configuration,
credentials,
accepted: AcceptedModel {
+ tool_mode: ToolMode::for_model(
+ &selection.model_id,
+ &model.base_url,
+ row.model_overrides
+ .as_ref()
+ .and_then(|models| models.get(&selection.model_id))
+ .and_then(|overrides| overrides.code_mode),
+ ),
binding: ModelBinding {
connection_id: row.connection_id.clone(),
connection_slug: row.slug.clone(),
diff --git a/plugins/agent/native/src/owner/execution.rs b/plugins/agent/native/src/owner/execution.rs
index 0a40fa7a56..26452d6ad5 100644
--- a/plugins/agent/native/src/owner/execution.rs
+++ b/plugins/agent/native/src/owner/execution.rs
@@ -274,7 +274,7 @@ impl Owner {
{
return Ok(parked(Reason::WorkspaceChanged));
}
- let (source, prepared) = crate::model::Source::select(
+ let (mut source, prepared) = crate::model::Source::select(
self.configuration.clone(),
self.credentials.clone(),
input.model,
@@ -284,6 +284,9 @@ impl Owner {
)
.await
.map_err(public_error)?;
+ // A continuation retains the original tool protocol even when the
+ // user selects a model whose default differs from the original Run.
+ source.accepted.tool_mode = configuration.tool_mode;
let basis = MessageBasis {
allowed_tools: session.configuration.tools.clone(),
background: None,
diff --git a/plugins/agent/native/src/owner/queue.rs b/plugins/agent/native/src/owner/queue.rs
index 4da2d85193..e0faae038a 100644
--- a/plugins/agent/native/src/owner/queue.rs
+++ b/plugins/agent/native/src/owner/queue.rs
@@ -324,6 +324,7 @@ impl Owner {
let (source, prepared) = *value;
configuration.model = Some(source.accepted.binding.clone());
configuration.thinking_level = source.accepted.thinking_level;
+ configuration.tool_mode = source.accepted.tool_mode;
PreparedRun::Model(Box::new(RunInput {
model_source: Some(Arc::new(source)),
model_revision: Some(prepared.revision),
diff --git a/plugins/agent/native/src/owner/tests/attachments.rs b/plugins/agent/native/src/owner/tests/attachments.rs
index e926a19aca..536cf248b6 100644
--- a/plugins/agent/native/src/owner/tests/attachments.rs
+++ b/plugins/agent/native/src/owner/tests/attachments.rs
@@ -192,7 +192,7 @@ async fn attachment_payload_validation_and_image_read_use_actual_bytes() {
let clipboard = f.mutation_with(2, "uploadAttachment", json!({"sessionId":session,"name":descriptor["name"],"bytes":descriptor["bytes"],"digest":descriptor["digest"]}), Uuid::new_v4(),
BTreeMap::from([("file".into(), snapshot as Arc<dyn ReadResource>)])).await.unwrap();
assert_eq!(clipboard["attachment"]["mimeType"], "image/png");
- assert_eq!(budget.usage(), (0, 0, 0));
+ assert_eq!(budget.usage(), (0, 0));
assert!(!f._dir.path().join("clipboard.png").exists());
f.mutation(2, "send", json!({"sessionId":session,"message":"","attachments":[attachment["id"],clipboard["attachment"]["id"]],"model":f.selection().await}), Uuid::new_v4()).await.unwrap();
let (mut socket, _) = listener.accept().await.unwrap();
diff --git a/plugins/agent/native/src/owner/tests/selection.rs b/plugins/agent/native/src/owner/tests/selection.rs
index ada42c587f..c238f4a678 100644
--- a/plugins/agent/native/src/owner/tests/selection.rs
+++ b/plugins/agent/native/src/owner/tests/selection.rs
@@ -708,3 +708,68 @@ async fn invalid_thinking_default_remains_unavailable_without_poisoning_other_mo
fixture.app.shutdown().await.unwrap();
fixture.config.shutdown().await.unwrap();
}
+
+#[tokio::test]
+async fn accepted_code_mode_survives_settings_changes_and_legacy_messages_remain_direct() {
+ let fixture = Fixture::new("http://127.0.0.1:1/v1", 1, None).await;
+ let session = fixture.create("Frozen tool policy").await;
+ edit(&fixture, |changes| {
+ changes.model_overrides = Patch::Set(BTreeMap::from([(
+ "fixture-model".into(),
+ ModelOverride {
+ code_mode: Some(true),
+ ..Default::default()
+ },
+ )]));
+ })
+ .await;
+ let (source, _) = crate::model::Source::select(
+ fixture.config.clone(),
+ fixture.owner.credentials.clone(),
+ fixture.selection().await,
+ None,
+ session.clone(),
+ fixture.owner.revision.clone(),
+ )
+ .await
+ .unwrap();
+ assert_eq!(source.accepted.tool_mode, ToolMode::CodeMode);
+ let stored = serde_json::to_value(&source.accepted).unwrap();
+ edit(&fixture, |changes| {
+ changes.model_overrides = Patch::Set(BTreeMap::from([(
+ "fixture-model".into(),
+ ModelOverride {
+ code_mode: Some(false),
+ ..Default::default()
+ },
+ )]));
+ })
+ .await;
+ let restored = crate::model::Source::restore(
+ fixture.config.clone(),
+ fixture.owner.credentials.clone(),
+ serde_json::from_value(stored.clone()).unwrap(),
+ session.clone(),
+ fixture.owner.revision.clone(),
+ )
+ .unwrap();
+ restored.capture().await.unwrap();
+ assert_eq!(restored.accepted.tool_mode, ToolMode::CodeMode);
+ let (next, _) = crate::model::Source::select(
+ fixture.config.clone(),
+ fixture.owner.credentials.clone(),
+ fixture.selection().await,
+ None,
+ session.clone(),
+ fixture.owner.revision.clone(),
+ )
+ .await
+ .unwrap();
+ assert_eq!(next.accepted.tool_mode, ToolMode::Direct);
+ let mut legacy = stored;
+ legacy.as_object_mut().unwrap().remove("tool_mode");
+ let accepted: crate::model::AcceptedModel = serde_json::from_value(legacy).unwrap();
+ assert_eq!(accepted.tool_mode, ToolMode::Direct);
+ fixture.app.shutdown().await.unwrap();
+ fixture.config.shutdown().await.unwrap();
+}
diff --git a/plugins/agent/native/src/owner/tests/service_tools.rs b/plugins/agent/native/src/owner/tests/service_tools.rs
index f7b38d83d0..db0a90a84c 100644
--- a/plugins/agent/native/src/owner/tests/service_tools.rs
+++ b/plugins/agent/native/src/owner/tests/service_tools.rs
@@ -133,6 +133,7 @@ pub(super) struct Setup {
title: Option<maka_agent_facts::display::Text>,
counter: Option<Arc<Counter>>,
granted: bool,
+ nestable: bool,
query: bool,
questions: bool,
forms: bool,
@@ -178,6 +179,7 @@ impl Setup {
preparation: None,
images: None,
confirmation: contract::ToolConfirmation::Preapproved,
+ nestable: false,
}
}
fn native(counter: Arc<Counter>, granted: bool) -> Self {
@@ -202,6 +204,7 @@ impl Setup {
preparation: None,
images: None,
confirmation: contract::ToolConfirmation::Preapproved,
+ nestable: false,
}
}
pub(super) fn forms() -> Self {
@@ -232,6 +235,7 @@ impl Setup {
preparation: None,
images: None,
confirmation: contract::ToolConfirmation::Preapproved,
+ nestable: false,
}
}
pub(super) fn files(method: &'static str) -> Self {
@@ -429,6 +433,7 @@ impl Setup {
}
pub(super) fn selection(&self) -> contract::ServiceTool {
contract::ServiceTool {
+ nestable: self.nestable,
input: if self.web {
contract::ToolInput::Web
} else {
@@ -1724,6 +1729,11 @@ async fn resume_replays_original_settlements_without_redispatching_effects() {
&format!("http://{}/v1", listener.local_addr().unwrap()), 1, None, None,
Some(Setup::native(counter.clone(), true)),
).await;
+ selection::edit(&fixture, |changes| {
+ changes.model_overrides = Patch::Set(BTreeMap::from([("fixture-model".into(), ModelOverride {
+ code_mode: Some(true), ..Default::default()
+ })]));
+ }).await;
let session = fixture.create("Resume settled tool").await;
let sent = fixture.send(&session).await.unwrap();
let (mut first, _) = listener.accept().await.unwrap();
@@ -1736,6 +1746,11 @@ async fn resume_replays_original_settlements_without_redispatching_effects() {
fixture.drained().await;
let source = fixture.query("execution", json!({"sessionId":session,"invocationId":sent["invocationId"]})).await.unwrap();
assert_eq!(source["execution"]["state"], "cancelled");
+ selection::edit(&fixture, |changes| {
+ changes.model_overrides = Patch::Set(BTreeMap::from([("fixture-model".into(), ModelOverride {
+ code_mode: Some(false), ..Default::default()
+ })]));
+ }).await;
let resumed = fixture.mutation(2, "resume", json!({
"sessionId":session, "sourceInvocationId":sent["invocationId"],
"sourceHighWater":source["execution"]["highWater"], "model":fixture.selection().await
@@ -1743,6 +1758,7 @@ async fn resume_replays_original_settlements_without_redispatching_effects() {
assert_eq!(resumed["kind"], "started", "{resumed}");
let (mut replay, _) = listener.accept().await.unwrap();
let prompt = request(&mut replay).await;
+ assert!(prompt["tools"].as_array().unwrap().iter().any(|tool| tool["function"]["name"] == "exec"), "resume retains the original Code Mode despite changed model settings");
let result = prompt["messages"].as_array().unwrap().iter().find(|message| message["role"] == "tool").unwrap();
if matches!(behavior, Behavior::Returned) {
assert_eq!(serde_json::from_str::<Value>(result["content"].as_str().unwrap()).unwrap()["effects"], 1);
@@ -1802,3 +1818,111 @@ async fn session_tool_selection_is_an_execution_ceiling_and_is_inherited() {
fixture.config.shutdown().await.unwrap();
}).await.unwrap();
}
+
+#[tokio::test]
+async fn code_mode_calls_selected_native_services_with_original_grants_and_receipts() {
+ tokio::time::timeout(Duration::from_secs(60), async {
+ for (nestable, granted) in [(true, true), (true, false), (false, true)] {
+ let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
+ let base = format!("http://{}/v1", listener.local_addr().unwrap());
+ let counter = Counter::new(Behavior::Returned);
+ let mut setup = Setup::native(counter.clone(), granted);
+ setup.nestable = nestable;
+ let fixture = Fixture::with_services(&base, 1, None, None, Some(setup)).await;
+ selection::edit(&fixture, |changes| {
+ changes.model_overrides = Patch::Set(BTreeMap::from([("fixture-model".into(), ModelOverride {
+ code_mode: Some(true), ..Default::default()
+ })]));
+ }).await;
+ let server = tokio::spawn(async move {
+ let (mut socket, _) = listener.accept().await.unwrap();
+ let first = request(&mut socket).await;
+ let names: Vec<_> = first["tools"].as_array().unwrap().iter().filter_map(|tool| tool["function"]["name"].as_str()).collect();
+ assert!(names.contains(&"exec") && names.contains(&"wait"));
+ assert_eq!(names.contains(&"Counter"), !nestable);
+ let code = "text(await tools.Counter({amount:1})); text(await tools.Counter({amount:1}));";
+ code_response(&mut socket, code).await;
+ let (mut socket, _) = listener.accept().await.unwrap();
+ let next = request(&mut socket).await;
+ let result = next["messages"].as_array().unwrap().iter().find(|message| message["role"] == "tool").unwrap();
+ assert_eq!(result["tool_call_id"], "code-call");
+ if nestable && granted {
+ assert!(result["content"].as_str().unwrap().contains("effects"));
+ }
+ response(&mut socket).await;
+ });
+ let session = fixture.create("Code Mode native services").await;
+ fixture.send(&session).await.unwrap();
+ fixture.drained().await;
+ server.await.unwrap();
+ assert_eq!(counter.effects.load(Ordering::SeqCst), if nestable && granted { 2 } else { 0 });
+ let recorded = facts(&fixture, &session).await;
+ assert!(recorded.iter().any(|fact| matches!(fact, Fact::InvocationOpened { configuration: Some(configuration), .. } if configuration.tool_mode == ToolMode::CodeMode)));
+ if nestable && granted {
+ assert_eq!(recorded.iter().filter(|fact| matches!(fact, Fact::ToolDispatched { name, .. } if name == "Counter")).count(), 2);
+ let operations: Vec<_> = recorded.iter().filter_map(|fact| match fact {
+ Fact::ToolDispatched { name, operation_id, .. } if name == "Counter" => Some(operation_id),
+ _ => None,
+ }).collect();
+ assert_ne!(operations[0], operations[1]);
+ for expected in operations {
+ assert_eq!(recorded.iter().filter(|fact| matches!(fact,
+ Fact::ToolSettled { operation_id, outcome: ToolOutcome::Succeeded { .. } }
+ if operation_id == expected
+ )).count(), 1, "each nested service has its own successful durable settlement");
+ }
+ }
+ fixture.app.shutdown().await.unwrap();
+ fixture.config.shutdown().await.unwrap();
+ }
+ }).await.unwrap();
+}
+
+async fn code_response(socket: &mut TcpStream, code: &str) {
+ let delta = json!({"id":"code-model","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"code-call","type":"function","function":{"name":"exec","arguments":json!({"code":code}).to_string()}}]},"finish_reason":null}]});
+ let body = format!(
+ "data: {delta}\n\ndata: {{\"id\":\"code-model\",\"choices\":[{{\"index\":0,\"delta\":{{}},\"finish_reason\":\"tool_calls\"}}]}}\n\ndata: [DONE]\n\n"
+ );
+ socket.write_all(format!("HTTP/1.1 200 OK\r\nContent-Type: text/event-stream\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{body}", body.len()).as_bytes()).await.unwrap();
+}
+
+#[tokio::test]
+async fn code_mode_native_file_writes_obey_the_live_session_permission_boundary() {
+ tokio::time::timeout(Duration::from_secs(60), async {
+ for writable in [true, false] {
+ let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
+ let base = format!("http://{}/v1", listener.local_addr().unwrap());
+ let mut setup = Setup::files("write");
+ setup.nestable = true;
+ let fixture = Fixture::with_services(&base, 1, None, None, Some(setup)).await;
+ selection::edit(&fixture, |changes| {
+ changes.model_overrides = Patch::Set(BTreeMap::from([("fixture-model".into(), ModelOverride {
+ code_mode: Some(true), ..Default::default()
+ })]));
+ }).await;
+ let session = fixture.create("Code Mode files").await;
+ if !writable {
+ files::change(&fixture, &session, "read_only", false, true).await;
+ }
+ fixture.send(&session).await.unwrap();
+ let (mut first, _) = listener.accept().await.unwrap();
+ let prompt = request(&mut first).await;
+ assert!(prompt["tools"].as_array().unwrap().iter().any(|tool| tool["function"]["name"] == "exec"));
+ code_response(&mut first, "text(await tools.WorkspaceFile({path:'code-mode.txt',content:'native Code Mode write'}));").await;
+ let (mut next, _) = listener.accept().await.unwrap();
+ let observed = request(&mut next).await;
+ let tool = observed["messages"].as_array().unwrap().iter().find(|message| message["role"] == "tool").unwrap();
+ assert_eq!(tool["tool_call_id"], "code-call");
+ let target = fixture.workspace.join("code-mode.txt");
+ assert_eq!(target.exists(), writable);
+ if writable {
+ assert_eq!(std::fs::read_to_string(target).unwrap(), "native Code Mode write");
+ }
+ assert!(fixture.store.pending_interactions(&session).await.unwrap().is_empty());
+ response(&mut next).await;
+ fixture.drained().await;
+ fixture.app.shutdown().await.unwrap();
+ fixture.config.shutdown().await.unwrap();
+ }
+ }).await.unwrap();
+}
diff --git a/plugins/agent/native/src/tools.rs b/plugins/agent/native/src/tools.rs
index 00b6d7c83d..3da5f62b3a 100644
--- a/plugins/agent/native/src/tools.rs
+++ b/plugins/agent/native/src/tools.rs
@@ -192,7 +192,11 @@ pub(crate) fn catalog(
},
freeform: None,
},
- nesting: ToolNesting::DirectOnly,
+ nesting: if selection.nestable {
+ ToolNesting::Nestable
+ } else {
+ ToolNesting::DirectOnly
+ },
semantics: if method.mode == MethodMode::Mutation {
ToolSemantics::ExclusiveStep
} else {
diff --git a/products/maka/bundle/src/installation.ts b/products/maka/bundle/src/installation.ts
index 962f344561..6cf6644bc3 100644
--- a/products/maka/bundle/src/installation.ts
+++ b/products/maka/bundle/src/installation.ts
@@ -44,7 +44,15 @@ export function installation(
description: string,
result: 'json' | 'image' = 'json',
) =>
- tools.push({ import: service, method, name, description, result, confirmation: 'preapproved' });
+ tools.push({
+ import: service,
+ method,
+ name,
+ description,
+ result,
+ confirmation: 'preapproved',
+ nestable: ['files', 'processes', 'web', 'skills'].includes(service),
+ });
add('files', 'readText', 'Read', 'Read text from a file in the selected workspace.');
add('files', 'readImage', 'ReadImage', 'Read an image in the selected workspace.', 'image');
add('files', 'glob', 'Glob', 'Find files in the selected workspace.');
diff --git a/products/maka/cli/notices.json b/products/maka/cli/notices.json
index aa194fa09b..7453a51e69 100644
--- a/products/maka/cli/notices.json
+++ b/products/maka/cli/notices.json
@@ -4,9 +4,9 @@
"Cargo.toml": "83d55b86f5c48c71bc65ff6f3a235d166e56c050ffcc1027fe390a836aee3a11",
"package-lock.json": "a5af15aca21fabe0e1bdd48784167df4dc81cee17777d54861dcbd641168a4eb",
"package.json": "38baf3beeb5876849ca16e31868d59bfaee769f260c7555b4a8a1847b92e28a1",
- "packages/plugin-sdk/src/configurations.ts": "ec70531da1097cae8d3835fcdeab73e2354e955b807a25f3cdbdab35005297a1",
+ "packages/plugin-sdk/src/configurations.ts": "2da8c45bdfc3fdfc1239e956d9eb5ce4e3acc42e8c40fe5e4896c4b4d35f83e1",
"packages/plugin-sdk/src/contracts.ts": "63010ab6d927cf45831d5d02afe93efef07c785b0a5cfbd09ed857a99d7d3118",
- "packages/plugin-sdk/src/generated/runtime.ts": "d2407ac687fe751518769ac380c4ac599bfc184f224642330bba19515afb8709",
+ "packages/plugin-sdk/src/generated/runtime.ts": "ac2d5f68ef4cde2d8ac560d7b6a98f43aebf1da87aadf56da50e4247d7418607",
"packages/plugin-sdk/src/index.ts": "27b68be5a29d1857f7fe361c8c678e77ba21413c79ec3870c1ce30d0faf9323f",
"packages/plugin-sdk/src/native.ts": "e207147ef7d3e2c39533c1ff24aae942c86da5350f8b282bae0d4fb417bbf37b",
"packages/plugin-sdk/src/ui.ts": "d6c64e9406c41ad6bbda73435b559aad24c31adb3c5bbb4ab6f49fff8a8330ca",
@@ -365,7 +365,7 @@
"products/maka/bundle/package.json": "dd17e0a82ab68c03cdfd8adb3e243d4c5e881530db66ff311cb642b3bdc1f7c0",
"products/maka/bundle/scripts/build.mjs": "db11d8cd6f29ef7ead087261848568da1ad3889a870a89f23fa969449d769d47",
"products/maka/bundle/src/composition.ts": "d5e8142d7839654ffa732e99f41bca1c19c364df20529de6f1e56db4ec880198",
- "products/maka/bundle/src/installation.ts": "25908ab7c6a6416fa2c452e9f25840cb9c542c6b99a7eb28ea71725adf220738",
+ "products/maka/bundle/src/installation.ts": "73cee5001b1ec45f45254932a9497ec1570f15dcee33de24a6a90ae4ce4deb6f",
"products/maka/cli/Cargo.toml": "dff55e4f17eecb5107b75c179e0077f122409503993d19bd24c70e5c9380ffba",
"products/maka/cli/build.rs": "98452274bb0f20fa55fda5a20313f81740e759652aa4227fba0b0de5e3f4cc29",
"products/maka/cli/build/product.rs": "02555a9bd0181080a061fe35b1b1caabec6c2dc338a35923b49f59f010892a6c",
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org
For additional commands, e-mail: commits-help@maka.apache.org