Skip to content

feat: add cli support#57

Merged
AQing-527 merged 1 commit into
mainfrom
feature/20260427_28974160_cli_support_github_clean_1
Apr 27, 2026
Merged

feat: add cli support#57
AQing-527 merged 1 commit into
mainfrom
feature/20260427_28974160_cli_support_github_clean_1

Conversation

@AQing-527
Copy link
Copy Markdown
Collaborator

This pull request introduces significant enhancements to the "experience disclosure" subsystem, improves Python string literal handling, and updates project versions. The main changes include the addition of progressive disclosure APIs and models for experience documents, better guidance and configuration for experience document access, and a safer, more robust approach to Python string literal serialization. Several new tests and configuration options have also been added.

Experience Disclosure Enhancements:

  • Introduced new model classes in ExperienceDisclosurePayloads for progressive disclosure: ReferenceManifestEntry, AssetManifestEntry, ReadExpDocRequest, ReadExpDocResponse, ReadExpDocument, and ReadExpDocError, supporting multi-layered experience document access and error reporting. Updated ReadExpResponse to include referenceManifest and assetManifest lists. [1] [2]
  • Updated ExperienceDisclosureService to populate referenceManifest and assetManifest in read() responses, and added necessary imports. [1] [2]
  • Improved prompt guidance in ExperienceDisclosurePromptContributor to explain progressive disclosure layers and usage of read_exp_doc, including limitations and correct access patterns.

Configuration and State Management:

  • Added readExpDocMaxPaths property to ExperienceExtensionProperties to limit the number of paths readable in a single read_exp_doc call, with corresponding getter/setter and wiring in auto-configuration. [1] [2] [3]
  • Introduced EXPERIENCE_READ_EXP_IDS session state key in CodeactStateKeys for tracking which experience IDs have been accessed, supporting session-level gating.

Python String Literal Handling:

  • Refactored Python string literal serialization in GraalCodeExecutor: replaced custom escaping logic with a robust toPythonStringLiteral method using JSON serialization as the primary approach, with a fallback for error cases. [1] [2]
  • Added unit tests in GraalCodeExecutorStringLiteralTest to verify correct escaping of special and multiline strings.

Documentation and Guidance:

  • Expanded the WRITE_CODE_DESCRIPTION in WriteCodeTool with clearer requirements for the code argument and best practices for writing complete Python functions in one go.

Project Version Updates:

  • Updated Maven module versions from 0.2.5 to 0.2.6 across all submodules to reflect ongoing development. [1] [2] [3] [4] [5]

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 27, 2026 08:53
Copy link
Copy Markdown
Collaborator

@canfuu canfuu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@AQing-527 AQing-527 merged commit 2fc7f17 into main Apr 27, 2026
3 checks passed
@AQing-527 AQing-527 deleted the feature/20260427_28974160_cli_support_github_clean_1 branch April 27, 2026 08:58
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR expands the “experience disclosure” and management subsystems to support progressive (L1/L2/L3) disclosure of experience documents, introduces CLI-bound skill import/export workflows (including references/assets handling), and hardens Python string literal serialization for Graal-based execution.

Changes:

  • Add progressive disclosure manifests (referenceManifest/assetManifest) and a gated read_exp_doc tool for on-demand reference document reads.
  • Extend skill package import/export to preserve references/assets, create CLI TOOL experiences, and add management-console UI for previewing and lazily loading assets + re-summarizing references.
  • Refactor Python string literal serialization to a JSON-based approach and add unit tests; bump module versions to 0.2.6.

Reviewed changes

