今日已更新 252 条资讯 | 累计 24209 条内容
关于我们

标签:#t

找到 11598 篇相关文章

开发者

Coolify: The Complete Manual Setup Guide (For When the Auto-Install Script Won't Cut It)

Coolify's one-line install script is great — until it isn't. Right now it officially supports Ubuntu 20.04, 22.04, and 24.04 LTS. If you're running anything newer (Ubuntu's already on 26.04 LTS), the script won't work and you're left doing it manually. This is that manual walkthrough — set up in the order that fits a security-first VPS workflow rather than the order Coolify's own docs use. If you've been following along with the Ansible playbooks from earlier in this series, this picks up right where that left off. Minimum Hardware Requirements CPU: 2 cores Memory: 2 GB RAM Storage: 30 GB free Coolify can technically run below this, but it's not recommended. Prerequisites Before touching Coolify itself, you'll need: SSH access to your VPS CURL installed Docker Engine installed If you're reconnecting to a server you've rebuilt or re-provisioned, clear the old fingerprint first: ssh-keygen -f '/home/your-path/.ssh/known_hosts' -R 'your-vps-ip' Installing SSH If you followed the earlier videos in this series, OpenSSH is already installed. If not: sudo apt update && sudo apt install -y openssh-server Confirm it's running and check which port it's listening on (you should have already changed this from the default 22 — see the VPS security video): sudo systemctl status ssh sudo ss -tulpn | grep ssh Installing CURL sudo apt update && sudo apt install -y curl curl --version curl and ca-certificates also get installed as part of the apt-update Ansible playbook below, so this may already be handled. Running the First Ansible Playbook Connect Ansible to the VPS: ANSIBLE_HOST_KEY_CHECKING = FALSE ansible -i ./inventory/hosts vpsDemo -m ping --user root --ask-pass Then run the update playbook: ansible-playbook ./playbooks/apt-update.yml --user root -e "ansible_port=22" --ask-pass --ask-become-pass -i ./inventory/hosts If you haven't set up the Ansible inventory and playbooks from the earlier videos, do that first — this guide assumes they're already in place. Installing Docker

2026-07-23 原文 →
AI 资讯

Inertia and API responses living together in harmony

I love InertiaJS to the point where it's becoming a personality trait I tend to want to use it for everything, but adding Inertia to an existing Laravel API gets awkward fast. Same thing happens in the other direction: you start with a full Inertia frontend and then realize you want to expose some of that data as a public API too. The naive solutions are: Sprinkle if ($request->wantsJson()) into your controllers Maintain two separate routes that return the exact same data Neither feels right. So I made inertia-split Starting fresh with Inertia: serve both from the same controller class ProjectController extends Controller { use HasHybridResponses ; public function index () { return $this -> respond () -> component ( 'Projects/Index' , [ 'projects' => Project :: all (), ]); // Inertia request → renders the Svelte/Vue/React component // API request → returns JSON } } The controller doesn't check anything. Inertia requests get an Inertia response, API clients get JSON. Existing API? Don't touch it If you just want to make an existing API method Inertia-aware, one annotation is enough: #[InertiaComponent('Users/Show')] public function show ( User $user ): array { return [ 'user' => $user ]; } The method body stays exactly as it was. Inertia requests get the component rendered with your data as props. Everything else gets the same JSON as before. Methods without the annotation are completely unaffected. Wait, how does this even work? The package can out Inertia's ResponseFactory for its own in the service provider (opt-in): $this -> app -> singleton ( ResponseFactory :: class , HybridResponseFactory :: class ); // checks if it's an Inertia request and returns appropriate response Good old OOP. Thank you polymorphism. Wrap-up Whatever the direction of your problem, making Inertia and API endpoints use the same controller is a big win. You're still responsible for writing routes and wiring middlewares, but this should save a lot of time and effort. Still in beta, use accor

2026-07-23 原文 →
AI 资讯

My requirements.txt Is Pinned. My MCP Server's Actual Contract Isn't, and Nothing Would Catch It Changing.

