bkai-init 0.1.0rc10__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 (77) hide show
  1. bkai_init-0.1.0rc10/Dockerfile +23 -0
  2. bkai_init-0.1.0rc10/MANIFEST.in +5 -0
  3. bkai_init-0.1.0rc10/Makefile +141 -0
  4. bkai_init-0.1.0rc10/PKG-INFO +351 -0
  5. bkai_init-0.1.0rc10/bkai_init/__init__.py +19 -0
  6. bkai_init-0.1.0rc10/bkai_init/__main__.py +5 -0
  7. bkai_init-0.1.0rc10/bkai_init/api/__init__.py +5 -0
  8. bkai_init-0.1.0rc10/bkai_init/api/client.py +398 -0
  9. bkai_init-0.1.0rc10/bkai_init/api/uploads.py +63 -0
  10. bkai_init-0.1.0rc10/bkai_init/cli.py +293 -0
  11. bkai_init-0.1.0rc10/bkai_init/enums.py +67 -0
  12. bkai_init-0.1.0rc10/bkai_init/services/__init__.py +20 -0
  13. bkai_init-0.1.0rc10/bkai_init/services/initializer.py +155 -0
  14. bkai_init-0.1.0rc10/bkai_init/services/inspection.py +483 -0
  15. bkai_init-0.1.0rc10/bkai_init/services/knowledge.py +33 -0
  16. bkai_init-0.1.0rc10/bkai_init/services/planning.py +177 -0
  17. bkai_init-0.1.0rc10/bkai_init/services/references.py +149 -0
  18. bkai_init-0.1.0rc10/bkai_init/services/scaffolding.py +167 -0
  19. bkai_init-0.1.0rc10/bkai_init/services/sync.py +732 -0
  20. bkai_init-0.1.0rc10/bkai_init/settings.py +175 -0
  21. bkai_init-0.1.0rc10/bkai_init/utils/__init__.py +1 -0
  22. bkai_init-0.1.0rc10/bkai_init/utils/archive.py +84 -0
  23. bkai_init-0.1.0rc10/bkai_init/utils/codes.py +37 -0
  24. bkai_init-0.1.0rc10/bkai_init/utils/exceptions.py +57 -0
  25. bkai_init-0.1.0rc10/bkai_init/utils/knowledge_archive.py +51 -0
  26. bkai_init-0.1.0rc10/bkai_init/utils/manifest.py +352 -0
  27. bkai_init-0.1.0rc10/bkai_init/utils/protocol.py +250 -0
  28. bkai_init-0.1.0rc10/bkai_init/utils/selection.py +37 -0
  29. bkai_init-0.1.0rc10/bkai_init/utils/variables.py +151 -0
  30. bkai_init-0.1.0rc10/bkai_init.egg-info/PKG-INFO +351 -0
  31. bkai_init-0.1.0rc10/bkai_init.egg-info/SOURCES.txt +75 -0
  32. bkai_init-0.1.0rc10/bkai_init.egg-info/dependency_links.txt +1 -0
  33. bkai_init-0.1.0rc10/bkai_init.egg-info/entry_points.txt +2 -0
  34. bkai_init-0.1.0rc10/bkai_init.egg-info/requires.txt +6 -0
  35. bkai_init-0.1.0rc10/bkai_init.egg-info/top_level.txt +1 -0
  36. bkai_init-0.1.0rc10/demo/Dockerfile +6 -0
  37. bkai_init-0.1.0rc10/demo/helm/Chart.yaml +6 -0
  38. bkai_init-0.1.0rc10/demo/helm/templates/bkai-init-job.yaml +67 -0
  39. bkai_init-0.1.0rc10/demo/helm/values.schema.json +39 -0
  40. bkai_init-0.1.0rc10/demo/helm/values.yaml +11 -0
  41. bkai_init-0.1.0rc10/demo/k8s-job.yaml +72 -0
  42. bkai_init-0.1.0rc10/demo/package/agents/demo_agent.yaml +33 -0
  43. bkai_init-0.1.0rc10/demo/package/agents/demo_child.yaml +38 -0
  44. bkai_init-0.1.0rc10/demo/package/bkai.yaml +12 -0
  45. bkai_init-0.1.0rc10/demo/package/knowledgebases/demo_docs/knowledgebase.yaml +12 -0
  46. bkai_init-0.1.0rc10/demo/package/knowledgebases/demo_docs/readme.md +3 -0
  47. bkai_init-0.1.0rc10/demo/package/skills/demo_skill/Dockerfile +3 -0
  48. bkai_init-0.1.0rc10/demo/package/skills/demo_skill/SKILL.md +9 -0
  49. bkai_init-0.1.0rc10/demo/package/skills/demo_skill/skill.yaml +8 -0
  50. bkai_init-0.1.0rc10/demo/readme.md +71 -0
  51. bkai_init-0.1.0rc10/docs/protocol.md +212 -0
  52. bkai_init-0.1.0rc10/pyproject.toml +29 -0
  53. bkai_init-0.1.0rc10/readme.md +337 -0
  54. bkai_init-0.1.0rc10/scripts/ci.py +178 -0
  55. bkai_init-0.1.0rc10/setup.cfg +4 -0
  56. bkai_init-0.1.0rc10/tests/test_archive.py +20 -0
  57. bkai_init-0.1.0rc10/tests/test_ci.py +222 -0
  58. bkai_init-0.1.0rc10/tests/test_cli.py +165 -0
  59. bkai_init-0.1.0rc10/tests/test_cli_environment.py +73 -0
  60. bkai_init-0.1.0rc10/tests/test_codes.py +218 -0
  61. bkai_init-0.1.0rc10/tests/test_context_window.py +52 -0
  62. bkai_init-0.1.0rc10/tests/test_demo.py +93 -0
  63. bkai_init-0.1.0rc10/tests/test_documentation.py +42 -0
  64. bkai_init-0.1.0rc10/tests/test_initializer.py +38 -0
  65. bkai_init-0.1.0rc10/tests/test_inspection.py +261 -0
  66. bkai_init-0.1.0rc10/tests/test_knowledge_sync.py +87 -0
  67. bkai_init-0.1.0rc10/tests/test_makefile.py +145 -0
  68. bkai_init-0.1.0rc10/tests/test_manifest.py +114 -0
  69. bkai_init-0.1.0rc10/tests/test_mcp_context.py +50 -0
  70. bkai_init-0.1.0rc10/tests/test_planning.py +356 -0
  71. bkai_init-0.1.0rc10/tests/test_protocol.py +283 -0
  72. bkai_init-0.1.0rc10/tests/test_services.py +74 -0
  73. bkai_init-0.1.0rc10/tests/test_settings.py +67 -0
  74. bkai_init-0.1.0rc10/tests/test_sync.py +425 -0
  75. bkai_init-0.1.0rc10/tests/test_variables.py +424 -0
  76. bkai_init-0.1.0rc10/tests/test_version_validation.py +90 -0
  77. bkai_init-0.1.0rc10/uv.lock +418 -0
