Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 60 additions & 35 deletions docs/SKILL_MARKETPLACE.ko.md

Large diffs are not rendered by default.

97 changes: 61 additions & 36 deletions docs/SKILL_MARKETPLACE.md

Large diffs are not rendered by default.

44 changes: 26 additions & 18 deletions docs/poc/appcontainer-product-integration.ko.md

Large diffs are not rendered by default.

42 changes: 25 additions & 17 deletions docs/poc/appcontainer-product-integration.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System.Threading;
using System.Threading.Tasks;
using TableCloth.ManagedAi;

namespace TableCloth.Components.Implementations;

/// <summary>Reads the existing compatibility preference for each AI request.</summary>
public sealed class ManagedAiNetworkSettings(IPreferencesManager preferences) : IManagedAiNetworkSettings
{
public async Task<AiNetworkSettings> GetAsync(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var settings = await preferences.LoadPreferencesAsync(cancellationToken).ConfigureAwait(false);
// PreferencesManager can fall back after a failed read, including cancellation.
cancellationToken.ThrowIfCancellationRequested();
return new(UseSystemProxyForSkills: settings?.EnableZScalerRootCertPropagation == true);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System;
using System.Net.Http;
using TableCloth.Components;
using TableCloth.ManagedAi;
using TableCloth.ManagedAi.Windows;
Expand All @@ -11,13 +14,27 @@ internal static IServiceCollection AddManagedAiWindows(this IServiceCollection s
{
services.AddSingleton<IJsonlProcessRunner, JsonlProcessRunner>();
services.AddSingleton<IManagedAiProfile, WindowsManagedAiProfile>();
services.TryAddSingleton<IManagedAiNetworkSettings, DefaultManagedAiNetworkSettings>();
// Host downloads keep Windows certificate trust and the existing default proxy.
// No certificate bypass or additional credential/environment propagation to workers.
services.AddHttpClient(WindowsManagedAiScriptRuntimeManager.DownloadHttpClientName,
client => client.Timeout = TimeSpan.FromMinutes(5))
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
{
AllowAutoRedirect = false, UseCookies = false,
UseDefaultCredentials = false, Credentials = null
}).RemoveAllLoggers();
services.AddSingleton<WindowsManagedAiScriptRuntimeManager>();
services.AddSingleton<IManagedAiScriptRuntimeManager>(service =>
service.GetRequiredService<WindowsManagedAiScriptRuntimeManager>());
services.AddSingleton<IManagedAiScriptExecutionRuntime>(service =>
service.GetRequiredService<WindowsManagedAiScriptRuntimeManager>());
services.AddSingleton<IManagedAiSkillExecution>(service => new WindowsManagedAiSkillExecution(
service.GetRequiredService<ManagedAiPaths>(),
service.GetRequiredService<WindowsManagedAiScriptRuntimeManager>(),
service.GetRequiredService<ISharedLocations>().ExecutableFilePath));
service.GetRequiredService<IManagedAiScriptExecutionRuntime>(),
service.GetRequiredService<ISharedLocations>().ExecutableFilePath,
service.GetService<IManagedAiSkillMarketplace>(),
service.GetRequiredService<IManagedAiNetworkSettings>()));
return services;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Serilog;
Expand Down Expand Up @@ -33,6 +34,7 @@ public static IHostApplicationBuilder UseTableCloth(this IHostApplicationBuilder
builder.Services.AddLogging();

builder.Services.AddManagedOpenAi();
builder.Services.Replace(ServiceDescriptor.Singleton<IManagedAiNetworkSettings, ManagedAiNetworkSettings>());
builder.Services.AddManagedAiWindows();
builder.Services.AddTransient<ITableClothBrowser, TableClothBrowserAdapter>();
builder.Services.AddTransient<IManagedAiCatalogLauncher, ManagedAiCatalogLauncher>();
Expand Down
3 changes: 2 additions & 1 deletion src/TableCloth.App/ViewModels/OptionsWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,8 @@ private async Task SaveMappedFoldersAsync()
[ObservableProperty]
private bool _enableSandboxPublicDnsFallback = true;

// ZScaler 루트 인증서 전파(이슈 #292). 기본 꺼짐 — SSL 검사(ZScaler) 환경에서만 켠다. 무설치 미지원.
// ZScaler compatibility: Sandbox certificate propagation and AI skill host system proxy; disabled by default.
// Only Sandbox certificate propagation is unavailable in portable mode. AI applies changes on its next request.
[ObservableProperty]
private bool _enableZScalerRootCertPropagation;

Expand Down
2 changes: 1 addition & 1 deletion src/TableCloth.App/ViewModels/SkillSettingsItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public sealed record SkillSettingsItem(AiSkill Skill, SkillCatalogEntry? Catalog
"The catalog commit differs from the installed commit. Updating replaces skill files and keeps the enabled state.")
: ManagedAiText.Select("설치한 커밋이 현재 카탈로그의 커밋과 일치합니다.", "The installed commit matches the current catalog commit.");
public string StateLabel => !IsValid ? ManagedAiText.Select("SKILL.md 확인 필요", "Invalid SKILL.md")
: Enabled ? ManagedAiText.Select("사용 중", "Enabled") : ManagedAiText.Select("사용 안 함", "Disabled");
: Enabled ? ManagedAiText.Select("활성화됨", "Enabled") : ManagedAiText.Select("사용 안 함", "Disabled");

internal static bool SourceMatches(AiSkill skill, SkillCatalogEntry entry) => skill.Source is { } source
&& string.Equals(source.CatalogId, entry.Id, StringComparison.OrdinalIgnoreCase)
Expand Down
14 changes: 8 additions & 6 deletions src/TableCloth.Core/Models/Configuration/PreferenceSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,15 @@ public class PreferenceSettings
public bool EnableSandboxPublicDnsFallback { get; set; } = true;

/// <summary>
/// 호스트에 설치된 ZScaler 루트 인증서를 샌드박스 안으로 전파할지 여부입니다.
/// ZScaler 같은 엔드포인트 통제(SSL 검사) 환경에서는 호스트가 신뢰하는 ZScaler 루트 인증서가
/// 샌드박스로 자동 전파되지 않아 샌드박스 내부의 HTTPS 연결이 모두 차단됩니다. 이 옵션을 켜면
/// ZScaler 환경을 위한 샌드박스 인증서 전파와 AI 스킬의 호스트 시스템 프록시 사용을 제어합니다.
/// ZScaler 같은 SSL 검사 환경에서는 호스트가 신뢰하는 루트 인증서를 샌드박스가 신뢰하지 않아
/// HTTPS 연결에 실패할 수 있습니다. 이 옵션을 켜면
/// 호스트의 <c>LocalMachine\Root</c> 저장소에서 Subject에 "Zscaler"가 포함된 루트 인증서를 찾아
/// 샌드박스로 전달하고, 샌드박스 부팅 시 사용자 신뢰 루트 저장소에 등록하여 인터넷 연결을 복원합니다
/// (이슈 #292). 기본값은 꺼짐이며, 호스트에 해당 인증서가 없으면 켜져 있어도 자동으로 건너뜁니다.
/// <b>이 옵션은 무설치(포터블) 식탁보에서는 지원되지 않습니다.</b>
/// 샌드박스로 전달하고 부팅 시 사용자 신뢰 루트 저장소에 등록합니다(이슈 #292).
/// 해당 인증서가 없으면 샌드박스 전파를 건너뛰며 무설치(포터블)에서는 이 전파 경로를 지원하지 않습니다.
/// AI 스킬은 다음 AI 요청부터 허용된 호스트 HTTPS 경로에서 Windows 시스템 프록시를 사용합니다.
/// TLS는 Windows의 인증서 신뢰를 따르며 Python과 Node.js AppContainer 작업자는 직접 네트워크를 사용하지 않습니다.
/// 인증서 검증을 생략하거나 프록시 자격 증명을 전달하지 않습니다. 기본값은 꺼짐입니다.
/// </summary>
public bool EnableZScalerRootCertPropagation { get; set; } = false;

Expand Down
4 changes: 2 additions & 2 deletions src/TableCloth.Core/Resources/UIStringResources.ko.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1002,10 +1002,10 @@ https://github.com/yourtablecloth/TableCloth</value>
<value>샌드박스의 DNS가 호스트 이름을 해석하지 못할 때만 네트워크 어댑터를 공용 DNS(8.8.8.8 / 1.1.1.1)로 임시 전환합니다. 정상 동작하는 DNS(사내 내부 리졸버 포함)는 건드리지 않으며, 이름 해석이 실제로 실패할 때만 폴백이 동작합니다. 공용 DNS가 정책상 금지된 환경이라면 끄세요. 다음 샌드박스 실행부터 적용됩니다.</value>
</data>
<data name="Option_EnableZScalerRootCertPropagationCheckbox" xml:space="preserve">
<value>호스트의 ZScaler 루트 인증서를 샌드박스로 전파</value>
<value>샌드박스와 AI 스킬의 ZScaler 호환성 지원</value>
</data>
<data name="Option_EnableZScalerRootCertPropagationCheckbox_Description" xml:space="preserve">
<value>ZScaler처럼 SSL 검사를 하는 엔드포인트 통제 환경에서는 호스트가 신뢰하는 ZScaler 루트 인증서가 샌드박스 내부로 자동 전파되지 않아 샌드박스의 HTTPS 연결이 모두 차단됩니다. 이 옵션을 켜면 호스트의 ZScaler 루트 인증서를 샌드박스로 복사해 사용자 신뢰 루트 저장소에 등록하여 인터넷 연결을 복원합니다. 호스트에 해당 인증서가 없으면 아무 동작도 하지 않습니다. 이 옵션은 무설치(포터블) 식탁보에서는 지원되지 않습니다. 다음 샌드박스 실행부터 적용됩니다.</value>
<value>호스트에 있는 ZScaler 루트 인증서를 다음 Windows Sandbox 세션으로 전파합니다. 무설치 식탁보에서는 인증서 전파를 지원하지 않습니다. AI 스킬에는 다음 AI 요청부터 허용된 호스트 HTTPS 요청에 Windows 시스템 프록시를 적용하며 TLS는 Windows 인증서 신뢰를 따릅니다. Python과 Node.js 작업자의 직접 네트워크 접근은 계속 차단합니다. 프록시 인증이나 조직 정책에 따라 연결에 실패할 수 있습니다.</value>
</data>
<data name="Option_Compatibility_SearchPlaceholder" xml:space="preserve">
<value>설정 검색 (이름 · 설명)</value>
Expand Down
4 changes: 2 additions & 2 deletions src/TableCloth.Core/Resources/UIStringResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1003,10 +1003,10 @@ Create it and open it now?</value>
<value>When the sandbox's DNS can't resolve host names, temporarily switch its network adapters to public DNS (8.8.8.8 / 1.1.1.1). Working DNS — including corporate internal resolvers — is left untouched; the fallback kicks in only when name resolution actually fails. Turn this off if your network policy forbids public DNS. Takes effect on the next sandbox launch.</value>
</data>
<data name="Option_EnableZScalerRootCertPropagationCheckbox" xml:space="preserve">
<value>Propagate the host's ZScaler root certificate into the sandbox</value>
<value>ZScaler compatibility for Sandbox and AI skills</value>
</data>
<data name="Option_EnableZScalerRootCertPropagationCheckbox_Description" xml:space="preserve">
<value>In endpoint-control environments that inspect SSL (such as ZScaler), the host's ZScaler root certificate is not automatically trusted inside the sandbox, so the sandbox's HTTPS connections are blocked. Enable this to copy the ZScaler root certificate from the host into the sandbox and register it in the user trust store, restoring internet access. If the host has no such certificate this option does nothing. This option is not supported in portable (no-install) TableCloth. Takes effect on the next sandbox launch.</value>
<value>Copies the host's ZScaler root certificates into the next Windows Sandbox session when present. Certificate propagation is unavailable in portable TableCloth. For AI skills, enables the Windows system proxy for allowed host HTTPS requests starting with the next AI request; TLS follows Windows certificate trust. Python and Node.js workers keep direct network access disabled. Proxy authentication and organization policies can still prevent a connection.</value>
</data>
<data name="Option_Compatibility_SearchPlaceholder" xml:space="preserve">
<value>Search settings (name or description)</value>
Expand Down
Loading
Loading