Back on 2026-07-14 I found and fixed a real landmine in this repo: requirements.txt had mcp[cli] with no version constraint at all. Any fresh install could pull in a breaking major version with zero warning. I pinned it to mcp[cli]>=1.28.0,<2.0.0 and moved on, feeling like I'd closed the gap. I hadn't. I'd only pinned the library . The actual contract my MCP server exposes to any agent that connects to it — the tool names, parameter shapes, and descriptions an LLM reads to decide how to call my code — isn't a version string anywhere. It's generated fresh, every time the server boots, from whatever my function signatures and docstrings happen to say at that moment. Nothing pins that. Nothing diffs it. Nothing tests it. What actually generates the contract My server ( server.py ) is a FastMCP app with plain @mcp.tool() -decorated functions: @mcp.tool () def create_article ( title : str , body_markdown : str , tags : list [ str ] = None , published : bool = False ) -> dict : """ Create a new DEV.to article. Returns id and url. """ payload = { " article " : { " title " : title , " body_markdown " : body_markdown , " published " : published }} if tags : payload [ " article " ][ " tags " ] = tags result = _dev ( " /articles " , method = " POST " , data = payload ) return { " id " : result [ " id " ], " url " : result . get ( " url " ), " published " : result . get ( " published " )} FastMCP inspects that signature at import time and builds the JSON Schema an agent actually sees — parameter names, types, which ones are required, and the docstring as the tool's description. I never write that schema by hand and I never check it in anywhere. It's derived, every run, from source that I edit for completely unrelated reasons. That's the gap. requirements.txt pinning stops FastMCP's own behavior from shifting under me between installs. It does nothing about my behavior shifting the schema FastMCP generates from my code, on every single commit, with no separate review step. Where

2026-07-23 原文 →
开发者

Unity Foundational Architecture: Managing Global State

