Skip to content
Open
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -466,3 +466,4 @@ ts/packages/agentSdkWrapper/plans/
/ts/packages/copilot-plugin/dist-exe
/ts/msi-out
ts/config.local.yaml.bak
/ts/tmp/bundled-agent-server
119 changes: 73 additions & 46 deletions pipelines/azure-build-publish-all.yml
Original file line number Diff line number Diff line change
Expand Up @@ -159,23 +159,12 @@ stages:
displayName: "Upload artifact: npm-packages"
artifact: npm-packages

# Stage copilot-plugin dist (platform-neutral; used by plugin
# publish and MSI build).
# Stage the minimal copilot-plugin runtime used by plugin publication
# and the MSI.
- bash: |
set -euo pipefail
PLUGIN_SRC="$(buildDirectory)/packages/copilot-plugin"
STAGE="$(stagingDir)/copilot-plugin"
mkdir -p "$STAGE"

cp -r "$PLUGIN_SRC/dist" "$STAGE/dist"
cp "$PLUGIN_SRC/hooks.json" "$STAGE/hooks.json"
cp "$PLUGIN_SRC/.mcp.json" "$STAGE/.mcp.json"
cp "$PLUGIN_SRC/plugin.json" "$STAGE/plugin.json"
cp -r "$PLUGIN_SRC/agents" "$STAGE/agents"
cp -r "$PLUGIN_SRC/skills" "$STAGE/skills"

echo "Staged copilot-plugin artifact:"
find "$STAGE" -type f | head -20 || true
node tools/scripts/stageCopilotPlugin.mjs \
--out "$(stagingDir)/copilot-plugin"
displayName: "Stage copilot-plugin artifact"
workingDirectory: $(buildDirectory)

Expand All @@ -184,7 +173,7 @@ stages:
artifact: copilot-plugin

# ── Job 1b: Platform-specific artifacts (matrix) ──────────────
# Produces: agent-server deploy, optional agents, MCP exe per RID.
# Produces: bundled agent-server, optional agent bundles, MCP exe per RID.
- job: build_platform_artifacts
displayName: "Build platform artifacts"
strategy:
Expand Down Expand Up @@ -226,24 +215,48 @@ stages:
displayName: "Build agent-server (+ deps)"
workingDirectory: $(buildDirectory)

- script: |
node tools/scripts/buildAgentProfile.mjs --profile all
displayName: "Build product agents"
workingDirectory: $(buildDirectory)

# Also build copilot-plugin (may already be built as an
# agent-server dep; this ensures the full plugin is ready).
- script: |
pnpm run build copilot-plugin
displayName: "Build copilot-plugin (+ deps)"
workingDirectory: $(buildDirectory)

# Deploy agent-server for this platform.
# Bundle and validate agent-server for this platform.
- bash: |
set -euo pipefail
EXTRA=""
if [ "${{ parameters.variant }}" = "external" ]; then EXTRA="--external-cli"; fi
node tools/scripts/deployAgentServer.mjs \
node tools/scripts/bundleAgentServer.mjs \
--out "$(stagingDir)/agent-server" \
--platform "$(platform)" --arch "$(arch)" \
--profile "${{ parameters.profile }}" $EXTRA
displayName: "Deploy agent-server ($(platform)-$(arch))"
displayName: "Bundle agent-server ($(platform)-$(arch))"
workingDirectory: $(buildDirectory)
env:
PUPPETEER_SKIP_DOWNLOAD: "true"
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: "true"

- script: |
node tools/scripts/validateBundledArtifact.mjs --dir "$(stagingDir)/agent-server"
displayName: "Validate bundled agent-server ($(platform)-$(arch))"
workingDirectory: $(buildDirectory)

# pnpm's legacy deploy implementation can leave the workspace in
# production-only mode. Restore development dependencies before
# running subsequent bundle and executable build scripts.
- script: |
pnpm install --prod=false --frozen-lockfile
displayName: "Restore build dependencies"
workingDirectory: $(buildDirectory)
env:
PUPPETEER_SKIP_DOWNLOAD: "true"
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: "true"

- publish: $(stagingDir)/agent-server
displayName: "Upload artifact: agent-server-$(platform)-$(arch)"
Expand Down Expand Up @@ -825,6 +838,7 @@ stages:
variables:
msiRid: win32-x64
MSI_BUILD_DIR: $(stagingDir)/msi
MSI_PUBLISH_DIR: $(stagingDir)/msi-publish
steps:
- checkout: self
displayName: "Checkout (for build scripts)"
Expand Down Expand Up @@ -958,8 +972,31 @@ stages:
Write-Host "Signing MSI: $($msiPath.FullName)"
node .\sign-msi.mjs "$($msiPath.FullName)"

# Publish MSI as pipeline artifact.
- publish: $(MSI_BUILD_DIR)
- pwsh: |
$source = Get-ChildItem "$(MSI_BUILD_DIR)" -Filter "*.msi"
if ($source.Count -ne 1) {
Write-Error "Expected exactly one MSI in $(MSI_BUILD_DIR); found $($source.Count)."
exit 1
}

$publishPath = "$(MSI_PUBLISH_DIR)"
if (Test-Path $publishPath) {
Remove-Item -LiteralPath $publishPath -Recurse -Force
}
New-Item -ItemType Directory -Force $publishPath | Out-Null
Copy-Item -LiteralPath $source[0].FullName -Destination $publishPath

$publishedFiles = @(Get-ChildItem $publishPath -File)
if ($publishedFiles.Count -ne 1 -or $publishedFiles[0].Extension -ne ".msi") {
Write-Error "MSI publication directory must contain exactly one .msi file."
exit 1
}
Write-Host "Prepared MSI-only publication directory:"
Write-Host " $($publishedFiles[0].FullName)"
displayName: "Stage signed MSI for publication"

# Publish the MSI-only directory as the pipeline artifact.
- publish: $(MSI_PUBLISH_DIR)
displayName: "Upload artifact: msi-$(msiRid)"
artifact: msi-$(msiRid)

