@auto-ai/agent 2.1.120 → 2.1.121
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.
- package/dist/404/index.html +1 -1
- package/dist/404.html +1 -1
- package/dist/index.html +1 -1
- package/dist/index.txt +1 -1
- package/dist/manage/about/index.html +2 -2
- package/dist/manage/about/index.txt +1 -1
- package/dist/manage/add-account/basic/index.html +2 -2
- package/dist/manage/add-account/basic/index.txt +4 -3
- package/dist/manage/add-account/index.html +2 -2
- package/dist/manage/add-account/index.txt +3 -4
- package/dist/manage/agent-teams/index.html +2 -2
- package/dist/manage/agent-teams/index.txt +1 -1
- package/dist/manage/env/index.html +2 -2
- package/dist/manage/env/index.txt +1 -1
- package/dist/manage/general/index.html +2 -2
- package/dist/manage/general/index.txt +1 -1
- package/dist/manage/index.html +1 -1
- package/dist/manage/index.txt +1 -1
- package/dist/manage/mcp/index.html +2 -2
- package/dist/manage/mcp/index.txt +1 -1
- package/dist/manage/permissions/index.html +2 -2
- package/dist/manage/permissions/index.txt +1 -1
- package/dist/manage/skills/index.html +2 -2
- package/dist/manage/skills/index.txt +1 -1
- package/dist/manage/task/index.html +2 -2
- package/dist/manage/task/index.txt +1 -1
- package/dist/manage/teams/index.html +2 -2
- package/dist/manage/teams/index.txt +1 -1
- package/dist/manage/tools/index.html +2 -2
- package/dist/manage/tools/index.txt +1 -1
- package/dist/ws-test.html +39 -127
- package/package.json +6 -6
- package/tools-runtime/code-tool/index.cjs +1 -0
- package/tools-runtime/code-tool/src/index.ts +7 -1
- package/tools-runtime/git-tool/index.cjs +18 -2
- package/tools-runtime/git-tool/src/wsInit.ts +26 -3
- /package/dist/_next/static/{fg4nA8liSSLEgWV4WTZDt → Uk25KzeENFNl8wcmEtL4K}/_buildManifest.js +0 -0
- /package/dist/_next/static/{fg4nA8liSSLEgWV4WTZDt → Uk25KzeENFNl8wcmEtL4K}/_clientMiddlewareManifest.json +0 -0
- /package/dist/_next/static/{fg4nA8liSSLEgWV4WTZDt → Uk25KzeENFNl8wcmEtL4K}/_ssgManifest.js +0 -0
package/dist/ws-test.html
CHANGED
|
@@ -4814,8 +4814,14 @@
|
|
|
4814
4814
|
if (typeof payload.sessionId === 'string' && payload.sessionId) {
|
|
4815
4815
|
sessionIdInput.value = payload.sessionId
|
|
4816
4816
|
sessionIdInput.placeholder = '留空下次新建'
|
|
4817
|
-
|
|
4818
|
-
|
|
4817
|
+
void loadSessions()
|
|
4818
|
+
if (pendingSessionOverrides) {
|
|
4819
|
+
void flushPendingSessionOverridesIfAny()
|
|
4820
|
+
} else {
|
|
4821
|
+
void loadSessionOverridesIntoComposer()
|
|
4822
|
+
}
|
|
4823
|
+
} else {
|
|
4824
|
+
updateMainHeader()
|
|
4819
4825
|
}
|
|
4820
4826
|
return true
|
|
4821
4827
|
}
|
|
@@ -4827,6 +4833,8 @@
|
|
|
4827
4833
|
const phase = typeof payload.phase === 'string' ? payload.phase : ''
|
|
4828
4834
|
if (phase === 'idle') {
|
|
4829
4835
|
if (serverReady) setStatus('已就绪。', 'ready')
|
|
4836
|
+
// 一轮 prompt 收尾后 transcript 已落盘,刷新列表以更新页签 firstPrompt/summary
|
|
4837
|
+
void loadSessions()
|
|
4830
4838
|
} else if (phase) {
|
|
4831
4839
|
setStatus('查询阶段: ' + phase + '…', '')
|
|
4832
4840
|
}
|
|
@@ -5536,12 +5544,6 @@
|
|
|
5536
5544
|
return u.toString()
|
|
5537
5545
|
}
|
|
5538
5546
|
|
|
5539
|
-
function buildToolBaseListUrl() {
|
|
5540
|
-
const u = new URL('/api/tools/base-list', httpOriginForApi() + '/')
|
|
5541
|
-
u.searchParams.set('agent', currentAgentParam())
|
|
5542
|
-
return u.toString()
|
|
5543
|
-
}
|
|
5544
|
-
|
|
5545
5547
|
function buildToolInstalledListUrl() {
|
|
5546
5548
|
const u = new URL('/api/tools/installed-list', httpOriginForApi() + '/')
|
|
5547
5549
|
u.searchParams.set('agent', currentAgentParam())
|
|
@@ -6781,19 +6783,6 @@
|
|
|
6781
6783
|
runId: data.runId,
|
|
6782
6784
|
seq: data.seq,
|
|
6783
6785
|
})
|
|
6784
|
-
if (
|
|
6785
|
-
data.type === 'session.meta' &&
|
|
6786
|
-
data.data &&
|
|
6787
|
-
typeof data.data === 'object' &&
|
|
6788
|
-
data.data.sessionId
|
|
6789
|
-
) {
|
|
6790
|
-
void loadSessions()
|
|
6791
|
-
if (pendingSessionOverrides) {
|
|
6792
|
-
void flushPendingSessionOverridesIfAny()
|
|
6793
|
-
} else {
|
|
6794
|
-
void loadSessionOverridesIntoComposer()
|
|
6795
|
-
}
|
|
6796
|
-
}
|
|
6797
6786
|
updateButtons()
|
|
6798
6787
|
return
|
|
6799
6788
|
}
|
|
@@ -7913,8 +7902,7 @@
|
|
|
7913
7902
|
|
|
7914
7903
|
if (kind === 'tools') {
|
|
7915
7904
|
const toolPickerState = {
|
|
7916
|
-
activeTab: '
|
|
7917
|
-
baseRows: [],
|
|
7905
|
+
activeTab: 'installed',
|
|
7918
7906
|
installedRows: [],
|
|
7919
7907
|
cloudRows: [],
|
|
7920
7908
|
cloudQuery: '',
|
|
@@ -7951,17 +7939,28 @@
|
|
|
7951
7939
|
if (!x.r.ok) throw new Error(x.b.message || x.r.statusText)
|
|
7952
7940
|
const tools = Array.isArray(x.b.tools) ? x.b.tools : []
|
|
7953
7941
|
return tools.map(function (t) {
|
|
7954
|
-
|
|
7942
|
+
const pkg = t.packageName ? String(t.packageName) : ''
|
|
7943
|
+
const layer = t.layer === 'system' || t.layer === 'agent' ? t.layer : ''
|
|
7944
|
+
const layerTag = layer === 'system' ? ' [系统]' : layer === 'agent' ? ' [Agent]' : ''
|
|
7945
|
+
return {
|
|
7946
|
+
id: t.name,
|
|
7947
|
+
t: t,
|
|
7948
|
+
packageId: pkg,
|
|
7949
|
+
deletable: t.deletable === true,
|
|
7950
|
+
layerTag: layerTag,
|
|
7951
|
+
}
|
|
7955
7952
|
})
|
|
7956
7953
|
})
|
|
7957
7954
|
}
|
|
7958
|
-
const makeManageRow = function (row
|
|
7955
|
+
const makeManageRow = function (row) {
|
|
7959
7956
|
const id = row.id
|
|
7957
|
+
const canDelete = row.deletable === true
|
|
7958
|
+
const packageId = row.packageId || ''
|
|
7960
7959
|
const div = document.createElement('div')
|
|
7961
7960
|
div.className = 'agent-picker-item'
|
|
7962
7961
|
const labelEl = document.createElement('div')
|
|
7963
7962
|
labelEl.className = 'agent-picker-item-label'
|
|
7964
|
-
labelEl.textContent = toolLabel(row)
|
|
7963
|
+
labelEl.textContent = toolLabel(row) + (row.layerTag || '')
|
|
7965
7964
|
div.appendChild(labelEl)
|
|
7966
7965
|
const actions = document.createElement('div')
|
|
7967
7966
|
actions.className = 'agent-picker-actions'
|
|
@@ -7976,13 +7975,13 @@
|
|
|
7976
7975
|
renderToolsRows()
|
|
7977
7976
|
})
|
|
7978
7977
|
actions.appendChild(toggleBtn)
|
|
7979
|
-
if (canDelete) {
|
|
7978
|
+
if (canDelete && packageId) {
|
|
7980
7979
|
const exportBtn = document.createElement('button')
|
|
7981
7980
|
exportBtn.type = 'button'
|
|
7982
7981
|
exportBtn.className = 'btn-picker-action'
|
|
7983
7982
|
exportBtn.textContent = '导出'
|
|
7984
7983
|
exportBtn.addEventListener('click', function () {
|
|
7985
|
-
window.open(buildRuntimeToolExportUrl(
|
|
7984
|
+
window.open(buildRuntimeToolExportUrl(packageId), '_blank', 'noopener')
|
|
7986
7985
|
})
|
|
7987
7986
|
actions.appendChild(exportBtn)
|
|
7988
7987
|
}
|
|
@@ -7990,10 +7989,13 @@
|
|
|
7990
7989
|
delBtn.type = 'button'
|
|
7991
7990
|
delBtn.className = 'btn-picker-action is-delete'
|
|
7992
7991
|
delBtn.textContent = '删除'
|
|
7993
|
-
delBtn.disabled = !canDelete
|
|
7992
|
+
delBtn.disabled = !canDelete || !packageId
|
|
7993
|
+
if (!canDelete) {
|
|
7994
|
+
delBtn.title = '系统内置工具不可删除'
|
|
7995
|
+
}
|
|
7994
7996
|
delBtn.addEventListener('click', function () {
|
|
7995
7997
|
if (delBtn.disabled) return
|
|
7996
|
-
fetch(buildRuntimeToolDeleteUrl(
|
|
7998
|
+
fetch(buildRuntimeToolDeleteUrl(packageId), { method: 'DELETE' })
|
|
7997
7999
|
.then(function (r) {
|
|
7998
8000
|
return r.json().catch(function () { return {} }).then(function (b) { return { r: r, b: b } })
|
|
7999
8001
|
})
|
|
@@ -8011,111 +8013,21 @@
|
|
|
8011
8013
|
div.appendChild(actions)
|
|
8012
8014
|
return div
|
|
8013
8015
|
}
|
|
8014
|
-
const loadCloudRows = function () { return Promise.resolve() }
|
|
8015
8016
|
const renderToolsRows = function () {
|
|
8016
8017
|
if (!agentPickerList) return
|
|
8017
8018
|
agentPickerList.innerHTML = ''
|
|
8018
|
-
|
|
8019
|
-
|
|
8020
|
-
|
|
8021
|
-
{ id: 'installed', label: '已安装工具' },
|
|
8022
|
-
],
|
|
8023
|
-
toolPickerState.activeTab,
|
|
8024
|
-
function (id) {
|
|
8025
|
-
toolPickerState.activeTab = id
|
|
8026
|
-
renderToolsRows()
|
|
8027
|
-
},
|
|
8028
|
-
)
|
|
8029
|
-
if (toolPickerState.activeTab === 'base') {
|
|
8030
|
-
const rows = toolPickerState.baseRows
|
|
8031
|
-
if (!rows.length) {
|
|
8032
|
-
agentPickerList.appendChild(document.createTextNode('(暂无)'))
|
|
8033
|
-
return
|
|
8034
|
-
}
|
|
8035
|
-
for (let i = 0; i < rows.length; i++) agentPickerList.appendChild(makeManageRow(rows[i], false))
|
|
8036
|
-
return
|
|
8037
|
-
}
|
|
8038
|
-
if (toolPickerState.activeTab === 'installed') {
|
|
8039
|
-
const rows = toolPickerState.installedRows
|
|
8040
|
-
if (!rows.length) {
|
|
8041
|
-
agentPickerList.appendChild(document.createTextNode('(暂无)'))
|
|
8042
|
-
return
|
|
8043
|
-
}
|
|
8044
|
-
for (let i = 0; i < rows.length; i++) agentPickerList.appendChild(makeManageRow(rows[i], true))
|
|
8045
|
-
return
|
|
8046
|
-
}
|
|
8047
|
-
const cloudSearch = document.createElement('input')
|
|
8048
|
-
cloudSearch.type = 'search'
|
|
8049
|
-
cloudSearch.className = 'agent-picker-cloud-search'
|
|
8050
|
-
cloudSearch.placeholder = '搜索云端工具…'
|
|
8051
|
-
cloudSearch.value = toolPickerState.cloudQuery
|
|
8052
|
-
cloudSearch.oninput = function () {
|
|
8053
|
-
toolPickerState.cloudQuery = cloudSearch.value.trim()
|
|
8054
|
-
toolPickerState.cloudPage = 1
|
|
8055
|
-
void loadCloudRows()
|
|
8056
|
-
}
|
|
8057
|
-
agentPickerList.appendChild(cloudSearch)
|
|
8058
|
-
agentPickerList.appendChild(createCloudPager({
|
|
8059
|
-
page: toolPickerState.cloudPage,
|
|
8060
|
-
totalPages: toolPickerState.cloudTotalPages,
|
|
8061
|
-
loading: toolPickerState.cloudLoading,
|
|
8062
|
-
}, function (nextPage) {
|
|
8063
|
-
toolPickerState.cloudPage = nextPage
|
|
8064
|
-
void loadCloudRows()
|
|
8065
|
-
}))
|
|
8066
|
-
if (toolPickerState.cloudError) {
|
|
8067
|
-
agentPickerList.appendChild(document.createTextNode('加载失败:' + toolPickerState.cloudError))
|
|
8019
|
+
const rows = toolPickerState.installedRows
|
|
8020
|
+
if (!rows.length) {
|
|
8021
|
+
agentPickerList.appendChild(document.createTextNode('(暂无已安装工具)'))
|
|
8068
8022
|
return
|
|
8069
8023
|
}
|
|
8070
|
-
|
|
8071
|
-
agentPickerList.appendChild(
|
|
8072
|
-
return
|
|
8073
|
-
}
|
|
8074
|
-
for (let i = 0; i < toolPickerState.cloudRows.length; i++) {
|
|
8075
|
-
const item = toolPickerState.cloudRows[i]
|
|
8076
|
-
const row = document.createElement('div')
|
|
8077
|
-
row.className = 'agent-picker-item'
|
|
8078
|
-
const label = document.createElement('div')
|
|
8079
|
-
label.className = 'agent-picker-item-label'
|
|
8080
|
-
label.textContent = item.title + ' · ' + item.toolName + (item.description ? ' — ' + item.description : '')
|
|
8081
|
-
row.appendChild(label)
|
|
8082
|
-
const actions = document.createElement('div')
|
|
8083
|
-
actions.className = 'agent-picker-actions'
|
|
8084
|
-
const opBtn = document.createElement('button')
|
|
8085
|
-
opBtn.type = 'button'
|
|
8086
|
-
opBtn.className = 'btn-picker-action' + (item.installed ? ' is-delete' : '')
|
|
8087
|
-
const running = !!toolPickerState.loadingMap[item.id]
|
|
8088
|
-
opBtn.disabled = running
|
|
8089
|
-
opBtn.textContent = running ? '处理中…' : item.installed ? '卸载' : '安装'
|
|
8090
|
-
opBtn.addEventListener('click', function () {
|
|
8091
|
-
if (opBtn.disabled) return
|
|
8092
|
-
toolPickerState.loadingMap[item.id] = true
|
|
8093
|
-
renderToolsRows()
|
|
8094
|
-
const req = item.installed
|
|
8095
|
-
? fetch(buildRuntimeToolDeleteUrl(item.packageId), { method: 'DELETE' })
|
|
8096
|
-
: Promise.reject(new Error('云端工具安装接口已下线'))
|
|
8097
|
-
req
|
|
8098
|
-
.then(function (r) { return r.json().catch(function () { return {} }).then(function (b) { return { r: r, b: b } }) })
|
|
8099
|
-
.then(function (x) {
|
|
8100
|
-
if (!x.r.ok) throw new Error(x.b.message || x.r.statusText)
|
|
8101
|
-
restartCurrentSessionSubprocessWithReason(item.installed ? 'cloud-tool-uninstall' : 'cloud-tool-install')
|
|
8102
|
-
return refreshToolPickerRows()
|
|
8103
|
-
})
|
|
8104
|
-
.catch(function (e) { window.alert((item.installed ? '卸载' : '安装') + '失败: ' + e) })
|
|
8105
|
-
.finally(function () { delete toolPickerState.loadingMap[item.id]; renderToolsRows() })
|
|
8106
|
-
})
|
|
8107
|
-
actions.appendChild(opBtn)
|
|
8108
|
-
row.appendChild(actions)
|
|
8109
|
-
agentPickerList.appendChild(row)
|
|
8024
|
+
for (let i = 0; i < rows.length; i++) {
|
|
8025
|
+
agentPickerList.appendChild(makeManageRow(rows[i]))
|
|
8110
8026
|
}
|
|
8111
8027
|
}
|
|
8112
8028
|
refreshToolPickerRows = function () {
|
|
8113
|
-
return
|
|
8114
|
-
|
|
8115
|
-
fetchToolRows(buildToolInstalledListUrl),
|
|
8116
|
-
]).then(function (allRows) {
|
|
8117
|
-
toolPickerState.baseRows = allRows[0]
|
|
8118
|
-
toolPickerState.installedRows = allRows[1]
|
|
8029
|
+
return fetchToolRows(buildToolInstalledListUrl).then(function (rows) {
|
|
8030
|
+
toolPickerState.installedRows = rows
|
|
8119
8031
|
renderToolsRows()
|
|
8120
8032
|
})
|
|
8121
8033
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@auto-ai/agent",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.121",
|
|
4
4
|
"description": "Auto AI Agent 网关 CLI(WebSocket,独立二进制,无需 Bun)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"maintainers": [
|
|
@@ -32,11 +32,11 @@
|
|
|
32
32
|
"zod": "^4.3.6"
|
|
33
33
|
},
|
|
34
34
|
"optionalDependencies": {
|
|
35
|
-
"@auto-ai/agent-linux-x64": "2.1.
|
|
36
|
-
"@auto-ai/agent-linux-arm64": "2.1.
|
|
37
|
-
"@auto-ai/agent-darwin-x64": "2.1.
|
|
38
|
-
"@auto-ai/agent-darwin-arm64": "2.1.
|
|
39
|
-
"@auto-ai/agent-win-x64": "2.1.
|
|
35
|
+
"@auto-ai/agent-linux-x64": "2.1.121",
|
|
36
|
+
"@auto-ai/agent-linux-arm64": "2.1.121",
|
|
37
|
+
"@auto-ai/agent-darwin-x64": "2.1.121",
|
|
38
|
+
"@auto-ai/agent-darwin-arm64": "2.1.121",
|
|
39
|
+
"@auto-ai/agent-win-x64": "2.1.121"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
42
|
"prepare": "node ../../scripts/sync-launcher-env.js",
|
|
@@ -46,6 +46,7 @@ __export(exports_src, {
|
|
|
46
46
|
ensureConfigured: () => ensureConfigured,
|
|
47
47
|
default: () => src_default,
|
|
48
48
|
configure: () => configure,
|
|
49
|
+
buildSessionAppend: () => buildCodeToolSessionAppend,
|
|
49
50
|
buildCodeToolSessionAppend: () => buildCodeToolSessionAppend,
|
|
50
51
|
CodeTool: () => CodeTool
|
|
51
52
|
});
|
|
@@ -13,7 +13,13 @@ import { configure, requireCodeWorkDir, resetConfigure, getCachedConfigure } fro
|
|
|
13
13
|
import { buildCodeToolSessionAppend } from './sessionAppend.js'
|
|
14
14
|
import { initWsSession } from './wsInit.js'
|
|
15
15
|
|
|
16
|
-
export {
|
|
16
|
+
export {
|
|
17
|
+
configure,
|
|
18
|
+
resetConfigure,
|
|
19
|
+
initWsSession,
|
|
20
|
+
buildCodeToolSessionAppend,
|
|
21
|
+
buildCodeToolSessionAppend as buildSessionAppend,
|
|
22
|
+
}
|
|
17
23
|
export { resolveCodeWorkDir } from './workspace.js'
|
|
18
24
|
export type { CodeToolConfigureHooks } from './hooks.js'
|
|
19
25
|
export { isEnabledInAgentConfig } from './agentConfig.js'
|
|
@@ -14568,9 +14568,25 @@ function ensureConfigured() {
|
|
|
14568
14568
|
async function initWsSession(ctx) {
|
|
14569
14569
|
if (!isEnabledInAgentConfig(ctx.agent)) {
|
|
14570
14570
|
resetConfigure();
|
|
14571
|
-
return;
|
|
14571
|
+
return { state: "skipped", reason: "GitTool disabled in agent config" };
|
|
14572
|
+
}
|
|
14573
|
+
try {
|
|
14574
|
+
const result = await prepareForAgent({ operWorkspaceDir: ctx.operWorkspaceDir });
|
|
14575
|
+
if (result === "skipped") {
|
|
14576
|
+
resetConfigure();
|
|
14577
|
+
return {
|
|
14578
|
+
state: "skipped",
|
|
14579
|
+
reason: "git work directory not ready (configure WS_GIT_REPO_URL or existing repo)"
|
|
14580
|
+
};
|
|
14581
|
+
}
|
|
14582
|
+
return { state: "ready" };
|
|
14583
|
+
} catch (e) {
|
|
14584
|
+
resetConfigure();
|
|
14585
|
+
return {
|
|
14586
|
+
state: "failed",
|
|
14587
|
+
error: e instanceof Error ? e.message : String(e)
|
|
14588
|
+
};
|
|
14572
14589
|
}
|
|
14573
|
-
await prepareForAgent({ operWorkspaceDir: ctx.operWorkspaceDir });
|
|
14574
14590
|
}
|
|
14575
14591
|
|
|
14576
14592
|
// src/index.ts
|
|
@@ -15,11 +15,34 @@ export type GitToolWsInitContext = {
|
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
export type GitToolWsInitResult =
|
|
19
|
+
| { state: 'ready' }
|
|
20
|
+
| { state: 'skipped'; reason?: string }
|
|
21
|
+
| { state: 'failed'; error: string }
|
|
22
|
+
|
|
18
23
|
/** WS init:按 agent 白名单与环境变量准备 git 工作区 */
|
|
19
|
-
export async function initWsSession(
|
|
24
|
+
export async function initWsSession(
|
|
25
|
+
ctx: GitToolWsInitContext,
|
|
26
|
+
): Promise<GitToolWsInitResult> {
|
|
20
27
|
if (!isEnabledInAgentConfig(ctx.agent)) {
|
|
21
28
|
resetConfigure()
|
|
22
|
-
return
|
|
29
|
+
return { state: 'skipped', reason: 'GitTool disabled in agent config' }
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
const result = await prepareForAgent({ operWorkspaceDir: ctx.operWorkspaceDir })
|
|
33
|
+
if (result === 'skipped') {
|
|
34
|
+
resetConfigure()
|
|
35
|
+
return {
|
|
36
|
+
state: 'skipped',
|
|
37
|
+
reason: 'git work directory not ready (configure WS_GIT_REPO_URL or existing repo)',
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return { state: 'ready' }
|
|
41
|
+
} catch (e: unknown) {
|
|
42
|
+
resetConfigure()
|
|
43
|
+
return {
|
|
44
|
+
state: 'failed',
|
|
45
|
+
error: e instanceof Error ? e.message : String(e),
|
|
46
|
+
}
|
|
23
47
|
}
|
|
24
|
-
await prepareForAgent({ operWorkspaceDir: ctx.operWorkspaceDir })
|
|
25
48
|
}
|
/package/dist/_next/static/{fg4nA8liSSLEgWV4WTZDt → Uk25KzeENFNl8wcmEtL4K}/_buildManifest.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|