Table of Contents: Introduction Constants Singletons & Services Singleton Service Locator Introduction Every Unity developer eventually hits the exact same wall: how do I get my UI script to talk to my Game Manager without turning my codebase into a tangled web of dependencies? Managing global state is a fundamental challenge in game architecture, and the internet is full of conflicting, often dogmatic advice on how to handle it. In this article, we are going to look at some popular approaches to managing global state: Static Constants, Singletons and Service Locator. Before we start though, I encourage you to read some of my previous blog posts in this series on project scaffolding or, even more crucial to some sections in this article, the bootstrapping process . Constants Not every piece of global data needs a instance to live in, interfaces, or an initialization phase. Some data is constant and never changes at runtime (constants). These constants are usually defined with static readonly or const (at least they should be if they never change). Example: public static class MathConstants { public const float MilesToKm = 1.60934f ; } public class CharacterAnimationController : MonoBehaviour { // we must use static readonly instead of const here because we need to generate the SpeedHash from the string literal. public static readonly int SpeedHash = Animator . StringToHash ( "Speed" ); } Constants are also tied to the type they are defined in. So to keep things neat, you should only define constants where appropriate. Meaning if you have a constant for the max networked inventory slot capacity, this shouldn't be defined in a class called NetworkedConstants and instead should reside inside the class that represents the NetworkedInventory which needs this data. In fact, if this is the only class that needs this data, you can even make it private although it's perfectly fine to make it public as well if there's a need for it in other scripts as long as you are not just

2026-07-23 原文 →
AI 资讯

用 FROST 家族治理模型,构建你的「AI 第一性原理」

用 FROST 家族治理模型,构建你的「AI 第一性原理」 作者 :神通说 日期 :2026-07-23 主题 :双项目联动 | 周四代码教程 阅读时间 :12分钟 前言:为什么你需要「第一性原理」? 埃隆·马斯克推崇「第一性原理」思维——从物理学的最基本定律出发,而不是类比他人的做法。 在 AI Agent 开发领域,大多数人都在用 LangChain、CrewAI、AutoGen 这些现成框架。它们很好用,但你是在用别人的「家族结构」,而不是理解为什么需要家族结构。 FROST 的目标是让你从第一性原理理解 AI Agent: 为什么需要治理结构?为什么需要记忆传承?为什么需要层级分工? 然后,FROST-SOP 帮你把第一性原理变成可运行的系统。 一、从细胞分裂看 AI Agent 本质 想象一个细胞分裂的场景: ┌─────────┐ │ 细胞 │ ← 拥有细胞核(记忆)、蛋白质(能力) └────┬────┘ │ 分裂 ┌────┴────┐ │ 细胞A │ │ 细胞B │ ← 各自独立,但共享DNA └─────────┘ └─────────┘ FROST 的四个原子就是生命的四个基本元素: 原子 生命类比 技术实现 Store 细胞核 记忆容器,持久化状态 Skill 蛋白质 无状态能力单元 Agent 细胞膜 包裹 Store + Skills 的执行单元 SOP DNA 序列 有序的操作指令集 # FROST 的最小可用示例:50行代码理解 Agent 本质 from frost.core import Store , Agent , skill_set , skill_get , skill_del # 1. 创建记忆容器 store = Store () # 2. 定义能力(蛋白质) skills = { " set " : skill_set , # 存记忆 " get " : skill_get , # 取记忆 " del " : skill_del # 删记忆 } # 3. 创建 Agent(细胞) agent = Agent ( " my_cell " , store , skills ) # 4. 定义 SOP(DNA 序列) sop_steps = [ " set " , # 存一个值 " get " , # 读回来 " del " # 删掉 ] # 5. 运行 result = agent . run ( sop_steps = sop_steps , initial_context = { " key " : " name " , " value " : " FROST " } ) print ( result [ " _result " ]) # 输出: "FROST" 这 50 行代码展示了 FROST 的核心: Agent = Store + Skills + SOP 。 二、为什么需要「家族」?从独居细胞到多细胞生物 单细胞生物可以独立存活。但复杂生命需要多细胞协作——肝脏细胞、心脏细胞、神经细胞各有分工,协同维持生命。 AI Agent 也是如此。简单任务一个 Agent 够了,但复杂系统需要多 Agent 协作。 FROST 的家族模型: ┌─────────────────────────────────────────────────────┐ │ 君主(Human Agent) │ │ 最高决策者,只发布任务不看执行 │ └─────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────┐ │ 祖辈(Ancestor) │ │ 全局编排、宪法定义、任务拆分、资源分配 │ │ ⚠️ 不亲自执行,只做调度 │ └─────────────────────────────────────────────────────┘ │ ┌─────────────┼─────────────┐ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ 斥候 │ │ 斥候 │ │ 斥候 │ │ (侦察) │ │ (侦察) │ │ (侦察) │ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │ │ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ 府兵 │ │ 府兵 │ │ 府兵 │ │ (执行) │ │ (执行) │ │ (执行) │ └──────────┘ └──────────┘ └──────────┘ │

2026-07-23 原文 →
AI 资讯

The best config in your bake-off didn't win. Selection did.

Best-of-K eval selection bias: pick the highest-scoring config from K candidates on one eval set and that observed score is biased up. It reports the expected maximum of K noisy estimates, which beats the field mean whenever K exceeds one. The bias appears even when all K configs are truly equal, grows with K, and shrinks with n. Here is the version that bites you. Your bake-off ran a batch of prompts against one eval set, the top one came out ahead, and you shipped it. In production it does worse. That drop reads like bad luck, or drift, or a bad week. It is none of those. It is a number you could have computed before you shipped, and it gets larger the more candidates you tried. I ran a small script to make the gap concrete. Eight configs, one hundred eval items, and here is the catch: I made all eight configs truly identical , every one a fair coin at 50%. There is no real best. Nothing to tune. Then I let selection pick a winner anyway: config 0: 47/100 = 47.0% config 1: 50/100 = 50.0% config 2: 52/100 = 52.0% config 3: 52/100 = 52.0% config 4: 50/100 = 50.0% config 5: 50/100 = 50.0% config 6: 54/100 = 54.0% <- selected winner (argmax) config 7: 44/100 = 44.0% config 6: 54.0% (k=54 n=100 SE=4.98) config 2: 52.0% (k=52 n=100 SE=5.00) RANK: INDISTINGUISHABLE - gap 2.00 pp against 7.06 pooled SE = 0.28 SE < 2.0. Ranking "config 6" above "config 2" is NOT allowed. Held-out the winner on a fresh 100 items: 48/100 = 48.0%. Config 6 wins the bake-off at 54.0%. Then I asked the same eval-guard I use in the McNemar and rule-of-three pieces to rank config 6 against the runner-up. It refused: the gap is 0.28 SE, far under the two-SE bar, so INDISTINGUISHABLE . The ranker would not call config 6 the best. Selection did. And on a fresh held-out set the 54.0% falls back to 48.0%, toward the true 50% it was always going to be. TL;DR Picking the best of K configs by observed pass rate reports the expected maximum of K noisy estimates. The max of K exceeds the field mean, strict

2026-07-23 原文 →
AI 资讯

Stop manually curling port 9600: Using MCP to triage Logstash bottlenecks

I have a ritual. Whenever a pipeline latency alert hits my phone, my first instinct isn't to open a heavy dashboard or spin up a full Grafana instance. I grab my terminal and start firing curl commands at port 9600. curl -s localhost:9600/_node/stats?pretty ... curl -s localhost:9600/_cat/pipelines ... curl -s localhost:9600/_plugins . It's a repetitive, mindless sequence of commands. It works, but it's reactive and solo. You are the one parsing the JSON, you are the one looking for the pattern in the JVM heap usage, and you are the one manually correlating a spike in event flow with a specific thread lock. With the Model Context Protocol (MCP), that ritual is becoming obsolete. I've been experimenting with connecting MCP-compatible agents—specifically through Cursor and Claude—directly to Logstash via a specialized API server. The difference isn't just 'convenience.' It's an architectural shift from manual inspection to agentic triage. Moving beyond the Chatbot Most people treat AI like a documentation search engine. They ask, "How do I configure a JDBC input in Logstash?" That’s fine, but it doesn't help when your production cluster is turning 'yellow' at 3 AM. The real value of MCP isn't the ability to talk to an AI; it's the ability to give that AI a set of hands—specifically, a set of tools that can interact with live infrastructure. I recently integrated the Logstash Server-side Log Pipeline API into my workflow. This isn't some experimental script I wrote over a weekend; it’s a production-grade implementation built on MCPFusion. It gives an AI agent direct access to several critical Logstash endpoints through a controlled, sandboxed environment. The Triage Workflow: A Real Scenario Let's walk through how this actually changes the debugging loop. Imagine you have a spike in ingestion lag. In the old way, you’d be digging through terminal history. In the new way, your agent acts as an extension of your SRE toolkit. 1. Initial Health Check Instead of parsing raw

2026-07-23 原文 →
AI 资讯

Sovereign Lemmings Released

I have released the Sovereign package on Github. It deploys Lemmings into up to 3 cloud regions for your choice in configuration flavor with cost estimations through dry-runs and aggregating the report into one final report as lemmings come and go in the result of the load test. I built it for organizations that plan on using AI to build something, not hire somebody like me who helped write The Library to do it for them. You can hire me in consulting if you need help, but it's available now. But, before you spend $50,000 on a television ad driving people to your new app that you just built after spending $50,000 on tokens, why not run Lemmings and Sovereign first? It's 100% free and does not involve me at all in order for you to read through the extensive README.md files and comments in the code for you to understand what to do to run it and adapt to its results. Enjoy using it! There - that is the post. Now - 🙌🏻 - Ask me anything 🙇🏻 👇🏻

2026-07-23 原文 →
AI 资讯

NocoBase and the mystery of the shifted timestamps: MySQL vs PostgreSQL, measured

There's a class of bug reports that keeps coming back in the NocoBase community, especially in the Chinese-language forum: "all my times are off by 8 hours" or "dates show up as the day before." China is UTC+8, so the shift is 8 hours there. I run my instances at UTC+9, and sure enough — my shift is 9 hours. Whatever your offset is, that's the size of your shift. That pattern is a strong hint that this isn't random corruption. It's a mechanism. I set up NocoBase 2.x against both PostgreSQL and MySQL and measured what actually gets stored and how it gets reinterpreted, until the mystery had a concrete answer. Test setup: NocoBase 2.0.51 and 2.1.23 (official Docker images) × PostgreSQL 16 and MySQL 8.4. All data written and read through the REST API, with the server timezone controlled via the container's TZ environment variable. I'm deliberately ignoring the browser-side rendering here — this is about what the server stores and how it interprets it. Background: 2.x has four datetime field types NocoBase 2.x collections offer four datetime-ish field types ( official list — though several of the per-type detail pages still say "To be added", which is exactly why I measured instead): Type What it's for Datetime (with time zone) Absolute instants — event start times, logs Datetime (without time zone) Wall-clock times you want preserved as-is Date only Birthdays, due dates, anniversaries Unix timestamp System integration Measurement 1: what each type actually stores I imported "2026-07-12 09:00" via xlsx and looked at the raw values in each database (identical on 2.0.51 and 2.1.23): Field type PostgreSQL MySQL Datetime (with TZ) timestamptz → 2026-07-12 09:00:00+09 ( an absolute instant, offset included ) DATETIME → 2026-07-12 09:00:00 ( wall clock only — no offset information ) Datetime (without TZ) timestamp → 09:00:00 DATETIME → 09:00:00 Date only date → 2026-07-12 date → 2026-07-12 The first row is the whole story. The same field type — "Datetime (with time zone)" — i

2026-07-23 原文 →
AI 资讯

4 ways canvas text rendering breaks in multilingual apps (that en/ja testing will never catch)

I run a large fleet of "preview it, then download it as PNG" web tools — name tags, certificate generators, price cards, badges — in five languages: Japanese, English, Spanish, French, Portuguese. Canvas 2D text rendering looks correct as long as you only test Japanese and English. It breaks when you run es/fr/pt through it. After stepping on these repeatedly, the failures collapse into four patterns. The premise: Latin languages run 1.4–2× longer than Japanese Design data first. The same label, measured across five locales: Example ja en es fr pt Tool name 22 chars 35 62 48 50 "Standard" button 4 8 10 20 12 Rule of thumb: fr/pt come out 1.4–1.7× longer than ja; es can balloon to nearly 3×. A font size and maxWidth tuned to fit Japanese will not fit the Latin locales. All four failure patterns grow from this. Pattern 1: hand-rolled wrapping via text.split(/\s+/) collapses on CJK The classic snippet — split on spaces, wrap word by word — does nothing for Japanese or Chinese, where words aren't space-delimited. An entire sentence becomes one unbreakable token and clips at the canvas edge. Test with real Japanese input and check that the final line renders to its last character. "Most of it showed up" is not a pass. Pattern 2: an ASCII-only tokenizer splits words at accented characters Fix pattern 1 with a character-class tokenizer like [A-Za-z0-9'\-_] and you've traded one regression for another: ç é ã ó ñ aren't in that class, so produção fragments into produ / ç / ão mid-word. An English test will never catch this. Generate actual PNGs with fr/es/pt samples and eyeball the area around accented characters. I never found another detection method — string-comparison tests can't see a rendering-level split. Pattern 3: the important word at the end vanishes into "…" Since fr/pt run 1.4–1.7× longer than the ja the layout was tuned for, text overflows its two lines and gets ellipsized. The cruel part: what disappears is the tail of the phrase — often the semantically criti

2026-07-23 原文 →
AI 资讯

Pillar research says the AI coding agent sandbox leaks through trusted files

Pillar Security's latest research says AI coding agents can be pushed to act outside their sandbox through files and tools they were told to trust, and the operational read for anyone wiring one of these into CI/CD is straightforward: an agent invocation now behaves closer to a build runner reaching your production plane than to a chat window. DevOps.com's Jeff Burt covered the work on July 22. The researchers demonstrated multiple sandbox-bypass techniques and a parallel class of prompt-injection attacks embedded in READMEs, code comments and dependencies, per the DevOps.com writeup. OpenAI, Google and Cursor have patched several of the reported flaws. Pillar's argument, as summarised there, is that the injection surface reaches every file the agent trusts on the way to the model's prompt, and every tool it can call on the way back. What the sandbox actually covered None of this is entirely new to anyone who has already read Cyberhaven Lab's May note that adoption of AI coding agents is outpacing the security tools built to protect them. What Pillar adds is a concrete demonstration of the gap. A coding agent asked to do a legitimate job can be steered to take actions outside its supposed security boundary through content that arrives on paths the sandbox was not asked to police. Those are the same paths your CI already fetches for you: dependency manifests, README files, the code comments the model reads as context. That surface has been named before. HalluSquatting and GhostApproval, both referenced in the DevOps.com piece, already gave teams a taxonomy for how AI-adjacent supply-chain attacks reach developers and their tools. Pillar's research is the sandbox counterpart. Same theme, one layer deeper into the runtime. The pipeline read Two things fall out for anyone who owns a runner fleet. First, the agent's identity, network scope and filesystem access have to be tighter than the developer who invoked it, not looser. Second, a patched-vendor list is not a covera

2026-07-23 原文 →
AI 资讯

Python's Object Model in Depth: Why Two Lines That Look the Same Behave Differently

Two lines of code. Same variable. Same operator. Completely different behavior. a = [ 1 , 2 , 3 ] b = a b += [ 4 ] # line A print ( a ) # [1, 2, 3, 4] x = 1 y = x y += 1 # line B print ( x ) # 1 Line A changes a . Line B does not change x . The only difference is whether the variable holds a mutable or immutable object. To understand why this happens, you need to understand how Python actually represents variables internally. Variables Are Not Boxes The box metaphor is how most introductory programming courses explain variables: a variable is a box that holds a value. You put 5 into the box called x . Later you can replace it with 10. In Python this metaphor is accurate for immutable types and dangerously misleading for mutable types. The more accurate model: a Python variable is a name that is bound to an object. The object exists independently of the name. Multiple names can be bound to the same object. Binding a name to a new object does not affect the old object or other names that reference it. You can inspect this directly: a = [ 1 , 2 , 3 ] b = a print ( id ( a ) == id ( b )) # True -- same object, two names x = 5 y = x print ( id ( x ) == id ( y )) # True -- both point to integer object 5 Both cases start the same: two names pointing to the same object. What happens next depends on whether you mutate the object or rebind the name. Two Fundamental Operations Every operation on a Python object falls into one of two categories. Mutation : the object at a given memory address is modified. All names pointing to that address see the change. Rebinding : a name is pointed at a different memory address. Other names pointing to the original address are unaffected. List methods like .append() , .extend() , .sort() , and item assignment lst[i] = x are mutations. Assignment with = is rebinding. The += operator is either mutation or rebinding depending on whether __iadd__ is implemented and the object is mutable. Tracing Through the Object Graph a = [[ 1 , 2 ], [ 3 , 4 ]]