Expand All @@ -971,7 +1008,7 @@ stages:
scriptType: pscore
scriptLocation: inlineScript
inlineScript: |
$publishPath = "$(MSI_BUILD_DIR)"
$publishPath = "$(MSI_PUBLISH_DIR)"
$msi = Get-ChildItem $publishPath -Filter "*.msi" | Select-Object -First 1
if ($null -eq $msi) {
Write-Error "No MSI found in $publishPath"
Expand Down Expand Up @@ -1005,34 +1042,24 @@ stages:
artifact: msi-win32-x64
displayName: "Download signed MSI artifact"

- pwsh: |
$src = "$(Pipeline.Workspace)/msi-win32-x64"
$dest = "$(stagingDir)/msi-publish"
New-Item -ItemType Directory -Force $dest | Out-Null

$msi = Get-ChildItem $src -Filter "*.msi" | Select-Object -First 1
if ($null -eq $msi) {
Write-Error "No MSI found in $src"
exit 1
}
Copy-Item $msi.FullName $dest

$hash = (Get-FileHash $msi.FullName -Algorithm SHA256).Hash.ToLower()
$meta = [ordered]@{
version = "$(packageVersion)"
file = $msi.Name
sha256 = $hash
}
$meta | ConvertTo-Json | Set-Content -Path (Join-Path $dest "latest.json") -Encoding utf8

Write-Host "Staged for blob publish:"
Get-ChildItem $dest | ForEach-Object { Write-Host " $($_.Name)" }
displayName: "Stage signed MSI + latest.json"
- task: AzureCLI@2
displayName: "Clear previous MSI channel files"
inputs:
azureSubscription: $(azureSubscription)
scriptType: pscore
scriptLocation: inlineScript
inlineScript: |
az storage blob delete-batch `
--account-name "$(azureStorageAccountName)" `
--source "$(azureStorageContainerName)" `
--pattern "msi/$(resolvedChannel)/*" `
--auth-mode login `
--only-show-errors

- task: AzureFileCopy@6
displayName: "Upload MSI to Azure Storage (msi/$(resolvedChannel))"
inputs:
SourcePath: $(stagingDir)/msi-publish/*
SourcePath: $(Pipeline.Workspace)\msi-win32-x64\*.msi
Destination: AzureBlob
azureSubscription: $(azureSubscription)
storage: $(azureStorageAccountName)
Expand Down
3 changes: 3 additions & 0 deletions ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
"build": "fluid-build . -t build",
"build:ext:vscode": "fluid-build . -t build:ext:vscode",
"build:shell": "fluid-build agent-shell -t build --dep",
"bundle:agent-server": "node tools/scripts/bundleAgentServer.mjs",
"bundle:copilot-plugin": "node tools/scripts/stageCopilotPlugin.mjs",
"check:dep": "node tools/scripts/fix-dependabot-alerts.mjs --dry-run",
"check:dep:fix": "node tools/scripts/fix-dependabot-alerts.mjs",
"check:link": "git ls-tree -r --name-only HEAD .. | grep \\.md | xargs markdown-link-check",
Expand Down Expand Up @@ -84,6 +86,7 @@
"devDependencies": {
"@fluidframework/build-tools": "^0.57.0",
"@types/node": "^22.0.0",
"esbuild": "0.28.1",
"eslint": "^10.6.0",
"eslint-plugin-sonarjs": "^4.1.0",
"jscpd": "^4.2.5",
Expand Down
35 changes: 35 additions & 0 deletions ts/packages/agentServer/bundledRuntime/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "agent-server-bundled-runtime",
"version": "0.0.1",
"private": true,
"description": "Runtime dependencies kept external from the bundled agent server",
"homepage": "https://github.com/microsoft/TypeAgent#readme",
"repository": {
"type": "git",
"url": "https://github.com/microsoft/TypeAgent.git",
"directory": "ts/packages/agentServer/bundledRuntime"
},
"license": "MIT",
"author": "Microsoft",
"type": "module",
"dependencies": {
"@anthropic-ai/claude-agent-sdk": "^0.3.150",
"@azure/msal-node-extensions": "^1.5.0",
"@github/copilot-sdk": "1.0.5",
"@modelcontextprotocol/server-filesystem": "2026.1.14",
"better-sqlite3": "12.6.2",
"graphology": "^0.25.4",
"graphology-communities-louvain": "^2.0.1",
"graphology-layout": "^0.6.1",
"graphology-layout-forceatlas2": "^0.10.1",
"graphology-layout-noverlap": "^0.4.1",
"graphology-metrics": "^2.1.0",
"keytar": "7.9.0",
"onnxruntime-node": "1.21.0",
"puppeteer": "^24.15.0",
"puppeteer-extra": "^3.3.6",
"puppeteer-extra-plugin-adblocker": "^2.13.6",
"puppeteer-extra-plugin-stealth": "^2.11.2",
"sharp": "^0.33.5"
}
}
31 changes: 30 additions & 1 deletion ts/packages/agents/browser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,35 @@
}
},
"typeagent": {
"defaultAgentName": "browser"
"defaultAgentName": "browser",
"bundle": {
"entries": [
"dist/views/server/server.mjs",
"dist/puppeteer/index.mjs"
],
"assets": [
"dist/views/public",
"dist/extension",
"src/agent/discovery/schema",
"src/agent/indexing/schema",
"src/agent/knowledge/actions/schema",
"src/agent/knowledge/schema",
"src/agent/search/schema",
"src/agent/webFlows/samples",
"src/agent/webFlows/schema"
],
"assetMappings": [
{
"package": "@typeagent/azure-ai-foundry",
"source": "dist/phrases.json",
"destination": "dist/agent/phrases.json"
},
{
"package": "@typeagent/browser",
"source": "src/agent/webFlows/webFlowSandbox.d.ts",
"destination": "src/agent/webFlows/webFlowSandbox.d.ts"
}
]
}
}
}
5 changes: 3 additions & 2 deletions ts/packages/agents/browser/src/agent/browserActionHandler.mts
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,8 @@ async function cleanupBrowserSession(
const dynamicDisplayRetryCounters = new Map<string, number>();
const MAX_RETRY_CYCLES = 2;

// Set up periodic cleanup for running extractions cache and retry counters
setInterval(
// Do not keep short-lived hosts alive solely for cache cleanup.
const cacheCleanupTimer = setInterval(
() => {
runningExtractionsCache.cleanup();

Expand All @@ -324,6 +324,7 @@ setInterval(
},
5 * 60 * 1000,
); // Clean up every 5 minutes
cacheCleanupTimer.unref();

async function getDynamicDisplayImpl(
type: DisplayType,
Expand Down
14 changes: 3 additions & 11 deletions ts/packages/agents/browser/src/agent/discovery/translator.mts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ import path from "path";
import fs from "fs";
import { openai as ai } from "@typeagent/aiclient";
import { hookModelTokenUsage } from "../tokenUsage.mjs";
import { fileURLToPath } from "node:url";
import { SchemaDiscoveryActions } from "./schema/discoveryActions.mjs";
import { PageDescription } from "./schema/pageSummary.mjs";
import registerDebug from "debug";
import { getBrowserPackageFilePath } from "../utils/packageFilePath.mjs";

const debugPerf = registerDebug("typeagent:browser:discover:perf");

Expand Down Expand Up @@ -118,17 +118,9 @@ function getScreenshotPromptSection(
}

async function getSchemaFileContents(fileName: string): Promise<string> {
const packageRoot = path.join("..", "..", "..");
return await fs.promises.readFile(
fileURLToPath(
new URL(
path.join(
packageRoot,
"./src/agent/discovery/schema",
fileName,
),
import.meta.url,
),
getBrowserPackageFilePath(
path.join("src", "agent", "discovery", "schema", fileName),
),
"utf8",
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,15 @@ import { openai as ai } from "@typeagent/aiclient";
import { ExtractionMode } from "@typeagent/website-memory";
import registerDebug from "debug";
import { PageSummary } from "./schema/summarization.mjs";
import { fileURLToPath } from "url";
import path from "path";
import fs from "fs";
import { getBrowserPackageFilePath } from "../utils/packageFilePath.mjs";
const debug = registerDebug("typeagent:browser:indexing");

function getSchemaFileContents(fileName: string): string {
const packageRoot = path.join("..", "..", "..");

return fs.readFileSync(
fileURLToPath(
new URL(
path.join(packageRoot, "./src/agent/indexing/schema", fileName),
import.meta.url,
),
getBrowserPackageFilePath(
path.join("src", "agent", "indexing", "schema", fileName),
),
"utf8",
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,18 @@ import { createTypeScriptJsonValidator } from "typechat/ts";
import { TopicRelationshipAnalysis } from "./schema/topicRelationship.mjs";
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
import { getBrowserPackageFilePath } from "../../utils/packageFilePath.mjs";

function getSchemaFileContents(fileName: string): string {
const packageRoot = path.join("..", "..", "..", "..");
return fs.readFileSync(
fileURLToPath(
new URL(
path.join(
packageRoot,
"./src/agent/knowledge/actions/schema",
fileName,
),
import.meta.url,
getBrowserPackageFilePath(
path.join(
"src",
"agent",
"knowledge",
"actions",
"schema",
fileName,
),
),
"utf8",
Expand Down
Loading
Loading