@@ -0,0 +1,23 @@
1
+ ARG PYTHON_BASE_IMAGE=python:3.11-slim-bookworm
2
+
3
+ FROM ${PYTHON_BASE_IMAGE}
4
+
5
+ ARG BKAI_INIT_PACKAGE=bkai-init
6
+ ARG BKAI_INIT_VERSION
7
+ ARG PIP_INDEX_URL
8
+ ARG PIP_EXTRA_INDEX_URL
9
+ ARG PIP_FIND_LINKS
10
+ ARG PIP_TRUSTED_HOST
11
+
12
+ ENV PIP_DISABLE_PIP_VERSION_CHECK=1 \
13
+ PYTHONDONTWRITEBYTECODE=1 \
14
+ PYTHONUNBUFFERED=1
15
+
16
+ RUN test -n "${BKAI_INIT_VERSION}" \
17
+ && python -m pip install --no-cache-dir "${BKAI_INIT_PACKAGE}==${BKAI_INIT_VERSION}"
18
+
19
+ WORKDIR /workspace
20
+ USER 10001:10001
21
+
22
+ ENTRYPOINT ["bkai-init"]
23
+ CMD ["--help"]
@@ -0,0 +1,5 @@
1
+ exclude README.md
2
+ include readme.md Dockerfile Makefile uv.lock
3
+ recursive-include scripts *.py
4
+ recursive-include docs *.md
5
+ recursive-include demo *.md *.yaml *.json Dockerfile
@@ -0,0 +1,141 @@
1
+ ROOT_DIR?=$(abspath $(dir $(lastword $(MAKEFILE_LIST))))
2
+ UV?=uv
3
+ CONTAINER_TOOL?=podman
4
+ PACKAGE_NAME?=bkai-init
5
+ PACKAGE_VERSION?=$(shell cd ${ROOT_DIR} && $(UV) version --short)
6
+ IMAGE?=bkai-init:local
7
+ DEMO_IMAGE?=bkai-init-demo:local
8
+ IMAGE_BUILD_ARGS?=
9
+ DIST_DIR?=$(ROOT_DIR)/dist
10
+ CI_REPO_ROOT?=$(abspath $(ROOT_DIR)/../..)
11
+ CI_PYTHON?=python3
12
+ CI_HELPER=$(ROOT_DIR)/scripts/ci.py
13
+ ENV_FILE?=$(CI_REPO_ROOT)/.local/env_bkai_init
14
+ PACKAGE_FILE?=$(ROOT_DIR)/demo/package/bkai.yaml
15
+ TENANT_ID?=system
16
+ SPACE?=
17
+ RESOURCES?=
18
+ EXCLUDE_RESOURCES?=
19
+ CHECK?=false
20
+ PUBLISH?=false
21
+ PUBLISH_CONFIG_ONLY?=1
22
+ pytest = $(UV) run --project ${ROOT_DIR} --no-sync pytest -c ${ROOT_DIR}/pyproject.toml
23
+
24
+ .PHONY: ALL
25
+ ALL: test
26
+
27
+ ${ROOT_DIR}/uv.lock: ${ROOT_DIR}/pyproject.toml
28
+ cd ${ROOT_DIR} && $(UV) lock
29
+ cd ${ROOT_DIR} && $(UV) lock --check
30
+
31
+ .PHONY: init
32
+ init: uv-install
33
+ @echo "Project initialization complete."
34
+
35
+ .PHONY: uv-install
36
+ uv-install: ${ROOT_DIR}/uv.lock
37
+ $(UV) --version
38
+ cd ${ROOT_DIR} && $(UV) sync --extra test --inexact
39
+
40
+ .PHONY: test
41
+ test: uv-install
42
+ $(eval path ?= ${ROOT_DIR}/tests)
43
+ $(eval maxfail ?= --maxfail=2)
44
+ ${pytest} ${path} ${maxfail} ${args}
45
+
46
+ # Commit gate: always run the full offline suite, including generated packages and demo.
47
+ # Do not load ENV_FILE or accept a narrowed test path here.
48
+ .PHONY: check
49
+ check: uv-install
50
+ ${pytest} ${ROOT_DIR}/tests --maxfail=2
51
+
52
+ .PHONY: ci-test
53
+ ci-test: uv-install
54
+ $(eval path ?= ${ROOT_DIR}/tests)
55
+ ${pytest} ${path} --maxfail=2 ${args}
56
+
57
+ # local-test never writes remote resources. Use local-sync explicitly for writes.
58
+ .PHONY: local-test local-validate local-show local-diff local-plan local-sync
59
+ local-test: local-validate
60
+
61
+ local-validate: uv-install
62
+ @set -eu; \
63
+ space="$(or $(SPACE),$${BKAI_SPACE_ID:-})"; \
64
+ set --; if test -n "$$space"; then set -- --space "$$space"; fi; \
65
+ $(UV) run --project "$(ROOT_DIR)" --no-sync bkai-init validate -f "$(PACKAGE_FILE)" "$$@"
66
+
67
+ local-show local-diff local-plan local-sync: uv-install
68
+ @set -eu; \
69
+ test -f "$(ENV_FILE)" || { echo "ENV_FILE does not exist; specify the local env file" >&2; exit 1; }; \
70
+ env_file="$(ENV_FILE)"; case "$$env_file" in /*) ;; *) env_file="./$$env_file" ;; esac; \
71
+ set -a; . "$$env_file"; set +a; \
72
+ space="$(or $(SPACE),$${BKAI_SPACE_ID:-})"; \
73
+ set --; if test -n "$$space"; then set -- --space "$$space"; fi; \
74
+ $(UV) run --project "$(ROOT_DIR)" --no-sync bkai-init $(patsubst local-%,%,$@) \
75
+ -f "$(PACKAGE_FILE)" --tenant-id "$(TENANT_ID)" \
76
+ "$$@" \
77
+ $(if $(filter local-sync,$@),--confirm) \
78
+ $(foreach resource,$(RESOURCES),--resource "$(resource)") \
79
+ $(if $(filter local-sync local-plan,$@),$(foreach resource,$(EXCLUDE_RESOURCES),--exclude-resource "$(resource)")) \
80
+ $(if $(and $(filter local-diff,$@),$(filter true,$(CHECK))),--check) \
81
+ $(if $(and $(filter local-sync local-plan,$@),$(filter true,$(PUBLISH))),--publish --publish_config_only="$(PUBLISH_CONFIG_ONLY)")
82
+
83
+ .PHONY: build
84
+ build:
85
+ rm -rf "$(DIST_DIR)"
86
+ cd "$(ROOT_DIR)" && $(UV) build --no-sources --out-dir "$(DIST_DIR)"
87
+
88
+ .PHONY: publish
89
+ publish: build
90
+ cd "$(ROOT_DIR)" && $(UV) publish ${publish_args} "$(DIST_DIR)"/*
91
+
92
+ # Pipeline parameters and credentials are inherited from the process environment.
93
+ # Keep publication separate so both indexes receive the same checked artifacts.
94
+ .PHONY: ci-prepare ci-build ci-publish ci-snapshot
95
+ ci-prepare:
96
+ @cd "$(CI_REPO_ROOT)" && $(CI_PYTHON) "$(CI_HELPER)" prepare
97
+
98
+ ci-build: ci-prepare
99
+ @set -eu; \
100
+ cd "$(ROOT_DIR)"; \
101
+ original=$$(mktemp); \
102
+ cp pyproject.toml "$$original"; \
103
+ trap 'cp "$$original" pyproject.toml; rm -f "$$original"' EXIT; \
104
+ $(UV) version --frozen "$$(cat "$(CI_REPO_ROOT)/bkai-build/version.txt")"; \
105
+ $(MAKE) build DIST_DIR="$(CI_REPO_ROOT)/bkai-build/dist"
106
+ $(CI_PYTHON) -m twine check --strict "$(CI_REPO_ROOT)"/bkai-build/dist/*
107
+ $(UV) venv --clear --python "$(CI_PYTHON)" "$(CI_REPO_ROOT)/.bkai-smoke"
108
+ $(UV) pip install --python "$(CI_REPO_ROOT)/.bkai-smoke/bin/python" "$(CI_REPO_ROOT)"/bkai-build/dist/*.whl
109
+ cd /tmp && "$(CI_REPO_ROOT)/.bkai-smoke/bin/bkai-init" --help
110
+ $(MAKE) ci-snapshot
111
+
112
+ ci-snapshot:
113
+ @cd "$(CI_REPO_ROOT)" && $(CI_PYTHON) "$(CI_HELPER)" snapshot
114
+
115
+ ci-publish:
116
+ @cd "$(CI_REPO_ROOT)" && $(CI_PYTHON) "$(CI_HELPER)" publish
117
+
118
+ .PHONY: image
119
+ image:
120
+ $(CONTAINER_TOOL) build \
121
+ --build-arg BKAI_INIT_PACKAGE=$(PACKAGE_NAME) \
122
+ --build-arg BKAI_INIT_VERSION=$(PACKAGE_VERSION) \
123
+ $(IMAGE_BUILD_ARGS) \
124
+ -t $(IMAGE) ${ROOT_DIR}
125
+
126
+ .PHONY: demo-image
127
+ demo-image: image
128
+ $(CONTAINER_TOOL) build -t $(DEMO_IMAGE) -f ${ROOT_DIR}/demo/Dockerfile ${ROOT_DIR}/demo
129
+
130
+ .PHONY: demo-test
131
+ demo-test: demo-image
132
+ $(CONTAINER_TOOL) run --rm --read-only --tmpfs /tmp:rw,size=64m \
133
+ $(DEMO_IMAGE) validate -f /bk-job/bkai.yaml $(if $(SPACE),--space "$(SPACE)")
134
+
135
+ .PHONY: clean
136
+ clean:
137
+ find ${ROOT_DIR} -type f -name '*.py[co]' -delete
138
+ find ${ROOT_DIR} -type d -name '__pycache__' -prune -exec rm -rf {} +
139
+ rm -rf ${ROOT_DIR}/.pytest_cache ${ROOT_DIR}/.ruff_cache
140
+ rm -rf ${ROOT_DIR}/build ${ROOT_DIR}/dist ${ROOT_DIR}/bkai_init.egg-info
141
+ rm -rf ${ROOT_DIR}/.venv
@@ -0,0 +1,351 @@
1
+ Metadata-Version: 2.4
2
+ Name: bkai-init
3
+ Version: 0.1.0rc10
4
+ Summary: Synchronize AIDEV agent packages through the application OpenAPI.
5
+ Author: Tencent BlueKing
6
+ License-Expression: MIT
7
+ Requires-Python: >=3.11
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: Jinja2<4,>=3.1.6
10
+ Requires-Dist: PyYAML>=6.0
11
+ Requires-Dist: requests>=2.31
12
+ Provides-Extra: test
13
+ Requires-Dist: pytest>=8.0; extra == "test"
14
+
15
+ # bkai-init
16
+
17
+ 将模块维护的 Agent Package 同步到 AIDEV。只调用平台 app 应用态接口,不回退 private。
18
+
19
+ [协议与接入目录](docs/protocol.md) · [主子智能体 Demo](demo/readme.md) · [支持范围](docs/protocol.md#支持范围)
20
+
21
+ 静态规则和公共默认值统一维护在 [bkai_init/settings.py](bkai_init/settings.py),包括变量白名单、code 命名、协议字段与范围校验。内部代码统一通过 `from bkai_init import settings` 获取;凭据仍由调用参数提供,不写入 settings。
22
+
23
+ 包顶层公开 `BkaiInit`、四类异常(`BkaiCliError`、`APIError`、`ConfigurationError`、`ManifestError`)及 `__version__`。服务类、返回类型从 `bkai_init.services` 导入;`SyncClient` 从 `services.sync`,`InspectionClient` / `inspection_as_dict` 从 `services.inspection` 导入。
24
+
25
+ ## pip 安装
26
+
27
+ 在发布相应版本的包仓库安装:
28
+
29
+ ```bash
30
+ python -m pip install "bkai-init==0.1.0"
31
+ bkai-init --help
32
+ ```
33
+
34
+ 使用内部包源时配置 `PIP_INDEX_URL`。此处版本仅作示例,需先确认目标包源已有该版本;本地构建不等于发布。
35
+
36
+ ## 快速生成模板
37
+
38
+ ```bash
39
+ # 默认单智能体;目标必须是新目录,无需凭据或 --space
40
+ bkai-init init ./bk-job --agent-code ai-job --name "作业助手"
41
+
42
+ # 按需生成并关联 Skill、知识库和带快捷指令的子智能体
43
+ bkai-init init ./bk-job-full --agent-code ai-job --name "作业助手" \
44
+ --with-skill job_skill --with-knowledgebase job_docs --with-subagent ai-job-child
45
+
46
+ bkai-init validate -f ./bk-job/bkai.yaml --space system-bkaidev
47
+ ```
48
+
49
+ 不指定 code/name 时默认 ai-demo / 初始化助手。目录已存在(包括空目录、符号链接)直接报错,不覆盖;不调用平台、不加载凭据、不发布。写入前使用现有完整协议校验。写入异常可能留下部分文件,检查后改用新目录重试。
50
+
51
+ 默认生成 bkai.yaml 和 agents/main.yaml;可选依赖同时加入资源清单及主智能体引用。知识库只生成 knowledgebase.yaml,不放示例 Markdown,避免误触发镜像删除;添加实际文档后同步前须确认删除范围。Skill 生成 skill.yaml / SKILL.md,自定义镜像按[协议](docs/protocol.md#文件白名单与变量替换)另行补充。MCP/角色不由 init 生成,按需手工配置。
52
+
53
+ Python 同样不需要凭据:
54
+
55
+ ```python
56
+ from bkai_init import BkaiInit
57
+
58
+ manifest = BkaiInit.init("./bk-job", agent_code="ai-job", name="作业助手",
59
+ skill_code="job_skill", knowledgebase_code="job_docs",
60
+ subagent_code="ai-job-child")
61
+ BkaiInit(space="system-bkaidev").validate(manifest)
62
+ ```
63
+
64
+ init 只是生成模板,不是完整业务实现;按用途完善 Prompt 和 Skill。新建主子智能体的同步仍遵循下文子智能体发布约束。
65
+
66
+ `model.context_window` 是会话轮次,只接受 1~30 的整数,默认模板填写 16;不是模型上下文 token 数,不能填写 256。所有资源在远程请求前校验,非法值不会自动截断。
67
+
68
+ 开发提交前在包目录运行 `make check`,执行全量本地测试(包含模板、Demo 与字段边界校验),不加载环境凭据或同步线上资源。安装仓库提交钩子后,修改 bkai-init 文件时会自动执行此检查,包含 settings.py。
69
+
70
+ ## CLI 调用
71
+
72
+ 先按[协议](docs/protocol.md)准备 `bkai.yaml` 及资源。凭据放在本机 `.local/env_bkai_init` 或部署环境,CLI 不自动加载 env 文件:
73
+
74
+ ```bash
75
+ set -a
76
+ source .local/env_bkai_init
77
+ set +a
78
+
79
+ # 仅本地校验,不需要凭据
80
+ bkai-init validate -f /bk-job/bkai.yaml --space system-bkaidev
81
+
82
+ # 查看、对比线上配置(不写入)
83
+ bkai-init show -f /bk-job/bkai.yaml --tenant-id system --space system-bkaidev --format json
84
+ bkai-init diff -f /bk-job/bkai.yaml --tenant-id system --space system-bkaidev
85
+
86
+ # 同步会创建或更新资源
87
+ bkai-init sync -f /bk-job/bkai.yaml --tenant-id system --space system-bkaidev --confirm
88
+ ```
89
+
90
+ | 参数 / 环境变量 | 说明 |
91
+ | --- | --- |
92
+ | `--base-url` / `BKAI_BASE_URL` | 必需。未设置时使用 `BK_API_URL_TMPL`,仅将 `{api_name}` 替换为 `bk_aidev`;支持服务根地址、网关 stage 或完整 `/openapi/aidev/app/v1` 前缀 |
93
+ | `--app-code` / `BKAI_APP_CODE` | 必需。蓝鲸应用编码,未设置时使用 `BKPAAS_APP_ID` |
94
+ | `--app-secret` / `BKAI_APP_SECRET` | 必需。应用密钥,未设置时使用 `BKPAAS_APP_SECRET` |
95
+ | `--access-token` / `BKAI_ACCESS_TOKEN` | 可选,兼容 `ACCESS_TOKEN`;token 不替代应用空间授权 |
96
+ | `--username` / `BKAI_USERNAME` | 可选,传递调用用户名 |
97
+ | `--tenant-id` | 默认 `system`,只通过参数传入 |
98
+ | `--space` | 默认 `bkaidev`,显式传值时不可为空;多租户传完整空间 ID,如 `system-bkaidev`,不会自动拼接租户前缀。所有资源统一使用此空间,旧 `metadata.space` 不再生效 |
99
+ | `--timeout` | 单次请求超时,默认 60 秒 |
100
+ | `--var KEY=VALUE` | 可重复;仅替换协议 YAML 与已声明 Skill 根目录 Dockerfile,详见[变量规则](docs/protocol.md#文件白名单与变量替换) |
101
+
102
+ CLI 不自动读取 `BKAI_SPACE_ID`;需要时显式传 `--space "$BKAI_SPACE_ID"`。不在命令示例、镜像或 Git 中保存真实凭据。
103
+
104
+ 以上三项逐项按 **命令行参数 > BKAI 环境变量 > PaaS 内置环境变量** 取值,可混合来源。空的 BKAI 环境变量视为未设置;命令行显式传空值会报缺参,不回退。`BK_API_URL_TMPL` 例如 `https://{api_name}.example.com/`,解析为 `https://bk_aidev.example.com/`;其余路径保持不变,不自动追加 Stage。Python 类仍显式接收调用参数,不自动加载环境变量。
105
+
106
+ PaaS 已注入 `BK_API_URL_TMPL`、`BKPAAS_APP_ID`、`BKPAAS_APP_SECRET` 时无需重复配置 BKAI 同名用途变量。容器或 Helm Job 需确保这三个变量实际注入进程;CLI 不会获取宿主机或其它容器的环境变量。
107
+
108
+ Python `BkaiInit()` 同样默认使用 `bkaidev`;多租户部署使用 `BkaiInit(space="system-bkaidev")`。下列显式传入 `system-bkaidev` 的示例适用于多租户部署。
109
+
110
+ ### 传入部署变量
111
+
112
+ Demo Skill 的 Dockerfile 使用短镜像名 `bkdbm-aidev-skills-env:0.0.1-alpha.13`。平台构建时按 `SKILL_SANDBOX_BASE_IMAGE_PREFIX`(对齐 Helm `global.imageRegistry`)补仓库前缀;Helm Job 不必传 registry 变量。需要覆盖完整地址时,再在已有 Dockerfile 中使用变量:
113
+
114
+ 在 Skill 根目录 Dockerfile 中引用基础镜像:
115
+
116
+ ```dockerfile
117
+ FROM {{ SKILL_BASE_IMAGE }}
118
+ ```
119
+
120
+ ```bash
121
+ bkai-init sync -f /bk-job/bkai.yaml --space system-bkaidev --confirm \
122
+ --var SKILL_BASE_IMAGE=registry.example.com/team/skill:1.0
123
+ ```
124
+
125
+ Python 调用同样支持:
126
+
127
+ ```python
128
+ from bkai_init import BkaiInit
129
+
130
+ initializer = BkaiInit(
131
+ space="system-bkaidev",
132
+ variables={"SKILL_BASE_IMAGE": "registry.example.com/team/skill:1.0"},
133
+ )
134
+ initializer.validate("/bk-job/bkai.yaml")
135
+ # 远程操作另需传入 base_url、app_code、app_secret,见下文。
136
+ ```
137
+
138
+ 也可以直接在变量引用处配置默认值(标准 Jinja 语法):
139
+
140
+ ```dockerfile
141
+ FROM {{ SKILL_BASE_IMAGE | default("registry.example.com/team/skill:1.0") }}
142
+ ```
143
+
144
+ 未传该变量时使用默认值;CLI `--var` 或 Python `variables` 显式传值时优先使用传入值,包括空字符串。YAML 示例:`name: "{{ SKILL_NAME | default('demo') }}"`。
145
+
146
+ 仅允许简单变量及 `default("字符串")`,不支持第二个参数、其它过滤器或模板功能,替换结果不再次渲染。不改源文件,不处理 Markdown、脚本或嵌套 Dockerfile。不提供独立的 Skill 镜像字段。
147
+
148
+ ### 查看指定资源
149
+
150
+ ```bash
151
+ # 单个资源
152
+ bkai-init show -f /bk-job/bkai.yaml --resource agent/ai-job-assist --space system-bkaidev
153
+
154
+ # 多个资源,也可重复传入 --resource
155
+ bkai-init show -f /bk-job/bkai.yaml --space system-bkaidev \
156
+ --resource skill/job_skill knowledgebase/job_docs --format json
157
+ ```
158
+
159
+ 资源必须在 Package 清单中;省略 `--resource` 查看全包,指定后只请求并输出所选资源,不额外查询其依赖。未知编码或空集合会在请求前报错,全包本地格式校验仍保留。无论选择哪些资源,均使用命令指定的空间。
160
+
161
+ `show` 不修改资源,不提供权限查询,也不支持 `--exclude-resource`。`diff` 同样支持 `--resource`,资源选择规则与 show 一致。
162
+
163
+ ### 同步预览与 CI 检查
164
+
165
+ ```bash
166
+ bkai-init plan -f /bk-job/bkai.yaml --resource agent/ai-job-assist --format json --space system-bkaidev
167
+ bkai-init sync -f /bk-job/bkai.yaml --space system-bkaidev
168
+ bkai-init diff -f /bk-job/bkai.yaml --resource agent/ai-job-assist --check --space system-bkaidev
169
+ ```
170
+
171
+ `plan` / 不带 `--confirm` 的 `sync` 只读取线上配置,不上传、创建、更新或发布。输出实际租户、资源空间、create/update/skip、差异、依赖来源、执行顺序和阻塞原因;支持资源选择、黑名单和发布参数。未选或排除的资源不会同步,其依赖需在线上存在。`ready` 仅表示已执行的检查未发现阻塞,不保证写权限、全部服务端校验或执行成功;已有资源即使无可见差异仍显示 update,与 sync 的行为一致。确认执行时增加 `--confirm`;不再提供 `--dry-run`。
172
+
173
+ `diff --check`:0 无差异,1 执行错误,2 有差异,3 无法完整比较。不可比较优先于有差异;不加 `--check` 保持原行为。Skill 文件摘要、envs 值、角色标签等未回显内容明确标记未知,不将其视为一致。
174
+
175
+ ### 同步并发布智能体
176
+
177
+ ```bash
178
+ # 显式开启发布;默认只发布配置,先子后主
179
+ bkai-init sync -f /bk-job/bkai.yaml --confirm --publish --publish_config_only=1 --space system-bkaidev
180
+
181
+ # 只预览包括发布的计划,不执行
182
+ bkai-init plan -f /bk-job/bkai.yaml --publish --space system-bkaidev
183
+
184
+ # 明确改用平台常规发布流程
185
+ bkai-init sync -f /bk-job/bkai.yaml --confirm --publish --publish_config_only=0 --space system-bkaidev
186
+ ```
187
+
188
+ 确认执行后,未指定 `--publish` 时仅同步草稿。Agent 不接受配置版本;发布请求不传 version,由平台分配,计划中显示 `auto`。脚本检查发布成功状态,并通过详情回读确认接口返回的版本;不覆盖已发布版本,发布失败时停止。
189
+
190
+ 主智能体仍只能引用已发布的子智能体和该版本中的指令。开启发布后,所选子智能体先同步并发布,再从发布版本展开主智能体的指令引用;未选或排除的子智能体不会发布。发布失败、非成功状态、缺少版本或回读不一致时立即停止,不继续写主智能体,也不自动回滚。常规发布可能异步完成,需到平台确认后再继续;脚本不自动重试发布。
191
+
192
+ ### 指定同步资源
193
+
194
+ ```bash
195
+ # 一个或多个资源;--resource 可重复传入
196
+ bkai-init sync -f /bk-job/bkai.yaml --space system-bkaidev --confirm \
197
+ --resource skill/job_skill knowledgebase/job_docs
198
+
199
+ # 跳过手工修改的资源,避免覆盖
200
+ bkai-init sync -f /bk-job/bkai.yaml --space system-bkaidev --confirm \
201
+ --exclude-resource agent/ai-job-assist
202
+ ```
203
+
204
+ 类型使用小写 `kind/code`。省略 `--resource` 表示全包同步,黑名单优先;未知资源或 Python 空集合会报错。不自动同步未选中的依赖,只选 Agent 时依赖需已存在。
205
+
206
+ **同步前先查看 plan / diff。** Agent 更新是整配置覆盖,失败不保证回滚。知识库目录含 Markdown 时会同步 ZIP,并移除线上目标目录中不在本地的内容。完整边界见[协议说明](docs/protocol.md#知识库文档同步)。
207
+
208
+ APIGW MCP 查询会携带已存在智能体的 `agent_code`,平台检查调用应用是否获授该智能体所在空间的权限。新建智能体预检查只查询公开 MCP;要引用非公开 MCP,需先创建智能体并完成网关授权。`plan` 不为查询授权提前创建资源。
209
+
210
+ ### 同步知识库文档
211
+
212
+ ```bash
213
+ bkai-init sync -f /bk-job/bkai.yaml --tenant-id system --space system-bkaidev \
214
+ --resource knowledgebase/job_docs --confirm
215
+ ```
216
+
217
+ 目录内的 Markdown 和图片按原层级打包,不替换正文变量、不包含根目录 `knowledgebase.yaml`。无文档时仅更新知识库配置,不清空线上目录。
218
+
219
+ 流程:app `upload/url` 获取临时授权 → PUT 直传 BKRepo → app `upload/status` 校验大小及 SHA256 → app `knowledges/archive/import` 提交。提交成功后继续同步后续资源,不等待导入任务完成。上传失败时停止,不回退 private 或网关文件上传。
220
+
221
+ 申请临时地址只发送空间、模块和文件名,不发送 `file_size`、`sha256`。上传后仍使用本地大小和摘要对比平台返回的实际元数据,确认一致后才提交导入。
222
+
223
+ 上传连接不携带应用凭据,不输出签名 URL。上传超时会先核对上传状态,不自动重复 PUT;导入接口若直接返回失败或部分成功则命令报错,不自动取消或重提,应先到平台确认。`show` 仍仅查看配置;`diff` 不比较文档内容,会标记无法完整比较。
224
+
225
+ ## Python 调用
226
+
227
+ 安装同一 pip 包后,统一从 `bkai_init` 导入:
228
+
229
+ ```python
230
+ import logging
231
+ import os
232
+ import sys
233
+
234
+ from bkai_init import BkaiInit, BkaiCliError
235
+
236
+ logging.basicConfig(level=logging.INFO, stream=sys.stdout)
237
+
238
+ # 无凭据也可进行本地校验
239
+ BkaiInit().validate("bkai.yaml")
240
+
241
+ initializer = BkaiInit(
242
+ base_url=os.environ["BKAI_BASE_URL"],
243
+ app_code=os.environ["BKAI_APP_CODE"],
244
+ app_secret=os.environ["BKAI_APP_SECRET"],
245
+ access_token=os.environ.get("BKAI_ACCESS_TOKEN") or os.environ.get("ACCESS_TOKEN"),
246
+ tenant_id="system",
247
+ space="system-bkaidev",
248
+ )
249
+
250
+ try:
251
+ online = initializer.show("bkai.yaml", resources={"agent/ai-job-assist"})
252
+ differences = initializer.diff("bkai.yaml", resources={"agent/ai-job-assist"})
253
+ preview = initializer.plan("bkai.yaml", publish=True, publish_config_only=True)
254
+ # 显式选择要写入的资源;省略 resources 表示全包同步
255
+ report = initializer.sync(
256
+ "bkai.yaml",
257
+ resources={"skill/job_skill", "knowledgebase/job_docs"},
258
+ excludes={"agent/ai-job-assist"},
259
+ )
260
+ # 完整同步并发布主子智能体时,显式传 publish=True(默认只发布配置)
261
+ # report = initializer.sync("bkai.yaml", publish=True, publish_config_only=True)
262
+ except BkaiCliError as exc:
263
+ logging.error("初始化失败:%s", exc)
264
+ raise
265
+ ```
266
+
267
+ 返回值分别为 `PackageInspection`、`tuple[ResourceDiff, ...]`、`PackagePlan` 和 `SyncReport`,均可从包级导入。同步资源必须与自己的清单编码一致。Python 的 `sync()` 本身就是显式执行,不需要 confirm 参数;只读预览调用 `plan()`。
268
+
269
+ 过程日志统一使用 logging。CLI 默认 INFO 输出到 stdout;类调用由应用配置日志,不修改 root logger。show 的 JSON/YAML 和 diff 的结果不带日志前缀;CLI 执行错误(含接口 URL、请求参数、输出和处理说明)返回 1 并写入 stdout,参数错误由 argparse 输出到 stderr。
270
+
271
+ ## Dockerfile 与镜像调用
272
+
273
+ [基础 Dockerfile](Dockerfile) 不复制源码,只通过 pip 安装指定版本。交付顺序为:**构建包 → 发布包 → 构建基础镜像 → 构建模块镜像**。
274
+
275
+ 在本目录执行:
276
+
277
+ ```bash
278
+ make build
279
+ make publish # 显式发布到配置的包仓库
280
+ make image PACKAGE_VERSION=0.1.0 IMAGE=bkai-init:local
281
+
282
+ # 模块镜像继承基础镜像,只增加初始化目录
283
+ podman build -f demo/Dockerfile \
284
+ --build-arg BKAI_INIT_IMAGE=bkai-init:local \
285
+ -t bkai-init-demo:local demo
286
+ ```
287
+
288
+ 基础镜像支持 `PYTHON_BASE_IMAGE`、`BKAI_INIT_PACKAGE`、`BKAI_INIT_VERSION` 和 pip 包源构建参数;可通过 `make image IMAGE_BUILD_ARGS="..."` 传入。不要通过构建参数传真实包源凭据。
289
+
290
+ [模块 Dockerfile](demo/Dockerfile) 将资源复制到 `/bk-job`,继承 `bkai-init` 入口。已有包源版本时,`make demo-test PACKAGE_VERSION=0.1.0 SPACE=system-bkaidev` 可构建镜像并仅执行 validate。
291
+
292
+ ```bash
293
+ # 先本地验证,不访问平台
294
+ podman run --rm bkai-init-demo:local validate -f /bk-job/bkai.yaml --space system-bkaidev
295
+
296
+ # 环境变量需先加载到宿主环境;容器继承应用凭据
297
+ # 这里只同步依赖;完整初始化主子智能体时使用 --publish
298
+ podman run --rm \
299
+ -e BKAI_BASE_URL -e BKAI_APP_CODE -e BKAI_APP_SECRET \
300
+ -e BKAI_ACCESS_TOKEN -e ACCESS_TOKEN \
301
+ bkai-init-demo:local sync -f /bk-job/bkai.yaml --confirm \
302
+ --tenant-id system --space system-bkaidev \
303
+ --resource skill/bkai_init_demo_skill knowledgebase/bkai_init_demo_docs
304
+ ```
305
+
306
+ ## Helm 接入
307
+
308
+ 模块镜像需包含 `bkai-init` 和清单目录,并推送到集群可访问的镜像仓库。将[Job 模板](demo/helm/templates/bkai-init-job.yaml)合入业务 Chart,通过 values 控制:
309
+
310
+ ```yaml
311
+ image:
312
+ repository: example.invalid/modules/bk-job
313
+ tag: "1.0.0"
314
+ pullPolicy: IfNotPresent
315
+
316
+ bkai:
317
+ enabled: true
318
+ tenantId: system
319
+ space: system-bkaidev
320
+ packagePath: /bk-job/bkai.yaml
321
+ excludeResources: []
322
+ ```
323
+
324
+ - `enabled: false` 不生成 Job;启用时在 `post-install`、`post-upgrade` 执行 `sync --confirm`。模板固定携带确认参数,避免只预览而未同步。
325
+ - Job 复用模块的 `image`;`packagePath` 为镜像内路径,`excludeResources` 映射为多个 `--exclude-resource`。
326
+ - 业务 Chart 必须将现有环境变量注入逻辑接入 Job,提供 `BKAI_BASE_URL`、`BKAI_APP_CODE`、`BKAI_APP_SECRET`,或对应 PaaS 内置变量 `BK_API_URL_TMPL`、`BKPAAS_APP_ID`、`BKPAAS_APP_SECRET`,按需传 token。示例模板未内置这部分逻辑,不增加 `credentialsSecretName` 开关。
327
+ - 当前示例 Chart 执行全包同步但不发布;首次主子初始化时需由业务 Chart 显式给 Job 添加 `--publish`,默认只发布配置。示例不是部署成功证明。
328
+
329
+ ```bash
330
+ helm lint demo/helm
331
+ helm template bkai-init-demo demo/helm
332
+ ```
333
+
334
+ 以上只检查或渲染模板,不部署到集群。独立 Job 参考 [k8s-job.yaml](demo/k8s-job.yaml),其中 Secret 仅是向容器注入环境变量的一种示例,需按部署环境调整。
335
+
336
+ ## 本地开发与验证
337
+
338
+ ```bash
339
+ make init
340
+ make test # 单元测试,不调用线上接口
341
+ make local-test SPACE=system-bkaidev # Demo 本地校验,不加载凭据
342
+ make local-show ENV_FILE=/path/to/.local/env_bkai_init RESOURCES="agent/ai-bkai-demo"
343
+ make local-diff ENV_FILE=/path/to/.local/env_bkai_init
344
+ make local-diff ENV_FILE=/path/to/.local/env_bkai_init RESOURCES="agent/ai-bkai-demo" CHECK=true
345
+ make local-plan ENV_FILE=/path/to/.local/env_bkai_init PUBLISH=true
346
+ make local-sync ENV_FILE=/path/to/.local/env_bkai_init \
347
+ RESOURCES="skill/bkai_init_demo_skill knowledgebase/bkai_init_demo_docs"
348
+ make clean # 清理虚拟环境与构建产物
349
+ ```
350
+
351
+ Makefile 参数:`PACKAGE_FILE` 替换默认 Demo 清单,`TENANT_ID` 默认 system,`SPACE` 优先于 env 中的 `BKAI_SPACE_ID`,两者均未设置时使用 CLI 默认空间 bkaidev;多租户部署需设置完整空间 ID(如 system-bkaidev);`RESOURCES` 用于 show/diff/plan/sync,`EXCLUDE_RESOURCES` 用于 plan/sync;`CHECK=true` 开启 diff 检查,Make 会将非零子命令退出码包装为自己的失败退出码。plan/sync 可传 `PUBLISH=true` 和 `PUBLISH_CONFIG_ONLY=0`,后者只接受 1 / 0、默认 1,转为 CLI 的 `--publish_config_only=1` / `0`;默认不发布,发布时默认只发布配置。远程入口显式加载 `ENV_FILE`,默认是业务仓库根目录的 `.local/env_bkai_init`。只有 `local-sync` 写入平台,该入口固定带 `--confirm`;预览使用 `local-plan`。
@@ -0,0 +1,19 @@
1
+ """AIDEV Agent Package initialization CLI."""
2
+
3
+ import logging
4
+
5
+ from .services import BkaiInit
6
+ from .utils.exceptions import APIError, BkaiCliError, ConfigurationError, ManifestError
7
+
8
+ logging.getLogger(__name__).addHandler(logging.NullHandler())
9
+
10
+ __version__ = "0.1.0"
11
+
12
+ __all__ = [
13
+ "APIError",
14
+ "BkaiCliError",
15
+ "BkaiInit",
16
+ "ConfigurationError",
17
+ "ManifestError",
18
+ "__version__",
19
+ ]
@@ -0,0 +1,5 @@
1
+ """Run ``bkai-init`` with ``python -m bkai_init``."""
2
+
3
+ from .cli import main
4
+
5
+ raise SystemExit(main())
@@ -0,0 +1,5 @@
1
+ """AIDEV application OpenAPI client."""
2
+
3
+ from .client import AidevClient
4
+
5
+ __all__ = ["AidevClient"]