2026-07-23 原文 →
AI 资讯

Beyond "Chat": Architecting Intelligence with Skills and Specification Engineering

Remember the days when we used to dump all our CSS and JavaScript into a single index.html file? That's exactly what a "Mega-Prompt" is today: an unmanageable monolith. A few weeks ago, while working on the orchestration of Vibrisse Agent (my local AI agent), I hit this exact wall. I was trying to stabilize a complex task by adding instructions to a 500-line system prompt. The more rules I added, the more the model forgot the older ones. The industry has sold us the myth of the Mega-Prompt. Those famous "50 ultimate prompts" or massive blocks of incantatory text are a technical dead end. Creative writing doesn't scale in production. As a web developer, my conviction is simple: to build reliable applications, we must stop "talking" to the machine and start configuring it. This is the shift from Prompt Engineering to Context Engineering . Context Engineering: Typing and Structure The first mistake with LLMs is mixing instructions (the logic) and context (the data) into an unstructured stream of text. It's the cognitive equivalent of spaghetti code. The solution? A strict separation of concerns. A highly effective technique (documented by Anthropic, but applicable to any model, including local SLMs), is XML Tagging . Here is the "dirty" approach (classic chat): You are a security expert. Analyze this authentication code, be strict, don't write a summary, check for XSS and SQLi vulnerabilities. Here is the code: function login() { ... } And here is the "engineering" approach: <role> Application Security Expert </role> <instructions> 1. Analyze the code provided in <context> . 2. Identify vulnerabilities (focus: XSS, SQLi). 3. Do not produce an introductory summary. </instructions> <context> function login() { ... } </context> Typing the language via tags creates clear boundaries. The model knows exactly where the directive is and where the data is. The Power of Exemplars (Few-Shot Prompting) Even with clear instructions, AI can drift in output format or tone. This is wh

2026-07-23 原文 →
AI 资讯

talonaudit.com

I built Talon Audit: a privacy-first approach to website exposure and remediation Most website audit tools answer one narrow question. A performance tool asks whether the page is fast. A security tool asks whether a protection is missing. An accessibility tool asks whether the interface meets specific standards. A conversion tool asks whether users are completing key actions. Visitors do not experience those categories separately. They experience one website. That observation led me to build Talon Audit, a privacy-first website analysis platform that connects technical exposure, reliability, usability, and conversion risk in one workflow. The four-domain model Talon analyses websites across four connected domains: Exposure Public security and privacy signals, including browser protections, TLS, cookies, third-party scripts, mixed content, and visible configuration risks. Integrity Broken resources, failed routes, script errors, redirects, forms, and reliability regressions. Experience Accessibility, mobile usability, visual clarity, speed, and interaction friction. Conversion Messaging, trust signals, pricing paths, calls to action, and barriers that stop users from moving forward. From detection to action The product follows a five-stage workflow: Detect → Explain → Fix → Verify → Monitor Every finding includes: evidence severity confidence impact remediation guidance verification method The goal is not to produce the longest possible report. It is to help teams decide what matters and what to do next. Passive by design Talon performs passive, low-impact analysis only. It does not exploit systems, bypass authentication, or claim to replace authorised penetration testing. Users must confirm they own the website or are authorised to test it. Customer reports are private, and the public demo uses a fictional environment rather than exposing real domains. AI-native, not AI-directed I built Talon through a terminal-first workflow using Codex 5.5 and Claude Fable. AI acc

2026-07-23 原文 →
AI 资讯

I built a serverless URL shortener for $4.68/year (total)

I wanted two things: short links under my own brand (every link I share points traffic back to my site ), and a real excuse to run a complete system on the edge — DNS, distributed compute, storage, auth and a dashboard — in production, at zero infrastructure cost. The result is flino.link : a shortener that responds in under 10 ms from 300+ locations, runs entirely on Cloudflare's free tier, and whose only expense is the domain: $4.68 a year. This post covers the design decisions, which is where the interesting parts are. The architecture in 30 seconds A single Cloudflare Worker serves the whole domain: GET /<slug> — the hot path. One read from Workers KV (globally replicated) and a 302 redirect. Nothing else touches that path. /api/links — a REST API with Bearer auth to create, list and delete links. /admin — a single-page dashboard served as inline HTML from the Worker itself. No framework, no build step. A Durable Object with embedded SQLite keeps per-slug click counts. No servers, no containers, no database to manage. The whole Worker is three TypeScript files and zero runtime dependencies. Why a dedicated domain? My first idea was to hang the shortener off a route on flino.dev . Bad idea: shorteners attract abuse — spam, phishing — and their domains sooner or later end up on blocklists. If that happens, I don't want it dragging my main domain down with it. A separate domain isolates that reputation risk completely, and a short .link costs less than a coffee per year. KV for links, a Durable Object for counters This is the central design decision. Workers KV is perfect for a shortener's access pattern — read-heavy, write-light, reads served from the edge — but its writes are eventually consistent : two concurrent increments in different datacenters would clobber each other. For counting clicks, it's useless. A Durable Object solves exactly that: it's a single global instance with transactional SQLite storage. Every increment, no matter which datacenter it comes

2026-07-23 原文 →
AI 资讯

Bizbox Build Log — Week of 2026-05-31

Shipped this week Workflows are now a first-class Bizbox primitive — PR #86 · v2026.603.0 The biggest drop this week. @DennisDenuto landed Workflows as a company-scoped concept that sits alongside issues and routines — not shoehorned into either. What that means in practice: Google ADK-backed execution — workflow pipelines run as ADK agents, with phase state persisted as run records. Human handoffs baked in — pipelines can pause and wait for a human before resuming. Deliverables that survive — artefacts from each run are persisted and surfaced in the UI. A pipeline graph in the UI — topologically ordered, showing live phase state and console output. This is the foundation. More on what we can build on top of it below. Workflow human-handoffs now route through ClickUp — PR #91 · v2026.605.0 The day after Workflows landed, @angelofallars wired up the last kilometre: when ADK Python code calls input() inside a pipeline, Bizbox now intercepts that call and sends a ClickUp message to collect the human reply — instead of blocking the process forever. A few things that were fixed along the way: input() monkey-patching now works consistently across Python environments (was silently failing in some setups). Failed workflow runs no longer submit deliverables. You only see artefacts from runs that actually completed. ClickUp awaiting-human bridge adapter ships as a pure plugin — PR #78 · v2026.601.0 This one technically crossed the line on the last day of May (23:56 UTC, 31 May), so it's in scope. @ralphbibera ported the ClickUp transport and adapter as a genuine plugin — implementing the AwaitingHumanBridgeAdapter registry interface — without touching bridge core at all. What that gives you: ClickUp works through the same provider-agnostic layer as any future provider (Slack, Discord, whatever comes next). The core doesn't know ClickUp exists. Included: send/poll/reaction transport, message templates for request_confirmation and ask_user_questions interactions, brain_is_think

2026-07-23 原文 →
AI 资讯

AutoGen's hidden token tax: why a 3-agent chat costs 15 what you expect

AutoGen's hidden token tax: why a 3-agent chat costs 15× what you expect Cost-audit series, episode 2. This series began with an AI agent that burned 136M tokens overnight → . AutoGen is Microsoft's multi-agent framework. It's genuinely good at orchestrating agents that hand off work to each other. But its default memory model has a cost shape that surprises almost every team that hits it in production. This audit shows you exactly where the tokens go, with line numbers. The setup: a 3-agent RoundRobin chat The canonical AutoGen pattern is a RoundRobinGroupChat with N agents taking turns on a task. Here's the minimal version from the docs: from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import MaxMessageTermination planner = AssistantAgent ( " planner " , model_client = client , system_message = " You plan. " ) coder = AssistantAgent ( " coder " , model_client = client , system_message = " You code. " ) reviewer = AssistantAgent ( " reviewer " , model_client = client , system_message = " You review. " ) team = RoundRobinGroupChat ( [ planner , coder , reviewer ], termination_condition = MaxMessageTermination ( max_messages = 10 ), ) await team . run ( task = " Build a web scraper for Hacker News. " ) Three agents, 10 turns total (~3–4 turns each). Seems cheap. It isn't. The default context: unbounded, per-agent Every AssistantAgent gets its own UnboundedChatCompletionContext by default: # autogen-agentchat/src/autogen_agentchat/agents/_assistant_agent.py, __init__ (L708) if model_context is not None : self . _model_context = model_context else : self . _model_context = UnboundedChatCompletionContext () source UnboundedChatCompletionContext.get_messages() returns self._messages — the full list, no cap, no truncation: # autogen-core/.../model_context/_unbounded_chat_completion_context.py (a ~20-line file) async def get_messages ( self ) -> List [ LLMMessage ]: """ Get at most

2026-07-23 原文 →