Copilot reviewed 46 out of 46 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
pom.xml Bump parent version to 0.2.6.
assistant-agent-start/pom.xml Bump module version to 0.2.6.
assistant-agent-prompt-builder/pom.xml Bump module version to 0.2.6.
assistant-agent-management/pom.xml Bump module version; add JUnit Jupiter dependency for new tests.
assistant-agent-management/src/main/resources/static/exp-console/index.html Add References/Assets sections and a “Re-summarize” button in the edit modal.
assistant-agent-management/src/main/resources/static/exp-console/app.js Render references/assets, lazy-load asset content, resummarize references, import as package, and export as zip download.
assistant-agent-management/src/main/java/com/alibaba/assistant/agent/management/spi/SkillExchangeService.java Add exportSkillPackage(experienceId) SPI method.
assistant-agent-management/src/main/java/com/alibaba/assistant/agent/management/spi/ReferenceSummarizer.java Introduce SPI for generating reference descriptions (LLM-backed or noop).
assistant-agent-management/src/main/java/com/alibaba/assistant/agent/management/spi/ExperienceManagementService.java Add loadAsset and resummarizeReferences for console lazy-load and maintenance.
assistant-agent-management/src/main/java/com/alibaba/assistant/agent/management/model/SkillPackageImportResult.java Include tool experience IDs/previews and references/assets preview lists in import results.
assistant-agent-management/src/main/java/com/alibaba/assistant/agent/management/model/ExperienceVO.java Expose references and an asset projection (without raw content by default) to the console.
assistant-agent-management/src/main/java/com/alibaba/assistant/agent/management/internal/SkillPackageParser.java Parse package.json as structured metadata via Jackson.
assistant-agent-management/src/main/java/com/alibaba/assistant/agent/management/internal/SkillContentClassifier.java Classify skill package files into references vs assets + assign asset roles.
assistant-agent-management/src/main/java/com/alibaba/assistant/agent/management/internal/RepositoryBackedExperienceManagementService.java Implement asset loading + reference re-summarization using the summarizer SPI.
assistant-agent-management/src/main/java/com/alibaba/assistant/agent/management/internal/NoopReferenceSummarizer.java Default summarizer that always returns null (forces fallback descriptions).
assistant-agent-management/src/main/java/com/alibaba/assistant/agent/management/internal/LlmReferenceSummarizer.java Spring AI ChatModel-backed reference summarizer implementation.
assistant-agent-management/src/main/java/com/alibaba/assistant/agent/management/internal/InMemorySkillExchangeService.java Implement package import/export zip, CLI TOOL experience creation, and parallel description generation.
assistant-agent-management/src/main/java/com/alibaba/assistant/agent/management/internal/DescriptionResolver.java Centralize H1/frontmatter/LLM/fallback description resolution + SHA-256 hashing.
assistant-agent-management/src/main/java/com/alibaba/assistant/agent/management/controller/SkillExchangeController.java Add GET /export-package/{id} endpoint returning zip bytes with proper headers.
assistant-agent-management/src/main/java/com/alibaba/assistant/agent/management/controller/ExperienceManagementController.java Add GET /{id}/assets/** and POST /{id}/resummarize endpoints for the console.
assistant-agent-management/src/main/java/com/alibaba/assistant/agent/management/config/ExperienceConsoleAutoConfiguration.java Wire ReferenceSummarizer (LLM if available, else noop) into console services.
assistant-agent-management/src/test/java/com/alibaba/assistant/agent/management/internal/SkillPackageParserTest.java Add test verifying structured package.json metadata parsing.
assistant-agent-management/src/test/java/com/alibaba/assistant/agent/management/internal/InMemorySkillExchangeServiceTest.java Add tests for CLI-bound skill preview/import and references/assets processing.
assistant-agent-extensions/pom.xml Bump module version to 0.2.6.
assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/experience/model/Experience.java Add references and assets to the domain model for progressive disclosure & sandbox materialization.
assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/experience/model/ReferenceEntry.java New model for L3 reference documents (path/mediaType/description/content/hash/size).
assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/experience/model/AssetEntry.java New model for sandbox-only assets (role/content/base64/contentRef/hash/size).
assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/experience/model/CliRuntimeConstants.java Add shared constants for CLI tool naming/IDs and sandbox defaults.
assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/experience/model/ExperienceArtifact.java Extend ToolArtifact source docs and add CLI tool-specific fields.
assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/experience/disclosure/ExperienceDisclosurePayloads.java Add manifest models + ReadExpDocRequest/Response payloads; extend ReadExpResponse.
assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/experience/disclosure/ExperienceDisclosureService.java Populate manifests in read_exp and implement readDocs for read_exp_doc.
assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/experience/disclosure/ExperienceRuntimeToolStateInterceptor.java Track read_exp IDs in session state to gate read_exp_doc.
assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/experience/disclosure/ExperienceRuntimeModelInterceptor.java Register read_exp_doc tool, enforce session gate, and apply max-path limit.
assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/experience/disclosure/ExperienceDisclosurePromptContributor.java Update prompt guidance to describe L1/L2/L3 disclosure and sandbox asset access.
assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/experience/config/ExperienceExtensionProperties.java Add readExpDocMaxPaths configuration.
assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/experience/config/ExperienceDisclosureAutoConfiguration.java Wire readExpDocMaxPaths into ExperienceRuntimeModelInterceptor.
assistant-agent-extensions/src/test/java/com/alibaba/assistant/agent/extension/experience/disclosure/ExperienceDisclosurePromptContributorTest.java Add assertions covering new prompt guidance.
assistant-agent-extensions/src/main/java/com/alibaba/assistant/agent/extension/reply/tools/BaseReplyCodeactTool.java Ensure empty tool input schema returns valid JSON Schema object instead of {}.
assistant-agent-common/src/main/java/com/alibaba/assistant/agent/common/constant/CodeactStateKeys.java Add session key EXPERIENCE_READ_EXP_IDS used by read_exp_doc gate.
assistant-agent-common/pom.xml Bump module version to 0.2.6.
assistant-agent-core/pom.xml Bump module version to 0.2.6.
assistant-agent-core/src/main/java/com/alibaba/assistant/agent/core/executor/GraalCodeExecutor.java Replace custom escaping with toPythonStringLiteral using JSON serialization + fallback.
assistant-agent-core/src/test/java/com/alibaba/assistant/agent/core/executor/GraalCodeExecutorStringLiteralTest.java Add tests for escaping quotes and multiline strings.
assistant-agent-evaluation/pom.xml Bump module version to 0.2.6.
assistant-agent-autoconfigure/pom.xml Bump module version to 0.2.6.
assistant-agent-autoconfigure/src/main/java/com/alibaba/assistant/agent/autoconfigure/tools/WriteCodeTool.java Strengthen guidance to require complete code in a single call.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +617 to +618
setText('form-label-references', t('referencesLabel'));
setText('form-label-assets', t('assetsLabel'));
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

applyLocale() calls setText('form-label-references', ...), which sets textContent on the <label> that currently contains the #btn-resummarize button. This will remove the button from the DOM and break the re-summarize feature. Consider moving the label text into a dedicated child element (e.g., a <span id="form-label-references-text">) and only updating that span, or update setText/applyLocale to preserve existing child nodes.

Copilot uses AI. Check for mistakes.
Comment on lines +248 to +249
<label class="form-label" id="form-label-references">References <button type="button" id="btn-resummarize" class="btn btn--ghost" style="margin-left:8px;font-size:12px;padding:2px 8px;">Re-summarize</button></label>
<div id="form-references-list" class="form-textarea form-textarea--mono" style="min-height:80px;max-height:240px;overflow:auto;padding:8px;white-space:pre-wrap;"></div>
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#form-label-references contains both the label text and the #btn-resummarize button, but the JS i18n logic updates this label via textContent, which will delete the button node. Split the translatable text into a nested element (e.g. <span ...>) so localization can update text without removing the button.

Copilot uses AI. Check for mistakes.
Comment on lines 53 to +57
public ExperienceRuntimeModelInterceptor(ExperienceDisclosureService experienceDisclosureService,
ExperienceDisclosureContextResolver contextResolver,
ExperienceToolInvocationClassifier toolInvocationClassifier) {
this(experienceDisclosureService, contextResolver, toolInvocationClassifier, 3);
}
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default constructor hard-codes readExpDocMaxPaths to 3, but ExperienceExtensionProperties#readExpDocMaxPaths defaults to 6 and the 4-arg ctor uses 6 as fallback. This can lead to inconsistent limits depending on wiring path (auto-config vs manual/tests). Consider centralizing the default (single constant) or delegating the default ctor to the properties default.

Copilot uses AI. Check for mistakes.
Comment on lines +183 to +186
if (!refPaths.contains(requested)) {
response.getErrors().add(new ReadExpDocError(requested,
"unknown path; available references: " + String.join(", ", refPaths)));
continue;
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For unknown paths, the error message includes String.join(", ", refPaths). If an experience has many references this can make tool responses very large and slow to serialize/transfer. Consider limiting the returned list (e.g., first N paths + total count) or omitting it from the error entirely.

Copilot uses AI. Check for mistakes.
Comment on lines +188 to +191
ReferenceEntry ref = experience.getReferences().stream()
.filter(r -> requested.equals(r.getPath()))
.findFirst()
.orElse(null);
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

readDocs() does a linear experience.getReferences().stream().findFirst() for each requested path. If there are many references and multiple paths requested, this becomes O(n*m). Consider building a Map<String, ReferenceEntry> once (and reusing it for membership checks + lookup) to keep lookups O(1).

Copilot uses AI. Check for mistakes.
Comment on lines +480 to +482
// 控制台可见的单行概要;正式日志由上层记录。
System.out.println("[skill-import] summarize cost=" + elapsed + "ms ok=" + ok + " fail=" + fail
+ " total=" + pending.size());
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

batchResolveDescriptions writes import telemetry via System.out.println(...). In a server/library module this bypasses the project logging setup and can be noisy/unstructured in production. Use the existing logging framework (SLF4J) or remove the line (and rely on upstream logging) so output can be controlled via log levels/appenders.

Copilot uses AI. Check for mistakes.
List<ReferenceEntry> references,
List<AssetEntry> assets,
Map<String, String> descriptionCache) {
// SKILL.md 同时保留为 reference(role=skill-md),以便 read_exp_doc 可按 path 检索。
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says SKILL.md is kept as a reference with role=skill-md, but ReferenceEntry doesn't have a role field and the code doesn’t set one. This is misleading documentation; either adjust the comment to reflect the actual data model, or add/propagate a role field if downstream logic relies on it.

Suggested change
// SKILL.md 同时保留为 reference(role=skill-md),以便 read_exp_doc 可按 path 检索。
// SKILL.md 同时保留为 reference,以便 read_exp_doc 可按 path 检索。

Copilot uses AI. Check for mistakes.
sb.append("经验分为三类:COMMON 用于解释概念/产品术语,REACT 用于提供流程与策略参考,TOOL 用于能力判断、工具选择与调用路径判断。\n");
sb.append("披露方式分为两种:`DIRECT` 表示内容已满足高置信短文本条件,可直接利用;`PROGRESSIVE` 表示当前只给候选卡,需要完整正文时调用 `read_exp`。\n");
sb.append("渐进披露分三层:L1 候选卡(本块内容) → L2 `read_exp(id)` 返回 content + referenceManifest + assetManifest → L3 `read_exp_doc(id, paths)` 仅按需读取 referenceManifest 中的某些参考文档完整内容。\n");
sb.append("调用 `read_exp_doc` 前必须先 `read_exp(id)`,否则会返回错误:\"请先 read_exp(<id>),再 read_exp_doc\";单次最多读取若干个路径,超出会被截断。\n");
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guidance text says when read_exp_doc exceeds the path limit it will be "截断" (truncated), but ExperienceDisclosureService#readDocs returns an error and no documents when paths.size() > maxPaths. Please align the prompt guidance with the actual tool behavior to avoid the model taking an incorrect call pattern.

Suggested change
sb.append("调用 `read_exp_doc` 前必须先 `read_exp(id)`,否则会返回错误:\"请先 read_exp(<id>),再 read_exp_doc\";单次最多读取若干个路径,超出会被截断\n");
sb.append("调用 `read_exp_doc` 前必须先 `read_exp(id)`,否则会返回错误:\"请先 read_exp(<id>),再 read_exp_doc\";单次最多读取若干个路径,超出会返回错误,且不会返回任何文档内容\n");

Copilot uses AI. Check for mistakes.
Comment on lines +1838 to +1839
showToast(t('toastImportSuccess') || 'Import successful', 'success');
closeSkillImport();
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

toastImportSuccess is not defined in the I18N dictionaries, and t() always returns a non-empty string (falls back to the key), so t('toastImportSuccess') || 'Import successful' will never hit the fallback. This will display the literal key to users. Add a toastImportSuccess entry to both locales (or reuse an existing toast key) and drop the ineffective || fallback.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants