echotools 2.3.3__tar.gz → 2.3.4__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 (150) hide show
  1. {echotools-2.3.3 → echotools-2.3.4}/PKG-INFO +2 -3
  2. {echotools-2.3.3 → echotools-2.3.4}/pyproject.toml +3 -4
  3. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/fncall/prompt/history.py +49 -1
  4. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/fncall/prompt/inject.py +5 -1
  5. {echotools-2.3.3 → echotools-2.3.4}/src/echotools.egg-info/PKG-INFO +2 -3
  6. {echotools-2.3.3 → echotools-2.3.4}/README.md +0 -0
  7. {echotools-2.3.3 → echotools-2.3.4}/setup.cfg +0 -0
  8. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/__init__.py +0 -0
  9. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/_version.py +0 -0
  10. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/cache/__init__.py +0 -0
  11. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/cache/list_cache.py +0 -0
  12. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/cache/memory_cache.py +0 -0
  13. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/config/__init__.py +0 -0
  14. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/config/base.py +0 -0
  15. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/config/center.py +0 -0
  16. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/config/loader.py +0 -0
  17. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/config/merge.py +0 -0
  18. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/dispatch/__init__.py +0 -0
  19. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/dispatch/candidate.py +0 -0
  20. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/dispatch/dispatcher.py +0 -0
  21. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/dispatch/proxy_selector.py +0 -0
  22. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/dispatch/selector.py +0 -0
  23. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/dispatch/usage.py +0 -0
  24. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/errors/__init__.py +0 -0
  25. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/errors/base.py +0 -0
  26. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/errors/classify.py +0 -0
  27. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/errors/common.py +0 -0
  28. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/errors/http.py +0 -0
  29. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/events/__init__.py +0 -0
  30. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/events/bus.py +0 -0
  31. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/events/event.py +0 -0
  32. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/files/__init__.py +0 -0
  33. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/files/file_util.py +0 -0
  34. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/fncall/__init__.py +0 -0
  35. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/fncall/parsers/__init__.py +0 -0
  36. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/fncall/parsers/stream.py +0 -0
  37. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/fncall/parsers/xml_parser.py +0 -0
  38. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/fncall/prompt/__init__.py +0 -0
  39. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/fncall/prompt/templates.py +0 -0
  40. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/fncall/protocols/__init__.py +0 -0
  41. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/fncall/protocols/entml.py +0 -0
  42. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/fncall/registry.py +0 -0
  43. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/fncall/shared/__init__.py +0 -0
  44. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/fncall/shared/coercion.py +0 -0
  45. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/fncall/shared/loop_detect.py +0 -0
  46. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/fncall/shared/normalization.py +0 -0
  47. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/fncall/shared/xml_helpers.py +0 -0
  48. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/ids/__init__.py +0 -0
  49. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/ids/generator.py +0 -0
  50. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/io/__init__.py +0 -0
  51. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/io/io_utils.py +0 -0
  52. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/io/printstream.py +0 -0
  53. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/keys.py +0 -0
  54. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/lifecycle/__init__.py +0 -0
  55. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/lifecycle/manager.py +0 -0
  56. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/lifecycle/updater.py +0 -0
  57. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/logger/__init__.py +0 -0
  58. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/logger/manager.py +0 -0
  59. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/network/__init__.py +0 -0
  60. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/network/http_utils.py +0 -0
  61. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/plugin/__init__.py +0 -0
  62. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/plugin/base.py +0 -0
  63. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/plugin/discovery.py +0 -0
  64. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/plugin/registry.py +0 -0
  65. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/process/__init__.py +0 -0
  66. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/process/port.py +0 -0
  67. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/protocol/__init__.py +0 -0
  68. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/protocol/base.py +0 -0
  69. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/proxy/__init__.py +0 -0
  70. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/proxy/manager.py +0 -0
  71. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/py.typed +0 -0
  72. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/retry/__init__.py +0 -0
  73. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/retry/retry.py +0 -0
  74. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/runtime/__init__.py +0 -0
  75. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/runtime/collector.py +0 -0
  76. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/scheduler/__init__.py +0 -0
  77. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/scheduler/scheduler.py +0 -0
  78. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/sdk/__init__.py +0 -0
  79. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/sdk/facade.py +0 -0
  80. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/terminal/__init__.py +0 -0
  81. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/terminal/conpty.py +0 -0
  82. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/terminal/local.py +0 -0
  83. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/terminal/sanitize.py +0 -0
  84. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/terminal/session.py +0 -0
  85. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/terminal/ssh.py +0 -0
  86. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/terminal/tmux.py +0 -0
  87. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/tracing/__init__.py +0 -0
  88. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/tracing/context.py +0 -0
  89. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/tracing/span.py +0 -0
  90. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/tracing/tracer.py +0 -0
  91. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/translate.py +0 -0
  92. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/watcher/__init__.py +0 -0
  93. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/watcher/file_watcher.py +0 -0
  94. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/web/__init__.py +0 -0
  95. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/web/application.py +0 -0
  96. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/web/broker.py +0 -0
  97. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/web/input_box/app.js +0 -0
  98. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/web/input_box/file-zone/file-zone.js +0 -0
  99. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/web/input_box/fonts/inter-400.woff2 +0 -0
  100. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/web/input_box/fonts/inter-500.woff2 +0 -0
  101. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/web/input_box/fonts/inter-600.woff2 +0 -0
  102. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/web/input_box/fonts/tailwind.min.css +0 -0
  103. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/web/input_box/input-box.css +0 -0
  104. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/web/input_box/input-box.js +0 -0
  105. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/web/input_box/motion-kit/motion-kit.js +0 -0
  106. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/web/input_box/send-button/send-button.js +0 -0
  107. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/web/input_box/sortable-list/sortable-list.css +0 -0
  108. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/web/input_box/sortable-list/sortable-list.js +0 -0
  109. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/web/input_box/style.css +0 -0
  110. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/web/input_box/text-input/text-input.js +0 -0
  111. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/web/input_box/voice-input/voice-input.js +0 -0
  112. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/web/middleware.py +0 -0
  113. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/web/stats.py +0 -0
  114. {echotools-2.3.3 → echotools-2.3.4}/src/echotools/web/utils.py +0 -0
  115. {echotools-2.3.3 → echotools-2.3.4}/src/echotools.egg-info/SOURCES.txt +0 -0
  116. {echotools-2.3.3 → echotools-2.3.4}/src/echotools.egg-info/dependency_links.txt +0 -0
  117. {echotools-2.3.3 → echotools-2.3.4}/src/echotools.egg-info/requires.txt +0 -0
  118. {echotools-2.3.3 → echotools-2.3.4}/src/echotools.egg-info/top_level.txt +0 -0
  119. {echotools-2.3.3 → echotools-2.3.4}/tests/test_cache_retry.py +0 -0
  120. {echotools-2.3.3 → echotools-2.3.4}/tests/test_completion.py +0 -0
  121. {echotools-2.3.3 → echotools-2.3.4}/tests/test_config.py +0 -0
  122. {echotools-2.3.3 → echotools-2.3.4}/tests/test_config_extended.py +0 -0
  123. {echotools-2.3.3 → echotools-2.3.4}/tests/test_coverage_core.py +0 -0
  124. {echotools-2.3.3 → echotools-2.3.4}/tests/test_dispatch.py +0 -0
  125. {echotools-2.3.3 → echotools-2.3.4}/tests/test_dispatch_extended.py +0 -0
  126. {echotools-2.3.3 → echotools-2.3.4}/tests/test_dispatch_race.py +0 -0
  127. {echotools-2.3.3 → echotools-2.3.4}/tests/test_errors.py +0 -0
  128. {echotools-2.3.3 → echotools-2.3.4}/tests/test_errors_common.py +0 -0
  129. {echotools-2.3.3 → echotools-2.3.4}/tests/test_events.py +0 -0
  130. {echotools-2.3.3 → echotools-2.3.4}/tests/test_events_event.py +0 -0
  131. {echotools-2.3.3 → echotools-2.3.4}/tests/test_facade.py +0 -0
  132. {echotools-2.3.3 → echotools-2.3.4}/tests/test_fncall.py +0 -0
  133. {echotools-2.3.3 → echotools-2.3.4}/tests/test_ids.py +0 -0
  134. {echotools-2.3.3 → echotools-2.3.4}/tests/test_imports.py +0 -0
  135. {echotools-2.3.3 → echotools-2.3.4}/tests/test_io.py +0 -0
  136. {echotools-2.3.3 → echotools-2.3.4}/tests/test_keys.py +0 -0
  137. {echotools-2.3.3 → echotools-2.3.4}/tests/test_lifecycle.py +0 -0
  138. {echotools-2.3.3 → echotools-2.3.4}/tests/test_logger.py +0 -0
  139. {echotools-2.3.3 → echotools-2.3.4}/tests/test_merge.py +0 -0
  140. {echotools-2.3.3 → echotools-2.3.4}/tests/test_plugin.py +0 -0
  141. {echotools-2.3.3 → echotools-2.3.4}/tests/test_printstream.py +0 -0
  142. {echotools-2.3.3 → echotools-2.3.4}/tests/test_protocols.py +0 -0
  143. {echotools-2.3.3 → echotools-2.3.4}/tests/test_proxy.py +0 -0
  144. {echotools-2.3.3 → echotools-2.3.4}/tests/test_proxy_selector.py +0 -0
  145. {echotools-2.3.3 → echotools-2.3.4}/tests/test_runtime.py +0 -0
  146. {echotools-2.3.3 → echotools-2.3.4}/tests/test_scheduler.py +0 -0
  147. {echotools-2.3.3 → echotools-2.3.4}/tests/test_tracing.py +0 -0
  148. {echotools-2.3.3 → echotools-2.3.4}/tests/test_usage.py +0 -0
  149. {echotools-2.3.3 → echotools-2.3.4}/tests/test_web.py +0 -0
  150. {echotools-2.3.3 → echotools-2.3.4}/tests/test_web_broker.py +0 -0
@@ -1,15 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: echotools
3
- Version: 2.3.3
3
+ Version: 2.3.4
4
4
  Summary: 通用基础设施 SDK:配置、日志、事件、调度、插件、协议、调用链
5
5
  Author: nichengfuben
6
- License: MIT
6
+ License-Expression: MIT
7
7
  Project-URL: Homepage, https://github.com/nichengfuben/echotools
8
8
  Project-URL: Repository, https://github.com/nichengfuben/echotools
9
9
  Project-URL: Issues, https://github.com/nichengfuben/echotools/issues
10
10
  Classifier: Development Status :: 4 - Beta
11
11
  Classifier: Intended Audience :: Developers
12
- Classifier: License :: OSI Approved :: MIT License
13
12
  Classifier: Programming Language :: Python :: 3
14
13
  Classifier: Programming Language :: Python :: 3.8
15
14
  Classifier: Programming Language :: Python :: 3.9
@@ -4,16 +4,15 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "echotools"
7
- version = "2.3.3"
7
+ version = "2.3.4"
8
8
  description = "通用基础设施 SDK:配置、日志、事件、调度、插件、协议、调用链"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
11
- license = { text = "MIT" }
11
+ license = "MIT"
12
12
  authors = [{ name = "nichengfuben" }]
13
13
  classifiers = [
14
14
  "Development Status :: 4 - Beta",
15
15
  "Intended Audience :: Developers",
16
- "License :: OSI Approved :: MIT License",
17
16
  "Programming Language :: Python :: 3",
18
17
  "Programming Language :: Python :: 3.8",
19
18
  "Programming Language :: Python :: 3.9",
@@ -136,4 +135,4 @@ exclude_lines = [
136
135
  "def __repr__",
137
136
  "if TYPE_CHECKING:",
138
137
  "raise NotImplementedError",
139
- ]
138
+ ]
@@ -36,6 +36,45 @@ _TOOL_CALL_MARKER_RE = re.compile(
36
36
  r"|<invoke\s+name=",
37
37
  )
38
38
 
39
+ # entml 标签清理正则
40
+ _ENTML_FNCALL_BLOCK_RE = re.compile(
41
+ r"<entml:function_calls\b[^>]*>.*?</entml:function_calls>",
42
+ re.DOTALL,
43
+ )
44
+ _ENTML_INVOKE_RE = re.compile(
45
+ r'<entml:invoke\s+name="[^"]+"\s*>.*?</entml:invoke>',
46
+ re.DOTALL,
47
+ )
48
+ _ENTML_PARAMETERS_RE = re.compile(
49
+ r'<entml:parameters>.*?</entml:parameters>',
50
+ re.DOTALL,
51
+ )
52
+ _ENTML_PARAM_RE = re.compile(
53
+ r'<entml:parameter\s+name="[^"]+"\s*>.*?</entml:parameter>',
54
+ re.DOTALL,
55
+ )
56
+ # 清理任意 entml:* 标签
57
+ _ENTML_ANY_TAG_RE = re.compile(
58
+ r'<entml:[a-zA-Z_][\w]*\b[^>]*>.*?</entml:[a-zA-Z_][\w]*>',
59
+ re.DOTALL,
60
+ )
61
+
62
+
63
+ def _clean_entml_tags(content: str) -> str:
64
+ """移除内容中的所有 entml 标签及其内部内容。"""
65
+ if not content:
66
+ return content
67
+ cleaned = content
68
+ cleaned = _ENTML_FNCALL_BLOCK_RE.sub("", cleaned)
69
+ cleaned = _ENTML_INVOKE_RE.sub("", cleaned)
70
+ cleaned = _ENTML_PARAMETERS_RE.sub("", cleaned)
71
+ cleaned = _ENTML_PARAM_RE.sub("", cleaned)
72
+ cleaned = _ENTML_ANY_TAG_RE.sub("", cleaned)
73
+ # 清理多余空行
74
+ lines = [line for line in cleaned.splitlines() if line.strip()]
75
+ return "\n".join(lines)
76
+
77
+
39
78
  # ---------------------------------------------------------------------------
40
79
  # 渲染工具调用 / 工具结果
41
80
  # ---------------------------------------------------------------------------
@@ -335,6 +374,7 @@ def _format_conversation_history(
335
374
  protocol: 可选的 ToolProtocol 实例。提供时使用
336
375
  protocol.format_assistant_tool_calls() 渲染工具调用,
337
376
  确保历史中的工具调用格式与 LLM 指令中的格式一致。
377
+ 同时使用 protocol.clean_tags() 清理 user 消息中的 entml 标签。
338
378
 
339
379
  始终渲染所有消息角色(包括 assistant tool_calls 和 tool results),
340
380
  不区分客户端类型。
@@ -346,11 +386,19 @@ def _format_conversation_history(
346
386
  seen_assistant_keys: Set[Tuple[str, Tuple[Tuple[str, str], ...]]] = set()
347
387
  parts: List[Tuple[str, bool]] = []
348
388
 
389
+ # 获取清理函数
390
+ clean_fn = None
391
+ if protocol and hasattr(protocol, 'clean_tags'):
392
+ clean_fn = protocol.clean_tags
393
+
349
394
  for m in messages:
350
395
  role: str = m.get("role") or "user"
351
396
  content_str = normalize_content(m.get("content", ""))
352
397
 
353
398
  if role == "user":
399
+ # 清理用户消息中的 entml 标签
400
+ if clean_fn:
401
+ content_str = clean_fn(content_str)
354
402
  parts.append((f"<user>\n{content_str}\n</user>", False))
355
403
 
356
404
  elif role == "assistant":
@@ -371,7 +419,7 @@ def _format_conversation_history(
371
419
  content_str and _TOOL_CALL_MARKER_RE.search(content_str)
372
420
  )
373
421
  if not content_has_markers:
374
- if protocol is not None:
422
+ if protocol is not None and hasattr(protocol, 'format_assistant_tool_calls'):
375
423
  blocks.append(protocol.format_assistant_tool_calls(tcs))
376
424
  else:
377
425
  for tc in tcs:
@@ -86,7 +86,11 @@ def inject_fncall(
86
86
  history_messages = normalized
87
87
  current_user_message = ""
88
88
 
89
- # 构建历史文本
89
+ # 清理当前用户消息中的 entml 标签
90
+ if hasattr(protocol, 'clean_tags'):
91
+ current_user_message = protocol.clean_tags(current_user_message)
92
+
93
+ # 构建历史文本(传入 protocol 以便清理 user 消息中的 entml 标签)
90
94
  history_text = _format_conversation_history(
91
95
  history_messages, protocol=protocol
92
96
  ).strip()
@@ -1,15 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: echotools
3
- Version: 2.3.3
3
+ Version: 2.3.4
4
4
  Summary: 通用基础设施 SDK:配置、日志、事件、调度、插件、协议、调用链
5
5
  Author: nichengfuben
6
- License: MIT
6
+ License-Expression: MIT
7
7
  Project-URL: Homepage, https://github.com/nichengfuben/echotools
8
8
  Project-URL: Repository, https://github.com/nichengfuben/echotools
9
9
  Project-URL: Issues, https://github.com/nichengfuben/echotools/issues
10
10
  Classifier: Development Status :: 4 - Beta
11
11
  Classifier: Intended Audience :: Developers
12
- Classifier: License :: OSI Approved :: MIT License
13
12
  Classifier: Programming Language :: Python :: 3
14
13
  Classifier: Programming Language :: Python :: 3.8
15
14
  Classifier: Programming Language :: Python :: 3.9
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes